diff --git a/src/routes/Player/Player.js b/src/routes/Player/Player.js index a55b228fc..eab38bd96 100644 --- a/src/routes/Player/Player.js +++ b/src/routes/Player/Player.js @@ -532,6 +532,53 @@ const Player = ({ urlParams, queryParams }) => { } }, [settings.pauseOnMinimize, shell.windowClosed, shell.windowHidden]); + // Media Session PlaybackState + React.useEffect(() => { + if (!navigator.mediaSession) return; + + const playbackState = !video.state.paused ? 'playing' : 'paused'; + navigator.mediaSession.playbackState = playbackState; + + return () => navigator.mediaSession.playbackState = 'none'; + }, [video.state.paused]); + + // Media Session Metadata + React.useEffect(() => { + if (!navigator.mediaSession) return; + + const metaItem = player.metaItem && player.metaItem.type === 'Ready' ? player.metaItem.content : null; + const videoId = player.selected ? player.selected.streamRequest.path.id : null; + const video = metaItem ? metaItem.videos.find(({ id }) => id === videoId) : null; + + const videoInfo = video && video.season && video.episode ? ` (${video.season}x${video.episode})`: null; + const videoTitle = video ? `${video.title}${videoInfo}` : null; + const metaTitle = metaItem ? metaItem.name : null; + const imageUrl = metaItem ? metaItem.logo : null; + + const title = videoTitle ?? metaTitle; + const artist = videoTitle ? metaTitle : undefined; + const artwork = imageUrl ? [{ src: imageUrl }] : undefined; + + if (title) { + navigator.mediaSession.metadata = new MediaMetadata({ + title, + artist, + artwork, + }); + } + }, [player.metaItem, player.selected]); + + // Media Session Actions + React.useEffect(() => { + if (!navigator.mediaSession) return; + + navigator.mediaSession.setActionHandler('play', onPlayRequested); + navigator.mediaSession.setActionHandler('pause', onPauseRequested); + + const nexVideoCallback = player.nextVideo ? onNextVideoRequested : null; + navigator.mediaSession.setActionHandler('nexttrack', nexVideoCallback); + }, [player.nextVideo, onPlayRequested, onPauseRequested, onNextVideoRequested]); + React.useLayoutEffect(() => { const onKeyDown = (event) => { switch (event.code) { @@ -547,36 +594,6 @@ const Player = ({ urlParams, queryParams }) => { break; } - case 'MediaPlayPause': { - if (!menusOpen && !nextVideoPopupOpen && video.state.paused !== null) { - event.preventDefault(); - if (video.state.paused) { - onPlayRequested(); - setSeeking(false); - } else { - onPauseRequested(); - } - } - - break; - } - case 'MediaPlay': { - if (!menusOpen && !nextVideoPopupOpen && video.state.paused === true) { - event.preventDefault(); - onPlayRequested(); - setSeeking(false); - } - - break; - } - case 'MediaPause': { - if (!menusOpen && !nextVideoPopupOpen && video.state.paused === false) { - event.preventDefault(); - onPauseRequested(); - } - - break; - } case 'ArrowRight': { if (!menusOpen && !nextVideoPopupOpen && video.state.time !== null) { const seekDuration = event.shiftKey ? settings.seekShortTimeDuration : settings.seekTimeDuration;