diff --git a/src/common/useShell.ts b/src/common/useShell.ts index 0471e38ab..3ecffe88e 100644 --- a/src/common/useShell.ts +++ b/src/common/useShell.ts @@ -27,6 +27,10 @@ export type WindowState = { state: number; }; +export type MediaStatus = { + paused: boolean; +}; + const createId = () => Math.floor(Math.random() * 9999) + 1; const useShell = () => { diff --git a/src/routes/Player/useMediaSession.ts b/src/routes/Player/useMediaSession.ts index 7a63423bd..05a1bc520 100644 --- a/src/routes/Player/useMediaSession.ts +++ b/src/routes/Player/useMediaSession.ts @@ -1,4 +1,6 @@ import { useEffect } from 'react'; +import { useShell } from 'stremio/common'; +import { MediaStatus } from 'stremio/common/useShell'; const useMediaSession = ( videoState: VideoState, @@ -7,20 +9,31 @@ const useMediaSession = ( onPauseRequested: () => void, onNextVideoRequested: () => void, ) => { - useEffect(() => { - if (!navigator.mediaSession) return; + const shell = useShell(); + // Playback state + useEffect(() => { const playbackState = !videoState.paused ? 'playing' : 'paused'; - navigator.mediaSession.playbackState = playbackState; + + if (navigator.mediaSession) { + navigator.mediaSession.playbackState = playbackState; + } + + if (shell.active) { + shell.send('media.status', { + paused: !!videoState.paused, + }); + } return () => { - navigator.mediaSession.playbackState = 'none'; + if (navigator.mediaSession) { + navigator.mediaSession.playbackState = 'none'; + } }; }, [videoState.paused]); + // Metadata useEffect(() => { - if (!navigator.mediaSession) return; - const metaItem = player.metaItem && player.metaItem?.type === 'Ready' ? player.metaItem.content as MetaItemPlayer : null; const videoId = player.selected ? player.selected?.streamRequest?.path?.id : null; const video = metaItem?.videos.find(({ id }) => id === videoId); @@ -35,22 +48,45 @@ const useMediaSession = ( const artwork = imageUrl ? [{ src: imageUrl }] : undefined; if (title) { - navigator.mediaSession.metadata = new MediaMetadata({ - title, - artist, - artwork, - }); + if (navigator.mediaSession) { + navigator.mediaSession.metadata = new MediaMetadata({ + title, + artist, + artwork, + }); + } + + if (shell.active) { + shell.send('media.metadata', { + title, + artist, + artUrl: imageUrl, + }); + } } }, [player.metaItem, player.selected]); + // Callbacks useEffect(() => { - if (!navigator.mediaSession) return; - - navigator.mediaSession.setActionHandler('play', onPlayRequested); - navigator.mediaSession.setActionHandler('pause', onPauseRequested); + if (navigator.mediaSession) { + navigator.mediaSession.setActionHandler('play', onPlayRequested); + navigator.mediaSession.setActionHandler('pause', onPauseRequested); + } const nexVideoCallback = player.nextVideo ? onNextVideoRequested : null; - navigator.mediaSession.setActionHandler('nexttrack', nexVideoCallback); + if (navigator.mediaSession && nexVideoCallback) { + navigator.mediaSession.setActionHandler('nexttrack', nexVideoCallback); + } + + const onMediaStatus = ({ paused }: MediaStatus) => { + paused ? onPauseRequested() : onPlayRequested(); + }; + + shell.on('media.status', onMediaStatus); + + return () => { + shell.on('media.status', onMediaStatus); + }; }, [player.nextVideo, onPlayRequested, onPauseRequested, onNextVideoRequested]); };