aboutsummaryrefslogtreecommitdiffstats
path: root/src/features/zaps.js
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-11-14 22:36:58 -0700
committerAdam Soltys <[email protected]>2026-11-14 22:36:58 -0700
commit1424cc46382266a51123a8425424f3c8cb943e8e (patch)
treee2b21346781566709e7d0e9c6800b6f812661ce7 /src/features/zaps.js
parent933e85020c2cc56b511ff47a73943c92ea1d044a (diff)
downloadcoinosv3-1424cc46382266a51123a8425424f3c8cb943e8e.tar.gz
coinosv3-1424cc46382266a51123a8425424f3c8cb943e8e.zip
A reply, zap or reaction is about the moment of a clip only when you say so. "i zapped and commented on a post from helen yrmom and didn't intend to tie it to the video timestamp but i guess it did by default. maybe we can revisit the ui/flow there so it doesn't do that by default?" (Adam, 2026-11-14). Anything done to a post whose clip had played took the clip's current time: the reply opened as "Comment at 0:12" (an × to drop it), and a zap's or reaction's sheet had nothing showing it at all. Now the time is offered as a toggle, off until tapped — "⏱ About 0:12 in the clip", ✓ when on — in the reply box, the reaction sheet, and both zap sheets (Ark and Lightning); a one-tap zap, which has no sheet, is never tied. Ticked, it goes out as before (the media tag, "[0:12]" before a comment, its mark on the clip's bar). media-moments-feed-test ticks the toggle where it used to rely on the default and checks it starts off; media-timeline, features-smoke and the zap tests pass
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01VMan6UKGJyuGyZFxddYRxS
Diffstat (limited to 'src/features/zaps.js')
-rw-r--r--src/features/zaps.js8
1 files changed, 6 insertions, 2 deletions
diff --git a/src/features/zaps.js b/src/features/zaps.js
index 8e29409..49e457f 100644
--- a/src/features/zaps.js
+++ b/src/features/zaps.js
@@ -12,6 +12,7 @@
// land here directly.
import { t } from '../i18n.js';
+import { momentToggle, mediaClock } from '../media-timeline.js';
import { npubOf } from '../nostr.js';
import { parseZapTarget, zapTargetFromProfile, fetchPayParams, buildZapRequest, requestInvoice, parseLnurlAuth, lnurlAuthKey, lnurlAuthLogin, submitWithdraw } from '../lnurl.js';
import { HDKey } from '@scure/bip32';
@@ -213,7 +214,8 @@ export function zapsFeature(ctx) {
const profile = await wallet.nostrProfile(target.pk);
const lnTarget = zapTargetFromProfile(profile, target.pk);
if (!lnTarget) throw new Error(t('lnZapNoAddress'));
- const t2 = { ...lnTarget, eventId: target.eventId || null, moment: target.moment };
+ // a one-tap zap has no sheet to tick: never tied to a moment
+ const t2 = { ...lnTarget, eventId: target.eventId || null, moment: null };
const p = await fetchPayParams(t2.url);
const msat = sats * 1000;
if (msat < p.minSendable || msat > p.maxSendable) {
@@ -286,7 +288,7 @@ export function zapsFeature(ctx) {
const sign = await zapSigner();
zapRequest = await buildZapRequest({
amountMsat: msat, relays: wallet.nostrRelays(), lnurlBech32: z.target.lnurlBech32,
- recipientPk: z.target.pk, eventId: z.target.eventId || null, moment: z.target.moment, comment: z.comment,
+ recipientPk: z.target.pk, eventId: z.target.eventId || null, moment: z.momentOn ? z.target.moment : null, comment: z.comment,
signFn: sign,
});
}
@@ -517,6 +519,8 @@ export function zapsFeature(ctx) {
maxlength: p.allowsNostr ? '280' : String(p.commentAllowed || 280),
onInput: (e) => { z.comment = e.target.value; } })
: null,
+ p.allowsNostr && z.target && z.target.moment ? h('div', { class: 'row' }, momentToggle(h, z.target.moment, !!z.momentOn, (on) => { z.momentOn = on; render(); },
+ t('mediaTieTo', { time: mediaClock(z.target.moment.seconds) }))) : null,
z.social ? h('div', { class: 'small faint' }, p.allowsNostr ? t('lnZapHintNostr') : t('lnZapHintPlain')) : null),
z.error ? h('div', { class: 'notice err' }, z.error) : null,
h('div', { class: 'row gap6' },