chore(UI): Use remember getUiModel (#1605)

* use remember getUiModel

* update headerIndexes to use remember for state management

* Refactor LibraryUpdateErrorScreen to improve state management

*   Move header index calculation from the screen model to the presentation layer.
*   Optimize UI model and header index memoization using `remember(state)`.
*   Remove redundant `LaunchedEffect` and simplify scroll-to-index logic.

* Refactor LibraryUpdateErrorScreen to enhance state management with derivedStateOf
This commit is contained in:
Cuong-Tran 2026-04-23 15:19:54 +07:00 committed by GitHub
parent bf9b663581
commit d8eb71e004
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 19 additions and 19 deletions

View file

@ -25,7 +25,6 @@ import androidx.compose.material3.Surface
import androidx.compose.material3.TopAppBarScrollBehavior import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.material3.surfaceColorAtElevation import androidx.compose.material3.surfaceColorAtElevation
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateListOf
@ -39,6 +38,7 @@ import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.components.AppBar
import eu.kanade.presentation.components.AppBarActions import eu.kanade.presentation.components.AppBarActions
import eu.kanade.presentation.libraryUpdateError.components.LibraryUpdateErrorUiModel
import eu.kanade.presentation.libraryUpdateError.components.libraryUpdateErrorUiItems import eu.kanade.presentation.libraryUpdateError.components.libraryUpdateErrorUiItems
import eu.kanade.presentation.manga.components.Button import eu.kanade.presentation.manga.components.Button
import eu.kanade.tachiyomi.ui.libraryUpdateError.LibraryUpdateErrorItem import eu.kanade.tachiyomi.ui.libraryUpdateError.LibraryUpdateErrorItem
@ -75,31 +75,33 @@ fun LibraryUpdateErrorScreen(
val scope = rememberCoroutineScope() val scope = rememberCoroutineScope()
val listState = rememberLazyListState() val listState = rememberLazyListState()
val headerIndexes = remember { mutableStateOf<List<Int>>(emptyList()) } val uiModels = remember(state) { state.getUiModel() }
LaunchedEffect(state) { val headerIndexes = remember(state) {
headerIndexes.value = state.getHeaderIndexes() uiModels.withIndex()
.filter { it.value is LibraryUpdateErrorUiModel.Header }
.map { it.index }
} }
val enableScrollToTop by remember { val enableScrollToTop by remember(listState) {
derivedStateOf { derivedStateOf {
listState.firstVisibleItemIndex > 0 listState.firstVisibleItemIndex > 0
} }
} }
val enableScrollToBottom by remember { val enableScrollToBottom by remember(listState) {
derivedStateOf { derivedStateOf {
listState.canScrollForward listState.canScrollForward
} }
} }
val enableScrollToPrevious by remember { val enableScrollToPrevious by remember(headerIndexes, listState) {
derivedStateOf { derivedStateOf {
headerIndexes.value.any { it < listState.firstVisibleItemIndex } headerIndexes.any { it < listState.firstVisibleItemIndex }
} }
} }
val enableScrollToNext by remember { val enableScrollToNext by remember(headerIndexes, listState) {
derivedStateOf { derivedStateOf {
headerIndexes.value.any { it > listState.firstVisibleItemIndex } headerIndexes.any { it > listState.firstVisibleItemIndex }
} }
} }
@ -141,7 +143,7 @@ fun LibraryUpdateErrorScreen(
scrollToPrevious = { scrollToPrevious = {
scope.launch { scope.launch {
listState.scrollToItem( listState.scrollToItem(
state.getHeaderIndexes() headerIndexes
.filter { it < listState.firstVisibleItemIndex } .filter { it < listState.firstVisibleItemIndex }
.maxOrNull() ?: 0, .maxOrNull() ?: 0,
) )
@ -150,7 +152,7 @@ fun LibraryUpdateErrorScreen(
scrollToNext = { scrollToNext = {
scope.launch { scope.launch {
listState.scrollToItem( listState.scrollToItem(
state.getHeaderIndexes() headerIndexes
.filter { it > listState.firstVisibleItemIndex } .filter { it > listState.firstVisibleItemIndex }
.minOrNull() ?: 0, .minOrNull() ?: 0,
) )
@ -173,7 +175,7 @@ fun LibraryUpdateErrorScreen(
state = listState, state = listState,
) { ) {
libraryUpdateErrorUiItems( libraryUpdateErrorUiItems(
uiModels = state.getUiModel(), uiModels = uiModels,
selectionMode = state.selectionMode, selectionMode = state.selectionMode,
onErrorSelected = onErrorSelected, onErrorSelected = onErrorSelected,
onClick = onClick, onClick = onClick,

View file

@ -112,6 +112,9 @@ fun UpdateScreen(
else -> { else -> {
val scope = rememberCoroutineScope() val scope = rememberCoroutineScope()
var isRefreshing by remember { mutableStateOf(false) } var isRefreshing by remember { mutableStateOf(false) }
// KMK -->
val uiModels = remember(state.items) { state.getUiModel() }
// KMK <--
PullRefresh( PullRefresh(
refreshing = isRefreshing, refreshing = isRefreshing,
@ -134,8 +137,8 @@ fun UpdateScreen(
updatesLastUpdatedItem(lastUpdated) updatesLastUpdatedItem(lastUpdated)
updatesUiItems( updatesUiItems(
uiModels = state.getUiModel(),
// KMK --> // KMK -->
uiModels = uiModels,
expandedState = state.expandedState, expandedState = state.expandedState,
collapseToggle = collapseToggle, collapseToggle = collapseToggle,
usePanoramaCover = usePanoramaCover, usePanoramaCover = usePanoramaCover,

View file

@ -189,11 +189,6 @@ data class LibraryUpdateErrorScreenState(
} }
return uiModels return uiModels
} }
fun getHeaderIndexes(): List<Int> = getUiModel()
.withIndex()
.filter { it.value is LibraryUpdateErrorUiModel.Header }
.map { it.index }
} }
@Immutable @Immutable