Browse Source

Made Amber session persistent.

master
silberengel 8 months ago
parent
commit
7cd1a522f2
  1. 42
      src/lib/components/LoginMenu.svelte
  2. 31
      src/routes/+layout.ts

42
src/lib/components/LoginMenu.svelte

@ -4,6 +4,7 @@
import { userStore, loginWithExtension, loginWithAmber, loginWithNpub, logoutUser } from '$lib/stores/userStore'; import { userStore, loginWithExtension, loginWithAmber, loginWithNpub, logoutUser } from '$lib/stores/userStore';
import { get } from 'svelte/store'; import { get } from 'svelte/store';
import NDK, { NDKNip46Signer, NDKPrivateKeySigner } from '@nostr-dev-kit/ndk'; import NDK, { NDKNip46Signer, NDKPrivateKeySigner } from '@nostr-dev-kit/ndk';
import { onMount } from 'svelte';
// UI state // UI state
let isLoadingExtension: boolean = $state(false); let isLoadingExtension: boolean = $state(false);
@ -15,6 +16,13 @@
let loginButtonRef: HTMLElement | undefined = $state(); let loginButtonRef: HTMLElement | undefined = $state();
let resultTimeout: ReturnType<typeof setTimeout> | null = null; let resultTimeout: ReturnType<typeof setTimeout> | null = null;
let profileAvatarId = 'profile-avatar-btn'; let profileAvatarId = 'profile-avatar-btn';
let showAmberReconnect = $state(false);
onMount(() => {
if (localStorage.getItem('alexandria/amber/reconnect') === '1') {
showAmberReconnect = true;
}
});
// Subscribe to userStore // Subscribe to userStore
let user = $state(get(userStore)); let user = $state(get(userStore));
@ -112,9 +120,17 @@
}; };
const handleLogout = () => { const handleLogout = () => {
localStorage.removeItem('amber/nsec');
localStorage.removeItem('alexandria/amber/reconnect');
logoutUser(); logoutUser();
}; };
function handleAmberReconnect() {
showAmberReconnect = false;
localStorage.removeItem('alexandria/amber/reconnect');
handleAmberLogin();
}
function shortenNpub(long: string | undefined) { function shortenNpub(long: string | undefined) {
if (!long) return ''; if (!long) return '';
return long.slice(0, 8) + '…' + long.slice(-4); return long.slice(0, 8) + '…' + long.slice(-4);
@ -287,3 +303,29 @@
</div> </div>
</div> </div>
{/if} {/if}
{#if showAmberReconnect}
<div class="fixed inset-0 bg-black bg-opacity-40 flex items-center justify-center z-50">
<div class="bg-white rounded-lg p-6 max-w-md w-full mx-4 shadow-lg border border-primary-300">
<div class="text-center">
<h2 class="text-lg font-semibold text-gray-900 mb-4">Reconnect Amber Wallet</h2>
<p class="text-sm text-gray-600 mb-4">
Your Amber wallet session could not be restored automatically.<br/>
Please reconnect your Amber wallet to continue.
</p>
<button
class="mt-4 bg-primary-600 hover:bg-primary-700 text-white px-4 py-2 rounded text-sm font-medium transition-colors"
onclick={handleAmberReconnect}
>
Reconnect Amber
</button>
<button
class="mt-2 ml-4 bg-gray-300 hover:bg-gray-400 text-gray-800 px-4 py-2 rounded text-sm font-medium transition-colors"
onclick={() => { showAmberReconnect = false; localStorage.removeItem('alexandria/amber/reconnect'); }}
>
Cancel
</button>
</div>
</div>
</div>
{/if}

31
src/routes/+layout.ts

@ -6,6 +6,7 @@ import { loginMethodStorageKey } from '$lib/stores/userStore';
import Pharos, { pharosInstance } from '$lib/parser'; import Pharos, { pharosInstance } from '$lib/parser';
import { feedType } from '$lib/stores'; import { feedType } from '$lib/stores';
import type { LayoutLoad } from './$types'; import type { LayoutLoad } from './$types';
import { get } from 'svelte/store';
export const ssr = false; export const ssr = false;
@ -31,9 +32,33 @@ export const load: LayoutLoad = () => {
console.log('Restoring extension login...'); console.log('Restoring extension login...');
loginWithExtension(); loginWithExtension();
} else if (loginMethod === 'amber') { } else if (loginMethod === 'amber') {
// Amber login restoration would require more context (e.g., session, signer), so skip for now // Attempt to restore Amber (NIP-46) session from localStorage
alert('Amber login cannot be restored automatically. Please reconnect your Amber wallet.'); const relay = 'wss://relay.nsec.app';
console.warn('Amber login cannot be restored automatically. Please reconnect your Amber wallet.'); 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') { } else if (loginMethod === 'npub') {
console.log('Restoring npub login...'); console.log('Restoring npub login...');
loginWithNpub(pubkey); loginWithNpub(pubkey);

Loading…
Cancel
Save