diff --git a/materialious/android/app/build.gradle b/materialious/android/app/build.gradle index 33a3b37b..1ab3fb87 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 200 - versionName "1.13.16" + versionCode 201 + versionName "1.13.17" 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 ccd373a5..29287bed 100644 --- a/materialious/electron/materialious.metainfo.xml +++ b/materialious/electron/materialious.metainfo.xml @@ -99,7 +99,11 @@ - + + + https://github.com/Materialious/Materialious/releases/tag/1.13.17 + + https://github.com/Materialious/Materialious/releases/tag/1.13.16 diff --git a/materialious/electron/package-lock.json b/materialious/electron/package-lock.json index fd23c2d2..fd0296f3 100644 --- a/materialious/electron/package-lock.json +++ b/materialious/electron/package-lock.json @@ -1,12 +1,12 @@ { "name": "Materialious", - "version": "1.13.16", + "version": "1.13.17", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "Materialious", - "version": "1.13.16", + "version": "1.13.17", "license": "MIT", "dependencies": { "@capacitor-community/electron": "^5.0.0", @@ -3138,9 +3138,9 @@ } }, "node_modules/electron": { - "version": "40.1.0", - "resolved": "https://registry.npmjs.org/electron/-/electron-40.1.0.tgz", - "integrity": "sha512-2j/kvw7uF0H1PnzYBzw2k2Q6q16J8ToKrtQzZfsAoXbbMY0l5gQi2DLOauIZLzwp4O01n8Wt/74JhSRwG0yj9A==", + "version": "40.2.1", + "resolved": "https://registry.npmjs.org/electron/-/electron-40.2.1.tgz", + "integrity": "sha512-0zOeyN8LB1KHIjVV5jyMmQmkqx3J8OkkVlab3p7vOM28jI46blxW7M52Tcdi6X2m5o2jj8ejOlAh5+boL3w8aQ==", "dev": true, "hasInstallScript": true, "license": "MIT", diff --git a/materialious/electron/package.json b/materialious/electron/package.json index 9fdd5fb5..574f6d4d 100644 --- a/materialious/electron/package.json +++ b/materialious/electron/package.json @@ -1,6 +1,6 @@ { "name": "Materialious", - "version": "1.13.16", + "version": "1.13.17", "description": "Modern material design for Invidious.", "author": { "name": "Ward Pearce", diff --git a/materialious/electron/src/setup.ts b/materialious/electron/src/setup.ts index 6a3cb751..e9089d23 100644 --- a/materialious/electron/src/setup.ts +++ b/materialious/electron/src/setup.ts @@ -190,7 +190,6 @@ export class ElectronCapacitorApp { globalShortcut.register('Control+Shift+I', () => { this.MainWindow.webContents.toggleDevTools(); }); - // Security this.MainWindow.webContents.setWindowOpenHandler((details) => { shell.openExternal(details.url); diff --git a/materialious/package-lock.json b/materialious/package-lock.json index 65e1e1b8..69807d81 100644 --- a/materialious/package-lock.json +++ b/materialious/package-lock.json @@ -1,12 +1,12 @@ { "name": "materialious", - "version": "1.13.14", + "version": "1.13.17", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "materialious", - "version": "1.13.14", + "version": "1.13.17", "hasInstallScript": true, "dependencies": { "@capacitor-community/electron": "^5.0.1", @@ -4883,13 +4883,13 @@ } }, "node_modules/axios": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz", - "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==", + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.5.tgz", + "integrity": "sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==", "license": "MIT", "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.4", + "follow-redirects": "^1.15.11", + "form-data": "^4.0.5", "proxy-from-env": "^1.1.0" } }, @@ -12522,9 +12522,9 @@ } }, "node_modules/svelte": { - "version": "5.49.2", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.49.2.tgz", - "integrity": "sha512-PYLwnngYzyhKzqDlGVlCH4z+NVI8mC0/bTv15vw25CcdOhxENsOHIbQ36oj5DIf3oBazM+STbCAvaskpxtBmWA==", + "version": "5.50.1", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.50.1.tgz", + "integrity": "sha512-/Jlom4ddkISyVHXpM2O5dXP9pYnaiFrVQzPbIL1/pEoOa77ZunCb6nDgUCTNCQ/X3t64z9ukrK6R+BbB3kPR3A==", "license": "MIT", "peer": true, "dependencies": { @@ -12576,9 +12576,9 @@ } }, "node_modules/svelte-check": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-4.3.5.tgz", - "integrity": "sha512-e4VWZETyXaKGhpkxOXP+B/d0Fp/zKViZoJmneZWe/05Y2aqSKj3YN2nLfYPJBQ87WEiY4BQCQ9hWGu9mPT1a1Q==", + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-4.3.6.tgz", + "integrity": "sha512-uBkz96ElE3G4pt9E1Tw0xvBfIUQkeH794kDQZdAUk795UVMr+NJZpuFSS62vcmO/DuSalK83LyOwhgWq8YGU1Q==", "dev": true, "license": "MIT", "dependencies": { diff --git a/materialious/package.json b/materialious/package.json index f627a8ab..92d5faf6 100644 --- a/materialious/package.json +++ b/materialious/package.json @@ -1,6 +1,6 @@ { "name": "materialious", - "version": "1.13.16", + "version": "1.13.17", "private": true, "scripts": { "dev": "npm run patch:github && vite dev", diff --git a/materialious/src/lib/components/Player.svelte b/materialious/src/lib/components/Player.svelte index 0aadf2e3..957a1803 100644 --- a/materialious/src/lib/components/Player.svelte +++ b/materialious/src/lib/components/Player.svelte @@ -128,20 +128,27 @@ let playerTimelineTooltip: HTMLDivElement | undefined = $state(); let playerTimelineThumbnails: TimelineThumbnail[] = $state([]); let playerTimelineThumbnailsCache = new ImageCache(); - let playerTimelineThumbnailCanvas: HTMLCanvasElement | undefined = $state(); + let playerTimelineThumbnailCanvas: { + timeline?: HTMLCanvasElement; + thumb?: HTMLCanvasElement; + } = $state({}); let playerInitalInteract = true; const playerTimelineSlider = new Slider({ min: 0, step: 0.1, value: () => currentTime, - onValueChange: (timeToSet) => { + onValueChange: async (timeToSet) => { userManualSeeking = true; currentTime = timeToSet; showPlayerUI(); setPlayerTimelineChapters(currentTime); + if (playerTimelineThumbnailCanvas.thumb) { + await setPlayerTimelineThumbnails(currentTime, playerTimelineThumbnailCanvas.thumb); + } + if (playerSliderDebounce) clearTimeout(playerSliderDebounce); playerSliderDebounce = setTimeout(() => { @@ -515,13 +522,14 @@ dashUrl += '?local=true'; } - if (data.video.storyboards && data.video.storyboards.length > 1) { - // Use best possible thumbnails - playerTimelineThumbnails = await storyboardThumbnails( - data.video.storyboards[data.video.storyboards.length - 1], + if (data.video.storyboards && data.video.storyboards.length > 2) { + storyboardThumbnails( + data.video.storyboards[2], playerTimelineThumbnailsCache, playerMaxKnownTime - ); + ).then((thumbnails) => { + playerTimelineThumbnails = thumbnails; + }); } if ( @@ -1127,6 +1135,19 @@ } } + async function setPlayerTimelineThumbnails(time: number, canvas: HTMLCanvasElement) { + const canvasContext = canvas.getContext('2d'); + + if (canvasContext) { + await drawTimelineThumbnail( + canvasContext, + playerTimelineThumbnailsCache, + playerTimelineThumbnails, + time + ); + } + } + async function updateTooltip() { if (!playerSliderElement || latestMouseX === undefined) { requestAnimationTooltip = undefined; @@ -1139,17 +1160,11 @@ playerTimelineTimeHover = percent * (data.video.lengthSeconds ?? 0); setPlayerTimelineChapters(playerTimelineTimeHover); - if (playerTimelineThumbnailCanvas) { - const canvasContext = playerTimelineThumbnailCanvas.getContext('2d'); - - if (canvasContext) { - await drawTimelineThumbnail( - canvasContext, - playerTimelineThumbnailsCache, - playerTimelineThumbnails, - playerTimelineTimeHover - ); - } + if (playerTimelineThumbnailCanvas.timeline) { + await setPlayerTimelineThumbnails( + playerTimelineTimeHover, + playerTimelineThumbnailCanvas.timeline + ); } if (playerTimelineTooltip) { @@ -1350,35 +1365,31 @@ onmousemove={timelineMouseMove} bind:this={playerSliderElement} > - {#snippet timelineTooltip()} + {#snippet timelineTooltip(key: 'thumb' | 'timeline')} + {#if playerTimelineThumbnails.length > 0} + + {/if} {#if playerCloestSponsor} - {sponsorSegments[playerCloestSponsor.category]} -
+

{sponsorSegments[playerCloestSponsor.category]}

{:else if playerCloestTimestamp} - {truncate(playerCloestTimestamp.title, 22)} -
+

{truncate(playerCloestTimestamp.title, 22)}

{/if} {/snippet}
{#if !userManualSeeking}
- {#if playerTimelineThumbnails.length > 0} - - > - {/if} - {@render timelineTooltip()} + {@render timelineTooltip('timeline')} {videoLength(playerTimelineTimeHover)}
{/if}
-
- {@render timelineTooltip()} +
+ {@render timelineTooltip('thumb')} {videoLength(currentTime)}
@@ -1748,10 +1759,6 @@ transform: translate(-50%, -50%); } - .thumb-tooltip { - left: var(--percentage); - } - .seek-double-click { background-color: var(--secondary-container); height: var(--video-player-height); @@ -1873,13 +1880,20 @@ pointer-events: none; will-change: transform; padding: 0; - border-radius: 0.25rem; display: block; } - .timeline.tooltip canvas { + .timeline.tooltip canvas, + .tooltip.thumb canvas { display: block; margin-bottom: 0.1rem; height: 100px; + border-radius: 0.25rem; + } + + .tooltip.thumb { + left: var(--percentage); + display: block; + padding: 0; } diff --git a/materialious/src/lib/timelineThumbnails.ts b/materialious/src/lib/timelineThumbnails.ts index 81147a30..db0cf70f 100644 --- a/materialious/src/lib/timelineThumbnails.ts +++ b/materialious/src/lib/timelineThumbnails.ts @@ -40,7 +40,7 @@ export async function storyboardThumbnails( for (let sheetIndex = 0; sheetIndex < storyboardCount; sheetIndex++) { const url = templateUrl.replace('M$M', `M${sheetIndex}`); - // Preload all images. + // Pre-cache sheet imageCache.load(url); for (let i = 0; i < count; i++) { diff --git a/materialious/src/routes/(app)/+layout.svelte b/materialious/src/routes/(app)/+layout.svelte index d81a7d2f..20f620c9 100644 --- a/materialious/src/routes/(app)/+layout.svelte +++ b/materialious/src/routes/(app)/+layout.svelte @@ -352,7 +352,7 @@ {#if isLoggedIn}