fast login with token

This commit is contained in:
2024-07-19 06:01:16 +03:00
parent 1817698031
commit 2b018add7c
3 changed files with 84 additions and 16 deletions
+1
View File
@@ -263,4 +263,5 @@
<string name="captcha_exit_warning">Are you sure? Captcha process will be cancelled</string>
<string name="validation_exit_warning">Are you sure? Validation process will be cancelled</string>
<string name="settings_general_enable_pull_to_refresh_title">Enable pull to refresh</string>
<string name="action_authorize">Authorize</string>
</resources>
@@ -3,6 +3,13 @@ package dev.meloda.fast.auth.login
import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dev.meloda.fast.auth.login.model.CaptchaArguments
import dev.meloda.fast.auth.login.model.LoginError
import dev.meloda.fast.auth.login.model.LoginScreenState
import dev.meloda.fast.auth.login.model.LoginUserBannedArguments
import dev.meloda.fast.auth.login.model.LoginValidationArguments
import dev.meloda.fast.auth.login.model.LoginValidationResult
import dev.meloda.fast.auth.login.validation.LoginValidator
import dev.meloda.fast.common.LongPollController
import dev.meloda.fast.common.UserConfig
import dev.meloda.fast.common.VkConstants
@@ -17,13 +24,6 @@ import dev.meloda.fast.data.processState
import dev.meloda.fast.datastore.AppSettings
import dev.meloda.fast.model.database.AccountEntity
import dev.meloda.fast.network.OAuthErrorDomain
import dev.meloda.fast.auth.login.model.CaptchaArguments
import dev.meloda.fast.auth.login.model.LoginError
import dev.meloda.fast.auth.login.model.LoginScreenState
import dev.meloda.fast.auth.login.model.LoginUserBannedArguments
import dev.meloda.fast.auth.login.model.LoginValidationArguments
import dev.meloda.fast.auth.login.model.LoginValidationResult
import dev.meloda.fast.auth.login.validation.LoginValidator
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
@@ -44,6 +44,7 @@ interface LoginViewModel {
val captchaArguments: StateFlow<CaptchaArguments?>
val userBannedArguments: StateFlow<LoginUserBannedArguments?>
val isNeedToOpenMain: StateFlow<Boolean>
val isNeedToShowFastSignInAlert: StateFlow<Boolean>
fun onPasswordVisibilityButtonClicked()
@@ -63,6 +64,9 @@ interface LoginViewModel {
fun onCaptchaCodeReceived(code: String)
fun onLogoLongClicked()
fun onFastLogInAlertDismissed()
fun onFastLogInAlertConfirmClicked(token: String)
}
class LoginViewModelImpl(
@@ -82,6 +86,7 @@ class LoginViewModelImpl(
override val captchaArguments = MutableStateFlow<CaptchaArguments?>(null)
override val userBannedArguments = MutableStateFlow<LoginUserBannedArguments?>(null)
override val isNeedToOpenMain = MutableStateFlow(false)
override val isNeedToShowFastSignInAlert = MutableStateFlow(false)
private val validationState: StateFlow<List<LoginValidationResult>> =
screenState.map(loginValidator::validate)
@@ -145,9 +150,17 @@ class LoginViewModelImpl(
}
override fun onLogoLongClicked() {
val currentAccount = AccountEntity(
userId = BuildConfig.debugUserId.toInt(),
accessToken = BuildConfig.debugAccessToken,
isNeedToShowFastSignInAlert.update { true }
}
override fun onFastLogInAlertDismissed() {
isNeedToShowFastSignInAlert.update { false }
}
override fun onFastLogInAlertConfirmClicked(token: String) {
var currentAccount = AccountEntity(
userId = -1,
accessToken = token,
fastToken = null,
trustedHash = null
).also { account ->
@@ -158,8 +171,6 @@ class LoginViewModelImpl(
UserConfig.trustedHash = account.trustedHash
}
startLongPoll()
usersUseCase.get(
userIds = null,
fields = VkConstants.USER_FIELDS,
@@ -167,19 +178,29 @@ class LoginViewModelImpl(
).listenValue { state ->
state.processState(
error = { error ->
UserConfig.currentUserId = -1
UserConfig.userId = -1
UserConfig.accessToken = ""
// TODO: 19/07/2024, Danil Nikolaev: show error?
},
success = { response ->
val actualUserId = response.first().id
currentAccount = currentAccount.copy(userId = actualUserId)
UserConfig.userId = actualUserId
UserConfig.currentUserId = actualUserId
startLongPoll()
viewModelScope.launch(Dispatchers.IO) {
accountsRepository.storeAccounts(listOf(currentAccount))
delay(350)
isNeedToOpenMain.update { true }
}
}
)
screenState.setValue { old -> old.copy(isLoading = state.isLoading()) }
}
}
@@ -17,12 +17,16 @@ import androidx.compose.foundation.layout.width
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
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
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.testTag
@@ -31,9 +35,12 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import dev.meloda.fast.ui.theme.LocalThemeConfig
import dev.meloda.fast.auth.login.BuildConfig
import dev.meloda.fast.auth.login.LoginViewModel
import dev.meloda.fast.auth.login.LoginViewModelImpl
import dev.meloda.fast.ui.components.ActionInvokeDismiss
import dev.meloda.fast.ui.components.MaterialDialog
import dev.meloda.fast.ui.theme.LocalThemeConfig
import org.koin.androidx.compose.koinViewModel
import dev.meloda.fast.ui.R as UiR
@@ -44,6 +51,7 @@ fun LogoRoute(
viewModel: LoginViewModel = koinViewModel<LoginViewModelImpl>()
) {
val isNeedToOpenMain by viewModel.isNeedToOpenMain.collectAsStateWithLifecycle()
val isNeedToShowSignInAlert by viewModel.isNeedToShowFastSignInAlert.collectAsStateWithLifecycle()
LaunchedEffect(isNeedToOpenMain) {
if (isNeedToOpenMain) {
@@ -56,6 +64,13 @@ fun LogoRoute(
onLogoLongClicked = viewModel::onLogoLongClicked,
onGoNextButtonClicked = onGoNextButtonClicked
)
if (isNeedToShowSignInAlert) {
SignInAlert(
onDismissRequest = viewModel::onFastLogInAlertDismissed,
onConfirmClick = viewModel::onFastLogInAlertConfirmClicked,
)
}
}
@OptIn(ExperimentalFoundationApi::class)
@@ -159,3 +174,34 @@ fun LogoScreen(
}
}
}
@Composable
fun SignInAlert(
onDismissRequest: () -> Unit,
onConfirmClick: (token: String) -> Unit
) {
var tokenText by rememberSaveable {
mutableStateOf(BuildConfig.debugAccessToken)
}
val maxWidthModifier = Modifier.fillMaxWidth()
MaterialDialog(
onDismissRequest = onDismissRequest,
title = "Fast authorization",
confirmText = stringResource(id = UiR.string.action_authorize),
confirmAction = { onConfirmClick(tokenText) },
cancelText = stringResource(id = UiR.string.cancel),
actionInvokeDismiss = ActionInvokeDismiss.Always
) {
Column(modifier = maxWidthModifier) {
OutlinedTextField(
modifier = maxWidthModifier.padding(horizontal = 16.dp),
value = tokenText,
onValueChange = { tokenText = it },
placeholder = { Text(text = "Access token") },
label = { Text(text = "Access token") }
)
}
}
}