@@ -241,6 +241,7 @@ const slidesSession = createSlidesSessionStore({
241241const slidesState = slidesSession . state ;
242242const pendingSummaryRunsByUrl = new Map < string , RunStart > ( ) ;
243243const pendingSlidesRunsByUrl = new Map < string , { runId : string ; url : string } > ( ) ;
244+ let lastPlannedSlidesRun : RunStart | null = null ;
244245const slidesTextController = createSlidesTextController ( {
245246 getSlides : ( ) => panelState . slides ?. slides ?? null ,
246247 getLengthValue : ( ) => appearanceControls . getLengthValue ( ) ,
@@ -375,24 +376,79 @@ function attachSummaryRun(run: RunStart) {
375376 } ;
376377 }
377378 slidesState . pendingRunForPlannedSlides = runRequestsSlides ? run : null ;
378- if ( ! panelState . summaryMarkdown ?. trim ( ) ) {
379- renderMarkdownDisplay ( ) ;
380- }
379+ lastPlannedSlidesRun = runRequestsSlides ? run : null ;
381380 if ( runRequestsSlides ) {
382381 startSlidesStream ( run ) ;
382+ seedPlannedSlidesForRun ( run ) ;
383+ }
384+ if ( ! panelState . summaryMarkdown ?. trim ( ) ) {
385+ renderMarkdownDisplay ( ) ;
383386 }
384387 void streamController . start ( run ) ;
385388}
386389
387390function maybeSeedPlannedSlidesForPendingRun ( ) {
388- if ( ! slidesState . pendingRunForPlannedSlides ) return false ;
389- if ( seedPlannedSlidesForRun ( slidesState . pendingRunForPlannedSlides ) ) {
390- slidesState . pendingRunForPlannedSlides = null ;
391+ const pendingRun = getPlannedSlidesRunForReseed ( ) ;
392+ if ( ! pendingRun ) return false ;
393+ if ( ! isCurrentPlannedSlidesRun ( pendingRun ) ) return false ;
394+ if ( seedPlannedSlidesForRun ( pendingRun ) ) {
395+ if ( plannedSlidesHaveUsableTimingOrImages ( pendingRun ) ) {
396+ clearPlannedSlidesRunForReseed ( ) ;
397+ }
391398 return true ;
392399 }
393400 return false ;
394401}
395402
403+ function getPlannedSlidesRunForReseed ( ) {
404+ if ( slidesState . pendingRunForPlannedSlides ) return slidesState . pendingRunForPlannedSlides ;
405+ if ( ! lastPlannedSlidesRun ) return null ;
406+ return panelState . runId === lastPlannedSlidesRun . id ||
407+ panelState . slidesRunId === lastPlannedSlidesRun . id
408+ ? lastPlannedSlidesRun
409+ : null ;
410+ }
411+
412+ function clearPlannedSlidesRunForReseed ( ) {
413+ slidesState . pendingRunForPlannedSlides = null ;
414+ lastPlannedSlidesRun = null ;
415+ }
416+
417+ function plannedSlidesHaveUsableTimingOrImages ( run : RunStart ) {
418+ if ( currentRunHasResolvedSlideImages ( run ) ) return true ;
419+ const sourceId = getPlannedSlidesSourceId ( run ) ;
420+ if ( ! panelState . slides || panelState . slides . sourceId !== sourceId ) return false ;
421+ return panelState . slides . slides . some (
422+ ( slide ) => Number . isFinite ( slide . timestamp ) || ( slide . imageUrl ?? "" ) . trim ( ) . length > 0 ,
423+ ) ;
424+ }
425+
426+ function currentRunHasResolvedSlideImages ( run : RunStart ) {
427+ if ( ! panelState . slides ) return false ;
428+ const hasResolvedImages = panelState . slides . slides . some (
429+ ( slide ) => ( slide . imageUrl ?? "" ) . trim ( ) . length > 0 ,
430+ ) ;
431+ if ( ! hasResolvedImages ) return false ;
432+ if ( panelState . runId === run . id || panelState . slidesRunId === run . id ) return true ;
433+ const sourceUrl = panelState . slides . sourceUrl || panelState . currentSource ?. url || activeTabUrl ;
434+ return sourceUrl ? panelUrlsMatch ( run . url , sourceUrl ) : false ;
435+ }
436+
437+ function seedPlannedSlidesForPendingRunAndConsumeWhenReady ( ) {
438+ const pendingRun = getPlannedSlidesRunForReseed ( ) ;
439+ if ( ! pendingRun ) return ;
440+ if ( ! isCurrentPlannedSlidesRun ( pendingRun ) ) return ;
441+ if ( seedPlannedSlidesForRun ( pendingRun ) && plannedSlidesHaveUsableTimingOrImages ( pendingRun ) ) {
442+ clearPlannedSlidesRunForReseed ( ) ;
443+ }
444+ }
445+
446+ function isCurrentPlannedSlidesRun ( run : RunStart ) {
447+ const currentUrl =
448+ panelState . currentSource ?. url ?? activeTabUrl ?? panelState . ui ?. tab . url ?? null ;
449+ return currentUrl ? panelUrlsMatch ( run . url , currentUrl ) : false ;
450+ }
451+
396452function showAutomationNotice ( {
397453 title,
398454 message,
@@ -1168,10 +1224,7 @@ const summaryStreamRuntime = createSummaryStreamRuntime({
11681224 panelCacheController . scheduleSync ( ) ;
11691225 } ,
11701226 seedPlannedSlidesForPendingRun : ( ) => {
1171- if ( slidesState . pendingRunForPlannedSlides ) {
1172- seedPlannedSlidesForRun ( slidesState . pendingRunForPlannedSlides ) ;
1173- slidesState . pendingRunForPlannedSlides = null ;
1174- }
1227+ seedPlannedSlidesForPendingRunAndConsumeWhenReady ( ) ;
11751228 } ,
11761229 setSlidesBusy,
11771230 setPhase,
@@ -1478,9 +1531,16 @@ summarizeControlRuntime = createSummarizeControlRuntime({
14781531 } ,
14791532} ) ;
14801533
1534+ function getPlannedSlidesSourceId ( run : RunStart ) {
1535+ const youtubeId = extractYouTubeVideoId ( run . url ) ;
1536+ return youtubeId ? `youtube-${ youtubeId } ` : `planned-${ run . id } ` ;
1537+ }
1538+
14811539function seedPlannedSlidesForRun ( run : RunStart ) {
14821540 const durationSeconds =
14831541 slidesState . summarizeVideoDurationSeconds ?? panelState . ui ?. stats . videoDurationSeconds ?? null ;
1542+ const hasDuration =
1543+ typeof durationSeconds === "number" && Number . isFinite ( durationSeconds ) && durationSeconds > 0 ;
14841544 if (
14851545 ! shouldSeedPlannedSlidesForRun ( {
14861546 durationSeconds,
@@ -1508,24 +1568,37 @@ function seedPlannedSlidesForRun(run: RunStart) {
15081568 ? 120
15091569 : 300 ;
15101570
1511- const target = Math . max ( 3 , Math . round ( durationSeconds / chunkSeconds ) ) ;
1571+ const defaultCount = 6 ;
1572+ const target = hasDuration
1573+ ? Math . max ( 3 , Math . round ( durationSeconds / chunkSeconds ) )
1574+ : defaultCount ;
15121575 const count = Math . max ( 3 , Math . min ( 80 , target ) ) ;
15131576
15141577 const youtubeId = extractYouTubeVideoId ( run . url ) ;
1515- const sourceId = youtubeId ? `youtube- ${ youtubeId } ` : `planned- ${ run . id } ` ;
1578+ const sourceId = getPlannedSlidesSourceId ( run ) ;
15161579 const sourceKind = youtubeId ? "youtube" : "direct" ;
1517-
1518- if (
1519- panelState . slides &&
1520- panelState . slides . sourceId === sourceId &&
1521- panelState . slides . slides . length > 0
1522- ) {
1580+ if ( currentRunHasResolvedSlideImages ( run ) ) {
15231581 return true ;
15241582 }
15251583
1584+ const existingSlides = panelState . slides ?. sourceId === sourceId ? panelState . slides : null ;
1585+ if ( existingSlides && existingSlides . slides . length > 0 ) {
1586+ const hasResolvedImages = existingSlides . slides . some (
1587+ ( slide ) => ( slide . imageUrl ?? "" ) . trim ( ) . length > 0 ,
1588+ ) ;
1589+ const hasUsableTimestamps = existingSlides . slides . some ( ( slide ) =>
1590+ Number . isFinite ( slide . timestamp ) ,
1591+ ) ;
1592+ if ( hasResolvedImages || ! hasDuration || hasUsableTimestamps ) {
1593+ return true ;
1594+ }
1595+ }
1596+
15261597 const slides = Array . from ( { length : count } , ( _ , i ) => {
15271598 const ratio = count <= 1 ? 0 : i / Math . max ( 1 , count - 1 ) ;
1528- const timestamp = Math . max ( 0 , Math . min ( durationSeconds - 0.1 , ratio * durationSeconds ) ) ;
1599+ const timestamp = hasDuration
1600+ ? Math . max ( 0 , Math . min ( durationSeconds - 0.1 , ratio * durationSeconds ) )
1601+ : Number . NaN ;
15291602 const index = i + 1 ;
15301603 return { index, timestamp, imageUrl : "" } ;
15311604 } ) ;
0 commit comments