Skip to content

Refactor Scanner into camera-only component and ScanModal wrapper - #748

Draft
tiero wants to merge 1 commit into
masterfrom
claude/camera-modal-refactor-iusadw
Draft

tiero wants to merge 1 commit into
masterfrom
claude/camera-modal-refactor-iusadw

Conversation

@tiero

@tiero tiero commented Jul 9, 2026

Copy link
Copy Markdown
Member

Summary

This PR refactors the Scanner component to separate concerns between the camera capture logic and the modal UI wrapper. The Scanner component is now a pure camera view that only handles video capture and data reporting, while a new ScanModal component manages the modal chrome (header, buttons, implementation switching).

Key Changes

  • Scanner component refactored: Removed all modal UI elements (Header, Content, Buttons) and props related to modal management (close, label, onSwitch). Scanner now only renders the video feed and error state.

  • New ScanModal component: Created a new modal wrapper that handles:

    • Modal presentation with animations
    • Header with close button and implementation switcher
    • Cancel button
    • Keyboard event handling (Escape to close)
    • Scanner implementation switching logic
  • Scanner implementation abstraction: Extracted scanner implementation types and utilities:

    • ScannerImplementation type ('qr' | 'qrmini' | 'mills')
    • scannerImplementationLabel mapping for UI display
    • nextScannerImplementation function for cycling through implementations
    • calculateMiniScanRegion function moved to module level
  • Simplified Scanner props: New minimal interface with only implementation, onData, and onError

  • Updated all Scanner consumers: Replaced direct Scanner usage with ScanModal in:

    • Send/Form.tsx
    • BitcoinDetail.tsx
    • HomeQuickActions.tsx
    • Apps/Assets/Import.tsx
    • Settings/Server.tsx
    • Wallet/Notes/Form.tsx
  • Flow context update: Changed SendInfo.scan boolean to SendInfo.scannedData string to pass captured data directly

Implementation Details

  • Scanner now properly cleans up resources in useEffect return callbacks
  • ScanModal uses React Portal to render at document.body level
  • Keyboard event handling uses capture phase to prevent app-wide Escape handler interference
  • Implementation switching is now owned by ScanModal, not Scanner
  • All modal chrome (animations, buttons, header) is centralized in ScanModal

https://claude.ai/code/session_01EvXfpmSRpupgCShjckrn5d

The camera previously behaved like a page on the navigator stack:
Scanner.tsx drew its own header with a back button, callers swapped
their whole screen for it, and the Scan quick actions pushed SendForm
onto the stack with a sendInfo.scan flag just to open the camera there,
breaking back navigation.

The camera now lives on top of a modal (fixes #742):

- Scanner.tsx is a pure camera view (video + decode engines only);
  it also now stops the camera on unmount for all engines.
- New ScanModal component: portal-based full-screen modal
  (role=dialog, slide-up animation, reduced-motion fallback, Escape
  and explicit close/cancel to dismiss) that emits the sanitized
  capture through onCapture to the invoking component.
- Send form, Notes form, Server settings and Asset import render the
  modal over the page instead of replacing it, so form state stays
  visible and back behaves.
- Home and Bitcoin detail Scan actions open the modal in place; on
  capture they navigate to Send with the recipient prefilled via
  sendInfo.scannedData (replaces the sendInfo.scan hack).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EvXfpmSRpupgCShjckrn5d
@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 79529b6d-d804-4b1c-b60f-10a5a84706b2

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/camera-modal-refactor-iusadw

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@arkana-ai-bot arkana-ai-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR has been open for 30+ days without review. @tiero is anyone looking at this?

@arkana-ai-bot arkana-ai-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR has been open for 40+ days without review. @tiero is anyone looking at this?

@arkana-ai-bot

Copy link
Copy Markdown
Contributor

This PR has been open for 50+ days without review. @tiero is anyone looking at this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants