Wayfinder: Reader media design (GIF, video, embeds) #30

Closed
opened 2026-08-03 15:00:13 +00:00 by TheAnachronism · 1 comment

Destination

An implementable Reader media specification (plus MVP-spec revision and ADR as needed) so the Reader properly displays feed-supplied images/GIFs, direct video files, and YouTube/Vimeo embeds — enough to hand off and build, not the built feature itself.

Notes

  • Domain: Flutter Android tt-rss Viewer (CONTEXT.md). Product language: Reader (not web view / article page).
  • Examples (feed shapes): .scratch/rss-examples/reddit-example.xml (preview GIF <img> + image/generic enclosure + full GIF link); .scratch/rss-examples/twitter-video-example.xml (<img> poster + <video src=…mp4 controls poster=…> via images.weserv.nl).
  • Locked charting decisions:
    • Generic media from article HTML / enclosures — no Reddit/Twitter scrapers.
    • Images/GIFs + direct video files + YouTube/Vimeo embeds; no in-app audio.
    • Prefer full-resolution image/GIF when a better URL is already linkable from content/enclosures.
    • Promote suitable image/video enclosures into inline media (dedupe chips).
    • Video UX: tap-to-play with controls, no autoplay.
    • Stack posture: stay on flutter_html + native players + targeted embeds; WebView remains escape hatch only.
    • Failures: visible failure + open media / open original actions.
    • Revise docs/mvp-spec.md “no in-app audio/video player” to allow in-app video under this design.
  • Current code: lib/reader/reader_page.dartflutter_html + custom <img> TagExtension (Image.network); attachments as ActionChips; no <video> handling.
  • Skills: /grilling, /domain-modeling, /research, /prototype. Prefer decisions and specs over implementation.
  • Tracker: Forgejo via fj; Part of #30; blocking via Blocked by: #n; claim via assignee.
  • Glossary updates only if new product terms crystallise (likely: something for inline media vs attachments).

Decisions so far

Not yet specified

(none — destination reached)

Out of scope

  • List hub Article thumbnail / flavor_image changes — left to ADR-0004 (Grill: assemble Reader media specification and MVP revision)
  • Separate ADR for Reader media stack/policy — trade-offs live in the Reader-media spec + MVP revision (Grill: assemble Reader media specification and MVP revision)
  • In-app audio / podcast player
  • Arbitrary iframe embedding beyond YouTube and Vimeo (v1)
  • Site-specific scrapers or unofficial Reddit/X APIs
  • Making WebView the primary Reader path
  • Server-side feed rewriting / rss.anachronis.dev proxy changes
  • Implementing and shipping the Reader media feature inside this map (destination is the design/spec)
  • Offline caching of media bytes (online-first; cache-ready seams only if an ADR needs them)

Tickets

  • #31 Research: Flutter video/GIF packages for flutter_html Reader
  • #32 Research: YouTube and Vimeo embed approaches for Flutter Reader
  • #33 Grill: full-resolution image/GIF preference rules
  • #34 Grill: enclosure promotion and dedupe rules
  • #35 Grill: YouTube/Vimeo embed UX in swipeable Reader
  • #36 Prototype: Reader media against example RSS entries
  • #37 Grill: assemble Reader media specification and MVP revision
