feat: 保留ExpandedSourceSheet的浏览进度

合并 PR #1279 by woruteyqi
This commit is contained in:
aoi
2026-06-02 18:32:04 +08:00
committed by GitHub
parent aa9e5a4458
commit 5da2e85395
3 changed files with 69 additions and 22 deletions
@@ -51,6 +51,9 @@ data class SearchUiState(
val expandedSourceEnd: Boolean = false,
val expandedSourceError: String? = null,
val expandedSourcePage: Int = 1,
val showExpandedSource: Boolean = false,
val expandedSourceSavedScrollIndex: Int = 0,
val expandedSourceSavedScrollOffset: Int = 0,
)
data class SearchEmptyScopeAction(
@@ -90,6 +93,7 @@ sealed interface SearchIntent {
data object DismissEmptyScopeAction : SearchIntent
data object OpenSourceManage : SearchIntent
data class SaveScrollState(val index: Int, val offset: Int) : SearchIntent
data class SaveExpandedSourceScrollState(val index: Int, val offset: Int) : SearchIntent
}
sealed interface SearchEffect {
@@ -698,14 +698,19 @@ fun SearchScreen(
)
ExpandedSourceSheet(
show = state.expandedSourceUrl != null,
show = state.showExpandedSource,
sourceName = state.expandedSourceName ?: "",
books = state.expandedSourceBooks,
isLoading = state.expandedSourceLoading,
isEnd = state.expandedSourceEnd,
errorMsg = state.expandedSourceError,
savedScrollIndex = state.expandedSourceSavedScrollIndex,
savedScrollOffset = state.expandedSourceSavedScrollOffset,
onDismiss = { viewModel.onIntent(SearchIntent.DismissExpandedSource) },
onLoadMore = { viewModel.onIntent(SearchIntent.LoadMoreExpandedSource) },
onSaveScrollState = { index, offset ->
viewModel.onIntent(SearchIntent.SaveExpandedSourceScrollState(index, offset))
},
onBookClick = { book, coverKey ->
viewModel.onIntent(SearchIntent.OpenExpandedSourceBook(book, coverKey))
},
@@ -888,8 +893,11 @@ private fun ExpandedSourceSheet(
isLoading: Boolean,
isEnd: Boolean,
errorMsg: String?,
savedScrollIndex: Int,
savedScrollOffset: Int,
onDismiss: () -> Unit,
onLoadMore: () -> Unit,
onSaveScrollState: (Int, Int) -> Unit,
onBookClick: (SearchBook, String?) -> Unit,
onBookLongClick: ((SearchBook, String?) -> Unit)? = null,
) {
@@ -900,7 +908,7 @@ private fun ExpandedSourceSheet(
) {
val listState = rememberLazyListState()
val showLoadMoreFooter = isLoading || errorMsg != null || isEnd
val currentOnSaveScrollState by rememberUpdatedState(onSaveScrollState)
val shouldLoadMore by remember {
derivedStateOf {
val total = listState.layoutInfo.totalItemsCount
@@ -915,6 +923,23 @@ private fun ExpandedSourceSheet(
}
}
LaunchedEffect(savedScrollIndex, savedScrollOffset) {
if (savedScrollIndex > 0 || savedScrollOffset > 0) {
listState.scrollToItem(savedScrollIndex, savedScrollOffset)
onSaveScrollState(0, 0)
}
}
DisposableEffect(listState) {
onDispose {
val first = listState.firstVisibleItemIndex
val offset = listState.firstVisibleItemScrollOffset
if (first > 0 || offset > 0) {
currentOnSaveScrollState(first, offset)
}
}
}
LazyColumn(
state = listState,
modifier = Modifier.fillMaxSize(),
@@ -225,6 +225,11 @@ class SearchViewModel(
SearchIntent.OpenSourceManage -> emitEffect(SearchEffect.OpenSourceManage)
is SearchIntent.ExpandSource -> {
val state = _uiState.value
if (state.expandedSourceUrl == intent.sourceUrl) {
_uiState.update { it.copy(showExpandedSource = true) }
return
}
_uiState.update {
it.copy(
expandedSourceUrl = intent.sourceUrl,
@@ -234,6 +239,9 @@ class SearchViewModel(
expandedSourceEnd = false,
expandedSourceError = null,
expandedSourcePage = 1,
showExpandedSource = true,
expandedSourceSavedScrollIndex = 0,
expandedSourceSavedScrollOffset = 0,
)
}
loadExpandedSourcePage(intent.sourceUrl, page = 1)
@@ -241,15 +249,7 @@ class SearchViewModel(
SearchIntent.DismissExpandedSource -> {
_uiState.update {
it.copy(
expandedSourceUrl = null,
expandedSourceName = null,
expandedSourceBooks = persistentListOf(),
expandedSourceLoading = false,
expandedSourceEnd = false,
expandedSourceError = null,
expandedSourcePage = 1,
)
it.copy(showExpandedSource = false)
}
}
@@ -267,17 +267,6 @@ class SearchViewModel(
}
is SearchIntent.OpenExpandedSourceBook -> {
_uiState.update {
it.copy(
expandedSourceUrl = null,
expandedSourceName = null,
expandedSourceBooks = persistentListOf(),
expandedSourceLoading = false,
expandedSourceEnd = false,
expandedSourceError = null,
expandedSourcePage = 1,
)
}
emitEffect(
SearchEffect.OpenBookInfo(
name = intent.book.name,
@@ -298,6 +287,15 @@ class SearchViewModel(
)
}
}
is SearchIntent.SaveExpandedSourceScrollState -> {
_uiState.update {
it.copy(
expandedSourceSavedScrollIndex = intent.index,
expandedSourceSavedScrollOffset = intent.offset,
)
}
}
}
}
@@ -426,6 +424,16 @@ class SearchViewModel(
processedSources = 0,
totalSources = 0,
emptyScopeAction = null,
expandedSourceUrl = null,
expandedSourceName = null,
expandedSourceBooks = persistentListOf(),
expandedSourceLoading = false,
expandedSourceEnd = false,
expandedSourceError = null,
expandedSourcePage = 1,
showExpandedSource = false,
expandedSourceSavedScrollIndex = 0,
expandedSourceSavedScrollOffset = 0,
)
}
@@ -550,6 +558,16 @@ class SearchViewModel(
hasMore = true,
showSuggestions = true,
emptyScopeAction = null,
expandedSourceUrl = null,
expandedSourceName = null,
expandedSourceBooks = persistentListOf(),
expandedSourceLoading = false,
expandedSourceEnd = false,
expandedSourceError = null,
expandedSourcePage = 1,
showExpandedSource = false,
expandedSourceSavedScrollIndex = 0,
expandedSourceSavedScrollOffset = 0,
)
}
}