Fix critical bugs found in code audit

- MoveStrokesAction.undo(): was offsetting by (0,0), now restores
  original pre-move point data correctly
- Stroke commit flicker: new strokes render incrementally onto existing
  backing bitmap instead of triggering full redraw
- Selection state leak: view-side selection cleared on page navigation
  via onPageNavigated callback
- Initial page fallback: blank canvas prevented if initialPageId
  not found in DB — falls back to first page
- Arrow head Paint: preallocated reusable object, no per-call allocation
- Updated PROGRESS.md with audit findings and backup design notes

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-24 17:35:06 -07:00
parent b18e77177e
commit ba1571011a
5 changed files with 83 additions and 21 deletions

View File

@@ -129,19 +129,57 @@ Tested on DC-1, identified and fixed rendering issues:
- **Line snap**: increased threshold to 60pt (~5mm) and switched to max-distance
tracking to handle EMR stylus hand tremor.
### Code Audit & Bug Fixes (2026-03-24)
Critical/high-priority fixes applied:
- **MoveStrokesAction.undo()**: was offsetting by (0,0) instead of restoring
original positions. Fixed to write back the pre-move point data.
- **Stroke commit flicker**: backing bitmap was fully redrawn on each new
stroke. Fixed with incremental rendering — new strokes draw directly
onto the existing bitmap without clearing.
- **Selection state leak**: view-side selection wasn't cleared on page
navigation. Added `onPageNavigated` callback.
- **Initial page fallback**: if `initialPageId` isn't found in DB,
fall back to first page instead of showing blank canvas.
- **Arrow head Paint allocation**: preallocated reusable Paint object
instead of allocating per drawArrowHeads() call.
Known issues still to address:
- CopyStrokesAction uses `takeLast(n)` to find new stroke IDs — fragile
- No mutex guarding concurrent page navigation + paste operations
- Grid redrawn every frame (could be cached)
## Backup Design (Not Yet Implemented)
Notebook backup as a zip file:
- Export: `notebook_title.engpad.zip` containing:
- `notebook.json` — notebook metadata (title, page_size, page count)
- `pages/` directory with one JSON per page:
- `pages/001.json` — page metadata + strokes array
- Each stroke: `{penSize, color, style, points: [x0,y0,x1,y1,...]}`
- Points stored as JSON float arrays (portable, human-readable)
- Import: parse zip, create notebook + pages + strokes in DB
- Could be shared via Android share intents like PDF/JPG export
- Consider: export all notebooks as a single zip for full backup,
or individual notebook export for sharing
Alternative: SQLite `VACUUM INTO` for raw DB backup (simpler but not
portable or human-readable).
## Status
All implementation phases complete. Remaining work:
- Test on Supernote Manta
- Verify line snap behavior on device
- Performance profiling with heavily annotated pages
- Implement notebook backup/restore
## Decisions & Deviations
- **Language**: Kotlin (chosen over Java for better Compose/coroutine support).
- **Storage**: Room/SQLite with packed float BLOBs for stroke points.
- **Palm rejection**: Hardware only (EMR digitizer handles it).
- **Pressure sensitivity**: None — two fixed pen sizes (0.38mm, 0.5mm).
- **Pressure sensitivity**: None — four pen sizes (0.38, 0.5, 0.6, 0.7mm).
- **Coordinate system**: 300 DPI canonical points (scaled to 72 DPI for PDF export).
- **UI framework**: Compose for chrome, custom View for canvas (Compose
Canvas lacks MotionEvent access needed for stylus input).