@@ -7,8 +7,8 @@ android {
|
||||
applicationId "us.materialio.app"
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 144
|
||||
versionName "1.10.3"
|
||||
versionCode 145
|
||||
versionName "1.10.4"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
aaptOptions {
|
||||
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
|
||||
|
||||
@@ -61,7 +61,11 @@
|
||||
|
||||
|
||||
|
||||
<release version="1.10.3" date="2025-8-11">
|
||||
|
||||
<release version="1.10.4" date="2025-8-19">
|
||||
<url>https://github.com/Materialious/Materialious/releases/tag/1.10.4</url>
|
||||
</release>
|
||||
<release version="1.10.3" date="2025-8-11">
|
||||
<url>https://github.com/Materialious/Materialious/releases/tag/1.10.3</url>
|
||||
</release>
|
||||
<release version="1.10.2" date="2025-8-06">
|
||||
|
||||
Generated
+6
-6
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "Materialious",
|
||||
"version": "1.10.3",
|
||||
"version": "1.10.4",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "Materialious",
|
||||
"version": "1.10.3",
|
||||
"version": "1.10.4",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@capacitor-community/electron": "^5.0.0",
|
||||
@@ -22,7 +22,7 @@
|
||||
"jsonfile": "^6.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"electron": "^37.2.5",
|
||||
"electron": "^37.2.6",
|
||||
"electron-builder": "^26.0.12",
|
||||
"electron-rebuild": "^3.2.9",
|
||||
"typescript": "^5.9.2"
|
||||
@@ -2492,9 +2492,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/electron": {
|
||||
"version": "37.2.5",
|
||||
"resolved": "https://registry.npmjs.org/electron/-/electron-37.2.5.tgz",
|
||||
"integrity": "sha512-719ZqEp43rj6xDJMICm4CIXl8keFFgvVNO9Ix6OtjNjrh9HtYlP/1WiYeRohnXj06aLyGx5NCzrHbG7j3BxO9w==",
|
||||
"version": "37.2.6",
|
||||
"resolved": "https://registry.npmjs.org/electron/-/electron-37.2.6.tgz",
|
||||
"integrity": "sha512-Ns6xyxE+hIK5UlujtRlw7w4e2Ju/ImCWXf1Q/PoOhc0N3/6SN6YW7+ujCarsHbxWnolbW+1RlkHtdklUJpjbPA==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Materialious",
|
||||
"version": "1.10.3",
|
||||
"version": "1.10.4",
|
||||
"description": "Modern material design for Invidious.",
|
||||
"author": {
|
||||
"name": "Ward Pearce",
|
||||
@@ -35,7 +35,7 @@
|
||||
"jsonfile": "^6.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"electron": "^37.2.5",
|
||||
"electron": "^37.2.6",
|
||||
"electron-builder": "^26.0.12",
|
||||
"electron-rebuild": "^3.2.9",
|
||||
"typescript": "^5.9.2"
|
||||
|
||||
Generated
+8
-8
@@ -30,7 +30,7 @@
|
||||
"material-dynamic-colors": "^1.1.1",
|
||||
"media-captions": "^1.0.4",
|
||||
"mousetrap": "^1.6.5",
|
||||
"peerjs": "^1.5.4",
|
||||
"peerjs": "^1.5.5",
|
||||
"shaka-player": "^4.11.7",
|
||||
"sponsorblock-api": "^0.2.4",
|
||||
"svelte-infinite-loading": "^1.4.0",
|
||||
@@ -57,7 +57,7 @@
|
||||
"eslint-plugin-svelte": "^3.11.0",
|
||||
"patch-package": "^8.0.0",
|
||||
"prettier": "^3.3.3",
|
||||
"prettier-plugin-svelte": "^3.2.7",
|
||||
"prettier-plugin-svelte": "^3.4.0",
|
||||
"svelte": "^5.19.7",
|
||||
"svelte-check": "^4.0.0",
|
||||
"tslib": "^2.7.0",
|
||||
@@ -9620,9 +9620,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/peerjs": {
|
||||
"version": "1.5.4",
|
||||
"resolved": "https://registry.npmjs.org/peerjs/-/peerjs-1.5.4.tgz",
|
||||
"integrity": "sha512-yFsoLMnurJKlQbx6kVSBpOp+AlNldY1JQS2BrSsHLKCZnq6t7saHleuHM5svuLNbQkUJXHLF3sKOJB1K0xulOw==",
|
||||
"version": "1.5.5",
|
||||
"resolved": "https://registry.npmjs.org/peerjs/-/peerjs-1.5.5.tgz",
|
||||
"integrity": "sha512-viMUCPDL6CSfOu0ZqVcFqbWRXNHIbv2lPqNbrBIjbFYrflebOjItJ4hPfhjnuUCstqciHVu9vVJ7jFqqKi/EuQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@msgpack/msgpack": "^2.8.0",
|
||||
@@ -9949,9 +9949,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/prettier-plugin-svelte": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/prettier-plugin-svelte/-/prettier-plugin-svelte-3.3.3.tgz",
|
||||
"integrity": "sha512-yViK9zqQ+H2qZD1w/bH7W8i+bVfKrD8GIFjkFe4Thl6kCT9SlAsXVNmt3jCvQOCsnOhcvYgsoVlRV/Eu6x5nNw==",
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/prettier-plugin-svelte/-/prettier-plugin-svelte-3.4.0.tgz",
|
||||
"integrity": "sha512-pn1ra/0mPObzqoIQn/vUTR3ZZI6UuZ0sHqMK5x2jMLGrs53h0sXhkVuDcrlssHwIMk7FYrMjHBPoUSyyEEDlBQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "materialious",
|
||||
"version": "1.10.3",
|
||||
"version": "1.10.4",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
@@ -32,7 +32,7 @@
|
||||
"eslint-plugin-svelte": "^3.11.0",
|
||||
"patch-package": "^8.0.0",
|
||||
"prettier": "^3.3.3",
|
||||
"prettier-plugin-svelte": "^3.2.7",
|
||||
"prettier-plugin-svelte": "^3.4.0",
|
||||
"svelte": "^5.19.7",
|
||||
"svelte-check": "^4.0.0",
|
||||
"tslib": "^2.7.0",
|
||||
@@ -62,11 +62,11 @@
|
||||
"material-dynamic-colors": "^1.1.1",
|
||||
"media-captions": "^1.0.4",
|
||||
"mousetrap": "^1.6.5",
|
||||
"peerjs": "^1.5.4",
|
||||
"peerjs": "^1.5.5",
|
||||
"shaka-player": "^4.11.7",
|
||||
"sponsorblock-api": "^0.2.4",
|
||||
"svelte-infinite-loading": "^1.4.0",
|
||||
"svelte-persisted-store": "^0.12.0",
|
||||
"youtubei.js": "^15.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
export async function dashManifestDomainInclusion(manifestUrl: string): Promise<string> {
|
||||
/* If on android, must manually format dash manifest to include URL. */
|
||||
|
||||
// Must fetch the headers of the request
|
||||
// using our custom android proxy logic
|
||||
const respIvg = await fetch(manifestUrl, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
__custom_return: 'json-headers',
|
||||
__redirect: 'manual'
|
||||
}
|
||||
});
|
||||
|
||||
if (!respIvg.ok) {
|
||||
throw Error('Unable to make request to Invidious');
|
||||
}
|
||||
|
||||
const ivgHeaders = await respIvg.json();
|
||||
// If location isn't present, then use base manifest URL.
|
||||
const companionUrl = 'location' in ivgHeaders ? ivgHeaders['location'] : manifestUrl;
|
||||
|
||||
const respCompanion = await fetch(companionUrl, {
|
||||
method: 'GET'
|
||||
});
|
||||
|
||||
if (!respCompanion.ok) {
|
||||
throw Error('Unable to make request to Companion');
|
||||
}
|
||||
|
||||
const manifestText = await respCompanion.text();
|
||||
|
||||
const parser = new DOMParser();
|
||||
const xmlDoc = parser.parseFromString(manifestText, 'application/xml');
|
||||
|
||||
const baseUrlElements = xmlDoc.getElementsByTagName('BaseURL');
|
||||
|
||||
for (let i = 0; i < baseUrlElements.length; i++) {
|
||||
const baseUrlElement = baseUrlElements[i];
|
||||
const baseUrlValue = baseUrlElement.textContent;
|
||||
|
||||
if (baseUrlValue && (baseUrlValue.startsWith('/') || !baseUrlValue.includes('://'))) {
|
||||
const companionUrlObj = new URL(companionUrl);
|
||||
const baseDomain = `${companionUrlObj.protocol}//${companionUrlObj.host}`;
|
||||
const resolvedUrl = new URL(baseUrlValue, baseDomain).href;
|
||||
baseUrlElement.textContent = resolvedUrl;
|
||||
}
|
||||
}
|
||||
|
||||
const serializer = new XMLSerializer();
|
||||
const updatedManifest = serializer.serializeToString(xmlDoc);
|
||||
|
||||
return `data:application/dash+xml;base64,${btoa(updatedManifest)}`;
|
||||
}
|
||||
@@ -49,12 +49,13 @@
|
||||
import { getDynamicTheme, setStatusBarColor } from '../theme';
|
||||
import { injectSABR } from '$lib/sabr';
|
||||
import { patchYoutubeJs } from '$lib/patches/youtubejs';
|
||||
import { playbackRates } from '$lib/const';
|
||||
import { playbackRates } from '$lib/player';
|
||||
import { EndTimeElement } from '$lib/shaka-elements/endTime';
|
||||
import { loadEntirePlaylist } from '$lib/playlist';
|
||||
import { goto } from '$app/navigation';
|
||||
import { unsafeRandomItem } from '$lib/misc';
|
||||
import type { PlayerEvents } from '$lib/player';
|
||||
import { dashManifestDomainInclusion } from '$lib/android/youtube/dash';
|
||||
|
||||
interface Props {
|
||||
data: { video: VideoPlay; content: PhasedDescription; playlistId: string | null };
|
||||
@@ -400,7 +401,16 @@
|
||||
dashUrl += '?local=true';
|
||||
}
|
||||
|
||||
await player.load(dashUrl, await getLastPlayPos());
|
||||
if (
|
||||
Capacitor.getPlatform() === 'android' &&
|
||||
$playerProxyVideosStore &&
|
||||
!data.video.fallbackPatch
|
||||
) {
|
||||
const manifest = await dashManifestDomainInclusion(dashUrl);
|
||||
await player.load(manifest, await getLastPlayPos());
|
||||
} else {
|
||||
await player.load(dashUrl, await getLastPlayPos());
|
||||
}
|
||||
} else {
|
||||
if (data.video.fallbackPatch === 'youtubejs') {
|
||||
if (!data.video.dashUrl) {
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
playerYouTubeJsAlways,
|
||||
playerYouTubeJsFallback
|
||||
} from '../../store';
|
||||
import { playbackRates } from '$lib/const';
|
||||
import { playbackRates } from '$lib/player';
|
||||
|
||||
let defaultLanguage = $state(get(playerDefaultLanguage));
|
||||
|
||||
@@ -49,9 +49,11 @@
|
||||
switch (localVideoFallback) {
|
||||
case 'enabled':
|
||||
playerYouTubeJsFallback.set(true);
|
||||
playerYouTubeJsAlways.set(false);
|
||||
break;
|
||||
case 'disabled':
|
||||
playerYouTubeJsFallback.set(false);
|
||||
playerYouTubeJsAlways.set(false);
|
||||
break;
|
||||
case 'always':
|
||||
playerYouTubeJsAlways.set(true);
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export const playbackRates = [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 2.25, 2.5, 2.75, 3];
|
||||
@@ -12,7 +12,6 @@
|
||||
|
||||
nav.top {
|
||||
padding-top: calc(var(--safe-area-inset-top) + 1rem) !important;
|
||||
height: 100px;
|
||||
padding-bottom: 1em;
|
||||
}
|
||||
|
||||
|
||||
@@ -74,7 +74,8 @@
|
||||
"title": "Teilen",
|
||||
"materialiousLink": "Materialious-Link kopieren",
|
||||
"invidiousRedirect": "Invidious-Weiterleitungslink kopieren",
|
||||
"youtubeLink": "YouTube-Link kopieren"
|
||||
"youtubeLink": "YouTube-Link kopieren",
|
||||
"includeTimestamp": "Mit Zeitstempel"
|
||||
},
|
||||
"download": "Herunterladen",
|
||||
"downloadSteps": {
|
||||
|
||||
@@ -156,7 +156,8 @@
|
||||
"title": "Teile",
|
||||
"materialiousLink": "Materialious-Link kopiere",
|
||||
"youtubeLink": "YouTube-Link kopiere",
|
||||
"invidiousRedirect": "Invidious-Wiiterleitigslink kopiere"
|
||||
"invidiousRedirect": "Invidious-Wiiterleitigslink kopiere",
|
||||
"includeTimestamp": "Mit Ziitstempel"
|
||||
},
|
||||
"download": "Abelade",
|
||||
"downloadSteps": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
export interface PlayerEvent {
|
||||
type: 'pause' | 'seek' | 'change-video' | 'play' | 'playlist' | 'goto';
|
||||
path?: string,
|
||||
path?: string;
|
||||
time?: number;
|
||||
videoId?: string;
|
||||
playlistId?: string;
|
||||
@@ -9,3 +9,5 @@ export interface PlayerEvent {
|
||||
export interface PlayerEvents {
|
||||
events: PlayerEvent[];
|
||||
}
|
||||
|
||||
export const playbackRates = [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 2.25, 2.5, 2.75, 3];
|
||||
|
||||
@@ -239,6 +239,12 @@
|
||||
box-shadow: none !important;
|
||||
}
|
||||
</style>
|
||||
{:else if Capacitor.getPlatform() === 'android'}
|
||||
<style>
|
||||
nav.top {
|
||||
height: 120px;
|
||||
}
|
||||
</style>
|
||||
{/if}
|
||||
</svelte:head>
|
||||
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ import os
|
||||
import re
|
||||
from datetime import datetime
|
||||
|
||||
LATEST_VERSION = "1.10.3"
|
||||
LATEST_VERSION = "1.10.4"
|
||||
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")
|
||||
|
||||
Reference in New Issue
Block a user