aboutsummaryrefslogtreecommitdiffstats
path: root/src/app.js
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-06-24 13:53:29 -0700
committerAdam Soltys <[email protected]>2026-06-24 13:53:29 -0700
commitb78b9a1c7e4e42b7f673b0e3f92424a762bd0986 (patch)
tree1c4c4b925e520501ed73f92e67ca3c6724b59d12 /src/app.js
parenteb299830a2611a45e997bc729176ede81c5eead2 (diff)
downloadcoinosv3-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.js27
1 files changed, 19 insertions, 8 deletions
diff --git a/src/app.js b/src/app.js
index b112f02..0ef0787 100644
--- a/src/app.js
+++ b/src/app.js
@@ -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;