From 7a49e9646cdfb976502c3cb1a3d2bded5fdaee47 Mon Sep 17 00:00:00 2001 From: Chad Curtis Date: Sat, 28 Mar 2026 09:43:43 -0500 Subject: [PATCH] Bypass nudge for encrypt and decrypt, remove phase-transition toast Encrypt and decrypt operations now call the signer directly without nudge/timeout/retry wrapping. The sign operation already provides the user-facing nudge when approval is needed, so the encrypt nudge was redundant noise. Phase-transition toast and related constants removed as dead code. --- src/lib/signerWithNudge.ts | 50 +++----------------------------------- 1 file changed, 3 insertions(+), 47 deletions(-) diff --git a/src/lib/signerWithNudge.ts b/src/lib/signerWithNudge.ts index 6c387d6b..297fd409 100644 --- a/src/lib/signerWithNudge.ts +++ b/src/lib/signerWithNudge.ts @@ -2,7 +2,7 @@ import type { NostrEvent, NostrSigner } from '@nostrify/types'; import { createElement } from 'react'; import { toast } from '@/hooks/useToast'; import { androidResume } from '@/lib/androidResume'; -import { NudgeToastContent, PhaseToastContent } from '@/components/SignerToastContent'; +import { NudgeToastContent } from '@/components/SignerToastContent'; // --------------------------------------------------------------------------- // Constants @@ -11,28 +11,10 @@ import { NudgeToastContent, PhaseToastContent } from '@/components/SignerToastCo /** Show the nudge toast after this delay if a signer op is still pending. */ const NUDGE_DELAY_MS = 4_000; -/** Longer delay for decrypt operations — auto-approve is common and nudging - * too early sends the user to the signer with nothing to approve. */ -const NUDGE_DELAY_DECRYPT_MS = 10_000; /** Hard timeout — reject the op entirely after this long with no response. */ const HARD_TIMEOUT_MS = 45_000; -/** - * Event kinds whose content is encrypted by the user's signer before signing. - * A signEvent for one of these kinds immediately after a nip44 encrypt is - * treated as the second phase of the same operation (encrypt-then-sign), and - * a phase-transition toast is shown so the user knows a second approval is - * coming. - * - * Only kinds where Ditto calls `user.signer.nip44.encrypt()` then immediately - * `createEvent()` qualify — DM gift-wraps use ephemeral random signers and - * are excluded. - */ -const ENCRYPTED_CONTENT_KINDS = new Set([ - 10000, // Mute list (NIP-51, private items encrypted to self) - 30078, // App settings (NIP-78, content encrypted to self) -]); /** Max number of automatic retries on Android foreground resume. */ const MAX_RETRIES = 2; @@ -174,16 +156,6 @@ function showSuccessToast(opType: OpType): void { toast({ title: `${verb} approved`, duration: 3000, variant: 'success' }); } -function showPhaseTransitionToast(signKind: number | undefined): void { - const android = isAndroid(); - const label = signKind !== undefined ? KIND_LABELS[signKind] : undefined; - const signDesc = label ? `approve ${label} signing` : 'approve signing'; - const message = `Encryption approved — now ${signDesc} in your signer app.`; - - const description = createElement(PhaseToastContent, { message, android }); - - toast({ title: 'Step 1 complete', description, duration: 8000 }); -} // --------------------------------------------------------------------------- // Core: run a signer operation with nudge + retry logic @@ -244,7 +216,7 @@ async function runWithNudge(op: () => Promise, opts: RunOpts): Promise void) | undefined; - const delay = opType === 'decrypt' ? NUDGE_DELAY_DECRYPT_MS : NUDGE_DELAY_MS; + const delay = NUDGE_DELAY_MS; const nudgeTimer = setTimeout(() => { nudgeFired = true; const handle = showNudgeToast({ @@ -344,11 +316,6 @@ export function signerWithNudge( signer: NostrSigner, isBunkerConnected?: () => boolean, ): NostrSigner { - // Multi-phase state: set to true when a nip44 encrypt completes with the - // nudge shown. Cleared on the next signEvent. Used to detect encrypt-then-sign - // flows for kinds whose content is encrypted by the user's signer. - let pendingEncryptNudge = false; - /** Run an op and return just the value (discarding nudge metadata). */ function run(op: () => Promise, kind: number | undefined, opType: OpType): Promise { return runWithNudge(op, { kind, opType, isBunkerConnected }).then((r) => r.value); @@ -358,13 +325,6 @@ export function signerWithNudge( getPublicKey: () => run(() => signer.getPublicKey(), undefined, 'sign'), signEvent: (event: NostrEvent) => { - // Show a phase-transition toast when signing an event whose content was - // just encrypted by the user's signer and the nudge was shown for that - // encrypt. Only fires for kinds we know use encrypt-then-sign. - if (pendingEncryptNudge && ENCRYPTED_CONTENT_KINDS.has(event.kind)) { - showPhaseTransitionToast(event.kind); - } - pendingEncryptNudge = false; return run(() => signer.signEvent(event), event.kind, 'sign'); }, }; @@ -381,11 +341,7 @@ export function signerWithNudge( }) { return { encrypt: (pubkey: string, plaintext: string) => - runWithNudge(() => crypto.encrypt(pubkey, plaintext), { kind: undefined, opType: 'encrypt', isBunkerConnected }) - .then(({ value, nudgeFired }) => { - pendingEncryptNudge = nudgeFired; - return value; - }), + crypto.encrypt(pubkey, plaintext), decrypt: (pubkey: string, ciphertext: string) => crypto.decrypt(pubkey, ciphertext), };