25dad88ed9fb40884c744ce9efde222a9f19a597
Favorites persisted the *resolved* stream metadata (resolveAndProbe mutates video.meta with yt-dlp's CDN format URLs), so a favorite opened the next day replayed a dead link. They now store only the page URL and identifying fields, and ignore any stale meta left in localStorage -- playback, download and info re-resolve through the backend, which resolves a page URL live in /api/stream. That left the quality switcher empty for anything not yet resolved (favorites, cards clicked before their hover-resolve landed, feed slides), so App.videos.ensureFormats now resolves formats once per session -- cached by video id rather than per object, so any object describing the same video gets them -- and both the player and the reels feed rebuild their format menu when they arrive. Playback isn't blocked: it already starts from the page URL via the proxy. Rotating a phone also jumped the grid to a completely different place: the anchor was read inside the resize handler (by which point the browser has already moved the scroll) and asserted once, and every re-pack discarded known card heights for the 16:9 placeholder estimate. The virtualizer now tracks the anchor on every scroll pass, re-asserts it across a short settling window (ending early on a real gesture), and remembers each thumbnail's true aspect ratio so a re-pack places cards at their real heights. Verified in headless Chrome across a portrait/landscape/portrait cycle: visible videos 37-39 -> 36-40 -> 36-38, against 37-39 -> 34-37 -> 29-30 before. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QBDkEXP4htyXTCZUwMLphd
Description
A webclient for hottub
Languages
JavaScript
68.7%
Python
17.6%
CSS
11%
HTML
2.1%
Shell
0.5%