@ -8,12 +8,25 @@
@@ -8,12 +8,25 @@
import { sessionManager } from '../../lib/services/auth/session-manager.js';
import { page } from '$app/stores';
import Icon from '../../lib/components/ui/Icon.svelte';
import { isPWAInstalled , getBrowserURL } from '../../lib/utils/pwa-detection.js';
onMount(async () => {
await nostrClient.initialize();
// Check NIP-07 availability dynamically
const { isNIP07Available } = await import('../../lib/services/auth/nip07-signer.js');
const { isNIP07Available , waitForNIP07 } = await import('../../lib/services/auth/nip07-signer.js');
// Initial check
nip07Available = isNIP07Available();
// In PWA mode, wait a bit for extensions to inject (some extensions inject with delay)
if (isPWA && !nip07Available) {
// Wait up to 2 seconds for NIP-07 to become available
const available = await waitForNIP07(2000);
if (available) {
nip07Available = true;
}
}
await loadStoredKeys();
});
@ -21,6 +34,26 @@
@@ -21,6 +34,26 @@
let loading = $state(false);
let activeTab = $state< 'nip07' | 'nsec' | 'anonymous'>('nip07');
let nip07Available = $state(false);
let isPWA = $state(false);
$effect(() => {
isPWA = isPWAInstalled();
// Re-check NIP-07 availability when PWA state changes
if (isPWA && !nip07Available) {
(async () => {
const { isNIP07Available , waitForNIP07 } = await import('../../lib/services/auth/nip07-signer.js');
const available = await waitForNIP07(2000);
if (available) {
nip07Available = true;
}
})();
}
});
function openInBrowser() {
const url = getBrowserURL();
window.open(url, '_blank');
}
// Stored keys
let storedNsecKeys = $state< Array < { pubkey : string ; created_at : number ; keyType ?: 'nsec' | 'anonymous' } > >([]);
@ -65,15 +98,29 @@
@@ -65,15 +98,29 @@
}
async function loginWithNIP07() {
if (!nip07Available) {
error = 'NIP-07 extension not available. Please install a Nostr extension like Alby or nos2x.';
return;
}
loading = true;
error = null;
try {
// Re-check NIP-07 availability (extensions might have injected since last check)
const { isNIP07Available , waitForNIP07 } = await import('../../lib/services/auth/nip07-signer.js');
// If not available, wait a bit for it to become available (especially in PWA mode)
if (!isNIP07Available()) {
const available = await waitForNIP07(2000);
if (!available) {
if (isPWA) {
error = 'NIP-07 extension not available in PWA mode. Browser extensions may not be accessible in standalone mode. Try opening in your regular browser, or use nsec/anonymous login.';
} else {
error = 'NIP-07 extension not available. Please install a Nostr extension like Alby or nos2x.';
}
loading = false;
return;
}
// Update availability state
nip07Available = true;
}
await authenticateWithNIP07();
// Redirect to stored route or default to home
const redirectRoute = sessionManager.getLogoutRedirect() || '/';
@ -337,6 +384,25 @@
@@ -337,6 +384,25 @@
< p class = "text-fog-text-light dark:text-fog-dark-text-light" style = "font-size: 0.875em;" >
Login using a Nostr browser extension (Alby, nos2x, etc.)
< / p >
{ #if isPWA && ! nip07Available }
< div class = "p-3 bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-800 rounded" >
< p class = "text-sm text-yellow-800 dark:text-yellow-200 mb-2" >
< strong > PWA Mode:< / strong > Browser extensions may not be accessible in PWA standalone mode, depending on your browser.
The app will attempt to detect your Nostr extension, but if it's not found, you can:
< / p >
< ul class = "text-sm text-yellow-800 dark:text-yellow-200 mb-2 list-disc list-inside space-y-1" >
< li > Try the login button anyway (some browsers support extensions in PWA mode)< / li >
< li > Open aitherboard in your regular browser to use extensions< / li >
< li > Use nsec or anonymous login instead< / li >
< / ul >
< button
onclick={ openInBrowser }
class="w-full px-3 py-2 bg-yellow-600 dark:bg-yellow-700 text-white hover:opacity-90 transition-colors rounded text-sm flex items-center justify-center gap-2"
>
< span > 🌐 Open in Browser< / span >
< / button >
< / div >
{ /if }
< button
onclick={ loginWithNIP07 }
disabled={ loading }