Capture the screen slightly before each click; record milestone in CHANGELOG
Template tests / tests (push) Successful in 1m58s
Template tests / tests (pull_request) Successful in 1m47s

Real-world recording now saves every click with exact markers; the only
remaining nit was screenshots feeling a touch late. Add a configurable
click-lead (capture.clickLeadMs, default 120ms) that targets the screen
just before the hook timestamp, and tighten the stream sampling cadence to
50ms so a frame near that target always exists. Verified end to end: frames
now land ~120-160ms before the click (was 25-57ms), markers stay at 0.00%
offset, and the 8-click burst still saves all 8.

Also document the milestone in docs/CHANGELOG.md and remove an accidental
paste of Gitea commit-page text from it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Iisyourdad
2026-06-12 08:12:13 -05:00
parent 951bba7a21
commit 5b89b5c927
4 changed files with 61 additions and 7 deletions
+14 -2
View File
@@ -557,14 +557,26 @@ class CaptureService {
async frameForClick(clickPos = null, clickAt = Date.now()) {
const mode = this.settings.get('capture.mode') || 'fullscreen';
const grabMode = mode === 'region' ? 'fullscreen' : mode;
const clickTime = Number.isFinite(clickAt) ? clickAt : Date.now();
const rawClickTime = Number.isFinite(clickAt) ? clickAt : Date.now();
// Click lead: aim selection at a moment slightly *before* the hook
// timestamp. The hook fires on button-down, but the visible UI often
// starts reacting within a frame or two of that (hover→press states,
// the cursor settling), and capture-stream pixels lag the real screen
// by a frame. Targeting clickTime - leadMs keeps the saved screenshot
// clear of the click's own onset so the step shows the screen the user
// was about to act on. Tunable via capture.clickLeadMs.
const leadMs = Math.max(0, Number(this.settings.get('capture.clickLeadMs')) || 0);
const clickTime = rawClickTime - leadMs;
const strict = this.strictClickFrames();
const opts = {
clickAt: clickTime,
clickPos,
mode: grabMode,
strict,
maxAgeMs: CLICK_FRAME_MAX_AGE_MS,
// The lead shifts the target earlier, so widen the staleness budget by
// the same amount — a frame that was fresh enough for the real click
// is still fresh enough for the lead-adjusted target.
maxAgeMs: CLICK_FRAME_MAX_AGE_MS + leadMs,
startSlackMs: CLICK_FRAME_START_SLACK_MS,
};