Skip to content

refactor(media): unify file and media previews across clients - #9253

Merged
juliusmarminge merged 8 commits into
mainfrom
t3code/mobile-media-viewers
Sep 3, 2026
Merged

juliusmarminge merged 8 commits into
mainfrom
t3code/mobile-media-viewers

Conversation

@juliusmarminge

@juliusmarminge juliusmarminge commented Sep 2, 2026 •

Copy link
Copy Markdown
Member

What changed

  • Moved markdown file-link parsing, media-source resolution, signed URL state, and media-action availability into client-runtime so web and mobile use the same rules.
  • Routed expanded web videos through the shared streaming player, including URL refresh and retry.
  • Routed every iOS video through AVKit and every iOS image, PDF, and HTML preview through Quick Look.
  • Moved media actions to a long-press on the thumbnail and removed the redundant in-player controls.

Native long-press menus on markdown file chips are in #9258.

Why

The web and mobile clients had separate path parsers, media resolvers, URL lifecycle code, and viewer paths. The copies had already drifted. Some videos downloaded before playback, expired URLs left expanded viewers stuck, and iOS media sometimes opened in React Native viewers instead of AVKit or Quick Look.

This puts the shared decisions in one package and leaves each client responsible only for presentation. On iOS, native viewers own media playback and document preview.

UI changes

Before: clipped initial video controls After: AVKit controls fill the thumbnail

Pre-fix tap and long-press race reproduced on device: screen recording

Testing

  • 40 focused mobile file, markdown, and media tests
  • Mobile TypeScript typecheck
  • TypeScript lint and formatting checks for changed files
  • Native Swift and Kotlin static checks
  • Physical iPhone 16 Pro pass against a disposable LAN environment, covering workspace and external files, images, videos, HTML, PDFs, attachments, composer drafts, markdown embeds, thumbnail long-press menus, AVKit, and Quick Look

Checklist

Created with gpt-5.6-sol using the Codex harness in T3 Code.

Note

Unify file and media preview parsing and playback across web and mobile

  • Adds shared markdown file-link and media-source resolvers in client-runtime (parseMarkdownFileLink, resolveMediaSource) and replaces local parsing implementations in web, mobile, and the t3-markdown module with these shared helpers
  • Reworks video previews on both platforms to use the shared MediaVideoPlayer; mobile removes the Expo-based VideoPlayback and MediaVideoPreviewModal, and web replaces raw <video> rendering in ExpandedImageDialog, MessagesTimeline, and ChatMarkdown with the shared player
  • Moves AssetUrlState and assetUrlStateFromResult into client-runtime; web and mobile asset URL hooks now derive loading/failure/success through the shared mapper instead of local inline checks
  • Unifies media action menus via a shared MediaActionId union and MediaActionsMenu/useMediaActions; both platforms now expose save/share/open-file actions through the same identifiers and long-press surfaces
  • Risk: resolveViewedImageAsset and ViewedImageAsset now only return media-file resources, removing the attachment-resource variant — callers expecting attachment resources from viewed workspace images will break; iOS FilePreview always uses NativeFilePreview and no longer renders MediaImagePreview for actionable images; MediaVideoPlayer no longer renders an expand/maximize control or accepts an onExpand callback

Macroscope summarized 452f18a.


Note

Medium Risk
Broad cross-platform media and preview behavior changes (iOS native viewers, inline vs modal video, shared URL lifecycle) touch high-traffic chat and file flows, though logic is consolidated and covered by focused tests.

Overview
Centralizes markdown file-link parsing, media-source classification, signed asset URL state, and media action IDs in client-runtime, then rewires web and mobile to call those helpers instead of duplicated local heuristics.

Mobile drops bespoke link/path code in favor of parseMarkdownFileLink and resolveMediaSource. Video and attachment UX converges on useMediaActions / MediaActionsMenu (long-press on thumbnails); VideoAttachmentMenu, MediaVideoPreviewModal, and the workspace image prefetch atom are removed. iOS routes all full-screen file previews through Quick Look and full-screen videos through AVKit (with URL re-mint on failure); inline/workspace video stays on Expo Video. Composer and thread attachments share attachmentVideoPreviewSource and attachment-scoped asset resources.

Web plays timeline and markdown videos inline via the shared MediaVideoPlayer (no separate “open video” flow or expand control); expanded dialogs stream through the same player with asset refresh. File attachment clicks no longer auto-open a modal for videos. Context menus align action IDs (save, copy-full-path, etc.) and expose save for videos as well as images.

Docs are updated to describe streaming, long-press save/share, and platform-specific players.

Reviewed by Cursor Bugbot for commit 452f18a. Bugbot is set up for automated code reviews on this repo. Configure here.

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

📱 Native Change Changes the native fingerprint; merging blocks production OTAs until a new store build ships. size:XXL 1,000+ changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant