Files
BadNote/README.md
Akiba So 198da00ecd
All checks were successful
CI / Windows build (push) Successful in 7m47s
feat: vault-aligned server v1 + UX polish
Redesign the optional FastAPI companion around vault files (manifest /
PUT/GET/DELETE + OCR jobs) instead of legacy strokes_json notes. Wire a
client Server settings panel for health/login. Polish shell UX: l10n for
settings/home/board, sticky-board empty state, and a narrow-screen
diagnostics FAB.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-05 19:04:48 +08:00

149 lines
6.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# BadNote
Local-first Surface Pen note-taking app with PDF / PPTX / DOCX annotation.
All notes, documents, search, and OCR run on your device. No server is required to use the app.
## Features
- Unified shell: Library · Sticky board · Search · Settings
- Ink notes with Surface Pen (pressure, predictor, undo/redo)
- PDF annotation + native OOXML PPTX/DOCX viewers (no LibreOffice required)
- Infinite sticky board with `[[wikilinks]]` / backlinks
- Full-text search over note titles, typed text, and OCR results
- Always-on diagnostics + one-click diagnostic pack export (Settings)
- Optional self-hosted **BadNote Server** (`/api/v1`: vault assist + OCR jobs) — see [server/README.md](server/README.md)
- **Local OCR** — ONNX when bundled, else Windows WinRT
- WebDAV vault sync (NAS)
## 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` builds a Windows release on a self-hosted **Windows**
runner. Format/analyze/test run but are non-blocking, so a usable `.exe` is
produced whenever the compile itself succeeds. It is written for runners behind
the GFW: the checkout action comes from the `gitea.com` mirror, Flutter is
expected to be pre-installed on the runner, pub uses `flutter-io.cn`, and the
sqlite3 native binary is vendored.
### Self-hosted runner prerequisites
These must hold on the runner machine (they can't be set from the workflow):
1. **Flutter SDK on `PATH`** in the runner's shell (the first build step prints
`flutter --version` and fails fast if it isn't).
2. **Visual Studio Build Tools** with **Desktop development with C++** (MSVC +
Windows SDK) — required to compile the Windows runner and the ONNX Runtime.
3. **The local proxy running** (default `http://127.0.0.1:7890`) so the
`flutter_onnxruntime` build can fetch the ONNX Runtime native lib. Override
via repo secrets `HTTP_PROXY` / `HTTPS_PROXY`, or install ONNX Runtime
system-wide to skip the download.
4. **`gitea.com` reachable** (for the checkout action). If it isn't, switch to
the manual-checkout fallback shown in `ci.yml` (it clones from your own Gitea
instance), or set `DEFAULT_ACTIONS_URL=https://gitea.com` in the runner
config and use bare `actions/checkout@v4`.
5. **Runner in host mode** with a sane work directory — a malformed workspace
path (e.g. `C:\C:\...`) is an `act_runner` config problem, not a workflow one.
## 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 # OCR entry point (delegates to a backend)
│ └── ocr/ # Pluggable OCR backends
│ ├── ocr_backend.dart # Backend interface
│ ├── ocr_backends.dart # Backend selector (ONNX → native)
│ ├── onnx_recognition_backend.dart # Embedded ONNX (cross-platform)
│ ├── native_ocr_backend.dart # OS OCR (Windows WinRT)
│ └── ctc_decoder.dart # Pure-Dart CTC greedy decode
├── 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. Recognize via the active local OCR backend (embedded ONNX if a model is
bundled, otherwise the platform's native OCR)
4. Merge recognized text into the local FTS index for search
## Local OCR
OCR runs entirely on-device through a pluggable backend (`lib/services/ocr/`).
`OcrBackends` selects, in order:
1. **`OnnxRecognitionBackend`** — embedded, cross-platform recognition via
`flutter_onnxruntime` (CPU/iGPU; suited to low-power APUs). Active only when
an ONNX model is bundled.
2. **`NativeOcrBackend`** — the OS built-in OCR (Windows WinRT today).
If no backend is available, OCR is a clean no-op — the app still works.
### Enabling the embedded ONNX model
The model is **not committed** (it is large). Fetch it onto your dev machine
before building so it bundles as an asset:
```bash
tool/fetch_ocr_model.sh # downloads PP-OCRv4 rec ONNX + ppocr_keys_v1.txt
# into assets/models/ocr/ (proxy hint inside)
```
See [assets/models/ocr/README.md](assets/models/ocr/README.md). The recognition
geometry / CTC-blank assumptions (PP-OCRv4 mobile rec, 3×48×W, blank=0) are
documented in `onnx_recognition_backend.dart` and should be verified on-device
against your exact exported model.
> **Windows build note:** the `flutter_onnxruntime` plugin downloads the ONNX
> Runtime native library (v1.22.0) from GitHub at build time. Behind a firewall,
> set `HTTPS_PROXY` for the build (CMake honours it), or install ONNX Runtime
> system-wide and build with `-DUSE_SYSTEM_ONNXRUNTIME=ON
> -DONNXRUNTIME_ROOT_DIR=<path>`.
## 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
```