save the lazy list state and make it scroll in the search view model to avoid coming back on another feed position
This commit is contained in:
+6
-2
@@ -20,6 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.search
|
package com.vitorpamplona.amethyst.ui.screen.loggedIn.search
|
||||||
|
|
||||||
|
import androidx.compose.foundation.lazy.LazyListState
|
||||||
import androidx.compose.runtime.Stable
|
import androidx.compose.runtime.Stable
|
||||||
import androidx.compose.runtime.derivedStateOf
|
import androidx.compose.runtime.derivedStateOf
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
@@ -87,8 +88,10 @@ class SearchBarViewModel(
|
|||||||
|
|
||||||
val searchDataSourceState = SearchQueryState(MutableStateFlow(searchValue), account)
|
val searchDataSourceState = SearchQueryState(MutableStateFlow(searchValue), account)
|
||||||
|
|
||||||
|
val listState: LazyListState = LazyListState(0, 0)
|
||||||
|
|
||||||
val directNip05Resolver: Flow<User?> =
|
val directNip05Resolver: Flow<User?> =
|
||||||
searchValueFlow
|
searchTerm
|
||||||
.debounce(400)
|
.debounce(400)
|
||||||
.mapLatest { term ->
|
.mapLatest { term ->
|
||||||
if (term.contains('@')) {
|
if (term.contains('@')) {
|
||||||
@@ -248,11 +251,12 @@ class SearchBarViewModel(
|
|||||||
|
|
||||||
fun clear() = updateSearchValue("")
|
fun clear() = updateSearchValue("")
|
||||||
|
|
||||||
fun updateDataSource(searchTerm: String) {
|
suspend fun updateDataSource(searchTerm: String) {
|
||||||
if (searchTerm.isBlank()) {
|
if (searchTerm.isBlank()) {
|
||||||
searchDataSourceState.searchQuery.tryEmit("")
|
searchDataSourceState.searchQuery.tryEmit("")
|
||||||
} else {
|
} else {
|
||||||
searchDataSourceState.searchQuery.tryEmit(searchTerm)
|
searchDataSourceState.searchQuery.tryEmit(searchTerm)
|
||||||
|
listState.scrollToItem(0, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+6
-25
@@ -31,7 +31,6 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
|||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.statusBarsPadding
|
import androidx.compose.foundation.layout.statusBarsPadding
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.LazyListState
|
|
||||||
import androidx.compose.foundation.lazy.itemsIndexed
|
import androidx.compose.foundation.lazy.itemsIndexed
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.foundation.text.KeyboardOptions
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
@@ -58,9 +57,7 @@ import com.vitorpamplona.amethyst.R
|
|||||||
import com.vitorpamplona.amethyst.model.LocalCache
|
import com.vitorpamplona.amethyst.model.LocalCache
|
||||||
import com.vitorpamplona.amethyst.model.nip11RelayInfo.loadRelayInfo
|
import com.vitorpamplona.amethyst.model.nip11RelayInfo.loadRelayInfo
|
||||||
import com.vitorpamplona.amethyst.service.relayClient.searchCommand.TextSearchDataSourceSubscription
|
import com.vitorpamplona.amethyst.service.relayClient.searchCommand.TextSearchDataSourceSubscription
|
||||||
import com.vitorpamplona.amethyst.ui.feeds.ScrollStateKeys
|
|
||||||
import com.vitorpamplona.amethyst.ui.feeds.WatchLifecycleAndUpdateModel
|
import com.vitorpamplona.amethyst.ui.feeds.WatchLifecycleAndUpdateModel
|
||||||
import com.vitorpamplona.amethyst.ui.feeds.rememberForeverLazyListState
|
|
||||||
import com.vitorpamplona.amethyst.ui.layouts.DisappearingScaffold
|
import com.vitorpamplona.amethyst.ui.layouts.DisappearingScaffold
|
||||||
import com.vitorpamplona.amethyst.ui.navigation.bottombars.AppBottomBar
|
import com.vitorpamplona.amethyst.ui.navigation.bottombars.AppBottomBar
|
||||||
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
|
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
|
||||||
@@ -109,16 +106,16 @@ fun SearchScreen(
|
|||||||
) {
|
) {
|
||||||
WatchLifecycleAndUpdateModel(searchBarViewModel)
|
WatchLifecycleAndUpdateModel(searchBarViewModel)
|
||||||
|
|
||||||
val listState = rememberForeverLazyListState(ScrollStateKeys.SEARCH_SCREEN)
|
|
||||||
|
|
||||||
LaunchedEffect(searchBarViewModel.focusRequester) {
|
LaunchedEffect(searchBarViewModel.focusRequester) {
|
||||||
searchBarViewModel.focusRequester.requestFocus()
|
if (searchBarViewModel.listState.firstVisibleItemIndex == 0) {
|
||||||
|
searchBarViewModel.focusRequester.requestFocus()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DisappearingScaffold(
|
DisappearingScaffold(
|
||||||
isInvertedLayout = false,
|
isInvertedLayout = false,
|
||||||
topBar = {
|
topBar = {
|
||||||
SearchBar(searchBarViewModel, listState, accountViewModel, nav)
|
SearchBar(searchBarViewModel, accountViewModel, nav)
|
||||||
},
|
},
|
||||||
bottomBar = {
|
bottomBar = {
|
||||||
AppBottomBar(Route.Search, accountViewModel) { route ->
|
AppBottomBar(Route.Search, accountViewModel) { route ->
|
||||||
@@ -131,7 +128,7 @@ fun SearchScreen(
|
|||||||
modifier = Modifier.padding(it).consumeWindowInsets(it),
|
modifier = Modifier.padding(it).consumeWindowInsets(it),
|
||||||
) {
|
) {
|
||||||
ObserveRelayListForSearchAndDisplayIfNotFound(accountViewModel, nav)
|
ObserveRelayListForSearchAndDisplayIfNotFound(accountViewModel, nav)
|
||||||
DisplaySearchResults(searchBarViewModel, listState, nav, accountViewModel)
|
DisplaySearchResults(searchBarViewModel, nav, accountViewModel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -140,7 +137,6 @@ fun SearchScreen(
|
|||||||
@Composable
|
@Composable
|
||||||
private fun SearchBar(
|
private fun SearchBar(
|
||||||
searchBarViewModel: SearchBarViewModel,
|
searchBarViewModel: SearchBarViewModel,
|
||||||
listState: LazyListState,
|
|
||||||
accountViewModel: AccountViewModel,
|
accountViewModel: AccountViewModel,
|
||||||
nav: INav,
|
nav: INav,
|
||||||
) {
|
) {
|
||||||
@@ -164,23 +160,9 @@ private fun SearchBar(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AnimateOnNewSearch(searchBarViewModel, listState)
|
|
||||||
|
|
||||||
SearchTextField(searchBarViewModel, Modifier.statusBarsPadding())
|
SearchTextField(searchBarViewModel, Modifier.statusBarsPadding())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun AnimateOnNewSearch(
|
|
||||||
searchBarViewModel: SearchBarViewModel,
|
|
||||||
listState: LazyListState,
|
|
||||||
) {
|
|
||||||
val searchTerm by searchBarViewModel.searchTerm.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
LaunchedEffect(searchTerm) {
|
|
||||||
listState.animateScrollToItem(0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun SearchTextField(
|
private fun SearchTextField(
|
||||||
searchBarViewModel: SearchBarViewModel,
|
searchBarViewModel: SearchBarViewModel,
|
||||||
@@ -237,7 +219,6 @@ private fun SearchTextField(
|
|||||||
@Composable
|
@Composable
|
||||||
private fun DisplaySearchResults(
|
private fun DisplaySearchResults(
|
||||||
searchBarViewModel: SearchBarViewModel,
|
searchBarViewModel: SearchBarViewModel,
|
||||||
listState: LazyListState,
|
|
||||||
nav: INav,
|
nav: INav,
|
||||||
accountViewModel: AccountViewModel,
|
accountViewModel: AccountViewModel,
|
||||||
) {
|
) {
|
||||||
@@ -256,7 +237,7 @@ private fun DisplaySearchResults(
|
|||||||
LazyColumn(
|
LazyColumn(
|
||||||
modifier = Modifier.fillMaxHeight(),
|
modifier = Modifier.fillMaxHeight(),
|
||||||
contentPadding = FeedPadding,
|
contentPadding = FeedPadding,
|
||||||
state = listState,
|
state = searchBarViewModel.listState,
|
||||||
) {
|
) {
|
||||||
itemsIndexed(
|
itemsIndexed(
|
||||||
hashTags,
|
hashTags,
|
||||||
|
|||||||
Reference in New Issue
Block a user