diff --git a/.github/workflows/prod-android.yml b/.github/workflows/prod-android.yml index b882b216..d246c46d 100644 --- a/.github/workflows/prod-android.yml +++ b/.github/workflows/prod-android.yml @@ -5,8 +5,8 @@ on: branches: [main] paths-ignore: - "**/*.md" - - "fastline/**" - - "materialious/src/i18n/locales/**" + - "./fastline/**" + - "./materialious/src/lib/i18n/locales/**" workflow_dispatch: diff --git a/.github/workflows/prod-desktop.yml b/.github/workflows/prod-desktop.yml index b10ee3f8..205813aa 100644 --- a/.github/workflows/prod-desktop.yml +++ b/.github/workflows/prod-desktop.yml @@ -5,8 +5,8 @@ on: branches: [main] paths-ignore: - "**/*.md" - - "fastline/**" - - "materialious/src/i18n/locales/**" + - "./fastline/**" + - "./materialious/src/lib/i18n/locales/**" workflow_dispatch: diff --git a/.github/workflows/prod-web.yml b/.github/workflows/prod-web.yml index ee0c8b2d..927e0465 100644 --- a/.github/workflows/prod-web.yml +++ b/.github/workflows/prod-web.yml @@ -6,8 +6,8 @@ on: - main paths-ignore: - "**/*.md" - - "fastline/**" - - "materialious/src/i18n/locales/**" + - "./fastline/**" + - "./materialious/src/lib/i18n/locales/**" jobs: web-build: diff --git a/README.md b/README.md index 45eadaef..a8566fb6 100644 --- a/README.md +++ b/README.md @@ -234,13 +234,13 @@ Help [translate Materialious via Weblate](https://toolate.othing.xyz/projects/ma # Special thanks to - [SecularSteve](https://github.com/SecularSteve) for creating Materialious' logo. -- [Invidious](https://github.com/iv-org) -- [Clipious](https://github.com/lamarios/clipious) for inspiration & a good source for learning more about undocumented Invidious routes. +- [Invidious](https://github.com/iv-org). +- [Clipious](https://github.com/lamarios/clipious) for inspiration & references to undocumented Invidious routes. - [Beer CSS](https://github.com/beercss/beercss) (Especially the [YouTube template](https://github.com/beercss/beercss/tree/main/src/youtube) what was used as the base for Materialious.) -- Every dependency in [package.json](/materialious/package.json). - [LuanRT](https://github.com/LuanRT) for YouTube.js & SABR implementation. - [FreeTube](https://github.com/FreeTubeApp/FreeTube) for their subtitle fix. - [spotube](https://github.com/KRTirtho/spotube) for using their README layout for local installation. +- Every dependency in [package.json](/materialious/package.json). # Developers - [How Materialious is built](./docs/BUILDING.md) diff --git a/materialious/android/app/build.gradle b/materialious/android/app/build.gradle index 04b0065a..3b0daeee 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 134 - versionName "1.9.17" + versionCode 135 + versionName "1.9.18" 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/electron/materialious.metainfo.xml b/materialious/electron/materialious.metainfo.xml index 773eb01f..bb88cc20 100644 --- a/materialious/electron/materialious.metainfo.xml +++ b/materialious/electron/materialious.metainfo.xml @@ -69,7 +69,11 @@ - + + + https://github.com/Materialious/Materialious/releases/tag/1.9.18 + + https://github.com/Materialious/Materialious/releases/tag/1.9.17 diff --git a/materialious/electron/package-lock.json b/materialious/electron/package-lock.json index 979e0c78..fde74e4d 100644 --- a/materialious/electron/package-lock.json +++ b/materialious/electron/package-lock.json @@ -1,12 +1,12 @@ { "name": "Materialious", - "version": "1.9.17", + "version": "1.9.18", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "Materialious", - "version": "1.9.17", + "version": "1.9.18", "license": "MIT", "dependencies": { "@capacitor-community/electron": "^5.0.0", diff --git a/materialious/electron/package.json b/materialious/electron/package.json index 3b16e650..10a1d81a 100644 --- a/materialious/electron/package.json +++ b/materialious/electron/package.json @@ -1,6 +1,6 @@ { "name": "Materialious", - "version": "1.9.17", + "version": "1.9.18", "description": "Modern material design for Invidious.", "author": { "name": "Ward Pearce", @@ -44,4 +44,4 @@ "capacitor", "electron" ] -} +} \ No newline at end of file diff --git a/materialious/package.json b/materialious/package.json index fca37748..abe87fbe 100644 --- a/materialious/package.json +++ b/materialious/package.json @@ -1,6 +1,6 @@ { "name": "materialious", - "version": "1.9.17", + "version": "1.9.18", "private": true, "scripts": { "dev": "vite dev", diff --git a/materialious/src/lib/api/index.ts b/materialious/src/lib/api/index.ts index d9d80f98..c3e40d9d 100644 --- a/materialious/src/lib/api/index.ts +++ b/materialious/src/lib/api/index.ts @@ -420,13 +420,18 @@ export async function getThumbnail( return URL.createObjectURL(await resp.blob()); } +function buildApiExtendedAuthHeaders(): Record> { + const authToken = get(authStore)?.token ?? ''; + return { headers: { Authorization: `Bearer ${authToken.replace('SID=', '')}` } }; +} + export async function getVideoProgress( videoId: string, fetchOptions: RequestInit = {} ): Promise { const resp = await fetchErrorHandle( await fetch(`${get(synciousInstanceStore)}/video/${encodeURIComponent(videoId)}`, { - ...buildAuthHeaders(), + ...buildApiExtendedAuthHeaders(), ...fetchOptions }) ); @@ -439,7 +444,7 @@ export async function saveVideoProgress( time: number, fetchOptions: RequestInit = {} ) { - const headers: Record> = buildAuthHeaders(); + const headers: Record> = buildApiExtendedAuthHeaders(); headers['headers']['Content-type'] = 'application/json'; await fetchErrorHandle( @@ -458,7 +463,7 @@ export async function deleteVideoProgress(videoId: string, fetchOptions: Request await fetchErrorHandle( await fetch(`${get(synciousInstanceStore)}/video/${videoId}`, { method: 'DELETE', - ...buildAuthHeaders(), + ...buildApiExtendedAuthHeaders(), ...fetchOptions }) ); @@ -468,7 +473,7 @@ export async function deleteAllVideoProgress(fetchOptions: RequestInit = {}) { await fetchErrorHandle( await fetch(`${get(synciousInstanceStore)}/videos`, { method: 'DELETE', - ...buildAuthHeaders(), + ...buildApiExtendedAuthHeaders(), ...fetchOptions }) ); diff --git a/materialious/src/lib/components/Player.svelte b/materialious/src/lib/components/Player.svelte index 2b28dc35..6c91c8c5 100644 --- a/materialious/src/lib/components/Player.svelte +++ b/materialious/src/lib/components/Player.svelte @@ -29,6 +29,7 @@ playerAndroidLockOrientation, playerAutoplayNextByDefaultStore, playerAutoPlayStore, + playerCCByDefault, playerDefaultLanguage, playerDefaultPlaybackSpeed, playerDefaultQualityStore, @@ -313,6 +314,24 @@ return false; } + function toggleSubtitles() { + const isVisible = player.isTextTrackVisible(); + if (isVisible) { + player.setTextTrackVisibility(false); + } else { + const defaultLanguage = get(playerDefaultLanguage); + const langCode = ISO6391.getCode(defaultLanguage); + + const tracks = player.getTextTracks(); + const subtitleTrack = tracks.find((track) => track.language === langCode); + + if (subtitleTrack) { + player.selectTextTrack(subtitleTrack); + player.setTextTrackVisibility(true); + } + } + } + page.subscribe((pageUpdate) => loadTimeFromUrl(pageUpdate)); async function loadVideo() { @@ -359,6 +378,9 @@ } } + if (watchProgressTimeout) { + clearInterval(watchProgressTimeout); + } // Auto save watch progress every minute. watchProgressTimeout = setInterval(() => savePlayerPos(), 60000); setupSponsorSkip(); @@ -378,9 +400,7 @@ dashUrl += '?local=true'; } - await player.load(dashUrl); - - await loadPlayerPos(); + await player.load(dashUrl, await getLastPlayPos()); } else { if (data.video.fallbackPatch === 'youtubejs') { await player.load(data.video.dashUrl); @@ -396,6 +416,9 @@ restoreQualityPreference(); restoreDefaultLanguage(); + if ($playerCCByDefault) { + toggleSubtitles(); + } if ($playerDefaultPlaybackSpeed && playerElement) { playerElement.playbackRate = $playerDefaultPlaybackSpeed; @@ -541,21 +564,7 @@ } Mousetrap.bind('c', () => { - const isVisible = player.isTextTrackVisible(); - if (isVisible) { - player.setTextTrackVisibility(false); - } else { - const defaultLanguage = get(playerDefaultLanguage); - const langCode = ISO6391.getCode(defaultLanguage); - - const tracks = player.getTextTracks(); - const subtitleTrack = tracks.find((track) => track.language === langCode); - - if (subtitleTrack) { - player.selectTextTrack(subtitleTrack); - player.setTextTrackVisibility(true); - } - } + toggleSubtitles(); return false; }); @@ -582,6 +591,10 @@ return false; }); + playerElement.addEventListener('pause', async () => { + savePlayerPos(); + }); + playerElement.addEventListener('ended', async () => { if (!data.playlistId) { if ($playerAutoplayNextByDefaultStore) { @@ -650,8 +663,8 @@ } }); - async function loadPlayerPos() { - if (loadTimeFromUrl($page)) return; + async function getLastPlayPos(): Promise { + if (loadTimeFromUrl($page)) return 0; let toSetTime = 0; @@ -670,7 +683,7 @@ } } - if (toSetTime > 0 && playerElement) playerElement.currentTime = toSetTime; + return toSetTime; } function savePlayerPos() { @@ -713,16 +726,16 @@ } } + try { + savePlayerPos(); + } catch (error) {} + Mousetrap.unbind(['left', 'right', 'space', 'c', 'f', 'shift+left', 'shift+right']); if (watchProgressTimeout) { clearTimeout(watchProgressTimeout); } - try { - savePlayerPos(); - } catch (error) {} - HttpFetchPlugin.cacheManager.clearCache(); if (playerElementResizeObserver) { diff --git a/materialious/src/lib/components/Settings/Player.svelte b/materialious/src/lib/components/Settings/Player.svelte index 183a3510..860f95d7 100644 --- a/materialious/src/lib/components/Settings/Player.svelte +++ b/materialious/src/lib/components/Settings/Player.svelte @@ -9,6 +9,7 @@ playerAndroidLockOrientation, playerAutoPlayStore, playerAutoplayNextByDefaultStore, + playerCCByDefault, playerDefaultLanguage, playerDefaultPlaybackSpeed, playerDefaultQualityStore, @@ -133,6 +134,22 @@ {/if} +
+ +
+