twoFa -> validation naming; fixes for preview for screens (separating view model from ui); some improvements & fixes

This commit is contained in:
2024-07-13 22:45:49 +03:00
parent dfdc48b682
commit 733627f935
98 changed files with 1611 additions and 1637 deletions
@@ -44,7 +44,7 @@ interface ConversationsViewModel {
val currentOffset: StateFlow<Int>
val canPaginate: StateFlow<Boolean>
fun onMetPaginationCondition()
fun onPaginationConditionsMet()
fun onDeleteDialogDismissed()
@@ -52,7 +52,7 @@ interface ConversationsViewModel {
fun onRefresh()
fun onConversationItemClick(conversationId: Int)
fun onConversationItemClick()
fun onConversationItemLongClick(conversation: UiConversation)
fun onPinDialogDismissed()
@@ -76,7 +76,7 @@ class ConversationsViewModelImpl(
override val currentOffset = MutableStateFlow(0)
override val canPaginate = MutableStateFlow(false)
override fun onMetPaginationCondition() {
override fun onPaginationConditionsMet() {
currentOffset.update { screenState.value.conversations.size }
loadConversations()
}
@@ -113,7 +113,7 @@ class ConversationsViewModelImpl(
loadConversations(offset = 0)
}
override fun onConversationItemClick(conversationId: Int) {
override fun onConversationItemClick() {
screenState.setValue { old ->
old.copy(
conversations = old.conversations.map { item ->
@@ -225,25 +225,14 @@ class ConversationsViewModelImpl(
conversationsUseCase.getConversations(count = LOAD_COUNT, offset = offset).listenValue { state ->
state.processState(
error = { error ->
when (error) {
is State.Error.ApiError -> {
val (code, message) = error
when (code) {
VkErrorCodes.UserAuthorizationFailed -> {
baseError.setValue { BaseError.SessionExpired }
}
else -> {
Unit
}
if (error is State.Error.ApiError) {
when (error.errorCode) {
VkErrorCodes.UserAuthorizationFailed -> {
baseError.setValue { BaseError.SessionExpired }
}
}
State.Error.ConnectionError -> TODO()
State.Error.InternalError -> TODO()
is State.Error.OAuthError -> TODO()
State.Error.Unknown -> TODO()
else -> Unit
}
}
},
success = { response ->
@@ -31,7 +31,6 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.meloda.app.fast.designsystem.AppTheme
const val numberOfDots = 3
val dotSize = 6.dp
@@ -298,7 +297,7 @@ fun DotsCollision() {
@Preview(showBackground = true)
@Composable
fun DotsPreview() = AppTheme {
fun DotsPreview() {
Column(
modifier = Modifier
.padding(4.dp)
@@ -6,27 +6,25 @@ import androidx.navigation.compose.composable
import com.meloda.app.fast.common.extensions.navigation.sharedViewModel
import com.meloda.app.fast.conversations.ConversationsViewModel
import com.meloda.app.fast.conversations.ConversationsViewModelImpl
import com.meloda.app.fast.conversations.presentation.ConversationsScreen
import com.meloda.app.fast.conversations.presentation.ConversationsRoute
import com.meloda.app.fast.model.BaseError
import kotlinx.serialization.Serializable
@Serializable
object Conversations
fun NavGraphBuilder.conversationsRoute(
fun NavGraphBuilder.conversationsScreen(
onError: (BaseError) -> Unit,
onNavigateToMessagesHistory: (id: Int) -> Unit,
onListScrollingUp: (Boolean) -> Unit,
onConversationItemClicked: (id: Int) -> Unit,
navController: NavController,
) {
composable<Conversations> {
val viewModel: ConversationsViewModel =
it.sharedViewModel<ConversationsViewModelImpl>(navController = navController)
ConversationsScreen(
ConversationsRoute(
onError = onError,
onNavigateToMessagesHistory = onNavigateToMessagesHistory,
onListScrollingUp = onListScrollingUp,
onConversationItemClicked = onConversationItemClicked,
viewModel = viewModel
)
}
@@ -72,6 +72,7 @@ import coil.request.ImageRequest
import com.meloda.app.fast.common.UiText
import com.meloda.app.fast.conversations.ConversationsViewModel
import com.meloda.app.fast.conversations.ConversationsViewModelImpl
import com.meloda.app.fast.conversations.model.ConversationOption
import com.meloda.app.fast.conversations.model.ConversationsScreenState
import com.meloda.app.fast.conversations.model.UiConversation
import com.meloda.app.fast.designsystem.LocalBottomPadding
@@ -89,34 +90,70 @@ import kotlinx.coroutines.launch
import org.koin.androidx.compose.koinViewModel
import com.meloda.app.fast.designsystem.R as UiR
@Composable
fun ConversationsRoute(
onError: (BaseError) -> Unit,
onConversationItemClicked: (conversationId: Int) -> Unit,
viewModel: ConversationsViewModel = koinViewModel<ConversationsViewModelImpl>()
) {
val context = LocalContext.current
val screenState by viewModel.screenState.collectAsStateWithLifecycle()
val baseError by viewModel.baseError.collectAsStateWithLifecycle()
val canPaginate by viewModel.canPaginate.collectAsStateWithLifecycle()
val imagesToPreload by viewModel.imagesToPreload.collectAsStateWithLifecycle()
LaunchedEffect(imagesToPreload) {
imagesToPreload.forEach { url ->
context.imageLoader.enqueue(
ImageRequest.Builder(context)
.data(url)
.build()
)
}
}
ConversationsScreen(
screenState = screenState,
baseError = baseError,
canPaginate = canPaginate,
onSessionExpiredLogOutButtonClicked = { onError(BaseError.SessionExpired) },
onConversationItemClicked = { id ->
onConversationItemClicked(id)
viewModel.onConversationItemClick()
},
onConversationItemLongClicked = viewModel::onConversationItemLongClick,
onOptionClicked = viewModel::onOptionClicked,
onPaginationConditionsMet = viewModel::onPaginationConditionsMet,
onRefreshDropdownItemClicked = viewModel::onRefresh,
onRefresh = viewModel::onRefresh
)
HandleDialogs(
screenState = screenState,
viewModel = viewModel
)
}
@OptIn(
ExperimentalMaterial3Api::class,
ExperimentalHazeMaterialsApi::class,
)
@Composable
fun ConversationsScreen(
onError: (BaseError) -> Unit,
onNavigateToMessagesHistory: (conversationId: Int) -> Unit,
onListScrollingUp: (Boolean) -> Unit,
viewModel: ConversationsViewModel = koinViewModel<ConversationsViewModelImpl>()
screenState: ConversationsScreenState = ConversationsScreenState.EMPTY,
baseError: BaseError? = null,
canPaginate: Boolean = false,
onSessionExpiredLogOutButtonClicked: () -> Unit,
onConversationItemClicked: (conversationId: Int) -> Unit = {},
onConversationItemLongClicked: (conversation: UiConversation) -> Unit = {},
onOptionClicked: (UiConversation, ConversationOption) -> Unit = { _, _ -> },
onPaginationConditionsMet: () -> Unit = {},
onRefreshDropdownItemClicked: () -> Unit = {},
onRefresh: () -> Unit = {}
) {
val baseError by viewModel.baseError.collectAsStateWithLifecycle()
val context = LocalContext.current
val imagesToPreload by viewModel.imagesToPreload.collectAsStateWithLifecycle()
imagesToPreload.forEach { url ->
context.imageLoader.enqueue(
ImageRequest.Builder(context)
.data(url)
.build()
)
}
val view = LocalView.current
val screenState by viewModel.screenState.collectAsStateWithLifecycle()
val canPaginate by viewModel.canPaginate.collectAsStateWithLifecycle()
val currentTheme = LocalTheme.current
val maxLines by remember {
@@ -129,10 +166,6 @@ fun ConversationsScreen(
val isListScrollingUp = listState.isScrollingUp()
LaunchedEffect(isListScrollingUp) {
onListScrollingUp(isListScrollingUp)
}
val paginationConditionMet by remember {
derivedStateOf {
canPaginate &&
@@ -143,7 +176,7 @@ fun ConversationsScreen(
LaunchedEffect(paginationConditionMet) {
if (paginationConditionMet && !screenState.isPaginating) {
viewModel.onMetPaginationCondition()
onPaginationConditionsMet()
}
}
@@ -213,7 +246,7 @@ fun ConversationsScreen(
) {
DropdownMenuItem(
onClick = {
viewModel.onRefresh()
onRefreshDropdownItemClicked()
dropDownMenuExpanded = false
},
text = {
@@ -301,7 +334,7 @@ fun ConversationsScreen(
ErrorView(
text = "Session expired",
buttonText = "Log out",
onButtonClick = { onError(BaseError.SessionExpired) }
onButtonClick = onSessionExpiredLogOutButtonClicked
)
}
@@ -320,10 +353,10 @@ fun ConversationsScreen(
) {
ConversationsListComposable(
onConversationsClick = { id ->
onNavigateToMessagesHistory(id)
viewModel.onConversationItemClick(id)
onConversationItemClicked(id)
},
onConversationsLongClick = viewModel::onConversationItemLongClick,
onConversationsLongClick = onConversationItemLongClicked,
screenState = screenState,
state = listState,
maxLines = maxLines,
@@ -335,13 +368,13 @@ fun ConversationsScreen(
} else {
Modifier
}.fillMaxSize(),
onOptionClicked = viewModel::onOptionClicked,
onOptionClicked = onOptionClicked,
padding = padding
)
if (pullToRefreshState.isRefreshing) {
LaunchedEffect(true) {
viewModel.onRefresh()
onRefresh()
}
}
@@ -362,11 +395,6 @@ fun ConversationsScreen(
}
}
}
HandleDialogs(
screenState = screenState,
viewModel = viewModel
)
}
}