From ee6ab56c790a43b60ee2728a46d12994514396b8 Mon Sep 17 00:00:00 2001 From: Lenny Angst Date: Thu, 11 Dec 2025 21:59:00 +0000 Subject: [PATCH 01/17] Translated using Weblate (German) Currently translated at 100.0% (174 of 174 strings) Translation: Materialious/Materialious Translate-URL: https://toolate.othing.xyz/projects/materialious/materialious/de/ --- materialious/src/lib/i18n/locales/de.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/materialious/src/lib/i18n/locales/de.json b/materialious/src/lib/i18n/locales/de.json index 5214269b..8e5e5fc7 100644 --- a/materialious/src/lib/i18n/locales/de.json +++ b/materialious/src/lib/i18n/locales/de.json @@ -205,5 +205,7 @@ }, "newest": "Neuste", "oldest": "Älteste", - "popular": "Populär" + "popular": "Populär", + "favouriteChannel": "Kanal favorisieren", + "unfavouriteChannel": "Kanal entfavorisieren" } From 87cbf84f6bbfaf0c7b3db1604a8cfaeb03b4595b Mon Sep 17 00:00:00 2001 From: Lenny Angst Date: Thu, 11 Dec 2025 21:59:17 +0000 Subject: [PATCH 02/17] Translated using Weblate (Alemannic) Currently translated at 100.0% (174 of 174 strings) Translation: Materialious/Materialious Translate-URL: https://toolate.othing.xyz/projects/materialious/materialious/gsw/ --- materialious/src/lib/i18n/locales/gsw.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/materialious/src/lib/i18n/locales/gsw.json b/materialious/src/lib/i18n/locales/gsw.json index 3f3da4a9..4c31b9bc 100644 --- a/materialious/src/lib/i18n/locales/gsw.json +++ b/materialious/src/lib/i18n/locales/gsw.json @@ -205,5 +205,7 @@ }, "newest": "Neusti", "oldest": "Ältisti", - "popular": "Populär" + "popular": "Populär", + "favouriteChannel": "Kanal favorisiere", + "unfavouriteChannel": "Kanal entfavorisiere" } From 6449919b1ded5b1329a4a11b5b094eebb1a96318 Mon Sep 17 00:00:00 2001 From: Ghost of Sparta Date: Sun, 14 Dec 2025 09:32:35 +0000 Subject: [PATCH 03/17] Translated using Weblate (Hungarian) Currently translated at 100.0% (174 of 174 strings) Translation: Materialious/Materialious Translate-URL: https://toolate.othing.xyz/projects/materialious/materialious/hu/ --- materialious/src/lib/i18n/locales/hu.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/materialious/src/lib/i18n/locales/hu.json b/materialious/src/lib/i18n/locales/hu.json index f81f56da..f1e6c4a9 100644 --- a/materialious/src/lib/i18n/locales/hu.json +++ b/materialious/src/lib/i18n/locales/hu.json @@ -205,5 +205,7 @@ }, "newest": "Legújabb", "oldest": "Legrégebbi", - "popular": "Népszerű" + "popular": "Népszerű", + "favouriteChannel": "Csatorna kedvelése", + "unfavouriteChannel": "Csatorna eltávolítása a kedvencekből" } From e9eadde68c2848576e37e541e0679d93148e879a Mon Sep 17 00:00:00 2001 From: Yurt Page Date: Mon, 15 Dec 2025 22:21:28 +0000 Subject: [PATCH 04/17] Translated using Weblate (Russian) Currently translated at 100.0% (174 of 174 strings) Translation: Materialious/Materialious Translate-URL: https://toolate.othing.xyz/projects/materialious/materialious/ru/ --- materialious/src/lib/i18n/locales/ru.json | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/materialious/src/lib/i18n/locales/ru.json b/materialious/src/lib/i18n/locales/ru.json index a3b229cc..7046f085 100644 --- a/materialious/src/lib/i18n/locales/ru.json +++ b/materialious/src/lib/i18n/locales/ru.json @@ -75,7 +75,8 @@ "materialiousLink": "Скопировать ссылку на Materialious", "invidiousRedirect": "Скопировать ссылку на сервер Invidious", "youtubeLink": "Скопировать ссылку на Youtube", - "includeTimestamp": "С отметкой времени" + "includeTimestamp": "С отметкой времени", + "copiedSuccess": "Скопированно в буфер обмена" }, "download": "Скачать", "downloadSteps": { @@ -176,7 +177,8 @@ "companionUrl": "URL-адрес компаньона", "expandChapters": "Раскрывать главы по умолчанию", "disableAutoUpdate": "Отключить автоматические обновления", - "about": "О приложении" + "about": "О приложении", + "androidNativeShare": "Использовать native share" }, "subscribe": "Подписаться", "invalidInstance": "Проверьте URL-адрес. Если он правильный, то возможно сервер сейчас недоступен или не поддерживает сторонние клиенты.", @@ -203,5 +205,7 @@ "contributors": "Участники", "newest": "Сначала новые", "oldest": "Сначала старые", - "popular": "Популярные" + "popular": "Популярные", + "favouriteChannel": "Любимый канал", + "unfavouriteChannel": "Нелюбимый канал" } From 754da046802f6308404f8afecff1fc55027640f2 Mon Sep 17 00:00:00 2001 From: Patrick Kempff Date: Sat, 20 Dec 2025 23:40:04 +0100 Subject: [PATCH 05/17] Fix thumbnail rendering for certain iOS devices --- materialious/src/lib/components/Thumbnail.svelte | 1 + 1 file changed, 1 insertion(+) diff --git a/materialious/src/lib/components/Thumbnail.svelte b/materialious/src/lib/components/Thumbnail.svelte index 2260246c..3c241f19 100644 --- a/materialious/src/lib/components/Thumbnail.svelte +++ b/materialious/src/lib/components/Thumbnail.svelte @@ -253,6 +253,7 @@ .thumbnail { width: 100%; overflow: hidden; + display: inline-block; } .thumbnail img { From b4ceb15cd68902cd2875cac73a490acea501d32a Mon Sep 17 00:00:00 2001 From: WardPearce Date: Mon, 22 Dec 2025 03:34:42 +1300 Subject: [PATCH 06/17] Bump version --- materialious/android/app/build.gradle | 4 ++-- materialious/electron/materialious.metainfo.xml | 6 +++++- materialious/electron/package.json | 2 +- materialious/package.json | 4 ++-- update_versions.py | 2 +- 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/materialious/android/app/build.gradle b/materialious/android/app/build.gradle index d4b619ab..dcbeaf08 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 177 - versionName "1.12.5" + versionCode 178 + versionName "1.12.6" 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 3e720ab4..678490f0 100644 --- a/materialious/electron/materialious.metainfo.xml +++ b/materialious/electron/materialious.metainfo.xml @@ -74,7 +74,11 @@ - + + + https://github.com/Materialious/Materialious/releases/tag/1.12.6 + + https://github.com/Materialious/Materialious/releases/tag/1.12.5 diff --git a/materialious/electron/package.json b/materialious/electron/package.json index d4cfc01d..d5df0fe8 100644 --- a/materialious/electron/package.json +++ b/materialious/electron/package.json @@ -1,6 +1,6 @@ { "name": "Materialious", - "version": "1.12.5", + "version": "1.12.6", "description": "Modern material design for Invidious.", "author": { "name": "Ward Pearce", diff --git a/materialious/package.json b/materialious/package.json index 06e17316..0e8a6af8 100644 --- a/materialious/package.json +++ b/materialious/package.json @@ -1,6 +1,6 @@ { "name": "materialious", - "version": "1.12.5", + "version": "1.12.6", "private": true, "scripts": { "dev": "vite dev", @@ -75,4 +75,4 @@ "svelte-infinite-loading": "^1.4.0", "youtubei.js": "^16.0.1" } -} +} \ No newline at end of file diff --git a/update_versions.py b/update_versions.py index 22fa28ad..1bfb48c8 100644 --- a/update_versions.py +++ b/update_versions.py @@ -3,7 +3,7 @@ import os import re from datetime import datetime -LATEST_VERSION = "1.12.5" +LATEST_VERSION = "1.12.6" RELEASE_DATE = datetime.now().strftime("%Y-%-m-%d") # Format: YYYY-M-D WORKING_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), "materialious") From 6ab7b87071fbff8c5cc750662b9af4a7bbcad59b Mon Sep 17 00:00:00 2001 From: WardPearce Date: Mon, 22 Dec 2025 03:48:49 +1300 Subject: [PATCH 07/17] Theatre mode fix --- materialious/electron/package-lock.json | 4 +- materialious/src/lib/components/Player.svelte | 40 ++++++++++++------- 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/materialious/electron/package-lock.json b/materialious/electron/package-lock.json index 5297bbb1..54131c68 100644 --- a/materialious/electron/package-lock.json +++ b/materialious/electron/package-lock.json @@ -1,12 +1,12 @@ { "name": "Materialious", - "version": "1.12.5", + "version": "1.12.6", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "Materialious", - "version": "1.12.5", + "version": "1.12.6", "license": "MIT", "dependencies": { "@capacitor-community/electron": "^5.0.0", diff --git a/materialious/src/lib/components/Player.svelte b/materialious/src/lib/components/Player.svelte index e816bb6c..6590999f 100644 --- a/materialious/src/lib/components/Player.svelte +++ b/materialious/src/lib/components/Player.svelte @@ -35,6 +35,7 @@ playerSavePlaybackPositionStore, playerState, playerStatisticsByDefault, + playertheatreModeIsActive, playerYouTubeJsFallback, sponsorBlockCategoriesStore, sponsorBlockDisplayToastStore, @@ -71,6 +72,7 @@ let player: shaka.Player; let shakaUi: shaka.ui.Overlay; let sabrAdapter: SabrStreamingAdapter | null; + let playerContainer: HTMLElement; const STORAGE_KEY_VOLUME = 'shaka-preferred-volume'; @@ -86,6 +88,10 @@ themeColorStore.subscribe(updateSeekBarTheme); darkModeStore.subscribe(updateSeekBarTheme); + playertheatreModeIsActive.subscribe(async () => { + await tick(); + updateVideoPlayerHeight(); + }); function restoreDefaultLanguage() { if (!$playerDefaultLanguage || $playerDefaultLanguage === 'original') { @@ -437,6 +443,16 @@ await loadVideo(); } + // Due to how our player is rendered in layout for stateful pip + // we calaculate player height to then allow children pages + // to wrap around it. + function updateVideoPlayerHeight() { + if (playerContainer) { + const height = playerContainer.getBoundingClientRect().height; + document.documentElement.style.setProperty('--video-player-height', `${height + 10}px`); + } + } + onMount(async () => { shaka.polyfill.installAll(); if (!shaka.Player.isBrowserSupported()) { @@ -470,24 +486,13 @@ playerState.set({ ...$playerState, playerElement: playerElement }); } - // Due to how our player is rendered in layout for stateful pip - // we calaculate player height to then allow children pages - // to wrap around it. - function updateVideoPlayerHeight() { - const container = document.getElementById('shaka-container') as HTMLElement; - - if (container) { - const height = container.getBoundingClientRect().height; - document.documentElement.style.setProperty('--video-player-height', `${height + 10}px`); - } - } - window.addEventListener('resize', updateVideoPlayerHeight); - updateVideoPlayerHeight(); - // Change instantly to stop video from being loud for a second restoreVolumePreference(); - const playerContainer = document.getElementById('shaka-container') as HTMLElement; + playerContainer = document.getElementById('shaka-container') as HTMLElement; + + window.addEventListener('resize', updateVideoPlayerHeight); + updateVideoPlayerHeight(); shakaUi = new shaka.ui.Overlay(player, playerContainer, playerElement); @@ -788,6 +793,9 @@ await reloadVideo(); } } + + // Update video player height again on video loaded. + updateVideoPlayerHeight(); }); async function getLastPlayPos(): Promise { @@ -869,6 +877,8 @@ // Continue regardless of error } + window.removeEventListener('resize', updateVideoPlayerHeight); + Mousetrap.unbind(['left', 'right', 'space', 'c', 'f', 'shift+left', 'shift+right']); if (watchProgressTimeout) { From 02c1cb0118aa192bde3f3667ced45ed94e877394 Mon Sep 17 00:00:00 2001 From: WardPearce Date: Mon, 22 Dec 2025 03:55:23 +1300 Subject: [PATCH 08/17] Instantly destroy player state on video change --- materialious/src/lib/components/Thumbnail.svelte | 8 ++++++-- materialious/src/routes/(app)/watch/[slug]/+page.svelte | 5 +++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/materialious/src/lib/components/Thumbnail.svelte b/materialious/src/lib/components/Thumbnail.svelte index 3c241f19..e59b076c 100644 --- a/materialious/src/lib/components/Thumbnail.svelte +++ b/materialious/src/lib/components/Thumbnail.svelte @@ -16,6 +16,7 @@ interfaceLowBandwidthMode, isAndroidTvStore, playerSavePlaybackPositionStore, + playerState, syncPartyConnectionsStore, syncPartyPeerStore, synciousInstanceStore, @@ -119,7 +120,9 @@ removeEventListener('resize', disableSideways); }); - function syncChangeVideo() { + function onVideoSelected() { + playerState.set(undefined); + if ($syncPartyConnectionsStore) { const events = { events: [{ type: 'change-video', videoId: video.videoId }] @@ -166,7 +169,7 @@ class="wave thumbnail" href={watchUrl.toString()} data-sveltekit-preload-data="off" - onclick={syncChangeVideo} + onclick={onVideoSelected} > {#if !$interfaceLowBandwidthMode} {#if !thumbnail} @@ -213,6 +216,7 @@ class="video-title" data-sveltekit-preload-data="off" href={watchUrl.toString()} + onclick={onVideoSelected} > {letterCase(video.title.trimEnd())} diff --git a/materialious/src/routes/(app)/watch/[slug]/+page.svelte b/materialious/src/routes/(app)/watch/[slug]/+page.svelte index 4371f241..740eb714 100644 --- a/materialious/src/routes/(app)/watch/[slug]/+page.svelte +++ b/materialious/src/routes/(app)/watch/[slug]/+page.svelte @@ -390,6 +390,7 @@ {premiereTime} +
{/if} @@ -718,6 +719,10 @@ justify-content: flex-end; } + .video-placeholder { + height: 50vh; + } + @media screen and (max-width: 1000px) { .video-actions { align-items: flex-start; From 8adf956ab1d3042859b7869b52088a4eff0db2e4 Mon Sep 17 00:00:00 2001 From: WardPearce Date: Mon, 22 Dec 2025 06:30:44 +1300 Subject: [PATCH 09/17] Progress on custom player ui --- materialious/src/lib/components/Player.svelte | 395 ++++++++++++++---- materialious/src/lib/css/global.css | 1 + materialious/src/lib/i18n/locales/en.json | 12 +- materialious/src/routes/(app)/+layout.svelte | 3 +- .../routes/(no-layout)/tv/[slug]/+page.svelte | 2 +- 5 files changed, 326 insertions(+), 87 deletions(-) diff --git a/materialious/src/lib/components/Player.svelte b/materialious/src/lib/components/Player.svelte index 6590999f..c7d8f465 100644 --- a/materialious/src/lib/components/Player.svelte +++ b/materialious/src/lib/components/Player.svelte @@ -10,8 +10,6 @@ import ui from 'beercss'; import ISO6391 from 'iso-639-1'; 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'; @@ -22,9 +20,9 @@ import type { VideoPlay } from '../api/model'; import { authStore, - darkModeStore, instanceStore, isAndroidTvStore, + playerAlwaysLoopStore, playerAndroidLockOrientation, playerAutoPlayStore, playerCCByDefault, @@ -34,7 +32,6 @@ playerProxyVideosStore, playerSavePlaybackPositionStore, playerState, - playerStatisticsByDefault, playertheatreModeIsActive, playerYouTubeJsFallback, sponsorBlockCategoriesStore, @@ -42,24 +39,30 @@ sponsorBlockStore, sponsorBlockUrlStore, synciousInstanceStore, - synciousStore, - themeColorStore + synciousStore } from '../store'; - import { getDynamicTheme, setStatusBarColor } from '../theme'; + import { setStatusBarColor } from '../theme'; import { patchYoutubeJs } from '$lib/patches/youtubejs'; import { goToNextVideo, goToPreviousVideo, playbackRates } from '$lib/player'; import { EndTimeElement } from '$lib/shaka-elements/endTime'; import { dashManifestDomainInclusion } from '$lib/android/youtube/dash'; import { injectSabr } from '$lib/sabr'; import type { SabrStreamingAdapter } from 'googlevideo/sabr-streaming-adapter'; + import { SvelteSet } from 'svelte/reactivity'; interface Props { data: { video: VideoPlay; content: PhasedDescription; playlistId: string | null }; isEmbed?: boolean; playerElement?: HTMLMediaElement | undefined; + hideControls?: boolean; } - let { data, isEmbed = false, playerElement = $bindable(undefined) }: Props = $props(); + let { + data, + isEmbed = false, + playerElement = $bindable(undefined), + hideControls = false + }: Props = $props(); let segments: Segment[] = []; @@ -70,24 +73,21 @@ let showVideoRetry = $state(false); let player: shaka.Player; - let shakaUi: shaka.ui.Overlay; let sabrAdapter: SabrStreamingAdapter | null; let playerContainer: HTMLElement; + let playerCurrentPlaybackState = $state(false); + let playerCurrentTime = $state(0); + let playerIsSeeking = $state(false); + let playerIsBuffering = $state(false); + let playerVolume = $state(0); + let playerSettings: 'quality' | 'speed' | 'language' | 'root' = $state('root'); + let playerCurrentVideoTrack: shaka.extern.VideoTrack | undefined = $state(undefined); + let playerCurrentAudioTrack: shaka.extern.AudioTrack | undefined = $state(undefined); + let playerLoop = $state($playerAlwaysLoopStore); + const STORAGE_KEY_VOLUME = 'shaka-preferred-volume'; - async function updateSeekBarTheme() { - if (!shakaUi) return; - await tick(); - shakaUi.configure({ - seekBarColors: { - played: (await getDynamicTheme())['--primary'] - } - }); - } - - themeColorStore.subscribe(updateSeekBarTheme); - darkModeStore.subscribe(updateSeekBarTheme); playertheatreModeIsActive.subscribe(async () => { await tick(); updateVideoPlayerHeight(); @@ -115,8 +115,24 @@ } } + function filterUniqueAudioTracks(tracks: shaka.extern.AudioTrack[]): shaka.extern.AudioTrack[] { + const uniqueTracks: shaka.extern.AudioTrack[] = []; + const seen = new SvelteSet(); + + for (const track of tracks) { + const identifier = `${track.language}-${track.label || 'No Label'}`; + if (!seen.has(identifier)) { + seen.add(identifier); + uniqueTracks.push(track); + } + } + + return uniqueTracks; + } + function saveVolumePreference() { if (!playerElement) return; + playerVolume = playerElement.volume; localStorage.setItem(STORAGE_KEY_VOLUME, playerElement.volume.toString()); } @@ -124,6 +140,7 @@ const savedVolume = localStorage.getItem(STORAGE_KEY_VOLUME); if (savedVolume && playerElement) { playerElement.volume = parseFloat(savedVolume); + playerVolume = playerElement.volume; } } @@ -304,20 +321,26 @@ page.subscribe((pageUpdate) => loadTimeFromUrl(pageUpdate)); + function setActiveVideoTrack() { + const videoTracks = player.getVideoTracks(); + playerCurrentVideoTrack = videoTracks.find((track) => track.active); + } + + function setActiveAudioTrack() { + const audioTracks = player.getAudioTracks(); + playerCurrentAudioTrack = audioTracks.find((track) => track.active); + } + async function loadVideo() { showVideoRetry = false; sabrAdapter = await injectSabr(data.video, player); - try { - document.getElementsByClassName('shaka-ad-info')[0].remove(); - } catch { - // Continue regardless of error - } - player.addEventListener('loaded', () => { restoreQualityPreference(); restoreDefaultLanguage(); + setActiveVideoTrack(); + setActiveAudioTrack(); if ($playerCCByDefault) { toggleSubtitles(); @@ -427,14 +450,6 @@ if ($playerDefaultPlaybackSpeed && playerElement) { playerElement.playbackRate = $playerDefaultPlaybackSpeed; } - - if ($playerStatisticsByDefault) { - // Appears to be no native way in shaka to toggle statistics on and off - const shakaStatisticsButton = document.querySelector('.shaka-statistics-button') as - | HTMLButtonElement - | undefined; - shakaStatisticsButton?.click(); - } } async function reloadVideo() { @@ -443,6 +458,14 @@ await loadVideo(); } + function toggleVideoPlaybackStatus() { + if (playerCurrentPlaybackState) { + playerElement?.pause(); + } else { + playerElement?.play(); + } + } + // Due to how our player is rendered in layout for stateful pip // we calaculate player height to then allow children pages // to wrap around it. @@ -482,6 +505,8 @@ }); playerElement = document.getElementById('player') as HTMLMediaElement; + playerElement.loop = playerLoop; + if ($playerState) { playerState.set({ ...$playerState, playerElement: playerElement }); } @@ -489,13 +514,11 @@ // Change instantly to stop video from being loud for a second restoreVolumePreference(); - playerContainer = document.getElementById('shaka-container') as HTMLElement; + playerContainer = document.getElementById('player-container') as HTMLElement; window.addEventListener('resize', updateVideoPlayerHeight); updateVideoPlayerHeight(); - shakaUi = new shaka.ui.Overlay(player, playerContainer, playerElement); - await player.attach(playerElement); shaka.ui.Controls.registerElement('end_time', { @@ -504,33 +527,6 @@ } }); - shakaUi.configure({ - addBigPlayButton: Capacitor.getPlatform() === 'android', - controlPanelElements: [ - 'play_pause', - Capacitor.getPlatform() === 'android' ? '' : 'volume', - 'spacer', - 'time_and_duration', - data.video.liveNow || data.video.lengthSeconds < 240 ? '' : 'end_time', - 'captions', - 'overflow_menu', - 'fullscreen' - ], - overflowMenuButtons: [ - 'cast', - 'airplay', - 'quality', - 'playback_rate', - 'loop', - 'language', - 'statistics' - ], - playbackRates: playbackRates, - enableTooltips: false - }); - - updateSeekBarTheme(); - player?.addEventListener('error', (event) => { const error = (event as CustomEvent).detail as shaka.util.Error; console.error('Player error:', error); @@ -715,17 +711,6 @@ }); } - const volumeContainer = playerContainer.getElementsByClassName('shaka-volume-bar-container'); - volumeContainer[0]?.addEventListener('mousewheel', (event) => { - event.preventDefault(); - const delta = Math.sign((event as any).deltaY); - const newVolume = Math.max( - 0, - Math.min(1, (playerElement as HTMLMediaElement).volume - delta * 0.05) - ); - (playerElement as HTMLMediaElement).volume = newVolume; - }); - Mousetrap.bind('c', () => { toggleSubtitles(); return false; @@ -735,7 +720,7 @@ if (document.fullscreenElement) { document.exitFullscreen(); } else { - shakaUi.getControls()?.toggleFullScreen(); + // TODO } return false; }); @@ -771,13 +756,32 @@ }); playerElement?.addEventListener('pause', async () => { + playerCurrentPlaybackState = false; + playerIsBuffering = false; savePlayerPos(); }); playerElement?.addEventListener('ended', async () => { + playerCurrentPlaybackState = false; + playerIsBuffering = false; await goToNextVideo(data.video, data.playlistId); }); + playerElement?.addEventListener('playing', () => { + playerCurrentPlaybackState = true; + playerIsBuffering = false; + }); + + playerElement?.addEventListener('waiting', () => { + playerCurrentPlaybackState = false; + playerIsBuffering = true; + }); + + playerElement?.addEventListener('timeupdate', () => { + if (playerIsSeeking) return; + playerCurrentTime = playerElement?.currentTime ?? 0; + }); + try { await loadVideo(); } catch (error: unknown) { @@ -893,19 +897,13 @@ player.unload(); player.destroy(); } - - if (shakaUi) { - shakaUi.destroy(); - } });
{#if showVideoRetry} @@ -948,6 +1140,41 @@ {/if}