From ebadea0d46bf4a5f6053148056870cf90b8a5951 Mon Sep 17 00:00:00 2001 From: Miguel Angel Simon Sierra Date: Mon, 20 Jul 2026 21:32:03 +0200 Subject: [PATCH] refactor(studio): extract live timeline clock --- packages/studio/src/player/store/liveTime.ts | 11 +++++++++++ packages/studio/src/player/store/playerStore.ts | 14 +------------- 2 files changed, 12 insertions(+), 13 deletions(-) create mode 100644 packages/studio/src/player/store/liveTime.ts diff --git a/packages/studio/src/player/store/liveTime.ts b/packages/studio/src/player/store/liveTime.ts new file mode 100644 index 0000000000..8025986f93 --- /dev/null +++ b/packages/studio/src/player/store/liveTime.ts @@ -0,0 +1,11 @@ +// Lightweight pub-sub avoids React re-renders on every playback frame. +type TimeListener = (time: number) => void; +const timeListeners = new Set(); + +export const liveTime = { + notify: (time: number) => timeListeners.forEach((listener) => listener(time)), + subscribe: (listener: TimeListener) => { + timeListeners.add(listener); + return () => timeListeners.delete(listener); + }, +}; diff --git a/packages/studio/src/player/store/playerStore.ts b/packages/studio/src/player/store/playerStore.ts index ff5400c6c8..510af7792d 100644 --- a/packages/studio/src/player/store/playerStore.ts +++ b/packages/studio/src/player/store/playerStore.ts @@ -7,6 +7,7 @@ import { computePinnedZoomPercent } from "../components/timelineZoom"; import { createKeyframeSlice, type KeyframeSlice } from "./keyframeSlice"; export type { KeyframeCacheEntry } from "./keyframeSlice"; +export { liveTime } from "./liveTime"; export interface TimelineElement { id: string; @@ -277,19 +278,6 @@ interface BeatHistoryEntry { label: string; } -// Lightweight pub-sub for current time during playback. -// Bypasses React state so the RAF loop can update the playhead/time display -// without triggering re-renders on every frame. -type TimeListener = (time: number) => void; -const _timeListeners = new Set(); -export const liveTime = { - notify: (t: number) => _timeListeners.forEach((cb) => cb(t)), - subscribe: (cb: TimeListener) => { - _timeListeners.add(cb); - return () => _timeListeners.delete(cb); - }, -}; - function createTimelineResetState() { return { isPlaying: false,