diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/app.js | 19 | ||||
| -rw-r--r-- | src/ark/manager.js | 14 |
2 files changed, 33 insertions, 0 deletions
@@ -2779,6 +2779,25 @@ function hasRecentIncoming() { // ---------------------------------------------------------------- Receive function receiveTab() { + // An Ark payment landed — same celebration as an on-chain receive, dismissed + // with a tap (the ack persists in the ark state so it shows exactly once). + const arkUnseen = ark && ark.state ? ark.unseenReceives() : []; + if (arkUnseen.length) { + const amt = arkUnseen.reduce((n, m) => n + m.amountSat, 0); + return h( + 'div', + { + class: 'card col', + style: 'align-items:center;text-align:center;gap:14px;cursor:pointer;padding:48px 20px', + onClick: () => { ark.ackReceives(); render(); }, + }, + h('div', { class: 'check-badge' }, '✓'), + h('h2', { style: 'margin:0' }, t('paymentReceived')), + amt ? h('div', { class: 'amount-pos', style: 'font-size:18px' }, '+' + fmtAmount(amt) + ' ' + unitLabel()) : null, + h('div', { class: 'small muted' }, t('tapToProceed')) + ); + } + // A payment landed on the shown address (the fresh index advanced past what // the user last saw) — celebrate, and wait for a tap before showing the next. // Until receiveSeenIndex has been baselined (post-scan, in enterWallet) it diff --git a/src/ark/manager.js b/src/ark/manager.js index b2d01ce..1f21159 100644 --- a/src/ark/manager.js +++ b/src/ark/manager.js @@ -122,6 +122,20 @@ export class ArkManager { const sum = (st) => this.state.vtxos.filter((v) => v.state === st).reduce((n, v) => n + v.amountSat, 0); return { spendableSat: sum('spendable'), pendingSat: sum('pending') }; } + + // Receives newer than the last acknowledgement — the UI's "Payment + // received!" celebration. Recency-guarded like the on-chain equivalent so an + // old payment never celebrates when a wallet is opened much later. + unseenReceives() { + const ack = this.state.receiveAckTs || 0; + const cutoff = Date.now() - 2 * 3600 * 1000; + return this.state.movements.filter((m) => + m.type === 'receive' && m.status === 'complete' && m.ts > ack && m.ts > cutoff); + } + ackReceives() { + this.state.receiveAckTs = Date.now(); + this._save(); + } vtxos() { return this.state.vtxos.slice(); } movements() { return this.state.movements.slice(); } pendingActions() { return this.state.actions.filter((a) => !['done', 'failed'].includes(a.step)); } |
