Skip to content

recorder: playback scopes — segment tap plays one clip, ▶ plays through - #170

Merged
morepriyam merged 2 commits into
feat/preview-card-glass-badgesfrom
feat/playback-scopes
Aug 26, 2026
Merged

recorder: playback scopes — segment tap plays one clip, ▶ plays through#170
morepriyam merged 2 commits into
feat/preview-card-glass-badgesfrom
feat/playback-scopes

Conversation

@morepriyam

@morepriyam morepriyam commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator

Closes #166. Closes #165.

Stacked on #169. Two commits:

  1. Playback scopes — a single-file diff in use-preview.ts (the behavior change)
  2. Segment-bar polish — UI fixes that fell out of exercising the scopes on device (segment-bar.tsx, playhead-cursor.tsx, track-metrics.ts)

Commit 1 — playback scopes

Previously, tapping a segment thumbnail auto-advanced through every following clip, and there was no way to hear just one clip. This splits playback into two scopes with no new UI:

Gesture Scope Result
Thumb tap (opens preview or mid-preview) single plays only that clip, parks at its end
Center ▶ / surface tap all plays through from wherever the playhead is, clip to clip, to the draft's end
Playhead scrub all lands paused; ▶ then continues through

▶ edge cases: parked at a clip's end → continues into the next playable clip; parked at the draft's very end → wraps to clip 1 (replay); single-clip draft → restarts in place.

#165 originally proposed a dedicated play-all button — during design this landed on reusing the existing center ▶ instead: no segment-bar space consumed, one obvious control, and "play through from here" covers the full-playthrough case.

Implementation notes

  • Scope lives in a ref ('single' | 'all') — playback events read it, nothing renders from it
  • playToEnd in single scope parks 1ms shy of the out-point: at exactly outMs the draft-global position is the clip boundary, which msToPx/indexAtGlobalMs resolve to the next segment at fraction 0 — the bar knob visibly hopped onto the next thumb
  • Clip boundaries still advance only on the native playToEnd event — no epsilon-based advancing, so no path truncates a clip or the timeline

