feat: refactor navigation structure by replacing AppNavigation with MainApp and updating ListDetailScreen and ListsScreen for improved functionality
This commit is contained in:
@@ -10,7 +10,7 @@ import androidx.compose.runtime.collectAsState
|
|||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import com.collabtable.app.data.preferences.PreferencesManager
|
import com.collabtable.app.data.preferences.PreferencesManager
|
||||||
import com.collabtable.app.ui.navigation.AppNavigation
|
import com.collabtable.app.ui.navigation.MainApp
|
||||||
import com.collabtable.app.ui.theme.CollabTableTheme
|
import com.collabtable.app.ui.theme.CollabTableTheme
|
||||||
|
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
@@ -34,7 +34,7 @@ class MainActivity : ComponentActivity() {
|
|||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
color = MaterialTheme.colorScheme.background,
|
color = MaterialTheme.colorScheme.background,
|
||||||
) {
|
) {
|
||||||
AppNavigation()
|
MainApp()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,131 @@
|
|||||||
|
package com.collabtable.app.ui.navigation
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.Home
|
||||||
|
import androidx.compose.material.icons.filled.Settings
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.NavigationBar
|
||||||
|
import androidx.compose.material3.NavigationBarItem
|
||||||
|
import androidx.compose.material3.Scaffold
|
||||||
|
import androidx.compose.material3.Surface
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.navigation.NavGraph.Companion.findStartDestination
|
||||||
|
import androidx.navigation.compose.NavHost
|
||||||
|
import androidx.navigation.compose.composable
|
||||||
|
import androidx.navigation.compose.currentBackStackEntryAsState
|
||||||
|
import androidx.navigation.compose.rememberNavController
|
||||||
|
import androidx.navigation.navArgument
|
||||||
|
import androidx.navigation.NavType
|
||||||
|
import com.collabtable.app.data.preferences.PreferencesManager
|
||||||
|
import com.collabtable.app.ui.screens.ListDetailScreen
|
||||||
|
import com.collabtable.app.ui.screens.ListsScreen
|
||||||
|
import com.collabtable.app.ui.screens.LogsScreen
|
||||||
|
import com.collabtable.app.ui.screens.ServerSetupScreen
|
||||||
|
import com.collabtable.app.ui.screens.SettingsScreen
|
||||||
|
|
||||||
|
private object Routes {
|
||||||
|
const val Setup = "server_setup"
|
||||||
|
const val MainRoot = "main_root"
|
||||||
|
const val Tables = "tables"
|
||||||
|
const val Settings = "settings"
|
||||||
|
const val ListDetail = "list/{listId}"
|
||||||
|
const val Logs = "logs"
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun MainApp() {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val prefs = remember { PreferencesManager.getInstance(context) }
|
||||||
|
|
||||||
|
// Show setup flow until completed; then show main app with bottom nav
|
||||||
|
if (prefs.isFirstRun()) {
|
||||||
|
val navController = rememberNavController()
|
||||||
|
NavHost(navController, startDestination = Routes.Setup) {
|
||||||
|
composable(Routes.Setup) {
|
||||||
|
ServerSetupScreen(
|
||||||
|
onSetupComplete = {
|
||||||
|
// Mark not first run and trigger recomposition to show main UI
|
||||||
|
prefs.setIsFirstRun(false)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val navController = rememberNavController()
|
||||||
|
val backStackEntry by navController.currentBackStackEntryAsState()
|
||||||
|
val currentRoute = backStackEntry?.destination?.route
|
||||||
|
|
||||||
|
Scaffold(
|
||||||
|
bottomBar = {
|
||||||
|
NavigationBar {
|
||||||
|
NavigationBarItem(
|
||||||
|
selected = currentRoute == Routes.Tables || currentRoute?.startsWith("list/") == true,
|
||||||
|
onClick = {
|
||||||
|
navController.navigate(Routes.Tables) {
|
||||||
|
popUpTo(navController.graph.findStartDestination().id) { saveState = true }
|
||||||
|
launchSingleTop = true
|
||||||
|
restoreState = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
icon = { androidx.compose.material3.Icon(Icons.Default.Home, contentDescription = null) },
|
||||||
|
label = { Text("Tables") },
|
||||||
|
)
|
||||||
|
NavigationBarItem(
|
||||||
|
selected = currentRoute == Routes.Settings,
|
||||||
|
onClick = {
|
||||||
|
navController.navigate(Routes.Settings) {
|
||||||
|
popUpTo(navController.graph.findStartDestination().id) { saveState = true }
|
||||||
|
launchSingleTop = true
|
||||||
|
restoreState = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
icon = { androidx.compose.material3.Icon(Icons.Default.Settings, contentDescription = null) },
|
||||||
|
label = { Text("Settings") },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
) { innerPadding ->
|
||||||
|
Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) {
|
||||||
|
NavHost(
|
||||||
|
navController = navController,
|
||||||
|
startDestination = Routes.Tables,
|
||||||
|
) {
|
||||||
|
composable(Routes.Tables) {
|
||||||
|
ListsScreen(
|
||||||
|
onNavigateToList = { listId -> navController.navigate("list/$listId") },
|
||||||
|
onNavigateToSettings = { navController.navigate(Routes.Settings) },
|
||||||
|
onNavigateToLogs = { navController.navigate(Routes.Logs) },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
composable(Routes.Settings) {
|
||||||
|
SettingsScreen(
|
||||||
|
onNavigateBack = { navController.popBackStack() },
|
||||||
|
onNavigateToLogs = { navController.navigate(Routes.Logs) },
|
||||||
|
onLeaveServer = {
|
||||||
|
// Reset to setup flow by toggling the flag and rebuilding graph via recomposition
|
||||||
|
prefs.setIsFirstRun(true)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
composable(Routes.Logs) {
|
||||||
|
LogsScreen(onNavigateBack = { navController.popBackStack() })
|
||||||
|
}
|
||||||
|
composable(
|
||||||
|
route = Routes.ListDetail,
|
||||||
|
arguments = listOf(navArgument("listId") { type = NavType.StringType }),
|
||||||
|
) { backStackEntry ->
|
||||||
|
val listId = backStackEntry.arguments?.getString("listId") ?: return@composable
|
||||||
|
ListDetailScreen(listId = listId, onNavigateBack = { navController.popBackStack() })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+8
-10
@@ -188,8 +188,8 @@ fun ListDetailScreen(
|
|||||||
val localCtx = LocalContext.current
|
val localCtx = LocalContext.current
|
||||||
val localPrefs = remember { PreferencesManager.getInstance(localCtx) }
|
val localPrefs = remember { PreferencesManager.getInstance(localCtx) }
|
||||||
ConnectionStatusAction(prefs = localPrefs)
|
ConnectionStatusAction(prefs = localPrefs)
|
||||||
IconButton(onClick = { showManageColumnsDialog = true }) {
|
IconButton(onClick = { showAddItemDialog = true }) {
|
||||||
Icon(Icons.Default.Settings, contentDescription = "Manage Columns")
|
Icon(Icons.Default.Add, contentDescription = stringResource(R.string.add_item))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
colors = TopAppBarDefaults.topAppBarColors(
|
colors = TopAppBarDefaults.topAppBarColors(
|
||||||
@@ -198,13 +198,7 @@ fun ListDetailScreen(
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
floatingActionButton = {
|
floatingActionButton = {},
|
||||||
FloatingActionButton(
|
|
||||||
onClick = { showAddItemDialog = true },
|
|
||||||
) {
|
|
||||||
Icon(Icons.Default.Add, contentDescription = stringResource(R.string.add_item))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
) { padding ->
|
) { padding ->
|
||||||
// Apply filtering, sorting, and grouping to items
|
// Apply filtering, sorting, and grouping to items
|
||||||
fun valueFor(item: ItemWithValues, field: Field?): String {
|
fun valueFor(item: ItemWithValues, field: Field?): String {
|
||||||
@@ -527,6 +521,7 @@ fun ListDetailScreen(
|
|||||||
},
|
},
|
||||||
scrollState = horizontalScrollState,
|
scrollState = horizontalScrollState,
|
||||||
isLast = (field.id == stableFields.lastOrNull()?.id),
|
isLast = (field.id == stableFields.lastOrNull()?.id),
|
||||||
|
onHeaderClick = { showManageColumnsDialog = true },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -741,6 +736,7 @@ fun FieldHeader(
|
|||||||
onWidthChange: (Float) -> Unit,
|
onWidthChange: (Float) -> Unit,
|
||||||
scrollState: androidx.compose.foundation.ScrollState,
|
scrollState: androidx.compose.foundation.ScrollState,
|
||||||
isLast: Boolean,
|
isLast: Boolean,
|
||||||
|
onHeaderClick: () -> Unit,
|
||||||
) {
|
) {
|
||||||
val density = LocalDensity.current
|
val density = LocalDensity.current
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
@@ -767,7 +763,9 @@ fun FieldHeader(
|
|||||||
Text(
|
Text(
|
||||||
text = field.name,
|
text = field.name,
|
||||||
style = MaterialTheme.typography.labelLarge,
|
style = MaterialTheme.typography.labelLarge,
|
||||||
modifier = Modifier.weight(1f),
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.clickable { onHeaderClick() },
|
||||||
)
|
)
|
||||||
|
|
||||||
// Resize handle
|
// Resize handle
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ import androidx.compose.material.icons.filled.DragHandle
|
|||||||
import androidx.compose.material.icons.filled.Edit
|
import androidx.compose.material.icons.filled.Edit
|
||||||
import androidx.compose.material.icons.filled.List
|
import androidx.compose.material.icons.filled.List
|
||||||
import androidx.compose.material.icons.filled.Refresh
|
import androidx.compose.material.icons.filled.Refresh
|
||||||
import androidx.compose.material.icons.filled.Settings
|
|
||||||
import androidx.compose.material.icons.filled.Sort
|
import androidx.compose.material.icons.filled.Sort
|
||||||
import androidx.compose.material3.AlertDialog
|
import androidx.compose.material3.AlertDialog
|
||||||
import androidx.compose.material3.CircularProgressIndicator
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
@@ -69,6 +68,7 @@ import org.burnoutcrew.reorderable.reorderable
|
|||||||
@Composable
|
@Composable
|
||||||
fun ListsScreen(
|
fun ListsScreen(
|
||||||
onNavigateToList: (String) -> Unit,
|
onNavigateToList: (String) -> Unit,
|
||||||
|
// Settings now accessed via bottom navigation; keep param for backward compat (unused)
|
||||||
onNavigateToSettings: () -> Unit,
|
onNavigateToSettings: () -> Unit,
|
||||||
onNavigateToLogs: () -> Unit = {},
|
onNavigateToLogs: () -> Unit = {},
|
||||||
) {
|
) {
|
||||||
@@ -108,10 +108,10 @@ fun ListsScreen(
|
|||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val prefsLocal = remember { PreferencesManager.getInstance(context) }
|
val prefsLocal = remember { PreferencesManager.getInstance(context) }
|
||||||
ConnectionStatusAction(prefs = prefsLocal)
|
ConnectionStatusAction(prefs = prefsLocal)
|
||||||
IconButton(onClick = onNavigateToSettings) {
|
IconButton(onClick = { showCreateDialog = true }) {
|
||||||
Icon(
|
Icon(
|
||||||
Icons.Default.Settings,
|
Icons.Default.Add,
|
||||||
contentDescription = stringResource(R.string.settings),
|
contentDescription = stringResource(R.string.create_list),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -122,11 +122,7 @@ fun ListsScreen(
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
floatingActionButton = {
|
floatingActionButton = {},
|
||||||
FloatingActionButton(onClick = { showCreateDialog = true }) {
|
|
||||||
Icon(Icons.Default.Add, contentDescription = stringResource(R.string.create_list))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
) { padding ->
|
) { padding ->
|
||||||
Box(
|
Box(
|
||||||
modifier =
|
modifier =
|
||||||
|
|||||||
Reference in New Issue
Block a user