forked from Olympic/NTO-2025-Android-TeamTask
navigation fix + code review
This commit is contained in:
@@ -2,48 +2,58 @@ package ru.myitschool.work.ui.screen
|
|||||||
|
|
||||||
import androidx.compose.animation.EnterTransition
|
import androidx.compose.animation.EnterTransition
|
||||||
import androidx.compose.animation.ExitTransition
|
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.Composable
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.navigation.NavHostController
|
import androidx.navigation.NavHostController
|
||||||
import androidx.navigation.compose.NavHost
|
import androidx.navigation.compose.NavHost
|
||||||
import androidx.navigation.compose.composable
|
import androidx.navigation.compose.composable
|
||||||
import androidx.navigation.compose.rememberNavController
|
import androidx.navigation.compose.rememberNavController
|
||||||
|
import ru.myitschool.work.data.repo.AuthRepository
|
||||||
import ru.myitschool.work.ui.nav.AuthScreenDestination
|
import ru.myitschool.work.ui.nav.AuthScreenDestination
|
||||||
import ru.myitschool.work.ui.nav.BookScreenDestination
|
import ru.myitschool.work.ui.nav.BookScreenDestination
|
||||||
import ru.myitschool.work.ui.nav.MainScreenDestination
|
import ru.myitschool.work.ui.nav.MainScreenDestination
|
||||||
import ru.myitschool.work.ui.screen.auth.AuthScreen
|
import ru.myitschool.work.ui.screen.auth.AuthScreen
|
||||||
|
import ru.myitschool.work.ui.screen.book.BookScreen
|
||||||
|
import ru.myitschool.work.ui.screen.main.MainScreen
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AppNavHost(
|
fun AppNavHost(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
navController: NavHostController = rememberNavController()
|
navController: NavHostController = rememberNavController()
|
||||||
) {
|
) {
|
||||||
|
// authorized state follow
|
||||||
|
val isAuthorized by AuthRepository.isAuthorized.collectAsState()
|
||||||
|
|
||||||
|
LaunchedEffect(isAuthorized) {
|
||||||
|
if (isAuthorized) {
|
||||||
|
navController.navigate(MainScreenDestination) {
|
||||||
|
popUpTo(0) { inclusive = false }
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
navController.navigate(AuthScreenDestination) {
|
||||||
|
popUpTo(0) { inclusive = false }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NavHost(
|
NavHost(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
enterTransition = { EnterTransition.None },
|
enterTransition = { EnterTransition.None },
|
||||||
exitTransition = { ExitTransition.None },
|
exitTransition = { ExitTransition.None },
|
||||||
navController = navController,
|
navController = navController,
|
||||||
startDestination = AuthScreenDestination,
|
startDestination = if (isAuthorized) MainScreenDestination else AuthScreenDestination,
|
||||||
) {
|
) {
|
||||||
composable<AuthScreenDestination> {
|
composable<AuthScreenDestination> {
|
||||||
AuthScreen(navController = navController)
|
AuthScreen(navController = navController)
|
||||||
}
|
}
|
||||||
composable<MainScreenDestination> {
|
composable<MainScreenDestination> {
|
||||||
Box(
|
MainScreen(navController = navController)
|
||||||
contentAlignment = Alignment.Center
|
|
||||||
) {
|
|
||||||
Text(text = "Hello")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
composable<BookScreenDestination> {
|
composable<BookScreenDestination> {
|
||||||
Box(
|
BookScreen(navController = navController)
|
||||||
contentAlignment = Alignment.Center
|
|
||||||
) {
|
|
||||||
Text(text = "Hello")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -20,6 +20,7 @@ import ru.myitschool.work.R
|
|||||||
import ru.myitschool.work.core.TestIds
|
import ru.myitschool.work.core.TestIds
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
@@ -43,79 +44,121 @@ fun BookScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Scaffold(
|
|
||||||
topBar = {
|
when (val currentState = state) {
|
||||||
TopAppBar(
|
BookState.Loading -> {
|
||||||
title = { Text(stringResource(R.string.book_title)) },
|
Box(
|
||||||
navigationIcon = {
|
modifier = Modifier.fillMaxSize(),
|
||||||
IconButton(
|
contentAlignment = Alignment.Center
|
||||||
onClick = { viewModel.onIntent(BookIntent.Back) },
|
) {
|
||||||
modifier = Modifier.testTag(TestIds.Book.BACK_BUTTON)
|
CircularProgressIndicator()
|
||||||
) {
|
}
|
||||||
Icon(
|
|
||||||
// TODO
|
|
||||||
painter = painterResource(id = R.drawable.back),
|
|
||||||
contentDescription = null
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
) { paddingValues ->
|
|
||||||
Box(
|
BookState.Empty -> {
|
||||||
modifier = Modifier
|
Scaffold(
|
||||||
.fillMaxSize()
|
topBar = {
|
||||||
.padding(paddingValues)
|
TopAppBar(
|
||||||
) {
|
title = { Text(stringResource(R.string.book_title)) },
|
||||||
when (val currentState = state) {
|
navigationIcon = {
|
||||||
BookState.Loading -> {
|
IconButton(
|
||||||
CircularProgressIndicator(
|
onClick = { viewModel.onIntent(BookIntent.Back) },
|
||||||
modifier = Modifier.align(Alignment.Center)
|
modifier = Modifier.testTag(TestIds.Book.BACK_BUTTON)
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(id = R.drawable.back),
|
||||||
|
contentDescription = null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
BookState.Empty -> {
|
) { paddingValues ->
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(paddingValues)
|
||||||
|
.padding(16.dp),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
verticalArrangement = Arrangement.Center
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.book_empty),
|
||||||
|
modifier = Modifier.testTag(TestIds.Book.EMPTY),
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
is BookState.Data -> {
|
||||||
|
if (currentState.error != null && currentState.dates.isEmpty()) {
|
||||||
|
Scaffold(
|
||||||
|
topBar = {
|
||||||
|
TopAppBar(
|
||||||
|
title = { Text(stringResource(R.string.book_title)) },
|
||||||
|
navigationIcon = {
|
||||||
|
IconButton(
|
||||||
|
onClick = { viewModel.onIntent(BookIntent.Back) },
|
||||||
|
modifier = Modifier.testTag(TestIds.Book.BACK_BUTTON)
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(id = R.drawable.back),
|
||||||
|
contentDescription = null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
) { paddingValues ->
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
|
.padding(paddingValues)
|
||||||
.padding(16.dp),
|
.padding(16.dp),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
verticalArrangement = Arrangement.Center
|
verticalArrangement = Arrangement.Center
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.book_empty),
|
text = currentState.error,
|
||||||
modifier = Modifier.testTag(TestIds.Book.EMPTY)
|
modifier = Modifier.testTag(TestIds.Book.ERROR),
|
||||||
|
color = MaterialTheme.colorScheme.error,
|
||||||
|
textAlign = TextAlign.Center
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
Button(
|
Button(
|
||||||
onClick = { viewModel.onIntent(BookIntent.Back) },
|
onClick = { viewModel.onIntent(BookIntent.Refresh) },
|
||||||
modifier = Modifier.testTag(TestIds.Book.BACK_BUTTON)
|
modifier = Modifier.testTag(TestIds.Book.REFRESH_BUTTON)
|
||||||
) {
|
) {
|
||||||
Text(stringResource(R.string.book_back))
|
Text(stringResource(R.string.book_refresh))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is BookState.Data -> {
|
} else {
|
||||||
if (currentState.error != null) {
|
Scaffold(
|
||||||
Column(
|
topBar = {
|
||||||
modifier = Modifier
|
TopAppBar(
|
||||||
.fillMaxSize()
|
title = { Text(stringResource(R.string.book_title)) },
|
||||||
.padding(16.dp),
|
navigationIcon = {
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
IconButton(
|
||||||
verticalArrangement = Arrangement.Center
|
onClick = { viewModel.onIntent(BookIntent.Back) },
|
||||||
) {
|
modifier = Modifier.testTag(TestIds.Book.BACK_BUTTON)
|
||||||
Text(
|
) {
|
||||||
text = currentState.error,
|
Icon(
|
||||||
modifier = Modifier.testTag(TestIds.Book.ERROR)
|
painter = painterResource(id = R.drawable.back),
|
||||||
)
|
contentDescription = null
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
)
|
||||||
Button(
|
}
|
||||||
onClick = { viewModel.onIntent(BookIntent.Refresh) },
|
|
||||||
modifier = Modifier.testTag(TestIds.Book.REFRESH_BUTTON)
|
|
||||||
) {
|
|
||||||
Text(stringResource(R.string.book_refresh))
|
|
||||||
}
|
}
|
||||||
}
|
)
|
||||||
} else {
|
}
|
||||||
|
) { paddingValues ->
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(paddingValues)
|
||||||
|
.padding(16.dp)
|
||||||
|
) {
|
||||||
Content(
|
Content(
|
||||||
state = currentState,
|
state = currentState,
|
||||||
onDateSelect = { viewModel.onIntent(BookIntent.SelectDate(it)) },
|
onDateSelect = { viewModel.onIntent(BookIntent.SelectDate(it)) },
|
||||||
@@ -140,24 +183,39 @@ private fun Content(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.verticalScroll(rememberScrollState())
|
.verticalScroll(rememberScrollState())
|
||||||
.padding(16.dp)
|
|
||||||
) {
|
) {
|
||||||
|
if (state.error != null) {
|
||||||
|
Text(
|
||||||
|
text = state.error,
|
||||||
|
color = MaterialTheme.colorScheme.error,
|
||||||
|
modifier = Modifier
|
||||||
|
.testTag(TestIds.Book.ERROR)
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(bottom = 16.dp),
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
ScrollableTabRow(
|
ScrollableTabRow(
|
||||||
selectedTabIndex = state.selectedDateIndex,
|
selectedTabIndex = state.selectedDateIndex,
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
edgePadding = 0.dp
|
||||||
) {
|
) {
|
||||||
state.dates.forEachIndexed { index, dateItem ->
|
state.dates.forEachIndexed { index, dateItem ->
|
||||||
Tab(
|
Tab(
|
||||||
selected = state.selectedDateIndex == index,
|
selected = state.selectedDateIndex == index,
|
||||||
onClick = { onDateSelect(index) },
|
onClick = { onDateSelect(index) },
|
||||||
modifier = Modifier.testTag(TestIds.Book.getIdDateItemByPosition(index)),
|
modifier = Modifier.testTag(TestIds.Book.getIdDateItemByPosition(index))
|
||||||
text = {
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.padding(vertical = 8.dp, horizontal = 16.dp)
|
||||||
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = dateItem.displayDate,
|
text = dateItem.displayDate,
|
||||||
modifier = Modifier.testTag(TestIds.Book.ITEM_DATE)
|
modifier = Modifier.testTag(TestIds.Book.ITEM_DATE)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,7 +231,7 @@ private fun Content(
|
|||||||
selected = state.selectedPlaceIndex == index,
|
selected = state.selectedPlaceIndex == index,
|
||||||
onClick = { onPlaceSelect(index) }
|
onClick = { onPlaceSelect(index) }
|
||||||
)
|
)
|
||||||
.padding(16.dp)
|
.padding(vertical = 8.dp, horizontal = 16.dp)
|
||||||
.testTag(TestIds.Book.getIdPlaceItemByPosition(index))
|
.testTag(TestIds.Book.getIdPlaceItemByPosition(index))
|
||||||
) {
|
) {
|
||||||
RadioButton(
|
RadioButton(
|
||||||
@@ -184,7 +242,8 @@ private fun Content(
|
|||||||
Spacer(modifier = Modifier.width(16.dp))
|
Spacer(modifier = Modifier.width(16.dp))
|
||||||
Text(
|
Text(
|
||||||
text = placeItem.name,
|
text = placeItem.name,
|
||||||
modifier = Modifier.testTag(TestIds.Book.ITEM_PLACE_TEXT)
|
modifier = Modifier.testTag(TestIds.Book.ITEM_PLACE_TEXT),
|
||||||
|
style = MaterialTheme.typography.bodyLarge
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user