Skip to content

feat(studio): asset click policy and canvas nudge gate#2200

Merged
miguel-heygen merged 2 commits into
studio-dnd/pr07-stacking-syncfrom
studio-dnd/pr09-asset-click-nudge-policy
Jul 12, 2026
Merged

feat(studio): asset click policy and canvas nudge gate#2200
miguel-heygen merged 2 commits into
studio-dnd/pr07-stacking-syncfrom
studio-dnd/pr09-asset-click-nudge-policy

Conversation

@ukimsanov

@ukimsanov ukimsanov commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator

What

two small pure modules with tests — assetClickBehavior (click vs double-click policy for sidebar assets) and canvasNudgeGate (debounce gate for arrow-key canvas nudges).

Why

policy dependencies of the upcoming asset card and nudge hook, reviewable as plain decision tables.

How

new files only.

Test plan

bunx vitest run on both test files; tsc --noEmit; fallow audit clean.


Stack position 9/25 — studio NLE overhaul (CapCut-parity timeline + canvas). Graphite manages bases; merge from #2192 upward. Temporary TEMP(studio-dnd) fallow entries (unwired-component windows) are all removed by #2213 (app-shell swap), whose tree is byte-identical to the fully-verified integration branch.

ukimsanov commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@ukimsanov ukimsanov force-pushed the studio-dnd/pr08-timeline-zones branch from f26cdeb to 95e9ca4 Compare July 11, 2026 00:55
@ukimsanov ukimsanov force-pushed the studio-dnd/pr09-asset-click-nudge-policy branch 2 times, most recently from af9f377 to fc4382f Compare July 11, 2026 01:15
@ukimsanov ukimsanov force-pushed the studio-dnd/pr08-timeline-zones branch from 95e9ca4 to d0aa2e0 Compare July 11, 2026 01:15

@miga-heygen miga-heygen left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed as part of the 25-PR NLE overhaul stack. Full stack review on #2205 (the keystone). No blockers on this PR. — Miga

@vanceingalls vanceingalls left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: LGTM (green) — small, sharp, correctly bounded

Two pure helpers plus a module-level singleton claim gate. The scope is deliberately narrow; each unit is exercised at its edges. No unit-consistency traps (both files are pixel-only or dimensionless).

The pointed queries

  • Click-vs-drag threshold (fair tie-break). packages/studio/src/utils/assetClickBehavior.ts:73–:75isPointerClick(dx, dy) = Math.abs(dx) < 4 && Math.abs(dy) < 4. Strict < at the boundary; exactly 4px is a drag, not a click. Deterministic and symmetric across axes. Test at :94–:98 pins the boundary in both directions (positive AND negative displacement); :100–:103 confirms the sign symmetry.
  • findClipForAsset — matcher normalisation. :43–:61 handles the four src shapes documented by deriveUsedPaths (absolute URL, /api/projects/.../preview/..., ./-prefixed, bare relative), plus query-string stripping and percent-decode. Every shape has a dedicated test at :26–:60. The earliest start deterministic pick at :62–:67 avoids returning an arbitrary duplicate. Robust.
  • Nudge gate — nesting semantics. packages/studio/src/utils/canvasNudgeGate.ts:10–:26 — module-level claims: number counter; acquireCanvasNudgeKeys() returns an idempotent release closure that decrements at most once. Test at :16–:24 verifies double-release is a no-op (guarded by the released flag at :16). Correct for nested overlays.
  • Wiring with #2203 (canvas nudge math). No direct import at these PR SHAs — canvasNudgeGate.ts doesn't reference domEditNudge.ts and vice versa. That's expected: this PR ships the gate, #2203 ships the delta math, and a downstream PR (per .fallowrc.jsonc markers, studio-dnd/pr22) wires both into DomEditOverlay. As long as the eventual consumer acquires the gate BEFORE binding its arrow-key listener and releases it on unmount, the ownership arbitration between DomEditOverlay and usePlaybackKeyboard (documented at :5–:8) will hold. No coupling to inspect here.

