From 0f97cda0a753476f0659fce5fc150bf9c64a3861 Mon Sep 17 00:00:00 2001 From: WardPearce Date: Sat, 8 Nov 2025 14:36:57 +1300 Subject: [PATCH] Fix for mini player only working once per video --- materialious/electron/package-lock.json | 4 +- materialious/src/lib/store.ts | 15 ++- materialious/src/routes/(app)/+layout.svelte | 3 +- .../routes/(app)/watch/[slug]/+page.svelte | 103 ++++++++++-------- 4 files changed, 67 insertions(+), 58 deletions(-) diff --git a/materialious/electron/package-lock.json b/materialious/electron/package-lock.json index 357eb009..2b1650c8 100644 --- a/materialious/electron/package-lock.json +++ b/materialious/electron/package-lock.json @@ -1,12 +1,12 @@ { "name": "Materialious", - "version": "1.11.4", + "version": "1.11.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "Materialious", - "version": "1.11.4", + "version": "1.11.5", "license": "MIT", "dependencies": { "@capacitor-community/electron": "^5.0.0", diff --git a/materialious/src/lib/store.ts b/materialious/src/lib/store.ts index f4e6556f..b8f1c98e 100644 --- a/materialious/src/lib/store.ts +++ b/materialious/src/lib/store.ts @@ -62,14 +62,13 @@ export const playerStatisticsByDefault = persisted('playerStatistics', false); export const playerMiniplayerEnabled = persisted('miniplayerEnabled', true); export const playerPlaylistHistory: Writable = writable([]); -export const playerState: Writable< - | { - data: { video: VideoPlay; content: PhasedDescription; playlistId: string | null }; - isSyncing?: boolean; - playerElement?: HTMLMediaElement | undefined; - } - | undefined -> = writable(undefined); +export interface PlayerState { + data: { video: VideoPlay; content: PhasedDescription; playlistId: string | null }; + isSyncing?: boolean; + playerElement?: HTMLMediaElement | undefined; +} + +export const playerState: Writable = writable(undefined); export const playertheatreModeIsActive = writable(false); export const returnYtDislikesStore = persisted('returnYtDislikes', false); diff --git a/materialious/src/routes/(app)/+layout.svelte b/materialious/src/routes/(app)/+layout.svelte index 83b18f98..f29db09b 100644 --- a/materialious/src/routes/(app)/+layout.svelte +++ b/materialious/src/routes/(app)/+layout.svelte @@ -487,7 +487,7 @@ .pip { position: fixed; bottom: 10px; - right: 0; + right: 30px; width: 400px; z-index: 99999; padding: 1em; @@ -506,6 +506,7 @@ .pip { width: 100%; bottom: 100px; + right: 0px; } .pip > .pip-info > .player { diff --git a/materialious/src/routes/(app)/watch/[slug]/+page.svelte b/materialious/src/routes/(app)/watch/[slug]/+page.svelte index 46db00de..0556d846 100644 --- a/materialious/src/routes/(app)/watch/[slug]/+page.svelte +++ b/materialious/src/routes/(app)/watch/[slug]/+page.svelte @@ -25,7 +25,8 @@ playlistCacheStore, playlistSettingsStore, syncPartyConnectionsStore, - syncPartyPeerStore + syncPartyPeerStore, + type PlayerState } from '$lib/store'; import ui from 'beercss'; import type { DataConnection } from 'peerjs'; @@ -71,7 +72,7 @@ let premiereTime = $state(''); let premiereUpdateInterval: NodeJS.Timeout; - if (!data.video.premiereTimestamp) { + if (!data.video.premiereTimestamp && !$playerState) { playerState.set({ data: data, isSyncing: $syncPartyPeerStore !== null @@ -223,53 +224,61 @@ playerSyncEvents(connections[connections.length - 1]); }); - onMount(() => { + async function load(state: PlayerState) { + playerElement = state.playerElement; + + if (data.playlistId) { + await goToCurrentPlaylistItem(); + playerPlaylistHistory.set([data.video.videoId, ...$playerPlaylistHistory]); + } + + if ($interfaceAutoExpandChapters) { + expandSummery('chapter-section'); + } + + if ($syncPartyConnectionsStore) { + $syncPartyConnectionsStore.forEach((conn) => { + playerSyncEvents(conn); + }); + } + + if (playerElement) { + playerElement.addEventListener('timeupdate', () => { + if (!playerElement) return; + playerCurrentTime = playerElement.currentTime; + }); + } + + if (data.video.premiereTimestamp) { + premiereTime = humanFriendlyTimestamp(data.video.premiereTimestamp); + premiereUpdateInterval = setInterval(async () => { + data = await getWatchDetails(data.video.videoId, page.url); + + if (data.video.premiereTimestamp) { + premiereTime = humanFriendlyTimestamp(data.video.premiereTimestamp); + } else { + clearInterval(premiereUpdateInterval); + playerState.set({ ...$playerState, data: { ...data } }); + } + }, 60000); + } + } + + onMount(async () => { // Required due to needing the playerElement - let loadedPlayer = false; - playerState.subscribe(async (updatedPlayerState) => { - if (!updatedPlayerState?.playerElement || loadedPlayer) { - return; - } - loadedPlayer = true; + if ($playerState?.playerElement) { + await load($playerState); + } else { + let loadedPlayer = false; + playerState.subscribe(async (updatedPlayerState) => { + if (!updatedPlayerState?.playerElement || loadedPlayer) { + return; + } + loadedPlayer = true; - playerElement = updatedPlayerState.playerElement; - - if (data.playlistId) { - await goToCurrentPlaylistItem(); - playerPlaylistHistory.set([data.video.videoId, ...$playerPlaylistHistory]); - } - - if ($interfaceAutoExpandChapters) { - expandSummery('chapter-section'); - } - - if ($syncPartyConnectionsStore) { - $syncPartyConnectionsStore.forEach((conn) => { - playerSyncEvents(conn); - }); - } - - if (playerElement) { - playerElement.addEventListener('timeupdate', () => { - if (!playerElement) return; - playerCurrentTime = playerElement.currentTime; - }); - } - - if (data.video.premiereTimestamp) { - premiereTime = humanFriendlyTimestamp(data.video.premiereTimestamp); - premiereUpdateInterval = setInterval(async () => { - data = await getWatchDetails(data.video.videoId, page.url); - - if (data.video.premiereTimestamp) { - premiereTime = humanFriendlyTimestamp(data.video.premiereTimestamp); - } else { - clearInterval(premiereUpdateInterval); - playerState.set({ ...$playerState, data: { ...data } }); - } - }, 60000); - } - }); + await load(updatedPlayerState); + }); + } }); onDestroy(() => {