Update pages on authStore set

This commit is contained in:
WardPearce
2026-02-14 21:42:22 +13:00
parent e9b4277eb8
commit b8823e0a7c
4 changed files with 84 additions and 53 deletions
@@ -11,7 +11,13 @@
import type { RgbaColor, HsvaColor, Colord } from 'colord';
import { _ } from '$lib/i18n';
import { get } from 'svelte/store';
import { isMobile, clearCaches, isUnrestrictedPlatform, setInvidiousInstance } from '../../misc';
import {
isMobile,
clearCaches,
isUnrestrictedPlatform,
setInvidiousInstance,
goToInvidiousLogin
} from '../../misc';
import { getPages, type Pages } from '../../navPages';
import ColorPicker from 'svelte-awesome-color-picker';
import {
@@ -91,11 +97,6 @@
}
async function setBackend(event: Event) {
if (isOwnBackend()?.internalAuth) {
rawMasterKeyStore.set(undefined);
fetch('/api/user/logout', { method: 'DELETE' });
}
const select = event.target as HTMLSelectElement;
backendInUseStore.set(select.value as 'ivg' | 'yt');
reloadState();
@@ -165,14 +166,31 @@
</button>
</nav>
</form>
{#if isOwnBackend()?.internalAuth}
{#if !$authStore}
<button onclick={goToInvidiousLogin}>
<i>link</i>
<span>{$_('linkInvidious')}</span>
</button>
{:else}
<button
onclick={() => {
authStore.set(null);
goto(resolve('/', {}));
}}
>
<i>link_off</i>
<span>{$_('unlinkInvidious')}</span>
</button>
{/if}
<div class="space"></div>
{/if}
{:else}
<div class="space"></div>
{/if}
{#if isMobile()}
{#if invalidInstance}
<div style="margin-bottom: 6em;"></div>
{/if}
{#if isMobile() && invalidInstance}
<div style="margin-bottom: 6em;"></div>
{/if}
{#if Capacitor.isNativePlatform() && (invalidInstance || $interfaceAllowInsecureRequests)}
@@ -11,6 +11,8 @@
"password": "Password",
"invalidPassword": "Invalid password",
"usernameTaken": "Username taken",
"linkInvidious": "Link Invidious account",
"unlinkInvidious": "Unlink Invidious account",
"createAccount": "Create account",
"needRegister": "I need to register",
"registrationDisabled": "Registration currently disabled, contact instance owner.",
+35
View File
@@ -13,6 +13,7 @@ import {
interfaceAndroidUseNativeShare,
isAndroidTvStore,
playlistCacheStore,
rawMasterKeyStore,
searchCacheStore
} from './store';
import type {
@@ -29,6 +30,8 @@ import { Capacitor } from '@capacitor/core';
import { Share } from '@capacitor/share';
import { Clipboard } from '@capacitor/clipboard';
import { isOwnBackend } from './shared';
import { Browser } from '@capacitor/browser';
import { clearFeedYTjs } from './api/youtubejs/subscriptions';
export function isMobile(): boolean {
const userAgent = navigator.userAgent;
@@ -289,3 +292,35 @@ export async function setInvidiousInstance(
return true;
}
export async function goToInvidiousLogin() {
if (!get(instanceStore)) return;
const path = new URL(`${get(instanceStore)}/authorize_token`);
const searchParams = new URLSearchParams({
scopes: ':feed,:subscriptions*,:playlists*,:history*,:notifications*'
});
if (Capacitor.getPlatform() === 'android') {
searchParams.set('callback_url', 'materialious-auth://');
path.search = searchParams.toString();
await Browser.open({ url: path.toString() });
} else {
searchParams.set('callback_url', `${location.origin}${resolve('/auth', {})}`);
path.search = searchParams.toString();
document.location.href = path.toString();
}
}
export async function logout() {
if (isYTBackend()) {
await clearFeedYTjs();
}
if (isOwnBackend()?.internalAuth) {
fetch('/api/user/logout', { method: 'DELETE' });
rawMasterKeyStore.set(undefined);
} else {
authStore.set(null);
}
goto(resolve('/', {}));
}
+19 -43
View File
@@ -40,11 +40,10 @@
import { _ } from '$lib/i18n';
import { get } from 'svelte/store';
import { pwaInfo } from 'virtual:pwa-info';
import { isYTBackend, truncate } from '$lib/misc';
import { goToInvidiousLogin, isYTBackend, logout, truncate } from '$lib/misc';
import Author from '$lib/components/Author.svelte';
import Toast from '$lib/components/Toast.svelte';
import { isOwnBackend } from '$lib/shared';
import { clearFeedYTjs } from '$lib/api/youtubejs/subscriptions';
let { children } = $props();
@@ -52,15 +51,20 @@
let mobileSearchShow = $state(false);
let isLoggedIn = $state(false);
authStore.subscribe((value) => {
isLoggedIn = value !== null;
});
let notifications: Notification[] = $state([]);
let playerIsPip: boolean = $state(false);
let pages = $state(getPages());
authStore.subscribe(() => {
pages = getPages();
});
rawMasterKeyStore.subscribe(() => {
pages = getPages();
});
page.subscribe((pageData) => {
playerIsPip = !pageData.url.pathname.includes('/watch');
requestAnimationFrame(() => resetScroll());
@@ -117,27 +121,13 @@
});
async function login() {
if (isOwnBackend()?.internalAuth && isYTBackend()) {
if (isOwnBackend()?.internalAuth) {
goto(resolve('/internal/login', {}));
return;
}
if (!$isAndroidTvStore) {
// eslint-disable-next-line svelte/prefer-svelte-reactivity
const path = new URL(`${get(instanceStore)}/authorize_token`);
// eslint-disable-next-line svelte/prefer-svelte-reactivity
const searchParams = new URLSearchParams({
scopes: ':feed,:subscriptions*,:playlists*,:history*,:notifications*'
});
if (Capacitor.getPlatform() === 'android') {
searchParams.set('callback_url', 'materialious-auth://');
path.search = searchParams.toString();
await Browser.open({ url: path.toString() });
} else {
searchParams.set('callback_url', `${location.origin}${resolve('/auth', {})}`);
path.search = searchParams.toString();
document.location.href = path.toString();
}
await goToInvidiousLogin();
} else {
await ui('#tv-login');
document.getElementById('username')?.focus();
@@ -188,20 +178,6 @@
loginError = true;
}
async function logout() {
if (isYTBackend()) {
await clearFeedYTjs();
}
if (isOwnBackend()?.internalAuth) {
fetch('/api/user/logout', { method: 'DELETE' });
}
rawMasterKeyStore.set(undefined);
authStore.set(null);
goto(resolve('/', {}));
}
async function loadNotifications() {
const feed = await getFeed(100, 1);
notifications = feed.notifications;
@@ -255,7 +231,7 @@
setTheme();
setAmoledTheme();
if (isLoggedIn && !isYTBackend()) {
if ($authStore && !isYTBackend()) {
loadNotifications().catch(() => logout());
}
@@ -295,7 +271,7 @@
<div>{$_('searchPlaceholder')}</div>
</a>
{/if}
{#each getPages() as navPage (navPage)}
{#each pages as navPage (navPage)}
<a href={resolve(navPage.href, {})} class:active={$page.url.href.endsWith(navPage.href)}
><i>{navPage.icon}</i>
<div>{navPage.name}</div>
@@ -308,7 +284,7 @@
<div>{$_('layout.settings')}</div>
</a>
{#if showLogin}
{#if !isLoggedIn}
{#if (!$authStore && !isOwnBackend()?.internalAuth) || !$rawMasterKeyStore}
<a onclick={login} href="#login">
<i>login</i>
<div>{$_('layout.login')}</div>
@@ -370,7 +346,7 @@
<i class:primary-text={$syncPartyPeerStore}>group</i>
<div class="tooltip bottom">{$_('layout.syncParty')}</div>
</button>
{#if isLoggedIn && !isYTBackend()}
{#if (!$authStore && !isOwnBackend()?.internalAuth) || !$rawMasterKeyStore}
<button
class="circle large transparent"
onclick={() => {
@@ -394,7 +370,7 @@
</button>
{#if showLogin}
{#if !isLoggedIn && !$rawMasterKeyStore}
{#if (!$authStore && !isOwnBackend()?.internalAuth) || (!$rawMasterKeyStore && isOwnBackend()?.internalAuth)}
<button onclick={login} class="circle large transparent">
<i>login</i>
<div class="tooltip bottom">{$_('layout.login')}</div>
@@ -411,7 +387,7 @@
{/if}
<nav class="bottom s">
{#each getPages() as navPage (navPage)}
{#each pages as navPage (navPage)}
<a
class="round"
href={resolve(navPage.href, {})}