Merge pull request #1285 from Materialious/update/1.12.11

Update/1.12.11
This commit is contained in:
Ward
2026-01-02 08:20:29 +00:00
committed by GitHub
14 changed files with 14143 additions and 14102 deletions
+2 -2
View File
@@ -7,8 +7,8 @@ android {
applicationId "us.materialio.app"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 182
versionName "1.12.10"
versionCode 183
versionName "1.12.11"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
aaptOptions {
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
@@ -79,7 +79,11 @@
<release version="1.12.10" date="2025-12-28">
<release version="1.12.11" date="2026-1-02">
<url>https://github.com/Materialious/Materialious/releases/tag/1.12.11</url>
</release>
<release version="1.12.10" date="2025-12-28">
<url>https://github.com/Materialious/Materialious/releases/tag/1.12.10</url>
</release>
<release version="1.12.9" date="2025-12-28">
+36 -29
View File
@@ -1,12 +1,12 @@
{
"name": "Materialious",
"version": "1.12.10",
"version": "1.12.11",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "Materialious",
"version": "1.12.10",
"version": "1.12.11",
"license": "MIT",
"dependencies": {
"@capacitor-community/electron": "^5.0.0",
@@ -18,11 +18,11 @@
"electron-unhandled": "^4.0.1",
"electron-updater": "^6.3.4",
"electron-window-state": "^5.0.3",
"jsdom": "^27.3.0",
"jsdom": "^27.4.0",
"jsonfile": "^6.2.0"
},
"devDependencies": {
"electron": "^39.2.6",
"electron": "^39.2.7",
"electron-builder": "^26.0.12",
"electron-rebuild": "^3.2.9",
"typescript": "^5.9.3"
@@ -698,6 +698,23 @@
"node": ">=14.14"
}
},
"node_modules/@exodus/bytes": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.7.0.tgz",
"integrity": "sha512-5i+BtvujK/vM07YCGDyz4C4AyDzLmhxHMtM5HpUyPRtJPBdFPsj290ffXW+UXY21/G7GtXeHD2nRmq0T1ShyQQ==",
"license": "MIT",
"engines": {
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
},
"peerDependencies": {
"@exodus/crypto": "^1.0.0-rc.4"
},
"peerDependenciesMeta": {
"@exodus/crypto": {
"optional": true
}
}
},
"node_modules/@gar/promisify": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz",
@@ -2597,9 +2614,9 @@
}
},
"node_modules/electron": {
"version": "39.2.6",
"resolved": "https://registry.npmjs.org/electron/-/electron-39.2.6.tgz",
"integrity": "sha512-dHBgTodWBZd+tL1Dt0PSh/CFLHeDkFCTKCTXu1dgPhlE9Z3k2zzlBQ9B2oW55CFsKanBDHiUomHJNw0XaSdQpA==",
"version": "39.2.7",
"resolved": "https://registry.npmjs.org/electron/-/electron-39.2.7.tgz",
"integrity": "sha512-KU0uFS6LSTh4aOIC3miolcbizOFP7N1M46VTYVfqIgFiuA2ilfNaOHLDS9tCMvwwHRowAsvqBrh9NgMXcTOHCQ==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
@@ -3591,15 +3608,15 @@
}
},
"node_modules/html-encoding-sniffer": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz",
"integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==",
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-6.0.0.tgz",
"integrity": "sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==",
"license": "MIT",
"dependencies": {
"whatwg-encoding": "^3.1.1"
"@exodus/bytes": "^1.6.0"
},
"engines": {
"node": ">=18"
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
}
},
"node_modules/http-cache-semantics": {
@@ -3681,6 +3698,7 @@
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"dev": true,
"license": "MIT",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
@@ -3958,17 +3976,18 @@
"license": "MIT"
},
"node_modules/jsdom": {
"version": "27.3.0",
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-27.3.0.tgz",
"integrity": "sha512-GtldT42B8+jefDUC4yUKAvsaOrH7PDHmZxZXNgF2xMmymjUbRYJvpAybZAKEmXDGTM0mCsz8duOa4vTm5AY2Kg==",
"version": "27.4.0",
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-27.4.0.tgz",
"integrity": "sha512-mjzqwWRD9Y1J1KUi7W97Gja1bwOOM5Ug0EZ6UDK3xS7j7mndrkwozHtSblfomlzyB4NepioNt+B2sOSzczVgtQ==",
"license": "MIT",
"dependencies": {
"@acemir/cssom": "^0.9.28",
"@asamuzakjp/dom-selector": "^6.7.6",
"@exodus/bytes": "^1.6.0",
"cssstyle": "^5.3.4",
"data-urls": "^6.0.0",
"decimal.js": "^10.6.0",
"html-encoding-sniffer": "^4.0.0",
"html-encoding-sniffer": "^6.0.0",
"http-proxy-agent": "^7.0.2",
"https-proxy-agent": "^7.0.6",
"is-potential-custom-element-name": "^1.0.1",
@@ -3978,7 +3997,6 @@
"tough-cookie": "^6.0.0",
"w3c-xmlserializer": "^5.0.0",
"webidl-conversions": "^8.0.0",
"whatwg-encoding": "^3.1.1",
"whatwg-mimetype": "^4.0.0",
"whatwg-url": "^15.1.0",
"ws": "^8.18.3",
@@ -5283,6 +5301,7 @@
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"dev": true,
"license": "MIT"
},
"node_modules/sanitize-filename": {
@@ -5996,18 +6015,6 @@
"node": ">=20"
}
},
"node_modules/whatwg-encoding": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz",
"integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==",
"license": "MIT",
"dependencies": {
"iconv-lite": "0.6.3"
},
"engines": {
"node": ">=18"
}
},
"node_modules/whatwg-mimetype": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz",
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "Materialious",
"version": "1.12.10",
"version": "1.12.11",
"description": "Modern material design for Invidious.",
"author": {
"name": "Ward Pearce",
@@ -31,11 +31,11 @@
"electron-unhandled": "^4.0.1",
"electron-updater": "^6.3.4",
"electron-window-state": "^5.0.3",
"jsdom": "^27.3.0",
"jsdom": "^27.4.0",
"jsonfile": "^6.2.0"
},
"devDependencies": {
"electron": "^39.2.6",
"electron": "^39.2.7",
"electron-builder": "^26.0.12",
"electron-rebuild": "^3.2.9",
"typescript": "^5.9.3"
-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);
+14028 -14028
View File
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "materialious",
"version": "1.12.10",
"version": "1.12.11",
"private": true,
"scripts": {
"dev": "npm run patch:github && vite dev",
@@ -18,7 +18,7 @@
"devDependencies": {
"@capacitor/assets": "^3.0.5",
"@capacitor/cli": "^8.0.0",
"@sveltejs/adapter-auto": "^6.0.1",
"@sveltejs/adapter-auto": "^7.0.0",
"@sveltejs/adapter-static": "^3.0.10",
"@sveltejs/kit": "^2.49.1",
"@sveltejs/vite-plugin-svelte": "^6.2.1",
@@ -43,7 +43,7 @@
"type": "module",
"dependencies": {
"@capacitor-community/electron": "^5.0.1",
"@capacitor-community/safe-area": "^7.0.0-alpha.1",
"@capacitor-community/safe-area": "^8.0.1",
"@capacitor/android": "^8.0.0",
"@capacitor/app": "^8.0.0",
"@capacitor/browser": "^8.0.0",
+31 -21
View File
@@ -85,7 +85,7 @@
let playerCurrentTime = $state(0);
let playerMaxKnownTime = $state(data.video.lengthSeconds);
let playerPauseTimeUpdates = $state(false);
let playerIsBuffering = $state(false);
let playerIsBuffering = $state(true);
let playerVolume = $state(0);
let playerSettings: 'quality' | 'speed' | 'language' | 'root' = $state('root');
let playerTextTracks: shaka.extern.TextTrack[] | undefined = $state(undefined);
@@ -98,6 +98,11 @@
let playerVideoEndTimePretty: string = $state('');
let playerBufferedTo: number = $state(0);
let playerCloestTimestamp: Timestamp | undefined = $state();
let playerControls: HTMLElement | undefined = $state();
// eslint-disable-next-line no-undef
let playerAndroidUITimeout: NodeJS.Timeout;
let playerAndroidforceHideControls = $state(false);
let clickCount = $state(0);
// eslint-disable-next-line no-undef
@@ -951,12 +956,22 @@
playerTimelineTooltipVisible = false;
}
let androidFirstTap = true;
function onVideoClick(
event: MouseEvent & {
currentTarget: EventTarget & HTMLDivElement;
}
) {
if (Capacitor.getPlatform() === 'android') {
if (playerAndroidUITimeout) {
clearTimeout(playerAndroidUITimeout);
playerAndroidforceHideControls = false;
}
playerAndroidUITimeout = setTimeout(() => {
playerAndroidforceHideControls = true;
}, 3000);
}
if (
event.target &&
event.target instanceof HTMLElement &&
@@ -965,12 +980,6 @@
) {
clickCount++;
// Force android to tap an addtional time.
if (Capacitor.getPlatform() === 'android' && androidFirstTap) {
androidFirstTap = false;
return;
}
const container = event.currentTarget;
const rect = container.getBoundingClientRect();
@@ -983,18 +992,6 @@
if (clickCount == 1) {
toggleVideoPlaybackStatus();
}
if (
Capacitor.getPlatform() === 'android' &&
event.target &&
event.target instanceof HTMLElement &&
parseFloat(getComputedStyle(event.target).opacity) > 0
) {
androidFirstTap = false;
} else {
androidFirstTap = true;
}
clickCount = 0;
}, 200);
@@ -1048,6 +1045,8 @@
if (clickCounterTimeout) clearTimeout(clickCounterTimeout);
if (playerAndroidUITimeout) clearTimeout(playerAndroidUITimeout);
if (player) {
player.unload();
player.destroy();
@@ -1060,8 +1059,10 @@
class:contain-video={!$isAndroidTvStore}
class:tv-contain-video={$isAndroidTvStore}
class:hide={showVideoRetry}
class:force-hide-controls={playerAndroidforceHideControls}
role="presentation"
onclick={onVideoClick}
bind:this={playerContainer}
>
<video
controls={false}
@@ -1122,7 +1123,7 @@
</div>
</div>
{#if !hideControls}
<div id="player-controls">
<div id="player-controls" bind:this={playerControls}>
<label class="slider" id="progress-slider">
{#key playerCurrentTime}
<input
@@ -1495,6 +1496,15 @@
transition: opacity 0.3s ease;
}
#player-container.force-hide-controls #player-controls {
opacity: 0 !important;
pointer-events: none !important;
}
#player-container.force-hide-controls #mobile-time {
display: none !important;
}
.seek-double-click {
background-color: var(--secondary-container);
height: var(--video-player-height);
@@ -26,9 +26,9 @@
if (get(interfaceLowBandwidthMode)) return;
let imgSrc = '';
if (playlist.videos.length > 0) {
if (playlist.videos && playlist.videos.length > 0) {
imgSrc = getBestThumbnail(playlist.videos[0].videoThumbnails) || '';
} else if (playlist.playlistThumbnail.length > 0) {
} else if (playlist.playlistThumbnail && playlist.playlistThumbnail.length > 0) {
imgSrc = playlist.playlistThumbnail;
} else {
imgSrc = '';
+4 -4
View File
@@ -80,7 +80,7 @@ function createStorage(): StorageInterface<any> | SelfUpdateStorageInterface<any
}
}
function platformDependentDefault(givenValue: any, defaultValue: any): any {
function ifNotWebDefault(givenValue: any, defaultValue: any): any {
if (typeof givenValue !== 'undefined' && givenValue !== null) {
return givenValue;
} else if (defaultValue && Capacitor.getPlatform() !== 'web') {
@@ -90,7 +90,7 @@ function platformDependentDefault(givenValue: any, defaultValue: any): any {
export const instanceStore: Writable<string> = persist(
writable(
platformDependentDefault(
ifNotWebDefault(
!import.meta.env.VITE_DEFAULT_INVIDIOUS_INSTANCE
? undefined
: ensureNoTrailingSlash(import.meta.env.VITE_DEFAULT_INVIDIOUS_INSTANCE),
@@ -183,7 +183,7 @@ export const playertheatreModeIsActive = writable(false);
export const returnYtDislikesStore = persist(writable(false), createStorage(), 'returnYtDislikes');
export const returnYTDislikesInstanceStore: Writable<string | null | undefined> = persist(
writable(
platformDependentDefault(
ifNotWebDefault(
import.meta.env.VITE_DEFAULT_RETURNYTDISLIKES_INSTANCE,
'https://ryd-proxy.materialio.us'
)
@@ -195,7 +195,7 @@ export const returnYTDislikesInstanceStore: Writable<string | null | undefined>
export const synciousStore = persist(writable(false), createStorage(), 'syncious');
export const synciousInstanceStore: Writable<string | null | undefined> = persist(
writable(
platformDependentDefault(
ifNotWebDefault(
import.meta.env.VITE_DEFAULT_SYNCIOUS_INSTANCE ||
import.meta.env.VITE_DEFAULT_API_EXTENDED_INSTANCE,
'https://extended-api.materialio.us'
@@ -577,11 +577,15 @@
{$_('videos')}
</p>
<p>
<a
href={resolve(`/channel/[authorId]`, {
authorId: $playlistCacheStore[data.playlistId].info.authorId
})}>{$playlistCacheStore[data.playlistId].info.author}</a
>
{#if $playlistCacheStore[data.playlistId].info.authorId}
<a
href={resolve(`/channel/[authorId]`, {
authorId: $playlistCacheStore[data.playlistId].info.authorId
})}>{$playlistCacheStore[data.playlistId].info.author}</a
>
{:else}
{$playlistCacheStore[data.playlistId].info.author}
{/if}
</p>
<nav>
<button
+18 -1
View File
@@ -6,9 +6,12 @@ import { getResolveUrl } from '$lib/api';
import '$lib/i18n'; // Import to initialize. Important :)
import { initI18n } from '$lib/i18n';
import { getPages } from '$lib/navPages';
import { authStore, interfaceDefaultPage, isAndroidTvStore } from '$lib/store';
import { authStore, instanceStore, interfaceDefaultPage, isAndroidTvStore } from '$lib/store';
import { get } from 'svelte/store';
import '$lib/android/http/androidRequests';
import { Capacitor } from '@capacitor/core';
import { Preferences } from '@capacitor/preferences';
import { deserialize } from '@macfja/serializer';
export const ssr = false;
@@ -19,6 +22,20 @@ export async function load({ url }) {
isAndroidTvStore.set((await androidTv.isAndroidTv()).value);
// Due to race condition with how we set & save persistent store values
// we manually set stores like auth & instance before load.
if (Capacitor.getPlatform() === 'android') {
const instancePreferences = await Preferences.get({ key: 'invidiousInstance' });
if (instancePreferences.value !== null) {
instanceStore.set(deserialize(instancePreferences.value));
}
const authPreferences = await Preferences.get({ key: 'authToken' });
if (authPreferences.value !== null) {
authStore.set(deserialize(authPreferences.value));
}
}
const resolvedRoot = resolve('/', {});
if (url.pathname.startsWith(resolvedRoot + '@')) {
const username = url.pathname.substring(resolvedRoot.length).split('/')[0];
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.12.10"
LATEST_VERSION = "1.12.11"
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")