release 0.1.5 (#98)
* settings reorganization; implement long press on emoji button for fast text; some deprecations fixed; some typos fixed; etc * ability to use more animations (experimental); fix online friends loading; conversation avatar in messages history screen; test second tap on conversations item in bottom bar to scroll to top; etc * version up
This commit is contained in:
+23
@@ -26,7 +26,9 @@ import dev.meloda.fast.model.LongPollEvent
|
||||
import dev.meloda.fast.model.api.domain.VkConversation
|
||||
import dev.meloda.fast.network.VkErrorCode
|
||||
import dev.meloda.fast.ui.util.ImmutableList
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
@@ -34,6 +36,7 @@ import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.coroutines.cancellation.CancellationException
|
||||
|
||||
interface ConversationsViewModel {
|
||||
@@ -43,6 +46,7 @@ interface ConversationsViewModel {
|
||||
val imagesToPreload: StateFlow<List<String>>
|
||||
val currentOffset: StateFlow<Int>
|
||||
val canPaginate: StateFlow<Boolean>
|
||||
val scrollToTop: StateFlow<Boolean>
|
||||
|
||||
fun onPaginationConditionsMet()
|
||||
|
||||
@@ -63,6 +67,10 @@ interface ConversationsViewModel {
|
||||
|
||||
fun setScrollIndex(index: Int)
|
||||
fun setScrollOffset(offset: Int)
|
||||
|
||||
|
||||
fun setScrollToTopFlow(scrollToTopFlow: Flow<Int>)
|
||||
fun onScrolledToTop()
|
||||
}
|
||||
|
||||
class ConversationsViewModelImpl(
|
||||
@@ -78,6 +86,7 @@ class ConversationsViewModelImpl(
|
||||
override val imagesToPreload = MutableStateFlow<List<String>>(emptyList())
|
||||
override val currentOffset = MutableStateFlow(0)
|
||||
override val canPaginate = MutableStateFlow(false)
|
||||
override val scrollToTop = MutableStateFlow(false)
|
||||
|
||||
override fun onPaginationConditionsMet() {
|
||||
currentOffset.update { screenState.value.conversations.size }
|
||||
@@ -217,6 +226,20 @@ class ConversationsViewModelImpl(
|
||||
screenState.setValue { old -> old.copy(scrollOffset = offset) }
|
||||
}
|
||||
|
||||
override fun setScrollToTopFlow(scrollToTopFlow: Flow<Int>) {
|
||||
scrollToTopFlow.listenValue(viewModelScope) { index ->
|
||||
if (index == 1) {
|
||||
scrollToTop.emit(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onScrolledToTop() {
|
||||
viewModelScope.launch(Dispatchers.Main) {
|
||||
scrollToTop.emit(false)
|
||||
}
|
||||
}
|
||||
|
||||
private fun hideOptions(conversationId: Int) {
|
||||
screenState.setValue { old ->
|
||||
old.copy(
|
||||
|
||||
+3
-3
@@ -1,14 +1,14 @@
|
||||
package dev.meloda.fast.conversations.di
|
||||
|
||||
import dev.meloda.fast.conversations.ConversationsViewModelImpl
|
||||
import dev.meloda.fast.domain.ConversationsUseCaseImpl
|
||||
import dev.meloda.fast.domain.ConversationsUseCase
|
||||
import org.koin.androidx.viewmodel.dsl.viewModelOf
|
||||
import dev.meloda.fast.domain.ConversationsUseCaseImpl
|
||||
import org.koin.core.module.dsl.singleOf
|
||||
import org.koin.core.module.dsl.viewModelOf
|
||||
import org.koin.dsl.bind
|
||||
import org.koin.dsl.module
|
||||
|
||||
val conversationsModule = module {
|
||||
singleOf(::ConversationsUseCaseImpl) bind dev.meloda.fast.domain.ConversationsUseCase::class
|
||||
singleOf(::ConversationsUseCaseImpl) bind ConversationsUseCase::class
|
||||
viewModelOf(::ConversationsViewModelImpl)
|
||||
}
|
||||
|
||||
+3
@@ -8,6 +8,7 @@ import dev.meloda.fast.conversations.ConversationsViewModelImpl
|
||||
import dev.meloda.fast.conversations.presentation.ConversationsRoute
|
||||
import dev.meloda.fast.model.BaseError
|
||||
import dev.meloda.fast.ui.extensions.sharedViewModel
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
@@ -17,11 +18,13 @@ fun NavGraphBuilder.conversationsScreen(
|
||||
onError: (BaseError) -> Unit,
|
||||
onConversationItemClicked: (id: Int) -> Unit,
|
||||
onPhotoClicked: (url: String) -> Unit,
|
||||
scrollToTopFlow: Flow<Int>,
|
||||
navController: NavController,
|
||||
) {
|
||||
composable<Conversations> {
|
||||
val viewModel: ConversationsViewModel =
|
||||
it.sharedViewModel<ConversationsViewModelImpl>(navController = navController)
|
||||
viewModel.setScrollToTopFlow(scrollToTopFlow)
|
||||
|
||||
ConversationsRoute(
|
||||
onError = onError,
|
||||
|
||||
+16
-3
@@ -101,6 +101,7 @@ fun ConversationsRoute(
|
||||
val screenState by viewModel.screenState.collectAsStateWithLifecycle()
|
||||
val baseError by viewModel.baseError.collectAsStateWithLifecycle()
|
||||
val canPaginate by viewModel.canPaginate.collectAsStateWithLifecycle()
|
||||
val isNeedToScrollToTop by viewModel.scrollToTop.collectAsStateWithLifecycle()
|
||||
|
||||
val imagesToPreload by viewModel.imagesToPreload.collectAsStateWithLifecycle()
|
||||
LaunchedEffect(imagesToPreload) {
|
||||
@@ -129,7 +130,9 @@ fun ConversationsRoute(
|
||||
onRefresh = viewModel::onRefresh,
|
||||
onConversationPhotoClicked = onConversationPhotoClicked,
|
||||
setScrollIndex = viewModel::setScrollIndex,
|
||||
setScrollOffset = viewModel::setScrollOffset
|
||||
setScrollOffset = viewModel::setScrollOffset,
|
||||
isNeedToScrollToTop = isNeedToScrollToTop,
|
||||
onScrolledToTop = viewModel::onScrolledToTop
|
||||
)
|
||||
|
||||
HandleDialogs(
|
||||
@@ -156,7 +159,9 @@ fun ConversationsScreen(
|
||||
onRefresh: () -> Unit = {},
|
||||
onConversationPhotoClicked: (url: String) -> Unit = {},
|
||||
setScrollIndex: (Int) -> Unit = {},
|
||||
setScrollOffset: (Int) -> Unit = {}
|
||||
setScrollOffset: (Int) -> Unit = {},
|
||||
isNeedToScrollToTop: Boolean = false,
|
||||
onScrolledToTop: () -> Unit = {}
|
||||
) {
|
||||
val view = LocalView.current
|
||||
val currentTheme = LocalThemeConfig.current
|
||||
@@ -170,6 +175,14 @@ fun ConversationsScreen(
|
||||
initialFirstVisibleItemScrollOffset = screenState.scrollOffset
|
||||
)
|
||||
|
||||
LaunchedEffect(isNeedToScrollToTop) {
|
||||
if (isNeedToScrollToTop) {
|
||||
listState.scrollToItem(0)
|
||||
onScrolledToTop()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(listState) {
|
||||
snapshotFlow { listState.firstVisibleItemIndex }
|
||||
.debounce(500L)
|
||||
@@ -310,7 +323,7 @@ fun ConversationsScreen(
|
||||
) {
|
||||
FloatingActionButton(
|
||||
onClick = {
|
||||
if (AppSettings.Debug.enableHaptic) {
|
||||
if (AppSettings.General.enableHaptic) {
|
||||
view.performHapticFeedback(HapticFeedbackConstantsCompat.REJECT)
|
||||
}
|
||||
scope.launch {
|
||||
|
||||
Reference in New Issue
Block a user