mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-10 22:20:14 +00:00
feat(studio): timeline leaf helpers — audio inspector, zoom math, UI prefs (#2192)
What: extends three leaf modules to their final NLE-stack form, tests in the same change: timelineInspector (isAudioTimelineElement, resolveBeatSourceTrack), timelineZoom (zoom/pps math incl. computePinnedZoomPercent), and studioUiPreferences (persisted editor prefs). Why: leaf dependencies of the NLE timeline stack; landing them first keeps the later glue PRs to wiring. How: additive from the consumer side — every export main already uses is unchanged (typecheck against main's consumers passes untouched); every new export is exercised by a test in this PR. Test plan: bunx vitest run on the three test files; tsc --noEmit in packages/studio; fallow audit --base origin/main clean.
This commit is contained in:
@@ -16,6 +16,18 @@ export interface StudioUiPreferences {
|
||||
gridVisible?: boolean;
|
||||
gridSpacing?: number;
|
||||
snapToGrid?: boolean;
|
||||
/** Timeline magnet: snap clip drags/trims/drops to playhead, clip edges, and beats. */
|
||||
timelineSnapEnabled?: boolean;
|
||||
/** Transport + ruler readout mode: timecode or frame number. */
|
||||
timeDisplayMode?: "time" | "frame";
|
||||
/**
|
||||
* Timeline zoom mode. Persisted so a zoom PINNED on the first edit survives the
|
||||
* post-edit iframe reload — otherwise the store reset to "fit" and the duration
|
||||
* change rescaled every clip (the blink-fix's rescale symptom).
|
||||
*/
|
||||
timelineZoomMode?: "fit" | "manual";
|
||||
/** Manual timeline zoom percent, paired with `timelineZoomMode: "manual"`. */
|
||||
timelineManualZoomPercent?: number;
|
||||
}
|
||||
|
||||
const STUDIO_UI_PREFERENCES_KEY = "hf-studio-ui-preferences";
|
||||
@@ -88,6 +100,21 @@ function readStorage(storage: Storage | null): StudioUiPreferences {
|
||||
if (typeof parsed.snapToGrid === "boolean") {
|
||||
preferences.snapToGrid = parsed.snapToGrid;
|
||||
}
|
||||
if (typeof parsed.timelineSnapEnabled === "boolean") {
|
||||
preferences.timelineSnapEnabled = parsed.timelineSnapEnabled;
|
||||
}
|
||||
if (parsed.timeDisplayMode === "time" || parsed.timeDisplayMode === "frame") {
|
||||
preferences.timeDisplayMode = parsed.timeDisplayMode;
|
||||
}
|
||||
if (parsed.timelineZoomMode === "fit" || parsed.timelineZoomMode === "manual") {
|
||||
preferences.timelineZoomMode = parsed.timelineZoomMode;
|
||||
}
|
||||
if (
|
||||
typeof parsed.timelineManualZoomPercent === "number" &&
|
||||
Number.isFinite(parsed.timelineManualZoomPercent)
|
||||
) {
|
||||
preferences.timelineManualZoomPercent = parsed.timelineManualZoomPercent;
|
||||
}
|
||||
return preferences;
|
||||
} catch {
|
||||
return {};
|
||||
|
||||
Reference in New Issue
Block a user