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") }
+ )
+ }
+ }
+}