Skip to content

feat(mobile): page viewer and ContentImage (SUPER-2079) - #7021

Closed
saddlepaddle wants to merge 2 commits into
satya/super-2078-page-assetsfrom
satya/super-2079-mobile-page-viewer
Closed

saddlepaddle wants to merge 2 commits into
satya/super-2078-page-assetsfrom
satya/super-2079-mobile-page-viewer

Conversation

@saddlepaddle

@saddlepaddle saddlepaddle commented Aug 30, 2026 •

Copy link
Copy Markdown
Collaborator

Links

Summary

  • The mobile page viewer: /(authenticated)/page/<id> loads viewUrl top-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. Plus ContentImage (disk cache keyed by storage key), a 512 MB boot-time image-cache bound, and sign-out clearing.

How It Works

  • page.get → viewUrl carries the ticket in its path, so the WebView needs no headers or cookies; the query's staleTime (55 min) holds the URL inside the ticket's window so reopening reuses WebKit's cache instead of minting a fresh URL.
  • onShouldStartLoadWithRequest keeps 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.
  • ContentImage wraps expo-image with cacheKey = storageKey (page.list returns thumbnailStorageKey; the files layer returns storageKey), so a rotated ticket URL is never a fresh download on cellular. OrganizationAvatar adopts 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 typecheck in apps/mobile — the one error is pre-existing on the base branch (useCloudWorkspaceItems / tags, from main's workspace-tags work; untouched here)
  • packages/i18n check clean (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-video intentionally 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-image with cacheKey = 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.
  • OrganizationAvatar is 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.

Written for commit 57b6677. Summary will update on new commits.

Review in cubic

A published page opens at /(authenticated)/page/<id> in a WebView
loading viewUrl top-level, so the page's origin is first-party: its
storage, CSP, and video playback work exactly as on the web, cached by
WebKit, with the ticket riding the URL's path (no headers, no cookies).
Navigation stays on the page's origin; anything else opens in the
browser. The URL is held for the ticket's window so reopening reuses
WebKit's cache. ContentImage wraps expo-image with cacheKey = storage
key, so a rotated ticket URL is never a fresh download; the image disk
cache gets a 512 MB bound at boot, and sign-out clears it. Error copy
reuses the desktop viewer's translated messages, so no new catalog
strings. Discovery UX (where pages appear on mobile) is deliberately
not here.
@coderabbitai

coderabbitai Bot commented Aug 30, 2026 •

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 2c1e002f-91b7-48f3-86e4-131cac7924e7

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Linux extraction on CI adds PageViewerScreen.tsx as a second reference
on the two reused dashboard.pageViewer ids; regenerate so the committed
catalogs match what the check produces.
@github-actions

github-actions Bot commented Aug 30, 2026 •

Copy link
Copy Markdown
Contributor

🚀 Preview Deployment

🔗 Preview Links

Service Status Link
Neon Database (Neon) ✅ View Branch
Vercel API (Vercel) ✅ Open Preview
Vercel Web (Vercel) ✅ Open Preview
Vercel Marketing (Vercel) ✅ Open Preview
Vercel Admin (Vercel) ✅ Open Preview
Vercel Docs (Vercel) ✅ Open Preview

Preview updates automatically with new commits

@saddlepaddle

Copy link
Copy Markdown
Collaborator Author

Closing this — the mobile page viewer is being handed off to someone else rather than landing on this stack.

The branch satya/super-2079-mobile-page-viewer is preserved, so the work here is a starting point rather than a loss. What's on it:

  • PageViewerScreen + the page/[id] route, registered in (authenticated)/_layout.tsx
  • ContentImage — the shared component for images served from the usercontent origin
  • OrganizationAvatar moved onto ContentImage
  • Extracted i18n messages across all 17 locales

Whoever picks this up should know: it is stacked on satya/super-2078-page-assets (#7020) and will need a rebase onto main once that merges. The asset-serving contract it depends on is settled — assets are referenced by path within a version, and page.publish takes assets: [{ path, fileId }].

This branch was previously deployed

1 inactive deployment
preview — 57b6677f Deployed Aug 30, 2026 by saddlepaddle via Deploy Admin #8782
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant