diff --git a/packages/wallet-webui/src/routes/App.tsx b/packages/wallet-webui/src/routes/App.tsx index e649abaf4..399057537 100644 --- a/packages/wallet-webui/src/routes/App.tsx +++ b/packages/wallet-webui/src/routes/App.tsx @@ -3096,10 +3096,12 @@ function QrScanRoute() { const [, navigate] = useLocation(); const videoRef = useRef(null); const [error, setError] = useState(); + const [rejected, setRejected] = useState(); useEffect(() => { let stream: MediaStream | undefined; let frame = 0; let finished = false; + let lastRejected: string | undefined; const canvas = document.createElement("canvas"); const scan = async () => { const video = videoRef.current; @@ -3120,7 +3122,11 @@ function QrScanRoute() { navigate(`/action/${entry.id}`, { replace: true }); return; } catch { - // Ignore non-Taler QR payloads and keep scanning. + // Not a Taler link: say so, and keep scanning. + if (code.data !== lastRejected) { + lastRejected = code.data; + setRejected(code.data); + } } } } @@ -3164,6 +3170,7 @@ function QrScanRoute() { navigate("/enter")} onCancel={() => navigate("/")} /> diff --git a/packages/wallet-webui/src/screens/QrScannerScreen.tsx b/packages/wallet-webui/src/screens/QrScannerScreen.tsx index 51f47e14f..5638fe6fc 100644 --- a/packages/wallet-webui/src/screens/QrScannerScreen.tsx +++ b/packages/wallet-webui/src/screens/QrScannerScreen.tsx @@ -6,6 +6,8 @@ import { i18n } from "../i18n/runtime.js"; export function QrScannerScreen(props: { videoRef: Ref; error?: string; + /** Content of the last scanned QR code that is not a usable Taler link. */ + rejected?: string; onEnterLink: () => void; onCancel: () => void; }) { @@ -31,6 +33,16 @@ export function QrScannerScreen(props: { muted /> )} + {props.rejected !== undefined && ( +
+

{i18n.str`This wallet action is invalid or unsupported.`}

+

+ {props.rejected.length > 120 + ? `${props.rejected.slice(0, 120)}…` + : props.rejected} +

+
+ )}