Tapping a file in the Files tab downloaded it and went straight to the
Android "Open with" chooser or the iOS share sheet. It now opens the
reader's attachment preview for the types that preview can show, and
hands only the rest to another app, as before.
- `filePreviewKind` (`src/lib/file-preview.ts`) builds on the reader's
`previewKindFor` and adds source code and config files as text; HTML,
SVG, images React Native cannot decode and PDFs on Android (no in-app
renderer) still go to another app
- files over a cap per type (text 512 KB, .eml 10 MB, images 25 MB,
PDFs 50 MB) open in another app instead; when a node has no size,
the downloaded file is checked
- the preview downloads the file once, with the same authenticated
download as Download, into a temp folder of its own; Open with, Share
and Download reuse that copy, so they work without another fetch
- the folder is deleted when the preview closes, or left to the
stale-export sweep, which now also clears preview folders, once
another app got the file
- the per-file menu offers Preview and "Open with…" instead of the
combined "Preview / Share"
- the shared preview gains a header Open button, an optional Download
button, labels on its icon buttons and a fallback when an image does
not decode; the .eml parsing moves into `emlPreviewFromBytes`, which
the reader uses too
Follow-up to the direct-view fix. No behaviour change on the happy path,
but the handoff is now easier to reason about and covered by tests.
- Use `File.contentUri` from the expo-file-system 19 API instead of the
legacy `getContentUriAsync`, dropping the `expo-file-system/legacy`
import. Same FileProvider, one less round trip through the bridge.
- Pull the intent launch into `openWithViewer`, which returns false when
the handoff didn't happen, so the fallback reads as a decision rather
than as an empty catch. It also no longer swallows the reason silently.
- Rewrite the expo-sharing comment above `shareAttachment`: it warns
against pre-translating to a content URI, which is still true for every
`Sharing.shareAsync` call but is exactly what the new VIEW path has to
do. Note why `downloadAttachment` keeps the share sheet as well.
- Record why FLAG_ACTIVITY_NEW_TASK is deliberately absent: the module
launches via startActivityForResult, which a new task would cancel.