Auth first steps

This commit is contained in:
2025-11-24 18:33:16 +03:00
parent be88863cb2
commit bcbca3a10f
7 changed files with 68 additions and 12 deletions

View File

@@ -0,0 +1,9 @@
package ru.myitschool.work.core
import androidx.datastore.preferences.core.intPreferencesKey
// Не добавляйте ничего, что уже есть в Constants!
object OurConstants {
const val SHABLON = "^[a-zA-Z0-9]*\$"
const val DS_AUTH_KEY = "authkey"
}

View File

@@ -1,15 +1,17 @@
package ru.myitschool.work.data.repo
import android.content.Context
import ru.myitschool.work.data.source.DataStoreDataSource.createAuthCode
import ru.myitschool.work.data.source.NetworkDataSource
object AuthRepository {
private var codeCache: String? = null
// TODO: разобраться с контекстом
suspend fun checkAndSave(text: String): Result<Boolean> {
return NetworkDataSource.checkAuth(text).onSuccess { success ->
if (success) {
codeCache = text
createAuthCode(context = appContext, code = text)
}
}
}

View File

@@ -0,0 +1,27 @@
package ru.myitschool.work.data.source
import android.content.Context
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import ru.myitschool.work.core.OurConstants.DS_AUTH_KEY
val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "auth")
val AUTH_KEY = stringPreferencesKey(DS_AUTH_KEY)
object DataStoreDataSource {
fun authFlow(context : Context): Flow<String> = context.dataStore.data.map { preferences ->
(preferences[AUTH_KEY] ?: 0).toString()
}
// TODO: разобраться с контекстом
suspend fun createAuthCode (context : Context, code : String) {
context.dataStore.updateData {
it.toMutablePreferences().also { preferences ->
preferences[AUTH_KEY] = code
}
}
}
}

View File

@@ -30,7 +30,7 @@ object NetworkDataSource {
suspend fun checkAuth(code: String): Result<Boolean> = withContext(Dispatchers.IO) {
return@withContext runCatching {
val response = client.get(getUrl(code, Constants.AUTH_URL))
val response = client.get(getUrl(code, Constants.AUTH_URL)) // TODO: Отпрвка запроса на сервер
when (response.status) {
HttpStatusCode.OK -> true
else -> error(response.bodyAsText())

View File

@@ -0,0 +1,6 @@
package ru.myitschool.work.ui.screen.auth
sealed interface AuthAction {
data class ShowError(val message: String) : AuthAction
}

View File

@@ -29,6 +29,7 @@ import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController
import ru.myitschool.work.R
import ru.myitschool.work.core.OurConstants.SHABLON
import ru.myitschool.work.core.TestIds
import ru.myitschool.work.ui.nav.MainScreenDestination
@@ -74,6 +75,7 @@ private fun Content(
state: AuthState.Data
) {
var inputText by remember { mutableStateOf("") }
var errorText : String? by remember { mutableStateOf(null) }
Spacer(modifier = Modifier.size(16.dp))
TextField(
modifier = Modifier.testTag(TestIds.Auth.CODE_INPUT).fillMaxWidth(),
@@ -88,12 +90,20 @@ private fun Content(
Button(
modifier = Modifier.testTag(TestIds.Auth.SIGN_BUTTON).fillMaxWidth(),
onClick = {
if (!inputText.isEmpty() || inputText.length == 4 || inputText.matches(Regex(SHABLON))){
viewModel.onIntent(AuthIntent.Send(inputText))
}
},
enabled = true
) { Text(stringResource(R.string.auth_sign_in))
) { Text(stringResource(R.string.auth_sign_in)) }
ShowError(errorText) // TODO: раскидать в коде когда показывается ошибка и когда нет
}
@Composable
fun ShowError(text : String?){
if (text != null){
Text(text, modifier = Modifier.testTag(TestIds.Auth.ERROR))
}
}

View File

@@ -18,21 +18,23 @@ class AuthViewModel : ViewModel() {
private val _uiState = MutableStateFlow<AuthState>(AuthState.Data)
val uiState: StateFlow<AuthState> = _uiState.asStateFlow()
private val _actionFlow: MutableSharedFlow<Unit> = MutableSharedFlow()
val actionFlow: SharedFlow<Unit> = _actionFlow
private val _actionFlow: MutableSharedFlow<AuthAction> = MutableSharedFlow()
val actionFlow: SharedFlow<AuthAction> = _actionFlow
fun onIntent(intent: AuthIntent) {
when (intent) {
is AuthIntent.Send -> {
viewModelScope.launch(Dispatchers.Default) {
viewModelScope.launch(Dispatchers.IO) {
_uiState.update { AuthState.Loading }
checkAndSaveAuthCodeUseCase.invoke("9999").fold(
checkAndSaveAuthCodeUseCase.invoke(intent.text).fold(
onSuccess = {
_actionFlow.emit(Unit)
// TODO: Поведение при успехе
},
onFailure = { error ->
error.printStackTrace()
_actionFlow.emit(Unit)
if (error.message != null) {
_actionFlow.emit(AuthAction.ShowError(error.message.toString()))
}
}
)
}