From ca135cc7f8068442fcf76f0c826d478ec2435387 Mon Sep 17 00:00:00 2001 From: Raphael Wickihalder Date: Sun, 29 May 2022 11:54:47 +0200 Subject: [PATCH] Integrate media session api --- ui/component/viewers/videoViewer/index.js | 11 ++++++++ .../videoViewer/internal/videojs-events.jsx | 25 +++++++++++++++++++ .../viewers/videoViewer/internal/videojs.jsx | 7 +++--- ui/component/viewers/videoViewer/view.jsx | 3 +++ 4 files changed, 43 insertions(+), 3 deletions(-) diff --git a/ui/component/viewers/videoViewer/index.js b/ui/component/viewers/videoViewer/index.js index daca4d43b..e0e958402 100644 --- a/ui/component/viewers/videoViewer/index.js +++ b/ui/component/viewers/videoViewer/index.js @@ -40,6 +40,16 @@ const select = (state, props) => { const uri = props.uri; const claim = selectClaimForUri(state, uri); + const { signing_channel } = claim || {}; + let channelTitle = null; + if (signing_channel) { + const { value, name } = signing_channel; + if (value && value.title) { + channelTitle = value.title; + } else { + channelTitle = name; + } + } // TODO: eventually this should be received from DB and not local state (https://github.com/lbryio/lbry-desktop/issues/6796) const position = urlParams.get('t') !== null ? urlParams.get('t') : selectContentPositionForUri(state, uri); @@ -74,6 +84,7 @@ const select = (state, props) => { videoPlaybackRate: selectClientSetting(state, SETTINGS.VIDEO_PLAYBACK_RATE), thumbnail: selectThumbnailForUri(state, uri), claim, + channelTitle, homepageData: selectHomepageData(state), authenticated: selectUserVerifiedEmail(state), shareTelemetry: IS_WEB || selectDaemonSettings(state).share_usage_data, diff --git a/ui/component/viewers/videoViewer/internal/videojs-events.jsx b/ui/component/viewers/videoViewer/internal/videojs-events.jsx index ab9f6dbda..87b4d1f3b 100644 --- a/ui/component/viewers/videoViewer/internal/videojs-events.jsx +++ b/ui/component/viewers/videoViewer/internal/videojs-events.jsx @@ -19,6 +19,7 @@ const VideoJsEvents = ({ claimId, userId, claimValues, + channelTitle, embedded, uri, doAnalyticsView, @@ -35,6 +36,7 @@ const VideoJsEvents = ({ claimId: ?string, userId: ?number, claimValues: any, + channelTitle: string, embedded: boolean, uri: string, doAnalyticsView: (string, number) => any, @@ -109,6 +111,8 @@ const VideoJsEvents = ({ function onInitialPlay() { const player = playerRef.current; + console.log('onInitialPlay'); + updateMediaSession(); const bigPlayButton = document.querySelector('.vjs-big-play-button'); if (bigPlayButton) bigPlayButton.style.setProperty('display', 'none'); @@ -198,6 +202,27 @@ const VideoJsEvents = ({ } } + function updateMediaSession() { + if ('mediaSession' in navigator) { + const player = playerRef.current; + // $FlowFixMe + navigator.mediaSession.metadata = new window.MediaMetadata({ + title: claimValues.title, + artist: channelTitle, + artwork: [{ src: claimValues.thumbnail.url }], + }); + + // $FlowFixMe + navigator.mediaSession.setActionHandler('seekbackward', function () { + player.currentTime(Math.max(0, player.currentTime() - 10)); + }); + // $FlowFixMe + navigator.mediaSession.setActionHandler('seekforward', function () { + player.currentTime(Math.max(0, player.currentTime() + 10)); + }); + } + } + useEffect(() => { const player = playerRef.current; if (replay && player) { diff --git a/ui/component/viewers/videoViewer/internal/videojs.jsx b/ui/component/viewers/videoViewer/internal/videojs.jsx index 44b04bec1..d4b43b67f 100644 --- a/ui/component/viewers/videoViewer/internal/videojs.jsx +++ b/ui/component/viewers/videoViewer/internal/videojs.jsx @@ -77,7 +77,7 @@ type Props = { autoplay: boolean, claimId: ?string, title: ?string, - channelName: ?string, + channelTitle: string, embedded: boolean, internalFeatureEnabled: ?boolean, isAudio: boolean, @@ -135,7 +135,7 @@ export default React.memo(function VideoJs(props: Props) { autoplay, claimId, title, - channelName, + channelTitle, embedded, // internalFeatureEnabled, // for people on the team to test new features internally isAudio, @@ -210,6 +210,7 @@ export default React.memo(function VideoJs(props: Props) { uri, playerServerRef, isLivestreamClaim, + channelTitle, }); const videoJsOptions = { @@ -243,7 +244,7 @@ export default React.memo(function VideoJs(props: Props) { techOrder: ['chromecast', 'html5'], chromecast: { requestTitleFn: (src) => title || '', - requestSubtitleFn: (src) => channelName || '', + requestSubtitleFn: (src) => channelTitle || '', }, bigPlayButton: embedded, // only show big play button if embedded liveui: isLivestreamClaim, diff --git a/ui/component/viewers/videoViewer/view.jsx b/ui/component/viewers/videoViewer/view.jsx index ce16a59b0..85dac444f 100644 --- a/ui/component/viewers/videoViewer/view.jsx +++ b/ui/component/viewers/videoViewer/view.jsx @@ -75,6 +75,7 @@ type Props = { doToast: ({ message: string, linkText: string, linkTarget: string }) => void, doSetContentHistoryItem: (uri: string) => void, doClearContentHistoryUri: (uri: string) => void, + channelTitle: string, }; /* @@ -92,6 +93,7 @@ function VideoViewer(props: Props) { thumbnail, position, claim, + channelTitle, uri, muted, volume, @@ -496,6 +498,7 @@ function VideoViewer(props: Props) { claimId={claimId} title={claim && ((claim.value && claim.value.title) || claim.name)} channelName={channelName} + channelTitle={channelTitle} userId={userId} allowPreRoll={!authenticated} // TODO: pull this into ads functionality so it's self contained internalFeatureEnabled={internalFeature}