feat(mobile): page viewer and ContentImage (SUPER-2079)
Closed
SA
2mo ago+168+168+012345678901234567890123456789-5-5-0123456789
Links
- Ticket: SUPER-2079
- Viewer spec: Device Content Cache
- Stacked on #7020 → #7019 → #6954.
Summary
- The mobile page viewer:
/(authenticated)/page/<id>loadsviewUrltop-level in a WebView — the page's origin is first-party, so storage, CSP and video playback work exactly as on the web, cached by WebKit. PlusContentImage(disk cache keyed by storage key), a 512 MB boot-time image-cache bound, and sign-out clearing.
How It Works
page.get→viewUrlcarries the ticket in its path, so the WebView needs no headers or cookies; the query'sstaleTime(55 min) holds the URL inside the ticket's window so reopening reuses WebKit's cache instead of minting a fresh URL.onShouldStartLoadWithRequestkeeps navigation on the page's own origin and hands anything else to the system browser.allowsInlineMediaPlayback+mediaPlaybackRequiresUserAction={false}are what let<video>inside a page play inline.ContentImagewraps expo-image withcacheKey = storageKey(page.listreturnsthumbnailStorageKey; the files layer returnsstorageKey), so a rotated ticket URL is never a fresh download on cellular.OrganizationAvataradopts it as the first consumer; the pages grid and attachments use it when they land.- Error copy reuses the desktop viewer's already-translated
dashboard.pageViewer.*messages — zero new catalog strings.
Manual QA Checklist
End-to-end viewing is blocked on the deployed origin (SUPER-2080). Verify in the simulator once it's up:
- Deep link to
/(authenticated)/page/<id>renders a page; a bogus id renders the error state - A page with
<video>plays inline and seeks - External links in a page open in Safari, not the WebView
- Reopening a page within the hour does not refetch its assets (Network inspector)
Testing
bun run typecheckinapps/mobile— the one error is pre-existing on the base branch (useCloudWorkspaceItems/tags, from main's workspace-tags work; untouched here)packages/i18n checkclean (reused ids)- Not sim-verified yet: the viewer has nothing real to load until the Worker deploys — flagged rather than skipped silently
Known Limitations
- No discovery UX on purpose — where pages appear on mobile is being designed separately; this screen is the deep-link target it will push to.
expo-videointentionally absent: page video plays natively in the WebView; the dependency lands with the attachments UI (decision 10).
Summary by cubic
Implements the mobile page viewer at /(authenticated)/page/<id>, loading published pages top-level in a WebView so the page's origin is first-party and storage, CSP, and inline video playback work as on the web. Also adds ContentImage, which caches remote images on disk by storage key instead of URL (SUPER-2079).
Page viewer
- The ticket rides the URL path, so the WebView needs no headers or cookies; a 55-minute stale time keeps the URL inside the ticket's window so reopening reuses WebKit's cache.
- Navigation stays on the page's origin; anything else opens in the system browser.
- Error copy reuses the desktop viewer's already-translated messages, and no discovery UX is included.
- End-to-end viewing is blocked until the deployed origin is updated (SUPER-2080), so the viewer was not sim-verified.
ContentImage
- Wraps
expo-imagewithcacheKey= storage key, so a rotated ticket URL is never a fresh download. - Bounds the image disk cache at 512 MB at boot and clears it on sign-out.
OrganizationAvataris the first consumer; the pages grid and attachments will use it when they land.- Locale catalogs were regenerated to record the viewer's references to the reused error message ids.