From c1408816a427a796c61186349488f4e34c8ebaa1 Mon Sep 17 00:00:00 2001 From: DaneEvans Date: Tue, 29 Jul 2025 19:13:06 +1000 Subject: [PATCH] Fix Debug panel: Decoded payload not showing (#2555) --- .../com/geeksville/mesh/ui/debug/Debug.kt | 516 +++++++----------- 1 file changed, 183 insertions(+), 333 deletions(-) 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 0c83f13e0..2a09a8591 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 @@ -99,9 +99,7 @@ private val REGEX_ANNOTATED_NODE_ID = Regex("\\(![0-9a-fA-F]{8}\\)$", RegexOptio @Suppress("LongMethod") @Composable -internal fun DebugScreen( - viewModel: DebugViewModel = hiltViewModel(), -) { +internal fun DebugScreen(viewModel: DebugViewModel = hiltViewModel()) { val listState = rememberLazyListState() val logs by viewModel.meshLog.collectAsStateWithLifecycle() val searchState by viewModel.searchState.collectAsStateWithLifecycle() @@ -111,13 +109,12 @@ internal fun DebugScreen( var filterMode by remember { mutableStateOf(FilterMode.OR) } // Use the new filterLogs method to include decodedPayload in filtering - val filteredLogs = remember(logs, filterTexts, filterMode) { - viewModel.filterManager.filterLogs(logs, filterTexts, filterMode).toImmutableList() - } + val filteredLogs = + remember(logs, filterTexts, filterMode) { + viewModel.filterManager.filterLogs(logs, filterTexts, filterMode).toImmutableList() + } - LaunchedEffect(filteredLogs) { - viewModel.updateFilteredLogs(filteredLogs) - } + LaunchedEffect(filteredLogs) { viewModel.updateFilteredLogs(filteredLogs) } val shouldAutoScroll by remember { derivedStateOf { listState.firstVisibleItemIndex < 3 } } if (shouldAutoScroll) { @@ -133,28 +130,19 @@ internal fun DebugScreen( listState.requestScrollToItem(searchState.allMatches[searchState.currentMatchIndex].logIndex) } } - Column( - modifier = Modifier.fillMaxSize() - ) { - LazyColumn( - modifier = Modifier.fillMaxSize(), - state = listState, - ) { + 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" - ) + val animatedAlpha by + animateFloatAsState(targetValue = if (!listState.isScrollInProgress) 1.0f else 0f, label = "alpha") DebugSearchStateviewModelDefaults( - modifier = Modifier.graphicsLayer( - alpha = animatedAlpha - ), + modifier = Modifier.graphicsLayer(alpha = animatedAlpha), searchState = searchState, filterTexts = filterTexts, presetFilters = viewModel.presetFilters, logs = logs, filterMode = filterMode, - onFilterModeChange = { filterMode = it } + onFilterModeChange = { filterMode = it }, ) } items(filteredLogs, key = { it.uuid }) { log -> @@ -163,9 +151,7 @@ internal fun DebugScreen( log = log, searchText = searchState.searchText, isSelected = selectedLogId == log.uuid, - onLogClick = { - viewModel.setSelectedLogId(if (selectedLogId == log.uuid) null else log.uuid) - } + onLogClick = { viewModel.setSelectedLogId(if (selectedLogId == log.uuid) null else log.uuid) }, ) } } @@ -178,49 +164,43 @@ internal fun DebugItem( modifier: Modifier = Modifier, searchText: String = "", isSelected: Boolean = false, - onLogClick: () -> Unit = {} + onLogClick: () -> Unit = {}, ) { val colorScheme = MaterialTheme.colorScheme Card( - modifier = modifier - .fillMaxWidth() - .padding(4.dp), - colors = CardDefaults.cardColors( - containerColor = if (isSelected) { + modifier = modifier.fillMaxWidth().padding(4.dp), + colors = + CardDefaults.cardColors( + containerColor = + if (isSelected) { colorScheme.primary.copy(alpha = 0.1f) } else { colorScheme.surface - } + }, ), - border = if (isSelected) { + border = + if (isSelected) { BorderStroke(2.dp, colorScheme.primary) } else { null - } + }, ) { SelectionContainer { Column( - modifier = Modifier - .padding(if (isSelected) 12.dp else 8.dp) - .fillMaxWidth() - .clickable { onLogClick() } + modifier = Modifier.padding(if (isSelected) 12.dp else 8.dp).fillMaxWidth().clickable { onLogClick() }, ) { - DebugItemHeader( - log = log, - searchText = searchText, - isSelected = isSelected, - theme = colorScheme - ) + DebugItemHeader(log = log, searchText = searchText, isSelected = isSelected, theme = colorScheme) val messageAnnotatedString = rememberAnnotatedLogMessage(log, searchText) Text( text = messageAnnotatedString, softWrap = false, - style = TextStyle( + style = + TextStyle( fontSize = if (isSelected) 12.sp else 9.sp, fontFamily = FontFamily.Monospace, - color = colorScheme.onSurface - ) + color = colorScheme.onSurface, + ), ) // Show decoded payload if available, with search highlighting if (!log.decodedPayload.isNullOrBlank()) { @@ -229,7 +209,7 @@ internal fun DebugItem( isSelected = isSelected, colorScheme = colorScheme, searchText = searchText, - modifier = Modifier.weight(1f) + modifier = Modifier, ) } } @@ -238,79 +218,60 @@ internal fun DebugItem( } @Composable -private fun DebugItemHeader( - log: UiMeshLog, - searchText: String, - isSelected: Boolean, - theme: ColorScheme -) { +private fun DebugItemHeader(log: UiMeshLog, searchText: String, isSelected: Boolean, theme: ColorScheme) { Row( - modifier = Modifier - .fillMaxWidth() - .padding(bottom = if (isSelected) 12.dp else 8.dp), + modifier = Modifier.fillMaxWidth().padding(bottom = if (isSelected) 12.dp else 8.dp), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically, ) { - val typeAnnotatedString = rememberAnnotatedString( - text = log.messageType, - searchText = searchText - ) + val typeAnnotatedString = rememberAnnotatedString(text = log.messageType, searchText = searchText) Text( text = typeAnnotatedString, modifier = Modifier.weight(1f), - style = TextStyle( + style = + TextStyle( fontWeight = FontWeight.Bold, fontSize = if (isSelected) 16.sp else 14.sp, - color = theme.onSurface + color = theme.onSurface, ), ) // Copy full log: message + decoded payload if present - val fullLogText = remember(log.logMessage, log.decodedPayload) { - buildString { - append(log.logMessage) - if (!log.decodedPayload.isNullOrBlank()) { - append("\n\nDecoded Payload:\n{") - append("\n") - append(log.decodedPayload) - append("\n}") + val fullLogText = + remember(log.logMessage, log.decodedPayload) { + buildString { + append(log.logMessage) + if (!log.decodedPayload.isNullOrBlank()) { + append("\n\nDecoded Payload:\n{") + append("\n") + append(log.decodedPayload) + append("\n}") + } } } - } - CopyIconButton( - valueToCopy = fullLogText, - modifier = Modifier.padding(start = 8.dp) - ) + CopyIconButton(valueToCopy = fullLogText, modifier = Modifier.padding(start = 8.dp)) Icon( imageVector = Icons.Outlined.FileDownload, contentDescription = stringResource(id = R.string.logs), tint = Color.Gray.copy(alpha = 0.6f), modifier = Modifier.padding(end = 8.dp), ) - val dateAnnotatedString = rememberAnnotatedString( - text = log.formattedReceivedDate, - searchText = searchText - ) + val dateAnnotatedString = rememberAnnotatedString(text = log.formattedReceivedDate, searchText = searchText) Text( text = dateAnnotatedString, - style = TextStyle( + style = + TextStyle( fontWeight = FontWeight.Bold, fontSize = if (isSelected) 14.sp else 12.sp, - color = theme.onSurface + color = theme.onSurface, ), ) } } @Composable -private fun rememberAnnotatedString( - text: String, - searchText: String -): AnnotatedString { +private fun rememberAnnotatedString(text: String, searchText: String): AnnotatedString { val theme = MaterialTheme.colorScheme - val highlightStyle = SpanStyle( - background = theme.primary.copy(alpha = 0.3f), - color = theme.onSurface - ) + val highlightStyle = SpanStyle(background = theme.primary.copy(alpha = 0.3f), color = theme.onSurface) return remember(text, searchText) { buildAnnotatedString { @@ -318,11 +279,7 @@ private fun rememberAnnotatedString( if (searchText.isNotEmpty()) { searchText.split(" ").forEach { term -> Regex(Regex.escape(term), RegexOption.IGNORE_CASE).findAll(text).forEach { match -> - addStyle( - style = highlightStyle, - start = match.range.first, - end = match.range.last + 1 - ) + addStyle(style = highlightStyle, start = match.range.first, end = match.range.last + 1) } } } @@ -333,38 +290,23 @@ private fun rememberAnnotatedString( @Composable private fun rememberAnnotatedLogMessage(log: UiMeshLog, searchText: String): AnnotatedString { val theme = MaterialTheme.colorScheme - val style = SpanStyle( - color = colorResource(id = R.color.colorAnnotation), - fontStyle = FontStyle.Italic, - ) - val highlightStyle = SpanStyle( - background = theme.primary.copy(alpha = 0.3f), - color = theme.onSurface - ) + val style = SpanStyle(color = colorResource(id = R.color.colorAnnotation), fontStyle = FontStyle.Italic) + val highlightStyle = SpanStyle(background = theme.primary.copy(alpha = 0.3f), color = theme.onSurface) return remember(log.uuid, searchText) { buildAnnotatedString { append(log.logMessage) // Add node ID annotations - REGEX_ANNOTATED_NODE_ID.findAll(log.logMessage).toList().reversed() - .forEach { - addStyle( - style = style, - start = it.range.first, - end = it.range.last + 1 - ) - } + REGEX_ANNOTATED_NODE_ID.findAll(log.logMessage).toList().reversed().forEach { + addStyle(style = style, start = it.range.first, end = it.range.last + 1) + } // Add search highlight annotations if (searchText.isNotEmpty()) { searchText.split(" ").forEach { term -> Regex(Regex.escape(term), RegexOption.IGNORE_CASE).findAll(log.logMessage).forEach { match -> - addStyle( - style = highlightStyle, - start = match.range.first, - end = match.range.last + 1 - ) + addStyle(style = highlightStyle, start = match.range.first, end = match.range.last + 1) } } } @@ -381,22 +323,23 @@ private fun DebugPacketPreview() { uuid = "", messageType = "NodeInfo", formattedReceivedDate = "9/27/20, 8:00:58 PM", - logMessage = "from: 2885173132\n" + - "decoded {\n" + - " position {\n" + - " altitude: 60\n" + - " battery_level: 81\n" + - " latitude_i: 411111136\n" + - " longitude_i: -711111805\n" + - " time: 1600390966\n" + - " }\n" + - "}\n" + - "hop_limit: 3\n" + - "id: 1737414295\n" + - "rx_snr: 9.5\n" + - "rx_time: 316400569\n" + - "to: -1409790708", - ) + logMessage = + "from: 2885173132\n" + + "decoded {\n" + + " position {\n" + + " altitude: 60\n" + + " battery_level: 81\n" + + " latitude_i: 411111136\n" + + " longitude_i: -711111805\n" + + " time: 1600390966\n" + + " }\n" + + "}\n" + + "hop_limit: 3\n" + + "id: 1737414295\n" + + "rx_snr: 9.5\n" + + "rx_time: 316400569\n" + + "to: -1409790708", + ), ) } } @@ -410,9 +353,9 @@ private fun DebugItemWithSearchHighlightPreview() { uuid = "1", messageType = "TextMessage", formattedReceivedDate = "9/27/20, 8:00:58 PM", - logMessage = "Hello world! This is a test message with some keywords to search for." + logMessage = "Hello world! This is a test message with some keywords to search for.", ), - searchText = "test message" + searchText = "test message", ) } } @@ -426,8 +369,8 @@ private fun DebugItemPositionPreview() { uuid = "2", messageType = "Position", formattedReceivedDate = "9/27/20, 8:01:15 PM", - logMessage = "Position update from node (!a1b2c3d4) at coordinates 40.7128, -74.0060" - ) + logMessage = "Position update from node (!a1b2c3d4) at coordinates 40.7128, -74.0060", + ), ) } } @@ -441,10 +384,11 @@ private fun DebugItemErrorPreview() { uuid = "3", messageType = "Error", formattedReceivedDate = "9/27/20, 8:02:30 PM", - logMessage = "Connection failed: timeout after 30 seconds\n" + - "Retry attempt: 3/5\n" + - "Last known position: 40.7128, -74.0060" - ) + logMessage = + "Connection failed: timeout after 30 seconds\n" + + "Retry attempt: 3/5\n" + + "Last known position: 40.7128, -74.0060", + ), ) } } @@ -458,16 +402,17 @@ private fun DebugItemLongMessagePreview() { uuid = "4", messageType = "Waypoint", formattedReceivedDate = "9/27/20, 8:03:45 PM", - logMessage = "Waypoint created:\n" + - " Name: Home Base\n" + - " Description: Primary meeting location\n" + - " Latitude: 40.7128\n" + - " Longitude: -74.0060\n" + - " Altitude: 100m\n" + - " Icon: 🏠\n" + - " Created by: (!a1b2c3d4)\n" + - " Expires: 2025-12-31 23:59:59" - ) + logMessage = + "Waypoint created:\n" + + " Name: Home Base\n" + + " Description: Primary meeting location\n" + + " Latitude: 40.7128\n" + + " Longitude: -74.0060\n" + + " Altitude: 100m\n" + + " Icon: 🏠\n" + + " Created by: (!a1b2c3d4)\n" + + " Expires: 2025-12-31 23:59:59", + ), ) } } @@ -481,9 +426,9 @@ private fun DebugItemSelectedPreview() { uuid = "5", messageType = "TextMessage", formattedReceivedDate = "9/27/20, 8:04:20 PM", - logMessage = "This is a selected log item with larger font sizes for better readability." + logMessage = "This is a selected log item with larger font sizes for better readability.", ), - isSelected = true + isSelected = true, ) } } @@ -492,26 +437,15 @@ private fun DebugItemSelectedPreview() { @Composable private fun DebugMenuActionsPreview() { AppTheme { - Row( - modifier = Modifier.padding(16.dp) - ) { - IconButton( - onClick = { /* Preview only */ }, - modifier = Modifier.padding(4.dp) - ) { + Row(modifier = Modifier.padding(16.dp)) { + IconButton(onClick = { /* Preview only */ }, modifier = Modifier.padding(4.dp)) { Icon( imageVector = Icons.Outlined.FileDownload, - contentDescription = stringResource(id = R.string.debug_logs_export) + contentDescription = stringResource(id = R.string.debug_logs_export), ) } - IconButton( - onClick = { /* Preview only */ }, - modifier = Modifier.padding(4.dp) - ) { - Icon( - imageVector = Icons.Default.Delete, - contentDescription = stringResource(id = R.string.debug_clear) - ) + IconButton(onClick = { /* Preview only */ }, modifier = Modifier.padding(4.dp)) { + Icon(imageVector = Icons.Default.Delete, contentDescription = stringResource(id = R.string.debug_clear)) } } } @@ -523,50 +457,33 @@ private fun DebugMenuActionsPreview() { private fun DebugScreenEmptyPreview() { AppTheme { Surface { - LazyColumn( - modifier = Modifier.fillMaxSize() - ) { + LazyColumn(modifier = Modifier.fillMaxSize()) { stickyHeader { - Surface( - modifier = Modifier - .fillMaxWidth() - .padding(8.dp) - ) { - Column( - modifier = Modifier.padding(8.dp) - ) { + Surface(modifier = Modifier.fillMaxWidth().padding(8.dp)) { + Column(modifier = Modifier.padding(8.dp)) { Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically + verticalAlignment = Alignment.CenterVertically, ) { Row( modifier = Modifier.weight(1f), horizontalArrangement = Arrangement.Start, - verticalAlignment = Alignment.CenterVertically + verticalAlignment = Alignment.CenterVertically, ) { OutlinedTextField( value = "", - onValueChange = { }, - modifier = Modifier - .weight(1f) - .padding(end = 8.dp), + onValueChange = {}, + modifier = Modifier.weight(1f).padding(end = 8.dp), placeholder = { Text("Search in logs...") }, - singleLine = true + singleLine = true, ) - TextButton( - onClick = { } - ) { - Row( - verticalAlignment = Alignment.CenterVertically - ) { - Text( - text = "Filters", - style = TextStyle(fontWeight = FontWeight.Bold) - ) + TextButton(onClick = {}) { + Row(verticalAlignment = Alignment.CenterVertically) { + Text(text = "Filters", style = TextStyle(fontWeight = FontWeight.Bold)) Icon( imageVector = Icons.TwoTone.FilterAltOff, - contentDescription = stringResource(id = R.string.debug_filters) + contentDescription = stringResource(id = R.string.debug_filters), ) } } @@ -577,29 +494,16 @@ private fun DebugScreenEmptyPreview() { } // Empty state item { - Box( - modifier = Modifier - .fillMaxWidth() - .padding(32.dp), - contentAlignment = Alignment.Center - ) { - Column( - horizontalAlignment = Alignment.CenterHorizontally - ) { + Box(modifier = Modifier.fillMaxWidth().padding(32.dp), contentAlignment = Alignment.Center) { + Column(horizontalAlignment = Alignment.CenterHorizontally) { Text( text = "No Debug Logs", - style = TextStyle( - fontSize = 18.sp, - fontWeight = FontWeight.Bold - ) + style = TextStyle(fontSize = 18.sp, fontWeight = FontWeight.Bold), ) Text( text = "Debug logs will appear here when available", - style = TextStyle( - fontSize = 14.sp, - color = Color.Gray - ), - modifier = Modifier.padding(top = 8.dp) + style = TextStyle(fontSize = 14.sp, color = Color.Gray), + modifier = Modifier.padding(top = 8.dp), ) } } @@ -614,12 +518,14 @@ private fun DebugScreenEmptyPreview() { @Suppress("detekt:LongMethod") // big preview private fun DebugScreenWithSampleDataPreview() { AppTheme { - val sampleLogs = listOf( - UiMeshLog( - uuid = "1", - messageType = "NodeInfo", - formattedReceivedDate = "9/27/20, 8:00:58 PM", - logMessage = "from: 2885173132\n" + + val sampleLogs = + listOf( + UiMeshLog( + uuid = "1", + messageType = "NodeInfo", + formattedReceivedDate = "9/27/20, 8:00:58 PM", + logMessage = + "from: 2885173132\n" + "decoded {\n" + " position {\n" + " altitude: 60\n" + @@ -633,100 +539,74 @@ private fun DebugScreenWithSampleDataPreview() { "id: 1737414295\n" + "rx_snr: 9.5\n" + "rx_time: 316400569\n" + - "to: -1409790708" - ), - UiMeshLog( - uuid = "2", - messageType = "TextMessage", - formattedReceivedDate = "9/27/20, 8:01:15 PM", - logMessage = "Hello from node (!a1b2c3d4)! How's the weather today?" - ), - UiMeshLog( - uuid = "3", - messageType = "Position", - formattedReceivedDate = "9/27/20, 8:02:30 PM", - logMessage = "Position update: 40.7128, -74.0060, altitude: 100m, battery: 85%" - ), - UiMeshLog( - uuid = "4", - messageType = "Waypoint", - formattedReceivedDate = "9/27/20, 8:03:45 PM", - logMessage = "New waypoint created: 'Meeting Point' at 40.7589, -73.9851" - ), - UiMeshLog( - uuid = "5", - messageType = "Error", - formattedReceivedDate = "9/27/20, 8:04:20 PM", - logMessage = "Connection timeout - retrying in 5 seconds..." + "to: -1409790708", + ), + UiMeshLog( + uuid = "2", + messageType = "TextMessage", + formattedReceivedDate = "9/27/20, 8:01:15 PM", + logMessage = "Hello from node (!a1b2c3d4)! How's the weather today?", + ), + UiMeshLog( + uuid = "3", + messageType = "Position", + formattedReceivedDate = "9/27/20, 8:02:30 PM", + logMessage = "Position update: 40.7128, -74.0060, altitude: 100m, battery: 85%", + ), + UiMeshLog( + uuid = "4", + messageType = "Waypoint", + formattedReceivedDate = "9/27/20, 8:03:45 PM", + logMessage = "New waypoint created: 'Meeting Point' at 40.7589, -73.9851", + ), + UiMeshLog( + uuid = "5", + messageType = "Error", + formattedReceivedDate = "9/27/20, 8:04:20 PM", + logMessage = "Connection timeout - retrying in 5 seconds...", + ), ) - ) // Note: This preview shows the UI structure but won't have actual data // since the ViewModel isn't injected in previews Surface { - LazyColumn( - modifier = Modifier.fillMaxSize() - ) { + LazyColumn(modifier = Modifier.fillMaxSize()) { stickyHeader { - Surface( - modifier = Modifier - .fillMaxWidth() - .padding(8.dp) - ) { - Column( - modifier = Modifier.padding(8.dp) - ) { + Surface(modifier = Modifier.fillMaxWidth().padding(8.dp)) { + Column(modifier = Modifier.padding(8.dp)) { Text( text = "Debug Screen Preview", style = TextStyle(fontWeight = FontWeight.Bold), - modifier = Modifier.padding(bottom = 8.dp) + modifier = Modifier.padding(bottom = 8.dp), ) Text( text = "Search and filter controls would appear here", - style = TextStyle(fontSize = 12.sp, color = Color.Gray) + style = TextStyle(fontSize = 12.sp, color = Color.Gray), ) } } } - items(sampleLogs) { log -> - DebugItem(log = log) - } + items(sampleLogs) { log -> DebugItem(log = log) } } } } } @Composable -fun DebugMenuActions( - viewModel: DebugViewModel = hiltViewModel(), - modifier: Modifier = Modifier, -) { +fun DebugMenuActions(viewModel: DebugViewModel = hiltViewModel(), modifier: Modifier = Modifier) { val context = LocalContext.current val scope = rememberCoroutineScope() val logs by viewModel.meshLog.collectAsStateWithLifecycle() var showDeleteLogsDialog by remember { mutableStateOf(false) } - IconButton( - onClick = { - scope.launch { - exportAllLogs(context, logs) - } - }, - modifier = modifier.padding(4.dp) - ) { + IconButton(onClick = { scope.launch { exportAllLogs(context, logs) } }, modifier = modifier.padding(4.dp)) { Icon( imageVector = Icons.Outlined.FileDownload, - contentDescription = stringResource(id = R.string.debug_logs_export) + contentDescription = stringResource(id = R.string.debug_logs_export), ) } - IconButton( - onClick = { showDeleteLogsDialog = true }, - modifier = modifier.padding(4.dp) - ) { - Icon( - imageVector = Icons.Default.Delete, - contentDescription = stringResource(id = R.string.debug_clear) - ) + IconButton(onClick = { showDeleteLogsDialog = true }, modifier = modifier.padding(4.dp)) { + Icon(imageVector = Icons.Default.Delete, contentDescription = stringResource(id = R.string.debug_clear)) } if (showDeleteLogsDialog) { SimpleAlertDialog( @@ -736,7 +616,7 @@ fun DebugMenuActions( showDeleteLogsDialog = false viewModel.deleteAllLogs() }, - onDismiss = { showDeleteLogsDialog = false } + onDismiss = { showDeleteLogsDialog = false }, ) } } @@ -767,28 +647,16 @@ private suspend fun exportAllLogs(context: Context, logs: List) = wit // Notify user of success withContext(Dispatchers.Main) { - Toast.makeText( - context, - "Logs exported to ${logFile.absolutePath}", - Toast.LENGTH_LONG - ).show() + Toast.makeText(context, "Logs exported to ${logFile.absolutePath}", Toast.LENGTH_LONG).show() } } catch (e: SecurityException) { withContext(Dispatchers.Main) { - Toast.makeText( - context, - "Permission denied: Cannot write to Downloads folder", - Toast.LENGTH_LONG - ).show() + Toast.makeText(context, "Permission denied: Cannot write to Downloads folder", Toast.LENGTH_LONG).show() warn("Error:SecurityException: " + e.toString()) } } catch (e: IOException) { withContext(Dispatchers.Main) { - Toast.makeText( - context, - "Failed to write log file: ${e.message}", - Toast.LENGTH_LONG - ).show() + Toast.makeText(context, "Failed to write log file: ${e.message}", Toast.LENGTH_LONG).show() } warn("Error:IOException: " + e.toString()) } @@ -800,42 +668,31 @@ private fun DecodedPayloadBlock( isSelected: Boolean, colorScheme: ColorScheme, searchText: String = "", - modifier: Modifier = Modifier + modifier: Modifier = Modifier, ) { - - val commonTextStyle = TextStyle( - fontSize = if (isSelected) 10.sp else 8.sp, - fontWeight = FontWeight.Bold, - color = colorScheme.primary - ) + val commonTextStyle = + TextStyle(fontSize = if (isSelected) 10.sp else 8.sp, fontWeight = FontWeight.Bold, color = colorScheme.primary) Column(modifier = modifier) { Text( text = stringResource(id = R.string.debug_decoded_payload), style = commonTextStyle, - modifier = Modifier.padding(top = 8.dp, bottom = 4.dp) - ) - Text( - text = "{", - style = commonTextStyle, - modifier = Modifier.padding(start = 8.dp, bottom = 2.dp) + modifier = Modifier.padding(top = 8.dp, bottom = 4.dp), ) + Text(text = "{", style = commonTextStyle, modifier = Modifier.padding(start = 8.dp, bottom = 2.dp)) val annotatedPayload = rememberAnnotatedDecodedPayload(decodedPayload, searchText, colorScheme) Text( text = annotatedPayload, softWrap = true, - style = TextStyle( + style = + TextStyle( fontSize = if (isSelected) 10.sp else 8.sp, fontFamily = FontFamily.Monospace, - color = colorScheme.onSurface.copy(alpha = 0.8f) + color = colorScheme.onSurface.copy(alpha = 0.8f), ), - modifier = Modifier.padding(start = 16.dp, bottom = 0.dp) - ) - Text( - text = "}", - style = commonTextStyle, - modifier = Modifier.padding(start = 8.dp, bottom = 4.dp) + modifier = Modifier.padding(start = 16.dp, bottom = 0.dp), ) + Text(text = "}", style = commonTextStyle, modifier = Modifier.padding(start = 8.dp, bottom = 4.dp)) } } @@ -843,23 +700,16 @@ private fun DecodedPayloadBlock( private fun rememberAnnotatedDecodedPayload( decodedPayload: String, searchText: String, - colorScheme: ColorScheme + colorScheme: ColorScheme, ): AnnotatedString { - val highlightStyle = SpanStyle( - background = colorScheme.primary.copy(alpha = 0.3f), - color = colorScheme.onSurface - ) + val highlightStyle = SpanStyle(background = colorScheme.primary.copy(alpha = 0.3f), color = colorScheme.onSurface) return remember(decodedPayload, searchText) { buildAnnotatedString { append(decodedPayload) if (searchText.isNotEmpty()) { searchText.split(" ").forEach { term -> Regex(Regex.escape(term), RegexOption.IGNORE_CASE).findAll(decodedPayload).forEach { match -> - addStyle( - style = highlightStyle, - start = match.range.first, - end = match.range.last + 1 - ) + addStyle(style = highlightStyle, start = match.range.first, end = match.range.last + 1) } } }