Browse Source

bug-fixes

master
Silberengel 1 month ago
parent
commit
a3079c2451
  1. 4
      public/healthz.json
  2. 31
      src/lib/services/auth/nip07-signer.ts
  3. 26
      src/lib/utils/pwa-detection.ts
  4. 78
      src/routes/login/+page.svelte

4
public/healthz.json

@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
"status": "ok",
"service": "aitherboard",
"version": "0.3.0",
"buildTime": "2026-02-11T10:52:47.456Z",
"buildTime": "2026-02-11T10:58:05.118Z",
"gitCommit": "unknown",
"timestamp": 1770807167456
"timestamp": 1770807485118
}

31
src/lib/services/auth/nip07-signer.ts

@ -16,6 +16,37 @@ export function isNIP07Available(): boolean { @@ -16,6 +16,37 @@ export function isNIP07Available(): boolean {
return typeof window !== 'undefined' && 'nostr' in window;
}
/**
* Wait for NIP-07 to become available (useful for PWA mode where extensions may inject with delay)
* @param timeout Maximum time to wait in milliseconds (default: 3000ms)
* @param interval Check interval in milliseconds (default: 100ms)
* @returns Promise that resolves to true if NIP-07 becomes available, false if timeout
*/
export async function waitForNIP07(
timeout: number = 3000,
interval: number = 100
): Promise<boolean> {
if (isNIP07Available()) {
return true;
}
return new Promise((resolve) => {
const startTime = Date.now();
const checkInterval = setInterval(() => {
if (isNIP07Available()) {
clearInterval(checkInterval);
resolve(true);
return;
}
if (Date.now() - startTime >= timeout) {
clearInterval(checkInterval);
resolve(false);
}
}, interval);
});
}
/**
* Get NIP-07 signer
*/

26
src/lib/utils/pwa-detection.ts

@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
/**
* PWA detection utilities
*/
/**
* Check if the app is running as a PWA (installed/standalone mode)
*/
export function isPWAInstalled(): boolean {
if (typeof window === 'undefined') return false;
// Check for standalone display mode (most common)
const isStandalone = window.matchMedia('(display-mode: standalone)').matches;
// Check for iOS standalone mode
const isIOSStandalone = (window.navigator as any).standalone === true;
return isStandalone || isIOSStandalone;
}
/**
* Get the current URL to open in browser
*/
export function getBrowserURL(): string {
if (typeof window === 'undefined') return '/';
return window.location.href;
}

78
src/routes/login/+page.svelte

@ -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}

Loading…
Cancel
Save