From c70b0d512a46ee256203616a71431ca12a84d6b3 Mon Sep 17 00:00:00 2001 From: andrekir Date: Tue, 19 Nov 2024 10:43:17 -0300 Subject: [PATCH] fix: remove `SelectionContainer` from `NodeItem` Removes `SelectionContainer` from `LazyColumn` items causing a crash when calculating positions between nodes that are no longer part of the same layout hierarchy, resulting in: Fatal Exception: java.lang.IllegalArgumentException: layouts are not part of the same hierarchy at androidx.compose.ui.node.NodeCoordinator.findCommonAncestor$ui_release(NodeCoordinator.kt:1210) ... closes #1408 --- .../java/com/geeksville/mesh/ui/NodeItem.kt | 307 +++++++++--------- 1 file changed, 148 insertions(+), 159 deletions(-) diff --git a/app/src/main/java/com/geeksville/mesh/ui/NodeItem.kt b/app/src/main/java/com/geeksville/mesh/ui/NodeItem.kt index 012a92668..23bb0c5fd 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/NodeItem.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/NodeItem.kt @@ -19,8 +19,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.wrapContentSize -import androidx.compose.foundation.text.selection.DisableSelection -import androidx.compose.foundation.text.selection.SelectionContainer import androidx.compose.material.Card import androidx.compose.material.Chip import androidx.compose.material.ChipDefaults @@ -134,178 +132,169 @@ fun NodeItem( onClick = { showDetails(!detailsShown) }, ) { Surface { - SelectionContainer { - Column( + Column( + modifier = Modifier + .fillMaxWidth() + .padding(8.dp) + .background(bgColor), + ) { + Row( modifier = Modifier - .fillMaxWidth() - .padding(8.dp) - .background(bgColor) + .fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, ) { + var menuExpanded by remember { mutableStateOf(false) } + Box( + modifier = Modifier.wrapContentSize(Alignment.TopStart), + ) { + Chip( + modifier = Modifier + .width(IntrinsicSize.Min) + .defaultMinSize(minHeight = 32.dp, minWidth = 72.dp), + colors = ChipDefaults.chipColors( + backgroundColor = Color(nodeColor), + contentColor = Color(textColor), + ), + onClick = { + menuExpanded = !menuExpanded + }, + ) { + Text( + modifier = Modifier.fillMaxWidth(), + text = thatNode.user.shortName.ifEmpty { "???" }, + fontWeight = FontWeight.Normal, + fontSize = MaterialTheme.typography.button.fontSize, + textDecoration = TextDecoration.LineThrough.takeIf { isIgnored }, + textAlign = TextAlign.Center, + ) + } + NodeMenu( + node = thatNode, + ignoreIncomingList = ignoreIncomingList, + isThisNode = isThisNode, + onMenuItemAction = menuItemActionClicked, + expanded = menuExpanded, + onDismissRequest = { menuExpanded = false }, + isConnected = isConnected, + ) + } + NodeKeyStatusIcon( + hasPKC = thatNode.hasPKC, + mismatchKey = thatNode.mismatchKey, + modifier = Modifier.size(32.dp) + ) { showEncryptionDialog = true } + Text( + modifier = Modifier.weight(1f), + text = longName, + style = style, + textDecoration = TextDecoration.LineThrough.takeIf { isIgnored }, + softWrap = true, + ) + + LastHeardInfo( + lastHeard = thatNode.lastHeard, + currentTimeMillis = currentTimeMillis + ) + } + Row( + modifier = Modifier + .fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + ) { + if (distance != null) { + Text( + text = distance, + fontSize = MaterialTheme.typography.button.fontSize, + ) + } else { + Spacer(modifier = Modifier.width(16.dp)) + } + BatteryInfo( + batteryLevel = thatNode.batteryLevel, + voltage = thatNode.voltage + ) + } + Spacer(modifier = Modifier.height(4.dp)) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + ) { + signalInfo( + node = thatNode, + isThisNode = isThisNode + ) + thatNode.validPosition?.let { position -> + val satCount = position.satsInView + if (satCount > 0) { + SatelliteCountInfo(satCount = satCount) + } + } + } + Spacer(modifier = Modifier.height(4.dp)) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + ) { + val telemetryString = thatNode.getTelemetryString(tempInFahrenheit) + if (telemetryString.isNotEmpty()) { + Text( + text = telemetryString, + color = MaterialTheme.colors.onSurface, + fontSize = MaterialTheme.typography.button.fontSize, + ) + } + } + + if (detailsShown || expanded) { + Spacer(modifier = Modifier.height(8.dp)) + Divider() + Spacer(modifier = Modifier.height(8.dp)) Row( modifier = Modifier .fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween, ) { - var menuExpanded by remember { mutableStateOf(false) } - Box( - modifier = Modifier.wrapContentSize(Alignment.TopStart) - ) { - Chip( - modifier = Modifier - .width(IntrinsicSize.Min) - .defaultMinSize(minHeight = 32.dp, minWidth = 72.dp), - colors = ChipDefaults.chipColors( - backgroundColor = Color(nodeColor), - contentColor = Color(textColor) - ), - onClick = { - menuExpanded = !menuExpanded - }, - content = { - Text( - modifier = Modifier.fillMaxWidth(), - text = thatNode.user.shortName.ifEmpty { "???" }, - fontWeight = FontWeight.Normal, - fontSize = MaterialTheme.typography.button.fontSize, - textDecoration = TextDecoration.LineThrough.takeIf { - ignoreIncomingList.contains(thatNode.num) - }, - textAlign = TextAlign.Center, - ) - }, - ) - NodeMenu( - node = thatNode, - ignoreIncomingList = ignoreIncomingList, - isThisNode = isThisNode, - onMenuItemAction = menuItemActionClicked, - expanded = menuExpanded, - onDismissRequest = { menuExpanded = false }, - isConnected = isConnected, + thatNode.validPosition?.let { + LinkedCoordinates( + latitude = thatNode.latitude, + longitude = thatNode.longitude, + format = gpsFormat, + nodeName = longName ) } - NodeKeyStatusIcon( - hasPKC = thatNode.hasPKC, - mismatchKey = thatNode.mismatchKey, - modifier = Modifier.size(32.dp) - ) { showEncryptionDialog = true } + thatNode.validPosition?.let { position -> + ElevationInfo( + altitude = position.altitude, + system = system, + suffix = stringResource(id = R.string.elevation_suffix) + ) + } + } + Spacer(modifier = Modifier.height(4.dp)) + Row( + modifier = Modifier.fillMaxWidth(), + ) { Text( modifier = Modifier.weight(1f), - text = longName, + text = hwInfoString, + fontSize = MaterialTheme.typography.button.fontSize, style = style, - textDecoration = TextDecoration.LineThrough.takeIf { isIgnored }, - softWrap = true, ) - - LastHeardInfo( - lastHeard = thatNode.lastHeard, - currentTimeMillis = currentTimeMillis + Text( + modifier = Modifier.weight(1f), + text = roleName, + textAlign = TextAlign.Center, + fontSize = MaterialTheme.typography.button.fontSize, + style = style, ) - } - Row( - modifier = Modifier - .fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween - ) { - if (distance != null) { - Text( - text = distance, - fontSize = MaterialTheme.typography.button.fontSize, - ) - } else { - Spacer(modifier = Modifier.width(16.dp)) - } - BatteryInfo( - batteryLevel = thatNode.batteryLevel, - voltage = thatNode.voltage + Text( + modifier = Modifier.weight(1f), + text = thatNode.user.id.ifEmpty { "???" }, + textAlign = TextAlign.End, + fontSize = MaterialTheme.typography.button.fontSize, + style = style, ) } - Spacer(modifier = Modifier.height(4.dp)) - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween - ) { - signalInfo( - node = thatNode, - isThisNode = isThisNode - ) - thatNode.validPosition?.let { position -> - val satCount = position.satsInView - if (satCount > 0) { - SatelliteCountInfo( - satCount = satCount - ) - } - } - } - Spacer(modifier = Modifier.height(4.dp)) - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween - ) { - val telemetryString = thatNode.getTelemetryString(tempInFahrenheit) - if (telemetryString.isNotEmpty()) { - Text( - text = telemetryString, - color = MaterialTheme.colors.onSurface, - fontSize = MaterialTheme.typography.button.fontSize - ) - } - } - - if (detailsShown || expanded) { - Spacer(modifier = Modifier.height(8.dp)) - Divider() - Spacer(modifier = Modifier.height(8.dp)) - Row( - modifier = Modifier - .fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween - ) { - thatNode.validPosition?.let { - DisableSelection { - LinkedCoordinates( - latitude = thatNode.latitude, - longitude = thatNode.longitude, - format = gpsFormat, - nodeName = longName - ) - } - } - thatNode.validPosition?.let { position -> - ElevationInfo( - altitude = position.altitude, - system = system, - suffix = stringResource(id = R.string.elevation_suffix) - ) - } - } - Spacer(modifier = Modifier.height(4.dp)) - Row( - modifier = Modifier.fillMaxWidth(), - ) { - Text( - modifier = Modifier.weight(1f), - text = hwInfoString, - fontSize = MaterialTheme.typography.button.fontSize, - style = style, - ) - Text( - modifier = Modifier.weight(1f), - text = roleName, - textAlign = TextAlign.Center, - fontSize = MaterialTheme.typography.button.fontSize, - style = style, - ) - Text( - modifier = Modifier.weight(1f), - text = thatNode.user.id.ifEmpty { "???" }, - textAlign = TextAlign.End, - fontSize = MaterialTheme.typography.button.fontSize, - style = style, - ) - } - } } } }