Repository navigation
fix: feed first-paint latency, MMAP 44.1 fallback, canvas/static cover handover - #315
Merged
Merged
Conversation
8335ccb blended discovery candidates into Quick Picks and made the feed's only mid-load emission (onUpdate) wait on the three related-songs round-trips behind them, so a cold feed — no cached feed for this user — showed nothing until the slowest calls in the whole load finished. The discovery feature is unchanged: familiar-only picks are emitted first, needing no network beyond the parallel batch already in flight, and the blended picks republish the same sections the moment the round-trips land, overlapping with the artist fetches that follow instead of blocking the first paint. Fresh Finds, Mixes and the final returned FeedData keep using the blended picks and discoveryTracks exactly as before.
…al MMAP path negotiate() opened the internal-direct stream at the probe's rate whenever the HAL refused the source rate, and the probe asks for no rate at all — DirectOutputStream::probe() builds its AAudio stream without setSampleRate — so it returns the device's native primary output rate. On a 44.1-primary HAL that made every refused source, 48 kHz YouTube streams included, resample DOWN to 44.1. fallbackRates() orders the attempts source -> 48 kHz -> device native: 48 is tried first, the probe rate is kept as the last resort, and the source rate is never repeated. A device that genuinely cannot open 48 kHz behaves exactly as before; attempts are cached per srcRate/encoding per route, so the extra try costs one failed open per format. Tests: fallbackRatesPrefer48kHzOverTheDeviceNativeRate, fallbackRatesSkipTheSourceRateAndDuplicates. The Signal Path verdict and the quality pill need no change — resampling is already reported honestly through internalSession.resampled and the pill is source-measured by design.
The full-screen hero (12114f3) stacks StaticArtworkHero and CanvasArtworkPlayer in identical bounds with the hero always at full alpha, so the cover showed through wherever the canvas is transparent — its bottom fade, its 320 ms reveal, and the repaint window on every track change — and the two fought for the same pixels. The coordination the hero originally had is restored via the API that survived bef22b9: the canvas reports its effective alpha (onCoverChanged) and the static art's alpha follows it, snapping off once coverage reaches 95%. Wired in both the full-bleed hero and the sleeve (PlayerArtwork), and a canvas leaving composition reports 0, so the cover returns the moment a track without one starts. The dead canvasRendered state (written, never read) is removed with it.
ajisth69
added a commit
that referenced
this pull request
Oct 13, 2026
1. FeedRepository: the #315 merge landed ea6a5e8 without its fixup commit a732c68, so the add(it to ...) typo inside the forEachIndexed lambdas is live on main and the app does not compile from it. Restored here: forEachIndexed blocks use add(t to ...), the unnamed forEach blocks below keep add(it to seedScore(...)). 2. ModernLyricsView: Modifier.blur has no clip parameter in this Compose version — its second parameter is edgeTreatment. The glow uses BlurredEdgeTreatment.Unbounded so the halo is not cut at the Text's own bounds.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Three independent fixes, one commit each (plus a follow-up repair commit — the first feed commit had an
add(it to ...)typo inside aforEachIndexedlambda; CI caught it, now green ona732c68):1. Feed page load time —
ea6a5e8The feed's only mid-load emission (
onUpdate) publishes Quick Picks, and since8335ccbblended discovery candidates into that list — so the first paint waited on three related-songs round-trips of 30 tracks each. On a cold start (no cached feed) the whole page sat blank until the slowest calls in the load finished.Not one of the recent USB/local-songs PRs — the discovery change was already in main's base.
Fix: two emissions — familiar-only picks paint immediately (no network beyond the parallel batch already in flight), the discovery-blended picks republish the same sections once the round-trips land, overlapping with the artist fetches that follow. Discovery feature fully intact; Fresh Finds / Mixes / final FeedData unchanged.
2. Internal MMAP resampling to 44.1 —
8b528c4negotiate()opened the internal-direct stream at the probe's rate when the HAL refused the source rate, andDirectOutputStream::probe()asks for no rate at all — so it returns the device's native primary output rate. On a 44.1-primary HAL, every refused source (48 kHz YouTube included) resampled down to 44.1.Fix:
fallbackRates()orders attempts source → 48 kHz → device native. 48 is tried first; the probe rate stays as the last resort, so a device that can't open 48 behaves exactly as before. One extra failed open per format, cached per rate+encoding per route. Signal Path verdict/pill need no change — conversion was already reported honestly.Tests:
fallbackRatesPrefer48kHzOverTheDeviceNativeRate,fallbackRatesSkipTheSourceRateAndDuplicates(7 cases).3. Canvas artwork vs static cover —
9a5dfb6The full-screen hero (
12114f3, merged with #301/#302 today) stacksStaticArtworkHeroandCanvasArtworkPlayerin identical bounds with the hero at full alpha, so the cover bled through wherever the canvas is transparent — its bottom fade, its 320 ms reveal, the repaint window on track change. The coordination the hero originally had was deleted bybef22b9and never restored by the rebuild.Fix: the canvas's own
onCoverChangedreports its effective alpha and the static art fades out in step, snapping off at ≥95 % coverage. Wired in both the full-bleed hero and the sleeve. A canvas leaving composition reports 0, so the cover returns the moment a track without one starts. DeadcanvasRenderedstate removed.Verification — CI green on
a732c68Unit tests (incl. the two new ones) and
assembleReleaseboth pass in CI: https://github.com/Clash-Projects/LastWave-Native/actions/runs/38409097146Still worth a device pass: feed cold start (force-stop, clear recents), a canvas track's cover handover, and — on a 44.1-primary-HAL device —
INTERNAL DIRECT (mmap) engaged ... device=48000Hzin logcat.