From 7cd1a522f222ece76f1955d4a858d618d8409d4a Mon Sep 17 00:00:00 2001 From: silberengel Date: Mon, 14 Jul 2025 18:48:03 +0200 Subject: [PATCH] Made Amber session persistent. --- src/lib/components/LoginMenu.svelte | 42 +++++++++++++++++++++++++++++ src/routes/+layout.ts | 31 ++++++++++++++++++--- 2 files changed, 70 insertions(+), 3 deletions(-) diff --git a/src/lib/components/LoginMenu.svelte b/src/lib/components/LoginMenu.svelte index 36c7e68..921d5f6 100644 --- a/src/lib/components/LoginMenu.svelte +++ b/src/lib/components/LoginMenu.svelte @@ -4,6 +4,7 @@ import { userStore, loginWithExtension, loginWithAmber, loginWithNpub, logoutUser } from '$lib/stores/userStore'; import { get } from 'svelte/store'; import NDK, { NDKNip46Signer, NDKPrivateKeySigner } from '@nostr-dev-kit/ndk'; + import { onMount } from 'svelte'; // UI state let isLoadingExtension: boolean = $state(false); @@ -15,6 +16,13 @@ let loginButtonRef: HTMLElement | undefined = $state(); let resultTimeout: ReturnType | null = null; let profileAvatarId = 'profile-avatar-btn'; + let showAmberReconnect = $state(false); + + onMount(() => { + if (localStorage.getItem('alexandria/amber/reconnect') === '1') { + showAmberReconnect = true; + } + }); // Subscribe to userStore let user = $state(get(userStore)); @@ -112,9 +120,17 @@ }; const handleLogout = () => { + localStorage.removeItem('amber/nsec'); + localStorage.removeItem('alexandria/amber/reconnect'); logoutUser(); }; + function handleAmberReconnect() { + showAmberReconnect = false; + localStorage.removeItem('alexandria/amber/reconnect'); + handleAmberLogin(); + } + function shortenNpub(long: string | undefined) { if (!long) return ''; return long.slice(0, 8) + '…' + long.slice(-4); @@ -286,4 +302,30 @@ +{/if} + +{#if showAmberReconnect} +
+
+
+

Reconnect Amber Wallet

+

+ Your Amber wallet session could not be restored automatically.
+ Please reconnect your Amber wallet to continue. +

+ + +
+
+
{/if} \ No newline at end of file diff --git a/src/routes/+layout.ts b/src/routes/+layout.ts index b45c6e8..4744b85 100644 --- a/src/routes/+layout.ts +++ b/src/routes/+layout.ts @@ -6,6 +6,7 @@ import { loginMethodStorageKey } from '$lib/stores/userStore'; import Pharos, { pharosInstance } from '$lib/parser'; import { feedType } from '$lib/stores'; import type { LayoutLoad } from './$types'; +import { get } from 'svelte/store'; export const ssr = false; @@ -31,9 +32,33 @@ export const load: LayoutLoad = () => { console.log('Restoring extension login...'); loginWithExtension(); } else if (loginMethod === 'amber') { - // Amber login restoration would require more context (e.g., session, signer), so skip for now - alert('Amber login cannot be restored automatically. Please reconnect your Amber wallet.'); - console.warn('Amber login cannot be restored automatically. Please reconnect your Amber wallet.'); + // Attempt to restore Amber (NIP-46) session from localStorage + const relay = 'wss://relay.nsec.app'; + const localNsec = localStorage.getItem('amber/nsec'); + if (localNsec) { + import('@nostr-dev-kit/ndk').then(async ({ NDKNip46Signer, default: NDK }) => { + const ndk = get(ndkInstance); + try { + const amberSigner = NDKNip46Signer.nostrconnect(ndk, relay, localNsec, { + name: 'Alexandria', + perms: 'sign_event:1;sign_event:4', + }); + // Try to reconnect (blockUntilReady will resolve if Amber is running and session is valid) + await amberSigner.blockUntilReady(); + const user = await amberSigner.user(); + await loginWithAmber(amberSigner, user); + console.log('Amber session restored.'); + } catch (err) { + // If reconnection fails, show a non-blocking prompt (handled in LoginMenu UI) + console.warn('Amber session could not be restored. Prompting user to reconnect.'); + // Optionally, set a flag in localStorage or a Svelte store to show a reconnect banner/modal + localStorage.setItem('alexandria/amber/reconnect', '1'); + } + }); + } else { + // No session data, prompt user to reconnect (handled in LoginMenu UI) + localStorage.setItem('alexandria/amber/reconnect', '1'); + } } else if (loginMethod === 'npub') { console.log('Restoring npub login...'); loginWithNpub(pubkey);