Files
eng-pad/CLAUDE.md
Kyle Isom 6e5c500786 Update project docs to reflect current state after post-Phase 10 polish
- PROGRESS.md: remove stale known issues (all fixed), add post-Phase 10
  feature polish section covering toolbar redesign, 4 pen sizes, line/box/move
  tools, edge swipe nav, page reorder, notebook rename, filter/sort, JPG
  export, clipboard ops, startup state restoration, and DB migrations
- PROJECT_PLAN.md: add Phase 11 (Server Sync Integration) and Phase 12
  (Notebook Backup/Export) with step breakdowns
- DESIGN.md: add Tools table, sync architecture section, backup/export design,
  JPG export, stroke styles, startup state restoration, edge swipe nav; update
  rendering strategy (3-layer compositing), source tree, schema, and pen sizes
- CLAUDE.md: update build commands, architecture, source tree, and key
  conventions to match current codebase

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 20:49:24 -07:00

111 lines
6.7 KiB
Markdown

# 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.