mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-11-04 04:46:59 +00:00
sync/hyperframes-codegen-75e380df
13
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
83b6419e97 |
test(studio): a script-hidden backdrop stays hidden over the A-roll while the preview plays (#5475)
A 9:16 fixture with a looping A-roll video, an untimed full-frame backdrop above it that the film's own GSAP script shows only from 6 s to 8 s, captions on top and two sub-compositions. The check plays it in Studio's preview and reads the preview's pixels and the element on top at the frame's centre: the video must show at rest and while playing outside the backdrop's window, and the backdrop must show inside it. It fails with #5458's visibility skip reverted. |
||
|
|
48bfe61803 |
fix(studio): a snap the saved clip would miss no longer moves it (#5006)
* fix(studio): a snap the saved clip would miss no longer moves it * test(studio): walk that a deep-zoom move lands where it shows, with no jump on release * test(studio): the release walk waits for the saved start, not the drag's own * test(studio): find the drag landing slot by its test id |
||
|
|
7859c0f003 |
fix(studio): trimming keeps the playhead still; clips snap to the ruler grid (#4986)
* fix(studio): trimming keeps the playhead still; clips snap to the ruler grid * fix(studio): an edge frame never becomes the playhead time; grid snaps where clips save * ci(studio): run the trim and grid snap walk with the other Studio browser checks * fix(studio): snap guides only where the clip saves; play keeps an explicit rewind * fix(studio): a snap guide shows only where the saved clip lands; preview frame gets its own store * fix(studio): judge a moved clip's guide by the duration the move keeps * chore(studio): trim comments the names already say |
||
|
|
7dea1e581f |
fix(studio): playhead keyframe edits keep their ease, undo names its edit and never waits on videos (#4889)
* fix(studio): an edit on a GSAP-animated layer writes its value at the playhead into the file's tween
* fix(studio): undo pressed while an edit saves undoes that edit, not one started after the key
* fix(studio): an edit stays saved when the history reply after it cannot be read
* feat(studio): export ColorField and GradientField; a session style commit takes a map
* refactor(studio): name the map form instead of commenting it
* feat(studio): a host can move layers by exact film px, one undo per call
handleDomGroupMoveBy(moves) on useDomEditSession and DomEditValue moves each
selection by its delta in composition px, for Desktop's align and distribute.
It reuses the group drag's own path: a drag member per element (press-time
route, measured offset map), the delta carried to screen px through the
preview frames, then handleGsapAwareGroupPathOffsetCommit, so one shared
coalesce key gives one undo entry and GSAP members take the GSAP write.
A member that can't move refuses the call before anything is written; the
refusal rejects with its reason and shows no Studio toast (the group commit
takes refusalToast: false; telemetry stays). Zero deltas are skipped.
Tests: a pre-offset element and one under a half-scale parent move by exactly
{10,0} and {0,-5} under one group key; a half-scale parent with a 30 deg
rotated ancestor lands within the 0.001 px a translate is written with; a
GSAP member goes through the GSAP write; three refusal kinds write nothing,
leave the boxes where they were, show no toast and leave no gesture mark,
while a canvas group drag still toasts; the session hands the call to the
group commit with refusalToast: false. Each mutation (no frame mapping, no
zero skip, no restore, no teardown, no capability check, toast on refusal)
fails at least one of them.
* fix(studio): an outside change during a drag waits for the drop to show
While a gesture mark is live in the preview, refreshPlayer takes the shadow load instead of
swapping scenes in place. A swap replaced the node under the pointer mid-drag; the shadow load
is then held by the existing gesture hold and, if the drop saved, reloaded fresh by the stale
rule, so this adds no second "released" signal.
Test: an outside change during a live drag on a preview that can swap scenes leaves the dragged
node in place, shows nothing under the pointer, and after the drop loads fresh with the dropped
position. It fails on the parent without the condition ("swapped under the pointer").
Cost case, measured in a real headless preview on the edit-accuracy bench's per-frame teleport
check. Every GSAP instant patch was forced to miss and fall back to reloadPreview during its own
commit; move and rotate of a held element (gsap.set and tl.set holds), px and xPercent
placement, r0 and r30, root and nested, at 100%:
- The gesture mark was live when the fallback asked for the reload, but had always ended by the
time refreshPlayer ran (refreshKey is consumed in an effect after the commit settles). So the
new condition never fired there: root previews offer no scene swap and load shadow on both
builds, and nested previews swap on both builds.
- Worst post-release frame offset, 32 cases on this build and 32 on the parent: 0.00 px over
76-106 frames each (release to settle). No frame was off by more than 0.5 px.
- Sensitivity: a 3 px nudge injected 50 ms after the fallback reads back as 3.00 px.
* fix(studio): an edit no longer reopens the live-updates stream, and thumbnails ask one at a time
* fix(studio): an undo no longer waits behind paused preview videos for a connection
* feat(studio): a host whose API needs same-origin cookies can have Studio send them
* docs(studio-server): a host on same-origin cookies sets the Studio credentials opt-out
* test(studio): an undo is not held up by the preview's paused videos
* fix(studio): a resize inside one gesture writes a mixed tween once, in place, never beside it
* chore(studio): keep the carried fixes inside the comment ratchet; telemetry posts through studioApiFetch
* test(studio): a drag on a mixed tween is one write under the gesture key
* fix(studio): freeze-frame, loudness and peak-map requests go through studioApiFetch too
* fix(studio): an undo with no project open reloads in full instead of skipping nested files
* refactor(studio): drop the soft reload's reparse seeding, the held-element sweep covers it
* test(studio): keep the undo-restore browser test off the network and inside its timeout
* test(studio): nested composition reads expect the cookie-free request studioApiFetch sends
* fix(studio): an edit at the playhead rewrites its tween in place, so later tweens keep their times
* fix(studio): a rotate on a tween that turns another axis holds its angle and never turns early
* fix(studio): plan every group member before the first write so one refusal moves none
A group drag or nudge preflighted each member against the move refusal rule only. The value-at-playhead planner ran later, in the commit loop, after earlier members were already flushed to disk, so a tween with extras, eased keyframes or an unknown ease left the group half moved.
The group preflight now runs the commit's own route and keyframe plan for every member with its real offset, so any refusal refuses the whole group with nothing written and one toast attributed to the refusing member. The plan is not reused in the commit: earlier members' writes change the file under it, so each member re-plans against the fresh tween, from the same planValueEdit.
* chore(studio): the fetch lint rule also catches window.fetch, globalThis.fetch and self.fetch
* docs(studio-server): set the credentials flag before Studio loads; a mounting host injects it
* test(studio): the undo socket test needs six pinned videos under Vite and checks each undo restores
* fix(studio): Studio leaves cookies out of its requests only when served from loopback
* fix(studio): undo takes back the first edit, and the first save never waits on media
* fix(studio): undo of a move whose save failed stays undone and steps back no older edit
* fix(studio): a style set by its JavaScript name saves under its CSS name
* test(studio): the undo socket test holds round 0 to a full restore too
* fix(studio): the host revert keeps returning what shows the edit again
* fix(studio): an entrance rewritten at the playhead still shows its start state before it starts
* fix(studio): undo takes back the edit pending at the key even after a later edit claims
* chore(studio): lift the late-write quarantine now that undo never waits on videos; format
* test(studio): pin an entrance's start render on the written tween, not a happy-dom GSAP run
* revert(studio): leave entrances as on main, immediateRender does not render a keyframed start
This reverts commit
|
||
|
|
67dbcf7bdb |
feat(studio): preview timeline track insertion (#4907)
* feat(studio): preview new tracks at drop boundaries * fix(studio): preserve group ownership across overlapping moves * refactor(studio): share timeline drop decisions and fixtures * fix(studio): open an empty audio zone below visual tracks * fix(studio): cancel thumbnails when project pages leave * refactor(studio): share thumbnail regression setup * test(studio): gate thumbnail socket release in browser CI * chore(studio): keep optimistic revision comments within ratchet * fix(studio): pin regression proxy requests to its backend * test(studio): bound the proxy origin probe * test(studio): probe proxy origin through the ready document |
||
|
|
e205207583 |
fix(studio): a text edited in place shows its caret in a scaled preview (#4875)
* fix(studio): a text edited in place shows its caret in a scaled preview * fix(studio): the drawn caret follows a resized preview and stands right at bold words and empty lines * fix(studio-server): a write receipt's replaced version comes only from the bytes it overwrote * fix(studio): the drawn caret stands on the selection inside a transformed canvas * test(studio): unmount the caret tests' roots before clearing the page * test(studio): the caret gate waits for each key to land and retries a text that does not open * test(studio): the caret gate checks what the DOM can tell at a soft wrap, and shows a text that would not open * test(studio): the caret gate opens a text with a double press when click and Enter do not * fix(studio): the drawn caret follows a pan or zoom of the preview * fix(studio): the inline text style bar stands by the selected text inside a transformed canvas * fix(studio): after End at a soft wrap the drawn caret stays at the line's end, as the system caret does * fix(studio): only End keeps the drawn caret at a wrapped line's end, as Chrome's own caret * refactor(studio): share the test mount helper and split the caret's placement for the code gates * docs(studio): trim the drawn caret's comments to the package's share * fix(studio): open inline edit on styled text whose nodes come from another window * refactor(studio): name the realm-safe html check instead of commenting it * docs(studio): shorten the caret fixture comment to the 120-character limit |
||
|
|
e3ac225a9c |
fix(studio): fade handles show a real tooltip and a 24 px target (#4819)
* fix(studio): fade handles show a real tooltip and a 24 px target
A sound clip's fade-in and fade-out dots now open Studio's tooltip
("Fade in 0.3 s") instead of a native title the clip's own title
competed with, take a 24 px hit box, and paint an opaque white dot that
reads on the audio clip in both timeline themes.
* fix(studio): fade handles sit at the clip's top corners, above its content
The fade-in and fade-out dots now pin to the clip's top-left and top-right
corners instead of the end of each fade, paint above the waveform and
thumbnail layers, and share a short clip's width without overlapping. The
fade ramps are clipped to the clip's rounded corners, and the tooltip
uses the same seconds format as the slider's value text.
* fix(studio): fade dots keep their 10 px size on a very narrow clip
On a clip narrower than two fade hit boxes the flex row squeezed each dot
below 10 px. The dot no longer shrinks and no longer takes the pointer, a
browser check measures its box on a 0.1 s clip in CI, and two drag test
comments now describe the corner handles.
* fix(studio): the Escape key cancels a fade drag wherever keyboard focus is
A press on a fade handle never focuses it, so Escape only reached the
handle's own key handler when something else had focused it, and the
release then saved the dragged fade. The drag now listens for Escape on
the window for as long as it lasts, restores the fade and saves nothing.
* test(studio): trim the fade handle browser check header to what the code cannot say
|
||
|
|
73519b6452 |
ci(studio): gate opening a film in Studio on work counts that only go down (#4457)
* ci(studio): gate Studio open and timeline scroll on work counts that only go down Beside the timeline viewport gate's ms budgets, count the work two Studio journeys do and hold each count under a checked-in ceiling in perf-ceilings.json: thumbnail renders, page loads and requests for opening a 12-scene film, and React commits, style recalcs and layouts per scroll tick. Counts repeat exactly run to run, so a rise names the work that grew. * ci(studio): hold style recalcs per scroll tick at the CI runner's count * ci(studio): gate the median scroll run and list which thumbnails rendered * ci(studio): set work-count ceilings from the CI runner's counts on main * ci(studio): fail the open count loudly when Studio never starts * ci(studio): fail a work-count gate that measured nothing * ci(studio): a scroll counter missing from any measured run reads as not measured * ci(studio): split the perf ratchet's CLI and page counters into small steps, and let its unit test count * ci(studio): count scroll work in an untimed pass and commit the open fixture's scenes * ci(studio): gate only the open journey's counts; scroll counts follow runner speed * ci(studio): fail a dropped journey and an unreadable base in the work-count ratchet * ci(studio): split the ratchet's checks into small functions |
||
|
|
6b5b4cb988 | feat(studio): make agent edits live and explicit (#3581) | ||
|
|
723d3381c4 |
fix(studio): keep dense keyframes readable (#2925)
* perf(studio): define timeline viewport budgets and fixtures * test(studio): gate timeline viewport performance in Chromium * refactor(studio): isolate clip drag lifecycle * refactor(studio): extract timeline render contracts * perf(studio): centralize timeline viewport geometry * perf(studio): follow playhead across virtualized rows * perf(studio): add timeline clip-window index primitive * perf(studio): virtualize timeline clip windows * perf(studio): stop timeline scroll work when row virtualization is off The row virtualization stack made the timeline publish a viewport snapshot on every scroll frame and swap `renderClipContent` across every mounted clip at gesture start and settle. Both are windowing concessions, and neither was gated on the flag, so the build users actually run paid for them while mounting all 1,000 clips anyway. Measured on a 3,000-clip project: median scroll step 16.6ms to 76.9ms, p95 17.9ms to 189.4ms, 40 long tasks to 247. Gate both on the row virtualization flag. The scroll path now stops at the door when the flag is off, so `isScrolling` stays false and resize-driven and programmatic syncs still publish through the immediate path. The flag moves into its own module: the scroll-viewport hook needs to read it, and the virtualization hook already imports the viewport snapshot type back, which would have closed an import cycle. Also release the perf fixture lease from the fixture rather than from the test-hook effect. Loading a fixture writes player state, which changed that effect's dependency identities and tore it down on the next frame, so the lease was revoked moments after it was taken and live iframe discovery overwrote the fixture before the gate could measure it. The e2e gate gains a flag-off arm (`test:timeline-default`, 1,000 elements) next to the existing flag-on one. It refuses the 50,000-element combination, verifies from the mounted DOM that the server under test matches the requested flag, and skips the DOM-size budgets for the unvirtualized build rather than relaxing them, so a skipped budget never reads as a passed one. Verified against a live Studio dev server on the fixture project: flag off, before: interactionP95 303.1ms, longest task 194ms, 0/5 runs pass flag off, after: interactionP95 33.6ms, longest task 0ms, 5/5 runs pass flag on, after: interactionP95 33.2ms, 4/5 runs pass, exit 0 The flag-on arm's fourth run reproducibly reports a 55-58ms long task against a 50ms budget. That is the residual tail of the window swap itself, tracked separately and not addressed here. * ci(studio): run the timeline viewport gate on studio changes The gate has existed since the row virtualization stack landed but nothing under `.github/` referenced it, so it only ever ran when someone ran it by hand. That is how the flag-off scroll regression reached eight merged-ready PRs without anything noticing. Adds a `studio-timeline-viewport` job that boots two Studio dev servers, one per flag state, and runs both arms of the gate against them. Two servers are needed because row virtualization is read from `import.meta.env` at module load, so one process cannot serve both builds. Scoped to a new `studio` paths filter rather than the broad `code` one: the gate only says anything about `packages/studio`, `packages/core` and `packages/studio-server`. Adds a `ci` tier. It applies the constrained budgets without any emulation, because a hosted runner is already slower and noisier than the machine the strict numbers were recorded on, while the existing `low-resource` tier would throttle it a further 4x and measure the throttle rather than the build. The fixture composition is tracked under `tests/e2e/fixtures` but Studio resolves projects from the gitignored `data/projects`, so the job copies it into place instead of a project directory being committed. Both arms run in about 7 seconds each locally, so the job cost is almost entirely dependency install and the workspace build it shares with `studio-load-smoke`. * fix(ci): preserve both timeline gate evidence arms * ci(studio): report timeline gate arm statuses * ci(studio): require timeline gate evidence artifacts * fix(studio): keep dense keyframes readable * fix(ci): resolve timeline stack audit findings |
||
|
|
d57039882f | fix(studio): harden keyframe editing semantics | ||
|
|
2b65b4efce |
fix(studio): harden composition timeline reliability (#2615)
* fix(studio): preserve composition playback continuity * feat(studio): drag compositions into the timeline * fix(studio): collapse expanded composition move aliases * fix(studio): make timeline cuts atomic * fix(studio): group inspector gesture history * test(studio): cover masked text selection * fix(studio): harden composition timeline reliability * fix(studio): satisfy CI source gates * fix(studio): harden composition mutation requests |
||
|
|
4d199c0f3a |
test(studio): add design-panel QA fixture and triage matrix (#1906)
Fixture project covering all panel-editable element archetypes, plus the QA findings matrix from the design-panel bug campaign. |