mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-09 03:16:38 +00:00
fix(studio): add preview zoom controls (#761)
* fix(studio): add smooth preview zoom with pinch/Ctrl+scroll - Scale iframe content from inside (contentDocument.documentElement) instead of scaling the parent div, avoiding compositor re-rasterization on every zoom frame — critical for smooth zoom on high-refresh displays (240Hz) - Document-level capture-phase wheel handler bypasses the DomEditOverlay - Center-based zoom (no pan drift from pointer-anchored formulas) - Transient HUD shows zoom % briefly, no persistent UI controls - Double-click preview area to reset zoom to fit - Drag-to-pan when zoomed past 100% - Momentum scroll suppression after pinch gesture (400ms cooldown) - Delta clamping (MAX_DELTA=10) prevents overshooting on fast gestures - toDomPrecision rounds transform values to 4 decimals (matches tldraw) - Zoom state persisted to localStorage with 200ms debounce - Exposes --preview-zoom CSS custom property for overlay coordinate mapping - Fix infinite render loop in NLELayout (onIframeRef → refreshPreviewDocumentVersion) * fix(studio): use CSS zoom instead of transform scale for preview zoom CSS transform: scale() on a div containing an iframe causes compositor cross-layer sync issues that produce visible frame tearing on high-refresh displays (240Hz ProMotion). CSS zoom property changes the actual rendered size without compositor layer synchronization, eliminating the jumping. - Replace transform: scale(Z) with zoom: Z on the stage div - Keep transform: translate() for panning (compositor-friendly, no iframe) - Overlays work correctly since getBoundingClientRect() includes zoom - Remove will-change, transition hacks, pointer-events toggles * fix(ci): use apt-get for ffmpeg in preview-regression workflow The FedericoCarboni/setup-ffmpeg action downloads from an external URL that has been persistently unreachable, causing CI failures. Switch to apt-get install which uses Ubuntu's package repos (same as ci.yml and player-perf.yml). * fix(studio): clear zoom timers on NLEPreview unmount settleTimerRef, hudTimerRef, and retiringTimerRef could fire after component unmount. Add cleanup effect to prevent stale callbacks. * feat(studio): persist sidebar, timeline, and playback speed across reloads Wire up studioUiPreferences for the three remaining UI states requested in #752: left sidebar collapsed, timeline visibility, and playback rate. All three now survive page reloads using the same localStorage key as preview zoom.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { create } from "zustand";
|
||||
import { readStudioUiPreferences, writeStudioUiPreferences } from "../../utils/studioUiPreferences";
|
||||
|
||||
export interface TimelineElement {
|
||||
id: string;
|
||||
@@ -88,7 +89,7 @@ export const usePlayerStore = create<PlayerState>((set) => ({
|
||||
timelineReady: false,
|
||||
elements: [],
|
||||
selectedElementId: null,
|
||||
playbackRate: 1,
|
||||
playbackRate: readStudioUiPreferences().playbackRate ?? 1,
|
||||
loopEnabled: false,
|
||||
zoomMode: "fit",
|
||||
manualZoomPercent: 100,
|
||||
@@ -98,7 +99,10 @@ export const usePlayerStore = create<PlayerState>((set) => ({
|
||||
clearSeekRequest: () => set({ requestedSeekTime: null }),
|
||||
|
||||
setIsPlaying: (playing) => set({ isPlaying: playing }),
|
||||
setPlaybackRate: (rate) => set({ playbackRate: rate }),
|
||||
setPlaybackRate: (rate) => {
|
||||
writeStudioUiPreferences({ playbackRate: rate });
|
||||
set({ playbackRate: rate });
|
||||
},
|
||||
setLoopEnabled: (enabled) => set({ loopEnabled: enabled }),
|
||||
setZoomMode: (mode) => set({ zoomMode: mode }),
|
||||
setManualZoomPercent: (percent) =>
|
||||
|
||||
Reference in New Issue
Block a user