Browse Source

bug-fixes

imwald
Silberengel 3 weeks ago
parent
commit
fa2238d888
  1. 4
      package-lock.json
  2. 2
      package.json
  3. 2
      src/components/ZapDialog/index.tsx
  4. 6
      src/index.css
  5. 202
      src/services/lightning.service.ts
  6. 7
      src/services/relay-info.service.ts

4
package-lock.json generated

@ -1,12 +1,12 @@ @@ -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",

2
package.json

@ -1,6 +1,6 @@ @@ -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",

2
src/components/ZapDialog/index.tsx

@ -110,7 +110,7 @@ export default function ZapDialog({ @@ -110,7 +110,7 @@ export default function ZapDialog({
return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogContent onOpenAutoFocus={(e) => e.preventDefault()}>
<DialogContent>
<DialogHeader>
<DialogTitle className="flex gap-2 items-center">
<div className="shrink-0">{t('Zap to')}</div>

6
src/index.css

@ -611,6 +611,12 @@ @@ -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;

202
src/services/lightning.service.ts

@ -103,58 +103,62 @@ class LightningService { @@ -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<typeof setInterval> | 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<typeof setInterval> | 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 { @@ -228,55 +232,57 @@ class LightningService {
return new Promise((resolve) => {
closeOuterModel?.()
let checkPaymentInterval: ReturnType<typeof setInterval> | 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<typeof setInterval> | 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 { @@ -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)
})
}

7
src/services/relay-info.service.ts

@ -187,7 +187,12 @@ class RelayInfoService { @@ -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
}
}

Loading…
Cancel
Save