Skip to content

Merging fix for Android file I/O permissions#28

Merged
kevincarlson merged 3 commits into
claude/bug-opening-a-file-from-recents-fails-with-a-permi-lFadJfrom
master
Mar 30, 2026
Merged

Merging fix for Android file I/O permissions#28
kevincarlson merged 3 commits into
claude/bug-opening-a-file-from-recents-fails-with-a-permi-lFadJfrom
master

Conversation

@kevincarlson

Copy link
Copy Markdown
Member

Android's Storage Access Framework (SAF) grants only a temporary permission for a content:// URI when the user picks a file via the file picker. That permission is tied to the app process and is revoked when the app is killed. Attempting to re-open the same URI from Recents in a new session therefore fails with a permissions error.

Fix — 4 changes:

  1. UriPermissionPlugin.kt (new) — A Tauri Android plugin that calls ContentResolver.takePersistableUriPermission(uri, READ | WRITE). Android will then persist that grant across app restarts in its own permission store.
  2. MainActivity.kt — Registers the plugin via registerPlugin(UriPermissionPlugin::class.java) so Tauri routes the JS invoke call to it.
  3. commands.ts — Adds takePersistableUriPermission(uri), a typed TypeScript wrapper around invoke('plugin:uriPermission|takePersistablePermission', { uri }).
  4. useFileOperations.ts — Calls takePersistableUriPermission in two places:
    • loadDocument() — when a content:// file is opened (covers the file picker path and the Recents path on first open)
    • handleSaveAs() — when a new file is saved to a content:// destination

Both calls are wrapped in try/catch so they are silently ignored on desktop and on URIs that don't support persistable permissions.

claude and others added 3 commits March 22, 2026 13:39
… audit gaps

- Split epub-logic/src/lib.rs (609 lines) into six focused submodules
  (conversion, html, css, nav, opf, table) so every file is ≤ 300 lines
- G1: Block::Image now renders <img src alt title/> and embeds data-URI
  images in OEBPS/Images/ via base64 decoding (new base64 dep)
- G2: Block::Table/TableRow/TableHeader/TableCell now render <table>,
  <thead>/<tbody>, <tr>, <th colspan rowspan>, <td colspan rowspan>
- G3: Inline text content is XML-escaped before HTML wrapping
- G4: Link href values are XML-escaped
- G5: Section <title> content is XML-escaped
- G6/G7: BlockAttrs.text_align and indent produce inline style= attributes
  on <p> and <h*> elements
- G8: TiptapMark::NamedSpanStyle wraps text in <span class="style-...">
- G9: Inline::Text.style_name wraps text in <span class="style-...">
- G10: fo:color, fo:background-color, style:font-name, fo:text-decoration,
  fo:letter-spacing, fo:font-variant and border/padding properties added to
  ODF→CSS mapping
- G11: metadata.creation_date emitted as <dc:date> in OPF
- G12: metadata.description and metadata.subject emitted in OPF
- G13: Embedded images listed in OPF manifest under OEBPS/Images/
- G14: 609-line file size violation resolved by submodule split
- Section titles extracted from first heading block instead of generic "N"
- EpubDocument gains images: Vec<ImageAsset> field; from_tiptap gains
  images parameter for pre-loaded assets from caller
- write_epub_zip writes OEBPS/Images/ directory with embedded image assets
- All 4 existing tests pass; cargo clippy -D warnings clean

https://claude.ai/code/session_01QXTY8ndVt2UpgKFqcJodX5
Formatting-only changes to satisfy the cargo fmt --all -- --check CI gate.
No logic changes.

https://claude.ai/code/session_01QXTY8ndVt2UpgKFqcJodX5
…pg5lF

Refactor EPUB generation: modularize code and add image asset support
@kevincarlson kevincarlson merged commit 61aca09 into claude/bug-opening-a-file-from-recents-fails-with-a-permi-lFadJ Mar 30, 2026
6 checks passed
@AppThere AppThere locked and limited conversation to collaborators Mar 30, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants