1+ import debounce from 'just-debounce-it' ;
12import { DOMEvent } from 'maverick.js/std' ;
23
34import { List , type ListReadonlyChangeEvent } from '../../../foundation/list/list' ;
45import { ListSymbol } from '../../../foundation/list/symbols' ;
6+ import type { MediaStorage } from '../../storage' ;
57import { TextTrackSymbol } from './symbols' ;
68import {
79 isTrackCaptionKind ,
@@ -16,29 +18,47 @@ import {
1618export class TextTrackList extends List < TextTrack , TextTrackListEvents > {
1719 private _canLoad = false ;
1820 private _defaults : Record < string , TextTrack | undefined > = { } ;
21+ private _preferredLang : string | null = null ;
1922
2023 /** @internal */
2124 [ TextTrackSymbol . _crossorigin ] ?: ( ) => string | null ;
2225
26+ constructor ( private readonly _storage ?: MediaStorage ) {
27+ super ( ) ;
28+ }
29+
2330 get selected ( ) {
2431 const track = this . _items . find ( ( t ) => t . mode === 'showing' && isTrackCaptionKind ( t ) ) ;
2532 return track ?? null ;
2633 }
2734
35+ get preferredLang ( ) {
36+ return this . _preferredLang ;
37+ }
38+
39+ set preferredLang ( lang : string | null ) {
40+ this . _preferredLang = lang ;
41+ }
42+
2843 add ( init : TextTrackInit | TextTrack , trigger ?: Event ) {
2944 const isTrack = init instanceof TextTrack ,
30- track = isTrack ? init : new TextTrack ( init ) ;
45+ track = isTrack ? init : new TextTrack ( init ) ,
46+ kind = init . kind === 'captions' || init . kind === 'subtitles' ? 'captions' : init . kind ;
3147
32- if ( this . _defaults [ init . kind ] && init . default ) delete init . default ;
48+ if ( this . _defaults [ kind ] && init . default ) delete init . default ;
3349
3450 track . addEventListener ( 'mode-change' , this . _onTrackModeChangeBind ) ;
3551 this [ ListSymbol . _add ] ( track , trigger ) ;
3652 track [ TextTrackSymbol . _crossorigin ] = this [ TextTrackSymbol . _crossorigin ] ;
3753 if ( this . _canLoad ) track [ TextTrackSymbol . _canLoad ] ( ) ;
3854
3955 if ( init . default ) {
40- this . _defaults [ init . kind ] = track ;
41- track . mode = 'showing' ;
56+ this . _defaults [ kind ] = track ;
57+ if ( kind !== 'captions' ) {
58+ track . mode = 'showing' ;
59+ } else {
60+ this . _selectCaptions ( ) ;
61+ }
4262 }
4363
4464 return this ;
@@ -78,10 +98,39 @@ export class TextTrackList extends List<TextTrack, TextTrackListEvents> {
7898 this . _canLoad = true ;
7999 }
80100
101+ private _selectCaptions = debounce ( ( ) => {
102+ if ( this . selected || this . _storage ?. data . captions === false ) return ;
103+
104+ if ( ! this . _preferredLang && this . _storage ) {
105+ this . _preferredLang = this . _storage . data . lang ;
106+ }
107+
108+ const preferredTrack =
109+ this . _preferredLang &&
110+ this . _items . find (
111+ ( track ) => isTrackCaptionKind ( track ) && track . language === this . _preferredLang ,
112+ ) ,
113+ defaultTrack = this . _defaults . captions ;
114+
115+ if ( preferredTrack ) {
116+ preferredTrack . mode = 'showing' ;
117+ } else if ( defaultTrack ) {
118+ if ( defaultTrack ) defaultTrack . mode = 'showing' ;
119+ }
120+
121+ if ( this . _storage ) {
122+ this . _storage . lang = this . _preferredLang ?? defaultTrack ?. language ?? null ;
123+ }
124+ } , 300 ) ;
125+
81126 private _onTrackModeChangeBind = this . _onTrackModeChange . bind ( this ) ;
82127 private _onTrackModeChange ( event : TextTrackModeChangeEvent ) {
83128 const track = event . detail ;
84129
130+ if ( this . _storage && isTrackCaptionKind ( track ) ) {
131+ this . _storage . captions = track . mode === 'showing' ;
132+ }
133+
85134 if ( track . mode === 'showing' ) {
86135 const kinds = isTrackCaptionKind ( track ) ? [ 'captions' , 'subtitles' ] : [ track . kind ] ;
87136 for ( const t of this . _items ) {
0 commit comments