Fix chromecast title handling (#1685)

Fixed the title that did not update from stale closure because we no longer re-initialize the plugin.

We still continue to sever the connection when switching sources for now (although videojs is now single-instance) due to a problem that stops the next remote playback after 5-10 seconds. Unclear whether it is the plugin problem or due to our changes (although I don't see this issue in their repo).
This commit is contained in:
infinite-persistence 2022-06-14 12:34:35 +08:00 committed by GitHub
parent 94d5c11a71
commit 363fe82050
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 41 additions and 5 deletions

View file

@ -1,7 +1,11 @@
// @flow // @flow
let gTitle = '';
let gChannelTitle = '';
/** /**
* Wrapper for @silvermine/videojs-chromecast * Wrapper for @silvermine/videojs-chromecast to consolidate all things related
* to chromecast.
*/ */
export default class Chromecast { export default class Chromecast {
/** /**
@ -10,6 +14,7 @@ export default class Chromecast {
static initialize(player: any) { static initialize(player: any) {
// --- Start plugin --- // --- Start plugin ---
player.chromecast(); player.chromecast();
// --- Init cast framework --- // --- Init cast framework ---
const CHROMECAST_API_SCRIPT_ID = 'chromecastApi'; const CHROMECAST_API_SCRIPT_ID = 'chromecastApi';
const existingChromecastScript = document.getElementById(CHROMECAST_API_SCRIPT_ID); const existingChromecastScript = document.getElementById(CHROMECAST_API_SCRIPT_ID);
@ -21,4 +26,34 @@ export default class Chromecast {
document.body.appendChild(script); document.body.appendChild(script);
} }
} }
/**
* A React-to-vjs interface to pass the new content and channel titles to the
* chromecast plugin. Inline functions cannot be used in the `chromecast`
* property in `videoJsOptions` due to stale closure, since we no longer
* dispose the player when the src changes.
*
* We need this info from React because are unable to derive them from the
* `src` argument of `requestTitleFn | requestSubtitleFn`.
*
* @param title
* @param channelTitle
*/
static updateTitles(title: ?string, channelTitle: ?string) {
gTitle = title;
gChannelTitle = channelTitle;
}
/**
* Returns the required 'chromecast' options to be appended to the videojs
* options object.
*/
static getOptions() {
return {
chromecast: {
requestTitleFn: (src: ?string) => gTitle || '',
requestSubtitleFn: (src: ?string) => gChannelTitle || '',
},
};
}
} }

View file

@ -256,10 +256,7 @@ export default React.memo<Props>(function VideoJs(props: Props) {
subsCapsButton: !IS_IOS, subsCapsButton: !IS_IOS,
}, },
techOrder: ['chromecast', 'html5'], techOrder: ['chromecast', 'html5'],
chromecast: { ...Chromecast.getOptions(),
requestTitleFn: (src) => title || '',
requestSubtitleFn: (src) => channelTitle || '',
},
bigPlayButton: embedded, // only show big play button if embedded bigPlayButton: embedded, // only show big play button if embedded
liveui: isLivestreamClaim, liveui: isLivestreamClaim,
suppressNotSupportedError: true, suppressNotSupportedError: true,
@ -345,6 +342,10 @@ export default React.memo<Props>(function VideoJs(props: Props) {
// } // }
// }, [showQualitySelector]); // }, [showQualitySelector]);
useEffect(() => {
Chromecast.updateTitles(title, channelTitle);
}, [title, channelTitle]);
// This lifecycle hook is only called once (on mount), or when `isAudio` or `source` changes. // This lifecycle hook is only called once (on mount), or when `isAudio` or `source` changes.
useEffect(() => { useEffect(() => {
(async function () { (async function () {