From abacbf2b41b0c45fa46039b61deef3a954fe9e13 Mon Sep 17 00:00:00 2001 From: NoCrypt <57245077+NoCrypt@users.noreply.github.com> Date: Sat, 10 Aug 2024 20:49:19 +0700 Subject: [PATCH] feat: controls in pip on android by correctly implementing Media Session using external plugin --- capacitor/android/app/capacitor.build.gradle | 1 + .../android/app/src/main/AndroidManifest.xml | 1 + capacitor/android/capacitor.settings.gradle | 3 ++ capacitor/package.json | 1 + common/views/Player/MediaHandler.svelte | 32 ++++++++++--------- common/views/Player/Player.svelte | 28 ++++++++++++---- pnpm-lock.yaml | 12 +++++++ 7 files changed, 56 insertions(+), 22 deletions(-) diff --git a/capacitor/android/app/capacitor.build.gradle b/capacitor/android/app/capacitor.build.gradle index e868c8b..bb255f4 100644 --- a/capacitor/android/app/capacitor.build.gradle +++ b/capacitor/android/app/capacitor.build.gradle @@ -16,6 +16,7 @@ dependencies { implementation project(':capacitor-filesystem') implementation project(':capacitor-local-notifications') implementation project(':capacitor-status-bar') + implementation project(':jofr-capacitor-media-session') implementation project(':capacitor-nodejs') implementation project(':capacitor-plugin-safe-area') implementation project(':capacitor-volume-control') diff --git a/capacitor/android/app/src/main/AndroidManifest.xml b/capacitor/android/app/src/main/AndroidManifest.xml index b539c6f..843f525 100644 --- a/capacitor/android/app/src/main/AndroidManifest.xml +++ b/capacitor/android/app/src/main/AndroidManifest.xml @@ -54,6 +54,7 @@ + diff --git a/capacitor/android/capacitor.settings.gradle b/capacitor/android/capacitor.settings.gradle index 85780dc..bd07bcc 100644 --- a/capacitor/android/capacitor.settings.gradle +++ b/capacitor/android/capacitor.settings.gradle @@ -23,6 +23,9 @@ project(':capacitor-local-notifications').projectDir = new File('../../node_modu include ':capacitor-status-bar' project(':capacitor-status-bar').projectDir = new File('../../node_modules/@capacitor/status-bar/android') +include ':jofr-capacitor-media-session' +project(':jofr-capacitor-media-session').projectDir = new File('../../node_modules/@jofr/capacitor-media-session/android') + include ':capacitor-nodejs' project(':capacitor-nodejs').projectDir = new File('../../node_modules/capacitor-nodejs/android') diff --git a/capacitor/package.json b/capacitor/package.json index 2c98c1f..5a178ae 100644 --- a/capacitor/package.json +++ b/capacitor/package.json @@ -37,6 +37,7 @@ "@capacitor/ios": "^6.1.1", "@capacitor/local-notifications": "^6.0.0", "@capacitor/status-bar": "^6.0.0", + "@jofr/capacitor-media-session": "^4.0.0", "capacitor-nodejs": "https://github.com/hampoelz/Capacitor-NodeJS/releases/download/v1.0.0-beta.7/capacitor-nodejs.tgz", "capacitor-plugin-safe-area": "^3.0.3", "capacitor-volume-control": "^0.0.1", diff --git a/common/views/Player/MediaHandler.svelte b/common/views/Player/MediaHandler.svelte index 6b29e46..1d1e3b1 100644 --- a/common/views/Player/MediaHandler.svelte +++ b/common/views/Player/MediaHandler.svelte @@ -5,6 +5,7 @@ import { tick } from 'svelte' import { state } from '../WatchTogether/WatchTogether.svelte' import IPC from '@/modules/ipc.js' + import { SUPPORTS } from '@/modules/support.js'; const episodeRx = /Episode (\d+) - (.*)/ @@ -183,23 +184,24 @@ }) function setMediaSession (nowPlaying) { - if (typeof MediaMetadata === 'undefined') return const name = [nowPlaying.title, nowPlaying.episode, nowPlaying.episodeTitle, 'Migu'].filter(i => i).join(' - ') - - const metadata = - nowPlaying.thumbnail - ? new MediaMetadata({ - title: name, - artwork: [ - { - src: nowPlaying.thumbnail, - sizes: '256x256', - type: 'image/jpg' - } + + const metadata = { + title: nowPlaying.title, + album: nowPlaying.episodeTitle, + artist: 'Migu', + artwork: [ + { + src: nowPlaying.thumbnail ? nowPlaying.thumbnail : './logo_filled.png', + sizes: '256x256', + type: 'image/jpg' + } ] - }) - : new MediaMetadata({ title: name }) - navigator.mediaSession.metadata = metadata + } + + if (SUPPORTS.isAndroid) window.Capacitor.Plugins.MediaSession.setMetadata(metadata) + if (typeof MediaMetadata === 'undefined') return + navigator.mediaSession.metadata = new MediaMetadata(metadata) } function setDiscordRPC (np = nowPlaying.value) { diff --git a/common/views/Player/Player.svelte b/common/views/Player/Player.svelte index 0e692c9..ea9bf40 100644 --- a/common/views/Player/Player.svelte +++ b/common/views/Player/Player.svelte @@ -42,6 +42,7 @@ } function updatew2g () { + if (SUPPORTS.isAndroid) window.Capacitor.Plugins.MediaSession.setPlaybackState( {playbackState: paused ? 'paused' : 'playing'} ) w2gEmitter.emit('player', { time: Math.floor(currentTime), paused }) } @@ -282,6 +283,8 @@ } function playPause () { paused = !paused + if (SUPPORTS.isAndroid) window.Capacitor.Plugins.MediaSession.setPlaybackState( {playbackState: paused ? 'paused' : 'playing'} ) + resetImmerse() } function toggleMute () { @@ -735,20 +738,31 @@ resetImmerse() }, 150) } - $: navigator.mediaSession?.setPositionState({ + + const mediaSession = navigator.mediaSession ? navigator.mediaSession : window.Capacitor.Plugins.MediaSession + $: mediaSession?.setPositionState({ duration: Math.max(0, safeduration || 0), playbackRate: 1, position: Math.max(0, Math.min(safeduration || 0, currentTime || 0)) }) if ('mediaSession' in navigator) { - navigator.mediaSession.setActionHandler('play', playPause) - navigator.mediaSession.setActionHandler('pause', playPause) - navigator.mediaSession.setActionHandler('nexttrack', playNext) - navigator.mediaSession.setActionHandler('previoustrack', playLast) - navigator.mediaSession.setActionHandler('seekforward', forward) - navigator.mediaSession.setActionHandler('seekbackward', rewind) + mediaSession.setActionHandler('play', playPause) + mediaSession.setActionHandler('pause', playPause) + mediaSession.setActionHandler('nexttrack', playNext) + mediaSession.setActionHandler('previoustrack', playLast) + mediaSession.setActionHandler('seekforward', forward) + mediaSession.setActionHandler('seekbackward', rewind) + } else { + mediaSession.setActionHandler({action: 'play'}, playPause) + mediaSession.setActionHandler({action: 'pause'}, playPause) + mediaSession.setActionHandler({action: 'nexttrack'}, playNext) + mediaSession.setActionHandler({action: 'previoustrack'}, playLast) + mediaSession.setActionHandler({action: 'seekforward'}, forward) + mediaSession.setActionHandler({action: 'seekbackward'}, rewind) } + + let stats = null let requestCallback = null function toggleStats () { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d88dcaf..00fe22d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -96,6 +96,9 @@ importers: '@capacitor/status-bar': specifier: ^6.0.0 version: 6.0.0(@capacitor/core@6.1.1) + '@jofr/capacitor-media-session': + specifier: ^4.0.0 + version: 4.0.0(@capacitor/core@6.1.1) capacitor-nodejs: specifier: https://github.com/hampoelz/Capacitor-NodeJS/releases/download/v1.0.0-beta.7/capacitor-nodejs.tgz version: https://github.com/hampoelz/Capacitor-NodeJS/releases/download/v1.0.0-beta.7/capacitor-nodejs.tgz(@capacitor/core@6.1.1) @@ -674,6 +677,11 @@ packages: resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} + '@jofr/capacitor-media-session@4.0.0': + resolution: {integrity: sha512-IGfc6BUzeeR0sJkk+0/jij3l0h78NdTqPMwBc9LXZrojtiqNtg4tw3CnIkYGccwZ/0glV3hPl8HVNTElOPVCyg==} + peerDependencies: + '@capacitor/core': ^6.0.0 + '@jridgewell/gen-mapping@0.3.5': resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} engines: {node: '>=6.0.0'} @@ -6173,6 +6181,10 @@ snapshots: wrap-ansi: 8.1.0 wrap-ansi-cjs: wrap-ansi@7.0.0 + '@jofr/capacitor-media-session@4.0.0(@capacitor/core@6.1.1)': + dependencies: + '@capacitor/core': 6.1.1 + '@jridgewell/gen-mapping@0.3.5': dependencies: '@jridgewell/set-array': 1.2.1