## Destination An implementable **Reader media** specification (plus MVP-spec revision and ADR as needed) so the Reader properly displays feed-supplied images/GIFs, direct video files, and YouTube/Vimeo embeds — enough to hand off and build, not the built feature itself. ## Notes - Domain: Flutter Android tt-rss Viewer (`CONTEXT.md`). Product language: **Reader** (not web view / article page). - Examples (feed shapes): `.scratch/rss-examples/reddit-example.xml` (preview GIF `<img>` + `image/generic` enclosure + full GIF link); `.scratch/rss-examples/twitter-video-example.xml` (`<img>` poster + `<video src=…mp4 controls poster=…>` via images.weserv.nl). - Locked charting decisions: - **Generic** media from article HTML / enclosures — no Reddit/Twitter scrapers. - **Images/GIFs + direct video files + YouTube/Vimeo embeds**; **no** in-app audio. - Prefer **full-resolution** image/GIF when a better URL is already linkable from content/enclosures. - **Promote** suitable image/video enclosures into inline media (dedupe chips). - Video UX: **tap-to-play with controls, no autoplay**. - Stack posture: stay on **`flutter_html`** + native players + targeted embeds; WebView remains escape hatch only. - Failures: **visible failure + open media / open original** actions. - **Revise** `docs/mvp-spec.md` “no in-app audio/video player” to allow in-app video under this design. - Current code: `lib/reader/reader_page.dart` — `flutter_html` + custom `<img>` `TagExtension` (`Image.network`); attachments as `ActionChip`s; no `<video>` handling. - Skills: `/grilling`, `/domain-modeling`, `/research`, `/prototype`. Prefer decisions and specs over implementation. - Tracker: Forgejo via `fj`; `Part of #30`; blocking via `Blocked by: #n`; claim via assignee. - Glossary updates only if new product terms crystallise (likely: something for inline media vs attachments). ## Decisions so far <!-- the index — one line per closed ticket: enough to judge relevance, then zoom the link for the detail the ticket holds --> - [#31 Research: Flutter video/GIF packages for flutter_html Reader](https://git.anachronis.dev/TheAnachronism/tt-rss-viewer/issues/31) — prefer `video_player` + custom `<video>` TagExtension (lazy tap-to-play, no autoplay); keep `Image.network` for GIFs (headers/decode caps); avoid stock `flutter_html_video` drop-in. Doc: [`docs/research/flutter-html-video-gif.md`](https://git.anachronis.dev/TheAnachronism/tt-rss-viewer/src/branch/research/flutter-html-video-gif/docs/research/flutter-html-video-gif.md) on `research/flutter-html-video-gif`. - [#32 Research: YouTube and Vimeo embed approaches for Flutter Reader](https://git.anachronis.dev/TheAnachronism/tt-rss-viewer/issues/32) — allowlisted YouTube/Vimeo detection via custom `flutter_html` extension; default poster + `url_launcher`; optional tap-mounted official-embed WebView slot (not WebView-as-Reader; avoid wholesale `flutter_html_iframe` / custom YouTube overlays); Vimeo `h=` + domain fallback. Doc: [`docs/research/youtube-vimeo-embeds.md`](https://git.anachronis.dev/TheAnachronism/tt-rss-viewer/src/branch/research/youtube-vimeo-embeds/docs/research/youtube-vimeo-embeds.md) on `research/youtube-vimeo-embeds`. - [Grill: full-resolution image/GIF preference rules](https://git.anachronis.dev/TheAnachronism/tt-rss-viewer/issues/33) — candidates = wrap + same-basename sibling image links + image enclosures + srcset/data-full-url; prefer larger declared size else drop resize/thumb markers; replace only image-URL + basename/size-upgrade; preference before enclosure promotion so upgrades are not double-injected. - [Grill: enclosure promotion and dedupe rules](https://git.anachronis.dev/TheAnachronism/tt-rss-viewer/issues/34) — promote image/* + video/* (URL heuristics when MIME generic/missing); image→inline, video→tap-to-play; after preference; dedupe via canonicalize+basename; suppress chip when promoted/consumed; append after body. - [Grill: YouTube/Vimeo embed UX in swipeable Reader](https://git.anachronis.dev/TheAnachronism/tt-rss-viewer/issues/35) — v1 poster+play → Custom Tabs/external; full width 16:9 with ~40–50% max height; no special gesture arena; no autoplay; visible failure + Open media / Open original; no inline embed WebView in v1. - [Prototype: Reader media against example RSS entries](https://git.anachronis.dev/TheAnachronism/tt-rss-viewer/issues/36) — accepted `prototype/reader-media`: preference/promote/dedupe + tap-to-play + YT poster→external feel right; spec must unwrap image-proxy-wrapped videos and not rely on flutter_html img TagExtensions inside tables (hoist images). - [Grill: assemble Reader media specification and MVP revision](https://git.anachronis.dev/TheAnachronism/tt-rss-viewer/issues/37) — handoff at [`docs/specs/reader-media.md`](https://git.anachronis.dev/TheAnachronism/tt-rss-viewer/src/branch/master/docs/specs/reader-media.md); MVP revised for tap-to-play video (no audio); research + fixtures on master; no ADR; Article thumbnails unchanged. ## Not yet specified _(none — destination reached)_ ## Out of scope - List hub **Article thumbnail** / `flavor_image` changes — left to ADR-0004 ([Grill: assemble Reader media specification and MVP revision](https://git.anachronis.dev/TheAnachronism/tt-rss-viewer/issues/37)) - Separate ADR for Reader media stack/policy — trade-offs live in the Reader-media spec + MVP revision ([Grill: assemble Reader media specification and MVP revision](https://git.anachronis.dev/TheAnachronism/tt-rss-viewer/issues/37)) - In-app audio / podcast player - Arbitrary iframe embedding beyond YouTube and Vimeo (v1) - Site-specific scrapers or unofficial Reddit/X APIs - Making WebView the primary Reader path - Server-side feed rewriting / rss.anachronis.dev proxy changes - Implementing and shipping the Reader media feature inside this map (destination is the design/spec) - Offline caching of media bytes (online-first; cache-ready seams only if an ADR needs them) ## Tickets - [x] #31 Research: Flutter video/GIF packages for flutter_html Reader - [x] #32 Research: YouTube and Vimeo embed approaches for Flutter Reader - [x] #33 Grill: full-resolution image/GIF preference rules - [x] #34 Grill: enclosure promotion and dedupe rules - [x] #35 Grill: YouTube/Vimeo embed UX in swipeable Reader - [x] #36 Prototype: Reader media against example RSS entries - [x] #37 Grill: assemble Reader media specification and MVP revision
Author
Owner

Destination reached: implementable Reader media handoff at docs/specs/reader-media.md (MVP revised; research + fixtures on master).

Destination reached: implementable Reader media handoff at docs/specs/reader-media.md (MVP revised; research + fixtures on master).
Sign in to join this conversation.
No description provided.