fix: stabilize studio preview and runtime sync#389
Conversation
This stack of pull requests is managed by Graphite. Learn more about stacking. |
|
One additional gap I noticed that I could not attach inline because the file is outside the PR diff: the selector-aware thumbnail path looks only partially wired through. |
|
Addressed the selector thumbnail gap in What changed:
Verification:
|
jrusso1020
left a comment
There was a problem hiding this comment.
Foundation looks solid. Good test coverage on the new pure helpers (mergeTimelineElementsPreservingDowngrades, getPreviewPlayerKey, thumbnail selector plumbing). The runtime-source fallback making dev/CI independent of a prebuilt @hyperframes/core artifact is a nice ergonomic win.
Two things worth calling out — neither blocking:
-
Soft breaking change in
timeline.ts: persistent overlays now requiredata-timeline-role="overlay"(or"persistent-overlay") to appear in Studio. Existing compositions with auto-showing<div id="grid-overlay">style decorations will silently disappear from the timeline UI. Playback isn't affected, but the in-Studio tracklist will look different. Worth a one-line mention in the alpha release notes so authors know about the opt-in attribute. -
Duration no longer "don't-downgrade": previous guard on
handleMessagewasif (dur > currentDur) setDuration(dur); this PR removes that and accepts any0 < dur < 7200. Reasoning is clear (stop drifting from runtime), andmergeTimelineElementsPreservingDowngradeshandles the element side. Just noting: if an intermediate manifest during generation reports a shorter duration, the timeline controls will now flap with it. Likely fine, but keep an eye on it once timeline editing lands on top. -
opts.selector→page.evaluate(selector => document.querySelector(selector)): safe functionally (querySelectordoesn't execute), but a crafted selector like*:has(*:has(...))could be arbitrarily expensive to evaluate and the cache-key sanitizer creates distinct keys per input, so every variation bypasses the cache. Post-alpha, worth a selector length/complexity guard on the route handler.
Approved for alpha.
— Rames Jusso
Merge activity
|
## Summary Add the actual Studio timeline editing layer on top of the preview/runtime foundation. This PR includes: - drag-to-move clips across time and tracks - left/right resize handles with media-aware trim persistence - edge auto-scroll and edge track creation while dragging - selector-based source patching for `data-start`, `data-duration`, `data-track-index`, `z-index`, and media trim attributes - timeline UI cleanup, theming, hover/drag states, and the `Copy Prompt` action ## Why This PR Is Separate This is the user-facing editing behavior. It depends on the preview/runtime fixes in the base PR, but it is much easier to review once that plumbing is isolated. ## Verification - `bun run --filter @hyperframes/studio test` - `bun run --filter @hyperframes/studio typecheck` - `bunx oxlint packages/studio/src/App.tsx packages/studio/src/components/nle/NLELayout.tsx packages/studio/src/player/components/EditModal.tsx packages/studio/src/player/components/Timeline.tsx packages/studio/src/player/components/TimelineClip.tsx packages/studio/src/player/components/timelineEditing.ts packages/studio/src/player/components/timelineEditing.test.ts packages/studio/src/player/components/timelineTheme.ts packages/studio/src/player/components/timelineTheme.test.ts packages/studio/src/utils/sourcePatcher.ts packages/studio/src/utils/sourcePatcher.test.ts` - `bunx oxfmt --check packages/studio/src/App.tsx packages/studio/src/components/nle/NLELayout.tsx packages/studio/src/player/components/EditModal.tsx packages/studio/src/player/components/Timeline.tsx packages/studio/src/player/components/TimelineClip.tsx packages/studio/src/player/components/timelineEditing.ts packages/studio/src/player/components/timelineEditing.test.ts packages/studio/src/player/components/timelineTheme.ts packages/studio/src/player/components/timelineTheme.test.ts packages/studio/src/utils/sourcePatcher.ts packages/studio/src/utils/sourcePatcher.test.ts` ## Browser Proof - verified timeline drag / resize / trim flows in Studio with `agent-browser` - verified preview hot-refresh behavior without iframe remount flashes ## Stack - depends on #389 - followed by `fix: smooth scrubber end seeking` [result.mp4 <span class="graphite__hidden">(uploaded via Graphite)</span> <img class="graphite__hidden" src="https://app.graphite.com/user-attachments/thumbnails/ca71c177-5042-468d-906f-b353938f40f8.mp4" />](https://app.graphite.com/user-attachments/video/ca71c177-5042-468d-906f-b353938f40f8.mp4)

Summary
Stabilize the Studio preview/runtime path so timeline data, preview rendering, and thumbnails stay in sync.
This PR includes:
Why This PR Exists
This is the foundation layer for timeline editing. Without it, the editor was prone to:
@hyperframes/playerartifacts were not prebuiltVerification
bun run --filter @hyperframes/studio testbun run --filter @hyperframes/studio typecheckbun run --filter @hyperframes/core typecheckbunx oxlint packages/cli/src/server/studioServer.ts packages/core/src/runtime/timeline.ts packages/core/src/runtime/timeline.test.ts packages/core/src/studio-api/routes/thumbnail.ts packages/core/src/studio-api/routes/thumbnail.test.ts packages/core/src/studio-api/types.ts packages/studio/src/components/nle/NLELayout.tsx packages/studio/src/components/nle/NLEPreview.tsx packages/studio/src/components/nle/NLEPreview.test.ts packages/studio/src/player/components/CompositionThumbnail.tsx packages/studio/src/player/components/Player.tsx packages/studio/src/player/hooks/useTimelinePlayer.ts packages/studio/src/player/store/playerStore.ts packages/studio/vite.config.tsbunx oxfmt --check packages/cli/src/server/studioServer.ts packages/core/src/runtime/timeline.ts packages/core/src/runtime/timeline.test.ts packages/core/src/studio-api/routes/thumbnail.ts packages/core/src/studio-api/routes/thumbnail.test.ts packages/core/src/studio-api/types.ts packages/studio/src/components/nle/NLELayout.tsx packages/studio/src/components/nle/NLEPreview.tsx packages/studio/src/components/nle/NLEPreview.test.ts packages/studio/src/player/components/CompositionThumbnail.tsx packages/studio/src/player/components/Player.tsx packages/studio/src/player/hooks/useTimelinePlayer.ts packages/studio/src/player/store/playerStore.ts packages/studio/vite.config.tsStack
feat: add studio timeline editingfix: smooth scrubber end seeking