First request #5
@@ -49,4 +49,5 @@ dependencies {
|
||||
implementation("io.ktor:ktor-serialization-kotlinx-json:$ktor")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.9.0")
|
||||
implementation("androidx.datastore:datastore-preferences:1.2.0")
|
||||
implementation("androidx.compose.material:material-icons-extended:1.7.8")
|
||||
}
|
||||
|
||||
@@ -7,6 +7,9 @@ object AuthRepository {
|
||||
suspend fun clearCode() {
|
||||
LocalDataSource.setCode("")
|
||||
}
|
||||
suspend fun getCode(): String {
|
||||
return LocalDataSource.getCode()
|
||||
}
|
||||
|
||||
val isCodePresentFlow: Flow<Boolean> = LocalDataSource.isCodePresentFlow
|
||||
suspend fun checkAndSave(text: String): Result<Boolean> {
|
||||
|
||||
12
app/src/main/java/ru/myitschool/work/domain/main/Logout.kt
Normal file
12
app/src/main/java/ru/myitschool/work/domain/main/Logout.kt
Normal file
@@ -0,0 +1,12 @@
|
||||
package ru.myitschool.work.domain.main
|
||||
|
||||
import ru.myitschool.work.data.repo.AuthRepository
|
||||
import kotlin.mapCatching
|
||||
|
||||
class Logout (
|
||||
private val repository: AuthRepository
|
||||
) {
|
||||
suspend operator fun invoke(): Unit {
|
||||
return repository.clearCode()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package ru.myitschool.work.ui.nav
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data object SplashScreenDestination: AppDestination
|
||||
@@ -10,6 +10,7 @@ import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import ru.myitschool.work.data.repo.AuthRepository
|
||||
@@ -23,7 +24,7 @@ class RootActivity() : ComponentActivity() {
|
||||
actionBar?.hide()
|
||||
setContent {
|
||||
WorkTheme {
|
||||
val codePresence by AuthRepository.isCodePresentFlow.collectAsState(false)
|
||||
val codePresence by AuthRepository.isCodePresentFlow.collectAsState(initial = null)
|
||||
|
||||
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
|
||||
AppNavHost(
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package ru.myitschool.work.ui.root
|
||||
|
||||
sealed interface RootState {
|
||||
object Loading: RootState
|
||||
|
||||
object CodePresent: RootState
|
||||
|
||||
object CodeAbsent: RootState
|
||||
}
|
||||
@@ -6,6 +6,7 @@ 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.State
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.navigation.NavHostController
|
||||
@@ -18,32 +19,38 @@ import ru.myitschool.work.data.repo.AuthRepository
|
||||
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.nav.SplashScreenDestination
|
||||
import ru.myitschool.work.ui.root.RootState
|
||||
import ru.myitschool.work.ui.screen.auth.AuthIntent
|
||||
import ru.myitschool.work.ui.screen.auth.AuthScreen
|
||||
import ru.myitschool.work.ui.screen.main.MainScreen
|
||||
import ru.myitschool.work.ui.screen.splash.SplashScreen
|
||||
|
||||
@Composable
|
||||
fun AppNavHost(
|
||||
modifier: Modifier = Modifier,
|
||||
navController: NavHostController = rememberNavController(),
|
||||
codePresence: Boolean
|
||||
codePresence: Boolean?
|
||||
) {
|
||||
val startDestination = if (codePresence == null) SplashScreenDestination
|
||||
else if (codePresence == true) MainScreenDestination
|
||||
else AuthScreenDestination
|
||||
|
||||
NavHost(
|
||||
modifier = modifier,
|
||||
enterTransition = { EnterTransition.None },
|
||||
exitTransition = { ExitTransition.None },
|
||||
navController = navController,
|
||||
startDestination = if (codePresence) MainScreenDestination else AuthScreenDestination,
|
||||
startDestination = startDestination,
|
||||
) {
|
||||
composable<AuthScreenDestination> {
|
||||
AuthScreen(navController = navController)
|
||||
}
|
||||
composable<SplashScreenDestination> {
|
||||
SplashScreen()
|
||||
}
|
||||
composable<MainScreenDestination> {
|
||||
Box(
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Text(text = "MAIN")
|
||||
// LaunchedEffect(Unit) { AuthRepository.clearCode() }
|
||||
|
||||
}
|
||||
MainScreen(navController = navController)
|
||||
}
|
||||
composable<BookScreenDestination> {
|
||||
Box(
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
package ru.myitschool.work.ui.screen.main
|
||||
|
||||
sealed interface MainIntent {
|
||||
data object Fetch: MainIntent
|
||||
data object Logout: MainIntent
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
package ru.myitschool.work.ui.screen.main
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.aspectRatio
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.offset
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.outlined.Logout
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedCard
|
||||
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.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.draw.shadow
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.navigation.NavController
|
||||
import coil3.compose.rememberAsyncImagePainter
|
||||
|
||||
@Composable
|
||||
fun MainScreen(
|
||||
viewModel: MainViewModel = viewModel(),
|
||||
navController: NavController
|
||||
) {
|
||||
val state by viewModel.uiState.collectAsState()
|
||||
|
||||
when (val currentState = state) {
|
||||
is MainState.Error -> {
|
||||
Text("ИДИ НАХУЙ")
|
||||
}
|
||||
|
||||
is MainState.Loading -> {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
verticalArrangement = Arrangement.Center,
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
CircularProgressIndicator()
|
||||
}
|
||||
}
|
||||
is MainState.Data -> {
|
||||
Column (
|
||||
modifier = Modifier.fillMaxSize()
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 40.dp)
|
||||
.height(200.dp),
|
||||
) {
|
||||
IconButton(
|
||||
onClick = { viewModel.onIntent(MainIntent.Logout) },
|
||||
modifier = Modifier
|
||||
.align(Alignment.TopEnd)
|
||||
.size(20.dp)
|
||||
.aspectRatio(1f)
|
||||
.offset(x = -30.dp, y = 40.dp)
|
||||
) {
|
||||
Icon(
|
||||
Icons.AutoMirrored.Outlined.Logout,
|
||||
contentDescription = null,
|
||||
tint = MaterialTheme.colorScheme.error,
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.shadow(7.dp)
|
||||
) }
|
||||
|
||||
|
||||
Row(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Column (
|
||||
verticalArrangement = Arrangement.Center,
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier
|
||||
.padding(start = 30.dp)
|
||||
.size(120.dp)
|
||||
.aspectRatio(1f)
|
||||
.background(MaterialTheme.colorScheme.primaryContainer, CircleShape)
|
||||
) {
|
||||
Image(
|
||||
painter = rememberAsyncImagePainter("https://catalog-cdn.detmir.st/media/2fe02057f9915e72a378795d32c79ea9.jpeg"),
|
||||
contentDescription = null,
|
||||
contentScale = ContentScale.Fit,
|
||||
modifier = Modifier.size(105.dp).clip(CircleShape)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Box(
|
||||
// modifier = Modifier
|
||||
// .fillMaxSize()
|
||||
// .background(MaterialTheme.colorScheme.surfaceContainerLow, RoundedCornerShape(topEnd = 24.dp , topStart = 24.dp))
|
||||
// ) {
|
||||
// LazyColumn(
|
||||
// modifier = Modifier
|
||||
// .fillMaxWidth()
|
||||
// .padding(horizontal = 20.dp)
|
||||
// .padding(top = 8.dp)
|
||||
// ) {
|
||||
// items(
|
||||
// items = [],
|
||||
// key = { item -> item.id }
|
||||
// ) { entry ->
|
||||
// OutlinedCard(
|
||||
// modifier = Modifier
|
||||
// .fillMaxWidth()
|
||||
// .padding(top = 12.dp)
|
||||
// ) {
|
||||
// Text(
|
||||
// text = entry.time,
|
||||
// style = MaterialTheme.typography.titleMedium,
|
||||
// fontWeight = FontWeight.Light,
|
||||
// modifier = Modifier
|
||||
// .padding(start = 16.dp)
|
||||
// .padding(top = 12.dp)
|
||||
// )
|
||||
// Text(
|
||||
// text = entry.place.name,
|
||||
// style = MaterialTheme.typography.titleMedium,
|
||||
// fontWeight = FontWeight.Normal,
|
||||
// modifier = Modifier
|
||||
// .padding(start = 16.dp)
|
||||
// .padding(bottom = 12.dp)
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
viewModel.onIntent(MainIntent.Fetch)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package ru.myitschool.work.ui.screen.main
|
||||
|
||||
sealed interface MainState {
|
||||
object Loading: MainState
|
||||
|
||||
object Data: MainState
|
||||
|
||||
object Error: MainState
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package ru.myitschool.work.ui.screen.main
|
||||
|
||||
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.launch
|
||||
import ru.myitschool.work.data.repo.AuthRepository
|
||||
import ru.myitschool.work.domain.main.Logout
|
||||
|
||||
class MainViewModel(): ViewModel() {
|
||||
private val logout by lazy { Logout(AuthRepository) }
|
||||
private val _uiState = MutableStateFlow<MainState>(MainState.Data)
|
||||
val uiState: StateFlow<MainState> = _uiState.asStateFlow()
|
||||
|
||||
fun onIntent(intent: MainIntent) {
|
||||
when (intent) {
|
||||
is MainIntent.Fetch -> Unit
|
||||
is MainIntent.Logout -> {
|
||||
viewModelScope.launch {
|
||||
logout.invoke()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package ru.myitschool.work.ui.screen.splash
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
|
||||
@Composable
|
||||
fun SplashScreen() {
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user