Заметки, задачи и системные напоминания. Работает полностью на устройстве: без сервера, аккаунта, облачной синхронизации, аналитики и обязательного интернета.
- Оболочка: Tauri 2
- Ядро: Rust (бизнес-логика, SQLite, поиск, повторения, парсинг, шифрование)
- Интерфейс: React 19 + TypeScript + Tailwind CSS v4
- Хранилище: локальная SQLite + FTS5
- Напоминания: Rust + Kotlin (
AlarmManager,NotificationManager,WorkManager) - Цель: подписанный APK для Google Pixel 8a (
arm64-v8a)
Проверенные версии (macOS arm64):
| Компонент | Версия | Где взять |
|---|---|---|
| Rust | 1.97.1 stable | rustup |
| Rust target | aarch64-linux-android |
rustup target add aarch64-linux-android |
| Node | 22.x | — |
| Bun | 1.3.x | пакетный менеджер проекта |
| JDK | 21 | brew install openjdk@21 |
| Android SDK Platform | android-36 |
sdkmanager |
| Android Build-Tools | 36.1.0 |
sdkmanager |
| Android NDK | 27.3.13750724 |
sdkmanager |
Platform-Tools (adb) |
последняя | sdkmanager |
JDK 26 не подходит. Android Gradle Plugin поддерживает JDK 17/21; на 26 сборка падает. Именно поэтому
JAVA_HOMEниже указывает наopenjdk@21.
brew install openjdk@21
brew install --cask android-commandlinetools # даёт sdkmanager
brew install android-platform-tools # даёт adb
export ANDROID_HOME="$HOME/Library/Android/sdk"
mkdir -p "$ANDROID_HOME"
yes | sdkmanager --sdk_root="$ANDROID_HOME" --licenses
sdkmanager --sdk_root="$ANDROID_HOME" \
"platform-tools" "platforms;android-36" "build-tools;36.1.0" "ndk;27.3.13750724"Обязательны для любой Android-команды. Используйте готовый скрипт — он ещё и проверяет, что тулчейн на месте:
source ./scripts/android-env.sh
java -version # должно быть 21.x
cargo --version
adb devicesЧто именно он выставляет:
export PATH="$HOME/.cargo/bin:$PATH"
export JAVA_HOME=/opt/homebrew/opt/openjdk@21
export ANDROID_HOME="$HOME/Library/Android/sdk"
export NDK_HOME="$ANDROID_HOME/ndk/27.3.13750724"
export PATH="$ANDROID_HOME/platform-tools:$PATH"bun install # зависимости фронтенда
bun run dev # только Vite (браузер, без Rust-команд)
bun run build # tsc -b + vite build
bun run check:ts # строгий TypeScript
bun run check:rust # cargo check
bun run lint:rust # clippy с -D warnings
bun run fmt:rust # cargo fmt
bun run test # vitest
bun run test:rust # cargo test
bun run android:init # однократная генерация gen/android
bun run android:dev # запуск на подключённом устройстве с HMR
bun run android:build:debug # debug APK (arm64)
bun run android:build # release APK (arm64)Полная проверка перед сдачей этапа:
source ./scripts/android-env.sh
bun run check:ts
bun run build
cargo fmt --check --manifest-path src-tauri/Cargo.toml
cargo clippy --manifest-path src-tauri/Cargo.toml --all-targets -- -D warnings
cargo test --manifest-path src-tauri/Cargo.toml
bun run test
bun run android:build- На телефоне: Настройки → О телефоне → Номер сборки — нажать 7 раз.
- Настройки → Система → Для разработчиков → Отладка по USB — включить.
- Подключить кабелем, подтвердить отпечаток ключа на экране телефона.
- Проверить:
adb devices— устройство должно бытьdevice, а неunauthorized.
adb install -r src-tauri/gen/android/app/build/outputs/apk/arm64/debug/app-arm64-debug.apkЖивая разработка с горячей перезагрузкой:
bun run android:devЛоги ядра:
adb logcat -s RustStdoutStderr:D Organizer:DKeystore и пароли никогда не попадают в Git — они уже в .gitignore.
Выполнить один раз и сохранить файл и пароли в надёжном месте. Потеря keystore означает невозможность выпустить обновление поверх установленного APK.
mkdir -p "$HOME/.android-keystores"
chmod 700 "$HOME/.android-keystores"
source ./scripts/android-env.sh
keytool -genkeypair -v \
-keystore "$HOME/.android-keystores/organizer-release.jks" \
-alias organizer \
-keyalg RSA \
-keysize 4096 \
-validity 10000 \
-storetype PKCS12keytool спросит пароль хранилища и данные владельца (CN, организация, страна).
Для PKCS12 пароль ключа совпадает с паролем хранилища.
Создайте src-tauri/gen/android/keystore.properties (игнорируется Git):
storeFile=/Users/ВАШ_ПОЛЬЗОВАТЕЛЬ/.android-keystores/organizer-release.jks
storePassword=ВАШ_ПАРОЛЬ
keyAlias=organizer
keyPassword=ВАШ_ПАРОЛЬchmod 600 src-tauri/gen/android/keystore.propertiesКонфигурация подписи активна только когда этот файл существует; иначе release-сборка останавливается с понятным сообщением вместо выпуска неподписанного APK.
bun run android:build
APK=src-tauri/gen/android/app/build/outputs/apk/arm64/release/app-arm64-release.apk
"$ANDROID_HOME/build-tools/36.1.0/apksigner" verify --print-certs "$APK"
adb install -r "$APK"Если на устройстве уже стоит debug-сборка, release с другой подписью поверх не установится. Сначала
adb uninstall dev.local.organizer.
src/ React UI (только интерфейс)
├── app/ провайдеры, роутинг, тема
├── pages/ экраны
├── widgets/ составные блоки экранов
├── features/ notes, tasks, reminders, search, attachments,
│ templates, backup, settings
├── entities/ доменные модели для UI
├── shared/ api, components, validation, hooks, lib, types
└── styles/ Tailwind v4
src-tauri/
├── src/
│ ├── domain/ бизнес-правила
│ ├── application/ commands, use_cases, dto
│ ├── infrastructure/ sqlite, filesystem, encryption, notifications, logging
│ ├── platform/ мост к Android-плагинам
│ ├── error.rs
│ ├── state.rs
│ └── lib.rs
├── migrations/ версионируемые SQL-миграции
├── capabilities/ разрешения Tauri
└── gen/android/ Gradle-проект (генерируется)
Правила, которые не нарушаются:
- React не обращается к SQLite и не содержит бизнес-логики;
- Kotlin содержит только вызовы Android API, без бизнес-логики;
- SQL живёт в repositories, не в Tauri-командах;
- системные напоминания не используют
setTimeout/setInterval.
Приложение не имеет сетевого кода. CSP в tauri.conf.json запрещает любые
внешние источники (default-src 'self'), список разрешений Tauri в
src-tauri/capabilities/default.json намеренно минимален.