Nits (non-blocking)

  • The module-level claims counter in canvasNudgeGate.ts persists across tests within a Vitest worker. Currently both tests clean up to zero, but there is no beforeEach(() => { /* reset */ }) — if a future test throws mid-way and leaks a claim, the next test's initial expect(claimed()).toBe(false) would fail without an obvious signal. A beforeEach guard, or exposing a __resetForTests() helper, would future-proof this. Cosmetic — the current tests happen to be well-behaved.

R1 by Via

@ukimsanov ukimsanov force-pushed the studio-dnd/pr08-timeline-zones branch from d0aa2e0 to b3f0ed0 Compare July 11, 2026 02:56
@ukimsanov ukimsanov force-pushed the studio-dnd/pr09-asset-click-nudge-policy branch 2 times, most recently from 8e77fb1 to ba28195 Compare July 11, 2026 08:18
@ukimsanov ukimsanov force-pushed the studio-dnd/pr08-timeline-zones branch from b3f0ed0 to 41f7e1d Compare July 11, 2026 08:18
@ukimsanov ukimsanov marked this pull request as ready for review July 11, 2026 09:06
@ukimsanov ukimsanov force-pushed the studio-dnd/pr09-asset-click-nudge-policy branch 2 times, most recently from ab2e3db to b88fb09 Compare July 11, 2026 12:51
@ukimsanov ukimsanov force-pushed the studio-dnd/pr08-timeline-zones branch from 69f9285 to 815d985 Compare July 11, 2026 21:08
@ukimsanov ukimsanov force-pushed the studio-dnd/pr09-asset-click-nudge-policy branch 2 times, most recently from 1a1a98b to bab0352 Compare July 11, 2026 22:38
@ukimsanov ukimsanov force-pushed the studio-dnd/pr08-timeline-zones branch from 16f409a to e79f78c Compare July 12, 2026 01:03
@ukimsanov ukimsanov force-pushed the studio-dnd/pr09-asset-click-nudge-policy branch from bab0352 to 7f0d8db Compare July 12, 2026 01:03
What: new pure module timelineZones — visual/audio track-zone
classification (classifyZone) and normalizeToZones, which re-packs lanes
into zone-consistent rows; tests cover the stacking/zones interaction.

Why: completes the z-model started in the stacking-sync PR.

How: new files; consumes isAudioTimelineElement (leaf-helpers PR) and
computeStackingPatches (stacking-sync PR); type-only playerStore imports.

Test plan: bunx vitest run timelineZones.test.ts; tsc --noEmit; fallow
audit clean.
What: two small pure modules with tests — assetClickBehavior (click vs
double-click policy for sidebar assets) and canvasNudgeGate (debounce gate
for arrow-key canvas nudges).

Why: policy dependencies of the upcoming asset card and nudge hook,
reviewable as plain decision tables.

How: new files only.

Test plan: bunx vitest run on both test files; tsc --noEmit; fallow audit
clean.
@ukimsanov ukimsanov force-pushed the studio-dnd/pr08-timeline-zones branch from e79f78c to 2733e34 Compare July 12, 2026 01:22
@ukimsanov ukimsanov force-pushed the studio-dnd/pr09-asset-click-nudge-policy branch from 7f0d8db to 4c8b88c Compare July 12, 2026 01:22

@miguel-heygen miguel-heygen left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed current head and verified the addressed feedback and required behavior. Approval is for this exact head; Graphite mergeability may still be pending.

Base automatically changed from studio-dnd/pr08-timeline-zones to studio-dnd/pr07-stacking-sync July 12, 2026 02:56
@miguel-heygen miguel-heygen merged commit 108142f into studio-dnd/pr07-stacking-sync Jul 12, 2026
14 of 15 checks passed
@miguel-heygen miguel-heygen deleted the studio-dnd/pr09-asset-click-nudge-policy branch July 12, 2026 02:56
@miguel-heygen miguel-heygen restored the studio-dnd/pr09-asset-click-nudge-policy branch July 12, 2026 04:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants