11import * as React from 'react' ;
22
33import { effect , type StopEffect } from 'maverick.js' ;
4- import { useReactContext } from 'maverick.js/react' ;
4+ import { useReactContext , useSignal } from 'maverick.js/react' ;
55import type { VTTCue } from 'media-captions' ;
66import { formatSpokenTime , formatTime , mediaContext } from 'vidstack' ;
77
@@ -15,50 +15,58 @@ import { useTextCues } from '../use-text-cues';
1515export function useChapterOptions ( ) : ChapterOptions {
1616 const media = useReactContext ( mediaContext ) ! ,
1717 track = useActiveTextTrack ( 'chapters' ) ,
18- cues = useTextCues ( track ) ;
18+ cues = useTextCues ( track ) ,
19+ $startTime = useSignal ( media . $state . clipStartTime ) ,
20+ $endTime = useSignal ( media . $state . clipEndTime ) || Infinity ;
1921
2022 useActiveTextCues ( track ) ;
2123
2224 return React . useMemo ( ( ) => {
2325 const options = track
24- ? cues . map < ChapterOption > ( ( cue , i ) => {
25- let currentRef : HTMLElement | null = null ,
26- stopProgressEffect : StopEffect | undefined ;
27- return {
28- cue,
29- label : cue . text ,
30- value : i + '' ,
31- startTimeText : formatTime ( cue . startTime , false ) ,
32- durationText : formatSpokenTime ( cue . endTime - cue . startTime ) ,
33- get selected ( ) {
34- return cue === track . activeCues [ 0 ] ;
35- } ,
36- setProgressVar ( ref ) {
37- if ( ! ref || cue !== track . activeCues [ 0 ] ) {
38- stopProgressEffect ?.( ) ;
39- stopProgressEffect = undefined ;
40- ref ?. style . setProperty ( '--progress' , '0%' ) ;
41- currentRef = null ;
42- return ;
43- }
26+ ? cues
27+ . filter ( ( cue ) => cue . startTime <= $endTime && cue . endTime >= $startTime )
28+ . map < ChapterOption > ( ( cue , i ) => {
29+ let currentRef : HTMLElement | null = null ,
30+ stopProgressEffect : StopEffect | undefined ;
31+ return {
32+ cue,
33+ label : cue . text ,
34+ value : i + '' ,
35+ startTimeText : formatTime ( Math . max ( 0 , cue . startTime - $startTime ) , false ) ,
36+ durationText : formatSpokenTime (
37+ Math . min ( $endTime , cue . endTime ) - Math . max ( $startTime , cue . startTime ) ,
38+ ) ,
39+ get selected ( ) {
40+ return cue === track . activeCues [ 0 ] ;
41+ } ,
42+ setProgressVar ( ref ) {
43+ if ( ! ref || cue !== track . activeCues [ 0 ] ) {
44+ stopProgressEffect ?.( ) ;
45+ stopProgressEffect = undefined ;
46+ ref ?. style . setProperty ( '--progress' , '0%' ) ;
47+ currentRef = null ;
48+ return ;
49+ }
50+
51+ if ( currentRef === ref ) return ;
52+ currentRef = ref ;
4453
45- if ( currentRef === ref ) return ;
46- currentRef = ref ;
54+ stopProgressEffect ?.( ) ;
55+ stopProgressEffect = effect ( ( ) => {
56+ const { realCurrentTime } = media . $state ,
57+ time = realCurrentTime ( ) ,
58+ cueStartTime = Math . max ( $startTime , cue . startTime ) ,
59+ duration = Math . min ( $endTime , cue . endTime ) - cueStartTime ,
60+ progress = ( Math . max ( 0 , time - cueStartTime ) / duration ) * 100 ;
4761
48- stopProgressEffect ?.( ) ;
49- stopProgressEffect = effect ( ( ) => {
50- const { currentTime } = media . $state ,
51- time = currentTime ( ) ,
52- progress =
53- Math . min ( ( time - cue . startTime ) / ( cue . endTime - cue . startTime ) , 1 ) * 100 ;
54- ref . style . setProperty ( '--progress' , progress . toFixed ( 3 ) + '%' ) ;
55- } ) ;
56- } ,
57- select ( trigger ) {
58- media . remote . seek ( cue . startTime , trigger ) ;
59- } ,
60- } ;
61- } )
62+ ref . style . setProperty ( '--progress' , progress . toFixed ( 3 ) + '%' ) ;
63+ } ) ;
64+ } ,
65+ select ( trigger ) {
66+ media . remote . seek ( cue . startTime - $startTime , trigger ) ;
67+ } ,
68+ } ;
69+ } )
6270 : [ ] ;
6371
6472 Object . defineProperty ( options , 'selectedValue' , {
@@ -69,7 +77,7 @@ export function useChapterOptions(): ChapterOptions {
6977 } ) ;
7078
7179 return options as ChapterOptions ;
72- } , [ cues ] ) ;
80+ } , [ cues , $startTime , $endTime ] ) ;
7381}
7482
7583export type ChapterOptions = ChapterOption [ ] & {
0 commit comments