Repository navigation
Conversation
- Add folder permission prompt for linked image dirs - Implement DocumentImagePathPolicy with path traversal safety - Serve resolved content:// URIs via capacitor_content bridge - Fix truthy grant check bug in access decision logic - Verify 716 Vitest and 134 JUnit tests pass cleanly
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Opening a Markdown file through the document picker grants the app access to that file alone, so a relative destination such as
could not be read: Muya resolved it tofile://images/cover.png, which the WebView refuses to load, and the block rendered as "Load image failed". Documents that keep their images in a sibling folder therefore only rendered on desktop.This resolves those destinations through a persisted SAF folder grant for the document's own folder, offered once with the system picker and remembered for later opens.
Type of change
Changes
Native
resolveDocumentImages({ sourceUri, sources })reports whether the document's folder is reachable and resolves the given relative destinations to readablecontent://documents.supportedis false for providers whose document ids carry no directory component (cloud drives), where a relative local image could never resolve and no offer should be shown.requestDocumentImageFolderAccess({ sourceUri })opensACTION_OPEN_DOCUMENT_TREEwithEXTRA_INITIAL_URIon the document (API 26+) so the picker lands in the document's own folder, then persists read access.DocumentImagePathPolicykeeps the path arithmetic Android-free and unit-testable. It picks the most specific covering tree, clamps..inside the granted tree so a crafted Markdown file cannot reach anything the user did not grant, understands volume roots such asprimary:, and rejects opaque (cloud) ids instead of guessing.Web
androidImages.tsscans the document for relative destinations, arms the existingMarkTextAndroidImageResolverhook, and also derives sibling URIs synchronously from the granted tree — so an image typed into the document after it opened still resolves without another bridge round trip.LocalImageAccessPrompt.vueoffers the grant once, before the document renders, so images appear on first paint instead of after a reopen.appExitDecisions.tsanswers the offer with Back.pdfExportHtml.tsrewrites relative destinations to content URIs, because the native print WebView has no Capacitor local server and the live editor'shttp://localhost/...form would not load.Test plan
pnpm buildpnpm android:syncVerification
pnpm typecheckpnpm lint— 0 warningspnpm test— 83 files, 732 testsDocumentImagePathPolicyTestcasespnpm android:syncand:app:assembleDebugimages/folder, accepted the folder offer, and confirmed the images render. Repeated on several other documents and image folders.Screenshots
Images stored beside the document, rendering in the editor (Samsung Galaxy A15, Android 16 / API 36). The document below is a 23-image tutorial whose Markdown only uses
:Note: To view the Markdown file for the attached image and the "images" folder containing the corresponding image, see the following link:
20240527-Resolucion-Diferencia-entre-Tamaño-en-píxeles-y-ppp
Android notes
takePersistableUriPermission(READ)...is clamped, and every candidate is verified with a metadata query before its URI is handed to the WebView._capacitor_content_path, so no new file copying or caching was added.Reviewer notes
/storage/emulated/0/...still becomesfile://and stays unrendered. Mapping a filesystem path back to a provider document id is provider-specific and is intentionally left out.DocumentGrantPolicyledger, so cleanup never releases it. That is deliberate — releasing it would break images for a document the user still has — but it does mean user-granted folder grants accumulate outside the existing cap accounting. Happy to fold it into the ledger with a new kind and a reference set if you want it bounded.