diff --git a/app/src/main/java/ru/myitschool/work/domain/auth/CheckAndSaveAuthCodeUseCase.kt b/app/src/main/java/ru/myitschool/work/domain/auth/CheckAndSaveAuthCodeUseCase.kt index 012fb6f..e308ad2 100644 --- a/app/src/main/java/ru/myitschool/work/domain/auth/CheckAndSaveAuthCodeUseCase.kt +++ b/app/src/main/java/ru/myitschool/work/domain/auth/CheckAndSaveAuthCodeUseCase.kt @@ -1,15 +1,23 @@ package ru.myitschool.work.domain.auth +import androidx.datastore.dataStore import ru.myitschool.work.data.repo.AuthRepository +import ru.myitschool.work.util.DataStoreManager class CheckAndSaveAuthCodeUseCase( - private val repository: AuthRepository + private val repository: AuthRepository, ) { suspend operator fun invoke( - text: String - ): Result { - return repository.checkAndSave(text).mapCatching { success -> - if (!success) error("Code is incorrect") + code: String + ): Result = try { + val response = repository.checkAndSave(code) + if (response.isSuccess) { + DataStoreManager.saveAuthCode(code) + Result.success(Unit) + } else { + Result.failure(Exception("Неверный код")) } + } catch (e: Exception){ + Result.failure(e) } } \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/ui/screen/NavigationGraph.kt b/app/src/main/java/ru/myitschool/work/ui/NavigationGraph.kt similarity index 60% rename from app/src/main/java/ru/myitschool/work/ui/screen/NavigationGraph.kt rename to app/src/main/java/ru/myitschool/work/ui/NavigationGraph.kt index 01b0f32..fa9c2e8 100644 --- a/app/src/main/java/ru/myitschool/work/ui/screen/NavigationGraph.kt +++ b/app/src/main/java/ru/myitschool/work/ui/NavigationGraph.kt @@ -1,44 +1,57 @@ -package ru.myitschool.work.ui.screen +package ru.myitschool.work.ui import androidx.compose.animation.EnterTransition import androidx.compose.animation.ExitTransition import androidx.compose.foundation.layout.Box 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.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController -import ru.myitschool.work.ui.nav.AuthScreenDestination -import ru.myitschool.work.ui.nav.BookScreenDestination -import ru.myitschool.work.ui.nav.MainScreenDestination -import ru.myitschool.work.ui.screen.auth.AuthScreen +import ru.myitschool.work.ui.auth.AuthScreen +import ru.myitschool.work.util.DataStoreManager @Composable fun AppNavHost( modifier: Modifier = Modifier, navController: NavHostController = rememberNavController() ) { + var startDestination by remember { mutableStateOf(Screen.Auth) } + + LaunchedEffect(Unit) { + val isAuth = DataStoreManager.isAuthenticated() + startDestination = if (isAuth) { + Screen.Main + } else { + Screen.Auth + } + } NavHost( modifier = modifier, enterTransition = { EnterTransition.None }, exitTransition = { ExitTransition.None }, navController = navController, - startDestination = AuthScreenDestination, + startDestination = startDestination, ) { - composable { + composable { AuthScreen(navController = navController) } - composable { + composable { Box( contentAlignment = Alignment.Center ) { Text(text = "Hello") } } - composable { + composable { Box( contentAlignment = Alignment.Center ) { diff --git a/app/src/main/java/ru/myitschool/work/ui/Screen.kt b/app/src/main/java/ru/myitschool/work/ui/Screen.kt new file mode 100644 index 0000000..02fd1ce --- /dev/null +++ b/app/src/main/java/ru/myitschool/work/ui/Screen.kt @@ -0,0 +1,12 @@ +package ru.myitschool.work.ui + +import kotlinx.serialization.Serializable + +sealed interface Screen{ + @Serializable + data object Auth: Screen + @Serializable + data object Book: Screen + @Serializable + data object Main: Screen +} \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/ui/auth/AuthIntent.kt b/app/src/main/java/ru/myitschool/work/ui/auth/AuthIntent.kt new file mode 100644 index 0000000..f05a1e9 --- /dev/null +++ b/app/src/main/java/ru/myitschool/work/ui/auth/AuthIntent.kt @@ -0,0 +1,6 @@ +package ru.myitschool.work.ui.auth + +sealed interface AuthIntent { + data object Send: AuthIntent + data class TextInput(val text: String): AuthIntent +} \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/ui/auth/AuthScreen.kt b/app/src/main/java/ru/myitschool/work/ui/auth/AuthScreen.kt new file mode 100644 index 0000000..3089de5 --- /dev/null +++ b/app/src/main/java/ru/myitschool/work/ui/auth/AuthScreen.kt @@ -0,0 +1,98 @@ +package ru.myitschool.work.ui.auth + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material3.Button +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.material3.TextField +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.testTag +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +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.TestIds +import ru.myitschool.work.ui.Screen + +@Composable +fun AuthScreen( + viewModel: AuthViewModel = viewModel(), + navController: NavController +) { + val state by viewModel.uiState.collectAsState() + + LaunchedEffect(state.isAuthenticated) { + if (state.isAuthenticated) { + navController.navigate(Screen.Main) { + popUpTo(navController.graph.startDestinationId) { inclusive = true } + launchSingleTop = true + } + } + } + + Column( + modifier = Modifier + .fillMaxSize() + .padding(24.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center, + ) { + if (state.isLoading){ + CircularProgressIndicator( + modifier = Modifier.size(64.dp) + ) + } else { + Text( + text = stringResource(R.string.auth_title), + style = MaterialTheme.typography.headlineSmall, + textAlign = TextAlign.Center + ) + + Spacer(Modifier.height(15.dp)) + + TextField( + modifier = Modifier.testTag(TestIds.Auth.CODE_INPUT).fillMaxWidth(), + value = state.code, + onValueChange = { + viewModel.onIntent(AuthIntent.TextInput(it)) + }, + label = { Text(stringResource(R.string.auth_label)) } + ) + + Text( + text = state.error?: "", + modifier = Modifier.testTag(TestIds.Auth.ERROR), + color = MaterialTheme.colorScheme.error) + + + + Button( + modifier = Modifier.testTag(TestIds.Auth.SIGN_BUTTON).fillMaxWidth(), + onClick = { + viewModel.onIntent(AuthIntent.Send) + }, + enabled = state.isButtonEnabled + ) { + Text(stringResource(R.string.auth_sign_in)) + } + } + + } + +} \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/ui/auth/AuthState.kt b/app/src/main/java/ru/myitschool/work/ui/auth/AuthState.kt new file mode 100644 index 0000000..d7d8052 --- /dev/null +++ b/app/src/main/java/ru/myitschool/work/ui/auth/AuthState.kt @@ -0,0 +1,9 @@ +package ru.myitschool.work.ui.auth + +data class AuthState( + val code: String = "", + val error: String? = null, + val isLoading: Boolean = false, + val isAuthenticated: Boolean = false, + val isButtonEnabled: Boolean = false +) \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/ui/auth/AuthViewModel.kt b/app/src/main/java/ru/myitschool/work/ui/auth/AuthViewModel.kt new file mode 100644 index 0000000..79628f6 --- /dev/null +++ b/app/src/main/java/ru/myitschool/work/ui/auth/AuthViewModel.kt @@ -0,0 +1,58 @@ +package ru.myitschool.work.ui.auth + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch +import ru.myitschool.work.data.repo.AuthRepository +import ru.myitschool.work.domain.auth.CheckAndSaveAuthCodeUseCase + +class AuthViewModel : ViewModel() { + private val checkAndSaveAuthCodeUseCase by lazy { CheckAndSaveAuthCodeUseCase(AuthRepository) } + private val _uiState = MutableStateFlow(AuthState()) + val uiState: StateFlow = _uiState.asStateFlow() + + fun onIntent(intent: AuthIntent) { + when (intent) { + is AuthIntent.Send -> { + viewModelScope.launch { + _uiState.update { + it.copy(isLoading = true) + } + + checkAndSaveAuthCodeUseCase(_uiState.value.code).fold( + onSuccess = { + _uiState.update { + it.copy( + isLoading = false, + isAuthenticated = true + ) + } + + }, + onFailure = { error -> + _uiState.update { + it.copy( + isLoading = false, + error = error.message ?: "Ошибка", + isAuthenticated = false + ) + } + } + ) + } + } + is AuthIntent.TextInput -> _uiState.update { + it.copy( + code = intent.text, + isButtonEnabled = intent.text.length == 4 && + uiState.value.code.matches(Regex("^[a-zA-Z0-9]+$")), + error = null + ) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/ui/booking/BookingScreen.kt b/app/src/main/java/ru/myitschool/work/ui/booking/BookingScreen.kt new file mode 100644 index 0000000..1d50b6a --- /dev/null +++ b/app/src/main/java/ru/myitschool/work/ui/booking/BookingScreen.kt @@ -0,0 +1,19 @@ +package ru.myitschool.work.ui.booking + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Scaffold +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.lifecycle.viewmodel.compose.viewModel +import androidx.navigation.NavController + +@Composable +fun BookingScreen( + viewModel: BookingViewModel = viewModel(), + navController: NavController +) { + Scaffold() { padding -> + Box(Modifier.padding(padding)) + } +} \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/ui/booking/BookingViewModel.kt b/app/src/main/java/ru/myitschool/work/ui/booking/BookingViewModel.kt new file mode 100644 index 0000000..368e9df --- /dev/null +++ b/app/src/main/java/ru/myitschool/work/ui/booking/BookingViewModel.kt @@ -0,0 +1,7 @@ +package ru.myitschool.work.ui.booking + +import androidx.lifecycle.ViewModel + +class BookingViewModel: ViewModel() { + +} \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/ui/main/MainScreen.kt b/app/src/main/java/ru/myitschool/work/ui/main/MainScreen.kt new file mode 100644 index 0000000..272b6cf --- /dev/null +++ b/app/src/main/java/ru/myitschool/work/ui/main/MainScreen.kt @@ -0,0 +1,19 @@ +package ru.myitschool.work.ui.main + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Scaffold +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.lifecycle.viewmodel.compose.viewModel +import androidx.navigation.NavController + +@Composable +fun MainScreen( + viewModel: MainViewModel = viewModel(), + navController: NavController +) { + Scaffold() { padding -> + Box(Modifier.padding(padding)) + } +} \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/ui/main/MainViewModel.kt b/app/src/main/java/ru/myitschool/work/ui/main/MainViewModel.kt new file mode 100644 index 0000000..030e031 --- /dev/null +++ b/app/src/main/java/ru/myitschool/work/ui/main/MainViewModel.kt @@ -0,0 +1,7 @@ +package ru.myitschool.work.ui.main + +import androidx.lifecycle.ViewModel + +class MainViewModel: ViewModel() { + +} diff --git a/app/src/main/java/ru/myitschool/work/ui/nav/AppDestination.kt b/app/src/main/java/ru/myitschool/work/ui/nav/AppDestination.kt deleted file mode 100644 index 557b893..0000000 --- a/app/src/main/java/ru/myitschool/work/ui/nav/AppDestination.kt +++ /dev/null @@ -1,3 +0,0 @@ -package ru.myitschool.work.ui.nav - -sealed interface AppDestination \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/ui/nav/AuthScreenDestination.kt b/app/src/main/java/ru/myitschool/work/ui/nav/AuthScreenDestination.kt deleted file mode 100644 index 52660b1..0000000 --- a/app/src/main/java/ru/myitschool/work/ui/nav/AuthScreenDestination.kt +++ /dev/null @@ -1,6 +0,0 @@ -package ru.myitschool.work.ui.nav - -import kotlinx.serialization.Serializable - -@Serializable -data object AuthScreenDestination: AppDestination \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/ui/nav/BookScreenDestination.kt b/app/src/main/java/ru/myitschool/work/ui/nav/BookScreenDestination.kt deleted file mode 100644 index 9a33073..0000000 --- a/app/src/main/java/ru/myitschool/work/ui/nav/BookScreenDestination.kt +++ /dev/null @@ -1,6 +0,0 @@ -package ru.myitschool.work.ui.nav - -import kotlinx.serialization.Serializable - -@Serializable -data object BookScreenDestination: AppDestination \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/ui/nav/MainScreenDestination.kt b/app/src/main/java/ru/myitschool/work/ui/nav/MainScreenDestination.kt deleted file mode 100644 index deca45f..0000000 --- a/app/src/main/java/ru/myitschool/work/ui/nav/MainScreenDestination.kt +++ /dev/null @@ -1,6 +0,0 @@ -package ru.myitschool.work.ui.nav - -import kotlinx.serialization.Serializable - -@Serializable -data object MainScreenDestination: AppDestination \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/ui/root/RootActivity.kt b/app/src/main/java/ru/myitschool/work/ui/root/RootActivity.kt index 54b156d..9e760fc 100644 --- a/app/src/main/java/ru/myitschool/work/ui/root/RootActivity.kt +++ b/app/src/main/java/ru/myitschool/work/ui/root/RootActivity.kt @@ -8,7 +8,7 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.material3.Scaffold import androidx.compose.ui.Modifier -import ru.myitschool.work.ui.screen.AppNavHost +import ru.myitschool.work.ui.AppNavHost import ru.myitschool.work.ui.theme.WorkTheme class RootActivity : ComponentActivity() { @@ -17,9 +17,9 @@ class RootActivity : ComponentActivity() { enableEdgeToEdge() setContent { WorkTheme { - Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -> + Scaffold(modifier = Modifier.Companion.fillMaxSize()) { innerPadding -> AppNavHost( - modifier = Modifier + modifier = Modifier.Companion .fillMaxSize() .padding(innerPadding) ) diff --git a/app/src/main/java/ru/myitschool/work/ui/screen/auth/AuthIntent.kt b/app/src/main/java/ru/myitschool/work/ui/screen/auth/AuthIntent.kt deleted file mode 100644 index 74f200a..0000000 --- a/app/src/main/java/ru/myitschool/work/ui/screen/auth/AuthIntent.kt +++ /dev/null @@ -1,6 +0,0 @@ -package ru.myitschool.work.ui.screen.auth - -sealed interface AuthIntent { - data class Send(val text: String): AuthIntent - data class TextInput(val text: String): AuthIntent -} \ 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 deleted file mode 100644 index f99978e..0000000 --- a/app/src/main/java/ru/myitschool/work/ui/screen/auth/AuthScreen.kt +++ /dev/null @@ -1,97 +0,0 @@ -package ru.myitschool.work.ui.screen.auth - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.material3.Button -import androidx.compose.material3.CircularProgressIndicator -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.material3.TextField -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.testTag -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextAlign -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.TestIds -import ru.myitschool.work.ui.nav.MainScreenDestination - -@Composable -fun AuthScreen( - viewModel: AuthViewModel = viewModel(), - navController: NavController -) { - val state by viewModel.uiState.collectAsState() - - LaunchedEffect(Unit) { - viewModel.actionFlow.collect { - navController.navigate(MainScreenDestination) - } - } - - Column( - modifier = Modifier - .fillMaxSize() - .padding(all = 24.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center - ) { - Text( - text = stringResource(R.string.auth_title), - style = MaterialTheme.typography.headlineSmall, - textAlign = TextAlign.Center - ) - when (val currentState = state) { - is AuthState.Data -> Content(viewModel, currentState) - is AuthState.Loading -> { - CircularProgressIndicator( - modifier = Modifier.size(64.dp) - ) - } - } - } -} - -@Composable -private fun Content( - viewModel: AuthViewModel, - state: AuthState.Data -) { - var inputText by remember { mutableStateOf("") } - Spacer(modifier = Modifier.size(16.dp)) - TextField( - modifier = Modifier.testTag(TestIds.Auth.CODE_INPUT).fillMaxWidth(), - value = inputText, - onValueChange = { - inputText = it - viewModel.onIntent(AuthIntent.TextInput(it)) - }, - label = { Text(stringResource(R.string.auth_label)) } - ) - Spacer(modifier = Modifier.size(16.dp)) - Button( - modifier = Modifier.testTag(TestIds.Auth.SIGN_BUTTON).fillMaxWidth(), - onClick = { - viewModel.onIntent(AuthIntent.Send(inputText)) - }, - enabled = true - ) { - Text(stringResource(R.string.auth_sign_in)) - } -} \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/ui/screen/auth/AuthState.kt b/app/src/main/java/ru/myitschool/work/ui/screen/auth/AuthState.kt deleted file mode 100644 index a06ba76..0000000 --- a/app/src/main/java/ru/myitschool/work/ui/screen/auth/AuthState.kt +++ /dev/null @@ -1,6 +0,0 @@ -package ru.myitschool.work.ui.screen.auth - -sealed interface AuthState { - object Loading: AuthState - object Data: AuthState -} \ 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 deleted file mode 100644 index 3153640..0000000 --- a/app/src/main/java/ru/myitschool/work/ui/screen/auth/AuthViewModel.kt +++ /dev/null @@ -1,43 +0,0 @@ -package ru.myitschool.work.ui.screen.auth - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.SharedFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.flow.update -import kotlinx.coroutines.launch -import ru.myitschool.work.data.repo.AuthRepository -import ru.myitschool.work.domain.auth.CheckAndSaveAuthCodeUseCase - -class AuthViewModel : ViewModel() { - private val checkAndSaveAuthCodeUseCase by lazy { CheckAndSaveAuthCodeUseCase(AuthRepository) } - private val _uiState = MutableStateFlow(AuthState.Data) - val uiState: StateFlow = _uiState.asStateFlow() - - private val _actionFlow: MutableSharedFlow = MutableSharedFlow() - val actionFlow: SharedFlow = _actionFlow - - fun onIntent(intent: AuthIntent) { - when (intent) { - is AuthIntent.Send -> { - viewModelScope.launch(Dispatchers.Default) { - _uiState.update { AuthState.Loading } - checkAndSaveAuthCodeUseCase.invoke("9999").fold( - onSuccess = { - _actionFlow.emit(Unit) - }, - onFailure = { error -> - error.printStackTrace() - _actionFlow.emit(Unit) - } - ) - } - } - is AuthIntent.TextInput -> Unit - } - } -} \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/util/DataStoreManager.kt b/app/src/main/java/ru/myitschool/work/util/DataStoreManager.kt new file mode 100644 index 0000000..9415f11 --- /dev/null +++ b/app/src/main/java/ru/myitschool/work/util/DataStoreManager.kt @@ -0,0 +1,38 @@ +package ru.myitschool.work.util + +import android.content.Context +import androidx.datastore.core.DataStore +import androidx.datastore.preferences.core.Preferences +import androidx.datastore.preferences.core.edit +import androidx.datastore.preferences.core.stringPreferencesKey +import androidx.datastore.preferences.preferencesDataStore +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.map +import ru.myitschool.work.App + +private val Context.dataStore: DataStore by preferencesDataStore(name = "auth_prefs") +object DataStoreManager { + private val AUTH_CODE_KEY = stringPreferencesKey("auth_code") + + suspend fun saveAuthCode(code: String){ + App.context.dataStore.edit { prefs -> + prefs[AUTH_CODE_KEY] = code + } + } + suspend fun getAuthCode(): String? { + return App.context.dataStore.data + .map { it[AUTH_CODE_KEY] } + .first() + } + + + suspend fun clearAuthCode() { + App.context.dataStore.edit { prefs -> + prefs.remove(AUTH_CODE_KEY) + } + } + suspend fun isAuthenticated(): Boolean { + return getAuthCode() != null + } +} \ No newline at end of file