<feed xmlns='http://www.w3.org/2005/Atom'>
<title>coinosv3.git/tools/feed-media-views-test.js, branch fdroid-v1.9</title>
<subtitle>coinos v3 — bitcoin, Ark, Lightning and nostr wallet (web + Android)</subtitle>
<id>https://git.coinos.io/coinosv3.git/atom?h=fdroid-v1.9</id>
<link rel='self' href='https://git.coinos.io/coinosv3.git/atom?h=fdroid-v1.9'/>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/'/>
<updated>2026-10-03T22:52:38Z</updated>
<entry>
<title>Video frames from bytes, not from a CORS player; pager clips load plainly again</title>
<updated>2026-10-03T22:52:38Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-10-03T22:52:38Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=141779ab97efad6abefaec0545bba5330fd1e12d'/>
<id>urn:sha1:141779ab97efad6abefaec0545bba5330fd1e12d</id>
<content type='text'>
Regression from 6488806: pager clips were loaded crossorigin so their
frame could be kept, and on a phone the large clip's slide went black.
Some hosts (Primal's R2 bucket) send CORS headers only to a request with
an Origin and don't Vary on it, so a copy the browser cached from a plain
player load answers a later CORS load without them, and it fails. The
same thing made the size probe fail for any clip that had played in the
feed.

- Pager clips load plainly again; the still under a tap-to-play cover is
  restored on every return.
- The probe (and its HEAD) go past the browser cache (no-store).
- A clip's frame is now made from bytes: the opening of the file (index
  plus about 1 MB, no-store) decoded from a blob and kept as a JPEG —
  for tiles and as the pager's poster. No CORS player anywhere. Files
  whose index trails, or hosts whose bytes can't be read, keep the plain
  player still (shown, not kept).
- Kept frames are 480 px wide (were 270) and capped at 600.
- Probe failures are stored as failedAt, so earlier failures are asked
  again at once.
- Test: an R2-style host, its clip cached by a plain load first, is
  still measured and its frame kept (failed before this change).

Co-Authored-By: Claude Fable 5.1 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01ULQZS9MQa6iAsXnrJUD9Du
</content>
</entry>
<entry>
<title>Pager: a large clip keeps its picture when you come back to it</title>
<updated>2026-10-03T22:41:42Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-10-03T22:41:42Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=6488806b840c009278f4ae16de9e079ea4b892bc'/>
<id>urn:sha1:6488806b840c009278f4ae16de9e079ea4b892bc</id>
<content type='text'>
Leaving a slide lets go of its file, and coming back skipped the still
because the cover was already there — black again. The still is now
restored on every return. Pager clips also load CORS-readable (a plain
retry for hosts without CORS), so their frame is kept the first time —
the still under a cover and any clip that plays — and from then on the
poster alone covers it.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01ULQZS9MQa6iAsXnrJUD9Du
</content>
</entry>
<entry>
<title>Pager: a large clip shows its frame under the tap-to-play cover</title>
<updated>2026-10-03T22:36:58Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-10-03T22:36:58Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=7adb8cdf7b1a405c58ad9c51c901d852c29dd2ad'/>
<id>urn:sha1:7adb8cdf7b1a405c58ad9c51c901d852c29dd2ad</id>
<content type='text'>
The slide's poster was fixed when the pager was built, and a clip over
budget held no source, so a clip whose frame was kept a moment later (or
never) was a black screen with a button. Now the kept frame is looked up
as a slide comes near; without one, the clip's first frame is loaded
under the cover (only the start of the file, when it leads with its
index or is served in ranges) and kept for next time. A tap plays it
from the start.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01ULQZS9MQa6iAsXnrJUD9Du
</content>
</entry>
<entry>
<title>Videos opens on a grid of thumbnails; the pager waits for a tap</title>
<updated>2026-10-03T21:49:57Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-10-03T21:49:57Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=09ce0c7f213802757b13501898c02cfe309bfbf8'/>
<id>urn:sha1:09ce0c7f213802757b13501898c02cfe309bfbf8</id>
<content type='text'>
Choosing Videos no longer jumps into the full-screen pager: it shows
the vertical clips as a grid, like Images, and a tile opens the pager
on that clip.

Every tile gets a first frame when that costs only the start of the
file (the index leads, or the server serves ranges), whatever the
clip's size; a clip over budget wears its cost as a badge. Only an
index-last file from a server without ranges shows its cost instead.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01ULQZS9MQa6iAsXnrJUD9Du
</content>
</entry>
<entry>
<title>Videos: know what a clip costs before fetching it; vertical clips only</title>
<updated>2026-10-03T20:38:13Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-10-03T20:38:13Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=347deec6465a42f24154457fb05227418ee83385'/>
<id>urn:sha1:347deec6465a42f24154457fb05227418ee83385</id>
<content type='text'>
- What a clip costs is learned up front: the post's imeta (size, dim,
  image) when it says, else one 64 KB ranged request — the total from
  Content-Range, whether ranges are served, whether the MP4's index
  (moov) comes before its data, and the picture size from the track
  header. Up to three at a time; remembered across sessions. It also
  replaces the player-based shape probe the feed ran on every clip.
- Clips over 25 MB (8 MB on 2G/3G, 3 MB with data saver), above 1080p,
  index-last files over 8 MB from servers without ranges, or clips that
  couldn't be measured wait for a tap: a cover saying what they cost
  ("50 MB", "4K"). Settings → Nostr → Videos: Autoplay large videos.
- The pager loads only the clip on screen in full; the next gets its
  opening if within budget; everything else holds nothing. Sizes are
  asked three slides ahead.
- Feed clips fetch nothing until they're about to play (preload none),
  with the post's still as a poster.
- Video grid tiles show a first frame only for small clips that start
  quickly; others show their cost.
- Videos lists only clips known to stand taller than wide; one of unknown
  shape is measured and joins when it qualifies; choosing Videos with none
  known yet opens the pager on the first that turns up.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01ULQZS9MQa6iAsXnrJUD9Du
</content>
</entry>
<entry>
<title>Feed media views: a grid of pictures, videos to flip through</title>
<updated>2026-10-03T20:12:30Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-10-03T20:12:30Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=543a66ca70323921acf4da9b8e4fca8128cf0b58'/>
<id>urn:sha1:543a66ca70323921acf4da9b8e4fca8128cf0b58</id>
<content type='text'>
All / Images / Videos sits under the feed chips (remembered).
- Images lays the feed's pictures out as a three-column grid.
- Videos opens straight into a full-screen pager: one clip per screen,
  snapping, the one on screen playing with sound (muted with an Unmute
  button when the browser refuses), the next a flick or ↓ away. Closing
  it leaves a grid of the clips.
- The pager shows only the media until tapped; a tap shows the author
  (tap for their profile), the post's words as a caption without the
  media links (tap to expand), and likes and sats in the bottom right,
  which also like and zap.
- It is a place: Back or Escape closes it. Built outside the morph, so a
  repaint never restarts a clip; off-screen clips let go of their media.
- Near the end of the grid or the pager the feed fetches older posts and
  new slides are appended.
- Toasts now sit above full-screen viewers.

tools/feed-media-views-test.js

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01ULQZS9MQa6iAsXnrJUD9Du
</content>
</entry>
</feed>
