feat(fs): Abstract storage paths and database initialization for Android data_dir #43

Closed
opened 2026-10-25 13:49:39 +01:00 by harald · 2 comments
Owner

Description

Android restricts arbitrary filesystem access. ink-notes cannot rely on desktop-style home directory lookups (dirs / standard config directories) and must resolve its internal SQLite and vector storage root via Android's native app internal directory.

Scope of Work

  1. Provide a storage abstraction layer:
    • On desktop: continue using default system directories.
    • On Android: resolve the base path via AndroidApp::internal_data_path().
  2. Ensure SQLite initialization via rusqlite builds correctly for the Android NDK:
    • Verify rusqlite uses the bundled feature flag to avoid missing system libsqlite on Android.
  3. Path propagation:
    • Inject the resolved base PathBuf into InkNotesApp state during creation in android_main.

Acceptance Criteria

  • SQLite database and notebook storage initialize correctly inside /data/user/0/eu.pansi.inknotes/files on target.
  • File I/O does not panic or trigger permission denials on fresh app start.
### Description Android restricts arbitrary filesystem access. `ink-notes` cannot rely on desktop-style home directory lookups (`dirs` / standard config directories) and must resolve its internal SQLite and vector storage root via Android's native app internal directory. ### Scope of Work 1. Provide a storage abstraction layer: - On desktop: continue using default system directories. - On Android: resolve the base path via `AndroidApp::internal_data_path()`. 2. Ensure SQLite initialization via `rusqlite` builds correctly for the Android NDK: - Verify `rusqlite` uses the `bundled` feature flag to avoid missing system libsqlite on Android. 3. Path propagation: - Inject the resolved base `PathBuf` into `InkNotesApp` state during creation in `android_main`. ### Acceptance Criteria - SQLite database and notebook storage initialize correctly inside `/data/user/0/eu.pansi.inknotes/files` on target. - File I/O does not panic or trigger permission denials on fresh app start.
Author
Owner

Corrections after checking the code (planned for the future, not started)

  • There is no SQLite, rusqlite or vector storage. Notebooks are folders with JSON files (manifest plus one file per page, assets alongside). The library index is a JSON file too (src/library.rs). The rusqlite/bundled part is not needed.
  • The paths are resolved in these places:
    • storage::default_storage_dir(), used in src/main.rs: notebooks under $XDG_DATA_HOME/~/.local/share/ink-notes/notebooks.
    • autosave::recovery_dir(): $XDG_DATA_HOME/ink-notes/recovery.
    • settings.rs: $XDG_CONFIG_HOME/~/.config, for UI settings.
    • updater.rs: $XDG_CACHE_HOME, not needed on Android.
    • file_picker.rs: $HOME and the XDG user dirs.
  • Proposal: one small module (e.g. paths.rs) with data_dir(), config_dir() and cache_dir().
    • Desktop: XDG as today.
    • Android: AndroidApp::internal_data_path() and external_data_path(), stored once at startup.
    • All the places above call this module.
  • PDF and image import and PDF export use filesystem paths and the built-in file picker. On Android they need the Storage Access Framework (an intent and a content URI), so that part is a separate follow-up.

Revised acceptance criteria:

  • Notebooks, settings and recovery files are created under /data/user/0/eu.pansi.inknotes/files on a fresh install, with no permission errors.
  • The desktop paths do not change.
**Corrections after checking the code** (planned for the future, not started) - There is **no SQLite, rusqlite or vector storage**. Notebooks are folders with JSON files (manifest plus one file per page, assets alongside). The library index is a JSON file too (`src/library.rs`). The `rusqlite`/`bundled` part is not needed. - The paths are resolved in these places: - `storage::default_storage_dir()`, used in `src/main.rs`: notebooks under `$XDG_DATA_HOME`/`~/.local/share/ink-notes/notebooks`. - `autosave::recovery_dir()`: `$XDG_DATA_HOME/ink-notes/recovery`. - `settings.rs`: `$XDG_CONFIG_HOME`/`~/.config`, for UI settings. - `updater.rs`: `$XDG_CACHE_HOME`, not needed on Android. - `file_picker.rs`: `$HOME` and the XDG user dirs. - Proposal: one small module (e.g. `paths.rs`) with `data_dir()`, `config_dir()` and `cache_dir()`. - Desktop: XDG as today. - Android: `AndroidApp::internal_data_path()` and `external_data_path()`, stored once at startup. - All the places above call this module. - PDF and image import and PDF export use filesystem paths and the built-in file picker. On Android they need the Storage Access Framework (an intent and a content URI), so that part is a separate follow-up. Revised acceptance criteria: - Notebooks, settings and recovery files are created under `/data/user/0/eu.pansi.inknotes/files` on a fresh install, with no permission errors. - The desktop paths do not change.
Author
Owner

Teil 1 ist in v0.39.0: src/paths.rs liefert data_dir(), config_dir() und cache_dir().

  • Linux: XDG wie bisher.
  • Windows: %APPDATA% bzw. %LOCALAPPDATA%.
  • Android: android_main setzt einmal AndroidApp::internal_data_path(). Notizbücher, recovery und Einstellungen landen dann darunter.

Noch offen: Prüfung auf einem Gerät, sobald die App dort startet (#42), sowie Import und Export über das Storage Access Framework.

Teil 1 ist in **v0.39.0**: `src/paths.rs` liefert `data_dir()`, `config_dir()` und `cache_dir()`. - Linux: XDG wie bisher. - Windows: `%APPDATA%` bzw. `%LOCALAPPDATA%`. - Android: `android_main` setzt einmal `AndroidApp::internal_data_path()`. Notizbücher, `recovery` und Einstellungen landen dann darunter. Noch offen: Prüfung auf einem Gerät, sobald die App dort startet (#42), sowie Import und Export über das Storage Access Framework.
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: harald/ink-notes#43