diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 1bcfa30ed..7c56194b4 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -197,6 +197,7 @@ dependencies {
implementation(projects.core.strings)
implementation(projects.core.ui)
implementation(projects.feature.map)
+ implementation(projects.feature.node)
// Bundles
implementation(libs.bundles.markdown)
diff --git a/app/detekt-baseline.xml b/app/detekt-baseline.xml
index 9ac0d78c3..52110d240 100644
--- a/app/detekt-baseline.xml
+++ b/app/detekt-baseline.xml
@@ -1,4 +1,4 @@
-
+
@@ -6,7 +6,7 @@
CommentSpacing:Constants.kt$/// a bool true means we expect this condition to continue until, false means device might come back
CommentSpacing:Coroutines.kt$/// Wrap launch with an exception handler, FIXME, move into a utility lib
CommentWrapping:SignalMetrics.kt$Metric.SNR$/* Selected 12 as the max to get 4 equal vertical sections. */
- ComposableNaming:NodeDetail.kt$notesSection
+ ComposableNaming:NodeDetailScreen.kt$notesSection
ComposableParamOrder:ChannelSettingsItemList.kt$ChannelSettingsItemList
ComposableParamOrder:Debug.kt$DebugMenuActions
ComposableParamOrder:Debug.kt$DecodedPayloadBlock
@@ -14,15 +14,12 @@
ComposableParamOrder:DebugSearch.kt$DebugSearchStateviewModelDefaults
ComposableParamOrder:DeviceMetrics.kt$DeviceMetricsChart
ComposableParamOrder:EditBase64Preference.kt$EditBase64Preference
- ComposableParamOrder:ElevationInfo.kt$ElevationInfo
ComposableParamOrder:EmptyStateContent.kt$EmptyStateContent
ComposableParamOrder:EnvironmentCharts.kt$ChartContent
ComposableParamOrder:EnvironmentCharts.kt$EnvironmentMetricsChart
ComposableParamOrder:EnvironmentCharts.kt$MetricPlottingCanvas
ComposableParamOrder:HostMetricsLog.kt$HostMetricsItem
ComposableParamOrder:HostMetricsLog.kt$LogLine
- ComposableParamOrder:LastHeardInfo.kt$LastHeardInfo
- ComposableParamOrder:LinkedCoordinates.kt$LinkedCoordinates
ComposableParamOrder:MainAppBar.kt$MainAppBar
ComposableParamOrder:MapReportingPreference.kt$MapReportingPreference
ComposableParamOrder:Message.kt$MessageScreen
@@ -32,24 +29,16 @@
ComposableParamOrder:MessageItem.kt$MessageItem
ComposableParamOrder:MessageList.kt$DeliveryInfo
ComposableParamOrder:MessageList.kt$MessageList
- ComposableParamOrder:NodeChip.kt$NodeChip
- ComposableParamOrder:NodeDetail.kt$DeviceActions
- ComposableParamOrder:NodeDetail.kt$EnvironmentMetrics
- ComposableParamOrder:NodeDetail.kt$NodeActionButton
- ComposableParamOrder:NodeDetail.kt$NodeDetailList
- ComposableParamOrder:NodeFilterTextField.kt$NodeFilterTextField
- ComposableParamOrder:NodeItem.kt$NodeItem
- ComposableParamOrder:NodeKeyStatusIcon.kt$NodeKeyStatusIcon
+ ComposableParamOrder:NodeDetailScreen.kt$DeviceActions
+ ComposableParamOrder:NodeDetailScreen.kt$EnvironmentMetrics
+ ComposableParamOrder:NodeDetailScreen.kt$NodeActionButton
+ ComposableParamOrder:NodeDetailScreen.kt$NodeDetailList
ComposableParamOrder:PaxMetrics.kt$PaxMetricsChart
ComposableParamOrder:PermissionScreenLayout.kt$PermissionScreenLayout
ComposableParamOrder:PowerMetrics.kt$PowerMetricsChart
ComposableParamOrder:QuickChat.kt$OutlinedTextFieldWithCounter
- ComposableParamOrder:SatelliteCountInfo.kt$SatelliteCountInfo
- ComposableParamOrder:SettingsItem.kt$SettingsItem
- ComposableParamOrder:SignalInfo.kt$SignalInfo
ComposableParamOrder:SignalMetrics.kt$SignalMetricsChart
ComposableParamOrder:TopLevelNavIcon.kt$ConnectionsNavIcon
- ComposableParamOrder:TracerouteButton.kt$TracerouteButton
ComposableParamOrder:WarningDialog.kt$WarningDialog
CyclomaticComplexMethod:MeshService.kt$MeshService$private fun handleReceivedData(packet: MeshPacket)
CyclomaticComplexMethod:NetworkConfigItemList.kt$@Composable fun NetworkConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel())
@@ -57,7 +46,7 @@
CyclomaticComplexMethod:RadioConfigViewModel.kt$RadioConfigViewModel$private fun processPacketResponse(packet: MeshProtos.MeshPacket)
EmptyClassBlock:DebugLogFile.kt$BinaryLogFile${ }
EmptyFunctionBlock:NopInterface.kt$NopInterface${ }
- EmptyFunctionBlock:NsdManager.kt$<no name provided>${ }
+ EmptyFunctionBlock:NsdManager.kt$<no name provided>${ }
EmptyFunctionBlock:TrustAllX509TrustManager.kt$TrustAllX509TrustManager${}
FinalNewline:BLEException.kt$com.geeksville.mesh.service.BLEException.kt
FinalNewline:BluetoothInterfaceFactory.kt$com.geeksville.mesh.repository.radio.BluetoothInterfaceFactory.kt
@@ -84,8 +73,8 @@
LambdaParameterEventTrailing:Message.kt$onClick
LambdaParameterEventTrailing:Message.kt$onSendMessage
LambdaParameterEventTrailing:MessageList.kt$onReply
- LambdaParameterEventTrailing:NodeDetail.kt$onClick
- LambdaParameterEventTrailing:NodeDetail.kt$onSaveNotes
+ LambdaParameterEventTrailing:NodeDetailScreen.kt$onClick
+ LambdaParameterEventTrailing:NodeDetailScreen.kt$onSaveNotes
LambdaParameterInRestartableEffect:Channel.kt$onConfirm
LambdaParameterInRestartableEffect:MessageList.kt$onUnreadChanged
LargeClass:MeshService.kt$MeshService : Service
@@ -145,7 +134,7 @@
MagicNumber:SafeBluetooth.kt$SafeBluetooth$100
MagicNumber:SafeBluetooth.kt$SafeBluetooth$1000
MagicNumber:SafeBluetooth.kt$SafeBluetooth$2500
- MagicNumber:SafeBluetooth.kt$SafeBluetooth.<no name provided>$2500
+ MagicNumber:SafeBluetooth.kt$SafeBluetooth.<no name provided>$2500
MagicNumber:SerialConnectionImpl.kt$SerialConnectionImpl$115200
MagicNumber:SerialConnectionImpl.kt$SerialConnectionImpl$200
MagicNumber:ServiceClient.kt$ServiceClient$500
@@ -158,7 +147,7 @@
MagicNumber:TCPInterface.kt$TCPInterface$500
MagicNumber:UIState.kt$4
MatchingDeclarationName:MeshServiceStarter.kt$ServiceStarter : Worker
- MaxLineLength:BluetoothInterface.kt$/* Info for the esp32 device side code. See that source for the 'gold' standard docs on this interface. MeshBluetoothService UUID 6ba1b218-15a8-461f-9fa8-5dcae273eafd FIXME - notify vs indication for fromradio output. Using notify for now, not sure if that is best FIXME - in the esp32 mesh management code, occasionally mirror the current net db to flash, so that if we reboot we still have a good guess of users who are out there. FIXME - make sure this protocol is guaranteed robust and won't drop packets "According to the BLE specification the notification length can be max ATT_MTU - 3. The 3 bytes subtracted is the 3-byte header(OP-code (operation, 1 byte) and the attribute handle (2 bytes)). In BLE 4.1 the ATT_MTU is 23 bytes (20 bytes for payload), but in BLE 4.2 the ATT_MTU can be negotiated up to 247 bytes." MAXPACKET is 256? look into what the lora lib uses. FIXME Characteristics: UUID properties description 8ba2bcc2-ee02-4a55-a531-c525c5e454d5 read fromradio - contains a newly received packet destined towards the phone (up to MAXPACKET bytes? per packet). After reading the esp32 will put the next packet in this mailbox. If the FIFO is empty it will put an empty packet in this mailbox. f75c76d2-129e-4dad-a1dd-7866124401e7 write toradio - write ToRadio protobufs to this charstic to send them (up to MAXPACKET len) ed9da18c-a800-4f66-a670-aa7547e34453 read|notify|write fromnum - the current packet # in the message waiting inside fromradio, if the phone sees this notify it should read messages until it catches up with this number. The phone can write to this register to go backwards up to FIXME packets, to handle the rare case of a fromradio packet was dropped after the esp32 callback was called, but before it arrives at the phone. If the phone writes to this register the esp32 will discard older packets and put the next packet >= fromnum in fromradio. When the esp32 advances fromnum, it will delay doing the notify by 100ms, in the hopes that the notify will never actally need to be sent if the phone is already pulling from fromradio. Note: that if the phone ever sees this number decrease, it means the esp32 has rebooted. Re: queue management Not all messages are kept in the fromradio queue (filtered based on SubPacket): * only the most recent Position and User messages for a particular node are kept * all Data SubPackets are kept * No WantNodeNum / DenyNodeNum messages are kept A variable keepAllPackets, if set to true will suppress this behavior and instead keep everything for forwarding to the phone (for debugging) */
+ MaxLineLength:BluetoothInterface.kt$/* Info for the esp32 device side code. See that source for the 'gold' standard docs on this interface. MeshBluetoothService UUID 6ba1b218-15a8-461f-9fa8-5dcae273eafd FIXME - notify vs indication for fromradio output. Using notify for now, not sure if that is best FIXME - in the esp32 mesh management code, occasionally mirror the current net db to flash, so that if we reboot we still have a good guess of users who are out there. FIXME - make sure this protocol is guaranteed robust and won't drop packets "According to the BLE specification the notification length can be max ATT_MTU - 3. The 3 bytes subtracted is the 3-byte header(OP-code (operation, 1 byte) and the attribute handle (2 bytes)). In BLE 4.1 the ATT_MTU is 23 bytes (20 bytes for payload), but in BLE 4.2 the ATT_MTU can be negotiated up to 247 bytes." MAXPACKET is 256? look into what the lora lib uses. FIXME Characteristics: UUID properties description 8ba2bcc2-ee02-4a55-a531-c525c5e454d5 read fromradio - contains a newly received packet destined towards the phone (up to MAXPACKET bytes? per packet). After reading the esp32 will put the next packet in this mailbox. If the FIFO is empty it will put an empty packet in this mailbox. f75c76d2-129e-4dad-a1dd-7866124401e7 write toradio - write ToRadio protobufs to this charstic to send them (up to MAXPACKET len) ed9da18c-a800-4f66-a670-aa7547e34453 read|notify|write fromnum - the current packet # in the message waiting inside fromradio, if the phone sees this notify it should read messages until it catches up with this number. The phone can write to this register to go backwards up to FIXME packets, to handle the rare case of a fromradio packet was dropped after the esp32 callback was called, but before it arrives at the phone. If the phone writes to this register the esp32 will discard older packets and put the next packet >= fromnum in fromradio. When the esp32 advances fromnum, it will delay doing the notify by 100ms, in the hopes that the notify will never actally need to be sent if the phone is already pulling from fromradio. Note: that if the phone ever sees this number decrease, it means the esp32 has rebooted. Re: queue management Not all messages are kept in the fromradio queue (filtered based on SubPacket): * only the most recent Position and User messages for a particular node are kept * all Data SubPackets are kept * No WantNodeNum / DenyNodeNum messages are kept A variable keepAllPackets, if set to true will suppress this behavior and instead keep everything for forwarding to the phone (for debugging) */
ModifierClickableOrder:Channel.kt$clickable(onClick = onClick)
ModifierMissing:BLEDevices.kt$BLEDevices
ModifierMissing:Channel.kt$ChannelScreen
@@ -185,8 +174,7 @@
ModifierMissing:MessageActions.kt$ReplyButton
ModifierMissing:NetworkConfigItemList.kt$NetworkConfigScreen
ModifierMissing:NetworkDevices.kt$NetworkDevices
- ModifierMissing:NodeScreen.kt$NodeScreen
- ModifierMissing:NodeStatusIcons.kt$NodeStatusIcons
+ ModifierMissing:NodeListScreen.kt$NodeListScreen
ModifierMissing:PaxMetrics.kt$PaxMetricsItem
ModifierMissing:PaxMetrics.kt$PaxMetricsScreen
ModifierMissing:PositionConfigItemList.kt$PositionConfigScreen
@@ -199,9 +187,6 @@
ModifierMissing:Reaction.kt$ReactionDialog
ModifierMissing:SecurityConfigItemList.kt$SecurityConfigScreen
ModifierMissing:SecurityIcon.kt$SecurityIcon
- ModifierMissing:SettingsItem.kt$SettingsItem
- ModifierMissing:SettingsItem.kt$SettingsItemDetail
- ModifierMissing:SettingsItem.kt$SettingsItemSwitch
ModifierMissing:SettingsScreen.kt$SettingsScreen
ModifierMissing:Share.kt$ShareScreen
ModifierMissing:SignalMetrics.kt$SignalMetricsScreen
@@ -217,11 +202,10 @@
ModifierNotUsedAtRoot:PowerMetrics.kt$modifier = modifier.weight(weight = Y_AXIS_WEIGHT)
ModifierNotUsedAtRoot:PowerMetrics.kt$modifier = modifier.width(dp)
ModifierNotUsedAtRoot:PowerMetrics.kt$modifier.width(dp)
- ModifierNotUsedAtRoot:SignalInfo.kt$modifier = modifier
ModifierNotUsedAtRoot:SignalMetrics.kt$modifier = modifier.weight(weight = Y_AXIS_WEIGHT)
ModifierNotUsedAtRoot:SignalMetrics.kt$modifier = modifier.width(dp)
ModifierNotUsedAtRoot:SignalMetrics.kt$modifier.width(dp)
- ModifierReused:DeviceMetrics.kt$Canvas(modifier = modifier.width(dp)) { val height = size.height val width = size.width for (i in telemetries.indices) { val telemetry = telemetries[i] /* x-value time */ val xRatio = (telemetry.time - oldest.time).toFloat() / timeDiff val x = xRatio * width /* Channel Utilization */ plotPoint( drawContext = drawContext, color = Device.CH_UTIL.color, x = x, value = telemetry.deviceMetrics.channelUtilization, divisor = MAX_PERCENT_VALUE, ) /* Air Utilization Transmit */ plotPoint( drawContext = drawContext, color = Device.AIR_UTIL.color, x = x, value = telemetry.deviceMetrics.airUtilTx, divisor = MAX_PERCENT_VALUE, ) } /* Battery Line */ var index = 0 while (index < telemetries.size) { val path = Path() index = createPath( telemetries = telemetries, index = index, path = path, oldestTime = oldest.time, timeRange = timeDiff, width = width, timeThreshold = selectedTime.timeThreshold(), ) { i -> val telemetry = telemetries.getOrNull(i) ?: telemetries.last() val ratio = telemetry.deviceMetrics.batteryLevel / MAX_PERCENT_VALUE val y = height - (ratio * height) return@createPath y } drawPath( path = path, color = Device.BATTERY.color, style = Stroke(width = GraphUtil.RADIUS, cap = StrokeCap.Round), ) } }
+ ModifierReused:DeviceMetrics.kt$Canvas(modifier = modifier.width(dp)) { val height = size.height val width = size.width for (i in telemetries.indices) { val telemetry = telemetries[i] /* x-value time */ val xRatio = (telemetry.time - oldest.time).toFloat() / timeDiff val x = xRatio * width /* Channel Utilization */ plotPoint( drawContext = drawContext, color = Device.CH_UTIL.color, x = x, value = telemetry.deviceMetrics.channelUtilization, divisor = MAX_PERCENT_VALUE, ) /* Air Utilization Transmit */ plotPoint( drawContext = drawContext, color = Device.AIR_UTIL.color, x = x, value = telemetry.deviceMetrics.airUtilTx, divisor = MAX_PERCENT_VALUE, ) } /* Battery Line */ var index = 0 while (index < telemetries.size) { val path = Path() index = createPath( telemetries = telemetries, index = index, path = path, oldestTime = oldest.time, timeRange = timeDiff, width = width, timeThreshold = selectedTime.timeThreshold(), ) { i -> val telemetry = telemetries.getOrNull(i) ?: telemetries.last() val ratio = telemetry.deviceMetrics.batteryLevel / MAX_PERCENT_VALUE val y = height - (ratio * height) return@createPath y } drawPath( path = path, color = Device.BATTERY.color, style = Stroke(width = GraphUtil.RADIUS, cap = StrokeCap.Round), ) } }
ModifierReused:DeviceMetrics.kt$HorizontalLinesOverlay( modifier.width(dp), lineColors = listOf(graphColor, Color.Yellow, Color.Red, graphColor, graphColor), )
ModifierReused:DeviceMetrics.kt$TimeAxisOverlay(modifier.width(dp), oldest = oldest.time, newest = newest.time, selectedTime.lineInterval())
ModifierReused:EnvironmentCharts.kt$Box( contentAlignment = Alignment.TopStart, modifier = modifier.horizontalScroll(state = scrollState, reverseScrolling = true), ) { HorizontalLinesOverlay(modifier.width(dp), lineColors = List(size = 5) { graphColor }) TimeAxisOverlay(modifier = modifier.width(dp), oldest = oldest, newest = newest, selectedTime.lineInterval()) MetricPlottingCanvas( modifier = modifier.width(dp), telemetries = telemetries, graphData = graphData, selectedTime = selectedTime, oldest = oldest, timeDiff = timeDiff, rightMin = rightMin, rightMax = rightMax, ) }
@@ -229,9 +213,9 @@
ModifierReused:EnvironmentCharts.kt$MetricPlottingCanvas( modifier = modifier.width(dp), telemetries = telemetries, graphData = graphData, selectedTime = selectedTime, oldest = oldest, timeDiff = timeDiff, rightMin = rightMin, rightMax = rightMax, )
ModifierReused:EnvironmentCharts.kt$TimeAxisOverlay(modifier = modifier.width(dp), oldest = oldest, newest = newest, selectedTime.lineInterval())
ModifierReused:PaxMetrics.kt$HorizontalLinesOverlay(modifier.width(dp), lineColors = List(size = 5) { Color.LightGray })
- ModifierReused:PaxMetrics.kt$Row(modifier = modifier.fillMaxWidth().fillMaxHeight(fraction = 0.33f)) { YAxisLabels( modifier = Modifier.weight(Y_AXIS_WEIGHT).fillMaxHeight().padding(start = 8.dp), labelColor = MaterialTheme.colorScheme.onSurface, minValue = minValue, maxValue = maxValue, ) Box( contentAlignment = Alignment.TopStart, modifier = Modifier.horizontalScroll(state = scrollState, reverseScrolling = true).weight(CHART_WEIGHT), ) { HorizontalLinesOverlay(modifier.width(dp), lineColors = List(size = 5) { Color.LightGray }) TimeAxisOverlay(modifier.width(dp), oldest = minTime, newest = maxTime, timeFrame.lineInterval()) Canvas(modifier = Modifier.width(dp).fillMaxHeight()) { val width = size.width val height = size.height fun xForTime(t: Int): Float = if (maxTime == minTime) width / 2 else (t - minTime).toFloat() / (maxTime - minTime) * width fun yForValue(v: Int): Float = height - (v - minValue) / (maxValue - minValue) * height fun drawLine(series: List<Pair<Int, Int>>, color: Color) { for (i in 1 until series.size) { drawLine( color = color, start = Offset(xForTime(series[i - 1].first), yForValue(series[i - 1].second)), end = Offset(xForTime(series[i].first), yForValue(series[i].second)), strokeWidth = 2.dp.toPx(), ) } } drawLine(bleSeries, PaxSeries.BLE.color) drawLine(wifiSeries, PaxSeries.WIFI.color) drawLine(totalSeries, PaxSeries.PAX.color) } } YAxisLabels( modifier = Modifier.weight(Y_AXIS_WEIGHT).fillMaxHeight().padding(end = 8.dp), labelColor = MaterialTheme.colorScheme.onSurface, minValue = minValue, maxValue = maxValue, ) }
+ ModifierReused:PaxMetrics.kt$Row(modifier = modifier.fillMaxWidth().fillMaxHeight(fraction = 0.33f)) { YAxisLabels( modifier = Modifier.weight(Y_AXIS_WEIGHT).fillMaxHeight().padding(start = 8.dp), labelColor = MaterialTheme.colorScheme.onSurface, minValue = minValue, maxValue = maxValue, ) Box( contentAlignment = Alignment.TopStart, modifier = Modifier.horizontalScroll(state = scrollState, reverseScrolling = true).weight(CHART_WEIGHT), ) { HorizontalLinesOverlay(modifier.width(dp), lineColors = List(size = 5) { Color.LightGray }) TimeAxisOverlay(modifier.width(dp), oldest = minTime, newest = maxTime, timeFrame.lineInterval()) Canvas(modifier = Modifier.width(dp).fillMaxHeight()) { val width = size.width val height = size.height fun xForTime(t: Int): Float = if (maxTime == minTime) width / 2 else (t - minTime).toFloat() / (maxTime - minTime) * width fun yForValue(v: Int): Float = height - (v - minValue) / (maxValue - minValue) * height fun drawLine(series: List<Pair<Int, Int>>, color: Color) { for (i in 1 until series.size) { drawLine( color = color, start = Offset(xForTime(series[i - 1].first), yForValue(series[i - 1].second)), end = Offset(xForTime(series[i].first), yForValue(series[i].second)), strokeWidth = 2.dp.toPx(), ) } } drawLine(bleSeries, PaxSeries.BLE.color) drawLine(wifiSeries, PaxSeries.WIFI.color) drawLine(totalSeries, PaxSeries.PAX.color) } } YAxisLabels( modifier = Modifier.weight(Y_AXIS_WEIGHT).fillMaxHeight().padding(end = 8.dp), labelColor = MaterialTheme.colorScheme.onSurface, minValue = minValue, maxValue = maxValue, ) }
ModifierReused:PaxMetrics.kt$TimeAxisOverlay(modifier.width(dp), oldest = minTime, newest = maxTime, timeFrame.lineInterval())
- ModifierReused:PowerMetrics.kt$Canvas(modifier = modifier.width(dp)) { val width = size.width val height = size.height /* Voltage */ var index = 0 while (index < telemetries.size) { val path = Path() index = createPath( telemetries = telemetries, index = index, path = path, oldestTime = oldest.time, timeRange = timeDiff, width = width, timeThreshold = selectedTime.timeThreshold(), ) { i -> val telemetry = telemetries.getOrNull(i) ?: telemetries.last() val ratio = (retrieveVoltage(selectedChannel, telemetry) - voltageMin) / voltageDiff val y = height - (ratio * height) return@createPath y } drawPath( path = path, color = VOLTAGE_COLOR, style = Stroke(width = GraphUtil.RADIUS, cap = StrokeCap.Round), ) } /* Current */ index = 0 while (index < telemetries.size) { val path = Path() index = createPath( telemetries = telemetries, index = index, path = path, oldestTime = oldest.time, timeRange = timeDiff, width = width, timeThreshold = selectedTime.timeThreshold(), ) { i -> val telemetry = telemetries.getOrNull(i) ?: telemetries.last() val ratio = (retrieveCurrent(selectedChannel, telemetry) - Power.CURRENT.min) / currentDiff val y = height - (ratio * height) return@createPath y } drawPath( path = path, color = Power.CURRENT.color, style = Stroke(width = GraphUtil.RADIUS, cap = StrokeCap.Round), ) } }
+ ModifierReused:PowerMetrics.kt$Canvas(modifier = modifier.width(dp)) { val width = size.width val height = size.height /* Voltage */ var index = 0 while (index < telemetries.size) { val path = Path() index = createPath( telemetries = telemetries, index = index, path = path, oldestTime = oldest.time, timeRange = timeDiff, width = width, timeThreshold = selectedTime.timeThreshold(), ) { i -> val telemetry = telemetries.getOrNull(i) ?: telemetries.last() val ratio = (retrieveVoltage(selectedChannel, telemetry) - voltageMin) / voltageDiff val y = height - (ratio * height) return@createPath y } drawPath( path = path, color = VOLTAGE_COLOR, style = Stroke(width = GraphUtil.RADIUS, cap = StrokeCap.Round), ) } /* Current */ index = 0 while (index < telemetries.size) { val path = Path() index = createPath( telemetries = telemetries, index = index, path = path, oldestTime = oldest.time, timeRange = timeDiff, width = width, timeThreshold = selectedTime.timeThreshold(), ) { i -> val telemetry = telemetries.getOrNull(i) ?: telemetries.last() val ratio = (retrieveCurrent(selectedChannel, telemetry) - Power.CURRENT.min) / currentDiff val y = height - (ratio * height) return@createPath y } drawPath( path = path, color = Power.CURRENT.color, style = Stroke(width = GraphUtil.RADIUS, cap = StrokeCap.Round), ) } }
ModifierReused:PowerMetrics.kt$HorizontalLinesOverlay(modifier.width(dp), lineColors = List(size = 5) { graphColor })
ModifierReused:PowerMetrics.kt$TimeAxisOverlay(modifier.width(dp), oldest = oldest.time, newest = newest.time, selectedTime.lineInterval())
ModifierReused:PowerMetrics.kt$YAxisLabels( modifier = modifier.weight(weight = Y_AXIS_WEIGHT), Power.CURRENT.color, minValue = Power.CURRENT.min, maxValue = Power.CURRENT.max, )
@@ -247,8 +231,8 @@
MultipleEmitters:CommonCharts.kt$LegendLabel
MultipleEmitters:DeviceMetrics.kt$DeviceMetricsChart
MultipleEmitters:EnvironmentCharts.kt$EnvironmentMetricsChart
- MultipleEmitters:NodeDetail.kt$EncryptionErrorContent
- MultipleEmitters:NodeDetail.kt$MetricsSection
+ MultipleEmitters:NodeDetailScreen.kt$EncryptionErrorContent
+ MultipleEmitters:NodeDetailScreen.kt$MetricsSection
MultipleEmitters:PaxMetrics.kt$PaxMetricsChart
MultipleEmitters:PowerMetrics.kt$PowerMetricsChart
MultipleEmitters:RadioConfig.kt$RadioConfigItemList
@@ -299,28 +283,15 @@
ParameterNaming:MapReportingPreference.kt$onPublishIntervalSecsChanged
ParameterNaming:MapReportingPreference.kt$onShouldReportLocationChanged
ParameterNaming:MessageList.kt$onUnreadChanged
- ParameterNaming:NodeDetail.kt$onFirmwareSelected
- ParameterNaming:NodeFilterTextField.kt$onToggleShowIgnored
+ ParameterNaming:NodeDetailScreen.kt$onFirmwareSelected
ParameterNaming:PositionPrecisionPreference.kt$onValueChanged
ParameterNaming:UsbDevices.kt$onDeviceSelected
ParameterNaming:WelcomeScreen.kt$onGetStarted
- PreviewAnnotationNaming:LargeFontPreview.kt$LargeFontPreview$LargeFontPreview
PreviewPublic:Channel.kt$ModemPresetInfoPreview
- PreviewPublic:ElevationInfo.kt$ElevationInfoPreview
PreviewPublic:EmptyStateContent.kt$EmptyStateContentPreview
- PreviewPublic:LastHeardInfo.kt$LastHeardInfoPreview
- PreviewPublic:LinkedCoordinates.kt$LinkedCoordinatesPreview
PreviewPublic:MapReportingPreference.kt$MapReportingPreview
- PreviewPublic:NodeChip.kt$NodeChipPreview
- PreviewPublic:NodeItem.kt$NodeInfoPreview
- PreviewPublic:NodeItem.kt$NodeInfoSimplePreview
- PreviewPublic:NodeStatusIcons.kt$StatusIconsPreview
PreviewPublic:Reaction.kt$ReactionItemPreview
PreviewPublic:Reaction.kt$ReactionRowPreview
- PreviewPublic:SatelliteCountInfo.kt$SatelliteCountInfoPreview
- PreviewPublic:SignalInfo.kt$SignalInfoPreview
- PreviewPublic:SignalInfo.kt$SignalInfoSelfPreview
- PreviewPublic:SignalInfo.kt$SignalInfoSimplePreview
RethrowCaughtException:SyncContinuation.kt$Continuation$throw ex
ReturnCount:RadioConfigViewModel.kt$RadioConfigViewModel$private fun processPacketResponse(packet: MeshProtos.MeshPacket)
SwallowedException:BluetoothInterface.kt$BluetoothInterface$ex: CancellationException
@@ -339,7 +310,7 @@
TooGenericExceptionCaught:LocationRepository.kt$LocationRepository$e: Exception
TooGenericExceptionCaught:MQTTRepository.kt$MQTTRepository$ex: Exception
TooGenericExceptionCaught:MeshService.kt$MeshService$ex: Exception
- TooGenericExceptionCaught:MeshService.kt$MeshService.<no name provided>$ex: Exception
+ TooGenericExceptionCaught:MeshService.kt$MeshService.<no name provided>$ex: Exception
TooGenericExceptionCaught:MeshServiceStarter.kt$ServiceStarter$ex: Exception
TooGenericExceptionCaught:RadioConfigViewModel.kt$RadioConfigViewModel$ex: Exception
TooGenericExceptionCaught:SafeBluetooth.kt$SafeBluetooth$ex: Exception
@@ -347,29 +318,28 @@
TooGenericExceptionCaught:SyncContinuation.kt$Continuation$ex: Throwable
TooGenericExceptionCaught:TCPInterface.kt$TCPInterface$ex: Throwable
TooGenericExceptionThrown:MeshService.kt$MeshService$throw Exception("Can't set user without a NodeInfo")
- TooGenericExceptionThrown:MeshService.kt$MeshService.<no name provided>$throw Exception("Port numbers must be non-zero!")
+ TooGenericExceptionThrown:MeshService.kt$MeshService.<no name provided>$throw Exception("Port numbers must be non-zero!")
TooGenericExceptionThrown:ServiceClient.kt$ServiceClient$throw Exception("Haven't called connect")
TooGenericExceptionThrown:ServiceClient.kt$ServiceClient$throw Exception("Service not bound")
TooGenericExceptionThrown:SyncContinuation.kt$SyncContinuation$throw Exception("SyncContinuation timeout")
TooGenericExceptionThrown:SyncContinuation.kt$SyncContinuation$throw Exception("This shouldn't happen")
TooManyFunctions:BluetoothInterface.kt$BluetoothInterface : IRadioInterface
TooManyFunctions:MeshService.kt$MeshService : Service
- TooManyFunctions:MeshService.kt$MeshService$<no name provided> : Stub
+ TooManyFunctions:MeshService.kt$MeshService$<no name provided> : Stub
TooManyFunctions:MessageViewModel.kt$MessageViewModel : ViewModel
- TooManyFunctions:NodeDetail.kt$com.geeksville.mesh.ui.node.NodeDetail.kt
- TooManyFunctions:NodesViewModel.kt$NodesViewModel : ViewModel
+ TooManyFunctions:NodeDetailScreen.kt$com.geeksville.mesh.ui.node.NodeDetailScreen.kt
TooManyFunctions:RadioConfigViewModel.kt$RadioConfigViewModel : ViewModel
TooManyFunctions:RadioInterfaceService.kt$RadioInterfaceService
TooManyFunctions:SafeBluetooth.kt$SafeBluetooth : Closeable
TooManyFunctions:UIState.kt$UIViewModel : ViewModel
TopLevelPropertyNaming:Constants.kt$const val prefix = "com.geeksville.mesh"
- UnusedParameter:ChannelSettingsItemList.kt$onBack: () -> Unit
+ UnusedParameter:ChannelSettingsItemList.kt$onBack: () -> Unit
UnusedParameter:ChannelSettingsItemList.kt$title: String
UnusedParameter:DropDownPreference.kt$modifier: Modifier = Modifier
UtilityClassWithPublicConstructor:NetworkRepositoryModule.kt$NetworkRepositoryModule
ViewModelForwarding:Main.kt$ScannedQrCodeDialog(uIViewModel, newChannelSet)
ViewModelForwarding:Main.kt$VersionChecks(uIViewModel)
ViewModelInjection:DebugSearch.kt$viewModel
- Wrapping:Message.kt${ event -> when (event) { is MessageScreenEvent.SendMessage -> { viewModel.sendMessage(event.text, contactKey, event.replyingToPacketId) if (event.replyingToPacketId != null) replyingToPacketId = null messageInputState.clearText() } is MessageScreenEvent.SendReaction -> viewModel.sendReaction(event.emoji, event.messageId, contactKey) is MessageScreenEvent.DeleteMessages -> { viewModel.deleteMessages(event.ids) selectedMessageIds.value = emptySet() showDeleteDialog = false } is MessageScreenEvent.ClearUnreadCount -> viewModel.clearUnreadCount(contactKey, event.lastReadMessageId) is MessageScreenEvent.NodeDetails -> navigateToNodeDetails(event.node.num) is MessageScreenEvent.SetTitle -> viewModel.setTitle(event.title) is MessageScreenEvent.NavigateToMessages -> navigateToMessages(event.contactKey) is MessageScreenEvent.NavigateToNodeDetails -> navigateToNodeDetails(event.nodeNum) MessageScreenEvent.NavigateBack -> onNavigateBack() is MessageScreenEvent.CopyToClipboard -> { clipboardManager.nativeClipboard.setPrimaryClip(ClipData.newPlainText(event.text, event.text)) selectedMessageIds.value = emptySet() } } }
+ Wrapping:Message.kt${ event -> when (event) { is MessageScreenEvent.SendMessage -> { viewModel.sendMessage(event.text, contactKey, event.replyingToPacketId) if (event.replyingToPacketId != null) replyingToPacketId = null messageInputState.clearText() } is MessageScreenEvent.SendReaction -> viewModel.sendReaction(event.emoji, event.messageId, contactKey) is MessageScreenEvent.DeleteMessages -> { viewModel.deleteMessages(event.ids) selectedMessageIds.value = emptySet() showDeleteDialog = false } is MessageScreenEvent.ClearUnreadCount -> viewModel.clearUnreadCount(contactKey, event.lastReadMessageId) is MessageScreenEvent.NodeDetails -> navigateToNodeDetails(event.node.num) is MessageScreenEvent.SetTitle -> viewModel.setTitle(event.title) is MessageScreenEvent.NavigateToMessages -> navigateToMessages(event.contactKey) is MessageScreenEvent.NavigateToNodeDetails -> navigateToNodeDetails(event.nodeNum) MessageScreenEvent.NavigateBack -> onNavigateBack() is MessageScreenEvent.CopyToClipboard -> { clipboardManager.nativeClipboard.setPrimaryClip(ClipData.newPlainText(event.text, event.text)) selectedMessageIds.value = emptySet() } } }
diff --git a/app/src/androidTest/java/com/geeksville/mesh/compose/MessageItemTest.kt b/app/src/androidTest/java/com/geeksville/mesh/compose/MessageItemTest.kt
index 1d1a46336..f9938dcd2 100644
--- a/app/src/androidTest/java/com/geeksville/mesh/compose/MessageItemTest.kt
+++ b/app/src/androidTest/java/com/geeksville/mesh/compose/MessageItemTest.kt
@@ -21,13 +21,13 @@ import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithContentDescription
import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.geeksville.mesh.ui.common.preview.NodePreviewParameterProvider
import com.geeksville.mesh.ui.message.components.MessageItem
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.meshtastic.core.database.model.Message
import org.meshtastic.core.model.MessageStatus
+import org.meshtastic.core.ui.component.preview.NodePreviewParameterProvider
@RunWith(AndroidJUnit4::class)
class MessageItemTest {
diff --git a/app/src/google/java/com/geeksville/mesh/ui/map/MapView.kt b/app/src/google/java/com/geeksville/mesh/ui/map/MapView.kt
index d777ef6d6..d8ad936e8 100644
--- a/app/src/google/java/com/geeksville/mesh/ui/map/MapView.kt
+++ b/app/src/google/java/com/geeksville/mesh/ui/map/MapView.kt
@@ -74,7 +74,6 @@ import com.geeksville.mesh.ui.map.components.WaypointMarkers
import com.geeksville.mesh.ui.metrics.HEADING_DEG
import com.geeksville.mesh.ui.metrics.formatPositionTime
import com.geeksville.mesh.ui.node.DEG_D
-import com.geeksville.mesh.ui.node.components.NodeChip
import com.geeksville.mesh.waypoint
import com.google.android.gms.location.LocationCallback
import com.google.android.gms.location.LocationRequest
@@ -112,6 +111,7 @@ import org.meshtastic.core.model.util.mpsToKmph
import org.meshtastic.core.model.util.mpsToMph
import org.meshtastic.core.model.util.toString
import org.meshtastic.core.strings.R
+import org.meshtastic.core.ui.component.NodeChip
import org.meshtastic.feature.map.LastHeardFilter
import org.meshtastic.feature.map.LayerType
import org.meshtastic.feature.map.LocationPermissionsHandler
diff --git a/app/src/google/java/com/geeksville/mesh/ui/map/components/ClusterItemsListDialog.kt b/app/src/google/java/com/geeksville/mesh/ui/map/components/ClusterItemsListDialog.kt
index 93b4092d7..6b87b1ed2 100644
--- a/app/src/google/java/com/geeksville/mesh/ui/map/components/ClusterItemsListDialog.kt
+++ b/app/src/google/java/com/geeksville/mesh/ui/map/components/ClusterItemsListDialog.kt
@@ -32,8 +32,8 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.geeksville.mesh.ui.map.NodeClusterItem
-import com.geeksville.mesh.ui.node.components.NodeChip
import org.meshtastic.core.strings.R
+import org.meshtastic.core.ui.component.NodeChip
@Composable
fun ClusterItemsListDialog(
diff --git a/app/src/google/java/com/geeksville/mesh/ui/map/components/NodeClusterMarkers.kt b/app/src/google/java/com/geeksville/mesh/ui/map/components/NodeClusterMarkers.kt
index 9bca72a27..f9eb7136f 100644
--- a/app/src/google/java/com/geeksville/mesh/ui/map/components/NodeClusterMarkers.kt
+++ b/app/src/google/java/com/geeksville/mesh/ui/map/components/NodeClusterMarkers.kt
@@ -21,12 +21,12 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.key
import androidx.compose.ui.graphics.Color
import com.geeksville.mesh.ui.map.NodeClusterItem
-import com.geeksville.mesh.ui.node.components.NodeChip
import com.google.maps.android.clustering.Cluster
import com.google.maps.android.clustering.view.DefaultClusterRenderer
import com.google.maps.android.compose.Circle
import com.google.maps.android.compose.MapsComposeExperimentalApi
import com.google.maps.android.compose.clustering.Clustering
+import org.meshtastic.core.ui.component.NodeChip
import org.meshtastic.feature.map.BaseMapViewModel
@OptIn(MapsComposeExperimentalApi::class)
diff --git a/app/src/main/java/com/geeksville/mesh/navigation/NodesNavigation.kt b/app/src/main/java/com/geeksville/mesh/navigation/NodesNavigation.kt
index b05be2265..c5a649617 100644
--- a/app/src/main/java/com/geeksville/mesh/navigation/NodesNavigation.kt
+++ b/app/src/main/java/com/geeksville/mesh/navigation/NodesNavigation.kt
@@ -50,8 +50,8 @@ import com.geeksville.mesh.ui.metrics.PowerMetricsScreen
import com.geeksville.mesh.ui.metrics.SignalMetricsScreen
import com.geeksville.mesh.ui.metrics.TracerouteLogScreen
import com.geeksville.mesh.ui.node.NodeDetailScreen
+import com.geeksville.mesh.ui.node.NodeListScreen
import com.geeksville.mesh.ui.node.NodeMapScreen
-import com.geeksville.mesh.ui.node.NodeScreen
import org.meshtastic.core.navigation.ContactsRoutes
import org.meshtastic.core.navigation.DEEP_LINK_BASE_URI
import org.meshtastic.core.navigation.NodeDetailRoutes
@@ -64,7 +64,7 @@ fun NavGraphBuilder.nodesGraph(navController: NavHostController, uiViewModel: UI
composable(
deepLinks = listOf(navDeepLink(basePath = "$DEEP_LINK_BASE_URI/nodes")),
) {
- NodeScreen(navigateToNodeDetails = { navController.navigate(NodesRoutes.NodeDetailGraph(it)) })
+ NodeListScreen(navigateToNodeDetails = { navController.navigate(NodesRoutes.NodeDetailGraph(it)) })
}
nodeDetailGraph(navController, uiViewModel)
}
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 5c0a094a6..db01edfeb 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,11 +43,11 @@ 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.node.components.NodeChip
import org.meshtastic.core.database.model.Node
import org.meshtastic.core.navigation.ContactsRoutes
import org.meshtastic.core.navigation.SettingsRoutes
import org.meshtastic.core.strings.R
+import org.meshtastic.core.ui.component.NodeChip
import org.meshtastic.core.ui.theme.AppTheme
@Suppress("CyclomaticComplexMethod")
diff --git a/app/src/main/java/com/geeksville/mesh/ui/connections/ConnectionsScreen.kt b/app/src/main/java/com/geeksville/mesh/ui/connections/ConnectionsScreen.kt
index 6d14e3b2b..28f776736 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/connections/ConnectionsScreen.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/connections/ConnectionsScreen.kt
@@ -70,7 +70,6 @@ import com.geeksville.mesh.ui.connections.components.ConnectionsSegmentedBar
import com.geeksville.mesh.ui.connections.components.CurrentlyConnectedInfo
import com.geeksville.mesh.ui.connections.components.NetworkDevices
import com.geeksville.mesh.ui.connections.components.UsbDevices
-import com.geeksville.mesh.ui.settings.components.SettingsItem
import com.geeksville.mesh.ui.settings.radio.RadioConfigViewModel
import com.geeksville.mesh.ui.settings.radio.components.PacketResponseStateDialog
import com.google.accompanist.permissions.ExperimentalPermissionsApi
@@ -79,6 +78,7 @@ import org.meshtastic.core.navigation.Route
import org.meshtastic.core.navigation.SettingsRoutes
import org.meshtastic.core.service.ConnectionState
import org.meshtastic.core.strings.R
+import org.meshtastic.core.ui.component.SettingsItem
import org.meshtastic.core.ui.component.TitledCard
fun String?.isIPAddress(): Boolean = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
diff --git a/app/src/main/java/com/geeksville/mesh/ui/connections/components/CurrentlyConnectedInfo.kt b/app/src/main/java/com/geeksville/mesh/ui/connections/components/CurrentlyConnectedInfo.kt
index 7efa867e2..abec83eef 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/connections/components/CurrentlyConnectedInfo.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/connections/components/CurrentlyConnectedInfo.kt
@@ -39,11 +39,11 @@ import androidx.compose.ui.unit.dp
import com.geeksville.mesh.MeshProtos
import com.geeksville.mesh.PaxcountProtos
import com.geeksville.mesh.TelemetryProtos
-import com.geeksville.mesh.ui.node.components.NodeChip
import org.meshtastic.core.database.model.Node
import org.meshtastic.core.strings.R
import org.meshtastic.core.ui.component.MaterialBatteryInfo
import org.meshtastic.core.ui.component.MaterialBluetoothSignalInfo
+import org.meshtastic.core.ui.component.NodeChip
import org.meshtastic.core.ui.theme.AppTheme
import org.meshtastic.core.ui.theme.StatusColors.StatusRed
diff --git a/app/src/main/java/com/geeksville/mesh/ui/message/Message.kt b/app/src/main/java/com/geeksville/mesh/ui/message/Message.kt
index c7cc300d1..116b36606 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/message/Message.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/message/Message.kt
@@ -96,7 +96,6 @@ import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.geeksville.mesh.AppOnlyProtos
import com.geeksville.mesh.ui.common.components.SecurityIcon
-import com.geeksville.mesh.ui.node.components.NodeKeyStatusIcon
import com.geeksville.mesh.ui.sharing.SharedContactDialog
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
@@ -107,6 +106,7 @@ import org.meshtastic.core.model.DataPacket
import org.meshtastic.core.model.util.getChannel
import org.meshtastic.core.strings.R
import org.meshtastic.core.ui.theme.AppTheme
+import org.meshtastic.feature.node.component.NodeKeyStatusIcon
import java.nio.charset.StandardCharsets
private const val MESSAGE_CHARACTER_LIMIT_BYTES = 200
diff --git a/app/src/main/java/com/geeksville/mesh/ui/message/components/MessageItem.kt b/app/src/main/java/com/geeksville/mesh/ui/message/components/MessageItem.kt
index adcd14593..e02b0b463 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/message/components/MessageItem.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/message/components/MessageItem.kt
@@ -49,16 +49,16 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.PreviewLightDark
import androidx.compose.ui.unit.dp
-import com.geeksville.mesh.ui.common.preview.NodePreviewParameterProvider
-import com.geeksville.mesh.ui.node.components.NodeChip
import org.meshtastic.core.database.entity.Reaction
import org.meshtastic.core.database.model.Message
import org.meshtastic.core.database.model.Node
import org.meshtastic.core.model.MessageStatus
import org.meshtastic.core.strings.R
import org.meshtastic.core.ui.component.MDText
+import org.meshtastic.core.ui.component.NodeChip
import org.meshtastic.core.ui.component.Rssi
import org.meshtastic.core.ui.component.Snr
+import org.meshtastic.core.ui.component.preview.NodePreviewParameterProvider
import org.meshtastic.core.ui.theme.AppTheme
import org.meshtastic.core.ui.theme.MessageItemColors
diff --git a/app/src/main/java/com/geeksville/mesh/ui/node/NodeDetail.kt b/app/src/main/java/com/geeksville/mesh/ui/node/NodeDetailScreen.kt
similarity index 98%
rename from app/src/main/java/com/geeksville/mesh/ui/node/NodeDetail.kt
rename to app/src/main/java/com/geeksville/mesh/ui/node/NodeDetailScreen.kt
index e13fd660d..927c518de 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/node/NodeDetail.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/node/NodeDetailScreen.kt
@@ -134,13 +134,6 @@ import com.geeksville.mesh.MeshProtos
import com.geeksville.mesh.model.MetricsState
import com.geeksville.mesh.model.MetricsViewModel
import com.geeksville.mesh.ui.common.components.MainAppBar
-import com.geeksville.mesh.ui.common.preview.NodePreviewParameterProvider
-import com.geeksville.mesh.ui.node.components.NodeActionDialogs
-import com.geeksville.mesh.ui.node.components.NodeMenuAction
-import com.geeksville.mesh.ui.node.components.TracerouteButton
-import com.geeksville.mesh.ui.settings.components.SettingsItem
-import com.geeksville.mesh.ui.settings.components.SettingsItemDetail
-import com.geeksville.mesh.ui.settings.components.SettingsItemSwitch
import com.geeksville.mesh.ui.sharing.SharedContactDialog
import com.geeksville.mesh.util.thenIf
import com.mikepenz.markdown.m3.Markdown
@@ -163,12 +156,20 @@ import org.meshtastic.core.navigation.Route
import org.meshtastic.core.navigation.SettingsRoutes
import org.meshtastic.core.service.ServiceAction
import org.meshtastic.core.strings.R
+import org.meshtastic.core.ui.component.SettingsItem
+import org.meshtastic.core.ui.component.SettingsItemDetail
+import org.meshtastic.core.ui.component.SettingsItemSwitch
import org.meshtastic.core.ui.component.TitledCard
+import org.meshtastic.core.ui.component.preview.NodePreviewParameterProvider
import org.meshtastic.core.ui.theme.AppTheme
import org.meshtastic.core.ui.theme.StatusColors.StatusGreen
import org.meshtastic.core.ui.theme.StatusColors.StatusOrange
import org.meshtastic.core.ui.theme.StatusColors.StatusRed
import org.meshtastic.core.ui.theme.StatusColors.StatusYellow
+import org.meshtastic.feature.node.component.NodeActionDialogs
+import org.meshtastic.feature.node.component.NodeMenuAction
+import org.meshtastic.feature.node.component.TracerouteButton
+import org.meshtastic.feature.node.detail.NodeDetailViewModel
import timber.log.Timber
private data class VectorMetricInfo(
diff --git a/app/src/main/java/com/geeksville/mesh/ui/node/NodeScreen.kt b/app/src/main/java/com/geeksville/mesh/ui/node/NodeListScreen.kt
similarity index 85%
rename from app/src/main/java/com/geeksville/mesh/ui/node/NodeScreen.kt
rename to app/src/main/java/com/geeksville/mesh/ui/node/NodeListScreen.kt
index 7d194b141..f56db1653 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/node/NodeScreen.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/node/NodeListScreen.kt
@@ -59,9 +59,6 @@ import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.geeksville.mesh.AdminProtos
import com.geeksville.mesh.ui.common.components.MainAppBar
-import com.geeksville.mesh.ui.node.components.NodeActionDialogs
-import com.geeksville.mesh.ui.node.components.NodeFilterTextField
-import com.geeksville.mesh.ui.node.components.NodeItem
import com.geeksville.mesh.ui.sharing.AddContactFAB
import com.geeksville.mesh.ui.sharing.supportsQrCodeSharing
import org.meshtastic.core.database.model.Node
@@ -70,24 +67,28 @@ import org.meshtastic.core.service.ConnectionState
import org.meshtastic.core.strings.R
import org.meshtastic.core.ui.component.rememberTimeTickWithLifecycle
import org.meshtastic.core.ui.theme.StatusColors.StatusRed
+import org.meshtastic.feature.node.component.NodeActionDialogs
+import org.meshtastic.feature.node.component.NodeFilterTextField
+import org.meshtastic.feature.node.component.NodeItem
+import org.meshtastic.feature.node.list.NodeListViewModel
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
@Suppress("LongMethod", "CyclomaticComplexMethod")
@Composable
-fun NodeScreen(nodesViewModel: NodesViewModel = hiltViewModel(), navigateToNodeDetails: (Int) -> Unit) {
- val state by nodesViewModel.nodesUiState.collectAsStateWithLifecycle()
+fun NodeListScreen(viewModel: NodeListViewModel = hiltViewModel(), navigateToNodeDetails: (Int) -> Unit) {
+ val state by viewModel.nodesUiState.collectAsStateWithLifecycle()
- val nodes by nodesViewModel.nodeList.collectAsStateWithLifecycle()
- val ourNode by nodesViewModel.ourNodeInfo.collectAsStateWithLifecycle()
- val onlineNodeCount by nodesViewModel.onlineNodeCount.collectAsStateWithLifecycle(0)
- val totalNodeCount by nodesViewModel.totalNodeCount.collectAsStateWithLifecycle(0)
- val unfilteredNodes by nodesViewModel.unfilteredNodeList.collectAsStateWithLifecycle()
+ val nodes by viewModel.nodeList.collectAsStateWithLifecycle()
+ val ourNode by viewModel.ourNodeInfo.collectAsStateWithLifecycle()
+ val onlineNodeCount by viewModel.onlineNodeCount.collectAsStateWithLifecycle(0)
+ val totalNodeCount by viewModel.totalNodeCount.collectAsStateWithLifecycle(0)
+ val unfilteredNodes by viewModel.unfilteredNodeList.collectAsStateWithLifecycle()
val ignoredNodeCount = unfilteredNodes.count { it.isIgnored }
val listState = rememberLazyListState()
val currentTimeMillis = rememberTimeTickWithLifecycle()
- val connectionState by nodesViewModel.connectionState.collectAsStateWithLifecycle()
+ val connectionState by viewModel.connectionState.collectAsStateWithLifecycle()
val isScrollInProgress by remember {
derivedStateOf { listState.isScrollInProgress && (listState.canScrollForward || listState.canScrollBackward) }
@@ -109,7 +110,7 @@ fun NodeScreen(nodesViewModel: NodesViewModel = hiltViewModel(), navigateToNodeD
val firmwareVersion = DeviceVersion(ourNode?.metadata?.firmwareVersion ?: "0.0.0")
val shareCapable = firmwareVersion.supportsQrCodeSharing()
val scannedContact: AdminProtos.SharedContact? by
- nodesViewModel.sharedContactRequested.collectAsStateWithLifecycle(null)
+ viewModel.sharedContactRequested.collectAsStateWithLifecycle(null)
AddContactFAB(
unfilteredNodes = unfilteredNodes,
scannedContact = scannedContact,
@@ -118,8 +119,8 @@ fun NodeScreen(nodesViewModel: NodesViewModel = hiltViewModel(), navigateToNodeD
visible = !isScrollInProgress && connectionState == ConnectionState.CONNECTED && shareCapable,
alignment = Alignment.BottomEnd,
),
- onSharedContactImport = { contact -> nodesViewModel.addSharedContact(contact) },
- onSharedContactRequested = { contact -> nodesViewModel.setSharedContactRequested(contact) },
+ onSharedContactImport = { contact -> viewModel.addSharedContact(contact) },
+ onSharedContactRequested = { contact -> viewModel.setSharedContactRequested(contact) },
)
},
) { contentPadding ->
@@ -135,17 +136,17 @@ fun NodeScreen(nodesViewModel: NodesViewModel = hiltViewModel(), navigateToNodeD
.background(MaterialTheme.colorScheme.surfaceDim)
.padding(8.dp),
filterText = state.filter.filterText,
- onTextChange = nodesViewModel::setNodeFilterText,
+ onTextChange = viewModel::setNodeFilterText,
currentSortOption = state.sort,
- onSortSelect = nodesViewModel::setSortOption,
+ onSortSelect = viewModel::setSortOption,
includeUnknown = state.filter.includeUnknown,
- onToggleIncludeUnknown = nodesViewModel::toggleIncludeUnknown,
+ onToggleIncludeUnknown = viewModel::toggleIncludeUnknown,
onlyOnline = state.filter.onlyOnline,
- onToggleOnlyOnline = nodesViewModel::toggleOnlyOnline,
+ onToggleOnlyOnline = viewModel::toggleOnlyOnline,
onlyDirect = state.filter.onlyDirect,
- onToggleOnlyDirect = nodesViewModel::toggleOnlyDirect,
+ onToggleOnlyDirect = viewModel::toggleOnlyDirect,
showIgnored = state.filter.showIgnored,
- onToggleShowIgnored = nodesViewModel::toggleShowIgnored,
+ onToggleShowIgnored = viewModel::toggleShowIgnored,
ignoredNodeCount = ignoredNodeCount,
)
}
@@ -165,9 +166,9 @@ fun NodeScreen(nodesViewModel: NodesViewModel = hiltViewModel(), navigateToNodeD
displayIgnoreDialog = false
displayRemoveDialog = false
},
- onConfirmFavorite = nodesViewModel::favoriteNode,
- onConfirmIgnore = nodesViewModel::ignoreNode,
- onConfirmRemove = { nodesViewModel.removeNode(it.num) },
+ onConfirmFavorite = viewModel::favoriteNode,
+ onConfirmIgnore = viewModel::ignoreNode,
+ onConfirmRemove = { viewModel.removeNode(it.num) },
)
var expanded by remember { mutableStateOf(false) }
diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/SettingsScreen.kt b/app/src/main/java/com/geeksville/mesh/ui/settings/SettingsScreen.kt
index 22316c9b8..b70bf00d7 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/settings/SettingsScreen.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/settings/SettingsScreen.kt
@@ -60,9 +60,6 @@ import com.geeksville.mesh.ClientOnlyProtos.DeviceProfile
import com.geeksville.mesh.android.gpsDisabled
import com.geeksville.mesh.navigation.getNavRouteFrom
import com.geeksville.mesh.ui.common.components.MainAppBar
-import com.geeksville.mesh.ui.settings.components.SettingsItem
-import com.geeksville.mesh.ui.settings.components.SettingsItemDetail
-import com.geeksville.mesh.ui.settings.components.SettingsItemSwitch
import com.geeksville.mesh.ui.settings.radio.RadioConfigItemList
import com.geeksville.mesh.ui.settings.radio.RadioConfigViewModel
import com.geeksville.mesh.ui.settings.radio.components.EditDeviceProfileDialog
@@ -75,6 +72,9 @@ import kotlinx.coroutines.delay
import org.meshtastic.core.navigation.Route
import org.meshtastic.core.strings.R
import org.meshtastic.core.ui.component.MultipleChoiceAlertDialog
+import org.meshtastic.core.ui.component.SettingsItem
+import org.meshtastic.core.ui.component.SettingsItemDetail
+import org.meshtastic.core.ui.component.SettingsItemSwitch
import org.meshtastic.core.ui.component.TitledCard
import org.meshtastic.core.ui.theme.MODE_DYNAMIC
import java.text.SimpleDateFormat
diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/CleanNodeDatabaseScreen.kt b/app/src/main/java/com/geeksville/mesh/ui/settings/radio/CleanNodeDatabaseScreen.kt
index 64dc57abc..a6423c681 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/CleanNodeDatabaseScreen.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/settings/radio/CleanNodeDatabaseScreen.kt
@@ -46,9 +46,9 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
-import com.geeksville.mesh.ui.node.components.NodeChip
import org.meshtastic.core.database.entity.NodeEntity
import org.meshtastic.core.strings.R
+import org.meshtastic.core.ui.component.NodeChip
/**
* Composable screen for cleaning the node database. Allows users to specify criteria for deleting nodes. The list of
diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/RadioConfig.kt b/app/src/main/java/com/geeksville/mesh/ui/settings/radio/RadioConfig.kt
index 9f2f88cb8..1a63250c2 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/RadioConfig.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/settings/radio/RadioConfig.kt
@@ -44,11 +44,11 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.geeksville.mesh.navigation.ConfigRoute
import com.geeksville.mesh.navigation.ModuleRoute
-import com.geeksville.mesh.ui.settings.components.SettingsItem
import com.geeksville.mesh.ui.settings.radio.components.WarningDialog
import org.meshtastic.core.navigation.Route
import org.meshtastic.core.navigation.SettingsRoutes
import org.meshtastic.core.strings.R
+import org.meshtastic.core.ui.component.SettingsItem
import org.meshtastic.core.ui.component.TitledCard
import org.meshtastic.core.ui.theme.AppTheme
import org.meshtastic.core.ui.theme.StatusColors.StatusRed
diff --git a/build.gradle.kts b/build.gradle.kts
index 0e7c45a87..b41d5377d 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -75,4 +75,5 @@ dependencies {
kover(projects.core.network)
kover(projects.core.prefs)
kover(projects.feature.map)
+ kover(projects.feature.node)
}
\ No newline at end of file
diff --git a/core/ui/build.gradle.kts b/core/ui/build.gradle.kts
index a8c2c92ad..450bdd9e7 100644
--- a/core/ui/build.gradle.kts
+++ b/core/ui/build.gradle.kts
@@ -23,6 +23,9 @@ plugins {
android { namespace = "org.meshtastic.core.ui" }
dependencies {
+ implementation(projects.core.database)
+ implementation(projects.core.model)
+ implementation(projects.core.proto)
implementation(projects.core.strings)
implementation(libs.bundles.markdown)
}
diff --git a/core/ui/detekt-baseline.xml b/core/ui/detekt-baseline.xml
index 102a440de..4f2b259f6 100644
--- a/core/ui/detekt-baseline.xml
+++ b/core/ui/detekt-baseline.xml
@@ -6,6 +6,9 @@
ComposableParamOrder:BatteryInfo.kt$BatteryInfo
ComposableParamOrder:EditTextPreference.kt$EditTextPreference
ComposableParamOrder:MaterialBatteryInfo.kt$MaterialBatteryInfo
+ ComposableParamOrder:NodeChip.kt$NodeChip
+ ComposableParamOrder:SettingsItem.kt$SettingsItem
+ ComposableParamOrder:SignalInfo.kt$SignalInfo
ComposableParamOrder:SwitchPreference.kt$SwitchPreference
ContentSlotReused:AdaptiveTwoPane.kt$second
LongMethod:EditTextPreference.kt$@Composable fun EditTextPreference( title: String, value: String, enabled: Boolean, isError: Boolean, keyboardOptions: KeyboardOptions, keyboardActions: KeyboardActions, onValueChanged: (String) -> Unit, modifier: Modifier = Modifier, summary: String? = null, maxSize: Int = 0, // max_size - 1 (in bytes) onFocusChanged: (FocusState) -> Unit = {}, trailingIcon: (@Composable () -> Unit)? = null, visualTransformation: VisualTransformation = VisualTransformation.None, )
@@ -30,8 +33,12 @@
ModifierMissing:LoraSignalIndicator.kt$Rssi
ModifierMissing:LoraSignalIndicator.kt$Snr
ModifierMissing:LoraSignalIndicator.kt$SnrAndRssi
+ ModifierMissing:SettingsItem.kt$SettingsItem
+ ModifierMissing:SettingsItem.kt$SettingsItemDetail
+ ModifierMissing:SettingsItem.kt$SettingsItemSwitch
ModifierMissing:SimpleAlertDialog.kt$SimpleAlertDialog
ModifierMissing:SlidingSelector.kt$OptionLabel
+ ModifierNotUsedAtRoot:SignalInfo.kt$modifier = modifier
ModifierNotUsedAtRoot:TextDividerPreference.kt$modifier = modifier.fillMaxWidth().padding(all = 16.dp)
ModifierNotUsedAtRoot:TextDividerPreference.kt$modifier = modifier.fillMaxWidth().wrapContentWidth(Alignment.End)
ModifierReused:PreferenceCategory.kt$Card(modifier = modifier.padding(bottom = 8.dp)) { Column( modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp, vertical = 16.dp), horizontalAlignment = Alignment.CenterHorizontally, ) { ProvideTextStyle(MaterialTheme.typography.bodyLarge) { content() } } }
@@ -52,5 +59,8 @@
PreviewPublic:IndoorAirQuality.kt$IAQScalePreview
PreviewPublic:LazyColumnDragAndDropDemo.kt$LazyColumnDragAndDropDemo
PreviewPublic:MaterialBatteryInfo.kt$MaterialBatteryInfoPreview
+ PreviewPublic:SignalInfo.kt$SignalInfoPreview
+ PreviewPublic:SignalInfo.kt$SignalInfoSelfPreview
+ PreviewPublic:SignalInfo.kt$SignalInfoSimplePreview
diff --git a/app/src/main/java/com/geeksville/mesh/ui/node/components/NodeChip.kt b/core/ui/src/main/kotlin/org/meshtastic/core/ui/component/NodeChip.kt
similarity index 98%
rename from app/src/main/java/com/geeksville/mesh/ui/node/components/NodeChip.kt
rename to core/ui/src/main/kotlin/org/meshtastic/core/ui/component/NodeChip.kt
index fa826f3bf..0b530c6e4 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/node/components/NodeChip.kt
+++ b/core/ui/src/main/kotlin/org/meshtastic/core/ui/component/NodeChip.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.node.components
+package org.meshtastic.core.ui.component
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.IntrinsicSize
@@ -79,7 +79,7 @@ fun NodeChip(modifier: Modifier = Modifier, node: Node, onClick: ((Node) -> Unit
@Suppress("MagicNumber")
@Preview
@Composable
-fun NodeChipPreview() {
+private fun NodeChipPreview() {
val user = MeshProtos.User.newBuilder().setShortName("\uD83E\uDEE0").setLongName("John Doe").build()
val node =
Node(
diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/components/SettingsItem.kt b/core/ui/src/main/kotlin/org/meshtastic/core/ui/component/SettingsItem.kt
similarity index 99%
rename from app/src/main/java/com/geeksville/mesh/ui/settings/components/SettingsItem.kt
rename to core/ui/src/main/kotlin/org/meshtastic/core/ui/component/SettingsItem.kt
index c9f774ea7..e9db8e4ff 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/settings/components/SettingsItem.kt
+++ b/core/ui/src/main/kotlin/org/meshtastic/core/ui/component/SettingsItem.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.settings.components
+package org.meshtastic.core.ui.component
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
diff --git a/app/src/main/java/com/geeksville/mesh/ui/common/components/SignalInfo.kt b/core/ui/src/main/kotlin/org/meshtastic/core/ui/component/SignalInfo.kt
similarity index 94%
rename from app/src/main/java/com/geeksville/mesh/ui/common/components/SignalInfo.kt
rename to core/ui/src/main/kotlin/org/meshtastic/core/ui/component/SignalInfo.kt
index 7f4223a58..abc1ef132 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/common/components/SignalInfo.kt
+++ b/core/ui/src/main/kotlin/org/meshtastic/core/ui/component/SignalInfo.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.common.components
+package org.meshtastic.core.ui.component
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
@@ -32,12 +32,9 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewLightDark
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
-import com.geeksville.mesh.ui.common.preview.NodePreviewParameterProvider
import org.meshtastic.core.database.model.Node
import org.meshtastic.core.strings.R
-import org.meshtastic.core.ui.component.Rssi
-import org.meshtastic.core.ui.component.Snr
-import org.meshtastic.core.ui.component.determineSignalQuality
+import org.meshtastic.core.ui.component.preview.NodePreviewParameterProvider
import org.meshtastic.core.ui.theme.AppTheme
const val MAX_VALID_SNR = 100F
diff --git a/app/src/main/java/com/geeksville/mesh/ui/common/preview/NodePreviewParameterProvider.kt b/core/ui/src/main/kotlin/org/meshtastic/core/ui/component/preview/NodePreviewParameterProvider.kt
similarity index 99%
rename from app/src/main/java/com/geeksville/mesh/ui/common/preview/NodePreviewParameterProvider.kt
rename to core/ui/src/main/kotlin/org/meshtastic/core/ui/component/preview/NodePreviewParameterProvider.kt
index 56f2bb882..e8d8a8064 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/common/preview/NodePreviewParameterProvider.kt
+++ b/core/ui/src/main/kotlin/org/meshtastic/core/ui/component/preview/NodePreviewParameterProvider.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.common.preview
+package org.meshtastic.core.ui.component.preview
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import com.geeksville.mesh.ConfigProtos
diff --git a/app/src/main/res/drawable/ic_antenna_24.xml b/core/ui/src/main/res/drawable/ic_antenna_24.xml
similarity index 100%
rename from app/src/main/res/drawable/ic_antenna_24.xml
rename to core/ui/src/main/res/drawable/ic_antenna_24.xml
diff --git a/app/src/main/res/drawable/ic_lock_open_right_24.xml b/core/ui/src/main/res/drawable/ic_lock_open_right_24.xml
similarity index 100%
rename from app/src/main/res/drawable/ic_lock_open_right_24.xml
rename to core/ui/src/main/res/drawable/ic_lock_open_right_24.xml
diff --git a/app/src/main/java/com/geeksville/mesh/ui/common/preview/LargeFontPreview.kt b/feature/node/build.gradle.kts
similarity index 52%
rename from app/src/main/java/com/geeksville/mesh/ui/common/preview/LargeFontPreview.kt
rename to feature/node/build.gradle.kts
index 9ebf6db99..0566d62fa 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/common/preview/LargeFontPreview.kt
+++ b/feature/node/build.gradle.kts
@@ -15,9 +15,24 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.common.preview
+plugins {
+ alias(libs.plugins.kover)
+ alias(libs.plugins.meshtastic.android.library)
+ alias(libs.plugins.meshtastic.android.library.compose)
+ alias(libs.plugins.meshtastic.hilt)
+}
-import androidx.compose.ui.tooling.preview.Preview
+android { namespace = "org.meshtastic.feature.node" }
-@Preview(name = "Large Font", fontScale = 2f)
-annotation class LargeFontPreview
+dependencies {
+ implementation(projects.core.data)
+ implementation(projects.core.database)
+ implementation(projects.core.datastore)
+ implementation(projects.core.model)
+ implementation(projects.core.proto)
+ implementation(projects.core.service)
+ implementation(projects.core.strings)
+ implementation(projects.core.ui)
+
+ implementation(libs.timber)
+}
diff --git a/feature/node/detekt-baseline.xml b/feature/node/detekt-baseline.xml
new file mode 100644
index 000000000..ac9bafa3a
--- /dev/null
+++ b/feature/node/detekt-baseline.xml
@@ -0,0 +1,19 @@
+
+
+
+
+ ComposableParamOrder:ElevationInfo.kt$ElevationInfo
+ ComposableParamOrder:LastHeardInfo.kt$LastHeardInfo
+ ComposableParamOrder:LinkedCoordinates.kt$LinkedCoordinates
+ ComposableParamOrder:NodeFilterTextField.kt$NodeFilterTextField
+ ComposableParamOrder:NodeItem.kt$NodeItem
+ ComposableParamOrder:NodeKeyStatusIcon.kt$NodeKeyStatusIcon
+ ComposableParamOrder:SatelliteCountInfo.kt$SatelliteCountInfo
+ ComposableParamOrder:TracerouteButton.kt$TracerouteButton
+ ModifierMissing:NodeStatusIcons.kt$NodeStatusIcons
+ ParameterNaming:NodeFilterTextField.kt$onToggleShowIgnored
+ PreviewPublic:NodeItem.kt$NodeInfoPreview
+ PreviewPublic:NodeItem.kt$NodeInfoSimplePreview
+ TooManyFunctions:NodeListViewModel.kt$NodeListViewModel : ViewModel
+
+
diff --git a/app/src/main/java/com/geeksville/mesh/ui/node/components/DistanceInfo.kt b/feature/node/src/main/kotlin/org/meshtastic/feature/node/component/DistanceInfo.kt
similarity index 96%
rename from app/src/main/java/com/geeksville/mesh/ui/node/components/DistanceInfo.kt
rename to feature/node/src/main/kotlin/org/meshtastic/feature/node/component/DistanceInfo.kt
index 8ef68fd94..12dee2d8e 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/node/components/DistanceInfo.kt
+++ b/feature/node/src/main/kotlin/org/meshtastic/feature/node/component/DistanceInfo.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.node.components
+package org.meshtastic.feature.node.component
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.SocialDistance
diff --git a/app/src/main/java/com/geeksville/mesh/ui/node/components/ElevationInfo.kt b/feature/node/src/main/kotlin/org/meshtastic/feature/node/component/ElevationInfo.kt
similarity index 95%
rename from app/src/main/java/com/geeksville/mesh/ui/node/components/ElevationInfo.kt
rename to feature/node/src/main/kotlin/org/meshtastic/feature/node/component/ElevationInfo.kt
index acbb58aff..234ff7faa 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/node/components/ElevationInfo.kt
+++ b/feature/node/src/main/kotlin/org/meshtastic/feature/node/component/ElevationInfo.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.node.components
+package org.meshtastic.feature.node.component
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
@@ -46,6 +46,6 @@ fun ElevationInfo(
@Composable
@Preview
-fun ElevationInfoPreview() {
+private fun ElevationInfoPreview() {
MaterialTheme { ElevationInfo(altitude = 100, system = DisplayUnits.METRIC, suffix = "ASL") }
}
diff --git a/app/src/main/java/com/geeksville/mesh/ui/node/components/IconInfo.kt b/feature/node/src/main/kotlin/org/meshtastic/feature/node/component/IconInfo.kt
similarity index 97%
rename from app/src/main/java/com/geeksville/mesh/ui/node/components/IconInfo.kt
rename to feature/node/src/main/kotlin/org/meshtastic/feature/node/component/IconInfo.kt
index 5d97ba9a9..645ea53e3 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/node/components/IconInfo.kt
+++ b/feature/node/src/main/kotlin/org/meshtastic/feature/node/component/IconInfo.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.node.components
+package org.meshtastic.feature.node.component
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
diff --git a/app/src/main/java/com/geeksville/mesh/ui/node/components/LastHeardInfo.kt b/feature/node/src/main/kotlin/org/meshtastic/feature/node/component/LastHeardInfo.kt
similarity index 93%
rename from app/src/main/java/com/geeksville/mesh/ui/node/components/LastHeardInfo.kt
rename to feature/node/src/main/kotlin/org/meshtastic/feature/node/component/LastHeardInfo.kt
index d055ca2d5..705e4204a 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/node/components/LastHeardInfo.kt
+++ b/feature/node/src/main/kotlin/org/meshtastic/feature/node/component/LastHeardInfo.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.node.components
+package org.meshtastic.feature.node.component
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
@@ -23,8 +23,8 @@ import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.tooling.preview.PreviewLightDark
-import com.geeksville.mesh.R
import org.meshtastic.core.model.util.formatAgo
+import org.meshtastic.core.ui.R
import org.meshtastic.core.ui.theme.AppTheme
@Composable
@@ -39,7 +39,7 @@ fun LastHeardInfo(modifier: Modifier = Modifier, lastHeard: Int, currentTimeMill
@PreviewLightDark
@Composable
-fun LastHeardInfoPreview() {
+private fun LastHeardInfoPreview() {
AppTheme {
LastHeardInfo(
lastHeard = (System.currentTimeMillis() / 1000).toInt() - 8600,
diff --git a/app/src/main/java/com/geeksville/mesh/ui/node/components/LinkedCoordinates.kt b/feature/node/src/main/kotlin/org/meshtastic/feature/node/component/LinkedCoordinates.kt
similarity index 98%
rename from app/src/main/java/com/geeksville/mesh/ui/node/components/LinkedCoordinates.kt
rename to feature/node/src/main/kotlin/org/meshtastic/feature/node/component/LinkedCoordinates.kt
index 9daff5a98..7b03af764 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/node/components/LinkedCoordinates.kt
+++ b/feature/node/src/main/kotlin/org/meshtastic/feature/node/component/LinkedCoordinates.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.node.components
+package org.meshtastic.feature.node.component
import android.content.ActivityNotFoundException
import android.content.ClipData
@@ -113,6 +113,6 @@ private fun handleClick(context: Context, annotatedString: AnnotatedString) {
@PreviewLightDark
@Composable
-fun LinkedCoordinatesPreview() {
+private fun LinkedCoordinatesPreview() {
AppTheme { LinkedCoordinates(latitude = 37.7749, longitude = -122.4194, nodeName = "Test Node Name") }
}
diff --git a/app/src/main/java/com/geeksville/mesh/ui/node/components/NodeFilterTextField.kt b/feature/node/src/main/kotlin/org/meshtastic/feature/node/component/NodeFilterTextField.kt
similarity index 97%
rename from app/src/main/java/com/geeksville/mesh/ui/node/components/NodeFilterTextField.kt
rename to feature/node/src/main/kotlin/org/meshtastic/feature/node/component/NodeFilterTextField.kt
index 4d6752411..8b595811f 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/node/components/NodeFilterTextField.kt
+++ b/feature/node/src/main/kotlin/org/meshtastic/feature/node/component/NodeFilterTextField.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.node.components
+package org.meshtastic.feature.node.component
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
@@ -33,7 +33,6 @@ import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.Sort
import androidx.compose.material.icons.filled.Clear
-import androidx.compose.material.icons.filled.Done
import androidx.compose.material.icons.filled.Search
import androidx.compose.material3.Checkbox
import androidx.compose.material3.DropdownMenu
@@ -59,9 +58,9 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewLightDark
import androidx.compose.ui.unit.dp
-import com.geeksville.mesh.ui.common.preview.LargeFontPreview
import org.meshtastic.core.database.model.NodeSortOption
import org.meshtastic.core.strings.R
import org.meshtastic.core.ui.theme.AppTheme
@@ -119,7 +118,7 @@ fun NodeFilterTextField(
style = MaterialTheme.typography.titleMedium,
color = MaterialTheme.colorScheme.onSurface,
modifier = Modifier.fillMaxWidth(),
- textAlign = androidx.compose.ui.text.style.TextAlign.Center,
+ textAlign = TextAlign.Center,
)
}
}
@@ -278,7 +277,7 @@ private fun DropdownMenuCheck(
}
@PreviewLightDark
-@LargeFontPreview
+@Preview(name = "Large Font", fontScale = 2f)
@Composable
private fun NodeFilterTextFieldPreview() {
AppTheme {
diff --git a/app/src/main/java/com/geeksville/mesh/ui/node/components/NodeItem.kt b/feature/node/src/main/kotlin/org/meshtastic/feature/node/component/NodeItem.kt
similarity index 97%
rename from app/src/main/java/com/geeksville/mesh/ui/node/components/NodeItem.kt
rename to feature/node/src/main/kotlin/org/meshtastic/feature/node/component/NodeItem.kt
index 26ba2ab17..254d05635 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/node/components/NodeItem.kt
+++ b/feature/node/src/main/kotlin/org/meshtastic/feature/node/component/NodeItem.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.node.components
+package org.meshtastic.feature.node.component
import android.content.res.Configuration
import androidx.compose.foundation.combinedClickable
@@ -37,7 +37,6 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.contentColorFor
import androidx.compose.runtime.Composable
-import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@@ -49,13 +48,14 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import com.geeksville.mesh.ConfigProtos.Config.DisplayConfig
-import com.geeksville.mesh.ui.common.components.SignalInfo
-import com.geeksville.mesh.ui.common.preview.NodePreviewParameterProvider
import org.meshtastic.core.database.model.Node
import org.meshtastic.core.database.model.isUnmessageableRole
import org.meshtastic.core.model.util.toDistanceString
import org.meshtastic.core.strings.R
import org.meshtastic.core.ui.component.MaterialBatteryInfo
+import org.meshtastic.core.ui.component.NodeChip
+import org.meshtastic.core.ui.component.SignalInfo
+import org.meshtastic.core.ui.component.preview.NodePreviewParameterProvider
import org.meshtastic.core.ui.theme.AppTheme
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
diff --git a/app/src/main/java/com/geeksville/mesh/ui/node/components/NodeKeyStatusIcon.kt b/feature/node/src/main/kotlin/org/meshtastic/feature/node/component/NodeKeyStatusIcon.kt
similarity index 97%
rename from app/src/main/java/com/geeksville/mesh/ui/node/components/NodeKeyStatusIcon.kt
rename to feature/node/src/main/kotlin/org/meshtastic/feature/node/component/NodeKeyStatusIcon.kt
index 1b52dd669..d73143585 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/node/components/NodeKeyStatusIcon.kt
+++ b/feature/node/src/main/kotlin/org/meshtastic/feature/node/component/NodeKeyStatusIcon.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.node.components
+package org.meshtastic.feature.node.component
import android.util.Base64
import androidx.annotation.StringRes
@@ -130,7 +130,7 @@ fun NodeKeyStatusIcon(
mismatchKey -> Icons.Default.KeyOff to colorScheme.StatusRed
hasPKC -> Icons.Default.Lock to colorScheme.StatusGreen
else ->
- ImageVector.vectorResource(com.geeksville.mesh.R.drawable.ic_lock_open_right_24) to
+ ImageVector.vectorResource(org.meshtastic.core.ui.R.drawable.ic_lock_open_right_24) to
colorScheme.StatusYellow
}
diff --git a/app/src/main/java/com/geeksville/mesh/ui/node/components/NodeMenu.kt b/feature/node/src/main/kotlin/org/meshtastic/feature/node/component/NodeMenu.kt
similarity index 98%
rename from app/src/main/java/com/geeksville/mesh/ui/node/components/NodeMenu.kt
rename to feature/node/src/main/kotlin/org/meshtastic/feature/node/component/NodeMenu.kt
index 6f9a98389..ce8a578ed 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/node/components/NodeMenu.kt
+++ b/feature/node/src/main/kotlin/org/meshtastic/feature/node/component/NodeMenu.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.node.components
+package org.meshtastic.feature.node.component
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
diff --git a/app/src/main/java/com/geeksville/mesh/ui/node/components/NodeStatusIcons.kt b/feature/node/src/main/kotlin/org/meshtastic/feature/node/component/NodeStatusIcons.kt
similarity index 98%
rename from app/src/main/java/com/geeksville/mesh/ui/node/components/NodeStatusIcons.kt
rename to feature/node/src/main/kotlin/org/meshtastic/feature/node/component/NodeStatusIcons.kt
index 82273a9be..e61fd0c22 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/node/components/NodeStatusIcons.kt
+++ b/feature/node/src/main/kotlin/org/meshtastic/feature/node/component/NodeStatusIcons.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.node.components
+package org.meshtastic.feature.node.component
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
@@ -123,6 +123,6 @@ fun NodeStatusIcons(isThisNode: Boolean, isUnmessageable: Boolean, isFavorite: B
@Preview
@Composable
-fun StatusIconsPreview() {
+private fun StatusIconsPreview() {
NodeStatusIcons(isThisNode = true, isUnmessageable = true, isFavorite = true, isConnected = false)
}
diff --git a/app/src/main/java/com/geeksville/mesh/ui/node/components/SatelliteCountInfo.kt b/feature/node/src/main/kotlin/org/meshtastic/feature/node/component/SatelliteCountInfo.kt
similarity index 94%
rename from app/src/main/java/com/geeksville/mesh/ui/node/components/SatelliteCountInfo.kt
rename to feature/node/src/main/kotlin/org/meshtastic/feature/node/component/SatelliteCountInfo.kt
index 581766036..81d5854f6 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/node/components/SatelliteCountInfo.kt
+++ b/feature/node/src/main/kotlin/org/meshtastic/feature/node/component/SatelliteCountInfo.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.node.components
+package org.meshtastic.feature.node.component
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.twotone.SatelliteAlt
@@ -37,6 +37,6 @@ fun SatelliteCountInfo(modifier: Modifier = Modifier, satCount: Int) {
@PreviewLightDark
@Composable
-fun SatelliteCountInfoPreview() {
+private fun SatelliteCountInfoPreview() {
AppTheme { SatelliteCountInfo(satCount = 5) }
}
diff --git a/app/src/main/java/com/geeksville/mesh/ui/node/components/TracerouteButton.kt b/feature/node/src/main/kotlin/org/meshtastic/feature/node/component/TracerouteButton.kt
similarity index 96%
rename from app/src/main/java/com/geeksville/mesh/ui/node/components/TracerouteButton.kt
rename to feature/node/src/main/kotlin/org/meshtastic/feature/node/component/TracerouteButton.kt
index 0fa4cd49c..76efe380b 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/node/components/TracerouteButton.kt
+++ b/feature/node/src/main/kotlin/org/meshtastic/feature/node/component/TracerouteButton.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.node.components
+package org.meshtastic.feature.node.component
import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.tween
@@ -34,8 +34,8 @@ import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
-import com.geeksville.mesh.ui.settings.components.SettingsItem
import org.meshtastic.core.strings.R
+import org.meshtastic.core.ui.component.SettingsItem
import org.meshtastic.core.ui.theme.AppTheme
private const val COOL_DOWN_TIME_MS = 30000L
diff --git a/app/src/main/java/com/geeksville/mesh/ui/node/NodeDetailViewModel.kt b/feature/node/src/main/kotlin/org/meshtastic/feature/node/detail/NodeDetailViewModel.kt
similarity index 97%
rename from app/src/main/java/com/geeksville/mesh/ui/node/NodeDetailViewModel.kt
rename to feature/node/src/main/kotlin/org/meshtastic/feature/node/detail/NodeDetailViewModel.kt
index 26354439d..6a4b5fada 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/node/NodeDetailViewModel.kt
+++ b/feature/node/src/main/kotlin/org/meshtastic/feature/node/detail/NodeDetailViewModel.kt
@@ -15,12 +15,11 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.node
+package org.meshtastic.feature.node.detail
import android.os.RemoteException
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
-import com.geeksville.mesh.ui.node.components.NodeMenuAction
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
@@ -32,6 +31,7 @@ import org.meshtastic.core.database.model.Node
import org.meshtastic.core.model.Position
import org.meshtastic.core.service.ServiceAction
import org.meshtastic.core.service.ServiceRepository
+import org.meshtastic.feature.node.component.NodeMenuAction
import timber.log.Timber
import javax.inject.Inject
diff --git a/app/src/main/java/com/geeksville/mesh/ui/node/NodesViewModel.kt b/feature/node/src/main/kotlin/org/meshtastic/feature/node/list/NodeListViewModel.kt
similarity index 99%
rename from app/src/main/java/com/geeksville/mesh/ui/node/NodesViewModel.kt
rename to feature/node/src/main/kotlin/org/meshtastic/feature/node/list/NodeListViewModel.kt
index 5e63de80a..b39226912 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/node/NodesViewModel.kt
+++ b/feature/node/src/main/kotlin/org/meshtastic/feature/node/list/NodeListViewModel.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.node
+package org.meshtastic.feature.node.list
import android.os.RemoteException
import androidx.lifecycle.ViewModel
@@ -44,7 +44,7 @@ import timber.log.Timber
import javax.inject.Inject
@HiltViewModel
-class NodesViewModel
+class NodeListViewModel
@Inject
constructor(
private val nodeRepository: NodeRepository,
diff --git a/mesh_service_example/detekt-baseline.xml b/mesh_service_example/detekt-baseline.xml
index 61cefa793..ecf2e0cce 100644
--- a/mesh_service_example/detekt-baseline.xml
+++ b/mesh_service_example/detekt-baseline.xml
@@ -1,37 +1,5 @@
-
- ImplicitDefaultLocale:NodeInfo.kt$NodeInfo$String.format("%d%%", batteryLevel)
- MagicNumber:DataPacket.kt$DataPacket.CREATOR$16
- MagicNumber:Extensions.kt$1000
- MagicNumber:Extensions.kt$1440000
- MagicNumber:Extensions.kt$24
- MagicNumber:Extensions.kt$2880
- MagicNumber:Extensions.kt$60
- MagicNumber:LocationUtils.kt$1e-7
- MagicNumber:NodeInfo.kt$DeviceMetrics.Companion$1000
- MagicNumber:NodeInfo.kt$EnvironmentMetrics.Companion$1000
- MagicNumber:NodeInfo.kt$NodeInfo$0.114
- MagicNumber:NodeInfo.kt$NodeInfo$0.299
- MagicNumber:NodeInfo.kt$NodeInfo$0.587
- MagicNumber:NodeInfo.kt$NodeInfo$0x0000FF
- MagicNumber:NodeInfo.kt$NodeInfo$0x00FF00
- MagicNumber:NodeInfo.kt$NodeInfo$0xFF0000
- MagicNumber:NodeInfo.kt$NodeInfo$1000
- MagicNumber:NodeInfo.kt$NodeInfo$1000.0
- MagicNumber:NodeInfo.kt$NodeInfo$16
- MagicNumber:NodeInfo.kt$NodeInfo$1609
- MagicNumber:NodeInfo.kt$NodeInfo$1609.34
- MagicNumber:NodeInfo.kt$NodeInfo$255
- MagicNumber:NodeInfo.kt$NodeInfo$3.281
- MagicNumber:NodeInfo.kt$NodeInfo$8
- MagicNumber:NodeInfo.kt$Position$180
- MagicNumber:NodeInfo.kt$Position$90
- MagicNumber:NodeInfo.kt$Position$90.0
- MagicNumber:NodeInfo.kt$Position.Companion$1000
- MagicNumber:NodeInfo.kt$Position.Companion$1e-7
- MagicNumber:NodeInfo.kt$Position.Companion$1e7
- MatchingDeclarationName:LocationUtils.kt$GPSFormat
-
+
diff --git a/settings.gradle.kts b/settings.gradle.kts
index cacdfb536..a0d13eca5 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -31,6 +31,7 @@ include(
":core:strings",
":core:ui",
":feature:map",
+ ":feature:node",
":mesh_service_example",
)
rootProject.name = "MeshtasticAndroid"