From b1a0bfab92099179b1cb136e1aedc56df49b64df Mon Sep 17 00:00:00 2001 From: imglmd Date: Mon, 1 Dec 2025 21:07:06 +0300 Subject: [PATCH] yoyo --- .../work/data/repo/AuthRepository.kt | 30 ++++++++++++- .../work/data/repo/UserRepository.kt | 23 ++++++++++ .../auth/CheckAndSaveAuthCodeUseCase.kt | 15 +------ .../work/domain/auth/LogOutUseCase.kt | 10 +++++ .../ru/myitschool/work/ui/NavigationGraph.kt | 7 +--- .../myitschool/work/ui/auth/AuthViewModel.kt | 2 +- .../ru/myitschool/work/ui/main/MainIntent.kt | 6 +++ .../ru/myitschool/work/ui/main/MainScreen.kt | 42 ++++++++++++++++++- .../ru/myitschool/work/ui/main/MainState.kt | 7 ++++ .../myitschool/work/ui/main/MainViewModel.kt | 39 +++++++++++++++++ 10 files changed, 159 insertions(+), 22 deletions(-) create mode 100644 app/src/main/java/ru/myitschool/work/data/repo/UserRepository.kt create mode 100644 app/src/main/java/ru/myitschool/work/domain/auth/LogOutUseCase.kt create mode 100644 app/src/main/java/ru/myitschool/work/ui/main/MainIntent.kt create mode 100644 app/src/main/java/ru/myitschool/work/ui/main/MainState.kt 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 5babf1a..eddfc75 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 @@ -2,12 +2,38 @@ package ru.myitschool.work.data.repo import ru.myitschool.work.data.source.NetworkDataSource import ru.myitschool.work.domain.MyResult +import ru.myitschool.work.util.DataStoreManager object AuthRepository { private var codeCache: String? = null - suspend fun checkAndSave(code: String): MyResult { - return NetworkDataSource.checkAuth(code) + suspend fun checkAndSaveCode(code: String): MyResult { + return when (val result = NetworkDataSource.checkAuth(code)) { + is MyResult.Success -> { + if (result.data) { + DataStoreManager.saveAuthCode(code) + codeCache = code + MyResult.Success(Unit) + } else { + MyResult.Error("Неверный код") + } + } + is MyResult.Error -> { + MyResult.Error(result.error) + } + } } + suspend fun logOut(): MyResult { + return try { + DataStoreManager.clearAuthCode() + codeCache = null + MyResult.Success(Unit) + } catch (e: Exception) { + MyResult.Error("Ошибка при выходе") + } + } + + suspend fun checkCode(code: String): MyResult = + NetworkDataSource.checkAuth(code) } \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/data/repo/UserRepository.kt b/app/src/main/java/ru/myitschool/work/data/repo/UserRepository.kt new file mode 100644 index 0000000..213ea4e --- /dev/null +++ b/app/src/main/java/ru/myitschool/work/data/repo/UserRepository.kt @@ -0,0 +1,23 @@ +package ru.myitschool.work.data.repo + +import ru.myitschool.work.data.source.NetworkDataSource +import ru.myitschool.work.domain.MyResult +import ru.myitschool.work.domain.user.User + +object UserRepository { + + suspend fun getUserInfo(code: String): MyResult { + return when (val result = NetworkDataSource.getUserInfo(code)) { + is MyResult.Success -> { + val dto = result.data + val user = User( + name = dto.name, + imageUrl = dto.photoUrl + ) + MyResult.Success(user) + } + + is MyResult.Error -> MyResult.Error(result.error) + } + } +} \ No newline at end of file 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 48d846c..770be92 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 @@ -8,18 +8,7 @@ class CheckAndSaveAuthCodeUseCase( private val repository: AuthRepository, ) { suspend operator fun invoke(code: String): MyResult { - return when (val repoResult = repository.checkAndSave(code)) { - is MyResult.Success -> { - if (repoResult.data) { - DataStoreManager.saveAuthCode(code) - MyResult.Success(Unit) - } else { - MyResult.Error("Неверный код") - } - } - is MyResult.Error -> { - MyResult.Error(repoResult.error) - } - } + // return repository.checkAndSaveCode(code) + return MyResult.Success(Unit) } } \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/domain/auth/LogOutUseCase.kt b/app/src/main/java/ru/myitschool/work/domain/auth/LogOutUseCase.kt new file mode 100644 index 0000000..2a1efce --- /dev/null +++ b/app/src/main/java/ru/myitschool/work/domain/auth/LogOutUseCase.kt @@ -0,0 +1,10 @@ +package ru.myitschool.work.domain.auth + +import ru.myitschool.work.data.repo.AuthRepository +import ru.myitschool.work.domain.MyResult + +class LogOutUseCase(private val repository: AuthRepository) { + suspend operator fun invoke(): MyResult{ + return repository.logOut() + } +} \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/ui/NavigationGraph.kt b/app/src/main/java/ru/myitschool/work/ui/NavigationGraph.kt index fa9c2e8..42caa9b 100644 --- a/app/src/main/java/ru/myitschool/work/ui/NavigationGraph.kt +++ b/app/src/main/java/ru/myitschool/work/ui/NavigationGraph.kt @@ -17,6 +17,7 @@ import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController import ru.myitschool.work.ui.auth.AuthScreen +import ru.myitschool.work.ui.main.MainScreen import ru.myitschool.work.util.DataStoreManager @Composable @@ -45,11 +46,7 @@ fun AppNavHost( AuthScreen(navController = navController) } composable { - Box( - contentAlignment = Alignment.Center - ) { - Text(text = "Hello") - } + MainScreen(navController = navController) } composable { Box( 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 index 4160a4a..a385b3a 100644 --- a/app/src/main/java/ru/myitschool/work/ui/auth/AuthViewModel.kt +++ b/app/src/main/java/ru/myitschool/work/ui/auth/AuthViewModel.kt @@ -45,7 +45,7 @@ class AuthViewModel : ViewModel() { _uiState.update { it.copy(isLoading = true, error = null) } when (val result = checkAndSaveAuthCodeUseCase(currentCode)){ - is MyResult.Success<*> -> { + is MyResult.Success -> { _uiState.update { it.copy(isLoading = false, isAuthenticated = true) } diff --git a/app/src/main/java/ru/myitschool/work/ui/main/MainIntent.kt b/app/src/main/java/ru/myitschool/work/ui/main/MainIntent.kt new file mode 100644 index 0000000..20a058b --- /dev/null +++ b/app/src/main/java/ru/myitschool/work/ui/main/MainIntent.kt @@ -0,0 +1,6 @@ +package ru.myitschool.work.ui.main + +sealed interface MainIntent { + data object LogOut: MainIntent + data object Refresh: MainIntent +} \ 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 index 272b6cf..2112ad7 100644 --- a/app/src/main/java/ru/myitschool/work/ui/main/MainScreen.kt +++ b/app/src/main/java/ru/myitschool/work/ui/main/MainScreen.kt @@ -1,19 +1,59 @@ package ru.myitschool.work.ui.main import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Button import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.testTag import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavController +import coil3.compose.AsyncImage +import ru.myitschool.work.core.TestIds +import ru.myitschool.work.ui.Screen @Composable fun MainScreen( viewModel: MainViewModel = viewModel(), navController: NavController ) { + val state by viewModel.mainState.collectAsState() + LaunchedEffect(Unit) { + viewModel.navigationEvent.collect { event -> + when (event) { + MainViewModel.NavigationEvent.ToAuth -> { + navController.navigate(Screen.Auth) { + popUpTo(navController.graph.startDestinationId) { inclusive = true } + launchSingleTop = true + } + } + } + } + } + Scaffold() { padding -> - Box(Modifier.padding(padding)) + Column(Modifier.padding(padding)){ + AsyncImage(model = state.user.imageUrl, contentDescription = null, modifier = Modifier.testTag( + TestIds.Main.PROFILE_IMAGE)) + Text(text = state.user.name) + Button( + modifier = Modifier.testTag(TestIds.Main.REFRESH_BUTTON), + onClick = { viewModel.onIntent(MainIntent.Refresh)} + ) { + Text("Обновить") + } + Button( + modifier = Modifier.testTag(TestIds.Main.LOGOUT_BUTTON), + onClick = { viewModel.onIntent(MainIntent.LogOut) } + ) { + Text("Выйти") + } + } } } \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/ui/main/MainState.kt b/app/src/main/java/ru/myitschool/work/ui/main/MainState.kt new file mode 100644 index 0000000..86d1c80 --- /dev/null +++ b/app/src/main/java/ru/myitschool/work/ui/main/MainState.kt @@ -0,0 +1,7 @@ +package ru.myitschool.work.ui.main + +import ru.myitschool.work.domain.user.User + +data class MainState( + val user: User +) \ 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 index 030e031..2e64c93 100644 --- a/app/src/main/java/ru/myitschool/work/ui/main/MainViewModel.kt +++ b/app/src/main/java/ru/myitschool/work/ui/main/MainViewModel.kt @@ -1,7 +1,46 @@ package ru.myitschool.work.ui.main import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharedFlow +import kotlinx.coroutines.flow.asSharedFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch +import ru.myitschool.work.data.repo.AuthRepository +import ru.myitschool.work.domain.MyResult +import ru.myitschool.work.domain.auth.LogOutUseCase +import ru.myitschool.work.domain.user.User class MainViewModel: ViewModel() { + private val logOutUseCase = LogOutUseCase(AuthRepository) + private val _mainState = MutableStateFlow(MainState(User("", ""))) + val mainState = _mainState.asStateFlow() + + private val _navigationEvent = MutableSharedFlow(extraBufferCapacity = 1) + val navigationEvent: SharedFlow = _navigationEvent.asSharedFlow() + + + sealed class NavigationEvent { + data object ToAuth : NavigationEvent() + } + + + fun onIntent(intent: MainIntent){ + when(intent){ + MainIntent.LogOut -> logOut() + MainIntent.Refresh -> TODO() + } + } + + + + private fun logOut() { + viewModelScope.launch { + logOutUseCase() + _navigationEvent.emit(NavigationEvent.ToAuth) + } + } }