Refactor BottomNavBar visibility and add Daily Review feature
This commit is contained in:
@@ -253,19 +253,23 @@ fun TranslatorApp(
|
|||||||
val currentDestination = navBackStackEntry?.destination
|
val currentDestination = navBackStackEntry?.destination
|
||||||
val selectedScreen = Screen.fromDestination(currentDestination)
|
val selectedScreen = Screen.fromDestination(currentDestination)
|
||||||
|
|
||||||
@Suppress("HardCodedStringLiteral") val isBottomBarHidden = currentDestination?.hierarchy?.any { destination ->
|
@Suppress("HardCodedStringLiteral")
|
||||||
|
val currentRoute = currentDestination?.route
|
||||||
|
val isHiddenByHierarchy = currentDestination?.hierarchy?.any { destination ->
|
||||||
destination.route in setOf(
|
destination.route in setOf(
|
||||||
Screen.Translation.route,
|
Screen.Translation.route,
|
||||||
Screen.Dictionary.route,
|
Screen.Dictionary.route,
|
||||||
Screen.Exercises.route,
|
Screen.Exercises.route,
|
||||||
Screen.Settings.route
|
Screen.Settings.route
|
||||||
)
|
)
|
||||||
} == true || currentDestination?.route in setOf(
|
} == true
|
||||||
"start_exercise",
|
val isBottomBarHidden = isHiddenByHierarchy || currentRoute in setOf(
|
||||||
"new_word",
|
"new_word",
|
||||||
"new_word_review",
|
"new_word_review",
|
||||||
"vocabulary_detail/{itemId}"
|
"vocabulary_detail/{itemId}",
|
||||||
)
|
"daily_review"
|
||||||
|
) || currentRoute?.startsWith("start_exercise") == true
|
||||||
|
|| currentRoute?.startsWith("vocabulary_exercise") == true
|
||||||
val showBottomNavLabels by settingsViewModel.showBottomNavLabels.collectAsStateWithLifecycle(initialValue = false)
|
val showBottomNavLabels by settingsViewModel.showBottomNavLabels.collectAsStateWithLifecycle(initialValue = false)
|
||||||
|
|
||||||
BottomNavigationBar(
|
BottomNavigationBar(
|
||||||
@@ -440,4 +444,4 @@ private fun AppTheme(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,10 +29,10 @@ import eu.gaudian.translator.view.exercises.MainExerciseScreen
|
|||||||
import eu.gaudian.translator.view.exercises.StartExerciseScreen
|
import eu.gaudian.translator.view.exercises.StartExerciseScreen
|
||||||
import eu.gaudian.translator.view.exercises.YouTubeBrowserScreen
|
import eu.gaudian.translator.view.exercises.YouTubeBrowserScreen
|
||||||
import eu.gaudian.translator.view.exercises.YouTubeExerciseScreen
|
import eu.gaudian.translator.view.exercises.YouTubeExerciseScreen
|
||||||
|
import eu.gaudian.translator.view.home.DailyReviewScreen
|
||||||
import eu.gaudian.translator.view.home.HomeScreen
|
import eu.gaudian.translator.view.home.HomeScreen
|
||||||
import eu.gaudian.translator.view.library.LibraryScreen
|
import eu.gaudian.translator.view.library.LibraryScreen
|
||||||
import eu.gaudian.translator.view.settings.DictionaryOptionsScreen
|
import eu.gaudian.translator.view.settings.DictionaryOptionsScreen
|
||||||
import eu.gaudian.translator.view.settings.SettingsRoutes
|
|
||||||
import eu.gaudian.translator.view.settings.TranslationSettingsScreen
|
import eu.gaudian.translator.view.settings.TranslationSettingsScreen
|
||||||
import eu.gaudian.translator.view.settings.settingsGraph
|
import eu.gaudian.translator.view.settings.settingsGraph
|
||||||
import eu.gaudian.translator.view.stats.StatsScreen
|
import eu.gaudian.translator.view.stats.StatsScreen
|
||||||
@@ -53,6 +53,7 @@ import eu.gaudian.translator.view.vocabulary.VocabularySortingScreen
|
|||||||
private const val TRANSITION_DURATION = 300
|
private const val TRANSITION_DURATION = 300
|
||||||
|
|
||||||
object NavigationRoutes {
|
object NavigationRoutes {
|
||||||
|
const val DAILY_REVIEW = "daily_review"
|
||||||
const val NEW_WORD = "new_word"
|
const val NEW_WORD = "new_word"
|
||||||
const val NEW_WORD_REVIEW = "new_word_review"
|
const val NEW_WORD_REVIEW = "new_word_review"
|
||||||
const val VOCABULARY_DETAIL = "vocabulary_detail"
|
const val VOCABULARY_DETAIL = "vocabulary_detail"
|
||||||
@@ -68,6 +69,7 @@ object NavigationRoutes {
|
|||||||
const val STATS_VOCABULARY_LIST = "stats/vocabulary_list"
|
const val STATS_VOCABULARY_LIST = "stats/vocabulary_list"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(androidx.compose.animation.ExperimentalAnimationApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun AppNavHost(
|
fun AppNavHost(
|
||||||
navController: NavHostController,
|
navController: NavHostController,
|
||||||
@@ -81,15 +83,23 @@ fun AppNavHost(
|
|||||||
Screen.Home.route,
|
Screen.Home.route,
|
||||||
Screen.Library.route,
|
Screen.Library.route,
|
||||||
Screen.Stats.route,
|
Screen.Stats.route,
|
||||||
Screen.Translation.route,
|
|
||||||
Screen.Dictionary.route,
|
|
||||||
Screen.Exercises.route,
|
|
||||||
SettingsRoutes.LIST
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Helper to check if a route is a top-level tab
|
// Helper to check if a route is a top-level tab
|
||||||
|
// Note: Routes can be "main_home", "main_library" etc. but mainTabRoutes contains parent routes
|
||||||
fun isTabTransition(initial: String?, target: String?): Boolean {
|
fun isTabTransition(initial: String?, target: String?): Boolean {
|
||||||
return mainTabRoutes.contains(initial) && mainTabRoutes.contains(target)
|
if (initial == null || target == null) return false
|
||||||
|
// Check if either the direct route OR a "main_*" variant is in mainTabRoutes
|
||||||
|
val initialIsTab = mainTabRoutes.contains(initial) ||
|
||||||
|
mainTabRoutes.any { route ->
|
||||||
|
initial == "main_${route}" || initial.startsWith("${route}_")
|
||||||
|
}
|
||||||
|
val targetIsTab = mainTabRoutes.contains(target) ||
|
||||||
|
mainTabRoutes.any { route ->
|
||||||
|
target == "main_${route}" || target.startsWith("${route}_")
|
||||||
|
}
|
||||||
|
return initialIsTab && targetIsTab
|
||||||
}
|
}
|
||||||
|
|
||||||
NavHost(
|
NavHost(
|
||||||
@@ -146,6 +156,10 @@ fun AppNavHost(
|
|||||||
HomeScreen(navController = navController)
|
HomeScreen(navController = navController)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
composable(NavigationRoutes.DAILY_REVIEW) {
|
||||||
|
DailyReviewScreen(navController = navController)
|
||||||
|
}
|
||||||
|
|
||||||
composable(NavigationRoutes.NEW_WORD) {
|
composable(NavigationRoutes.NEW_WORD) {
|
||||||
NewWordScreen(navController = navController)
|
NewWordScreen(navController = navController)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ fun HomeScreen(
|
|||||||
val streak by viewModel.streak.collectAsState()
|
val streak by viewModel.streak.collectAsState()
|
||||||
val dailyGoal by viewModel.dailyGoal.collectAsState()
|
val dailyGoal by viewModel.dailyGoal.collectAsState()
|
||||||
val todayCompletedCount by viewModel.todayCompletedCount.collectAsState()
|
val todayCompletedCount by viewModel.todayCompletedCount.collectAsState()
|
||||||
|
val dueTodayCount by viewModel.dueTodayCount.collectAsState()
|
||||||
|
|
||||||
// Calculate daily goal progress
|
// Calculate daily goal progress
|
||||||
val progress = if (dailyGoal > 0) {
|
val progress = if (dailyGoal > 0) {
|
||||||
@@ -95,13 +96,12 @@ fun HomeScreen(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
item {
|
item {
|
||||||
//TODO replace with actual implementation
|
|
||||||
@Suppress("HardCodedStringLiteral")
|
|
||||||
ActionCard(
|
ActionCard(
|
||||||
title = "Daily Review",
|
title = stringResource(R.string.label_daily_review),
|
||||||
subtitle = "42 words need attention",
|
subtitle = stringResource(R.string.desc_daily_review_due, dueTodayCount),
|
||||||
icon = Icons.Default.Psychology,
|
icon = Icons.Default.Psychology,
|
||||||
contentColor = MaterialTheme.colorScheme.onPrimary
|
contentColor = MaterialTheme.colorScheme.onPrimary,
|
||||||
|
onClick = { navController.navigate(NavigationRoutes.DAILY_REVIEW) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
item {
|
item {
|
||||||
|
|||||||
@@ -1088,6 +1088,9 @@
|
|||||||
<string name="label_2d_days">%1$d Days</string>
|
<string name="label_2d_days">%1$d Days</string>
|
||||||
<string name="label_current_streak">Current Streak</string>
|
<string name="label_current_streak">Current Streak</string>
|
||||||
<string name="label_daily_goal">Daily Goal</string>
|
<string name="label_daily_goal">Daily Goal</string>
|
||||||
|
<string name="label_daily_review">Daily Review</string>
|
||||||
|
<string name="desc_daily_review_due">%1$d words need attention</string>
|
||||||
|
<string name="text_daily_review_placeholder">Daily review screen - implementation pending</string>
|
||||||
<string name="text_desc_no_activity_data_available">No activity data available</string>
|
<string name="text_desc_no_activity_data_available">No activity data available</string>
|
||||||
<string name="label_see_history">See History</string>
|
<string name="label_see_history">See History</string>
|
||||||
<string name="label_weekly_progress">Weekly Progress</string>
|
<string name="label_weekly_progress">Weekly Progress</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user