Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Oculus Mobile

Shared component of both the Petrarca Project and the Boccaccio Project — Android companion to Oculus

Oculus Mobile is the Android counterpart to the Electron desktop app Oculus: a document-scanning tool for turning photos of physical pages into usable images. It is built with React and Capacitor instead of Electron, targeting Android as a native app while sharing the same core editing pipeline (filters, crop, perspective straightening) as the desktop version.

This is a reduced-functionality counterpart to the desktop app, not a like-for-like port — see Differences from the desktop app for exactly what was left out and why.


Table of Contents


Architecture Overview

Oculus Mobile is a Capacitor app: a React single-page app running inside a native Android WebView shell, with a small set of native plugins bridging to platform APIs (camera/gallery, filesystem, share sheet). There is no separate main/renderer process split like on desktop — everything, including PDF/ZIP generation, runs client-side inside the WebView, and only file system access and native share/camera dialogs go through Capacitor's plugin bridge.

The app has the same three-view structure as the desktop version, switched directly in App.jsx with no router: Capture, Editor, and Export. State lives in the same kind of single Zustand store (useAppStore.js) — photo batch, selected photo, editor step, export selection — minus everything related to double-page splitting (see below).


Capture

The Capture page (CapturePage) combines two independent ways of getting a photo into the batch, plus an in-app rapid-fire mode:

  • Native camera capture — via the @capacitor/camera plugin (useCamera hook), opening the device's own camera UI (full-screen, per capacitor.config.json) and returning a high-resolution photo (up to 4032×3024, with automatic orientation correction) straight into the batch.
  • Native gallery picker — the same plugin's CameraSource.Photos mode, for adding existing photos from the device's gallery.
  • In-app batch camera — a getUserMedia-based live camera view (useStreamCamera, shared with the desktop app's implementation) for rapidly capturing several pages in a row without leaving a single screen, with a quick flash feedback effect per shot and a running photo count badge.
  • Cache management — a "Clear cache" action wipes the app's native Cache and Data storage directories directly (via @capacitor/filesystem), for a real on-device cleanup rather than just clearing in-memory state.
  • Batch gallery — the same swipeable/paginated photo gallery component as desktop, with per-photo delete and entry points into the Editor and Export views.

Manual Editor

The Editor (EditorPage) mirrors the desktop app's guided 4-step workflow — Filters → Crop → Straighten → Confirm — almost exactly, reusing the same underlying geometry engine (three-straighten.js) and the same step-by-step UX (auto-hiding header overlay, step indicator, prev/next photo navigation within the batch).

  • Step 1 — Filters — brightness, contrast, saturation, sepia, invert, hue rotation, blur, and free rotation, baked into the image via canvas before moving on, identical to the desktop implementation.
  • Step 2 — Crop — drag-to-resize crop rectangle with pixel-accurate mapping between displayed and natural-resolution pixels.
  • Step 3 — Straighten — the same 8-point (4 corners + 4 edge midpoints) Three.js-based perspective correction as desktop, with the same page-size presets (A4/A5/Letter, portrait/landscape, or free/auto).
  • Step 4 — Confirm — side-by-side original-vs-processed comparison, with discard or save-and-replace actions.

Export & Share

ExportPanel covers the same two export formats as desktop, but the whole export pipeline runs in the WebView and hands off to native APIs only for saving/sharing the result.

  • Selective export — choose which batch photos to include, with select-all/deselect-all.
  • Customizable file name — freely editable output file name, with automatic extension handling when switching between formats.
  • ZIP export — sequentially numbered JPEG pages bundled into a ZIP, built client-side with JSZip (rather than in a Node main process, as on desktop).
  • PDF export — one photo per page (A4/Letter, configurable margin, optional "fit to page"), built client-side with jsPDF (rather than pdfkit, as on desktop) — images only, no text/fonts involved.
  • Save to device storage — the exported file is written via @capacitor/filesystem to external/public storage (falling back to the app's Documents directory), automatically finding a free numbered name (file (1).zip, file (2).zip, …) if a file with the same name already exists.
  • Native share sheet — after export, the saved file can be handed directly to Android's native share sheet via @capacitor/share, using the file's native file:// URI.
  • Progress feedback — a live progress indicator during export, mirroring the desktop app's UX.

Differences from the desktop app

Oculus Mobile intentionally ships a subset of the desktop app's functionality, favoring a simpler, phone-friendly workflow over full feature parity:

  • No OpenCV auto-processing pipeline. The desktop app's automatic page-edge detection, one-tap perspective correction, and guided auto-process review flow are not present here — every photo goes through the manual Filters → Crop → Straighten workflow.
  • No double-page-spread support. There is no "double page" capture toggle, no split-line detection, and no ability to turn one photo of an open book/spread into two separate corrected pages — the crop/straighten geometry engine (three-straighten.js) ships without its splitting logic entirely.
  • No PDF import. Extracting images out of an existing PDF to seed the batch (available on desktop) isn't available; only the camera and the native gallery can add photos.
  • No camera-device picker. Since Android exposes camera selection through its own native camera UI, there's no in-app equivalent of the desktop app's video-input-device selection modal.
  • Client-side PDF/ZIP generation. Desktop delegates PDF (pdfkit) and ZIP (JSZip) generation to the Electron main process; the mobile app runs the equivalent generation (jsPDF + JSZip) entirely inside the WebView, since there's no separate native process to hand the work to.
  • Native-storage-aware cache clearing. Unlike desktop, mobile storage is sandboxed per-app, so a dedicated "Clear cache" action was added to let users reclaim space directly from within the app.

Tech Stack

  • Application shell: Capacitor (@capacitor/core, @capacitor/android), Vite
  • UI framework: React 19, Zustand (state management)
  • Native device access: @capacitor/camera (camera & gallery), @capacitor/filesystem (storage read/write, cache clearing), @capacitor/share (native share sheet)
  • 3D/graphics engine: Three.js — shared 8-point perspective-correction engine with the desktop app
  • PDF generation: jsPDF (client-side, WebView)
  • Archiving: JSZip (client-side, WebView)

Project Structure

Oculus-mobile/
├── capacitor.config.json     # App id, web dir, Android camera presentation style
├── index.html
├── src/
│   ├── App.jsx                # View switcher: capture / editor / export
│   ├── main.jsx
│   ├── store/
│   │   └── useAppStore.js     # Zustand store: photos, editor step, export selection
│   ├── hooks/
│   │   ├── useCamera.js       # Capacitor Camera plugin: native capture + gallery picker
│   │   ├── useStreamCamera.js # getUserMedia in-app batch camera (shared logic w/ desktop)
│   │   ├── useFilters.js
│   │   └── useStraighten.js
│   ├── lib/
│   │   ├── three-straighten.js  # Filters baking, crop, perspective warp, page presets (no split)
│   │   ├── pdf-export.js        # Photo batch → PDF (jsPDF, client-side)
│   │   ├── zip-export.js        # Photo batch → ZIP (JSZip, client-side)
│   │   └── share-utils.js       # saveToDownloads / shareFile (Capacitor Filesystem + Share, w/ web fallback)
│   ├── pages/
│   │   ├── CapturePage.jsx    # Camera + gallery + cache clearing
│   │   └── EditorPage.jsx     # Guided 4-step manual editing workflow
│   └── components/
│       ├── CameraCapture/     # Native camera/gallery buttons, in-app batch camera trigger
│       ├── BatchCamera/       # Rapid-fire in-app batch capture modal
│       ├── PhotoGallery/      # Swipeable batch gallery
│       ├── FilterPanel/       # Step 1: image filters
│       ├── CropTool/          # Step 2: crop
│       ├── Straightener/      # Step 3: 8-point perspective correction
│       └── ExportPanel/       # ZIP/PDF export, save & share
└── package.json

About

Oculus Mobile is the Android counterpart to the Electron desktop app Oculus: a document-scanning tool for turning photos of physical pages into images.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages