diff options
| author | Adam Soltys <[email protected]> | 2026-06-28 09:42:25 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-06-28 09:42:25 -0700 |
| commit | 1e43db6e50e5e1dc7ccb8fb53e7ce68cc580967d (patch) | |
| tree | 3853ac2612ff27a49aef5b629434f22ad4a6907c /src | |
| parent | 0fbeb3c55413fb221d890b3bf3464ebd2aed9fa1 (diff) | |
| download | coinosv3-1e43db6e50e5e1dc7ccb8fb53e7ce68cc580967d.tar.gz coinosv3-1e43db6e50e5e1dc7ccb8fb53e7ce68cc580967d.zip | |
Fix gift creation silently failing on large (many-input) gifts; one Back button
- A many-input gift produces a URL too long for a QR, and qrSvg threw — uncaught,
inside render() — so the click did nothing and showed no error. Wrap the gift QR
in try/catch: render the QR when it fits, otherwise fall back to a 'too large for
a QR — use the link' note. The link itself still works.
- The split-offer card has its own Back; hide the gift sub-view's outer Back while
the split offer is showing, so there aren't two stacked Back buttons.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Diffstat (limited to 'src')
| -rw-r--r-- | src/app.js | 12 | ||||
| -rw-r--r-- | src/i18n.js | 1 |
2 files changed, 10 insertions, 3 deletions
@@ -1549,8 +1549,13 @@ function giftCard() { })(), // A bearer gift uppercases the URL for a smaller alphanumeric QR (the // base32 code is case-insensitive). A locked gift's payload is - // case-sensitive base64url, so it uses a plain byte-mode QR. - h('div', { html: ui.giftLocked ? qrSvg(giftUrl()) : qrSvg(giftUrl().toUpperCase(), { ec: 'L', mode: 'Alphanumeric' }) }), + // case-sensitive base64url, so it uses a plain byte-mode QR. A large + // (many-input) gift can exceed QR capacity — then fall back to the link. + (() => { + let svg = null; + try { svg = ui.giftLocked ? qrSvg(giftUrl()) : qrSvg(giftUrl().toUpperCase(), { ec: 'L', mode: 'Alphanumeric' }); } catch {} + return svg ? h('div', { html: svg }) : h('div', { class: 'small faint', style: 'text-align:center;padding:8px' }, t('giftQrTooLong')); + })(), h('div', { class: 'addr-box break', style: 'width:100%;font-size:12px' }, giftUrl()), h('div', { class: 'row gap6 wrap' }, copyBtn(giftUrl(), t('copyLink')), @@ -2533,7 +2538,8 @@ function giftView() { 'div', { class: 'col', style: 'gap:12px' }, giftCard(), - h('button', { class: 'btn-ghost btn-block', onClick: () => { ui.giftCode = null; ui.giftError = ''; ui.giftMax = false; ui.giftSplitOffer = null; ui.revokeId = null; goBack(() => { ui.giftMode = false; }); } }, t('back')) + // The split-offer card has its own Back; don't show a second one under it. + ui.giftSplitOffer ? null : h('button', { class: 'btn-ghost btn-block', onClick: () => { ui.giftCode = null; ui.giftError = ''; ui.giftMax = false; ui.giftSplitOffer = null; ui.revokeId = null; goBack(() => { ui.giftMode = false; }); } }, t('back')) ); } diff --git a/src/i18n.js b/src/i18n.js index 31cc3c9..66f866d 100644 --- a/src/i18n.js +++ b/src/i18n.js @@ -240,6 +240,7 @@ const STR = { giftDmSending: 'Sending the claim code…', giftDmFailed: 'Couldn’t send the nostr DM. Share this code with them privately:', giftCopyCode: 'Copy claim code', + giftQrTooLong: 'Too large for a QR code — share the link below instead.', claimWithExtension: 'Claim with nostr extension', orEnterCode: 'or paste the claim code', extWrongAccount: 'Your extension is signed in as a different nostr account than this gift is for.', |
