From e8411c92fdbaf65e1c16ad7d3f8fca9717a5238a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nu=C5=A1a=20Puk=C5=A1i=C4=8D?= Date: Thu, 4 Dec 2025 15:53:33 +0100 Subject: [PATCH] Fix signing of lists --- .../nostr_single_sign_controller.js | 24 ++++++++++-- assets/controllers/signer_manager.js | 37 ++++++++++++++++--- 2 files changed, 52 insertions(+), 9 deletions(-) diff --git a/assets/controllers/nostr_single_sign_controller.js b/assets/controllers/nostr_single_sign_controller.js index eaf629b..f8fca57 100644 --- a/assets/controllers/nostr_single_sign_controller.js +++ b/assets/controllers/nostr_single_sign_controller.js @@ -38,22 +38,30 @@ export default class extends Controller { async signAndPublish(event) { event.preventDefault(); + console.log('[nostr_single_sign] Sign and publish triggered'); let signer; try { + this.showStatus('Connecting to signer...'); signer = await getSigner(); + console.log('[nostr_single_sign] Signer obtained successfully'); } catch (e) { - this.showError('No Nostr signer available. Please connect Amber or install a Nostr signer extension.'); + console.error('[nostr_single_sign] Failed to get signer:', e); + this.showError(`No Nostr signer available: ${e.message}. Please connect Amber or install a Nostr signer extension.`); return; } if (!this.publishUrlValue || !this.csrfTokenValue) { + console.error('[nostr_single_sign] Missing config', { publishUrl: this.publishUrlValue, csrf: !!this.csrfTokenValue }); this.showError('Missing config'); return; } this.publishButtonTarget.disabled = true; try { + this.showStatus('Getting public key...'); const pubkey = await signer.getPublicKey(); + console.log('[nostr_single_sign] Public key obtained:', pubkey); + const skeleton = JSON.parse(this.eventValue || '{}'); // Update content from textarea before signing const textarea = this.element.querySelector('textarea'); @@ -64,15 +72,23 @@ export default class extends Controller { this.ensureContent(skeleton); skeleton.pubkey = pubkey; - this.showStatus('Signing feedback…'); + this.showStatus('Signing event…'); + console.log('[nostr_single_sign] Signing event:', skeleton); const signed = await signer.signEvent(skeleton); + console.log('[nostr_single_sign] Event signed successfully'); this.showStatus('Publishing…'); await this.publishSigned(signed); + console.log('[nostr_single_sign] Event published successfully'); + + this.showSuccess('Published successfully! Redirecting...'); - this.showSuccess('Published feedback successfully'); + // Redirect to reading list index after successful publish + setTimeout(() => { + window.location.href = '/reading-list'; + }, 1500); } catch (e) { - console.error(e); + console.error('[nostr_single_sign] Error during sign/publish:', e); this.showError(e.message || 'Publish failed'); } finally { this.publishButtonTarget.disabled = false; diff --git a/assets/controllers/signer_manager.js b/assets/controllers/signer_manager.js index 5355db4..f3d4552 100644 --- a/assets/controllers/signer_manager.js +++ b/assets/controllers/signer_manager.js @@ -14,10 +14,17 @@ export async function getSigner() { if (session) { if (remoteSigner) return remoteSigner; if (remoteSignerPromise) return remoteSignerPromise; - remoteSignerPromise = createRemoteSigner(session).then(signer => { - remoteSigner = signer; - return signer; - }); + + remoteSignerPromise = createRemoteSigner(session) + .then(signer => { + remoteSigner = signer; + return signer; + }) + .catch(error => { + // Reset promise on failure so next call can retry + remoteSignerPromise = null; + throw error; + }); return remoteSignerPromise; } // Fallback to browser extension @@ -53,6 +60,26 @@ export function getRemoteSignerSession() { async function createRemoteSigner(session) { remoteSignerPool = new SimplePool(); - return await BunkerSigner.fromURI(session.privkey, session.uri, { pool: remoteSignerPool }); + + // Add timeout to prevent hanging indefinitely + const timeoutPromise = new Promise((_, reject) => { + setTimeout(() => reject(new Error('Remote signer connection timeout')), 10000); + }); + + try { + return await Promise.race([ + BunkerSigner.fromURI(session.privkey, session.uri, { pool: remoteSignerPool }), + timeoutPromise + ]); + } catch (error) { + // Clean up on error + if (remoteSignerPool) { + try { remoteSignerPool.close?.([]); } catch (_) {} + remoteSignerPool = null; + } + remoteSigner = null; + remoteSignerPromise = null; + throw error; + } }