vc=67: fix subs feed scroll jank
LazyColumn items() now keyed by url so pagination doesn't re-key every row from scratch when visibleCount jumps. The displayed page slice is remembered so SubsPane doesn't reallocate the take() ArrayList on every recomposition. ThumbnailProgressOverlay switched from collectAsStateWithLifecycle to plain collectAsState — the lifecycle wrapper added a DisposableEffect per call site, which adds up across the ~30 visible rows and was contributing to scroll hitch.
This commit is contained in:
parent
dd151e322d
commit
796244e065
3 changed files with 19 additions and 6 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 = 66
|
||||
const val STRAW_VERSION_NAME = "0.1.0-BZ"
|
||||
const val STRAW_VERSION_CODE = 67
|
||||
const val STRAW_VERSION_NAME = "0.1.0-CA"
|
||||
const val STRAW_APPLICATION_ID = "com.sulkta.straw"
|
||||
|
|
|
|||
|
|
@ -323,7 +323,11 @@ private fun SubsPane(
|
|||
visibleCount = PAGE_SIZE
|
||||
}
|
||||
}
|
||||
val displayed = filteredItems.take(visibleCount)
|
||||
// remember the page-slice so we don't allocate a new ArrayList on
|
||||
// every recomposition (scroll hitch vc=67).
|
||||
val displayed = remember(filteredItems, visibleCount) {
|
||||
filteredItems.take(visibleCount)
|
||||
}
|
||||
val hasMore = filteredItems.size > visibleCount
|
||||
|
||||
Column {
|
||||
|
|
@ -442,7 +446,10 @@ private fun SubsPane(
|
|||
state = listState,
|
||||
contentPadding = rememberBottomContentPadding(),
|
||||
) {
|
||||
items(displayed) { item ->
|
||||
items(
|
||||
items = displayed,
|
||||
key = { it.url },
|
||||
) { item ->
|
||||
FeedRow(
|
||||
item = item,
|
||||
onClick = { onOpenVideo(item.url, item.title) },
|
||||
|
|
|
|||
|
|
@ -25,13 +25,13 @@ import androidx.compose.foundation.shape.RoundedCornerShape
|
|||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import coil3.compose.AsyncImage
|
||||
import com.sulkta.straw.OverlayDimColor
|
||||
import com.sulkta.straw.ProgressBarFillColor
|
||||
|
|
@ -51,7 +51,13 @@ import com.sulkta.straw.util.formatDuration
|
|||
@Composable
|
||||
fun BoxScope.ThumbnailProgressOverlay(videoId: String?) {
|
||||
if (videoId.isNullOrBlank()) return
|
||||
val positions by Resume.get().positions.collectAsStateWithLifecycle()
|
||||
// Plain collectAsState — collectAsStateWithLifecycle adds a
|
||||
// DisposableEffect for lifecycle observation per call site, which
|
||||
// adds up across 30 visible LazyColumn rows and contributes to
|
||||
// scroll jank (vc=67). The Lifecycle pause optimization doesn't
|
||||
// matter for a foreground feed that's only collected while the
|
||||
// composable is on screen anyway.
|
||||
val positions by Resume.get().positions.collectAsState()
|
||||
val entry = positions[videoId] ?: return
|
||||
if (entry.durationMs <= 0L) return
|
||||
val fraction = (entry.positionMs.toFloat() / entry.durationMs.toFloat())
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue