Merge pull request #1392 from Materialious/update/1.13.17

Update/1.13.17
This commit is contained in:
Ward
2026-02-11 04:43:59 +13:00
committed by GitHub
12 changed files with 86 additions and 69 deletions
+2 -2
View File
@@ -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.
@@ -99,7 +99,11 @@
<release version="1.13.16" date="2026-2-10">
<release version="1.13.17" date="2026-2-11">
<url>https://github.com/Materialious/Materialious/releases/tag/1.13.17</url>
</release>
<release version="1.13.16" date="2026-2-10">
<url>https://github.com/Materialious/Materialious/releases/tag/1.13.16</url>
</release>
<release version="1.13.15" date="2026-2-10">
+5 -5
View File
@@ -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",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "Materialious",
"version": "1.13.16",
"version": "1.13.17",
"description": "Modern material design for Invidious.",
"author": {
"name": "Ward Pearce",
-1
View File
@@ -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);
+13 -13
View File
@@ -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": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "materialious",
"version": "1.13.16",
"version": "1.13.17",
"private": true,
"scripts": {
"dev": "npm run patch:github && vite dev",
+55 -41
View File
@@ -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}
<canvas
bind:this={playerTimelineThumbnailCanvas[key]}
width={playerTimelineThumbnails[0].width}
height={playerTimelineThumbnails[0].height}
></canvas>
{/if}
{#if playerCloestSponsor}
{sponsorSegments[playerCloestSponsor.category]}
<br />
<p class="no-margin">{sponsorSegments[playerCloestSponsor.category]}</p>
{:else if playerCloestTimestamp}
{truncate(playerCloestTimestamp.title, 22)}
<br />
<p class="no-margin">{truncate(playerCloestTimestamp.title, 22)}</p>
{/if}
{/snippet}
<div class="track">
{#if !userManualSeeking}
<div bind:this={playerTimelineTooltip} class="timeline tooltip">
{#if playerTimelineThumbnails.length > 0}
<canvas
bind:this={playerTimelineThumbnailCanvas}
width={playerTimelineThumbnails[0].width}
height={playerTimelineThumbnails[0].height}
>
></canvas
>
{/if}
{@render timelineTooltip()}
{@render timelineTooltip('timeline')}
{videoLength(playerTimelineTimeHover)}
</div>
{/if}
<div class="range"></div>
<div {...playerTimelineSlider.thumb}>
<div class="tooltip thumb-tooltip">
{@render timelineTooltip()}
<div class="tooltip thumb">
{@render timelineTooltip('thumb')}
{videoLength(currentTime)}
</div>
</div>
@@ -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;
}
</style>
+1 -1
View File
@@ -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++) {
+1 -1
View File
@@ -352,7 +352,7 @@
{#if isLoggedIn}
<button class="circle large transparent" onclick={() => ui('#dialog-notifications')}
><i>notifications</i>
<div class="badge">
<div class="badge secondary">
{#if notifications.length > 99}
99+
{:else}
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -3,7 +3,7 @@ import os
import re
from datetime import datetime
LATEST_VERSION = "1.13.16"
LATEST_VERSION = "1.13.17"
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")