diff --git a/app/src/main/java/ru/myitschool/work/core/OurConstants.kt b/app/src/main/java/ru/myitschool/work/core/OurConstants.kt new file mode 100644 index 0000000..ea99bec --- /dev/null +++ b/app/src/main/java/ru/myitschool/work/core/OurConstants.kt @@ -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" +} \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/data/repo/AuthRepository.kt b/app/src/main/java/ru/myitschool/work/data/repo/AuthRepository.kt index 3ef28f1..febfcbb 100644 --- a/app/src/main/java/ru/myitschool/work/data/repo/AuthRepository.kt +++ b/app/src/main/java/ru/myitschool/work/data/repo/AuthRepository.kt @@ -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 { return NetworkDataSource.checkAuth(text).onSuccess { success -> if (success) { codeCache = text + createAuthCode(context = appContext, code = text) } } } diff --git a/app/src/main/java/ru/myitschool/work/data/source/DataStoreDataSource.kt b/app/src/main/java/ru/myitschool/work/data/source/DataStoreDataSource.kt new file mode 100644 index 0000000..16bd7ee --- /dev/null +++ b/app/src/main/java/ru/myitschool/work/data/source/DataStoreDataSource.kt @@ -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 by preferencesDataStore(name = "auth") +val AUTH_KEY = stringPreferencesKey(DS_AUTH_KEY) + +object DataStoreDataSource { + fun authFlow(context : Context): Flow = 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 + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/data/source/NetworkDataSource.kt b/app/src/main/java/ru/myitschool/work/data/source/NetworkDataSource.kt index fbdfef5..f12b719 100644 --- a/app/src/main/java/ru/myitschool/work/data/source/NetworkDataSource.kt +++ b/app/src/main/java/ru/myitschool/work/data/source/NetworkDataSource.kt @@ -30,7 +30,7 @@ object NetworkDataSource { suspend fun checkAuth(code: String): Result = 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()) diff --git a/app/src/main/java/ru/myitschool/work/ui/screen/auth/AuthAction.kt b/app/src/main/java/ru/myitschool/work/ui/screen/auth/AuthAction.kt new file mode 100644 index 0000000..939a280 --- /dev/null +++ b/app/src/main/java/ru/myitschool/work/ui/screen/auth/AuthAction.kt @@ -0,0 +1,6 @@ +package ru.myitschool.work.ui.screen.auth + +sealed interface AuthAction { + data class ShowError(val message: String) : AuthAction + +} \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/ui/screen/auth/AuthScreen.kt b/app/src/main/java/ru/myitschool/work/ui/screen/auth/AuthScreen.kt index a8aac84..845e8ab 100644 --- a/app/src/main/java/ru/myitschool/work/ui/screen/auth/AuthScreen.kt +++ b/app/src/main/java/ru/myitschool/work/ui/screen/auth/AuthScreen.kt @@ -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 = { - viewModel.onIntent(AuthIntent.Send(inputText)) + 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)) } -} \ No newline at end of file +} diff --git a/app/src/main/java/ru/myitschool/work/ui/screen/auth/AuthViewModel.kt b/app/src/main/java/ru/myitschool/work/ui/screen/auth/AuthViewModel.kt index 3153640..4f5ea07 100644 --- a/app/src/main/java/ru/myitschool/work/ui/screen/auth/AuthViewModel.kt +++ b/app/src/main/java/ru/myitschool/work/ui/screen/auth/AuthViewModel.kt @@ -18,21 +18,23 @@ class AuthViewModel : ViewModel() { private val _uiState = MutableStateFlow(AuthState.Data) val uiState: StateFlow = _uiState.asStateFlow() - private val _actionFlow: MutableSharedFlow = MutableSharedFlow() - val actionFlow: SharedFlow = _actionFlow + private val _actionFlow: MutableSharedFlow = MutableSharedFlow() + val actionFlow: SharedFlow = _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())) + } } ) }