# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview eng-pad is an Android note-taking app built around notebooks with an EMR pen as the primary input method. Target devices are the Supernote Manta (Android 11) and Daylight DC-1 (Android 13). Minimum API level is Android 11 (API 30). ## Build Commands ```bash make all # lint -> test -> build make build # Compile debug + release APKs make test # Run unit tests make lint # Run Android Lint make clean # Clean build artifacts make apk # Build release APK make run # Build, install, and launch on emulator (starts emulator if needed) make devrun # Build, install, and launch on connected USB device make run AVD=Medium_Phone_API_36.0 # Use a specific AVD # Run a single test class: make test-one CLASS=net.metacircular.engpad.data.StrokeBlobTest # Direct Gradle commands: ./gradlew build # Compile + test + lint ./gradlew test # Unit tests only ./gradlew lint # Android Lint only ``` ## Architecture - **Kotlin + Jetpack Compose** for UI chrome (screens, toolbar, dialogs) - **Custom View** (`PadCanvasView`) for the drawing canvas — Compose Canvas lacks `MotionEvent` access needed for stylus input - **Room** (SQLite) for persistence — notebooks, pages, strokes (schema version 3) - **SharedPreferences** for startup state restoration (last notebook, page list flag) - **Single Activity** with Compose Navigation (three routes: notebook list -> page list -> editor) - **Coordinate system**: 300 DPI canonical points. Regular page = 2550x3300pt, large = 3300x5100pt. Scaled to 72 DPI (x0.24) for PDF export. - **Input dispatch**: `TOOL_TYPE_STYLUS` -> draw/erase/select/move, `TOOL_TYPE_FINGER` -> zoom/pan/edge swipe ## Project Documents - **DESIGN.md** — Full technical design (architecture, data model, rendering, tools, source tree) - **PROJECT_PLAN.md** — All implementation steps with checkboxes. Check off steps as completed. - **PROGRESS.md** — What's been done, what's in progress, decisions made. Update after every step. **Keep PROJECT_PLAN.md and PROGRESS.md in sync.** When a step is completed, check it off in PROJECT_PLAN.md and log it in PROGRESS.md. When files are added, update the source tree in both DESIGN.md and this file. ## Source Tree ``` eng-pad/ ├── app/ │ ├── build.gradle.kts -- Module build config │ └── src/ │ ├── main/ │ │ ├── AndroidManifest.xml │ │ ├── kotlin/net/metacircular/engpad/ │ │ │ ├── EngPadApp.kt -- Application class, SharedPreferences │ │ │ ├── MainActivity.kt -- Single activity, Compose NavHost │ │ │ ├── data/ │ │ │ │ ├── db/ -- Room database (v3), DAOs, converters │ │ │ │ ├── model/ -- Entities: Notebook, Page, Stroke, PageSize │ │ │ │ └── repository/ -- NotebookRepository, PageRepository │ │ │ ├── ui/ │ │ │ │ ├── navigation/NavGraph.kt -- Routes, auto-restore last notebook │ │ │ │ ├── notebooks/ -- Library: list, filter, sort, rename + ViewModel │ │ │ │ ├── pages/ -- Page grid, drag-to-reorder + ViewModel │ │ │ │ ├── editor/ -- PadCanvasView, EditorScreen, ViewModel, Toolbar │ │ │ │ ├── export/PdfExporter.kt -- PDF + JPG generation + sharing │ │ │ │ └── theme/Theme.kt -- Material3 high-contrast e-ink theme │ │ │ └── undo/ -- UndoManager, UndoableAction, StrokeActions, SelectionActions │ │ └── res/ │ │ ├── values/ -- strings.xml, themes.xml │ │ ├── drawable/ -- Launcher icons │ │ ├── mipmap-anydpi/ -- Adaptive icon │ │ └── xml/file_provider_paths.xml -- FileProvider config │ └── test/ -- Unit tests (StrokeBlobTest, PageSizeTest, UndoManagerTest) ├── build.gradle.kts -- Root build config ├── settings.gradle.kts -- Project settings (foojay JDK resolver) ├── gradle.properties ├── gradle/libs.versions.toml -- Version catalog ├── Makefile -- Build targets (build, test, lint, run, devrun, apk) ├── CLAUDE.md -- This file ├── README.md ├── DESIGN.md -- Technical design ├── PROJECT_PLAN.md -- Implementation steps └── PROGRESS.md -- Completion tracking ``` ## Key Conventions - Stroke points are packed as little-endian float BLOBs: `[x0,y0,x1,y1,...]` - All coordinates are in canonical space (300 DPI). Screen transform via `Matrix`. - Grid drawn in **screen space** with pixel-snapped positions (not canonical space) for uniform squares. Cached in a grid bitmap, redrawn only on zoom/pan/resize. - **4 pen sizes**: 0.38mm (4.49pt), 0.5mm (5.91pt), 0.6mm (7.09pt), 0.7mm (8.27pt) at 300 DPI. - Single PEN tool with long-press for size selection; remembers last size. - **Line styles** stored in stroke `style` DB column: plain, dashed, arrow, double_arrow. - LINE tool with long-press for style selection; BOX tool for rectangles. - MOVE tool for tap-and-drag stroke relocation. - Anti-aliasing disabled on all paint objects for crisp e-ink rendering. - Screen-resolution backing bitmap with incremental stroke addition (no full redraw on each new stroke). - Viewport: page always fills screen, pan clamped to edges, dynamic min zoom. - Edge swipe navigation: finger swipe from screen edge -> previous/next page. - Line snap: hold pen still 1.5s to snap to straight line (60pt movement threshold). - Hardware palm rejection only (EMR digitizer). - Startup state restoration via SharedPreferences (last notebook ID, page list flag). - Notebook `lastPageId` tracks resume position per-notebook. - Clipboard: cut/copy/paste with toolbar buttons shown contextually. - Export: PDF (multi-page, 72 DPI) and JPG (single page, 300 DPI) via share intents.