From 30c260aa8276b770e845268fc80a2f3b5376fb0d Mon Sep 17 00:00:00 2001 From: thePR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> Date: Sat, 27 Sep 2025 22:19:30 -0400 Subject: [PATCH] Improve NIP-07 login reliability --- js/app.js | 23 ++++++++++++++++++++++- js/nostr.js | 49 +++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 69 insertions(+), 3 deletions(-) diff --git a/js/app.js b/js/app.js index e7c5bb9b..c3cac2fc 100644 --- a/js/app.js +++ b/js/app.js @@ -3229,7 +3229,22 @@ class bitvidApp { // 6) NIP-07 button inside the login modal => call the extension & login const nip07Button = document.getElementById("loginNIP07"); if (nip07Button) { + const originalLabel = nip07Button.textContent; + const setLoadingState = (isLoading) => { + nip07Button.disabled = isLoading; + nip07Button.dataset.loading = isLoading ? "true" : "false"; + nip07Button.setAttribute("aria-busy", isLoading ? "true" : "false"); + nip07Button.textContent = isLoading + ? "Connecting to NIP-07 extension..." + : originalLabel; + }; + nip07Button.addEventListener("click", async () => { + if (nip07Button.dataset.loading === "true") { + return; + } + + setLoadingState(true); console.log( "[app.js] loginNIP07 clicked! Attempting extension login..." ); @@ -3245,7 +3260,13 @@ class bitvidApp { } } catch (err) { console.error("[NIP-07 login error]", err); - this.showError("Failed to login with NIP-07. Please try again."); + const message = + err && typeof err.message === "string" && err.message.trim() + ? err.message.trim() + : "Failed to login with NIP-07. Please try again."; + this.showError(message); + } finally { + setLoadingState(false); } }); } diff --git a/js/nostr.js b/js/nostr.js index 10a290a9..ecc6fb3b 100644 --- a/js/nostr.js +++ b/js/nostr.js @@ -20,6 +20,7 @@ const RELAY_URLS = [ const EVENTS_CACHE_STORAGE_KEY = "bitvid:eventsCache:v1"; const LEGACY_EVENTS_STORAGE_KEY = "bitvidEvents"; const EVENTS_CACHE_TTL_MS = 10 * 60 * 1000; // 10 minutes +const NIP07_LOGIN_TIMEOUT_MS = 15_000; // 15 seconds // To limit error spam let errorLogCount = 0; @@ -492,13 +493,57 @@ class NostrClient { */ async login() { try { - if (!window.nostr) { + const extension = window.nostr; + if (!extension) { console.log("No Nostr extension found"); throw new Error( "Please install a Nostr extension (Alby, nos2x, etc.)." ); } - const pubkey = await window.nostr.getPublicKey(); + + if (typeof extension.getPublicKey !== "function") { + throw new Error( + "This NIP-07 extension is missing getPublicKey support. Please update the extension." + ); + } + + if (typeof extension.enable === "function") { + if (isDevMode) { + console.log("Requesting permissions from NIP-07 extension..."); + } + try { + await extension.enable(); + } catch (enableErr) { + throw new Error( + enableErr && enableErr.message + ? enableErr.message + : "The NIP-07 extension denied the permission request." + ); + } + } + + let timeoutId; + const pubkey = await Promise.race([ + extension.getPublicKey(), + new Promise((_, reject) => { + timeoutId = setTimeout(() => { + reject( + new Error( + "Timed out waiting for the NIP-07 extension. Check the extension prompt and try again." + ) + ); + }, NIP07_LOGIN_TIMEOUT_MS); + }), + ]).finally(() => { + if (timeoutId) { + clearTimeout(timeoutId); + } + }); + if (!pubkey || typeof pubkey !== "string") { + throw new Error( + "The NIP-07 extension did not return a public key. Please try again." + ); + } const npub = window.NostrTools.nip19.npubEncode(pubkey); if (isDevMode) {