forked from melod1n/fast-messenger
support for articles; ui & ux & logic fixes for 2fa and captcha screens; fix mentions;
This commit is contained in:
+12
-26
@@ -1,10 +1,8 @@
|
||||
package com.meloda.app.fast.auth.twofa
|
||||
|
||||
import android.util.Log
|
||||
import androidx.lifecycle.SavedStateHandle
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.meloda.app.fast.auth.twofa.model.TwoFaArguments
|
||||
import com.meloda.app.fast.auth.twofa.model.TwoFaScreenState
|
||||
import com.meloda.app.fast.auth.twofa.model.TwoFaValidationType
|
||||
import com.meloda.app.fast.auth.twofa.navigation.TwoFa
|
||||
@@ -20,6 +18,7 @@ import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
|
||||
@@ -27,6 +26,8 @@ interface TwoFaViewModel {
|
||||
|
||||
val screenState: StateFlow<TwoFaScreenState>
|
||||
|
||||
val isNeedToOpenLogin: StateFlow<Boolean>
|
||||
|
||||
fun onCodeInputChanged(newCode: String)
|
||||
|
||||
fun onBackButtonClicked()
|
||||
@@ -36,8 +37,6 @@ interface TwoFaViewModel {
|
||||
fun onDoneButtonClicked()
|
||||
|
||||
fun onNavigatedToLogin()
|
||||
|
||||
fun setArguments(arguments: TwoFaArguments)
|
||||
}
|
||||
|
||||
class TwoFaViewModelImpl(
|
||||
@@ -48,6 +47,8 @@ class TwoFaViewModelImpl(
|
||||
|
||||
override val screenState = MutableStateFlow(TwoFaScreenState.EMPTY)
|
||||
|
||||
override val isNeedToOpenLogin = MutableStateFlow(false)
|
||||
|
||||
private var delayJob: Job? = null
|
||||
|
||||
init {
|
||||
@@ -88,12 +89,8 @@ class TwoFaViewModelImpl(
|
||||
}
|
||||
|
||||
override fun onCancelButtonClicked() {
|
||||
screenState.updateValue(
|
||||
screenState.value.copy(
|
||||
twoFaCode = null,
|
||||
isNeedToOpenLogin = true
|
||||
)
|
||||
)
|
||||
screenState.setValue { old -> old.copy(twoFaCode = null) }
|
||||
isNeedToOpenLogin.update { true }
|
||||
}
|
||||
|
||||
override fun onRequestSmsButtonClicked() {
|
||||
@@ -107,25 +104,12 @@ class TwoFaViewModelImpl(
|
||||
override fun onDoneButtonClicked() {
|
||||
if (!processValidation()) return
|
||||
|
||||
screenState.updateValue(screenState.value.copy(isNeedToOpenLogin = true))
|
||||
isNeedToOpenLogin.update { true }
|
||||
}
|
||||
|
||||
override fun onNavigatedToLogin() {
|
||||
screenState.updateValue(TwoFaScreenState.EMPTY)
|
||||
}
|
||||
|
||||
override fun setArguments(arguments: TwoFaArguments) {
|
||||
Log.d("TwoFaViewModel", "TwoFaArguments: $arguments")
|
||||
|
||||
// screenState.updateValue(
|
||||
// screenState.value.copy(
|
||||
// twoFaSid = arguments.validationSid,
|
||||
// canResendSms = arguments.canResendSms,
|
||||
// codeError = arguments.wrongCodeError,
|
||||
// twoFaText = getTwoFaText(TwoFaValidationType.parse(arguments.validationType)),
|
||||
// phoneMask = arguments.phoneMask
|
||||
// )
|
||||
// )
|
||||
isNeedToOpenLogin.update { false }
|
||||
}
|
||||
|
||||
private fun processValidation(): Boolean {
|
||||
@@ -147,7 +131,9 @@ class TwoFaViewModelImpl(
|
||||
authUseCase.sendSms(validationSid)
|
||||
.listenValue { state ->
|
||||
state.processState(
|
||||
error = { error -> },
|
||||
error = { error ->
|
||||
|
||||
},
|
||||
success = { response ->
|
||||
val newValidationType = response.validationType
|
||||
val newCanResendSms = response.validationResend == "sms"
|
||||
|
||||
-2
@@ -9,7 +9,6 @@ data class TwoFaScreenState(
|
||||
val canResendSms: Boolean,
|
||||
val codeError: String?,
|
||||
val delayTime: Int,
|
||||
val isNeedToOpenLogin: Boolean,
|
||||
val phoneMask: String
|
||||
) {
|
||||
|
||||
@@ -21,7 +20,6 @@ data class TwoFaScreenState(
|
||||
canResendSms = false,
|
||||
codeError = null,
|
||||
delayTime = 0,
|
||||
isNeedToOpenLogin = false,
|
||||
phoneMask = ""
|
||||
)
|
||||
}
|
||||
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
package com.meloda.app.fast.auth.twofa.model
|
||||
|
||||
sealed class TwoFaUiAction {
|
||||
data class CodeResult(val code: String) : TwoFaUiAction()
|
||||
data object BackClicked : TwoFaUiAction()
|
||||
}
|
||||
+5
-8
@@ -6,7 +6,6 @@ import androidx.navigation.NavGraphBuilder
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.toRoute
|
||||
import com.meloda.app.fast.auth.twofa.model.TwoFaArguments
|
||||
import com.meloda.app.fast.auth.twofa.model.TwoFaUiAction
|
||||
import com.meloda.app.fast.auth.twofa.presentation.TwoFaScreen
|
||||
import com.meloda.app.fast.common.customNavType
|
||||
import kotlinx.serialization.Serializable
|
||||
@@ -28,12 +27,8 @@ fun NavGraphBuilder.twoFaRoute(
|
||||
) {
|
||||
composable<TwoFa>(typeMap = TwoFa.typeMap) {
|
||||
TwoFaScreen(
|
||||
onAction = { action ->
|
||||
when (action) {
|
||||
TwoFaUiAction.BackClicked -> onBack()
|
||||
is TwoFaUiAction.CodeResult -> onResult(action.code)
|
||||
}
|
||||
}
|
||||
onBack = onBack,
|
||||
onCodeResult = onResult
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -42,8 +37,10 @@ fun NavController.navigateToTwoFa(arguments: TwoFaArguments) {
|
||||
this.navigate(TwoFa(arguments))
|
||||
}
|
||||
|
||||
fun NavController.setTwoFaResult(code: String) {
|
||||
fun NavController.setTwoFaResult(code: String?) {
|
||||
this.currentBackStackEntry
|
||||
?.savedStateHandle
|
||||
?.set("twofacode", code)
|
||||
}
|
||||
|
||||
|
||||
|
||||
+22
-17
@@ -26,6 +26,7 @@ import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextField
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
@@ -43,7 +44,6 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.meloda.app.fast.auth.twofa.TwoFaViewModel
|
||||
import com.meloda.app.fast.auth.twofa.TwoFaViewModelImpl
|
||||
import com.meloda.app.fast.auth.twofa.model.TwoFaUiAction
|
||||
import com.meloda.app.fast.common.UiText
|
||||
import com.meloda.app.fast.designsystem.MaterialDialog
|
||||
import com.meloda.app.fast.designsystem.TextFieldErrorText
|
||||
@@ -51,17 +51,18 @@ import com.meloda.app.fast.designsystem.getString
|
||||
import org.koin.androidx.compose.koinViewModel
|
||||
import com.meloda.app.fast.designsystem.R as UiR
|
||||
|
||||
private typealias OnAction = (TwoFaUiAction) -> Unit
|
||||
|
||||
@Composable
|
||||
fun TwoFaScreen(
|
||||
onAction: OnAction,
|
||||
onBack: () -> Unit,
|
||||
onCodeResult: (code: String) -> Unit,
|
||||
viewModel: TwoFaViewModel = koinViewModel<TwoFaViewModelImpl>(),
|
||||
) {
|
||||
val focusManager = LocalFocusManager.current
|
||||
|
||||
val screenState by viewModel.screenState.collectAsStateWithLifecycle()
|
||||
|
||||
val isNeedToOpenLogin by viewModel.isNeedToOpenLogin.collectAsStateWithLifecycle()
|
||||
|
||||
var confirmedExit by rememberSaveable {
|
||||
mutableStateOf(false)
|
||||
}
|
||||
@@ -70,8 +71,10 @@ fun TwoFaScreen(
|
||||
mutableStateOf(false)
|
||||
}
|
||||
|
||||
if (confirmedExit) {
|
||||
onAction(TwoFaUiAction.BackClicked)
|
||||
LaunchedEffect(confirmedExit) {
|
||||
if (confirmedExit) {
|
||||
onBack()
|
||||
}
|
||||
}
|
||||
|
||||
BackHandler(enabled = !confirmedExit) {
|
||||
@@ -93,17 +96,22 @@ fun TwoFaScreen(
|
||||
)
|
||||
}
|
||||
|
||||
if (screenState.isNeedToOpenLogin) {
|
||||
viewModel.onNavigatedToLogin()
|
||||
LaunchedEffect(isNeedToOpenLogin) {
|
||||
if (isNeedToOpenLogin) {
|
||||
viewModel.onNavigatedToLogin()
|
||||
|
||||
val code = screenState.twoFaCode
|
||||
if (code == null) {
|
||||
onAction(TwoFaUiAction.BackClicked)
|
||||
} else {
|
||||
onAction(TwoFaUiAction.CodeResult(code = code))
|
||||
val code = screenState.twoFaCode
|
||||
if (code == null) {
|
||||
onBack()
|
||||
} else {
|
||||
onCodeResult(code)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var code by remember { mutableStateOf(TextFieldValue(screenState.twoFaCode.orEmpty())) }
|
||||
val codeError = screenState.codeError
|
||||
|
||||
Scaffold { padding ->
|
||||
Column(
|
||||
modifier = Modifier
|
||||
@@ -113,7 +121,7 @@ fun TwoFaScreen(
|
||||
verticalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
ExtendedFloatingActionButton(
|
||||
onClick = { onAction(TwoFaUiAction.BackClicked) },
|
||||
onClick = onBack,
|
||||
text = {
|
||||
Text(
|
||||
text = "Cancel",
|
||||
@@ -155,9 +163,6 @@ fun TwoFaScreen(
|
||||
}
|
||||
Spacer(modifier = Modifier.height(10.dp))
|
||||
|
||||
var code by remember { mutableStateOf(TextFieldValue(screenState.twoFaCode.orEmpty())) }
|
||||
val codeError = screenState.codeError
|
||||
|
||||
TextField(
|
||||
value = code,
|
||||
onValueChange = { newText ->
|
||||
|
||||
Reference in New Issue
Block a user