From fa2238d8888c9973954b48528c27d48ecf30d574 Mon Sep 17 00:00:00 2001 From: Silberengel Date: Thu, 9 Apr 2026 09:03:27 +0200 Subject: [PATCH] bug-fixes --- package-lock.json | 4 +- package.json | 2 +- src/components/ZapDialog/index.tsx | 2 +- src/index.css | 6 + src/services/lightning.service.ts | 202 +++++++++++++++-------------- src/services/relay-info.service.ts | 7 +- 6 files changed, 121 insertions(+), 102 deletions(-) diff --git a/package-lock.json b/package-lock.json index f98a0469..52e42b68 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "imwald", - "version": "22.3.2", + "version": "22.4.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "imwald", - "version": "22.3.2", + "version": "22.4.0", "license": "MIT", "dependencies": { "@asciidoctor/core": "^3.0.4", diff --git a/package.json b/package.json index ce11a7aa..8e54058b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "imwald", - "version": "22.3.2", + "version": "22.4.0", "description": "Imwald — a user-friendly Nostr client focused on relay feed browsing, publications, and relay discovery", "private": true, "type": "module", diff --git a/src/components/ZapDialog/index.tsx b/src/components/ZapDialog/index.tsx index abd4355f..7a03f036 100644 --- a/src/components/ZapDialog/index.tsx +++ b/src/components/ZapDialog/index.tsx @@ -110,7 +110,7 @@ export default function ZapDialog({ return ( - e.preventDefault()}> +
{t('Zap to')}
diff --git a/src/index.css b/src/index.css index e5b0e29c..6b73285d 100644 --- a/src/index.css +++ b/src/index.css @@ -611,6 +611,12 @@ .yarl__portal { pointer-events: auto; } + +/* Bitcoin Connect (Alby) payment UI: web component on document.body while a Sheet/Dialog may + still be tearing down; same pointer-events issue as the lightbox when nested under Radix. */ +bc-modal { + pointer-events: auto; +} @media (max-width: 768px) { .yarl__slide_captions_container { padding: 12px; diff --git a/src/services/lightning.service.ts b/src/services/lightning.service.ts index c4a8e4df..180ac984 100644 --- a/src/services/lightning.service.ts +++ b/src/services/lightning.service.ts @@ -103,58 +103,62 @@ class LightningService { } return new Promise((resolve) => { + // Close our Radix dialog first; opening bc-modal in the same turn can leave body + // pointer-events stuck so the payment UI is visible but inert (esp. from Sheet / secondary pane). closeOuterModel?.() - let checkPaymentInterval: ReturnType | undefined - let subCloser: SubCloser | undefined - const { setPaid } = launchPaymentModal({ - invoice: pr, - onPaid: (response) => { - clearInterval(checkPaymentInterval) - subCloser?.close() - resolve({ preimage: response.preimage, invoice: pr }) - }, - onCancelled: () => { - clearInterval(checkPaymentInterval) - subCloser?.close() - resolve(null) - } - }) + window.setTimeout(() => { + let checkPaymentInterval: ReturnType | undefined + let subCloser: SubCloser | undefined + const { setPaid } = launchPaymentModal({ + invoice: pr, + onPaid: (response) => { + clearInterval(checkPaymentInterval) + subCloser?.close() + resolve({ preimage: response.preimage, invoice: pr }) + }, + onCancelled: () => { + clearInterval(checkPaymentInterval) + subCloser?.close() + resolve(null) + } + }) - if (verify) { - checkPaymentInterval = setInterval(async () => { - const invoice = new Invoice({ pr, verify }) - const paid = await invoice.verifyPayment() + if (verify) { + checkPaymentInterval = setInterval(async () => { + const invoice = new Invoice({ pr, verify }) + const paid = await invoice.verifyPayment() - if (paid && invoice.preimage) { - setPaid({ - preimage: invoice.preimage - }) + if (paid && invoice.preimage) { + setPaid({ + preimage: invoice.preimage + }) + } + }, 1000) + } else { + const filter: Filter = { + kinds: [kinds.Zap], + '#p': [recipient], + since: dayjs().subtract(1, 'minute').unix() } - }, 1000) - } else { - const filter: Filter = { - kinds: [kinds.Zap], - '#p': [recipient], - since: dayjs().subtract(1, 'minute').unix() - } - if (event) { - filter['#e'] = [event.id] - } - subCloser = client.subscribe( - senderRelayList.write.concat(FAST_READ_RELAY_URLS).slice(0, 4), - filter, - { - onevent: (evt) => { - const info = getZapInfoFromEvent(evt) - if (!info) return + if (event) { + filter['#e'] = [event.id] + } + subCloser = client.subscribe( + senderRelayList.write.concat(FAST_READ_RELAY_URLS).slice(0, 4), + filter, + { + onevent: (evt) => { + const info = getZapInfoFromEvent(evt) + if (!info) return - if (info.invoice === pr) { - setPaid({ preimage: info.preimage ?? '' }) + if (info.invoice === pr) { + setPaid({ preimage: info.preimage ?? '' }) + } } } - } - ) - } + ) + } + }, 0) }) } @@ -228,55 +232,57 @@ class LightningService { return new Promise((resolve) => { closeOuterModel?.() - let checkPaymentInterval: ReturnType | undefined - let subCloser: SubCloser | undefined - const { setPaid } = launchPaymentModal({ - invoice: pr, - onPaid: (response) => { - clearInterval(checkPaymentInterval) - subCloser?.close() - resolve({ preimage: response.preimage, invoice: pr }) - }, - onCancelled: () => { - clearInterval(checkPaymentInterval) - subCloser?.close() - resolve(null) - } - }) + window.setTimeout(() => { + let checkPaymentInterval: ReturnType | undefined + let subCloser: SubCloser | undefined + const { setPaid } = launchPaymentModal({ + invoice: pr, + onPaid: (response) => { + clearInterval(checkPaymentInterval) + subCloser?.close() + resolve({ preimage: response.preimage, invoice: pr }) + }, + onCancelled: () => { + clearInterval(checkPaymentInterval) + subCloser?.close() + resolve(null) + } + }) - if (verify) { - checkPaymentInterval = setInterval(async () => { - const invoice = new Invoice({ pr, verify }) - const paid = await invoice.verifyPayment() + if (verify) { + checkPaymentInterval = setInterval(async () => { + const invoice = new Invoice({ pr, verify }) + const paid = await invoice.verifyPayment() - if (paid && invoice.preimage) { - setPaid({ - preimage: invoice.preimage - }) + if (paid && invoice.preimage) { + setPaid({ + preimage: invoice.preimage + }) + } + }, 1000) + } else { + const filter: Filter = { + kinds: [kinds.Zap], + '#p': [rec], + '#e': [pollEvent.id], + since: dayjs().subtract(1, 'minute').unix() } - }, 1000) - } else { - const filter: Filter = { - kinds: [kinds.Zap], - '#p': [rec], - '#e': [pollEvent.id], - since: dayjs().subtract(1, 'minute').unix() - } - subCloser = client.subscribe( - senderRelayList.write.concat(FAST_READ_RELAY_URLS).slice(0, 4), - filter, - { - onevent: (evt) => { - const info = getZapInfoFromEvent(evt) - if (!info) return + subCloser = client.subscribe( + senderRelayList.write.concat(FAST_READ_RELAY_URLS).slice(0, 4), + filter, + { + onevent: (evt) => { + const info = getZapInfoFromEvent(evt) + if (!info) return - if (info.invoice === pr) { - setPaid({ preimage: info.preimage ?? '' }) + if (info.invoice === pr) { + setPaid({ preimage: info.preimage ?? '' }) + } } } - } - ) - } + ) + } + }, 0) }) } @@ -292,15 +298,17 @@ class LightningService { return new Promise((resolve) => { closeOuterModel?.() - launchPaymentModal({ - invoice: invoice, - onPaid: (response) => { - resolve({ preimage: response.preimage, invoice: invoice }) - }, - onCancelled: () => { - resolve(null) - } - }) + window.setTimeout(() => { + launchPaymentModal({ + invoice: invoice, + onPaid: (response) => { + resolve({ preimage: response.preimage, invoice: invoice }) + }, + onCancelled: () => { + resolve(null) + } + }) + }, 0) }) } diff --git a/src/services/relay-info.service.ts b/src/services/relay-info.service.ts index f2052db3..a267cd76 100644 --- a/src/services/relay-info.service.ts +++ b/src/services/relay-info.service.ts @@ -187,7 +187,12 @@ class RelayInfoService { }) return data } catch (err) { - logger.warn('[RelayInfo] NIP-11 fetch threw', { url, err }) + // Browser NIP-11 is often cross-origin without CORS → TypeError / "NetworkError". Expected; Firefox still logs CORS separately. + if (err instanceof TypeError) { + logger.debug('[RelayInfo] NIP-11 fetch failed (likely CORS or network)', { url }) + } else { + logger.warn('[RelayInfo] NIP-11 fetch threw', { url, err }) + } return undefined } }