# BadNote Local-first Surface Pen note-taking app with PDF/PPT annotation. All notes, documents, search, and OCR run on your device. No server is required to use the app. ## Features - Ink notes with Surface Pen (pressure, stabilizer, undo/redo) - PDF and PPT import with page-level annotation - Full-text search over note titles, typed text, and OCR results - **Local OCR** — handwriting recognition via Windows built-in OCR (Windows desktop) ## Build (Windows) Prerequisites: - Flutter SDK (3.10+) - Visual Studio Build Tools with **Desktop development with C++** - Developer Mode enabled (for Flutter plugin symlinks) ```powershell flutter pub get flutter build windows --release ``` Output: `build\windows\x64\runner\Release\badnote.exe` The `sqlite3` native binary is **vendored** under `vendor/sqlite3/` (configured via `hooks.user_defines` in `pubspec.yaml`), so the build does not download anything from GitHub — it works fully offline / behind a firewall. To add another platform or architecture, drop its official release binary from [sqlite3.dart releases](https://github.com/simolus3/sqlite3.dart/releases) into `vendor/sqlite3/` (the build validates each file's SHA-256). In mainland China, point pub/Flutter at the local mirrors: ```powershell $env:PUB_HOSTED_URL="https://pub.flutter-io.cn" $env:FLUTTER_STORAGE_BASE_URL="https://storage.flutter-io.cn" flutter pub get flutter build windows --release ``` ## Continuous integration `.gitea/workflows/ci.yml` runs format + analyze + test + Windows release build on a self-hosted **Windows** runner. It is written for runners behind the GFW: actions come from the `gitea.com` mirror, Flutter is expected to be pre-installed on the runner, and pub uses the `flutter-io.cn` mirror. If `gitea.com` is unreachable too, set `DEFAULT_ACTIONS_URL=https://gitea.com` (or your own mirror) in the runner config and use bare `actions/checkout@v4`. ## Architecture ``` lib/ ├── screens/ # UI (notes, PDF/PPT annotator, search, settings) ├── services/ # Local business logic │ ├── database_service.dart # SQLite + FTS5 │ ├── ocr_service.dart # Local OCR orchestration │ ├── stroke_rasterizer.dart # Ink → PNG for OCR │ └── ocr_engine.dart # Platform OCR bridge ├── providers/ # Riverpod state └── widgets/ # Ink canvas, toolbars, thumbnails ``` OCR flow on save: 1. Extract typed text from text-tool strokes 2. Rasterize handwriting strokes to PNG 3. Run Windows OCR on the PNG 4. Merge recognized text into the local FTS index for search ## Optional server The `server/` directory contains an experimental FastAPI backend (sync + EasyOCR). It is **not required** for the desktop app and is kept separately for future multi-device sync experiments. See [server/README.md](server/README.md). ## Development ```bash flutter run -d windows flutter test ```