@@ -1588,6 +1588,8 @@ export default defineComponent({
1588
1588
1589
1589
// #region custom player controls
1590
1590
1591
+ const { ContextMenu : shakaContextMenu , Controls : shakaControls , OverflowMenu : shakaOverflowMenu } = shaka . ui
1592
+
1591
1593
function registerAudioTrackSelection ( ) {
1592
1594
/** @implements {shaka.extern.IUIElement.Factory} */
1593
1595
class AudioTrackSelectionFactory {
@@ -1596,8 +1598,8 @@ export default defineComponent({
1596
1598
}
1597
1599
}
1598
1600
1599
- shaka . ui . Controls . registerElement ( 'ft_audio_tracks' , new AudioTrackSelectionFactory ( ) )
1600
- shaka . ui . OverflowMenu . registerElement ( 'ft_audio_tracks' , new AudioTrackSelectionFactory ( ) )
1601
+ shakaControls . registerElement ( 'ft_audio_tracks' , new AudioTrackSelectionFactory ( ) )
1602
+ shakaOverflowMenu . registerElement ( 'ft_audio_tracks' , new AudioTrackSelectionFactory ( ) )
1601
1603
}
1602
1604
1603
1605
function registerTheatreModeButton ( ) {
@@ -1614,8 +1616,8 @@ export default defineComponent({
1614
1616
}
1615
1617
}
1616
1618
1617
- shaka . ui . Controls . registerElement ( 'ft_theatre_mode' , new TheatreModeButtonFactory ( ) )
1618
- shaka . ui . OverflowMenu . registerElement ( 'ft_theatre_mode' , new TheatreModeButtonFactory ( ) )
1619
+ shakaControls . registerElement ( 'ft_theatre_mode' , new TheatreModeButtonFactory ( ) )
1620
+ shakaOverflowMenu . registerElement ( 'ft_theatre_mode' , new TheatreModeButtonFactory ( ) )
1619
1621
}
1620
1622
1621
1623
function registerFullWindowButton ( ) {
@@ -1642,8 +1644,8 @@ export default defineComponent({
1642
1644
}
1643
1645
}
1644
1646
1645
- shaka . ui . Controls . registerElement ( 'ft_full_window' , new FullWindowButtonFactory ( ) )
1646
- shaka . ui . OverflowMenu . registerElement ( 'ft_full_window' , new FullWindowButtonFactory ( ) )
1647
+ shakaControls . registerElement ( 'ft_full_window' , new FullWindowButtonFactory ( ) )
1648
+ shakaOverflowMenu . registerElement ( 'ft_full_window' , new FullWindowButtonFactory ( ) )
1647
1649
}
1648
1650
1649
1651
function registerLegacyQualitySelection ( ) {
@@ -1677,8 +1679,8 @@ export default defineComponent({
1677
1679
}
1678
1680
}
1679
1681
1680
- shaka . ui . Controls . registerElement ( 'ft_legacy_quality' , new LegacyQualitySelectionFactory ( ) )
1681
- shaka . ui . OverflowMenu . registerElement ( 'ft_legacy_quality' , new LegacyQualitySelectionFactory ( ) )
1682
+ shakaControls . registerElement ( 'ft_legacy_quality' , new LegacyQualitySelectionFactory ( ) )
1683
+ shakaOverflowMenu . registerElement ( 'ft_legacy_quality' , new LegacyQualitySelectionFactory ( ) )
1682
1684
}
1683
1685
1684
1686
function registerStatsButton ( ) {
@@ -1699,7 +1701,7 @@ export default defineComponent({
1699
1701
}
1700
1702
}
1701
1703
1702
- shaka . ui . ContextMenu . registerElement ( 'ft_stats' , new StatsButtonFactory ( ) )
1704
+ shakaContextMenu . registerElement ( 'ft_stats' , new StatsButtonFactory ( ) )
1703
1705
}
1704
1706
1705
1707
function registerScreenshotButton ( ) {
@@ -1716,8 +1718,34 @@ export default defineComponent({
1716
1718
}
1717
1719
}
1718
1720
1719
- shaka . ui . Controls . registerElement ( 'ft_screenshot' , new ScreenshotButtonFactory ( ) )
1720
- shaka . ui . OverflowMenu . registerElement ( 'ft_screenshot' , new ScreenshotButtonFactory ( ) )
1721
+ shakaControls . registerElement ( 'ft_screenshot' , new ScreenshotButtonFactory ( ) )
1722
+ shakaOverflowMenu . registerElement ( 'ft_screenshot' , new ScreenshotButtonFactory ( ) )
1723
+ }
1724
+
1725
+ /**
1726
+ * As shaka-player doesn't let you unregister custom control factories,
1727
+ * overwrite them with `null` instead so the referenced objects
1728
+ * (e.g. {@linkcode events}, {@linkcode fullWindowEnabled}) can get gargabe collected
1729
+ */
1730
+ function cleanUpCustomPlayerControls ( ) {
1731
+ shakaControls . registerElement ( 'ft_audio_tracks' , null )
1732
+ shakaOverflowMenu . registerElement ( 'ft_audio_tracks' , null )
1733
+
1734
+ shakaControls . registerElement ( 'ft_theatre_mode' , null )
1735
+ shakaOverflowMenu . registerElement ( 'ft_theatre_mode' , null )
1736
+
1737
+ shakaControls . registerElement ( 'ft_full_window' , null )
1738
+ shakaOverflowMenu . registerElement ( 'ft_full_window' , null )
1739
+
1740
+ shakaControls . registerElement ( 'ft_legacy_quality' , null )
1741
+ shakaOverflowMenu . registerElement ( 'ft_legacy_quality' , null )
1742
+
1743
+ shakaContextMenu . registerElement ( 'ft_stats' , null )
1744
+
1745
+ if ( process . env . IS_ELECTRON ) {
1746
+ shakaControls . registerElement ( 'ft_screenshot' , null )
1747
+ shakaOverflowMenu . registerElement ( 'ft_screenshot' , null )
1748
+ }
1721
1749
}
1722
1750
1723
1751
// #endregion custom player controls
@@ -2636,12 +2664,7 @@ export default defineComponent({
2636
2664
resizeObserver = null
2637
2665
}
2638
2666
2639
- if ( ui ) {
2640
- // destroying the ui also destroys the player
2641
- ui . destroy ( )
2642
- ui = null
2643
- player = null
2644
- }
2667
+ cleanUpCustomPlayerControls ( )
2645
2668
2646
2669
stopPowerSaveBlocker ( )
2647
2670
window . removeEventListener ( 'beforeunload' , stopPowerSaveBlocker )
@@ -2679,13 +2702,41 @@ export default defineComponent({
2679
2702
video . value . currentTime = time
2680
2703
}
2681
2704
2705
+ /**
2706
+ * Vue's lifecycle hooks are synchonous, so if we destroy the player in {@linkcode onBeforeUnmount},
2707
+ * it won't be finished in time, as the player destruction is asynchronous.
2708
+ * To workaround that we destroy the player first and wait for it to finish before we unmount this component.
2709
+ */
2710
+ async function destroyPlayer ( ) {
2711
+ if ( ui ) {
2712
+ // destroying the ui also destroys the player
2713
+ await ui . destroy ( )
2714
+ ui = null
2715
+ player = null
2716
+ } else if ( player ) {
2717
+ await player . destroy ( )
2718
+ player = null
2719
+ }
2720
+
2721
+ // shaka-player doesn't clear these itself, which prevents shaka.ui.Overlay from being garbage collected
2722
+ // Should really be fixed in shaka-player but it's easier just to do it ourselves
2723
+ if ( container . value ) {
2724
+ container . value . ui = null
2725
+ }
2726
+
2727
+ if ( video . value ) {
2728
+ video . value . ui = null
2729
+ }
2730
+ }
2731
+
2682
2732
expose ( {
2683
2733
hasLoaded,
2684
2734
2685
2735
isPaused,
2686
2736
pause,
2687
2737
getCurrentTime,
2688
- setCurrentTime
2738
+ setCurrentTime,
2739
+ destroyPlayer
2689
2740
} )
2690
2741
2691
2742
// #endregion functions used by the watch page
0 commit comments