diff --git a/app/src/components/StoriesTab/StoryTrackEditor.tsx b/app/src/components/StoriesTab/StoryTrackEditor.tsx index e27e4706..15d98c6a 100644 --- a/app/src/components/StoriesTab/StoryTrackEditor.tsx +++ b/app/src/components/StoriesTab/StoryTrackEditor.tsx @@ -139,16 +139,32 @@ export function StoryTrackEditor({ storyId, items }: StoryTrackEditorProps) { // Playback state const isPlaying = useStoryStore((state) => state.isPlaying); const currentTimeMs = useStoryStore((state) => state.currentTimeMs); - const storeTotalDurationMs = useStoryStore((state) => state.totalDurationMs); const playbackStoryId = useStoryStore((state) => state.playbackStoryId); const play = useStoryStore((state) => state.play); const pause = useStoryStore((state) => state.pause); const stop = useStoryStore((state) => state.stop); const seek = useStoryStore((state) => state.seek); + const setActiveStory = useStoryStore((state) => state.setActiveStory); const isActiveStory = playbackStoryId === storyId; const isCurrentlyPlaying = isPlaying && isActiveStory; + // Auto-activate this story when the editor is shown so playhead is visible + useEffect(() => { + if (items.length > 0 && !isActiveStory) { + const totalDuration = Math.max( + ...items.map((item) => { + const trimStart = item.trim_start_ms || 0; + const trimEnd = item.trim_end_ms || 0; + const effectiveDuration = (item.duration * 1000) - trimStart - trimEnd; + return item.start_time_ms + effectiveDuration; + }), + 0 + ); + setActiveStory(storyId, items, totalDuration); + } + }, [storyId, items, isActiveStory, setActiveStory]); + // Sort items by start time for play const sortedItems = useMemo(() => { return [...items].sort((a, b) => a.start_time_ms - b.start_time_ms); @@ -656,11 +672,11 @@ export function StoryTrackEditor({ storyId, items }: StoryTrackEditorProps) { )} - - {formatTime(isActiveStory ? currentTimeMs : 0)} / {formatTime(isActiveStory ? storeTotalDurationMs : 0)} + {formatTime(currentTimeMs)} / {formatTime(totalDurationMs)} @@ -875,15 +891,13 @@ export function StoryTrackEditor({ storyId, items }: StoryTrackEditorProps) { ); })} - {/* Playhead */} - {isActiveStory && ( -
-
-
- )} + {/* Playhead - always visible */} +
+
+
diff --git a/app/src/stores/storyStore.ts b/app/src/stores/storyStore.ts index ae46368e..c20f6254 100644 --- a/app/src/stores/storyStore.ts +++ b/app/src/stores/storyStore.ts @@ -28,6 +28,7 @@ interface StoryPlaybackState { stop: () => void; seek: (timeMs: number) => void; setPlaybackTiming: (contextTime: number, storyTime: number) => void; // Set timing anchors for Web Audio API + setActiveStory: (storyId: string, items: StoryItemDetail[], totalDurationMs: number) => void; // Activate story for seeking without playing } const DEFAULT_TRACK_EDITOR_HEIGHT = 250; @@ -126,4 +127,18 @@ export const useStoryStore = create((set, get) => ({ playbackStartStoryTime: storyTime, }); }, + + setActiveStory: (storyId, items, totalDurationMs) => { + const currentState = get(); + // Only update if switching to a different story + if (currentState.playbackStoryId !== storyId) { + set({ + playbackStoryId: storyId, + playbackItems: items, + totalDurationMs, + currentTimeMs: 0, + isPlaying: false, + }); + } + }, }));