- Audio-only toggle no longer drops the max-resolution cap: both the
fullscreen button (PlayerScreen) and the detail Audio pill (VideoDetailBody)
rebuilt TrackSelectionParameters from a fresh Builder, wiping the data-saver
ceiling. Now buildUpon() the existing params so the cap survives. (H2)
- Subscriptions Refresh button no longer sticks at "..." forever on a warm
restart within the cache TTL: refreshIfStale clears the initial loading
seed when it decides nothing needs refreshing. (M2)
- Search + Channel result lists get a stable item key (video url) so paging /
shorts-filtering stops re-binding rows to new data (re-triggered thumbnail
loads, scroll shift). (M3, M4)
- IosSafeHttpDataSource: the unknown-length (LENGTH_UNSET) chunk path rolls
forward to the next Range chunk at inner-EOF instead of re-reading the
exhausted source forever (was truncating playback to the first chunk). (M5)
- strawcore channel_feed_rss propagates the real failure (network/HTTP/parse)
instead of collapsing every error to an empty list, so a broken fetch is
distinguishable from "no new videos" (subscription_feed keeps its per-channel
tolerance for fan-out). (M6)
- Feed recency: a clock-skewed future upload emits "0 seconds ago" (parses to
top) instead of "just now" (which Kotlin's recency parser couldn't read, so
the item sank to the bottom). (L4)
Deferred to a follow-up: M1 (bg-refresh cache-key mismatch — needs a worker
redesign) + M7 (build config-cache wiring). Verified: cargo check/clippy +
full Android compileDebugKotlin green.