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