diff options
Diffstat (limited to 'apps/web/src/core')
| -rw-r--r-- | apps/web/src/core/managers/audio-manager.ts | 23 | ||||
| -rw-r--r-- | apps/web/src/core/managers/playback-manager.ts | 44 | ||||
| -rw-r--r-- | apps/web/src/core/managers/timeline-manager.ts | 12 |
3 files changed, 36 insertions, 43 deletions
diff --git a/apps/web/src/core/managers/audio-manager.ts b/apps/web/src/core/managers/audio-manager.ts index 545565be..d0716aad 100644 --- a/apps/web/src/core/managers/audio-manager.ts +++ b/apps/web/src/core/managers/audio-manager.ts @@ -1,9 +1,6 @@ import type { EditorCore } from "@/core"; import { TICKS_PER_SECOND } from "@/wasm"; -import { - clampRetimeRate, - shouldMaintainPitch, -} from "@/retime/rate"; +import { clampRetimeRate, shouldMaintainPitch } from "@/retime/rate"; import type { AudioClipSource } from "@/media/audio"; import { createAudioContext, collectAudioClips } from "@/media/audio"; import { @@ -56,10 +53,8 @@ export class AudioManager { this.editor.playback.subscribe(this.handlePlaybackChange), this.editor.timeline.subscribe(this.handleTimelineChange), this.editor.media.subscribe(this.handleTimelineChange), + this.editor.playback.onSeek(this.handleSeek), ); - if (typeof window !== "undefined") { - window.addEventListener("playback-seek", this.handleSeek); - } } dispose(): void { @@ -68,9 +63,6 @@ export class AudioManager { unsub(); } this.unsubscribers = []; - if (typeof window !== "undefined") { - window.removeEventListener("playback-seek", this.handleSeek); - } this.disposeSinks(); this.preparedClipBuffers.clear(); this.decodedBuffers.clear(); @@ -102,17 +94,14 @@ export class AudioManager { } }; - private handleSeek = (event: Event): void => { - const detail = (event as CustomEvent<{ time: number }>).detail; - if (!detail) return; - + private handleSeek = (time: number): void => { if (this.editor.playback.getIsScrubbing()) { this.stopPlayback(); return; } if (this.editor.playback.getIsPlaying()) { - void this.startPlayback({ time: detail.time / TICKS_PER_SECOND }); + void this.startPlayback({ time: time / TICKS_PER_SECOND }); return; } @@ -126,7 +115,9 @@ export class AudioManager { if (!this.editor.playback.getIsPlaying()) return; - void this.startPlayback({ time: this.editor.playback.getCurrentTime() / TICKS_PER_SECOND }); + void this.startPlayback({ + time: this.editor.playback.getCurrentTime() / TICKS_PER_SECOND, + }); }; private ensureAudioContext(): AudioContext | null { diff --git a/apps/web/src/core/managers/playback-manager.ts b/apps/web/src/core/managers/playback-manager.ts index 1ea09826..a243dc19 100644 --- a/apps/web/src/core/managers/playback-manager.ts +++ b/apps/web/src/core/managers/playback-manager.ts @@ -10,6 +10,8 @@ export class PlaybackManager { private previousVolume = 1; private isScrubbing = false; private listeners = new Set<() => void>(); + private updateListeners = new Set<(time: number) => void>(); + private seekListeners = new Set<(time: number) => void>(); private playbackTimer: number | null = null; private playbackStartWallTime = 0; private playbackStartTime = 0; @@ -67,7 +69,7 @@ export class PlaybackManager { this.playbackStartTime = this.currentTime; } this.notify(); - this.dispatchSeekEvent(this.currentTime); + this.notifySeek(this.currentTime); } setVolume({ volume }: { volume: number }): void { @@ -133,6 +135,16 @@ export class PlaybackManager { return () => this.listeners.delete(listener); } + onUpdate(listener: (time: number) => void): () => void { + this.updateListeners.add(listener); + return () => this.updateListeners.delete(listener); + } + + onSeek(listener: (time: number) => void): () => void { + this.seekListeners.add(listener); + return () => this.seekListeners.delete(listener); + } + private reconcileTimelineScope(): void { const maxTime = this.editor.timeline.getTotalDuration(); const nextTime = this.clampTimeToTimeline(this.currentTime); @@ -152,7 +164,7 @@ export class PlaybackManager { this.notify(); if (timeChanged) { - this.dispatchSeekEvent(this.currentTime); + this.notifySeek(this.currentTime); } } @@ -196,12 +208,12 @@ export class PlaybackManager { this.pause(); this.currentTime = maxTime; this.notify(); - this.dispatchSeekEvent(maxTime); + this.notifySeek(maxTime); return; } this.currentTime = newTime; - this.dispatchUpdateEvent(newTime); + this.notifyUpdate(newTime); this.playbackTimer = requestAnimationFrame(this.updateTime); }; @@ -210,27 +222,15 @@ export class PlaybackManager { return Math.max(0, Math.min(maxTime, time)); } - private dispatchSeekEvent(time: number): void { - if (typeof window === "undefined") { - return; + private notifySeek(time: number): void { + for (const fn of this.seekListeners) { + fn(time); } - - window.dispatchEvent( - new CustomEvent("playback-seek", { - detail: { time }, - }), - ); } - private dispatchUpdateEvent(time: number): void { - if (typeof window === "undefined") { - return; + private notifyUpdate(time: number): void { + for (const fn of this.updateListeners) { + fn(time); } - - window.dispatchEvent( - new CustomEvent("playback-update", { - detail: { time }, - }), - ); } } diff --git a/apps/web/src/core/managers/timeline-manager.ts b/apps/web/src/core/managers/timeline-manager.ts index dbc3332b..6f54c5aa 100644 --- a/apps/web/src/core/managers/timeline-manager.ts +++ b/apps/web/src/core/managers/timeline-manager.ts @@ -9,6 +9,7 @@ import type { RetimeConfig, } from "@/timeline"; import { calculateTotalDuration } from "@/timeline"; +import { TimelineDragSource } from "@/timeline/drag-source"; import { findTrackInSceneTracks } from "@/timeline/track-element-update"; import { canElementBeHidden, @@ -67,6 +68,7 @@ export class TimelineManager { private listeners = new Set<() => void>(); private previewOverlay = new Map<string, Partial<TimelineElement>>(); private previewTracks: SceneTracks | null = null; + public readonly dragSource = new TimelineDragSource(); constructor(private editor: EditorCore) {} @@ -706,11 +708,11 @@ export class TimelineManager { previewElements({ updates, }: { - updates: Array<{ - trackId: string; - elementId: string; - updates: Partial<TimelineElement>; - }>; + updates: readonly { + readonly trackId: string; + readonly elementId: string; + readonly updates: Partial<TimelineElement>; + }[]; }): void { let changedOverlayCount = 0; for (const { elementId, updates: elementUpdates } of updates) { |
