@@ -51,6 +51,9 @@ data class SearchUiState(
|
|||||||
val expandedSourceEnd: Boolean = false,
|
val expandedSourceEnd: Boolean = false,
|
||||||
val expandedSourceError: String? = null,
|
val expandedSourceError: String? = null,
|
||||||
val expandedSourcePage: Int = 1,
|
val expandedSourcePage: Int = 1,
|
||||||
|
val showExpandedSource: Boolean = false,
|
||||||
|
val expandedSourceSavedScrollIndex: Int = 0,
|
||||||
|
val expandedSourceSavedScrollOffset: Int = 0,
|
||||||
)
|
)
|
||||||
|
|
||||||
data class SearchEmptyScopeAction(
|
data class SearchEmptyScopeAction(
|
||||||
@@ -90,6 +93,7 @@ sealed interface SearchIntent {
|
|||||||
data object DismissEmptyScopeAction : SearchIntent
|
data object DismissEmptyScopeAction : SearchIntent
|
||||||
data object OpenSourceManage : SearchIntent
|
data object OpenSourceManage : SearchIntent
|
||||||
data class SaveScrollState(val index: Int, val offset: Int) : SearchIntent
|
data class SaveScrollState(val index: Int, val offset: Int) : SearchIntent
|
||||||
|
data class SaveExpandedSourceScrollState(val index: Int, val offset: Int) : SearchIntent
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed interface SearchEffect {
|
sealed interface SearchEffect {
|
||||||
|
|||||||
@@ -698,14 +698,19 @@ fun SearchScreen(
|
|||||||
)
|
)
|
||||||
|
|
||||||
ExpandedSourceSheet(
|
ExpandedSourceSheet(
|
||||||
show = state.expandedSourceUrl != null,
|
show = state.showExpandedSource,
|
||||||
sourceName = state.expandedSourceName ?: "",
|
sourceName = state.expandedSourceName ?: "",
|
||||||
books = state.expandedSourceBooks,
|
books = state.expandedSourceBooks,
|
||||||
isLoading = state.expandedSourceLoading,
|
isLoading = state.expandedSourceLoading,
|
||||||
isEnd = state.expandedSourceEnd,
|
isEnd = state.expandedSourceEnd,
|
||||||
errorMsg = state.expandedSourceError,
|
errorMsg = state.expandedSourceError,
|
||||||
|
savedScrollIndex = state.expandedSourceSavedScrollIndex,
|
||||||
|
savedScrollOffset = state.expandedSourceSavedScrollOffset,
|
||||||
onDismiss = { viewModel.onIntent(SearchIntent.DismissExpandedSource) },
|
onDismiss = { viewModel.onIntent(SearchIntent.DismissExpandedSource) },
|
||||||
onLoadMore = { viewModel.onIntent(SearchIntent.LoadMoreExpandedSource) },
|
onLoadMore = { viewModel.onIntent(SearchIntent.LoadMoreExpandedSource) },
|
||||||
|
onSaveScrollState = { index, offset ->
|
||||||
|
viewModel.onIntent(SearchIntent.SaveExpandedSourceScrollState(index, offset))
|
||||||
|
},
|
||||||
onBookClick = { book, coverKey ->
|
onBookClick = { book, coverKey ->
|
||||||
viewModel.onIntent(SearchIntent.OpenExpandedSourceBook(book, coverKey))
|
viewModel.onIntent(SearchIntent.OpenExpandedSourceBook(book, coverKey))
|
||||||
},
|
},
|
||||||
@@ -888,8 +893,11 @@ private fun ExpandedSourceSheet(
|
|||||||
isLoading: Boolean,
|
isLoading: Boolean,
|
||||||
isEnd: Boolean,
|
isEnd: Boolean,
|
||||||
errorMsg: String?,
|
errorMsg: String?,
|
||||||
|
savedScrollIndex: Int,
|
||||||
|
savedScrollOffset: Int,
|
||||||
onDismiss: () -> Unit,
|
onDismiss: () -> Unit,
|
||||||
onLoadMore: () -> Unit,
|
onLoadMore: () -> Unit,
|
||||||
|
onSaveScrollState: (Int, Int) -> Unit,
|
||||||
onBookClick: (SearchBook, String?) -> Unit,
|
onBookClick: (SearchBook, String?) -> Unit,
|
||||||
onBookLongClick: ((SearchBook, String?) -> Unit)? = null,
|
onBookLongClick: ((SearchBook, String?) -> Unit)? = null,
|
||||||
) {
|
) {
|
||||||
@@ -900,7 +908,7 @@ private fun ExpandedSourceSheet(
|
|||||||
) {
|
) {
|
||||||
val listState = rememberLazyListState()
|
val listState = rememberLazyListState()
|
||||||
val showLoadMoreFooter = isLoading || errorMsg != null || isEnd
|
val showLoadMoreFooter = isLoading || errorMsg != null || isEnd
|
||||||
|
val currentOnSaveScrollState by rememberUpdatedState(onSaveScrollState)
|
||||||
val shouldLoadMore by remember {
|
val shouldLoadMore by remember {
|
||||||
derivedStateOf {
|
derivedStateOf {
|
||||||
val total = listState.layoutInfo.totalItemsCount
|
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(
|
LazyColumn(
|
||||||
state = listState,
|
state = listState,
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
|
|||||||
@@ -225,6 +225,11 @@ class SearchViewModel(
|
|||||||
SearchIntent.OpenSourceManage -> emitEffect(SearchEffect.OpenSourceManage)
|
SearchIntent.OpenSourceManage -> emitEffect(SearchEffect.OpenSourceManage)
|
||||||
|
|
||||||
is SearchIntent.ExpandSource -> {
|
is SearchIntent.ExpandSource -> {
|
||||||
|
val state = _uiState.value
|
||||||
|
if (state.expandedSourceUrl == intent.sourceUrl) {
|
||||||
|
_uiState.update { it.copy(showExpandedSource = true) }
|
||||||
|
return
|
||||||
|
}
|
||||||
_uiState.update {
|
_uiState.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
expandedSourceUrl = intent.sourceUrl,
|
expandedSourceUrl = intent.sourceUrl,
|
||||||
@@ -234,6 +239,9 @@ class SearchViewModel(
|
|||||||
expandedSourceEnd = false,
|
expandedSourceEnd = false,
|
||||||
expandedSourceError = null,
|
expandedSourceError = null,
|
||||||
expandedSourcePage = 1,
|
expandedSourcePage = 1,
|
||||||
|
showExpandedSource = true,
|
||||||
|
expandedSourceSavedScrollIndex = 0,
|
||||||
|
expandedSourceSavedScrollOffset = 0,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
loadExpandedSourcePage(intent.sourceUrl, page = 1)
|
loadExpandedSourcePage(intent.sourceUrl, page = 1)
|
||||||
@@ -241,15 +249,7 @@ class SearchViewModel(
|
|||||||
|
|
||||||
SearchIntent.DismissExpandedSource -> {
|
SearchIntent.DismissExpandedSource -> {
|
||||||
_uiState.update {
|
_uiState.update {
|
||||||
it.copy(
|
it.copy(showExpandedSource = false)
|
||||||
expandedSourceUrl = null,
|
|
||||||
expandedSourceName = null,
|
|
||||||
expandedSourceBooks = persistentListOf(),
|
|
||||||
expandedSourceLoading = false,
|
|
||||||
expandedSourceEnd = false,
|
|
||||||
expandedSourceError = null,
|
|
||||||
expandedSourcePage = 1,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -267,17 +267,6 @@ class SearchViewModel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
is SearchIntent.OpenExpandedSourceBook -> {
|
is SearchIntent.OpenExpandedSourceBook -> {
|
||||||
_uiState.update {
|
|
||||||
it.copy(
|
|
||||||
expandedSourceUrl = null,
|
|
||||||
expandedSourceName = null,
|
|
||||||
expandedSourceBooks = persistentListOf(),
|
|
||||||
expandedSourceLoading = false,
|
|
||||||
expandedSourceEnd = false,
|
|
||||||
expandedSourceError = null,
|
|
||||||
expandedSourcePage = 1,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
emitEffect(
|
emitEffect(
|
||||||
SearchEffect.OpenBookInfo(
|
SearchEffect.OpenBookInfo(
|
||||||
name = intent.book.name,
|
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,
|
processedSources = 0,
|
||||||
totalSources = 0,
|
totalSources = 0,
|
||||||
emptyScopeAction = null,
|
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,
|
hasMore = true,
|
||||||
showSuggestions = true,
|
showSuggestions = true,
|
||||||
emptyScopeAction = null,
|
emptyScopeAction = null,
|
||||||
|
expandedSourceUrl = null,
|
||||||
|
expandedSourceName = null,
|
||||||
|
expandedSourceBooks = persistentListOf(),
|
||||||
|
expandedSourceLoading = false,
|
||||||
|
expandedSourceEnd = false,
|
||||||
|
expandedSourceError = null,
|
||||||
|
expandedSourcePage = 1,
|
||||||
|
showExpandedSource = false,
|
||||||
|
expandedSourceSavedScrollIndex = 0,
|
||||||
|
expandedSourceSavedScrollOffset = 0,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user