diff options
| author | Adam Soltys <[email protected]> | 2026-06-24 13:53:29 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-06-24 13:53:29 -0700 |
| commit | b78b9a1c7e4e42b7f673b0e3f92424a762bd0986 (patch) | |
| tree | 1c4c4b925e520501ed73f92e67ca3c6724b59d12 /src/app.js | |
| parent | eb299830a2611a45e997bc729176ede81c5eead2 (diff) | |
| download | coinosv3-b78b9a1c7e4e42b7f673b0e3f92424a762bd0986.tar.gz coinosv3-b78b9a1c7e4e42b7f673b0e3f92424a762bd0986.zip | |
Offer passive reclaim vs immediate revoke for gifts
The reserved-coin button is now "Reclaim". Tapping it prompts a choice:
- Reclaim (free): just un-reserves the coin so a future payment can
spend it — no fee, but the link stays claimable until then.
- Revoke now (pays a fee): sweeps the coin back immediately, killing
the link once it confirms.
New/updated strings translated across all 19 locales.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Diffstat (limited to 'src/app.js')
| -rw-r--r-- | src/app.js | 27 |
1 files changed, 19 insertions, 8 deletions
@@ -755,18 +755,19 @@ function giftCard() { const label = u ? fmtAmount(u.value) + ' ' + unitLabel() : id.slice(0, 12) + '…'; if (ui.revokeId === id) { return h('div', { class: 'col gap6' }, - h('span', { class: 'small muted' }, t('giftRevokeConfirm')), - h('div', { class: 'row gap6' }, - ui.busy - ? h('button', { class: 'btn-primary grow', disabled: true }, h('span', { class: 'spinner' })) - : h('button', { class: 'btn-primary grow', onClick: () => doRevoke(id) }, t('giftRevoke')), - h('button', { class: 'btn-ghost grow', onClick: () => { ui.revokeId = null; render(); } }, t('back')) - ) + h('span', { class: 'small muted' }, t('giftReclaimPrompt')), + ui.busy + ? h('button', { class: 'btn-primary btn-block', disabled: true }, h('span', { class: 'spinner' })) + : h('div', { class: 'row gap6' }, + h('button', { class: 'btn-ghost grow', onClick: () => doReclaim(id) }, t('giftReclaim')), + h('button', { class: 'btn-primary grow', onClick: () => doRevoke(id) }, t('giftRevoke')) + ), + ui.busy ? null : h('button', { class: 'btn-ghost btn-block', onClick: () => { ui.revokeId = null; render(); } }, t('back')) ); } return h('div', { class: 'row between' }, h('span', { class: 'small mono' }, label), - h('button', { class: 'btn-sm', onClick: () => { ui.revokeId = id; render(); } }, t('giftRevoke')) + h('button', { class: 'btn-sm', onClick: () => { ui.revokeId = id; render(); } }, t('giftReclaim')) ); }) ) @@ -774,6 +775,16 @@ function giftCard() { ); } +// Passive reclaim: just free the coin for a future payment (no fee, no +// broadcast). The link stays claimable until the coin is actually spent. +function doReclaim(id) { + wallet.unreserve(id); + ui.revokeId = null; + toast(t('giftReclaimed')); + render(); +} + +// Active revoke: spend the coin back now (pays a fee), killing the link. async function doRevoke(id) { if (wallet.offline) { toast(t('scanOffline')); return; } ui.busy = true; |
