# 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)
