4.1 KiB
4.1 KiB
Complete Refactor Plan
✅ COMPLETED
-
Created Command Pattern Architecture
- Base
Commandclass withexecute(),undo(),redo() - 15 timeline commands in
src/lib/commands/timeline/ - All phases implemented (track ops, element ops, toggles, split, paste, etc.)
- Base
-
Created HistoryManager
- Generic
HistoryManager<T>for undo/redo tracking - Returns command after execution (for getting return values like IDs)
- Completely decoupled from timeline logic
- Generic
-
Refactored TimelineManager
- Removed all UI state (
snappingEnabled,rippleEditingEnabled,selectedElements,dragState,clipboard) - Removed UI-only methods
- Now purely command-driven core logic
- All operations go through commands + history
- Only 315 lines (was 1800+)
- Focus: data management, persistence, queries
- Removed all UI state (
-
Refactored Timeline Store
- Now ONLY UI state (104 lines)
selectedElements+ selection methodssnappingEnabled+ togglerippleEditingEnabled+ toggleclipboard+ setter- Removed all core logic
🔲 TODO - HIGH PRIORITY
-
Move dragState from Store to Timeline Component
- Currently in Zustand (wrong place)
- Move to
Timelinecomponent local state - Pass down via props to
TimelineTrackandTimelineElement - Remove from timeline-store.ts
- Eliminates unnecessary global state
-
Update All Component Imports
- Remove
dragState,startDrag,updateDragTime,endDragfrom all components reading from store - Update to receive via props instead
- Components affected:
timeline-track.tsx(producer)timeline-element.tsx(consumer)index.tsx(consumer - snap indicator)
- Remove
-
Update Store Action Calls
- Components calling store methods now need to call
editor.timeline.*instead - Examples:
updateElementStartTime()→editor.timeline.updateElementStartTime()deleteSelected()→editor.timeline.deleteElements()copySelected()stays in store (UI orchestration)pasteAtTime()→editor.timeline.pasteAtTime()after store manages clipboard
- Components calling store methods now need to call
-
Create useDragState Hook (Optional Later)
- Extract drag logic into custom hook
- Would contain: drag state, handlers, listeners
- Keep in Timeline for now (simpler), extract later if needed
🔲 TODO - MEDIUM PRIORITY
-
Implement Remaining TimelineManager Methods
checkElementOverlap()— utility logicfindOrCreateTrack()— utilityloadProjectTimeline()— persistencesaveProjectTimeline()— persistenceclearTimeline()— core operationgetSortedTracks()— already in manager but not implemented
-
Wire Up Commands to UI
- Update all action calls to create commands + execute
- E.g., when user clicks "add track":
const trackId = editor.timeline.addTrack({ type: "media" }); - This internally creates
AddTrackCommand, executes it through history
🔲 TODO - POLISH
-
Remove Duplicate Methods
copySelectedexists in both store (UI) and old timeline-store (removed)- Store version should orchestrate: copy → call
editor.timeline.pasteAtTime()
-
Add Type Safety
- Ensure all commands properly typed
- Ensure all manager methods properly typed
- Fix any remaining linter errors
Architecture Summary
EditorCore (singleton)
├── history: HistoryManager
├── timeline: TimelineManager (pure logic)
│ ├── _tracks (data)
│ ├── Command execution
│ └── Persistence
├── project: ProjectManager
├── media: MediaManager
├── scene: SceneManager
└── playback: PlaybackManager
Timeline Component (UI)
├── dragState (local)
├── TimelineTrackContent
│ ├── dragState (via props)
│ └── TimelineElement
│ └── dragState (via props)
TimelineStore (Zustand - UI state)
├── selectedElements
├── snappingEnabled
├── rippleEditingEnabled
└── clipboard
Key Principle: Core logic in managers + commands. UI state in store. Ephemeral interaction state in components (dragState).