navigation fix + code review

This commit is contained in:
solovushka56
2025-12-11 17:06:05 +03:00
parent d8416283ae
commit b74a74f3bd
2 changed files with 144 additions and 75 deletions

View File

@@ -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")
}
} }
} }
} }

View File

@@ -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
) )
} }
} }