forked from melod1n/fast-messenger
saving scroll position only while app is working & add divider with spacer on conversations screen
This commit is contained in:
+11
@@ -60,6 +60,9 @@ interface ConversationsViewModel {
|
||||
fun onOptionClicked(conversation: UiConversation, option: ConversationOption)
|
||||
|
||||
fun onErrorConsumed()
|
||||
|
||||
fun setScrollIndex(index: Int)
|
||||
fun setScrollOffset(offset: Int)
|
||||
}
|
||||
|
||||
class ConversationsViewModelImpl(
|
||||
@@ -206,6 +209,14 @@ class ConversationsViewModelImpl(
|
||||
baseError.setValue { null }
|
||||
}
|
||||
|
||||
override fun setScrollIndex(index: Int) {
|
||||
screenState.setValue { old -> old.copy(scrollIndex = index) }
|
||||
}
|
||||
|
||||
override fun setScrollOffset(offset: Int) {
|
||||
screenState.setValue { old -> old.copy(scrollOffset = offset) }
|
||||
}
|
||||
|
||||
private fun hideOptions(conversationId: Int) {
|
||||
screenState.setValue { old ->
|
||||
old.copy(
|
||||
|
||||
+6
-2
@@ -9,7 +9,9 @@ data class ConversationsScreenState(
|
||||
val isLoading: Boolean,
|
||||
val isPaginating: Boolean,
|
||||
val isPaginationExhausted: Boolean,
|
||||
val profileImageUrl: String?
|
||||
val profileImageUrl: String?,
|
||||
val scrollIndex: Int,
|
||||
val scrollOffset: Int
|
||||
) {
|
||||
|
||||
companion object {
|
||||
@@ -19,7 +21,9 @@ data class ConversationsScreenState(
|
||||
isLoading = true,
|
||||
isPaginating = false,
|
||||
isPaginationExhausted = false,
|
||||
profileImageUrl = null
|
||||
profileImageUrl = null,
|
||||
scrollIndex = 0,
|
||||
scrollOffset = 0,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+2
-3
@@ -45,8 +45,6 @@ fun ConversationsList(
|
||||
) {
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
|
||||
val conversations = screenState.conversations
|
||||
|
||||
val bottomPadding = LocalBottomPadding.current
|
||||
|
||||
LazyColumn(
|
||||
@@ -55,9 +53,10 @@ fun ConversationsList(
|
||||
) {
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(padding.calculateTopPadding()))
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
}
|
||||
items(
|
||||
items = conversations,
|
||||
items = screenState.conversations,
|
||||
key = UiConversation::id,
|
||||
) { conversation ->
|
||||
val isUserAccount by remember(conversation) {
|
||||
|
||||
+12
-22
@@ -1,6 +1,5 @@
|
||||
package dev.meloda.fast.conversations.presentation
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.animateColorAsState
|
||||
import androidx.compose.animation.core.Animatable
|
||||
@@ -29,6 +28,7 @@ import androidx.compose.material3.DropdownMenu
|
||||
import androidx.compose.material3.DropdownMenuItem
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.FloatingActionButton
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.LinearProgressIndicator
|
||||
@@ -63,7 +63,6 @@ import androidx.compose.ui.unit.DpOffset
|
||||
import androidx.compose.ui.unit.IntOffset
|
||||
import androidx.compose.ui.unit.LayoutDirection
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.content.edit
|
||||
import androidx.core.view.HapticFeedbackConstantsCompat
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import coil.imageLoader
|
||||
@@ -88,7 +87,6 @@ import dev.meloda.fast.ui.util.isScrollingUp
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.debounce
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.compose.koinInject
|
||||
import dev.meloda.fast.ui.R as UiR
|
||||
|
||||
@Composable
|
||||
@@ -100,8 +98,6 @@ fun ConversationsRoute(
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
|
||||
val prefs: SharedPreferences = koinInject()
|
||||
|
||||
val screenState by viewModel.screenState.collectAsStateWithLifecycle()
|
||||
val baseError by viewModel.baseError.collectAsStateWithLifecycle()
|
||||
val canPaginate by viewModel.canPaginate.collectAsStateWithLifecycle()
|
||||
@@ -121,8 +117,6 @@ fun ConversationsRoute(
|
||||
screenState = screenState,
|
||||
baseError = baseError,
|
||||
canPaginate = canPaginate,
|
||||
firstVisibleItemIndex = prefs.getInt("conversations_all_scroll_position", 0),
|
||||
firstVisibleItemScrollOffset = prefs.getInt("conversations_all_scroll_offset", 0),
|
||||
onSessionExpiredLogOutButtonClicked = { onError(BaseError.SessionExpired) },
|
||||
onConversationItemClicked = { id ->
|
||||
onConversationItemClicked(id)
|
||||
@@ -134,15 +128,10 @@ fun ConversationsRoute(
|
||||
onRefreshDropdownItemClicked = viewModel::onRefresh,
|
||||
onRefresh = viewModel::onRefresh,
|
||||
onConversationPhotoClicked = onConversationPhotoClicked,
|
||||
onSaveScrollPosition = { index ->
|
||||
prefs.edit { putInt("conversations_all_scroll_position", index) }
|
||||
},
|
||||
onSaveScrollOffsetPosition = { offset ->
|
||||
prefs.edit { putInt("conversations_all_scroll_offset", offset) }
|
||||
}
|
||||
setScrollIndex = viewModel::setScrollIndex,
|
||||
setScrollOffset = viewModel::setScrollOffset
|
||||
)
|
||||
|
||||
|
||||
HandleDialogs(
|
||||
screenState = screenState,
|
||||
viewModel = viewModel
|
||||
@@ -158,8 +147,6 @@ fun ConversationsScreen(
|
||||
screenState: ConversationsScreenState = ConversationsScreenState.EMPTY,
|
||||
baseError: BaseError? = null,
|
||||
canPaginate: Boolean = false,
|
||||
firstVisibleItemIndex: Int = 0,
|
||||
firstVisibleItemScrollOffset: Int = 0,
|
||||
onSessionExpiredLogOutButtonClicked: () -> Unit,
|
||||
onConversationItemClicked: (conversationId: Int) -> Unit = {},
|
||||
onConversationItemLongClicked: (conversation: UiConversation) -> Unit = {},
|
||||
@@ -168,8 +155,8 @@ fun ConversationsScreen(
|
||||
onRefreshDropdownItemClicked: () -> Unit = {},
|
||||
onRefresh: () -> Unit = {},
|
||||
onConversationPhotoClicked: (url: String) -> Unit = {},
|
||||
onSaveScrollPosition: (Int) -> Unit = {},
|
||||
onSaveScrollOffsetPosition: (Int) -> Unit = {}
|
||||
setScrollIndex: (Int) -> Unit = {},
|
||||
setScrollOffset: (Int) -> Unit = {}
|
||||
) {
|
||||
val view = LocalView.current
|
||||
val currentTheme = LocalThemeConfig.current
|
||||
@@ -179,20 +166,20 @@ fun ConversationsScreen(
|
||||
}
|
||||
|
||||
val listState = rememberLazyListState(
|
||||
initialFirstVisibleItemIndex = firstVisibleItemIndex,
|
||||
initialFirstVisibleItemScrollOffset = firstVisibleItemScrollOffset
|
||||
initialFirstVisibleItemIndex = screenState.scrollIndex,
|
||||
initialFirstVisibleItemScrollOffset = screenState.scrollOffset
|
||||
)
|
||||
|
||||
LaunchedEffect(listState) {
|
||||
snapshotFlow { listState.firstVisibleItemIndex }
|
||||
.debounce(500L)
|
||||
.collectLatest(onSaveScrollPosition)
|
||||
.collectLatest(setScrollIndex)
|
||||
}
|
||||
|
||||
LaunchedEffect(listState) {
|
||||
snapshotFlow { listState.firstVisibleItemScrollOffset }
|
||||
.debounce(500L)
|
||||
.collectLatest(onSaveScrollOffsetPosition)
|
||||
.collectLatest(setScrollOffset)
|
||||
}
|
||||
|
||||
val paginationConditionMet by remember(canPaginate, listState) {
|
||||
@@ -306,6 +293,9 @@ fun ConversationsScreen(
|
||||
AnimatedVisibility(showHorizontalProgressBar) {
|
||||
LinearProgressIndicator(modifier = Modifier.fillMaxWidth())
|
||||
}
|
||||
AnimatedVisibility(!showHorizontalProgressBar) {
|
||||
HorizontalDivider()
|
||||
}
|
||||
}
|
||||
},
|
||||
floatingActionButton = {
|
||||
|
||||
Reference in New Issue
Block a user