refactor(studio): simplify hooks, split contexts, remove dead code#1416
Merged
Conversation
…re memory leak - Guard setIsPlaying to skip set() when value unchanged (eliminates 60 notifications/sec during reverse playback) - Guard caption store selectGroup to bail before set() when group missing (prevents empty Zustand notifications) - Guard clearSelection to skip when already empty - Fix useConsoleErrorCapture: restore original console.error, remove error event listener, and delete __hfErrorCapture flag on cleanup
Remove 7 dead files (audioBeatDetection, keyframeSnapping, timelineInspector, DopesheetStrip, StaggerControls, TimelineLayerPanel, TimelineEditorNotice) and their test companions. Delete unused computeFitToChildrenSize export from propertyPanelHelpers. Fix re-export indirection: useDomEditCommits and studioMotionOps.test now import patch builders directly from manualEditsDomPatches instead of the re-export passthrough in manualEditsDom.
…, hover, and GSAP fetch Move lint findingsByElement sync from App.tsx into useLintModal where the value is produced, removing the mirroring useEffect. Consolidate 4 hover-clearing effects in useDomSelection into 2 (one unconditional on context change, one conditional combining caption mode, selection match, and disconnected element checks). Fold the GSAP retry effect into the fetch effect in useGsapTweenCache, scheduling a single retry via setTimeout when the initial fetch returns 0 animations. Eliminates 3 unnecessary render cycles from effect chains.
… re-render cascade - Wrap renderQueue object in useMemo so StudioContext consumers don't re-render on every App render - Memoize timelineToolbar JSX so NLELayout memo isn't defeated - Move canvasRect getBoundingClientRect() from render-time IIFE to a useLayoutEffect-backed ref, eliminating layout thrashing - Track and clear setTimeout handles in refreshPreviewDocumentVersion to prevent stale timer accumulation on rapid calls and unmount
…me access, keyframe parsing Extract duplicated PROPERTY_DEFAULTS, IframeGsap interface, iframe accessors (getIframeGsap, queryIframeElement), percentage keyframe parsing, and toAbsoluteTime into a single gsapShared.ts module. Removes ~120 lines of copy-pasted logic across 8 hook files, reducing drift risk between the duplicate implementations.
…nd unsafe assertions
…ntage computation, and iframe access
…implification-wave-1 Co-authored-by: Miguel Ángel <miguel07alm@protonmail.com>
…fication-wave-1 Co-authored-by: Miguel Ángel <miguel07alm@protonmail.com>
…io-simplification-wave-1 Co-authored-by: Miguel Ángel <miguel07alm@protonmail.com>
…-simplification-wave-1 Co-authored-by: Miguel Ángel <miguel07alm@protonmail.com>
…mplification-wave-1 # Conflicts: # packages/studio/src/hooks/gsapRuntimePreview.ts
…ification-wave-1 # Conflicts: # packages/studio/src/hooks/gsapKeyframeCommit.ts # packages/studio/src/hooks/gsapRuntimeBridge.ts # packages/studio/src/hooks/gsapRuntimeKeyframes.ts # packages/studio/src/hooks/gsapRuntimeReaders.ts # packages/studio/src/hooks/gsapShared.ts # packages/studio/src/utils/audioBeatDetection.ts
…n hooks Extract useFileTree (tree loading, refresh, derived assets/compositions) and useEditorSave (debounced save with history tracking) from the 508-LOC useFileManager. The parent hook composes both and retains file I/O, click-to-source, upload/import, and CRUD — preserving the same public interface so no consumers change.
Extract geometry (path offset, box size, rotation) and element lifecycle (delete, z-index reorder) into useDomGeometryCommits and useElementLifecycleOps. Parent keeps persistDomEditOperations as core and composes all sub-hooks — public interface unchanged.
Replace 15 individual useRef callback refs with a single cbRef object. Extract keydown dispatch into pure dispatchModifierKey/dispatchPlainKey functions. Merge duplicate undo/redo logic into shared applyHistory. Extract cross-origin listener boilerplate into safeAddListener/safeRemoveListener. Hook body: 204 LOC (down from 445). Public API unchanged.
Extract GSAP-aware geometry intercepts (move/resize/rotation) and animated property commit into useGsapAwareEditing, and selection wiring, GSAP cache management, preview sync, and selection handlers into useDomEditWiring. The parent remains a pure composition shell.
Comment on lines
+57
to
+59
| const response = await fetch( | ||
| `/api/projects/${pid}/files/${encodeURIComponent(targetPath)}`, | ||
| ); |
Comment on lines
+75
to
+82
| const removeResponse = await fetch( | ||
| `/api/projects/${pid}/file-mutations/remove-element/${encodeURIComponent(targetPath)}`, | ||
| { | ||
| method: "POST", | ||
| headers: { "Content-Type": "application/json" }, | ||
| body: JSON.stringify({ target: patchTarget }), | ||
| }, | ||
| ); |
| } | ||
| let cancelled = false; | ||
| setFileTreeLoaded(false); | ||
| fetch(`/api/projects/${projectId}`) |
| const refreshFileTree = useCallback(async () => { | ||
| const pid = projectIdRef.current; | ||
| if (!pid) return; | ||
| const res = await fetch(`/api/projects/${pid}`); |
Collaborator
Author
|
Splitting into a Graphite stack of 9 smaller PRs for easier review. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
StudioContextinto Shell + Playback to stop playback state re-rendering shell UIDomEditContextinto Actions + Selection to stop hover re-rendering edit consumersTimelineEditContextto eliminate 15-callback prop drilling chaingsapShared.tsTest plan
bun run --cwd packages/studio typecheckpassesbun run --cwd packages/studio test— all 796 tests pass