vc=85: image caching + SB/RYD clients -> Rust + crash/autoplay fixes

- Thumbnails + channel icons stay cached: pin an explicit 256MB Coil disk
  cache + sized memory cache via SingletonImageLoader.Factory. Coil's
  default disk cap is 2% of the device's free space, so on a storage-tight
  phone the subs feed (most image-heavy screen) thrashed it and
  re-downloaded thumbnails on every visit.
- SponsorBlock + Return-YouTube-Dislike clients moved Kotlin -> Rust
  (strawcore net.rs: fetchSponsorSegments / fetchRydVotes). SponsorBlock
  keeps its privacy-preserving SHA-256 hash-prefix lookup. Kotlin is now a
  thin shim mapping the FFI records onto the SbSegment/RydVotes domain
  types; behavior identical. Migration #2 of "all backend -> Rust".
- Fix crash: extract_channel_id sliced the channel URL by a length derived
  from a lowercased copy of itself; to_lowercase() can change byte length
  on non-ASCII, so a non-ASCII URL tail could panic across the FFI and
  abort the app on a feed refresh. Now matches the prefix case-insensitively
  against the original with length + char-boundary guards.
- Fix autoplay hijack: advancing to the next video resolves over ~500ms; if
  you manually start a different video meanwhile, autoplay would replace
  your choice with the stale next-up. Added a staleness fence.

Verified: cargo check/test/clippy on the wrapper, full Android
compileDebugKotlin green, adversarial FFI pre-push audit passed.
This commit is contained in:
Sulkta 2026-06-21 12:59:04 -07:00
parent 4affa1e739
commit a36e673627
10 changed files with 487 additions and 141 deletions

View file

@ -9,6 +9,30 @@ const val STRAW_SDK_TARGET = 35
// Sulkta fork — Straw
//
// vc=85 / 0.1.0-CS — image caching + SB/RYD → Rust + crash/autoplay fixes:
// * Thumbnails + channel icons stay cached. Coil's default disk cache is
// only 2% of the phone's FREE space, so on a storage-tight device the
// subs feed (the most image-heavy screen) thrashed its cache and
// re-downloaded thumbnails on every visit — the "each load takes a
// second" lag. Pinned an explicit 256 MB image disk cache + a sized
// memory cache via a SingletonImageLoader.Factory.
// * SponsorBlock + Return-YouTube-Dislike clients moved out of Kotlin
// into Rust (strawcore fetchSponsorSegments / fetchRydVotes) — network
// + JSON belong behind the FFI, not in the UI layer. SponsorBlock keeps
// its privacy-preserving SHA-256 hash-prefix lookup. Kotlin is now a
// thin shim mapping the FFI records onto the existing SbSegment/RydVotes
// domain types; behavior identical. (Migration #2 of "all backend → Rust".)
// * FIX a crash: extract_channel_id() sliced the channel URL using a
// length derived from a lowercased copy of itself — to_lowercase() can
// change byte length on non-ASCII, so a channel URL with any non-ASCII
// tail could panic across the FFI and abort the app on a feed refresh.
// Now matches the prefix case-insensitively against the original with
// length + char-boundary guards.
// * FIX autoplay hijack: advancing to the next video resolves over ~500ms;
// if you manually started a different video in that window, autoplay
// would still fire and replace your choice with the stale next-up. Added
// a staleness fence (same class as the vc=83 minibar fix).
//
// vc=84 / 0.1.0-CR — name + stream-picker → Rust:
// * The app is now just "Straw" in the launcher, not "Straw debug" —
// we're past the debug-branding phase. (The package id stays
@ -178,6 +202,6 @@ const val STRAW_SDK_TARGET = 35
// vc=19 / 0.1.0-AE — rust pipeline cutover. Extraction via
// strawcore-core (Sulkta-OSS/strawcore) via the UniFFI wrapper; no
// NewPipeExtractor in the runtime path.
const val STRAW_VERSION_CODE = 84
const val STRAW_VERSION_NAME = "0.1.0-CR"
const val STRAW_VERSION_CODE = 85
const val STRAW_VERSION_NAME = "0.1.0-CS"
const val STRAW_APPLICATION_ID = "com.sulkta.straw"