vc=57: hide stale inline player frame during video switch
Cobb-reported 2026-05-26: tapping a related/search/subs video while another is playing rendered the NEW detail page (title, description) with the OLD video's last frame visible in the inline player slot. Root cause — there's a window between streamInfo resolving for the new URL and setPlayingFrom landing on the controller. PlayerView bound to the controller renders the previous video's surface during that window because the controller's MediaItem hasn't swapped yet. Fix — observe NowPlaying.current and add a branch in InlinePlayer's state-when that renders thumbnail + spinner when the controller is still on a different streamUrl. Branch sits above the PlayerView else-arm so the stale surface never gets attached. Flips to PlayerView the moment NowPlaying.claim() lands the new URL.
This commit is contained in:
parent
50f4ce0a6c
commit
8dec2f2621
2 changed files with 26 additions and 2 deletions
|
|
@ -55,6 +55,6 @@ const val NEWPIPE_APPLICATION_ID_NEW = "net.newpipe.app"
|
|||
// vc=19 / 0.1.0-AE — rust pipeline cutover. Extraction via
|
||||
// strawcore-core (Sulkta-Coop/strawcore) via the UniFFI wrapper; no
|
||||
// NewPipeExtractor in the runtime path.
|
||||
const val STRAW_VERSION_CODE = 56
|
||||
const val STRAW_VERSION_NAME = "0.1.0-BP"
|
||||
const val STRAW_VERSION_CODE = 57
|
||||
const val STRAW_VERSION_NAME = "0.1.0-BQ"
|
||||
const val STRAW_APPLICATION_ID = "com.sulkta.straw"
|
||||
|
|
|
|||
|
|
@ -776,6 +776,14 @@ private fun InlinePlayer(
|
|||
onDispose { c?.removeListener(listener) }
|
||||
}
|
||||
|
||||
// Track whether the shared controller has actually swapped over to
|
||||
// THIS video's stream. Until it does (the brief window between
|
||||
// streamInfo resolving and setPlayingFrom + setMediaItem landing),
|
||||
// binding PlayerView to the controller would render the PREVIOUS
|
||||
// video's frame under the new detail page — exactly the "new page,
|
||||
// old video" bug.
|
||||
val nowPlaying by NowPlaying.current.collectAsStateWithLifecycle()
|
||||
val controllerOnThisVideo = nowPlaying?.streamUrl == streamUrl
|
||||
Box(modifier = modifier, contentAlignment = Alignment.Center) {
|
||||
when {
|
||||
controller == null || state.loading -> CircularProgressIndicator(color = Color.White)
|
||||
|
|
@ -794,6 +802,22 @@ private fun InlinePlayer(
|
|||
color = Color.White,
|
||||
modifier = Modifier.padding(16.dp),
|
||||
)
|
||||
// Stream resolved for THIS URL but the controller hasn't
|
||||
// actually swapped media items yet — show the thumbnail
|
||||
// with a spinner. Without this, the PlayerView below would
|
||||
// bind to the controller and render the OUTGOING video's
|
||||
// last frame while the new detail page chrome shows the
|
||||
// new title/description. Bug reported 2026-05-26.
|
||||
!controllerOnThisVideo -> {
|
||||
if (!thumbnail.isNullOrBlank()) {
|
||||
AsyncImage(
|
||||
model = thumbnail,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
)
|
||||
}
|
||||
CircularProgressIndicator(color = Color.White)
|
||||
}
|
||||
else -> {
|
||||
AndroidView(
|
||||
factory = { ctx ->
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue