diff --git a/materialious/android/app/build.gradle b/materialious/android/app/build.gradle index 003749e3..04b0065a 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 133 - versionName "1.9.16" + versionCode 134 + versionName "1.9.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 bd3f756d..773eb01f 100644 --- a/materialious/electron/materialious.metainfo.xml +++ b/materialious/electron/materialious.metainfo.xml @@ -68,7 +68,11 @@ - + + + https://github.com/Materialious/Materialious/releases/tag/1.9.17 + + https://github.com/Materialious/Materialious/releases/tag/1.9.16 diff --git a/materialious/electron/package-lock.json b/materialious/electron/package-lock.json index 803fa2a1..979e0c78 100644 --- a/materialious/electron/package-lock.json +++ b/materialious/electron/package-lock.json @@ -1,12 +1,12 @@ { "name": "Materialious", - "version": "1.9.16", + "version": "1.9.17", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "Materialious", - "version": "1.9.16", + "version": "1.9.17", "license": "MIT", "dependencies": { "@capacitor-community/electron": "^5.0.0", diff --git a/materialious/electron/package.json b/materialious/electron/package.json index 05842ada..3b16e650 100644 --- a/materialious/electron/package.json +++ b/materialious/electron/package.json @@ -1,6 +1,6 @@ { "name": "Materialious", - "version": "1.9.16", + "version": "1.9.17", "description": "Modern material design for Invidious.", "author": { "name": "Ward Pearce", @@ -44,4 +44,4 @@ "capacitor", "electron" ] -} \ No newline at end of file +} diff --git a/materialious/package.json b/materialious/package.json index 5f94b409..fca37748 100644 --- a/materialious/package.json +++ b/materialious/package.json @@ -1,6 +1,6 @@ { "name": "materialious", - "version": "1.9.16", + "version": "1.9.17", "private": true, "scripts": { "dev": "vite dev", diff --git a/materialious/src/lib/api/apiExtended.ts b/materialious/src/lib/api/apiExtended.ts index ec321213..221a8df7 100644 --- a/materialious/src/lib/api/apiExtended.ts +++ b/materialious/src/lib/api/apiExtended.ts @@ -1,4 +1,3 @@ -// src/lib/requestQueue.ts import { writable, type Writable } from 'svelte/store'; import type { SynciousProgressModel } from './model'; import { getVideoProgress } from '.'; diff --git a/materialious/src/lib/components/Player.svelte b/materialious/src/lib/components/Player.svelte index 067f2769..2b28dc35 100644 --- a/materialious/src/lib/components/Player.svelte +++ b/materialious/src/lib/components/Player.svelte @@ -61,14 +61,14 @@ isSyncing?: boolean; isEmbed?: boolean; segments?: Segment[]; - playerElement: HTMLMediaElement | undefined; + playerElement?: HTMLMediaElement | undefined; } let { data, isEmbed = false, segments = $bindable([]), - playerElement = $bindable() + playerElement = $bindable(undefined) }: Props = $props(); let snackBarAlert = $state(''); diff --git a/materialious/src/lib/misc.ts b/materialious/src/lib/misc.ts index 57b1c901..586cee97 100644 --- a/materialious/src/lib/misc.ts +++ b/materialious/src/lib/misc.ts @@ -5,7 +5,6 @@ import type Peer from 'peerjs'; import { get } from 'svelte/store'; import { instanceStore, interfaceAllowInsecureRequests } from './store'; import type { Channel, HashTag, Playlist, PlaylistPageVideo, Video, VideoBase } from './api/model'; -import { Capacitor } from '@capacitor/core'; export function truncate(value: string, maxLength: number = 50): string { return value.length > maxLength ? `${value.substring(0, maxLength)}...` : value; diff --git a/materialious/src/lib/store.ts b/materialious/src/lib/store.ts index 9204cd25..d46a1c4d 100644 --- a/materialious/src/lib/store.ts +++ b/materialious/src/lib/store.ts @@ -16,7 +16,7 @@ import type { import { ensureNoTrailingSlash } from './misc'; function platformDependentDefault(givenValue: any, defaultValue: any): any { - if (typeof givenValue !== 'undefined' && typeof givenValue !== null) { + if (typeof givenValue !== 'undefined' && givenValue !== null) { return givenValue; } else if (defaultValue && Capacitor.getPlatform() !== 'web') { return defaultValue; diff --git a/materialious/src/lib/timestamps.ts b/materialious/src/lib/timestamps.ts index 41195fca..dc28a1c7 100644 --- a/materialious/src/lib/timestamps.ts +++ b/materialious/src/lib/timestamps.ts @@ -41,64 +41,74 @@ export function phaseDescription( ): PhasedDescription { const timestamps: Timestamps = []; const lines = content.split('\n'); - - // Regular expressions for different timestamp formats - const urlRegex = /(\d+:\d+(?::\d+)?)<\/a>\s*(.+)/; - const timestampRegexYtJs = new RegExp( - `href="https://www\\.youtube\\.com/watch\\?v=${videoId}(?:&t=(\\d+)s)?"[^>]*>\\s*]*>\\s*([^<]+)\\s*\\s*\\s*]*>\\s*([^<]+)\\s*`, - 'i' - ); - const filteredLines: string[] = []; + + const parser = new DOMParser(); + lines.forEach((line) => { - const urlMatch = urlRegex.exec(line); - // Use appropriate regex based on the `usingYoutubeJs` flag - const timestampMatch = ( - fallbackPatch === 'youtubejs' ? timestampRegexYtJs : timestampRegexInvidious - ).exec(fallbackPatch === 'youtubejs' ? line + '' : line); + const doc = parser.parseFromString(line, 'text/html'); + const link = doc.querySelector('a'); - if (urlMatch !== null && timestampMatch === null) { - // If line contains a URL but not a timestamp, modify the URL - const modifiedLine = processYoutubeLink(line).replace( - /]+>/g, '') - .replace(/\n/g, '') - .trim() - ), - timePretty: timestamp, - endTime: -1 - }); + // Handle youtubejs timestamps + if ( + fallbackPatch === 'youtubejs' && + href.includes(`https://www.youtube.com/watch?v=${videoId}`) + ) { + const url = new URL(href); + const timeParam = url.searchParams.get('t') || '0'; + + const timePretty = link.textContent?.trim() || ''; + const spans = doc.querySelectorAll('span'); + const title = spans.length > 1 ? spans[1].textContent?.trim() || '' : ''; + + timestamps.push({ + time: convertToSeconds(timeParam.replace('s', '')), + title: decodeHtmlCharCodes(title), + timePretty, + endTime: -1 + }); + } + // Handle invidious-like timestamps + else if ( + fallbackPatch !== 'youtubejs' && + link.hasAttribute('data-onclick') && + link.getAttribute('data-onclick') === 'jump_to_time' + ) { + const timePretty = link.textContent?.trim() || ''; + const time = link.getAttribute('data-jump-time') || '0'; + + // Get remaining text after the link for title + const title = link.nextSibling?.textContent?.trim() || ''; + + timestamps.push({ + time: convertToSeconds(time), + title: decodeHtmlCharCodes(title), + timePretty, + endTime: -1 + }); + } + // Normal link, modify to not use youtube redirect + else { + const modifiedLine = processYoutubeLink(line).replace( + / { - if (idx < timestamps.length - 1) { - ts.endTime = timestamps[idx + 1].time; - } else { - ts.endTime = -1; - } + ts.endTime = idx < timestamps.length - 1 ? timestamps[idx + 1].time : -1; }); const filteredContent = filteredLines.join('\n'); - return { description: filteredContent, timestamps: timestamps }; + return { description: filteredContent, timestamps }; } diff --git a/materialious/src/routes/(no-layout)/embed/[slug]/+page@.svelte b/materialious/src/routes/(no-layout)/embed/[slug]/+page@.svelte index 7679e37e..9c6d2b15 100644 --- a/materialious/src/routes/(no-layout)/embed/[slug]/+page@.svelte +++ b/materialious/src/routes/(no-layout)/embed/[slug]/+page@.svelte @@ -2,8 +2,6 @@ import Player from '$lib/components/Player.svelte'; let { data } = $props(); - - let playerElement: HTMLMediaElement; - + diff --git a/update_versions.py b/update_versions.py index 416cd1db..c824f933 100644 --- a/update_versions.py +++ b/update_versions.py @@ -3,7 +3,7 @@ import os import re from datetime import datetime -LATEST_VERSION = "1.9.16" +LATEST_VERSION = "1.9.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")