From 8b9cd8f1cfa811767c9a8e831c243b2783af67aa Mon Sep 17 00:00:00 2001 From: WardPearce Date: Wed, 30 Oct 2024 00:29:54 +1300 Subject: [PATCH] Add support for @username urls --- docs/BUILDING.md | 6 +----- materialious/src/lib/Comment.svelte | 5 +++-- materialious/src/lib/api/index.ts | 6 ++++++ materialious/src/lib/api/model.ts | 6 ++++++ materialious/src/routes/+layout.ts | 18 +++++++++++++++--- 5 files changed, 31 insertions(+), 10 deletions(-) diff --git a/docs/BUILDING.md b/docs/BUILDING.md index a0e3dbd9..e2f080f2 100644 --- a/docs/BUILDING.md +++ b/docs/BUILDING.md @@ -19,11 +19,7 @@ Materialious desktop builds are handled through GitHub using [prod-desktop.yml]( - From here, the process follows standard [electron-builder](https://www.electron.build/) steps to complete the build. ### Desktop Release (via Flatpak) -Flatpak builds for desktop releases are managed via [us.materailio.app](../flatpak/us.materialio.app.json). - -- We generate the necessary remote npm packages with `flatpak-node-generator npm -r ../materialious/package-lock.json -R ../materialious/electron/package-lock.json`, which creates [generated-sources.json](../flatpak/generated-sources.json). -- The Linux x64 runtime is downloaded as part of the Flatpak build sources and placed in `main/materialious/electron/.electron-cache`. The [electron-builder.config.json](../materialious/electron/electron-builder.config.json) is configured to use this cache directory to avoid downloading the runtime again during the build. -- The build process is similar to [prod-desktop.yml](../.github/workflows/prod-desktop.yml), following the guidelines for [Flatpak Electron](https://docs.flatpak.org/en/latest/electron.html). +TODO ### Android Release Android builds are handled using the workflow [prod-android.yml](../.github/workflows/prod-android.yml). diff --git a/materialious/src/lib/Comment.svelte b/materialious/src/lib/Comment.svelte index f1cdf954..3fbc02c1 100644 --- a/materialious/src/lib/Comment.svelte +++ b/materialious/src/lib/Comment.svelte @@ -22,8 +22,8 @@ function commentTimestamps(html: string): string { const regex = - /(\d+:\d+(?::\d+)?)<\/a>\s*(.+)/; - const replacement = `$3`; + /([^<]+)<\/a>\s*(.+)/g; + const replacement = `$3 $4`; const processedHtml = html.replace(regex, replacement); @@ -107,6 +107,7 @@ .comment { display: flex; margin-bottom: 0.8em; + white-space: pre-line; } .channel-owner { diff --git a/materialious/src/lib/api/index.ts b/materialious/src/lib/api/index.ts index d0bbef1b..5b90854f 100644 --- a/materialious/src/lib/api/index.ts +++ b/materialious/src/lib/api/index.ts @@ -22,6 +22,7 @@ import type { Feed, Playlist, PlaylistPage, + ResolvedUrl, ReturnYTDislikes, SearchSuggestion, Subscription, @@ -71,6 +72,11 @@ export async function getPopular(fetchOptions?: RequestInit): Promise { return await resp.json(); } +export async function getResolveUrl(url: string): Promise { + const resp = await fetchErrorHandle(await fetch(`${buildPath('resolveurl')}?url=${url}`)); + return await resp.json(); +} + export async function getVideo(videoId: string, local: boolean = false, fetchOptions?: RequestInit): Promise { const resp = await fetch(setRegion(buildPath(`videos/${videoId}?local=${local}`)), fetchOptions); if ( diff --git a/materialious/src/lib/api/model.ts b/materialious/src/lib/api/model.ts index ffae475d..db048ac7 100644 --- a/materialious/src/lib/api/model.ts +++ b/materialious/src/lib/api/model.ts @@ -21,6 +21,12 @@ export interface VideoBase { viewCountText: string; } +export interface ResolvedUrl { + ucid: string; + params: string; + pageType: string; +} + export interface Video extends VideoBase { type: 'video'; title: string; diff --git a/materialious/src/routes/+layout.ts b/materialious/src/routes/+layout.ts index d7f14dac..2879758a 100644 --- a/materialious/src/routes/+layout.ts +++ b/materialious/src/routes/+layout.ts @@ -1,13 +1,25 @@ import { browser } from '$app/environment'; +import { goto } from '$app/navigation'; +import { getResolveUrl } from '$lib/api'; import '$lib/i18n'; // Import to initialize. Important :) import { locale, waitLocale } from 'svelte-i18n'; -import type { LayoutLoad } from './$types'; export let ssr = false; -export const load: LayoutLoad = async () => { +export async function load({ url }) { + if (url.pathname.startsWith('/@')) { + const username = url.pathname.split('/')[1]; + + try { + const resolvedUrl = await getResolveUrl(`www.youtube.com/${username}`); + if (resolvedUrl.pageType === 'WEB_PAGE_TYPE_CHANNEL') { + goto(`/channel/${resolvedUrl.ucid}`); + } + } catch { } + } + if (browser) { locale.set(window.navigator.language); } await waitLocale(); -}; +}