From 5190fb447447bdfce55b9b359086796c3b0b3456 Mon Sep 17 00:00:00 2001 From: Yiannis Christodoulou Date: Sun, 9 Nov 2025 22:42:14 +0200 Subject: [PATCH] fix: First chapter is not saved, if not given a name, although indicating it is saved (151) --- .../src/components/TimelineControls.tsx | 42 ++++++++++++++++--- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/frontend-tools/chapters-editor/client/src/components/TimelineControls.tsx b/frontend-tools/chapters-editor/client/src/components/TimelineControls.tsx index 1f609713..18263066 100644 --- a/frontend-tools/chapters-editor/client/src/components/TimelineControls.tsx +++ b/frontend-tools/chapters-editor/client/src/components/TimelineControls.tsx @@ -26,6 +26,18 @@ const mediaPageLinkStyles = { }, } as const; +// Helper function to parse time string (HH:MM:SS.mmm) to seconds +const parseTimeToSeconds = (timeString: string): number => { + const parts = timeString.split(':'); + if (parts.length !== 3) return 0; + + const hours = parseInt(parts[0], 10) || 0; + const minutes = parseInt(parts[1], 10) || 0; + const seconds = parseFloat(parts[2]) || 0; + + return hours * 3600 + minutes * 60 + seconds; +}; + interface TimelineControlsProps { currentTime: number; duration: number; @@ -191,7 +203,17 @@ const TimelineControls = ({ setIsAutoSaving(true); // Format segments data for API request - use ref to get latest segments and sort by start time + // ONLY save chapters that have custom titles - filter out chapters without titles or with default names const chapters = clipSegmentsRef.current + .filter((segment) => { + // Filter out empty titles + if (!segment.chapterTitle || !segment.chapterTitle.trim()) { + return false; + } + // Filter out default chapter names like "Chapter 1", "Chapter 2", etc. + const isDefaultName = /^Chapter \d+$/.test(segment.chapterTitle); + return !isDefaultName; + }) .sort((a, b) => a.startTime - b.startTime) // Sort by start time chronologically .map((chapter) => ({ startTime: formatDetailedTime(chapter.startTime), @@ -199,7 +221,7 @@ const TimelineControls = ({ chapterTitle: chapter.chapterTitle, })); - logger.debug('chapters', chapters); + logger.debug('Filtered chapters (only custom titles):', chapters); const mediaId = (typeof window !== 'undefined' && (window as any).MEDIA_DATA?.mediaId) || null; // For testing, use '1234' if no mediaId is available @@ -207,12 +229,13 @@ const TimelineControls = ({ logger.debug('mediaId', finalMediaId); - if (!finalMediaId || chapters.length === 0) { - logger.debug('No mediaId or segments, skipping auto-save'); + if (!finalMediaId) { + logger.debug('No mediaId, skipping auto-save'); setIsAutoSaving(false); return; } + // Save chapters (empty array if no chapters have titles) logger.debug('Auto-saving segments:', { mediaId: finalMediaId, chapters }); const response = await autoSaveVideo(finalMediaId, { chapters }); @@ -499,11 +522,20 @@ const TimelineControls = ({ try { // Format chapters data for API request - sort by start time first + // ONLY save chapters that have custom titles - filter out chapters without titles or with default names const chapters = clipSegments - .filter((segment) => segment.chapterTitle && segment.chapterTitle.trim()) + .filter((segment) => { + // Filter out empty titles + if (!segment.chapterTitle || !segment.chapterTitle.trim()) { + return false; + } + // Filter out default chapter names like "Chapter 1", "Chapter 2", etc. + const isDefaultName = /^Chapter \d+$/.test(segment.chapterTitle); + return !isDefaultName; + }) .sort((a, b) => a.startTime - b.startTime) // Sort by start time chronologically .map((segment) => ({ - chapterTitle: segment.chapterTitle || `Chapter ${segment.id}`, + chapterTitle: segment.chapterTitle, from: formatDetailedTime(segment.startTime), to: formatDetailedTime(segment.endTime), }));