mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-11 14:50:02 +00:00
fix(studio): label undo history with the track display row
The timeline track key is a fractional z-order sort key: an expanded sub-composition child gets `host.track + n / (siblings + 2)`. The undo history entry for the eye toggle interpolated that key directly, so hiding an expanded child recorded "Hide track 0.16666666666666666". Give the key-to-display-row conversion a single owner (timelineTrackDisplay.ts) and route both the track header labels and the history label through it, so the two cannot drift apart again. The raw key still routes the callbacks and lookups that need it. Adds a regression test that toggles a track keyed 1 / 6; a test on track 0 formats cleanly and proves nothing.
This commit is contained in:
@@ -4,6 +4,7 @@ import { TimelineClipDiamonds } from "./TimelineClipDiamonds";
|
||||
import { TimelinePropertyLanes } from "./TimelinePropertyLanes";
|
||||
import { TimelineTrackHeader } from "./TimelineTrackHeader";
|
||||
import { resolveTrackKeyframeClip } from "./useTimelineTrackLayout";
|
||||
import { trackDisplayNumber } from "./timelineTrackDisplay";
|
||||
import { clipTimingStart } from "../../hooks/gsapShared";
|
||||
import { getTimelineEditCapabilities, resolveBlockedTimelineEditIntent } from "./timelineEditing";
|
||||
import { CLIP_Y, CLIP_HANDLE_W, TRACK_H, getTimelineRowHeight } from "./timelineLayout";
|
||||
@@ -105,6 +106,7 @@ export function TimelineLanes({
|
||||
// in a virtualizer if editorial workflows ever push very high clip counts.
|
||||
// fallow-ignore-next-line complexity
|
||||
displayTrackOrder.map((trackNum, row) => {
|
||||
const displayNumber = trackDisplayNumber(displayTrackOrder, trackNum);
|
||||
const rowHeight = getTimelineRowHeight(row, rowHeights);
|
||||
const els = tracks.find(([t]) => t === trackNum)?.[1] ?? [];
|
||||
const ts = trackStyles.get(trackNum) ?? getTrackStyle("");
|
||||
@@ -150,8 +152,10 @@ export function TimelineLanes({
|
||||
trackNumber={trackNum}
|
||||
// What gets announced. `trackNum` is a fractional z-order sort
|
||||
// key, so it stays out of every label and in every callback.
|
||||
trackDisplayNumber={row + 1}
|
||||
trackLabel={els[0]?.label ?? els[0]?.domId ?? els[0]?.id ?? `Track ${row + 1}`}
|
||||
trackDisplayNumber={displayNumber}
|
||||
trackLabel={
|
||||
els[0]?.label ?? els[0]?.domId ?? els[0]?.id ?? `Track ${displayNumber}`
|
||||
}
|
||||
lanesId={lanesId}
|
||||
contentOrigin={contentOrigin}
|
||||
keyframeClip={keyframeClip}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* The one owner of "what track number does the user see".
|
||||
*
|
||||
* `TimelineElement.track` is a z-order SORT key, not a row number: an expanded
|
||||
* sub-composition child gets a synthesized fractional key (`host.track + n /
|
||||
* (siblings + 2)`, see `useExpandedTimelineElements`), so putting it in a string
|
||||
* announces "Hide track 0.16666666666666666". Every user-visible track number,
|
||||
* whether it is rendered by a component or baked into an undo-history label,
|
||||
* routes through here; the raw key stays in callbacks and lookups only.
|
||||
*/
|
||||
|
||||
/** Ascending distinct track keys, the row order the timeline renders in. */
|
||||
export function timelineTrackOrder(elements: readonly { track: number }[]): number[] {
|
||||
return [...new Set(elements.map((element) => element.track))].sort((a, b) => a - b);
|
||||
}
|
||||
|
||||
/**
|
||||
* A track key's 1-based display row. A key not in `trackOrder` (a drag preview
|
||||
* onto a brand-new track, say) reads as the row it would land on at the end.
|
||||
*/
|
||||
export function trackDisplayNumber(trackOrder: readonly number[], track: number): number {
|
||||
const row = trackOrder.indexOf(track);
|
||||
return row < 0 ? trackOrder.length + 1 : row + 1;
|
||||
}
|
||||
Reference in New Issue
Block a user