From 2e60047382f0f1e012a5d693bcbbe060a070453c Mon Sep 17 00:00:00 2001 From: orveth Date: Fri, 5 Jun 2026 15:07:18 -0700 Subject: [PATCH] fix(send-scanner): navigate before async work Rebased onto post-monorepo master; paths relocated app/ -> apps/web-wallet/app/. Original commits: - fix(send-scanner): pass scanned input via hash, let /send loader resolve --- .../app/features/send/send-scanner.tsx | 95 +++---------------- 1 file changed, 12 insertions(+), 83 deletions(-) diff --git a/apps/web-wallet/app/features/send/send-scanner.tsx b/apps/web-wallet/app/features/send/send-scanner.tsx index cd3c1f77d..6835540be 100644 --- a/apps/web-wallet/app/features/send/send-scanner.tsx +++ b/apps/web-wallet/app/features/send/send-scanner.tsx @@ -5,96 +5,25 @@ import { PageHeaderTitle, } from '~/components/page'; import { QRScanner } from '~/components/qr-scanner'; -import { useExchangeRate } from '~/hooks/use-exchange-rate'; import { useBuildLinkWithSearchParams } from '~/hooks/use-search-params-link'; -import { useToast } from '~/hooks/use-toast'; -import type { Money } from '~/lib/money'; import { useNavigateWithViewTransition } from '~/lib/transitions/view-transition'; -import type { Account } from '../accounts/account'; -import { DomainError, getErrorMessage } from '../shared/error'; -import { useSendStore } from './send-provider'; - -/** - * Converts an amount to the send account currency. - * If the amount is already in the send account currency, returns the amount. - * - * @throws if the exchange rate fails to load - */ -const useConverter = (sendAccount: Account) => { - const otherCurrency = sendAccount.currency === 'BTC' ? 'USD' : 'BTC'; - - const { data: rate } = useExchangeRate( - `${otherCurrency}-${sendAccount.currency}`, - ); - - return (amount: Money) => { - if (!rate) throw new Error('Exchange rate not found'); - - return amount.convert(sendAccount.currency, rate); - }; -}; export default function SendScanner() { - const { toast } = useToast(); const navigate = useNavigateWithViewTransition(); const buildLinkWithSearchParams = useBuildLinkWithSearchParams(); - const sendAccount = useSendStore((state) => state.getSourceAccount()); - const selectDestination = useSendStore((state) => state.selectDestination); - const continueSend = useSendStore((state) => state.proceedWithSend); - - const convert = useConverter(sendAccount); - - const handleDecode = async (input: string) => { - const selectDestinationResult = await selectDestination(input); - if (!selectDestinationResult.success) { - toast({ - title: 'Invalid input', - description: selectDestinationResult.error, - variant: 'destructive', - }); - return; - } - - const { amount } = selectDestinationResult.data; - - if (!amount) { - // Navigate to send input to enter the amount - return navigate(buildLinkWithSearchParams('/send'), { - applyTo: 'oldView', - transition: 'slideDown', - }); - } - - const convertedAmount = - amount.currency !== sendAccount.currency ? convert(amount) : undefined; - const result = await continueSend(amount, convertedAmount); - - if (!result.success) { - const toastOptions = - result.error instanceof DomainError - ? { description: result.error.message } - : { - title: 'Error', - description: getErrorMessage( - result.error, - 'Failed to get a send quote. Please try again', - ), - variant: 'destructive' as const, - }; - - toast(toastOptions); - return; - } - - if (result.next !== 'confirmQuote') { - return; - } - - navigate(buildLinkWithSearchParams('/send/confirm'), { - applyTo: 'newView', - transition: 'slideUp', - }); + const handleDecode = (scannedContent: string) => { + if (!scannedContent) return; + + const hash = `#${scannedContent}`; + // The hash needs to be set manually before navigating or the destination + // route's clientLoader won't see it. + // See https://github.com/remix-run/remix/discussions/10721 + window.history.replaceState(null, '', hash); + navigate( + { ...buildLinkWithSearchParams('/send'), hash }, + { transition: 'slideDown', applyTo: 'oldView' }, + ); }; return (