Commit 2 — segment-bar polish (found while testing commit 1)

  • playhead line no longer strikes through the ordinal pills — the cursor is a sibling drawn over the ScrollView (zIndex can't cross that boundary), so the line now starts below the pill's dip into the thumb; BADGE_SIZE moves into track-metrics so bar and cursor share it. Directly caused by commit 1: single-clip playback parks the playhead ON a clip, making the strike-through constantly visible
  • stable bar size — the scrub lane is reserved permanently instead of added with the cursor, which grew the bar and bumped it upward on every preview open; the → button gets a matching margin to stay on the thumbs' centerline
  • centered + slimmer — the lane mirrored as top padding centers the thumbs; lane trimmed 16→12 (the knob only overhangs ~4pt, the rest is hitSlop headroom)
  • glass segment barGlassPill as a passive absolute-fill background layer (pointerEvents="none") behind the existing hierarchy; Sortable grid, ScrollView, playhead, and drag-to-trash portal untouched. Resolves the ui: extend Liquid Glass to all chrome floating over video #168 segment-bar item (perf-verified on device: scrub, reorder, playhead-follow all smooth)

Testing

  • tsc --noEmit, ESLint, and the jest suite (126 passing) clean
  • Verified on device: single-clip play + park position, ▶ continuing across boundaries to the draft end, replay-from-end wrap, scrub-then-resume playing through, pause/resume mid-clip; bar stability across preview open/close, reorder + drag-to-trash, scroll preservation on delete

A tapped segment now plays only itself and parks at its end instead of
auto-advancing through every following clip. The center ▶ / surface tap
becomes the play-through control: it resumes from wherever the playhead
is and walks clip to clip to the draft's end — continuing into the next
clip when parked at a clip's end, and wrapping to the first clip when
parked at the draft's very end.

- new playback scope ref ('single' | 'all'): tap-open and thumb taps
  narrow to 'single'; togglePlay and bar scrubs widen to 'all'
- playToEnd parks 1ms shy of the out-point in 'single' scope so the bar
  knob rests inside the played clip — at exactly outMs the global
  position is the boundary, which msToPx resolves to the NEXT thumb's
  left edge
- clip boundaries still advance only on the native playToEnd event, so
  no path truncates playback

Closes #166, closes #165
…ean ordinals

Preview-adjacent polish that fell out of exercising the playback scopes:

- glass segment bar: GlassPill as a passive absolute-fill background LAYER
  (pointerEvents none) behind the existing hierarchy — the Sortable grid,
  ScrollView, playhead, and drag-to-trash portal are untouched, so no
  gesture or reorder behavior can change
- stable bar size: the scrub lane is reserved permanently instead of added
  with the cursor, which grew the bar and bumped it upward on every
  preview open; the → button gets a matching margin to stay on the
  thumbs' centerline
- centered + slimmer: the lane is mirrored as top padding (thumbs land
  dead-center) and trimmed 16→12 — the knob only overhangs ~4pt, the rest
  is hitSlop headroom
- playhead line no longer strikes through the ordinal pills: the cursor
  is a sibling drawn OVER the ScrollView (zIndex can't cross that
  boundary), so the line now starts below the pill's dip into the thumb;
  BADGE_SIZE moves into track-metrics so bar and cursor share it
@morepriyam

Copy link
Copy Markdown
Collaborator Author

Added a second commit with segment-bar polish that fell out of exercising the playback scopes on device:

  • glass segment barGlassPill as a passive absolute-fill background layer (pointerEvents="none") behind the existing hierarchy; the Sortable grid, ScrollView, playhead, and drag-to-trash portal are untouched. This was the ui: extend Liquid Glass to all chrome floating over video #168 item flagged "perf-test glass + Reanimated before committing" — verified on device: scrub, reorder, and playhead-follow all stay smooth
  • stable bar size — the scrub lane is reserved permanently instead of appearing with the cursor, which grew the bar and visibly bumped it upward on every preview open
  • centered + slimmer — the lane mirrored as top padding centers the thumbs; lane trimmed 16→12
  • clean ordinals — the playhead line starts below the badge pills instead of striking through them (the cursor is a sibling drawn over the ScrollView, so zIndex can't fix it from inside)

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Updates the in-recorder preview playback behavior so segment thumbnail taps play only the selected clip, while the center ▶ / surface tap plays through the draft from the current playhead position.

Changes:

  • Add a 'single' | 'all' playback scope ref in usePreview, switching scope based on gesture (thumb tap vs ▶/surface tap vs scrub).
  • In 'single' scope, park playback at the clip end (1ms shy of outMs) instead of auto-advancing; in 'all' scope, continue across clip boundaries and wrap/replay from the end.
  • Adjust recorder segment bar visuals/geometry (glass background layer + scrub/badge metrics) to keep layout stable while previewing.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
src/features/recorder/use-preview.ts Introduces playback scopes and changes end-of-clip handling + ▶ behavior to support single-clip vs play-through.
src/features/recorder/track-metrics.ts Tweaks track constants (SCRUB_LANE) and centralizes BADGE_SIZE for shared geometry.
src/features/recorder/segment-bar.tsx Adds a GlassPill background layer and updates padding/viewport behavior for a stable scrub lane.
src/features/recorder/playhead-cursor.tsx Updates cursor line start/height to account for the badge pill geometry (BADGE_SIZE).

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/features/recorder/segment-bar.tsx

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

@morepriyam morepriyam self-assigned this Aug 14, 2026

@SarkarShubhdeep SarkarShubhdeep 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.

Everything looks good.

@morepriyam
morepriyam added this pull request to the merge queue Aug 26, 2026
Merged via the queue into main with commit b5a6727 Aug 26, 2026
2 checks passed
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.

recorder: segment tap plays only that segment, then stops recorder: “play all” button for full playthrough of the draft

3 participants