fix(debug): replace top app bar with actions (delete) (#3276)

Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>
pull/3275/head^2
James Rich 2025-10-01 15:32:50 -05:00 zatwierdzone przez GitHub
rodzic 31d4ef67ed
commit 5a6cd5acbc
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: B5690EEEBB952194
3 zmienionych plików z 74 dodań i 44 usunięć

Wyświetl plik

@ -129,7 +129,7 @@ fun NavGraphBuilder.settingsGraph(navController: NavHostController) {
deepLinks =
listOf(navDeepLink<SettingsRoutes.DebugPanel>(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<SettingsRoutes.User>(navController, entry.name, entry.screenComposable)
is SettingsRoutes.ChannelConfig ->
addRadioConfigScreenComposable<SettingsRoutes.ChannelConfig>(
navController,
entry.name,
entry.screenComposable,
)
is SettingsRoutes.Device ->
addRadioConfigScreenComposable<SettingsRoutes.Device>(navController, entry.name, entry.screenComposable)
is SettingsRoutes.Position ->
addRadioConfigScreenComposable<SettingsRoutes.Position>(
navController,
entry.name,
entry.screenComposable,
)
is SettingsRoutes.Power ->
addRadioConfigScreenComposable<SettingsRoutes.Power>(navController, entry.name, entry.screenComposable)
is SettingsRoutes.Network ->
addRadioConfigScreenComposable<SettingsRoutes.Network>(
navController,
entry.name,
entry.screenComposable,
)
is SettingsRoutes.Display ->
addRadioConfigScreenComposable<SettingsRoutes.Display>(
navController,
entry.name,
entry.screenComposable,
)
is SettingsRoutes.LoRa ->
addRadioConfigScreenComposable<SettingsRoutes.LoRa>(navController, entry.name, entry.screenComposable)
is SettingsRoutes.Bluetooth ->
addRadioConfigScreenComposable<SettingsRoutes.Bluetooth>(
navController,
entry.name,
entry.screenComposable,
)
is SettingsRoutes.Security ->
addRadioConfigScreenComposable<SettingsRoutes.Security>(
navController,
@ -232,70 +241,83 @@ private fun NavGraphBuilder.moduleRoutesScreens(navController: NavHostController
when (entry.route) {
is SettingsRoutes.MQTT ->
addRadioConfigScreenComposable<SettingsRoutes.MQTT>(navController, entry.name, entry.screenComposable)
is SettingsRoutes.Serial ->
addRadioConfigScreenComposable<SettingsRoutes.Serial>(navController, entry.name, entry.screenComposable)
is SettingsRoutes.ExtNotification ->
addRadioConfigScreenComposable<SettingsRoutes.ExtNotification>(
navController,
entry.name,
entry.screenComposable,
)
is SettingsRoutes.StoreForward ->
addRadioConfigScreenComposable<SettingsRoutes.StoreForward>(
navController,
entry.name,
entry.screenComposable,
)
is SettingsRoutes.RangeTest ->
addRadioConfigScreenComposable<SettingsRoutes.RangeTest>(
navController,
entry.name,
entry.screenComposable,
)
is SettingsRoutes.Telemetry ->
addRadioConfigScreenComposable<SettingsRoutes.Telemetry>(
navController,
entry.name,
entry.screenComposable,
)
is SettingsRoutes.CannedMessage ->
addRadioConfigScreenComposable<SettingsRoutes.CannedMessage>(
navController,
entry.name,
entry.screenComposable,
)
is SettingsRoutes.Audio ->
addRadioConfigScreenComposable<SettingsRoutes.Audio>(navController, entry.name, entry.screenComposable)
is SettingsRoutes.RemoteHardware ->
addRadioConfigScreenComposable<SettingsRoutes.RemoteHardware>(
navController,
entry.name,
entry.screenComposable,
)
is SettingsRoutes.NeighborInfo ->
addRadioConfigScreenComposable<SettingsRoutes.NeighborInfo>(
navController,
entry.name,
entry.screenComposable,
)
is SettingsRoutes.AmbientLighting ->
addRadioConfigScreenComposable<SettingsRoutes.AmbientLighting>(
navController,
entry.name,
entry.screenComposable,
)
is SettingsRoutes.DetectionSensor ->
addRadioConfigScreenComposable<SettingsRoutes.DetectionSensor>(
navController,
entry.name,
entry.screenComposable,
)
is SettingsRoutes.Paxcounter ->
addRadioConfigScreenComposable<SettingsRoutes.Paxcounter>(
navController,
entry.name,
entry.screenComposable,
)
else -> Unit // Should not happen if ModuleRoute enum is exhaustive for this context
}
}

Wyświetl plik

@ -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<SettingsRoutes.DebugPanel>() -> DebugMenuActions()
else -> {}
}
}
},
actions = {},
onClickChip = onClickChip,
)
}

Wyświetl plik

@ -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<String> = 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 },
)