From 2b018add7c853b4fec9e7d9c65259b7074c54e1c Mon Sep 17 00:00:00 2001 From: Danil Nikolaev Date: Fri, 19 Jul 2024 06:01:16 +0300 Subject: [PATCH] fast login with token --- core/ui/src/main/res/values/strings.xml | 1 + .../meloda/fast/auth/login/LoginViewModel.kt | 51 +++++++++++++------ .../auth/login/presentation/LogoScreen.kt | 48 ++++++++++++++++- 3 files changed, 84 insertions(+), 16 deletions(-) diff --git a/core/ui/src/main/res/values/strings.xml b/core/ui/src/main/res/values/strings.xml index b9db56a6..1762c9c4 100644 --- a/core/ui/src/main/res/values/strings.xml +++ b/core/ui/src/main/res/values/strings.xml @@ -263,4 +263,5 @@ Are you sure? Captcha process will be cancelled Are you sure? Validation process will be cancelled Enable pull to refresh + Authorize diff --git a/feature/auth/login/src/main/kotlin/dev/meloda/fast/auth/login/LoginViewModel.kt b/feature/auth/login/src/main/kotlin/dev/meloda/fast/auth/login/LoginViewModel.kt index d79892f3..d932a99d 100644 --- a/feature/auth/login/src/main/kotlin/dev/meloda/fast/auth/login/LoginViewModel.kt +++ b/feature/auth/login/src/main/kotlin/dev/meloda/fast/auth/login/LoginViewModel.kt @@ -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 val userBannedArguments: StateFlow val isNeedToOpenMain: StateFlow + val isNeedToShowFastSignInAlert: StateFlow 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(null) override val userBannedArguments = MutableStateFlow(null) override val isNeedToOpenMain = MutableStateFlow(false) + override val isNeedToShowFastSignInAlert = MutableStateFlow(false) private val validationState: StateFlow> = 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()) } } } diff --git a/feature/auth/login/src/main/kotlin/dev/meloda/fast/auth/login/presentation/LogoScreen.kt b/feature/auth/login/src/main/kotlin/dev/meloda/fast/auth/login/presentation/LogoScreen.kt index 6901f335..7cb8122a 100644 --- a/feature/auth/login/src/main/kotlin/dev/meloda/fast/auth/login/presentation/LogoScreen.kt +++ b/feature/auth/login/src/main/kotlin/dev/meloda/fast/auth/login/presentation/LogoScreen.kt @@ -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() ) { 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") } + ) + } + } +}