# Media & URL preview — handoff ## Summary Handles file uploads, encrypted media, image/video viewers, thumbnails, and URL preview cards (Open Graph, Giphy, etc.). Upload progress shown via upload cards in the composer. ## User-facing behavior - Attach files via `+` button, paste, or drag-drop - Image/video lightbox viewers - Link URLs expand to preview cards in timeline - Encrypted attachments decrypted client-side - Upload progress and cancel ## Architecture ``` UploadCardRenderer / upload state atoms → encryptFile (utils/matrix) for encrypted rooms → matrix uploadContent url-preview/ components → fetch OG metadata, Giphy embed → gated by embed-filters image-viewer/, video-viewer/ — fullscreen media ``` ## Key files | Path | Role | |------|------| | `cinny/src/app/components/upload-card/UploadCardRenderer.tsx` | Upload UI | | `cinny/src/app/state/upload.ts` | Upload state | | `cinny/src/app/state/room/roomInputDrafts.ts` | `TUploadItem` | | `cinny/src/app/utils/matrix.ts` | `encryptFile`, upload helpers | | `cinny/src/app/components/url-preview/` | Link embed cards | | `cinny/src/app/components/image-viewer/` | Image lightbox | | `cinny/src/app/components/video-viewer/` | Video player | | `cinny/src/app/hooks/useMediaAuthentication.ts` | Authenticated media URLs | | `cinny/src/app/hooks/useAuthenticatedMediaUrl.ts` | MXC → HTTP with auth | | `cinny/src/app/components/message/content/` | Image/video/thumbnail content | ## Data model Upload queue in Jotai atom families (per room). Media itself on homeserver as MXC. ## Dependencies - Homeserver media repository config (`useMediaConfig`) - `matrix-js-sdk` encryption APIs ## Integration points - **room-timeline**: attachment messages + URL embeds - **embed-filters**: suppress previews - **editor-and-composer**: upload from composer - **avatar-metadata**: separate pipeline for profile images ## Testing ### Manual 1. Upload image in encrypted room; verify decrypt on receive. 2. Post URL; preview card appears. 3. Block URL pattern via embed filter; no card. 4. Open image in viewer; zoom/navigate. ### Automated - None ## Known issues & gotchas - Media authentication required on some homeservers (`useMediaAuthentication`) - Large file memory on mobile - Giphy embed has separate CSS module ## Future work - Resumable uploads - Blurhash placeholders ## Related docs - [embed-filters HANDOFF](../embed-filters/HANDOFF.md) - [room-timeline HANDOFF](../room-timeline/HANDOFF.md) ## Add your extra things here - `ThumbnailContent.tsx`, `VideoContent.tsx` in message/content/ - Android share materializes files into upload draft (see android handoff)