{{ effectiveMethod === 'lightning' ? 'Invoice' : effectiveMethod === 'ark' ? 'Destination' : 'Address' }}
+{{ destDisplay }}
+Creates a {{ methodLabel }} token you can share — sats leave your balance when it's redeemed.
+Not enough {{ methodLabel }} balance for this amount.
+Sweeps the entire on-chain balance minus network fees.
+Network fees are deducted on top of the amount.
+ +How do you want to read the QR?
+{{ scanStatus || 'Point the camera at a Lightning invoice, Bitcoin address, Cashu or Fedimint code' }} @@ -282,7 +300,9 @@ function goBack() { if (pane.value === 'amount') { error.value = '' goTo('scan', 'back') - nextTick(() => { if (!liveCameraUnavailable.value) startScanning() }) + // Only relight the camera when that's what the user chose; otherwise + // they land back on the scan/upload chooser. + nextTick(() => { if (scanChoice.value === 'camera' && !liveCameraUnavailable.value) startScanning() }) } else if (pane.value === 'success') { close() } @@ -295,6 +315,16 @@ const isScanning = ref(false) // open) — the fallback buttons stay hidden until it resolves, so they don't // flash for a second on every open. const autoStarting = ref(false) + +// Camera-vs-photo chooser, shown on EVERY open (user request 2026-07-23): +// nothing starts until the user picks, and Back from a later pane returns to +// the live camera only if that's what they chose. +const scanChoice = ref<'unset' | 'camera'>('unset') + +function chooseCamera() { + scanChoice.value = 'camera' + void nextTick(() => startScanning()) +} const scanStatus = ref('') const scanStatusIsError = ref(false) const cameraError = ref(false) @@ -709,7 +739,8 @@ function close() { watch(() => props.show, (open) => { if (open) { resetAll() - nextTick(() => { if (!liveCameraUnavailable.value) startScanning() }) + // No auto-start: the chooser interstitial owns the first move every time. + scanChoice.value = 'unset' } else { stopScanning() }