diff --git a/app/src/main/java/com/geeksville/mesh/navigation/SettingsNavigation.kt b/app/src/main/java/com/geeksville/mesh/navigation/SettingsNavigation.kt index e1f6fae20..26eb67200 100644 --- a/app/src/main/java/com/geeksville/mesh/navigation/SettingsNavigation.kt +++ b/app/src/main/java/com/geeksville/mesh/navigation/SettingsNavigation.kt @@ -129,7 +129,7 @@ fun NavGraphBuilder.settingsGraph(navController: NavHostController) { deepLinks = listOf(navDeepLink(basePath = "$DEEP_LINK_BASE_URI/settings/debug_panel")), ) { - DebugScreen() + DebugScreen(onNavigateUp = navController::navigateUp) } } } @@ -178,42 +178,51 @@ private fun NavGraphBuilder.configRoutesScreens(navController: NavHostController when (entry.route) { is SettingsRoutes.User -> addRadioConfigScreenComposable(navController, entry.name, entry.screenComposable) + is SettingsRoutes.ChannelConfig -> addRadioConfigScreenComposable( navController, entry.name, entry.screenComposable, ) + is SettingsRoutes.Device -> addRadioConfigScreenComposable(navController, entry.name, entry.screenComposable) + is SettingsRoutes.Position -> addRadioConfigScreenComposable( navController, entry.name, entry.screenComposable, ) + is SettingsRoutes.Power -> addRadioConfigScreenComposable(navController, entry.name, entry.screenComposable) + is SettingsRoutes.Network -> addRadioConfigScreenComposable( navController, entry.name, entry.screenComposable, ) + is SettingsRoutes.Display -> addRadioConfigScreenComposable( navController, entry.name, entry.screenComposable, ) + is SettingsRoutes.LoRa -> addRadioConfigScreenComposable(navController, entry.name, entry.screenComposable) + is SettingsRoutes.Bluetooth -> addRadioConfigScreenComposable( navController, entry.name, entry.screenComposable, ) + is SettingsRoutes.Security -> addRadioConfigScreenComposable( navController, @@ -232,70 +241,83 @@ private fun NavGraphBuilder.moduleRoutesScreens(navController: NavHostController when (entry.route) { is SettingsRoutes.MQTT -> addRadioConfigScreenComposable(navController, entry.name, entry.screenComposable) + is SettingsRoutes.Serial -> addRadioConfigScreenComposable(navController, entry.name, entry.screenComposable) + is SettingsRoutes.ExtNotification -> addRadioConfigScreenComposable( navController, entry.name, entry.screenComposable, ) + is SettingsRoutes.StoreForward -> addRadioConfigScreenComposable( navController, entry.name, entry.screenComposable, ) + is SettingsRoutes.RangeTest -> addRadioConfigScreenComposable( navController, entry.name, entry.screenComposable, ) + is SettingsRoutes.Telemetry -> addRadioConfigScreenComposable( navController, entry.name, entry.screenComposable, ) + is SettingsRoutes.CannedMessage -> addRadioConfigScreenComposable( navController, entry.name, entry.screenComposable, ) + is SettingsRoutes.Audio -> addRadioConfigScreenComposable(navController, entry.name, entry.screenComposable) + is SettingsRoutes.RemoteHardware -> addRadioConfigScreenComposable( navController, entry.name, entry.screenComposable, ) + is SettingsRoutes.NeighborInfo -> addRadioConfigScreenComposable( navController, entry.name, entry.screenComposable, ) + is SettingsRoutes.AmbientLighting -> addRadioConfigScreenComposable( navController, entry.name, entry.screenComposable, ) + is SettingsRoutes.DetectionSensor -> addRadioConfigScreenComposable( navController, entry.name, entry.screenComposable, ) + is SettingsRoutes.Paxcounter -> addRadioConfigScreenComposable( navController, entry.name, entry.screenComposable, ) + else -> Unit // Should not happen if ModuleRoute enum is exhaustive for this context } } diff --git a/app/src/main/java/com/geeksville/mesh/ui/common/components/MainAppBar.kt b/app/src/main/java/com/geeksville/mesh/ui/common/components/MainAppBar.kt index 08e98dacd..5c0a094a6 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/common/components/MainAppBar.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/common/components/MainAppBar.kt @@ -43,7 +43,6 @@ import androidx.compose.ui.unit.dp import androidx.navigation.NavDestination.Companion.hasRoute import androidx.navigation.NavHostController import androidx.navigation.compose.currentBackStackEntryAsState -import com.geeksville.mesh.ui.debug.DebugMenuActions import com.geeksville.mesh.ui.node.components.NodeChip import org.meshtastic.core.database.model.Node import org.meshtastic.core.navigation.ContactsRoutes @@ -86,14 +85,7 @@ fun MainAppBar( ourNode = ourNode, showNodeChip = false, onNavigateUp = navController::navigateUp, - actions = { - currentDestination?.let { - when { - currentDestination.hasRoute() -> DebugMenuActions() - else -> {} - } - } - }, + actions = {}, onClickChip = onClickChip, ) } diff --git a/app/src/main/java/com/geeksville/mesh/ui/debug/Debug.kt b/app/src/main/java/com/geeksville/mesh/ui/debug/Debug.kt index 4b6bbda04..4b77a57d8 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/debug/Debug.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/debug/Debug.kt @@ -47,6 +47,7 @@ import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.Scaffold import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.material3.TextButton @@ -79,6 +80,7 @@ import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.geeksville.mesh.model.DebugViewModel import com.geeksville.mesh.model.DebugViewModel.UiMeshLog +import com.geeksville.mesh.ui.common.components.MainAppBar import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -102,7 +104,7 @@ private var redactedKeys: List = listOf("session_passkey", "private_key" @Suppress("LongMethod") @Composable -internal fun DebugScreen(viewModel: DebugViewModel = hiltViewModel()) { +internal fun DebugScreen(onNavigateUp: () -> Unit, viewModel: DebugViewModel = hiltViewModel()) { val listState = rememberLazyListState() val logs by viewModel.meshLog.collectAsStateWithLifecycle() val searchState by viewModel.searchState.collectAsStateWithLifecycle() @@ -143,34 +145,51 @@ internal fun DebugScreen(viewModel: DebugViewModel = hiltViewModel()) { } } - Column(modifier = Modifier.fillMaxSize()) { - LazyColumn(modifier = Modifier.fillMaxSize(), state = listState) { - stickyHeader { - val animatedAlpha by - animateFloatAsState(targetValue = if (!listState.isScrollInProgress) 1.0f else 0f, label = "alpha") - DebugSearchStateviewModelDefaults( - modifier = Modifier.graphicsLayer(alpha = animatedAlpha), - searchState = searchState, - filterTexts = filterTexts, - presetFilters = viewModel.presetFilters, - logs = logs, - filterMode = filterMode, - onFilterModeChange = { filterMode = it }, - onExportLogs = { - val timestamp = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(Date()) - val fileName = "meshtastic_debug_$timestamp.txt" - exportLogsLauncher.launch(fileName) - }, - ) - } - items(filteredLogs, key = { it.uuid }) { log -> - DebugItem( - modifier = Modifier.animateItem(), - log = log, - searchText = searchState.searchText, - isSelected = selectedLogId == log.uuid, - onLogClick = { viewModel.setSelectedLogId(if (selectedLogId == log.uuid) null else log.uuid) }, - ) + Scaffold( + topBar = { + MainAppBar( + title = stringResource(R.string.debug_panel), + ourNode = null, + showNodeChip = false, + canNavigateUp = true, + onNavigateUp = onNavigateUp, + actions = { DebugMenuActions(deleteLogs = { viewModel.deleteAllLogs() }) }, + onClickChip = {}, + ) + }, + ) { paddingValues -> + Column(modifier = Modifier.padding(paddingValues).fillMaxSize()) { + LazyColumn(modifier = Modifier.fillMaxSize(), state = listState) { + stickyHeader { + val animatedAlpha by + animateFloatAsState( + targetValue = if (!listState.isScrollInProgress) 1.0f else 0f, + label = "alpha", + ) + DebugSearchStateviewModelDefaults( + modifier = Modifier.graphicsLayer(alpha = animatedAlpha), + searchState = searchState, + filterTexts = filterTexts, + presetFilters = viewModel.presetFilters, + logs = logs, + filterMode = filterMode, + onFilterModeChange = { filterMode = it }, + onExportLogs = { + val timestamp = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(Date()) + val fileName = "meshtastic_debug_$timestamp.txt" + exportLogsLauncher.launch(fileName) + }, + ) + } + items(filteredLogs, key = { it.uuid }) { log -> + DebugItem( + modifier = Modifier.animateItem(), + log = log, + searchText = searchState.searchText, + isSelected = selectedLogId == log.uuid, + onLogClick = { viewModel.setSelectedLogId(if (selectedLogId == log.uuid) null else log.uuid) }, + ) + } } } } @@ -327,10 +346,7 @@ private fun rememberAnnotatedLogMessage(log: UiMeshLog, searchText: String): Ann } @Composable -fun DebugMenuActions(viewModel: DebugViewModel = hiltViewModel(), modifier: Modifier = Modifier) { - val context = LocalContext.current - val scope = rememberCoroutineScope() - +fun DebugMenuActions(deleteLogs: () -> Unit, modifier: Modifier = Modifier) { var showDeleteLogsDialog by remember { mutableStateOf(false) } IconButton(onClick = { showDeleteLogsDialog = true }, modifier = modifier.padding(4.dp)) { @@ -342,7 +358,7 @@ fun DebugMenuActions(viewModel: DebugViewModel = hiltViewModel(), modifier: Modi text = R.string.debug_clear_logs_confirm, onConfirm = { showDeleteLogsDialog = false - viewModel.deleteAllLogs() + deleteLogs() }, onDismiss = { showDeleteLogsDialog = false }, )