vidply 1.2.1 → 1.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -2
- package/dist/dev/{vidply.AudioDescriptionManager-6RFVF27Z.js → vidply.AudioDescriptionManager-JYYLK5KB.js} +6 -6
- package/dist/dev/{vidply.CaptionStyleMenu-R2SCQ6VP.js → vidply.CaptionStyleMenu-47RCKQF5.js} +4 -4
- package/dist/dev/{vidply.DASHRenderer-EOVEW73H.js → vidply.DASHRenderer-VEJ4HDHO.js} +3 -3
- package/dist/dev/{vidply.FloatingPlayerManager-V5XQWS75.js → vidply.FloatingPlayerManager-C2UVRPZY.js} +5 -5
- package/dist/dev/{vidply.HLSRenderer-ZBEFVH5W.js → vidply.HLSRenderer-ZVBK2TNQ.js} +4 -4
- package/dist/dev/vidply.HTML5Renderer-HLRQUOCU.js +12 -0
- package/dist/dev/{vidply.SignLanguageManager-7IAJOVF6.js → vidply.SignLanguageManager-FLUCBW5H.js} +8 -8
- package/dist/dev/{vidply.SoundCloudRenderer-OA7QQYGN.js → vidply.SoundCloudRenderer-MGMAJ7NK.js} +3 -3
- package/dist/dev/{vidply.TranscriptManager-BPM3T23L.js → vidply.TranscriptManager-Y2RYXHJW.js} +10 -10
- package/dist/dev/{vidply.VimeoRenderer-BRHFYPNJ.js → vidply.VimeoRenderer-RQFQD7OE.js} +3 -3
- package/dist/dev/{vidply.YouTubeRenderer-HRTN4EJ5.js → vidply.YouTubeRenderer-EU2BARZF.js} +3 -3
- package/dist/dev/{vidply.chunk-UHMVDBDB.js → vidply.chunk-6LYZYI5G.js} +3 -3
- package/dist/dev/{vidply.chunk-W5BR65JY.js → vidply.chunk-A4ESEOQ2.js} +6 -6
- package/dist/dev/{vidply.chunk-XAK3DPTO.js → vidply.chunk-CGYIED2I.js} +2 -2
- package/dist/dev/{vidply.chunk-YVCYQZJI.js → vidply.chunk-HZ7UOKOU.js} +3 -3
- package/dist/dev/{vidply.chunk-NSMAZCMB.js → vidply.chunk-I6EDRYGJ.js} +33 -6
- package/dist/dev/{vidply.chunk-NSMAZCMB.js.map → vidply.chunk-I6EDRYGJ.js.map} +2 -2
- package/dist/dev/{vidply.chunk-LDVFAFGC.js → vidply.chunk-JKMQGLCJ.js} +5 -5
- package/dist/dev/{vidply.chunk-HOYEMJSD.js → vidply.chunk-JZNZX32Z.js} +2 -2
- package/dist/dev/{vidply.chunk-JAKZNGOR.js → vidply.chunk-P25MRJ6O.js} +2 -2
- package/dist/dev/{vidply.chunk-5IK3IC5V.js → vidply.chunk-PRFNESYA.js} +2 -2
- package/dist/dev/{vidply.chunk-RQG3MA7W.js → vidply.chunk-UI3RYCVF.js} +4 -3
- package/dist/dev/{vidply.chunk-RQG3MA7W.js.map → vidply.chunk-UI3RYCVF.js.map} +2 -2
- package/dist/dev/{vidply.chunk-C55OBT5H.js → vidply.chunk-UNFGMABP.js} +2 -2
- package/dist/dev/{vidply.de-5W5LBFSJ.js → vidply.de-VAUVSQXC.js} +29 -2
- package/dist/dev/{vidply.de-5W5LBFSJ.js.map → vidply.de-VAUVSQXC.js.map} +2 -2
- package/dist/dev/{vidply.es-SHDAT6L6.js → vidply.es-G65HFWO6.js} +29 -2
- package/dist/dev/{vidply.es-SHDAT6L6.js.map → vidply.es-G65HFWO6.js.map} +2 -2
- package/dist/dev/vidply.esm.js +594 -20
- package/dist/dev/vidply.esm.js.map +3 -3
- package/dist/dev/{vidply.fr-2JANOMNB.js → vidply.fr-MJNOZELM.js} +29 -2
- package/dist/dev/{vidply.fr-2JANOMNB.js.map → vidply.fr-MJNOZELM.js.map} +2 -2
- package/dist/dev/{vidply.ja-WWMSTEJH.js → vidply.ja-INMDHIYJ.js} +29 -2
- package/dist/dev/{vidply.ja-WWMSTEJH.js.map → vidply.ja-INMDHIYJ.js.map} +2 -2
- package/dist/legacy/vidply.js +718 -3
- package/dist/legacy/vidply.js.map +3 -3
- package/dist/legacy/vidply.min.js +2 -2
- package/dist/legacy/vidply.min.meta.json +72 -19
- package/dist/prod/{vidply.AudioDescriptionManager-YTDVDQBO.min.js → vidply.AudioDescriptionManager-EKWUNOPE.min.js} +2 -2
- package/dist/prod/{vidply.CaptionStyleMenu-2AFF3HF2.min.js → vidply.CaptionStyleMenu-JTWSNHRQ.min.js} +2 -2
- package/dist/prod/{vidply.DASHRenderer-URDOTOKS.min.js → vidply.DASHRenderer-CIDAHFWM.min.js} +2 -2
- package/dist/prod/{vidply.FloatingPlayerManager-QUBFK7CQ.min.js → vidply.FloatingPlayerManager-VZXHPCPM.min.js} +2 -2
- package/dist/prod/{vidply.HLSRenderer-46KNUVAB.min.js → vidply.HLSRenderer-Q6EFYKID.min.js} +2 -2
- package/dist/prod/vidply.HTML5Renderer-XRDJUTOO.min.js +6 -0
- package/dist/prod/{vidply.SignLanguageManager-H4C36EVL.min.js → vidply.SignLanguageManager-JUOSA5AM.min.js} +2 -2
- package/dist/prod/{vidply.SoundCloudRenderer-OYSWMW7D.min.js → vidply.SoundCloudRenderer-7ODD46PO.min.js} +2 -2
- package/dist/prod/{vidply.TranscriptManager-BA3DAS63.min.js → vidply.TranscriptManager-4B2QKYGQ.min.js} +2 -2
- package/dist/prod/{vidply.VimeoRenderer-NF3COTHU.min.js → vidply.VimeoRenderer-MR3UYLY7.min.js} +2 -2
- package/dist/prod/{vidply.YouTubeRenderer-UCQKYIJ4.min.js → vidply.YouTubeRenderer-ITRTC7NR.min.js} +2 -2
- package/dist/prod/{vidply.chunk-7S5AFTST.min.js → vidply.chunk-3EEDXU4T.min.js} +2 -2
- package/dist/prod/{vidply.chunk-EUOA2DJK.min.js → vidply.chunk-5HTX5QXW.min.js} +1 -1
- package/dist/prod/{vidply.chunk-JPMAK3NS.min.js → vidply.chunk-6OGHHIYP.min.js} +2 -2
- package/dist/prod/{vidply.chunk-XXUH7ADU.min.js → vidply.chunk-GUPGMFUZ.min.js} +2 -2
- package/dist/prod/{vidply.chunk-M76ABMKB.min.js → vidply.chunk-MWEBITCP.min.js} +1 -1
- package/dist/prod/{vidply.chunk-G6KGXNEW.min.js → vidply.chunk-PL3P3JHR.min.js} +1 -1
- package/dist/prod/{vidply.chunk-6ECBIYVI.min.js → vidply.chunk-QQZGV7TD.min.js} +2 -2
- package/dist/prod/{vidply.chunk-2HNCP64N.min.js → vidply.chunk-U5IRRYG5.min.js} +1 -1
- package/dist/prod/{vidply.chunk-WRVDVD33.min.js → vidply.chunk-VKHV4QHA.min.js} +2 -2
- package/dist/prod/{vidply.chunk-L4O44K63.min.js → vidply.chunk-XA4M574A.min.js} +1 -1
- package/dist/prod/{vidply.chunk-X2FQEQYR.min.js → vidply.chunk-ZPTV4JEP.min.js} +2 -2
- package/dist/prod/{vidply.de-JMCATTKZ.min.js → vidply.de-UZHFCEZU.min.js} +2 -2
- package/dist/prod/{vidply.es-YVG37V7Z.min.js → vidply.es-BOISUV2S.min.js} +2 -2
- package/dist/prod/vidply.esm.min.js +2 -2
- package/dist/prod/{vidply.fr-OGKGN2R4.min.js → vidply.fr-ICSMKPFM.min.js} +2 -2
- package/dist/prod/{vidply.ja-Z6DS7QLS.min.js → vidply.ja-VQ2HKGAY.min.js} +2 -2
- package/dist/vidply.css +56 -0
- package/dist/vidply.esm.min.meta.json +154 -112
- package/dist/vidply.min.css +1 -1
- package/package.json +7 -7
- package/src/controls/ControlBar.ts +32 -0
- package/src/controls/KeyboardHelp.ts +326 -0
- package/src/controls/KeyboardManager.ts +4 -0
- package/src/core/MediaSessionManager.ts +341 -0
- package/src/core/Player.ts +59 -1
- package/src/i18n/languages/de.ts +27 -0
- package/src/i18n/languages/en.ts +27 -0
- package/src/i18n/languages/es.ts +27 -0
- package/src/i18n/languages/fr.ts +27 -0
- package/src/i18n/languages/ja.ts +27 -0
- package/src/icons/Icons.ts +2 -1
- package/src/styles/vidply.css +56 -0
- package/src/types/events.ts +4 -0
- package/src/types/options.ts +14 -0
- package/dist/dev/vidply.HTML5Renderer-P7ICKYU4.js +0 -12
- package/dist/prod/vidply.HTML5Renderer-7TQDMIGY.min.js +0 -6
- /package/dist/dev/{vidply.AudioDescriptionManager-6RFVF27Z.js.map → vidply.AudioDescriptionManager-JYYLK5KB.js.map} +0 -0
- /package/dist/dev/{vidply.CaptionStyleMenu-R2SCQ6VP.js.map → vidply.CaptionStyleMenu-47RCKQF5.js.map} +0 -0
- /package/dist/dev/{vidply.DASHRenderer-EOVEW73H.js.map → vidply.DASHRenderer-VEJ4HDHO.js.map} +0 -0
- /package/dist/dev/{vidply.FloatingPlayerManager-V5XQWS75.js.map → vidply.FloatingPlayerManager-C2UVRPZY.js.map} +0 -0
- /package/dist/dev/{vidply.HLSRenderer-ZBEFVH5W.js.map → vidply.HLSRenderer-ZVBK2TNQ.js.map} +0 -0
- /package/dist/dev/{vidply.HTML5Renderer-P7ICKYU4.js.map → vidply.HTML5Renderer-HLRQUOCU.js.map} +0 -0
- /package/dist/dev/{vidply.SignLanguageManager-7IAJOVF6.js.map → vidply.SignLanguageManager-FLUCBW5H.js.map} +0 -0
- /package/dist/dev/{vidply.SoundCloudRenderer-OA7QQYGN.js.map → vidply.SoundCloudRenderer-MGMAJ7NK.js.map} +0 -0
- /package/dist/dev/{vidply.TranscriptManager-BPM3T23L.js.map → vidply.TranscriptManager-Y2RYXHJW.js.map} +0 -0
- /package/dist/dev/{vidply.VimeoRenderer-BRHFYPNJ.js.map → vidply.VimeoRenderer-RQFQD7OE.js.map} +0 -0
- /package/dist/dev/{vidply.YouTubeRenderer-HRTN4EJ5.js.map → vidply.YouTubeRenderer-EU2BARZF.js.map} +0 -0
- /package/dist/dev/{vidply.chunk-UHMVDBDB.js.map → vidply.chunk-6LYZYI5G.js.map} +0 -0
- /package/dist/dev/{vidply.chunk-W5BR65JY.js.map → vidply.chunk-A4ESEOQ2.js.map} +0 -0
- /package/dist/dev/{vidply.chunk-XAK3DPTO.js.map → vidply.chunk-CGYIED2I.js.map} +0 -0
- /package/dist/dev/{vidply.chunk-YVCYQZJI.js.map → vidply.chunk-HZ7UOKOU.js.map} +0 -0
- /package/dist/dev/{vidply.chunk-LDVFAFGC.js.map → vidply.chunk-JKMQGLCJ.js.map} +0 -0
- /package/dist/dev/{vidply.chunk-HOYEMJSD.js.map → vidply.chunk-JZNZX32Z.js.map} +0 -0
- /package/dist/dev/{vidply.chunk-JAKZNGOR.js.map → vidply.chunk-P25MRJ6O.js.map} +0 -0
- /package/dist/dev/{vidply.chunk-5IK3IC5V.js.map → vidply.chunk-PRFNESYA.js.map} +0 -0
- /package/dist/dev/{vidply.chunk-C55OBT5H.js.map → vidply.chunk-UNFGMABP.js.map} +0 -0
package/dist/legacy/vidply.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* VidPly v1.2.
|
|
2
|
+
* VidPly v1.2.3 - Universal, Accessible Video Player
|
|
3
3
|
* (c) 2026 Matthias Peltzer
|
|
4
4
|
* Released under GPL-2.0-or-later License
|
|
5
5
|
*/
|
|
@@ -428,6 +428,33 @@
|
|
|
428
428
|
reset: "Reset to defaults",
|
|
429
429
|
close: "Close"
|
|
430
430
|
},
|
|
431
|
+
help: {
|
|
432
|
+
title: "Keyboard shortcuts",
|
|
433
|
+
button: "Keyboard shortcuts",
|
|
434
|
+
close: "Close",
|
|
435
|
+
or: "or",
|
|
436
|
+
keys: {
|
|
437
|
+
space: "Space"
|
|
438
|
+
},
|
|
439
|
+
actions: {
|
|
440
|
+
"play-pause": "Play / Pause",
|
|
441
|
+
"seek-backward": "Seek backward",
|
|
442
|
+
"seek-forward": "Seek forward",
|
|
443
|
+
"volume-up": "Volume up",
|
|
444
|
+
"volume-down": "Volume down",
|
|
445
|
+
"mute": "Mute / Unmute",
|
|
446
|
+
"captions": "Toggle captions",
|
|
447
|
+
"caption-style-menu": "Caption styling",
|
|
448
|
+
"speed-down": "Decrease speed",
|
|
449
|
+
"speed-up": "Increase speed",
|
|
450
|
+
"speed-menu": "Playback speed",
|
|
451
|
+
"quality-menu": "Quality",
|
|
452
|
+
"chapters-menu": "Chapters",
|
|
453
|
+
"transcript-toggle": "Toggle transcript",
|
|
454
|
+
"fullscreen": "Toggle fullscreen",
|
|
455
|
+
"help": "Keyboard shortcuts"
|
|
456
|
+
}
|
|
457
|
+
},
|
|
431
458
|
speeds: {
|
|
432
459
|
normal: "Normal"
|
|
433
460
|
},
|
|
@@ -652,6 +679,33 @@
|
|
|
652
679
|
reset: "Zurücksetzen",
|
|
653
680
|
close: "Schließen"
|
|
654
681
|
},
|
|
682
|
+
help: {
|
|
683
|
+
title: "Tastaturkürzel",
|
|
684
|
+
button: "Tastaturkürzel",
|
|
685
|
+
close: "Schließen",
|
|
686
|
+
or: "oder",
|
|
687
|
+
keys: {
|
|
688
|
+
space: "Leertaste"
|
|
689
|
+
},
|
|
690
|
+
actions: {
|
|
691
|
+
"play-pause": "Wiedergabe / Pause",
|
|
692
|
+
"seek-backward": "Zurückspulen",
|
|
693
|
+
"seek-forward": "Vorspulen",
|
|
694
|
+
"volume-up": "Lauter",
|
|
695
|
+
"volume-down": "Leiser",
|
|
696
|
+
"mute": "Stumm / Ton an",
|
|
697
|
+
"captions": "Untertitel umschalten",
|
|
698
|
+
"caption-style-menu": "Untertitel-Stil",
|
|
699
|
+
"speed-down": "Langsamer",
|
|
700
|
+
"speed-up": "Schneller",
|
|
701
|
+
"speed-menu": "Wiedergabegeschwindigkeit",
|
|
702
|
+
"quality-menu": "Qualität",
|
|
703
|
+
"chapters-menu": "Kapitel",
|
|
704
|
+
"transcript-toggle": "Transkript umschalten",
|
|
705
|
+
"fullscreen": "Vollbild umschalten",
|
|
706
|
+
"help": "Tastaturkürzel"
|
|
707
|
+
}
|
|
708
|
+
},
|
|
655
709
|
speeds: {
|
|
656
710
|
normal: "Normal"
|
|
657
711
|
},
|
|
@@ -873,6 +927,33 @@
|
|
|
873
927
|
reset: "Restablecer",
|
|
874
928
|
close: "Cerrar"
|
|
875
929
|
},
|
|
930
|
+
help: {
|
|
931
|
+
title: "Atajos de teclado",
|
|
932
|
+
button: "Atajos de teclado",
|
|
933
|
+
close: "Cerrar",
|
|
934
|
+
or: "o",
|
|
935
|
+
keys: {
|
|
936
|
+
space: "Espacio"
|
|
937
|
+
},
|
|
938
|
+
actions: {
|
|
939
|
+
"play-pause": "Reproducir / Pausar",
|
|
940
|
+
"seek-backward": "Retroceder",
|
|
941
|
+
"seek-forward": "Avanzar",
|
|
942
|
+
"volume-up": "Subir volumen",
|
|
943
|
+
"volume-down": "Bajar volumen",
|
|
944
|
+
"mute": "Silenciar / Activar sonido",
|
|
945
|
+
"captions": "Alternar subtítulos",
|
|
946
|
+
"caption-style-menu": "Estilo de subtítulos",
|
|
947
|
+
"speed-down": "Reducir velocidad",
|
|
948
|
+
"speed-up": "Aumentar velocidad",
|
|
949
|
+
"speed-menu": "Velocidad de reproducción",
|
|
950
|
+
"quality-menu": "Calidad",
|
|
951
|
+
"chapters-menu": "Capítulos",
|
|
952
|
+
"transcript-toggle": "Alternar transcripción",
|
|
953
|
+
"fullscreen": "Alternar pantalla completa",
|
|
954
|
+
"help": "Atajos de teclado"
|
|
955
|
+
}
|
|
956
|
+
},
|
|
876
957
|
speeds: {
|
|
877
958
|
normal: "Normal"
|
|
878
959
|
},
|
|
@@ -1094,6 +1175,33 @@
|
|
|
1094
1175
|
reset: "Réinitialiser",
|
|
1095
1176
|
close: "Fermer"
|
|
1096
1177
|
},
|
|
1178
|
+
help: {
|
|
1179
|
+
title: "Raccourcis clavier",
|
|
1180
|
+
button: "Raccourcis clavier",
|
|
1181
|
+
close: "Fermer",
|
|
1182
|
+
or: "ou",
|
|
1183
|
+
keys: {
|
|
1184
|
+
space: "Espace"
|
|
1185
|
+
},
|
|
1186
|
+
actions: {
|
|
1187
|
+
"play-pause": "Lecture / Pause",
|
|
1188
|
+
"seek-backward": "Reculer",
|
|
1189
|
+
"seek-forward": "Avancer",
|
|
1190
|
+
"volume-up": "Augmenter le volume",
|
|
1191
|
+
"volume-down": "Baisser le volume",
|
|
1192
|
+
"mute": "Couper / Activer le son",
|
|
1193
|
+
"captions": "Activer/désactiver les sous-titres",
|
|
1194
|
+
"caption-style-menu": "Style des sous-titres",
|
|
1195
|
+
"speed-down": "Ralentir",
|
|
1196
|
+
"speed-up": "Accélérer",
|
|
1197
|
+
"speed-menu": "Vitesse de lecture",
|
|
1198
|
+
"quality-menu": "Qualité",
|
|
1199
|
+
"chapters-menu": "Chapitres",
|
|
1200
|
+
"transcript-toggle": "Activer/désactiver la transcription",
|
|
1201
|
+
"fullscreen": "Activer/désactiver le plein écran",
|
|
1202
|
+
"help": "Raccourcis clavier"
|
|
1203
|
+
}
|
|
1204
|
+
},
|
|
1097
1205
|
speeds: {
|
|
1098
1206
|
normal: "Normal"
|
|
1099
1207
|
},
|
|
@@ -1315,6 +1423,33 @@
|
|
|
1315
1423
|
reset: "リセット",
|
|
1316
1424
|
close: "閉じる"
|
|
1317
1425
|
},
|
|
1426
|
+
help: {
|
|
1427
|
+
title: "キーボードショートカット",
|
|
1428
|
+
button: "キーボードショートカット",
|
|
1429
|
+
close: "閉じる",
|
|
1430
|
+
or: "または",
|
|
1431
|
+
keys: {
|
|
1432
|
+
space: "スペース"
|
|
1433
|
+
},
|
|
1434
|
+
actions: {
|
|
1435
|
+
"play-pause": "再生 / 一時停止",
|
|
1436
|
+
"seek-backward": "巻き戻し",
|
|
1437
|
+
"seek-forward": "早送り",
|
|
1438
|
+
"volume-up": "音量を上げる",
|
|
1439
|
+
"volume-down": "音量を下げる",
|
|
1440
|
+
"mute": "ミュート / ミュート解除",
|
|
1441
|
+
"captions": "字幕の切り替え",
|
|
1442
|
+
"caption-style-menu": "字幕スタイル",
|
|
1443
|
+
"speed-down": "速度を下げる",
|
|
1444
|
+
"speed-up": "速度を上げる",
|
|
1445
|
+
"speed-menu": "再生速度",
|
|
1446
|
+
"quality-menu": "画質",
|
|
1447
|
+
"chapters-menu": "チャプター",
|
|
1448
|
+
"transcript-toggle": "文字起こしの切り替え",
|
|
1449
|
+
"fullscreen": "全画面表示の切り替え",
|
|
1450
|
+
"help": "キーボードショートカット"
|
|
1451
|
+
}
|
|
1452
|
+
},
|
|
1318
1453
|
speeds: {
|
|
1319
1454
|
normal: "通常"
|
|
1320
1455
|
},
|
|
@@ -1767,7 +1902,8 @@
|
|
|
1767
1902
|
move: `<path d="M10 9h4V6h3l-5-5-5 5h3v3zm-1 1H6V7l-5 5 5 5v-3h3v-4zm14 2l-5-5v3h-3v4h3v3l5-5zm-9 3h-4v3H7l5 5 5-5h-3v-3z"/>`,
|
|
1768
1903
|
resize: `<path d="M21.71 11.29l-9-9c-.39-.39-1.02-.39-1.41 0l-9 9c-.39.39-.39 1.02 0 1.41l9 9c.39.39 1.02.39 1.41 0l9-9c.39-.38.39-1.01 0-1.41zM14 14.5V12h-4v2.5L7 11l3-3.5V10h4V7.5l3 3.5-3 3.5z"/>`,
|
|
1769
1904
|
clock: `<path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"/><path d="M12.5 7H11v6l5.25 3.15.75-1.23-4.5-2.67z"/>`,
|
|
1770
|
-
download: `<path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"
|
|
1905
|
+
download: `<path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"/>`,
|
|
1906
|
+
help: `<path d="M11 18h2v-2h-2v2zm1-16C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm0-14c-2.21 0-4 1.79-4 4h2c0-1.1.9-2 2-2s2 .9 2 2c0 2-3 1.75-3 5h2c0-2.25 3-2.5 3-5 0-2.21-1.79-4-4-4z"/>`
|
|
1771
1907
|
};
|
|
1772
1908
|
svgWrapper = (paths) => `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">${paths}</svg>`;
|
|
1773
1909
|
Icons = Object.fromEntries(
|
|
@@ -12376,6 +12512,12 @@
|
|
|
12376
12512
|
}
|
|
12377
12513
|
this.rightButtons.appendChild(btn);
|
|
12378
12514
|
}
|
|
12515
|
+
if (this.player.options.helpButton && this.player.options.keyboard) {
|
|
12516
|
+
const btn = this.createHelpButton();
|
|
12517
|
+
btn.dataset.overflowPriority = "3";
|
|
12518
|
+
btn.dataset.overflowPriorityMobile = "3";
|
|
12519
|
+
this.rightButtons.appendChild(btn);
|
|
12520
|
+
}
|
|
12379
12521
|
this.overflowMenuButton = this.createOverflowMenuButton();
|
|
12380
12522
|
this.overflowMenuButton.style.display = "none";
|
|
12381
12523
|
this.rightButtons.appendChild(this.overflowMenuButton);
|
|
@@ -13697,6 +13839,24 @@
|
|
|
13697
13839
|
const isVisible = this.player.transcriptManager && this.player.transcriptManager.isVisible;
|
|
13698
13840
|
this.controls.transcript.setAttribute("aria-expanded", isVisible ? "true" : "false");
|
|
13699
13841
|
}
|
|
13842
|
+
createHelpButton() {
|
|
13843
|
+
const ariaLabel = i18n.t("help.button");
|
|
13844
|
+
const button = DOMUtils.createElement("button", {
|
|
13845
|
+
className: `${this.player.options.classPrefix}-button ${this.player.options.classPrefix}-help`,
|
|
13846
|
+
attributes: {
|
|
13847
|
+
"type": "button",
|
|
13848
|
+
"aria-label": ariaLabel,
|
|
13849
|
+
"aria-haspopup": "dialog"
|
|
13850
|
+
}
|
|
13851
|
+
});
|
|
13852
|
+
button.appendChild(createIconElement("help"));
|
|
13853
|
+
DOMUtils.attachTooltip(button, ariaLabel, this.player.options.classPrefix);
|
|
13854
|
+
button.addEventListener("click", () => {
|
|
13855
|
+
this.player.toggleKeyboardHelp();
|
|
13856
|
+
});
|
|
13857
|
+
this.controls.help = button;
|
|
13858
|
+
return button;
|
|
13859
|
+
}
|
|
13700
13860
|
createAudioDescriptionButton() {
|
|
13701
13861
|
const ariaLabel = i18n.t("player.audioDescription");
|
|
13702
13862
|
const button = DOMUtils.createElement("button", {
|
|
@@ -14944,6 +15104,9 @@
|
|
|
14944
15104
|
return true;
|
|
14945
15105
|
}
|
|
14946
15106
|
return false;
|
|
15107
|
+
case "help":
|
|
15108
|
+
this.player.toggleKeyboardHelp();
|
|
15109
|
+
return true;
|
|
14947
15110
|
default:
|
|
14948
15111
|
return false;
|
|
14949
15112
|
}
|
|
@@ -15031,6 +15194,252 @@
|
|
|
15031
15194
|
}
|
|
15032
15195
|
};
|
|
15033
15196
|
|
|
15197
|
+
// src/core/MediaSessionManager.ts
|
|
15198
|
+
var POSITION_THROTTLE_MS = 1e3;
|
|
15199
|
+
var activeManager = null;
|
|
15200
|
+
var MediaSessionManager = class {
|
|
15201
|
+
constructor(player) {
|
|
15202
|
+
__publicField(this, "player");
|
|
15203
|
+
__publicField(this, "supported");
|
|
15204
|
+
__publicField(this, "handlers", {});
|
|
15205
|
+
__publicField(this, "boundActions", []);
|
|
15206
|
+
__publicField(this, "lastPositionUpdate", 0);
|
|
15207
|
+
this.player = player;
|
|
15208
|
+
this.supported = typeof navigator !== "undefined" && "mediaSession" in navigator;
|
|
15209
|
+
if (!this.supported) return;
|
|
15210
|
+
this.attachEvents();
|
|
15211
|
+
if (activeManager === null) {
|
|
15212
|
+
this.claimSession();
|
|
15213
|
+
}
|
|
15214
|
+
}
|
|
15215
|
+
/** Does this manager currently own the global media session? */
|
|
15216
|
+
isActive() {
|
|
15217
|
+
return activeManager === this;
|
|
15218
|
+
}
|
|
15219
|
+
/**
|
|
15220
|
+
* Take ownership of the global session: (re)register the action handlers so
|
|
15221
|
+
* the OS controls drive this player, and refresh metadata/state/position.
|
|
15222
|
+
*/
|
|
15223
|
+
claimSession() {
|
|
15224
|
+
if (!this.supported) return;
|
|
15225
|
+
activeManager = this;
|
|
15226
|
+
this.setupActionHandlers();
|
|
15227
|
+
this.updateMetadata();
|
|
15228
|
+
this.updatePlaybackState();
|
|
15229
|
+
this.updatePositionState(true);
|
|
15230
|
+
}
|
|
15231
|
+
get session() {
|
|
15232
|
+
return navigator.mediaSession;
|
|
15233
|
+
}
|
|
15234
|
+
setActionHandler(action, handler) {
|
|
15235
|
+
try {
|
|
15236
|
+
this.session.setActionHandler(action, handler);
|
|
15237
|
+
if (handler && !this.boundActions.includes(action)) {
|
|
15238
|
+
this.boundActions.push(action);
|
|
15239
|
+
}
|
|
15240
|
+
} catch {
|
|
15241
|
+
}
|
|
15242
|
+
}
|
|
15243
|
+
setupActionHandlers() {
|
|
15244
|
+
this.setActionHandler("play", () => this.player.play());
|
|
15245
|
+
this.setActionHandler("pause", () => this.player.pause());
|
|
15246
|
+
this.setActionHandler("stop", () => this.player.stop());
|
|
15247
|
+
this.setActionHandler("seekbackward", (details) => {
|
|
15248
|
+
this.player.seekBackward(this.offsetFrom(details));
|
|
15249
|
+
});
|
|
15250
|
+
this.setActionHandler("seekforward", (details) => {
|
|
15251
|
+
this.player.seekForward(this.offsetFrom(details));
|
|
15252
|
+
});
|
|
15253
|
+
this.setActionHandler("seekto", (details) => {
|
|
15254
|
+
if (details && typeof details.seekTime === "number") {
|
|
15255
|
+
this.player.seek(details.seekTime);
|
|
15256
|
+
}
|
|
15257
|
+
});
|
|
15258
|
+
this.updateTrackHandlers();
|
|
15259
|
+
}
|
|
15260
|
+
offsetFrom(details) {
|
|
15261
|
+
const offset = details && typeof details.seekOffset === "number" ? details.seekOffset : void 0;
|
|
15262
|
+
return typeof offset === "number" && offset > 0 ? offset : void 0;
|
|
15263
|
+
}
|
|
15264
|
+
/**
|
|
15265
|
+
* previous/next track only make sense with a multi-item playlist; bind
|
|
15266
|
+
* or clear them whenever the playlist state changes so the OS shows the
|
|
15267
|
+
* correct affordances.
|
|
15268
|
+
*/
|
|
15269
|
+
updateTrackHandlers() {
|
|
15270
|
+
const pm = this.player.playlistManager;
|
|
15271
|
+
const hasPlaylist = Boolean(pm && Array.isArray(pm.tracks) && pm.tracks.length > 1);
|
|
15272
|
+
if (hasPlaylist && pm) {
|
|
15273
|
+
this.setActionHandler("previoustrack", () => pm.previous());
|
|
15274
|
+
this.setActionHandler("nexttrack", () => pm.next());
|
|
15275
|
+
} else {
|
|
15276
|
+
this.setActionHandler("previoustrack", null);
|
|
15277
|
+
this.setActionHandler("nexttrack", null);
|
|
15278
|
+
}
|
|
15279
|
+
}
|
|
15280
|
+
attachEvents() {
|
|
15281
|
+
this.handlers = {
|
|
15282
|
+
// Starting playback makes this player the session owner, taking over
|
|
15283
|
+
// the OS controls from any other player on the page.
|
|
15284
|
+
play: () => this.claimSession(),
|
|
15285
|
+
pause: () => {
|
|
15286
|
+
if (!this.isActive()) return;
|
|
15287
|
+
this.updatePlaybackState();
|
|
15288
|
+
this.updatePositionState(true);
|
|
15289
|
+
},
|
|
15290
|
+
ended: () => {
|
|
15291
|
+
if (!this.isActive()) return;
|
|
15292
|
+
this.updatePlaybackState();
|
|
15293
|
+
},
|
|
15294
|
+
timeupdate: () => {
|
|
15295
|
+
if (!this.isActive()) return;
|
|
15296
|
+
this.updatePositionState();
|
|
15297
|
+
},
|
|
15298
|
+
durationchange: () => {
|
|
15299
|
+
if (!this.isActive()) return;
|
|
15300
|
+
this.updatePositionState(true);
|
|
15301
|
+
},
|
|
15302
|
+
ratechange: () => {
|
|
15303
|
+
if (!this.isActive()) return;
|
|
15304
|
+
this.updatePositionState(true);
|
|
15305
|
+
},
|
|
15306
|
+
loadedmetadata: () => {
|
|
15307
|
+
if (!this.isActive()) return;
|
|
15308
|
+
this.updateMetadata();
|
|
15309
|
+
this.updatePositionState(true);
|
|
15310
|
+
},
|
|
15311
|
+
playlisttrackchange: () => {
|
|
15312
|
+
if (!this.isActive()) return;
|
|
15313
|
+
this.updateMetadata();
|
|
15314
|
+
this.updateTrackHandlers();
|
|
15315
|
+
this.updatePositionState(true);
|
|
15316
|
+
}
|
|
15317
|
+
};
|
|
15318
|
+
for (const [event, handler] of Object.entries(this.handlers)) {
|
|
15319
|
+
if (handler) {
|
|
15320
|
+
this.player.on(event, handler);
|
|
15321
|
+
}
|
|
15322
|
+
}
|
|
15323
|
+
}
|
|
15324
|
+
resolveMetadata() {
|
|
15325
|
+
const opts = this.player.options;
|
|
15326
|
+
let title = opts.title || "";
|
|
15327
|
+
let artist = opts.artist || "";
|
|
15328
|
+
const album = opts.album || "";
|
|
15329
|
+
let poster = opts.poster || null;
|
|
15330
|
+
const pm = this.player.playlistManager;
|
|
15331
|
+
if (pm && Array.isArray(pm.tracks) && pm.currentIndex >= 0) {
|
|
15332
|
+
const track = pm.tracks[pm.currentIndex];
|
|
15333
|
+
if (track) {
|
|
15334
|
+
if (track.title) title = track.title;
|
|
15335
|
+
if (track.artist) artist = track.artist;
|
|
15336
|
+
if (track.poster) poster = track.poster;
|
|
15337
|
+
}
|
|
15338
|
+
}
|
|
15339
|
+
if (!title && typeof document !== "undefined") {
|
|
15340
|
+
title = document.title || "VidPly";
|
|
15341
|
+
}
|
|
15342
|
+
return { title, artist, album, poster };
|
|
15343
|
+
}
|
|
15344
|
+
updateMetadata() {
|
|
15345
|
+
if (!this.supported || typeof window === "undefined" || typeof window.MediaMetadata === "undefined") {
|
|
15346
|
+
return;
|
|
15347
|
+
}
|
|
15348
|
+
const { title, artist, album, poster } = this.resolveMetadata();
|
|
15349
|
+
const artwork = [];
|
|
15350
|
+
if (poster) {
|
|
15351
|
+
try {
|
|
15352
|
+
const src = this.player.resolvePosterPath(poster);
|
|
15353
|
+
if (src) {
|
|
15354
|
+
artwork.push({ src });
|
|
15355
|
+
}
|
|
15356
|
+
} catch {
|
|
15357
|
+
}
|
|
15358
|
+
}
|
|
15359
|
+
try {
|
|
15360
|
+
this.session.metadata = new window.MediaMetadata({
|
|
15361
|
+
title,
|
|
15362
|
+
artist,
|
|
15363
|
+
album,
|
|
15364
|
+
artwork
|
|
15365
|
+
});
|
|
15366
|
+
} catch {
|
|
15367
|
+
}
|
|
15368
|
+
}
|
|
15369
|
+
updatePlaybackState() {
|
|
15370
|
+
if (!this.supported) return;
|
|
15371
|
+
try {
|
|
15372
|
+
this.session.playbackState = this.player.state.playing ? "playing" : "paused";
|
|
15373
|
+
} catch {
|
|
15374
|
+
}
|
|
15375
|
+
}
|
|
15376
|
+
/**
|
|
15377
|
+
* Push the current position to the OS scrubber. `timeupdate` fires
|
|
15378
|
+
* several times a second, so non-forced updates are throttled.
|
|
15379
|
+
*/
|
|
15380
|
+
updatePositionState(force = false) {
|
|
15381
|
+
if (!this.supported || typeof this.session.setPositionState !== "function") {
|
|
15382
|
+
return;
|
|
15383
|
+
}
|
|
15384
|
+
const now = Date.now();
|
|
15385
|
+
if (!force && now - this.lastPositionUpdate < POSITION_THROTTLE_MS) {
|
|
15386
|
+
return;
|
|
15387
|
+
}
|
|
15388
|
+
this.lastPositionUpdate = now;
|
|
15389
|
+
const duration = this.player.state.duration;
|
|
15390
|
+
if (!Number.isFinite(duration) || duration <= 0) {
|
|
15391
|
+
try {
|
|
15392
|
+
this.session.setPositionState();
|
|
15393
|
+
} catch {
|
|
15394
|
+
}
|
|
15395
|
+
return;
|
|
15396
|
+
}
|
|
15397
|
+
const playbackRate = this.player.state.playbackSpeed || 1;
|
|
15398
|
+
const position = Math.min(Math.max(0, this.player.state.currentTime || 0), duration);
|
|
15399
|
+
try {
|
|
15400
|
+
this.session.setPositionState({
|
|
15401
|
+
duration,
|
|
15402
|
+
playbackRate: playbackRate > 0 ? playbackRate : 1,
|
|
15403
|
+
position
|
|
15404
|
+
});
|
|
15405
|
+
} catch {
|
|
15406
|
+
}
|
|
15407
|
+
}
|
|
15408
|
+
destroy() {
|
|
15409
|
+
if (!this.supported) return;
|
|
15410
|
+
for (const [event, handler] of Object.entries(this.handlers)) {
|
|
15411
|
+
if (handler) {
|
|
15412
|
+
this.player.off(event, handler);
|
|
15413
|
+
}
|
|
15414
|
+
}
|
|
15415
|
+
this.handlers = {};
|
|
15416
|
+
if (this.isActive()) {
|
|
15417
|
+
for (const action of this.boundActions) {
|
|
15418
|
+
try {
|
|
15419
|
+
this.session.setActionHandler(action, null);
|
|
15420
|
+
} catch {
|
|
15421
|
+
}
|
|
15422
|
+
}
|
|
15423
|
+
try {
|
|
15424
|
+
this.session.metadata = null;
|
|
15425
|
+
} catch {
|
|
15426
|
+
}
|
|
15427
|
+
try {
|
|
15428
|
+
if (typeof this.session.setPositionState === "function") {
|
|
15429
|
+
this.session.setPositionState();
|
|
15430
|
+
}
|
|
15431
|
+
} catch {
|
|
15432
|
+
}
|
|
15433
|
+
try {
|
|
15434
|
+
this.session.playbackState = "none";
|
|
15435
|
+
} catch {
|
|
15436
|
+
}
|
|
15437
|
+
activeManager = null;
|
|
15438
|
+
}
|
|
15439
|
+
this.boundActions = [];
|
|
15440
|
+
}
|
|
15441
|
+
};
|
|
15442
|
+
|
|
15034
15443
|
// src/core/Player.ts
|
|
15035
15444
|
init_HTML5Renderer();
|
|
15036
15445
|
init_Icons();
|
|
@@ -16147,6 +16556,263 @@
|
|
|
16147
16556
|
}
|
|
16148
16557
|
};
|
|
16149
16558
|
|
|
16559
|
+
// src/controls/KeyboardHelp.ts
|
|
16560
|
+
init_DOMUtils();
|
|
16561
|
+
init_Icons();
|
|
16562
|
+
init_i18n();
|
|
16563
|
+
var ACTION_ORDER = [
|
|
16564
|
+
"play-pause",
|
|
16565
|
+
"seek-backward",
|
|
16566
|
+
"seek-forward",
|
|
16567
|
+
"volume-up",
|
|
16568
|
+
"volume-down",
|
|
16569
|
+
"mute",
|
|
16570
|
+
"captions",
|
|
16571
|
+
"caption-style-menu",
|
|
16572
|
+
"speed-down",
|
|
16573
|
+
"speed-up",
|
|
16574
|
+
"speed-menu",
|
|
16575
|
+
"quality-menu",
|
|
16576
|
+
"chapters-menu",
|
|
16577
|
+
"transcript-toggle",
|
|
16578
|
+
"fullscreen",
|
|
16579
|
+
"help"
|
|
16580
|
+
];
|
|
16581
|
+
var ACTION_REQUIRES_CONTROL = {
|
|
16582
|
+
captions: "captions",
|
|
16583
|
+
"caption-style-menu": "captionStyle",
|
|
16584
|
+
"speed-down": "speed",
|
|
16585
|
+
"speed-up": "speed",
|
|
16586
|
+
"speed-menu": "speed",
|
|
16587
|
+
"quality-menu": "quality",
|
|
16588
|
+
"chapters-menu": "chapters",
|
|
16589
|
+
"transcript-toggle": "transcript",
|
|
16590
|
+
fullscreen: "fullscreen"
|
|
16591
|
+
};
|
|
16592
|
+
var KeyboardHelp = class {
|
|
16593
|
+
constructor(player) {
|
|
16594
|
+
__publicField(this, "player");
|
|
16595
|
+
__publicField(this, "isOpen", false);
|
|
16596
|
+
__publicField(this, "overlay", null);
|
|
16597
|
+
__publicField(this, "_triggerElement", null);
|
|
16598
|
+
__publicField(this, "_keydownHandler", null);
|
|
16599
|
+
__publicField(this, "_content", null);
|
|
16600
|
+
this.player = player;
|
|
16601
|
+
}
|
|
16602
|
+
get prefix() {
|
|
16603
|
+
return this.player.options.classPrefix;
|
|
16604
|
+
}
|
|
16605
|
+
/**
|
|
16606
|
+
* Turn a raw KeyboardEvent.key value into a human-readable label. Arrow
|
|
16607
|
+
* keys become universally understood glyphs; the space bar and single
|
|
16608
|
+
* letters are normalised for legibility.
|
|
16609
|
+
*/
|
|
16610
|
+
formatKey(key) {
|
|
16611
|
+
switch (key) {
|
|
16612
|
+
case " ":
|
|
16613
|
+
return i18n.t("help.keys.space");
|
|
16614
|
+
case "ArrowUp":
|
|
16615
|
+
return "↑";
|
|
16616
|
+
case "ArrowDown":
|
|
16617
|
+
return "↓";
|
|
16618
|
+
case "ArrowLeft":
|
|
16619
|
+
return "←";
|
|
16620
|
+
case "ArrowRight":
|
|
16621
|
+
return "→";
|
|
16622
|
+
case "Escape":
|
|
16623
|
+
return "Esc";
|
|
16624
|
+
default:
|
|
16625
|
+
return key.length === 1 ? key.toUpperCase() : key;
|
|
16626
|
+
}
|
|
16627
|
+
}
|
|
16628
|
+
createElement() {
|
|
16629
|
+
const titleId = `${this.prefix}-help-title-${this.player.instanceId}`;
|
|
16630
|
+
const overlay = DOMUtils.createElement("div", {
|
|
16631
|
+
className: `${this.prefix}-settings-overlay ${this.prefix}-help-overlay`,
|
|
16632
|
+
attributes: {
|
|
16633
|
+
role: "dialog",
|
|
16634
|
+
"aria-modal": "true",
|
|
16635
|
+
"aria-labelledby": titleId
|
|
16636
|
+
}
|
|
16637
|
+
});
|
|
16638
|
+
overlay.style.display = "none";
|
|
16639
|
+
const dialog = DOMUtils.createElement("div", {
|
|
16640
|
+
className: `${this.prefix}-settings-dialog ${this.prefix}-help-dialog`
|
|
16641
|
+
});
|
|
16642
|
+
const header = DOMUtils.createElement("div", {
|
|
16643
|
+
className: `${this.prefix}-settings-header`
|
|
16644
|
+
});
|
|
16645
|
+
const title = DOMUtils.createElement("h2", {
|
|
16646
|
+
textContent: i18n.t("help.title"),
|
|
16647
|
+
attributes: { id: titleId }
|
|
16648
|
+
});
|
|
16649
|
+
const closeButton = DOMUtils.createElement("button", {
|
|
16650
|
+
className: `${this.prefix}-button ${this.prefix}-settings-close`,
|
|
16651
|
+
attributes: {
|
|
16652
|
+
type: "button",
|
|
16653
|
+
"aria-label": i18n.t("help.close")
|
|
16654
|
+
}
|
|
16655
|
+
});
|
|
16656
|
+
closeButton.appendChild(createIconElement("close"));
|
|
16657
|
+
closeButton.addEventListener("click", () => this.hide());
|
|
16658
|
+
header.appendChild(title);
|
|
16659
|
+
header.appendChild(closeButton);
|
|
16660
|
+
const content = DOMUtils.createElement("div", {
|
|
16661
|
+
className: `${this.prefix}-settings-content`
|
|
16662
|
+
});
|
|
16663
|
+
this._content = content;
|
|
16664
|
+
content.appendChild(this.buildShortcutList());
|
|
16665
|
+
dialog.appendChild(header);
|
|
16666
|
+
dialog.appendChild(content);
|
|
16667
|
+
overlay.appendChild(dialog);
|
|
16668
|
+
overlay.addEventListener("click", (e) => {
|
|
16669
|
+
if (e.target === overlay) {
|
|
16670
|
+
this.hide();
|
|
16671
|
+
}
|
|
16672
|
+
});
|
|
16673
|
+
this._keydownHandler = (e) => {
|
|
16674
|
+
if (!this.isOpen || !this.overlay) return;
|
|
16675
|
+
if (e.key === "Escape") {
|
|
16676
|
+
e.preventDefault();
|
|
16677
|
+
this.hide();
|
|
16678
|
+
return;
|
|
16679
|
+
}
|
|
16680
|
+
if (e.key === "Tab") {
|
|
16681
|
+
const focusable = Array.from(
|
|
16682
|
+
this.overlay.querySelectorAll(
|
|
16683
|
+
'button, [href], select, input, textarea, [tabindex]:not([tabindex="-1"])'
|
|
16684
|
+
)
|
|
16685
|
+
).filter((el) => !el.hasAttribute("disabled") && el.offsetParent !== null);
|
|
16686
|
+
if (focusable.length === 0) return;
|
|
16687
|
+
const first = focusable[0];
|
|
16688
|
+
const last = focusable[focusable.length - 1];
|
|
16689
|
+
if (!first || !last) return;
|
|
16690
|
+
const active = document.activeElement;
|
|
16691
|
+
if (e.shiftKey && (active === first || !this.overlay.contains(active))) {
|
|
16692
|
+
e.preventDefault();
|
|
16693
|
+
last.focus({ preventScroll: true });
|
|
16694
|
+
} else if (!e.shiftKey && active === last) {
|
|
16695
|
+
e.preventDefault();
|
|
16696
|
+
first.focus({ preventScroll: true });
|
|
16697
|
+
}
|
|
16698
|
+
}
|
|
16699
|
+
};
|
|
16700
|
+
const lifecycleSignal = this.player.lifecycleSignal;
|
|
16701
|
+
document.addEventListener(
|
|
16702
|
+
"keydown",
|
|
16703
|
+
this._keydownHandler,
|
|
16704
|
+
lifecycleSignal ? { signal: lifecycleSignal } : void 0
|
|
16705
|
+
);
|
|
16706
|
+
return overlay;
|
|
16707
|
+
}
|
|
16708
|
+
/**
|
|
16709
|
+
* Whether a shortcut row is worth showing for *this* player. Feature actions
|
|
16710
|
+
* are hidden when their control isn't present (e.g. no captions track, an
|
|
16711
|
+
* audio-only player with no fullscreen). Core actions are always relevant.
|
|
16712
|
+
*
|
|
16713
|
+
* When the player has no control bar we can't infer availability, so nothing
|
|
16714
|
+
* is hidden — the shortcuts still work and we'd rather over-show than mislead.
|
|
16715
|
+
*/
|
|
16716
|
+
isActionRelevant(action) {
|
|
16717
|
+
const requiredControl = ACTION_REQUIRES_CONTROL[action];
|
|
16718
|
+
if (!requiredControl) return true;
|
|
16719
|
+
const controlBar = this.player.controlBar;
|
|
16720
|
+
if (!controlBar || !controlBar.controls) return true;
|
|
16721
|
+
return Boolean(controlBar.controls[requiredControl]);
|
|
16722
|
+
}
|
|
16723
|
+
buildShortcutList() {
|
|
16724
|
+
const list = DOMUtils.createElement("dl", {
|
|
16725
|
+
className: `${this.prefix}-help-list`
|
|
16726
|
+
});
|
|
16727
|
+
const shortcuts = this.player.options.keyboardShortcuts;
|
|
16728
|
+
for (const action of ACTION_ORDER) {
|
|
16729
|
+
const keys = shortcuts[action];
|
|
16730
|
+
if (!Array.isArray(keys) || keys.length === 0) continue;
|
|
16731
|
+
if (!this.isActionRelevant(action)) continue;
|
|
16732
|
+
const term = DOMUtils.createElement("dt", {
|
|
16733
|
+
className: `${this.prefix}-help-action`,
|
|
16734
|
+
textContent: i18n.t(`help.actions.${action}`)
|
|
16735
|
+
});
|
|
16736
|
+
const desc = DOMUtils.createElement("dd", {
|
|
16737
|
+
className: `${this.prefix}-help-keys`
|
|
16738
|
+
});
|
|
16739
|
+
keys.forEach((key, index) => {
|
|
16740
|
+
if (index > 0) {
|
|
16741
|
+
desc.appendChild(
|
|
16742
|
+
DOMUtils.createElement("span", {
|
|
16743
|
+
className: `${this.prefix}-help-key-sep`,
|
|
16744
|
+
textContent: i18n.t("help.or")
|
|
16745
|
+
})
|
|
16746
|
+
);
|
|
16747
|
+
}
|
|
16748
|
+
desc.appendChild(
|
|
16749
|
+
DOMUtils.createElement("kbd", {
|
|
16750
|
+
className: `${this.prefix}-help-key`,
|
|
16751
|
+
textContent: this.formatKey(key)
|
|
16752
|
+
})
|
|
16753
|
+
);
|
|
16754
|
+
});
|
|
16755
|
+
list.appendChild(term);
|
|
16756
|
+
list.appendChild(desc);
|
|
16757
|
+
}
|
|
16758
|
+
return list;
|
|
16759
|
+
}
|
|
16760
|
+
show() {
|
|
16761
|
+
if (this.isOpen) return;
|
|
16762
|
+
if (!this.overlay) {
|
|
16763
|
+
this.overlay = this.createElement();
|
|
16764
|
+
this.player.container.appendChild(this.overlay);
|
|
16765
|
+
} else if (this._content) {
|
|
16766
|
+
this._content.replaceChildren(this.buildShortcutList());
|
|
16767
|
+
}
|
|
16768
|
+
const active = typeof document !== "undefined" ? document.activeElement : null;
|
|
16769
|
+
this._triggerElement = active && typeof active.focus === "function" ? active : null;
|
|
16770
|
+
this.overlay.style.display = "flex";
|
|
16771
|
+
this.isOpen = true;
|
|
16772
|
+
const closeButton = this.overlay.querySelector(`.${this.prefix}-settings-close`);
|
|
16773
|
+
closeButton == null ? void 0 : closeButton.focus({ preventScroll: true });
|
|
16774
|
+
this.player.emit("keyboardhelpopen");
|
|
16775
|
+
}
|
|
16776
|
+
hide() {
|
|
16777
|
+
var _a, _b;
|
|
16778
|
+
if (!this.overlay) return;
|
|
16779
|
+
this.overlay.style.display = "none";
|
|
16780
|
+
this.isOpen = false;
|
|
16781
|
+
const trigger = this._triggerElement;
|
|
16782
|
+
this._triggerElement = null;
|
|
16783
|
+
if (trigger && document.contains(trigger)) {
|
|
16784
|
+
try {
|
|
16785
|
+
trigger.focus({ preventScroll: true });
|
|
16786
|
+
} catch {
|
|
16787
|
+
(_a = this.player.container) == null ? void 0 : _a.focus();
|
|
16788
|
+
}
|
|
16789
|
+
} else {
|
|
16790
|
+
(_b = this.player.container) == null ? void 0 : _b.focus();
|
|
16791
|
+
}
|
|
16792
|
+
this.player.emit("keyboardhelpclose");
|
|
16793
|
+
}
|
|
16794
|
+
toggle() {
|
|
16795
|
+
if (this.isOpen) {
|
|
16796
|
+
this.hide();
|
|
16797
|
+
} else {
|
|
16798
|
+
this.show();
|
|
16799
|
+
}
|
|
16800
|
+
}
|
|
16801
|
+
destroy() {
|
|
16802
|
+
if (this._keydownHandler) {
|
|
16803
|
+
document.removeEventListener("keydown", this._keydownHandler);
|
|
16804
|
+
this._keydownHandler = null;
|
|
16805
|
+
}
|
|
16806
|
+
if (this.overlay && this.overlay.parentNode) {
|
|
16807
|
+
this.overlay.parentNode.removeChild(this.overlay);
|
|
16808
|
+
}
|
|
16809
|
+
this.overlay = null;
|
|
16810
|
+
this._content = null;
|
|
16811
|
+
this._triggerElement = null;
|
|
16812
|
+
this.isOpen = false;
|
|
16813
|
+
}
|
|
16814
|
+
};
|
|
16815
|
+
|
|
16150
16816
|
// src/core/Player.ts
|
|
16151
16817
|
var AudioDescriptionManagerModule = null;
|
|
16152
16818
|
var SignLanguageManagerModule = null;
|
|
@@ -16190,9 +16856,11 @@
|
|
|
16190
16856
|
__publicField(this, "controlBar", null);
|
|
16191
16857
|
__publicField(this, "captionManager", null);
|
|
16192
16858
|
__publicField(this, "keyboardManager", null);
|
|
16859
|
+
__publicField(this, "mediaSessionManager", null);
|
|
16193
16860
|
__publicField(this, "transcriptManager", null);
|
|
16194
16861
|
__publicField(this, "playlistManager", null);
|
|
16195
16862
|
__publicField(this, "settingsDialog", null);
|
|
16863
|
+
__publicField(this, "keyboardHelp", null);
|
|
16196
16864
|
__publicField(this, "audioDescriptionManager", null);
|
|
16197
16865
|
__publicField(this, "signLanguageManager", null);
|
|
16198
16866
|
__publicField(this, "floatingPlayerManager", null);
|
|
@@ -16306,6 +16974,11 @@
|
|
|
16306
16974
|
poster: null,
|
|
16307
16975
|
responsive: true,
|
|
16308
16976
|
fillContainer: false,
|
|
16977
|
+
// Media metadata + OS media controls (Media Session API)
|
|
16978
|
+
title: null,
|
|
16979
|
+
artist: null,
|
|
16980
|
+
album: null,
|
|
16981
|
+
mediaSession: true,
|
|
16309
16982
|
// Playback
|
|
16310
16983
|
autoplay: false,
|
|
16311
16984
|
loop: false,
|
|
@@ -16353,6 +17026,7 @@
|
|
|
16353
17026
|
captionsButton: true,
|
|
16354
17027
|
transcriptButton: true,
|
|
16355
17028
|
fullscreenButton: true,
|
|
17029
|
+
helpButton: true,
|
|
16356
17030
|
pipButton: false,
|
|
16357
17031
|
floating: false,
|
|
16358
17032
|
floatingPosition: "bottom-right",
|
|
@@ -16411,7 +17085,8 @@
|
|
|
16411
17085
|
"speed-menu": ["s"],
|
|
16412
17086
|
"quality-menu": ["q"],
|
|
16413
17087
|
"chapters-menu": ["j"],
|
|
16414
|
-
"transcript-toggle": ["t"]
|
|
17088
|
+
"transcript-toggle": ["t"],
|
|
17089
|
+
"help": ["?"]
|
|
16415
17090
|
},
|
|
16416
17091
|
// Accessibility
|
|
16417
17092
|
ariaLabels: {},
|
|
@@ -16794,6 +17469,9 @@
|
|
|
16794
17469
|
if (this.options.keyboard) {
|
|
16795
17470
|
this.keyboardManager = new KeyboardManager(this);
|
|
16796
17471
|
}
|
|
17472
|
+
if (this.options.mediaSession) {
|
|
17473
|
+
this.mediaSessionManager = new MediaSessionManager(this);
|
|
17474
|
+
}
|
|
16797
17475
|
this.setupResponsiveHandlers();
|
|
16798
17476
|
if (this.options.startTime > 0) {
|
|
16799
17477
|
this.seek(this.options.startTime);
|
|
@@ -18135,6 +18813,27 @@
|
|
|
18135
18813
|
}
|
|
18136
18814
|
hideSettings() {
|
|
18137
18815
|
}
|
|
18816
|
+
/**
|
|
18817
|
+
* Lazily build (on first use) and toggle the keyboard-shortcuts help
|
|
18818
|
+
* dialog. Reflects the live `keyboardShortcuts` bindings, including any
|
|
18819
|
+
* consumer overrides.
|
|
18820
|
+
*/
|
|
18821
|
+
toggleKeyboardHelp() {
|
|
18822
|
+
if (!this.keyboardHelp) {
|
|
18823
|
+
this.keyboardHelp = new KeyboardHelp(this);
|
|
18824
|
+
}
|
|
18825
|
+
this.keyboardHelp.toggle();
|
|
18826
|
+
}
|
|
18827
|
+
showKeyboardHelp() {
|
|
18828
|
+
if (!this.keyboardHelp) {
|
|
18829
|
+
this.keyboardHelp = new KeyboardHelp(this);
|
|
18830
|
+
}
|
|
18831
|
+
this.keyboardHelp.show();
|
|
18832
|
+
}
|
|
18833
|
+
hideKeyboardHelp() {
|
|
18834
|
+
var _a;
|
|
18835
|
+
(_a = this.keyboardHelp) == null ? void 0 : _a.hide();
|
|
18836
|
+
}
|
|
18138
18837
|
// Utility methods
|
|
18139
18838
|
getCurrentTime() {
|
|
18140
18839
|
return this.state.currentTime;
|
|
@@ -18275,6 +18974,22 @@
|
|
|
18275
18974
|
}
|
|
18276
18975
|
this.settingsDialog = null;
|
|
18277
18976
|
}
|
|
18977
|
+
if (this.keyboardHelp && typeof this.keyboardHelp.destroy === "function") {
|
|
18978
|
+
try {
|
|
18979
|
+
this.keyboardHelp.destroy();
|
|
18980
|
+
} catch (err) {
|
|
18981
|
+
this.log(`KeyboardHelp.destroy failed: ${err}`, "warn");
|
|
18982
|
+
}
|
|
18983
|
+
this.keyboardHelp = null;
|
|
18984
|
+
}
|
|
18985
|
+
if (this.mediaSessionManager && typeof this.mediaSessionManager.destroy === "function") {
|
|
18986
|
+
try {
|
|
18987
|
+
this.mediaSessionManager.destroy();
|
|
18988
|
+
} catch (err) {
|
|
18989
|
+
this.log(`MediaSessionManager.destroy failed: ${err}`, "warn");
|
|
18990
|
+
}
|
|
18991
|
+
this.mediaSessionManager = null;
|
|
18992
|
+
}
|
|
18278
18993
|
if (this.floatingPlayerManager) {
|
|
18279
18994
|
try {
|
|
18280
18995
|
this.floatingPlayerManager.destroy();
|