diff --git a/materialious/android/app/build.gradle b/materialious/android/app/build.gradle index acb4b4ad..d4b619ab 100644 --- a/materialious/android/app/build.gradle +++ b/materialious/android/app/build.gradle @@ -7,8 +7,8 @@ android { applicationId "us.materialio.app" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 176 - versionName "1.12.4" + versionCode 177 + versionName "1.12.5" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" aaptOptions { // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps. diff --git a/materialious/android/app/capacitor.build.gradle b/materialious/android/app/capacitor.build.gradle index a4cf34b2..149e2450 100644 --- a/materialious/android/app/capacitor.build.gradle +++ b/materialious/android/app/capacitor.build.gradle @@ -16,6 +16,7 @@ dependencies { implementation project(':capacitor-preferences') implementation project(':capacitor-screen-orientation') implementation project(':capacitor-share') + implementation project(':capacitor-music-controls-plugin') implementation project(':capacitor-nodejs') } diff --git a/materialious/android/capacitor.settings.gradle b/materialious/android/capacitor.settings.gradle index 915df42d..6f462263 100644 --- a/materialious/android/capacitor.settings.gradle +++ b/materialious/android/capacitor.settings.gradle @@ -23,5 +23,8 @@ project(':capacitor-screen-orientation').projectDir = new File('../node_modules/ include ':capacitor-share' project(':capacitor-share').projectDir = new File('../node_modules/@capacitor/share/android') +include ':capacitor-music-controls-plugin' +project(':capacitor-music-controls-plugin').projectDir = new File('../node_modules/capacitor-music-controls-plugin/android') + include ':capacitor-nodejs' project(':capacitor-nodejs').projectDir = new File('../node_modules/capacitor-nodejs/android') diff --git a/materialious/electron/materialious.metainfo.xml b/materialious/electron/materialious.metainfo.xml index 66dbba9d..3e720ab4 100644 --- a/materialious/electron/materialious.metainfo.xml +++ b/materialious/electron/materialious.metainfo.xml @@ -73,7 +73,11 @@ - + + + https://github.com/Materialious/Materialious/releases/tag/1.12.5 + + https://github.com/Materialious/Materialious/releases/tag/1.12.4 diff --git a/materialious/electron/package-lock.json b/materialious/electron/package-lock.json index e673cb9b..5297bbb1 100644 --- a/materialious/electron/package-lock.json +++ b/materialious/electron/package-lock.json @@ -1,12 +1,12 @@ { "name": "Materialious", - "version": "1.12.4", + "version": "1.12.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "Materialious", - "version": "1.12.4", + "version": "1.12.5", "license": "MIT", "dependencies": { "@capacitor-community/electron": "^5.0.0", diff --git a/materialious/electron/package.json b/materialious/electron/package.json index ab78b666..d4cfc01d 100644 --- a/materialious/electron/package.json +++ b/materialious/electron/package.json @@ -1,6 +1,6 @@ { "name": "Materialious", - "version": "1.12.4", + "version": "1.12.5", "description": "Modern material design for Invidious.", "author": { "name": "Ward Pearce", diff --git a/materialious/package-lock.json b/materialious/package-lock.json index 7484baf3..ad9cac84 100644 --- a/materialious/package-lock.json +++ b/materialious/package-lock.json @@ -1,12 +1,12 @@ { "name": "materialious", - "version": "1.12.4", + "version": "1.12.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "materialious", - "version": "1.12.4", + "version": "1.12.5", "hasInstallScript": true, "dependencies": { "@capacitor-community/electron": "^5.0.1", @@ -23,6 +23,7 @@ "@macfja/svelte-persistent-store": "^2.4.2", "beercss": "^3.13.1", "bgutils-js": "^3.2.0", + "capacitor-music-controls-plugin": "^6.1.0", "capacitor-nodejs": "https://github.com/hampoelz/capacitor-nodejs/releases/download/v1.0.0-beta.9/capacitor-nodejs.tgz", "dayjs": "^1.11.19", "dexie": "^4.2.1", @@ -4728,6 +4729,24 @@ ], "license": "CC-BY-4.0" }, + "node_modules/capacitor-music-controls-plugin": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/capacitor-music-controls-plugin/-/capacitor-music-controls-plugin-6.1.0.tgz", + "integrity": "sha512-j9NwUtUqiIAJQx+t8Zmf/zbYi10eQ37nrXIPbdnYA0B80sCXuX4MGdO+DTkyXCxP/c8BpM5rAJUqR9hZyTnSyQ==", + "license": "MIT", + "dependencies": { + "@capacitor/core": "^6.0.0" + } + }, + "node_modules/capacitor-music-controls-plugin/node_modules/@capacitor/core": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@capacitor/core/-/core-6.2.1.tgz", + "integrity": "sha512-urZwxa7hVE/BnA18oCFAdizXPse6fCKanQyEqpmz6cBJ2vObwMpyJDG5jBeoSsgocS9+Ax+9vb4ducWJn0y2qQ==", + "license": "MIT", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/capacitor-nodejs": { "version": "1.0.0-beta.9", "resolved": "https://github.com/hampoelz/capacitor-nodejs/releases/download/v1.0.0-beta.9/capacitor-nodejs.tgz", diff --git a/materialious/package.json b/materialious/package.json index 6a9982d7..06e17316 100644 --- a/materialious/package.json +++ b/materialious/package.json @@ -1,6 +1,6 @@ { "name": "materialious", - "version": "1.12.4", + "version": "1.12.5", "private": true, "scripts": { "dev": "vite dev", @@ -55,6 +55,7 @@ "@macfja/svelte-persistent-store": "^2.4.2", "beercss": "^3.13.1", "bgutils-js": "^3.2.0", + "capacitor-music-controls-plugin": "^6.1.0", "capacitor-nodejs": "https://github.com/hampoelz/capacitor-nodejs/releases/download/v1.0.0-beta.9/capacitor-nodejs.tgz", "dayjs": "^1.11.19", "dexie": "^4.2.1", @@ -74,4 +75,4 @@ "svelte-infinite-loading": "^1.4.0", "youtubei.js": "^16.0.1" } -} \ No newline at end of file +} diff --git a/materialious/src/lib/components/Player.svelte b/materialious/src/lib/components/Player.svelte index 4af75e8f..e816bb6c 100644 --- a/materialious/src/lib/components/Player.svelte +++ b/materialious/src/lib/components/Player.svelte @@ -12,6 +12,7 @@ import Mousetrap from 'mousetrap'; import 'shaka-player/dist/controls.css'; import '$lib/css/shaka-player-theme.css'; + import { CapacitorMusicControls } from 'capacitor-music-controls-plugin'; import shaka from 'shaka-player/dist/shaka-player.ui'; import { SponsorBlock, type Category, type Segment } from 'sponsorblock-api'; import { onDestroy, onMount, tick } from 'svelte'; @@ -570,7 +571,55 @@ await androidHandleRotate(); - if ('mediaSession' in navigator) { + if (Capacitor.getPlatform() === 'android') { + await CapacitorMusicControls.create({ + track: data.video.title, + artist: data.video.author, + cover: getBestThumbnail(data.video.videoThumbnails, 800, 800), + hasPrev: data.playlistId !== null, + hasNext: data.playlistId !== null, + isPlaying: true, + hasClose: true, + dismissable: true, + playIcon: 'media_play', + pauseIcon: 'media_pause', + prevIcon: 'media_prev', + nextIcon: 'media_next', + closeIcon: 'media_close', + notificationIcon: 'notification', + ticker: `Now playing "${data.video.title}"` + }); + + // @ts-expect-error: Is handle correctly via https://github.com/ingageco/capacitor-music-controls-plugin + document.addEventListener('controlsNotification', (event: { message: string }) => { + if ( + event.message === 'music-controls-headset-unplugged' || + event.message === 'music-controls-pause' + ) { + playerElement?.pause(); + return; + } else if (event.message === 'music-controls-play') { + playerElement?.play(); + return; + } + + if (data.playlistId) { + if (event.message === 'music-controls-next') { + goToNextVideo(data.video, data.playlistId); + } else if (event.message === 'music-controls-previous') { + goToPreviousVideo(data.playlistId); + } + } + }); + + playerElement?.addEventListener('play', () => { + CapacitorMusicControls.updateIsPlaying({ isPlaying: true }); + }); + + playerElement?.addEventListener('pause', () => { + CapacitorMusicControls.updateIsPlaying({ isPlaying: false }); + }); + } else if ('mediaSession' in navigator) { const metadataArtwork: MediaImage[] = []; data.video.videoThumbnails.forEach((thumbnail) => { metadataArtwork.push({ @@ -800,14 +849,18 @@ } onDestroy(async () => { - if (Capacitor.getPlatform() === 'android' && !$isAndroidTvStore) { - document.removeEventListener('fullscreenchange', onAndroidFullscreenChange); + if (Capacitor.getPlatform() === 'android') { + if (!$isAndroidTvStore) { + document.removeEventListener('fullscreenchange', onAndroidFullscreenChange); - if (originalOrigination) { - await ScreenOrientation.lock({ - orientation: originalOrigination.type - }); + if (originalOrigination) { + await ScreenOrientation.lock({ + orientation: originalOrigination.type + }); + } } + + await CapacitorMusicControls.destroy(); } try { diff --git a/materialious/src/lib/store.ts b/materialious/src/lib/store.ts index 9014d285..7c1ee505 100644 --- a/materialious/src/lib/store.ts +++ b/materialious/src/lib/store.ts @@ -13,6 +13,9 @@ import type { TitleCase } from './letterCasing'; import { serialize, deserialize } from '@macfja/serializer'; import type { Channel, + ChannelContentPlaylists, + ChannelContentVideos, + ChannelPage, HashTag, Playlist, PlaylistPage, @@ -334,3 +337,10 @@ export const playlistCacheStore: Writable<{ }> = writable({}); export const isAndroidTvStore: Writable = writable(false); + +export const channelCacheStore: Writable<{ + [key: string]: { + channel: ChannelPage; + displayContent: { [key: string]: ChannelContentVideos | ChannelContentPlaylists }; + }; +}> = writable({}); diff --git a/materialious/src/routes/(app)/+layout.svelte b/materialious/src/routes/(app)/+layout.svelte index af6a5df4..3459f339 100644 --- a/materialious/src/routes/(app)/+layout.svelte +++ b/materialious/src/routes/(app)/+layout.svelte @@ -411,13 +411,24 @@ >
{#if playerIsPip} - -
+
+ + +
{/if}
{#key $playerState.data.video.videoId} @@ -426,17 +437,6 @@
{#if playerIsPip} - -