From 315950b7c68c23b28c1d5af2ffa71e646bedeae5 Mon Sep 17 00:00:00 2001
From: Phil Oliver <3497406+poliver@users.noreply.github.com>
Date: Mon, 3 Nov 2025 14:43:02 -0500
Subject: [PATCH] Modularize remaining nodes code (#3599)
---
app/detekt-baseline.xml | 69 -------------------
.../mesh/navigation/NodesNavigation.kt | 22 +++---
.../main/java/com/geeksville/mesh/ui/Main.kt | 2 +-
core/proto/build.gradle.kts | 1 +
.../core/proto}/HardwareModelExtensions.kt | 2 +-
feature/node/build.gradle.kts | 4 ++
feature/node/detekt-baseline.xml | 69 +++++++++++++++++++
.../feature/node/detail}/NodeDetailList.kt | 2 +-
.../feature/node/detail}/NodeDetailScreen.kt | 5 +-
.../feature/node/list}/NodeListScreen.kt | 3 +-
.../feature/node}/metrics/CommonCharts.kt | 9 ++-
.../feature/node}/metrics/DeviceMetrics.kt | 14 ++--
.../node}/metrics/EnvironmentCharts.kt | 8 +--
.../node}/metrics/EnvironmentMetrics.kt | 7 +-
.../node/metrics}/EnvironmentMetricsState.kt | 2 +-
.../feature/node/metrics}/GraphUtil.kt | 2 +-
.../feature/node}/metrics/HostMetricsLog.kt | 5 +-
.../feature/node/metrics}/MetricsViewModel.kt | 10 +--
.../feature/node}/metrics/PaxMetrics.kt | 3 +-
.../feature/node}/metrics/PositionLog.kt | 3 +-
.../feature/node}/metrics/PowerMetrics.kt | 10 ++-
.../feature/node}/metrics/SignalMetrics.kt | 9 ++-
.../feature/node}/metrics/TracerouteLog.kt | 5 +-
23 files changed, 125 insertions(+), 141 deletions(-)
rename {app/src/main/java/com/geeksville/mesh/util => core/proto/src/main/kotlin/org/meshtastic/core/proto}/HardwareModelExtensions.kt (98%)
rename {app/src/main/java/com/geeksville/mesh/ui/node => feature/node/src/main/kotlin/org/meshtastic/feature/node/detail}/NodeDetailList.kt (99%)
rename {app/src/main/java/com/geeksville/mesh/ui/node => feature/node/src/main/kotlin/org/meshtastic/feature/node/detail}/NodeDetailScreen.kt (97%)
rename {app/src/main/java/com/geeksville/mesh/ui/node => feature/node/src/main/kotlin/org/meshtastic/feature/node/list}/NodeListScreen.kt (99%)
rename {app/src/main/java/com/geeksville/mesh/ui => feature/node/src/main/kotlin/org/meshtastic/feature/node}/metrics/CommonCharts.kt (97%)
rename {app/src/main/java/com/geeksville/mesh/ui => feature/node/src/main/kotlin/org/meshtastic/feature/node}/metrics/DeviceMetrics.kt (97%)
rename {app/src/main/java/com/geeksville/mesh/ui => feature/node/src/main/kotlin/org/meshtastic/feature/node}/metrics/EnvironmentCharts.kt (98%)
rename {app/src/main/java/com/geeksville/mesh/ui => feature/node/src/main/kotlin/org/meshtastic/feature/node}/metrics/EnvironmentMetrics.kt (98%)
rename {app/src/main/java/com/geeksville/mesh/model => feature/node/src/main/kotlin/org/meshtastic/feature/node/metrics}/EnvironmentMetricsState.kt (99%)
rename {app/src/main/java/com/geeksville/mesh/util => feature/node/src/main/kotlin/org/meshtastic/feature/node/metrics}/GraphUtil.kt (99%)
rename {app/src/main/java/com/geeksville/mesh/ui => feature/node/src/main/kotlin/org/meshtastic/feature/node}/metrics/HostMetricsLog.kt (98%)
rename {app/src/main/java/com/geeksville/mesh/model => feature/node/src/main/kotlin/org/meshtastic/feature/node/metrics}/MetricsViewModel.kt (97%)
rename {app/src/main/java/com/geeksville/mesh/ui => feature/node/src/main/kotlin/org/meshtastic/feature/node}/metrics/PaxMetrics.kt (99%)
rename {app/src/main/java/com/geeksville/mesh/ui => feature/node/src/main/kotlin/org/meshtastic/feature/node}/metrics/PositionLog.kt (99%)
rename {app/src/main/java/com/geeksville/mesh/ui => feature/node/src/main/kotlin/org/meshtastic/feature/node}/metrics/PowerMetrics.kt (98%)
rename {app/src/main/java/com/geeksville/mesh/ui => feature/node/src/main/kotlin/org/meshtastic/feature/node}/metrics/SignalMetrics.kt (97%)
rename {app/src/main/java/com/geeksville/mesh/ui => feature/node/src/main/kotlin/org/meshtastic/feature/node}/metrics/TracerouteLog.kt (98%)
diff --git a/app/detekt-baseline.xml b/app/detekt-baseline.xml
index fb1d6c77d..fae4c81d4 100644
--- a/app/detekt-baseline.xml
+++ b/app/detekt-baseline.xml
@@ -5,21 +5,11 @@
CommentSpacing:BLEException.kt$BLEConnectionClosing$/// Our interface is being shut down
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. */
ComposableParamOrder:Channel.kt$ChannelScreen
ComposableParamOrder:Channel.kt$EditChannelUrl
ComposableParamOrder:ConnectionsNavIcon.kt$ConnectionsNavIcon
- ComposableParamOrder:DeviceMetrics.kt$DeviceMetricsChart
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:PaxMetrics.kt$PaxMetricsChart
- ComposableParamOrder:PowerMetrics.kt$PowerMetricsChart
ComposableParamOrder:Share.kt$ShareScreen
- ComposableParamOrder:SignalMetrics.kt$SignalMetricsChart
CyclomaticComplexMethod:MeshService.kt$MeshService$private fun handleReceivedData(packet: MeshPacket)
EmptyClassBlock:DebugLogFile.kt$BinaryLogFile${ }
EmptyFunctionBlock:NopInterface.kt$NopInterface${ }
@@ -45,10 +35,8 @@
FinalNewline:UsbRepositoryModule.kt$com.geeksville.mesh.repository.usb.UsbRepositoryModule.kt
ForbiddenComment:SafeBluetooth.kt$SafeBluetooth$// TODO: display some kind of UI about restarting BLE
LambdaParameterEventTrailing:Channel.kt$onConfirm
- LambdaParameterEventTrailing:TracerouteLog.kt$onNavigateUp
LambdaParameterInRestartableEffect:Channel.kt$onConfirm
LargeClass:MeshService.kt$MeshService : Service
- LongMethod:EnvironmentMetrics.kt$@Composable fun EnvironmentMetricsScreen(viewModel: MetricsViewModel = hiltViewModel(), onNavigateUp: () -> Unit)
LongMethod:MeshService.kt$MeshService$private fun handleReceivedData(packet: MeshPacket)
MagicNumber:BluetoothInterface.kt$BluetoothInterface$1000
MagicNumber:BluetoothInterface.kt$BluetoothInterface$500
@@ -65,9 +53,6 @@
MagicNumber:MeshService.kt$MeshService$32
MagicNumber:MeshService.kt$MeshService$60000
MagicNumber:MeshService.kt$MeshService$8
- MagicNumber:MetricsViewModel.kt$MetricsViewModel$1000L
- MagicNumber:MetricsViewModel.kt$MetricsViewModel$1e-5
- MagicNumber:MetricsViewModel.kt$MetricsViewModel$1e-7
MagicNumber:ProbeTableProvider.kt$ProbeTableProvider$21972
MagicNumber:ProbeTableProvider.kt$ProbeTableProvider$32809
MagicNumber:ProbeTableProvider.kt$ProbeTableProvider$6790
@@ -91,67 +76,13 @@
ModifierClickableOrder:Channel.kt$clickable(onClick = onClick)
ModifierMissing:BLEDevices.kt$BLEDevices
ModifierMissing:Channel.kt$ChannelScreen
- ModifierMissing:CommonCharts.kt$ChartHeader
- ModifierMissing:CommonCharts.kt$Legend
- ModifierMissing:CommonCharts.kt$TimeLabels
ModifierMissing:Contacts.kt$ContactListView
ModifierMissing:Contacts.kt$ContactsScreen
ModifierMissing:Contacts.kt$SelectionToolbar
- ModifierMissing:DeviceMetrics.kt$DeviceMetricsScreen
ModifierMissing:EmptyStateContent.kt$EmptyStateContent
- ModifierMissing:EnvironmentMetrics.kt$EnvironmentMetricsScreen
- ModifierMissing:HostMetricsLog.kt$HostMetricsLogScreen
ModifierMissing:Main.kt$MainScreen
ModifierMissing:NetworkDevices.kt$NetworkDevices
- ModifierMissing:NodeListScreen.kt$NodeListScreen
- ModifierMissing:PaxMetrics.kt$PaxMetricsItem
- ModifierMissing:PaxMetrics.kt$PaxMetricsScreen
- ModifierMissing:PositionLog.kt$PositionItem
- ModifierMissing:PositionLog.kt$PositionLogScreen
- ModifierMissing:PowerMetrics.kt$PowerMetricsScreen
ModifierMissing:Share.kt$ShareScreen
- ModifierMissing:SignalMetrics.kt$SignalMetricsScreen
- ModifierNotUsedAtRoot:DeviceMetrics.kt$modifier = modifier.weight(weight = Y_AXIS_WEIGHT)
- ModifierNotUsedAtRoot:DeviceMetrics.kt$modifier = modifier.width(dp)
- ModifierNotUsedAtRoot:DeviceMetrics.kt$modifier.width(dp)
- ModifierNotUsedAtRoot:EnvironmentCharts.kt$modifier = modifier.width(dp)
- ModifierNotUsedAtRoot:EnvironmentCharts.kt$modifier.width(dp)
- ModifierNotUsedAtRoot:PaxMetrics.kt$modifier.width(dp)
- ModifierNotUsedAtRoot:PowerMetrics.kt$modifier = modifier.weight(weight = Y_AXIS_WEIGHT)
- ModifierNotUsedAtRoot:PowerMetrics.kt$modifier = modifier.width(dp)
- ModifierNotUsedAtRoot:PowerMetrics.kt$modifier.width(dp)
- ModifierNotUsedAtRoot:SignalMetrics.kt$modifier = modifier.weight(weight = Y_AXIS_WEIGHT)
- ModifierNotUsedAtRoot:SignalMetrics.kt$modifier = modifier.width(dp)
- ModifierNotUsedAtRoot:SignalMetrics.kt$modifier.width(dp)
- ModifierNotUsedAtRoot:TracerouteLog.kt$modifier = modifier.fillMaxSize().padding(innerPadding)
- 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, ) }
- ModifierReused:EnvironmentCharts.kt$HorizontalLinesOverlay(modifier.width(dp), lineColors = List(size = 5) { graphColor })
- 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$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$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, )
- ModifierReused:PowerMetrics.kt$YAxisLabels( modifier = modifier.weight(weight = Y_AXIS_WEIGHT), VOLTAGE_COLOR, minValue = voltageMin, maxValue = voltageMax, )
- ModifierReused:SignalMetrics.kt$Canvas(modifier = modifier.width(dp)) { val width = size.width /* Plot */ for (packet in meshPackets) { val xRatio = (packet.rxTime - oldest.rxTime).toFloat() / timeDiff val x = xRatio * width /* SNR */ plotPoint( drawContext = drawContext, color = Metric.SNR.color, x = x, value = packet.rxSnr - Metric.SNR.min, divisor = snrDiff, ) /* RSSI */ plotPoint( drawContext = drawContext, color = Metric.RSSI.color, x = x, value = packet.rxRssi - Metric.RSSI.min, divisor = rssiDiff, ) } }
- ModifierReused:SignalMetrics.kt$HorizontalLinesOverlay(modifier.width(dp), lineColors = List(size = 5) { graphColor })
- ModifierReused:SignalMetrics.kt$TimeAxisOverlay( modifier.width(dp), oldest = oldest.rxTime, newest = newest.rxTime, selectedTime.lineInterval(), )
- ModifierReused:SignalMetrics.kt$YAxisLabels( modifier = modifier.weight(weight = Y_AXIS_WEIGHT), Metric.RSSI.color, minValue = Metric.RSSI.min, maxValue = Metric.RSSI.max, )
- ModifierReused:SignalMetrics.kt$YAxisLabels( modifier = modifier.weight(weight = Y_AXIS_WEIGHT), Metric.SNR.color, minValue = Metric.SNR.min, maxValue = Metric.SNR.max, )
- ModifierWithoutDefault:CommonCharts.kt$modifier
- ModifierWithoutDefault:EnvironmentCharts.kt$modifier
- MultipleEmitters:CommonCharts.kt$LegendLabel
- MultipleEmitters:DeviceMetrics.kt$DeviceMetricsChart
- MultipleEmitters:EnvironmentCharts.kt$EnvironmentMetricsChart
- MultipleEmitters:PaxMetrics.kt$PaxMetricsChart
- MultipleEmitters:PowerMetrics.kt$PowerMetricsChart
- MultipleEmitters:SignalMetrics.kt$SignalMetricsChart
MutableStateAutoboxing:Contacts.kt$mutableStateOf(2)
NestedBlockDepth:MeshService.kt$MeshService$private fun handleReceivedAdmin(fromNodeNum: Int, a: AdminProtos.AdminMessage)
NestedBlockDepth:MeshService.kt$MeshService$private fun handleReceivedData(packet: MeshPacket)
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 c646c3388..f6ab5f4fc 100644
--- a/app/src/main/java/com/geeksville/mesh/navigation/NodesNavigation.kt
+++ b/app/src/main/java/com/geeksville/mesh/navigation/NodesNavigation.kt
@@ -39,17 +39,6 @@ import androidx.navigation.NavHostController
import androidx.navigation.compose.composable
import androidx.navigation.compose.navigation
import androidx.navigation.navDeepLink
-import com.geeksville.mesh.model.MetricsViewModel
-import com.geeksville.mesh.ui.metrics.DeviceMetricsScreen
-import com.geeksville.mesh.ui.metrics.EnvironmentMetricsScreen
-import com.geeksville.mesh.ui.metrics.HostMetricsLogScreen
-import com.geeksville.mesh.ui.metrics.PaxMetricsScreen
-import com.geeksville.mesh.ui.metrics.PositionLogScreen
-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 org.meshtastic.core.navigation.ContactsRoutes
import org.meshtastic.core.navigation.DEEP_LINK_BASE_URI
import org.meshtastic.core.navigation.NodeDetailRoutes
@@ -58,6 +47,17 @@ import org.meshtastic.core.navigation.Route
import org.meshtastic.core.strings.R
import org.meshtastic.feature.map.node.NodeMapScreen
import org.meshtastic.feature.map.node.NodeMapViewModel
+import org.meshtastic.feature.node.detail.NodeDetailScreen
+import org.meshtastic.feature.node.list.NodeListScreen
+import org.meshtastic.feature.node.metrics.DeviceMetricsScreen
+import org.meshtastic.feature.node.metrics.EnvironmentMetricsScreen
+import org.meshtastic.feature.node.metrics.HostMetricsLogScreen
+import org.meshtastic.feature.node.metrics.MetricsViewModel
+import org.meshtastic.feature.node.metrics.PaxMetricsScreen
+import org.meshtastic.feature.node.metrics.PositionLogScreen
+import org.meshtastic.feature.node.metrics.PowerMetricsScreen
+import org.meshtastic.feature.node.metrics.SignalMetricsScreen
+import org.meshtastic.feature.node.metrics.TracerouteLogScreen
fun NavGraphBuilder.nodesGraph(navController: NavHostController) {
navigation(startDestination = NodesRoutes.Nodes) {
diff --git a/app/src/main/java/com/geeksville/mesh/ui/Main.kt b/app/src/main/java/com/geeksville/mesh/ui/Main.kt
index 7f1a6cacd..856c6d63d 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/Main.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/Main.kt
@@ -94,7 +94,6 @@ import com.geeksville.mesh.repository.radio.MeshActivity
import com.geeksville.mesh.service.MeshService
import com.geeksville.mesh.ui.connections.DeviceType
import com.geeksville.mesh.ui.connections.components.ConnectionsNavIcon
-import com.geeksville.mesh.ui.metrics.annotateTraceroute
import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.google.accompanist.permissions.isGranted
import com.google.accompanist.permissions.rememberPermissionState
@@ -120,6 +119,7 @@ import org.meshtastic.core.ui.qr.ScannedQrCodeDialog
import org.meshtastic.core.ui.share.SharedContactDialog
import org.meshtastic.core.ui.theme.StatusColors.StatusBlue
import org.meshtastic.core.ui.theme.StatusColors.StatusGreen
+import org.meshtastic.feature.node.metrics.annotateTraceroute
import org.meshtastic.feature.settings.navigation.settingsGraph
import org.meshtastic.proto.MeshProtos
import timber.log.Timber
diff --git a/core/proto/build.gradle.kts b/core/proto/build.gradle.kts
index 142880f8f..d7dce83a3 100644
--- a/core/proto/build.gradle.kts
+++ b/core/proto/build.gradle.kts
@@ -56,6 +56,7 @@ protobuf {
dependencies {
implementation(projects.core.strings)
+ implementation(libs.timber)
// This needs to be API for consuming modules
api(libs.protobuf.kotlin)
}
diff --git a/app/src/main/java/com/geeksville/mesh/util/HardwareModelExtensions.kt b/core/proto/src/main/kotlin/org/meshtastic/core/proto/HardwareModelExtensions.kt
similarity index 98%
rename from app/src/main/java/com/geeksville/mesh/util/HardwareModelExtensions.kt
rename to core/proto/src/main/kotlin/org/meshtastic/core/proto/HardwareModelExtensions.kt
index 905d76c2e..5aa0ef516 100644
--- a/app/src/main/java/com/geeksville/mesh/util/HardwareModelExtensions.kt
+++ b/core/proto/src/main/kotlin/org/meshtastic/core/proto/HardwareModelExtensions.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.util
+package org.meshtastic.core.proto
import org.meshtastic.proto.MeshProtos
import timber.log.Timber
diff --git a/feature/node/build.gradle.kts b/feature/node/build.gradle.kts
index 837b40dd8..ae51361bc 100644
--- a/feature/node/build.gradle.kts
+++ b/feature/node/build.gradle.kts
@@ -28,6 +28,7 @@ dependencies {
implementation(projects.core.data)
implementation(projects.core.database)
implementation(projects.core.datastore)
+ implementation(projects.core.di)
implementation(projects.core.model)
implementation(projects.core.proto)
implementation(projects.core.service)
@@ -35,10 +36,13 @@ dependencies {
implementation(projects.core.ui)
implementation(projects.core.navigation)
+ implementation(libs.androidx.activity.compose)
implementation(libs.androidx.compose.material.iconsExtended)
implementation(libs.androidx.compose.material3)
implementation(libs.androidx.compose.ui.text)
implementation(libs.androidx.compose.ui.tooling.preview)
+ implementation(libs.androidx.hilt.lifecycle.viewmodel.compose)
+ implementation(libs.androidx.navigation.common)
implementation(libs.timber)
implementation(libs.coil)
implementation(libs.markdown.renderer.android)
diff --git a/feature/node/detekt-baseline.xml b/feature/node/detekt-baseline.xml
index 2238abd36..d3fc2282a 100644
--- a/feature/node/detekt-baseline.xml
+++ b/feature/node/detekt-baseline.xml
@@ -2,16 +2,85 @@
+ CommentWrapping:SignalMetrics.kt$Metric.SNR$/* Selected 12 as the max to get 4 equal vertical sections. */
+ ComposableParamOrder:DeviceMetrics.kt$DeviceMetricsChart
ComposableParamOrder:ElevationInfo.kt$ElevationInfo
+ 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:NodeFilterTextField.kt$NodeFilterTextField
ComposableParamOrder:NodeItem.kt$NodeItem
+ ComposableParamOrder:PaxMetrics.kt$PaxMetricsChart
+ ComposableParamOrder:PowerMetrics.kt$PowerMetricsChart
ComposableParamOrder:SatelliteCountInfo.kt$SatelliteCountInfo
+ ComposableParamOrder:SignalMetrics.kt$SignalMetricsChart
ComposableParamOrder:TracerouteButton.kt$TracerouteButton
+ LambdaParameterEventTrailing:TracerouteLog.kt$onNavigateUp
+ LongMethod:EnvironmentMetrics.kt$@Composable fun EnvironmentMetricsScreen(viewModel: MetricsViewModel = hiltViewModel(), onNavigateUp: () -> Unit)
LongMethod:NodeDetailsSection.kt$@Composable private fun MainNodeDetails(node: Node)
+ MagicNumber:MetricsViewModel.kt$MetricsViewModel$1000L
+ MagicNumber:MetricsViewModel.kt$MetricsViewModel$1e-5
+ MagicNumber:MetricsViewModel.kt$MetricsViewModel$1e-7
+ ModifierMissing:CommonCharts.kt$ChartHeader
+ ModifierMissing:CommonCharts.kt$Legend
+ ModifierMissing:CommonCharts.kt$TimeLabels
+ ModifierMissing:DeviceMetrics.kt$DeviceMetricsScreen
+ ModifierMissing:EnvironmentMetrics.kt$EnvironmentMetricsScreen
+ ModifierMissing:HostMetricsLog.kt$HostMetricsLogScreen
+ ModifierMissing:NodeListScreen.kt$NodeListScreen
ModifierMissing:NodeStatusIcons.kt$NodeStatusIcons
+ ModifierMissing:PaxMetrics.kt$PaxMetricsItem
+ ModifierMissing:PaxMetrics.kt$PaxMetricsScreen
+ ModifierMissing:PositionLog.kt$PositionItem
+ ModifierMissing:PositionLog.kt$PositionLogScreen
+ ModifierMissing:PowerMetrics.kt$PowerMetricsScreen
+ ModifierMissing:SignalMetrics.kt$SignalMetricsScreen
+ ModifierNotUsedAtRoot:DeviceMetrics.kt$modifier = modifier.weight(weight = Y_AXIS_WEIGHT)
+ ModifierNotUsedAtRoot:DeviceMetrics.kt$modifier = modifier.width(dp)
+ ModifierNotUsedAtRoot:DeviceMetrics.kt$modifier.width(dp)
+ ModifierNotUsedAtRoot:EnvironmentCharts.kt$modifier = modifier.width(dp)
+ ModifierNotUsedAtRoot:EnvironmentCharts.kt$modifier.width(dp)
+ ModifierNotUsedAtRoot:PaxMetrics.kt$modifier.width(dp)
+ ModifierNotUsedAtRoot:PowerMetrics.kt$modifier = modifier.weight(weight = Y_AXIS_WEIGHT)
+ ModifierNotUsedAtRoot:PowerMetrics.kt$modifier = modifier.width(dp)
+ ModifierNotUsedAtRoot:PowerMetrics.kt$modifier.width(dp)
+ ModifierNotUsedAtRoot:SignalMetrics.kt$modifier = modifier.weight(weight = Y_AXIS_WEIGHT)
+ ModifierNotUsedAtRoot:SignalMetrics.kt$modifier = modifier.width(dp)
+ ModifierNotUsedAtRoot:SignalMetrics.kt$modifier.width(dp)
+ ModifierNotUsedAtRoot:TracerouteLog.kt$modifier = modifier.fillMaxSize().padding(innerPadding)
+ 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, ) }
+ ModifierReused:EnvironmentCharts.kt$HorizontalLinesOverlay(modifier.width(dp), lineColors = List(size = 5) { graphColor })
+ 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$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$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, )
+ ModifierReused:PowerMetrics.kt$YAxisLabels( modifier = modifier.weight(weight = Y_AXIS_WEIGHT), VOLTAGE_COLOR, minValue = voltageMin, maxValue = voltageMax, )
+ ModifierReused:SignalMetrics.kt$Canvas(modifier = modifier.width(dp)) { val width = size.width /* Plot */ for (packet in meshPackets) { val xRatio = (packet.rxTime - oldest.rxTime).toFloat() / timeDiff val x = xRatio * width /* SNR */ plotPoint( drawContext = drawContext, color = Metric.SNR.color, x = x, value = packet.rxSnr - Metric.SNR.min, divisor = snrDiff, ) /* RSSI */ plotPoint( drawContext = drawContext, color = Metric.RSSI.color, x = x, value = packet.rxRssi - Metric.RSSI.min, divisor = rssiDiff, ) } }
+ ModifierReused:SignalMetrics.kt$HorizontalLinesOverlay(modifier.width(dp), lineColors = List(size = 5) { graphColor })
+ ModifierReused:SignalMetrics.kt$TimeAxisOverlay( modifier.width(dp), oldest = oldest.rxTime, newest = newest.rxTime, selectedTime.lineInterval(), )
+ ModifierReused:SignalMetrics.kt$YAxisLabels( modifier = modifier.weight(weight = Y_AXIS_WEIGHT), Metric.RSSI.color, minValue = Metric.RSSI.min, maxValue = Metric.RSSI.max, )
+ ModifierReused:SignalMetrics.kt$YAxisLabels( modifier = modifier.weight(weight = Y_AXIS_WEIGHT), Metric.SNR.color, minValue = Metric.SNR.min, maxValue = Metric.SNR.max, )
+ ModifierWithoutDefault:CommonCharts.kt$modifier
+ ModifierWithoutDefault:EnvironmentCharts.kt$modifier
+ MultipleEmitters:CommonCharts.kt$LegendLabel
+ MultipleEmitters:DeviceMetrics.kt$DeviceMetricsChart
+ MultipleEmitters:EnvironmentCharts.kt$EnvironmentMetricsChart
MultipleEmitters:NodeDetailsSection.kt$MainNodeDetails
+ MultipleEmitters:PaxMetrics.kt$PaxMetricsChart
+ MultipleEmitters:PowerMetrics.kt$PowerMetricsChart
MultipleEmitters:RemoteDeviceActions.kt$RemoteDeviceActions
+ MultipleEmitters:SignalMetrics.kt$SignalMetricsChart
ParameterNaming:NodeFilterTextField.kt$onToggleShowIgnored
PreviewPublic:NodeItem.kt$NodeInfoPreview
PreviewPublic:NodeItem.kt$NodeInfoSimplePreview
diff --git a/app/src/main/java/com/geeksville/mesh/ui/node/NodeDetailList.kt b/feature/node/src/main/kotlin/org/meshtastic/feature/node/detail/NodeDetailList.kt
similarity index 99%
rename from app/src/main/java/com/geeksville/mesh/ui/node/NodeDetailList.kt
rename to feature/node/src/main/kotlin/org/meshtastic/feature/node/detail/NodeDetailList.kt
index f16ac8c35..8ad94eebf 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/node/NodeDetailList.kt
+++ b/feature/node/src/main/kotlin/org/meshtastic/feature/node/detail/NodeDetailList.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.node
+package org.meshtastic.feature.node.detail
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
diff --git a/app/src/main/java/com/geeksville/mesh/ui/node/NodeDetailScreen.kt b/feature/node/src/main/kotlin/org/meshtastic/feature/node/detail/NodeDetailScreen.kt
similarity index 97%
rename from app/src/main/java/com/geeksville/mesh/ui/node/NodeDetailScreen.kt
rename to feature/node/src/main/kotlin/org/meshtastic/feature/node/detail/NodeDetailScreen.kt
index 8225f4c71..19bda743c 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/node/NodeDetailScreen.kt
+++ b/feature/node/src/main/kotlin/org/meshtastic/feature/node/detail/NodeDetailScreen.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.node
+package org.meshtastic.feature.node.detail
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
@@ -30,13 +30,12 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
-import com.geeksville.mesh.model.MetricsViewModel
import org.meshtastic.core.database.model.Node
import org.meshtastic.core.model.DataPacket
import org.meshtastic.core.navigation.Route
import org.meshtastic.core.ui.component.MainAppBar
import org.meshtastic.feature.node.component.NodeMenuAction
-import org.meshtastic.feature.node.detail.NodeDetailViewModel
+import org.meshtastic.feature.node.metrics.MetricsViewModel
import org.meshtastic.feature.node.model.LogsType
import org.meshtastic.feature.node.model.NodeDetailAction
diff --git a/app/src/main/java/com/geeksville/mesh/ui/node/NodeListScreen.kt b/feature/node/src/main/kotlin/org/meshtastic/feature/node/list/NodeListScreen.kt
similarity index 99%
rename from app/src/main/java/com/geeksville/mesh/ui/node/NodeListScreen.kt
rename to feature/node/src/main/kotlin/org/meshtastic/feature/node/list/NodeListScreen.kt
index 56b4647f9..3a92600ab 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/node/NodeListScreen.kt
+++ b/feature/node/src/main/kotlin/org/meshtastic/feature/node/list/NodeListScreen.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 androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.background
@@ -69,7 +69,6 @@ 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
import org.meshtastic.proto.AdminProtos
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
diff --git a/app/src/main/java/com/geeksville/mesh/ui/metrics/CommonCharts.kt b/feature/node/src/main/kotlin/org/meshtastic/feature/node/metrics/CommonCharts.kt
similarity index 97%
rename from app/src/main/java/com/geeksville/mesh/ui/metrics/CommonCharts.kt
rename to feature/node/src/main/kotlin/org/meshtastic/feature/node/metrics/CommonCharts.kt
index 46faaddac..96748275c 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/metrics/CommonCharts.kt
+++ b/feature/node/src/main/kotlin/org/meshtastic/feature/node/metrics/CommonCharts.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.metrics
+package org.meshtastic.feature.node.metrics
import android.graphics.Paint
import android.graphics.Typeface
@@ -56,11 +56,10 @@ import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
-import com.geeksville.mesh.model.Environment
-import com.geeksville.mesh.ui.metrics.CommonCharts.DATE_TIME_MINUTE_FORMAT
-import com.geeksville.mesh.ui.metrics.CommonCharts.MAX_PERCENT_VALUE
-import com.geeksville.mesh.ui.metrics.CommonCharts.MS_PER_SEC
import org.meshtastic.core.strings.R
+import org.meshtastic.feature.node.metrics.CommonCharts.DATE_TIME_MINUTE_FORMAT
+import org.meshtastic.feature.node.metrics.CommonCharts.MAX_PERCENT_VALUE
+import org.meshtastic.feature.node.metrics.CommonCharts.MS_PER_SEC
import java.text.DateFormat
object CommonCharts {
diff --git a/app/src/main/java/com/geeksville/mesh/ui/metrics/DeviceMetrics.kt b/feature/node/src/main/kotlin/org/meshtastic/feature/node/metrics/DeviceMetrics.kt
similarity index 97%
rename from app/src/main/java/com/geeksville/mesh/ui/metrics/DeviceMetrics.kt
rename to feature/node/src/main/kotlin/org/meshtastic/feature/node/metrics/DeviceMetrics.kt
index ecd4bf65d..fee492ef9 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/metrics/DeviceMetrics.kt
+++ b/feature/node/src/main/kotlin/org/meshtastic/feature/node/metrics/DeviceMetrics.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.metrics
+package org.meshtastic.feature.node.metrics
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.horizontalScroll
@@ -60,13 +60,6 @@ import androidx.compose.ui.tooling.preview.PreviewLightDark
import androidx.compose.ui.unit.dp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
-import com.geeksville.mesh.model.MetricsViewModel
-import com.geeksville.mesh.ui.metrics.CommonCharts.DATE_TIME_FORMAT
-import com.geeksville.mesh.ui.metrics.CommonCharts.MAX_PERCENT_VALUE
-import com.geeksville.mesh.ui.metrics.CommonCharts.MS_PER_SEC
-import com.geeksville.mesh.util.GraphUtil
-import com.geeksville.mesh.util.GraphUtil.createPath
-import com.geeksville.mesh.util.GraphUtil.plotPoint
import org.meshtastic.core.strings.R
import org.meshtastic.core.ui.component.MainAppBar
import org.meshtastic.core.ui.component.MaterialBatteryInfo
@@ -76,6 +69,11 @@ import org.meshtastic.core.ui.theme.AppTheme
import org.meshtastic.core.ui.theme.GraphColors.Cyan
import org.meshtastic.core.ui.theme.GraphColors.Green
import org.meshtastic.core.ui.theme.GraphColors.Magenta
+import org.meshtastic.feature.node.metrics.CommonCharts.DATE_TIME_FORMAT
+import org.meshtastic.feature.node.metrics.CommonCharts.MAX_PERCENT_VALUE
+import org.meshtastic.feature.node.metrics.CommonCharts.MS_PER_SEC
+import org.meshtastic.feature.node.metrics.GraphUtil.createPath
+import org.meshtastic.feature.node.metrics.GraphUtil.plotPoint
import org.meshtastic.feature.node.model.TimeFrame
import org.meshtastic.proto.TelemetryProtos
import org.meshtastic.proto.TelemetryProtos.Telemetry
diff --git a/app/src/main/java/com/geeksville/mesh/ui/metrics/EnvironmentCharts.kt b/feature/node/src/main/kotlin/org/meshtastic/feature/node/metrics/EnvironmentCharts.kt
similarity index 98%
rename from app/src/main/java/com/geeksville/mesh/ui/metrics/EnvironmentCharts.kt
rename to feature/node/src/main/kotlin/org/meshtastic/feature/node/metrics/EnvironmentCharts.kt
index cc29a935a..619d184c9 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/metrics/EnvironmentCharts.kt
+++ b/feature/node/src/main/kotlin/org/meshtastic/feature/node/metrics/EnvironmentCharts.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.metrics
+package org.meshtastic.feature.node.metrics
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.ScrollState
@@ -40,11 +40,9 @@ import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalWindowInfo
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
-import com.geeksville.mesh.model.Environment
-import com.geeksville.mesh.model.EnvironmentGraphingData
-import com.geeksville.mesh.util.GraphUtil.createPath
-import com.geeksville.mesh.util.GraphUtil.drawPathWithGradient
import org.meshtastic.core.strings.R
+import org.meshtastic.feature.node.metrics.GraphUtil.createPath
+import org.meshtastic.feature.node.metrics.GraphUtil.drawPathWithGradient
import org.meshtastic.feature.node.model.TimeFrame
import org.meshtastic.proto.TelemetryProtos.Telemetry
diff --git a/app/src/main/java/com/geeksville/mesh/ui/metrics/EnvironmentMetrics.kt b/feature/node/src/main/kotlin/org/meshtastic/feature/node/metrics/EnvironmentMetrics.kt
similarity index 98%
rename from app/src/main/java/com/geeksville/mesh/ui/metrics/EnvironmentMetrics.kt
rename to feature/node/src/main/kotlin/org/meshtastic/feature/node/metrics/EnvironmentMetrics.kt
index 183241ca0..58df5a4e0 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/metrics/EnvironmentMetrics.kt
+++ b/feature/node/src/main/kotlin/org/meshtastic/feature/node/metrics/EnvironmentMetrics.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.metrics
+package org.meshtastic.feature.node.metrics
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
@@ -49,9 +49,6 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
-import com.geeksville.mesh.model.MetricsViewModel
-import com.geeksville.mesh.ui.metrics.CommonCharts.DATE_TIME_FORMAT
-import com.geeksville.mesh.ui.metrics.CommonCharts.MS_PER_SEC
import org.meshtastic.core.model.util.UnitConversions.celsiusToFahrenheit
import org.meshtastic.core.strings.R
import org.meshtastic.core.ui.component.IaqDisplayMode
@@ -59,6 +56,8 @@ import org.meshtastic.core.ui.component.IndoorAirQuality
import org.meshtastic.core.ui.component.MainAppBar
import org.meshtastic.core.ui.component.OptionLabel
import org.meshtastic.core.ui.component.SlidingSelector
+import org.meshtastic.feature.node.metrics.CommonCharts.DATE_TIME_FORMAT
+import org.meshtastic.feature.node.metrics.CommonCharts.MS_PER_SEC
import org.meshtastic.feature.node.model.TimeFrame
import org.meshtastic.proto.TelemetryProtos
import org.meshtastic.proto.TelemetryProtos.Telemetry
diff --git a/app/src/main/java/com/geeksville/mesh/model/EnvironmentMetricsState.kt b/feature/node/src/main/kotlin/org/meshtastic/feature/node/metrics/EnvironmentMetricsState.kt
similarity index 99%
rename from app/src/main/java/com/geeksville/mesh/model/EnvironmentMetricsState.kt
rename to feature/node/src/main/kotlin/org/meshtastic/feature/node/metrics/EnvironmentMetricsState.kt
index 3de99782c..e7bc8c897 100644
--- a/app/src/main/java/com/geeksville/mesh/model/EnvironmentMetricsState.kt
+++ b/feature/node/src/main/kotlin/org/meshtastic/feature/node/metrics/EnvironmentMetricsState.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.model
+package org.meshtastic.feature.node.metrics
import androidx.compose.ui.graphics.Color
import org.meshtastic.core.model.util.UnitConversions
diff --git a/app/src/main/java/com/geeksville/mesh/util/GraphUtil.kt b/feature/node/src/main/kotlin/org/meshtastic/feature/node/metrics/GraphUtil.kt
similarity index 99%
rename from app/src/main/java/com/geeksville/mesh/util/GraphUtil.kt
rename to feature/node/src/main/kotlin/org/meshtastic/feature/node/metrics/GraphUtil.kt
index dd3dcad6b..d195fa238 100644
--- a/app/src/main/java/com/geeksville/mesh/util/GraphUtil.kt
+++ b/feature/node/src/main/kotlin/org/meshtastic/feature/node/metrics/GraphUtil.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.util
+package org.meshtastic.feature.node.metrics
import android.content.res.Resources
import androidx.compose.ui.geometry.Offset
diff --git a/app/src/main/java/com/geeksville/mesh/ui/metrics/HostMetricsLog.kt b/feature/node/src/main/kotlin/org/meshtastic/feature/node/metrics/HostMetricsLog.kt
similarity index 98%
rename from app/src/main/java/com/geeksville/mesh/ui/metrics/HostMetricsLog.kt
rename to feature/node/src/main/kotlin/org/meshtastic/feature/node/metrics/HostMetricsLog.kt
index 23bd577d3..98dfd9b2f 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/metrics/HostMetricsLog.kt
+++ b/feature/node/src/main/kotlin/org/meshtastic/feature/node/metrics/HostMetricsLog.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.metrics
+package org.meshtastic.feature.node.metrics
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.combinedClickable
@@ -54,12 +54,11 @@ import androidx.compose.ui.tooling.preview.PreviewLightDark
import androidx.compose.ui.unit.dp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
-import com.geeksville.mesh.model.MetricsViewModel
-import com.geeksville.mesh.ui.metrics.CommonCharts.DATE_TIME_FORMAT
import org.meshtastic.core.model.util.formatUptime
import org.meshtastic.core.strings.R
import org.meshtastic.core.ui.component.MainAppBar
import org.meshtastic.core.ui.theme.AppTheme
+import org.meshtastic.feature.node.metrics.CommonCharts.DATE_TIME_FORMAT
import org.meshtastic.proto.TelemetryProtos
import java.text.DecimalFormat
diff --git a/app/src/main/java/com/geeksville/mesh/model/MetricsViewModel.kt b/feature/node/src/main/kotlin/org/meshtastic/feature/node/metrics/MetricsViewModel.kt
similarity index 97%
rename from app/src/main/java/com/geeksville/mesh/model/MetricsViewModel.kt
rename to feature/node/src/main/kotlin/org/meshtastic/feature/node/metrics/MetricsViewModel.kt
index ec8a28c37..7915c5cab 100644
--- a/app/src/main/java/com/geeksville/mesh/model/MetricsViewModel.kt
+++ b/feature/node/src/main/kotlin/org/meshtastic/feature/node/metrics/MetricsViewModel.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.model
+package org.meshtastic.feature.node.metrics
import android.app.Application
import android.net.Uri
@@ -23,7 +23,6 @@ import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.navigation.toRoute
-import com.geeksville.mesh.util.safeNumber
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
@@ -49,12 +48,11 @@ import org.meshtastic.core.database.model.Node
import org.meshtastic.core.di.CoroutineDispatchers
import org.meshtastic.core.model.DataPacket
import org.meshtastic.core.navigation.NodesRoutes
-import org.meshtastic.core.prefs.map.MapPrefs
+import org.meshtastic.core.proto.safeNumber
import org.meshtastic.core.proto.toPosition
import org.meshtastic.core.service.ServiceAction
import org.meshtastic.core.service.ServiceRepository
import org.meshtastic.core.strings.R
-import org.meshtastic.feature.map.model.CustomTileSource
import org.meshtastic.feature.node.model.MetricsState
import org.meshtastic.feature.node.model.TimeFrame
import org.meshtastic.proto.MeshProtos
@@ -88,7 +86,6 @@ constructor(
private val nodeRepository: NodeRepository,
private val deviceHardwareRepository: DeviceHardwareRepository,
private val firmwareReleaseRepository: FirmwareReleaseRepository,
- private val mapPrefs: MapPrefs,
) : ViewModel() {
private val destNum = savedStateHandle.toRoute().destNum
@@ -116,9 +113,6 @@ constructor(
fun getUser(nodeNum: Int) = nodeRepository.getUser(nodeNum)
- val tileSource
- get() = CustomTileSource.getTileSource(mapPrefs.mapStyle)
-
fun deleteLog(uuid: String) = viewModelScope.launch(dispatchers.io) { meshLogRepository.deleteLog(uuid) }
fun clearPosition() = viewModelScope.launch(dispatchers.io) {
diff --git a/app/src/main/java/com/geeksville/mesh/ui/metrics/PaxMetrics.kt b/feature/node/src/main/kotlin/org/meshtastic/feature/node/metrics/PaxMetrics.kt
similarity index 99%
rename from app/src/main/java/com/geeksville/mesh/ui/metrics/PaxMetrics.kt
rename to feature/node/src/main/kotlin/org/meshtastic/feature/node/metrics/PaxMetrics.kt
index 5b5ab8fce..a19ebbe87 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/metrics/PaxMetrics.kt
+++ b/feature/node/src/main/kotlin/org/meshtastic/feature/node/metrics/PaxMetrics.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.metrics
+package org.meshtastic.feature.node.metrics
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.horizontalScroll
@@ -54,7 +54,6 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
-import com.geeksville.mesh.model.MetricsViewModel
import org.meshtastic.core.database.entity.MeshLog
import org.meshtastic.core.model.util.formatUptime
import org.meshtastic.core.strings.R
diff --git a/app/src/main/java/com/geeksville/mesh/ui/metrics/PositionLog.kt b/feature/node/src/main/kotlin/org/meshtastic/feature/node/metrics/PositionLog.kt
similarity index 99%
rename from app/src/main/java/com/geeksville/mesh/ui/metrics/PositionLog.kt
rename to feature/node/src/main/kotlin/org/meshtastic/feature/node/metrics/PositionLog.kt
index 3ea113823..0d0a875dc 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/metrics/PositionLog.kt
+++ b/feature/node/src/main/kotlin/org/meshtastic/feature/node/metrics/PositionLog.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.metrics
+package org.meshtastic.feature.node.metrics
import android.app.Activity
import android.content.Intent
@@ -62,7 +62,6 @@ import androidx.compose.ui.tooling.preview.PreviewScreenSizes
import androidx.compose.ui.unit.dp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
-import com.geeksville.mesh.model.MetricsViewModel
import org.meshtastic.core.model.util.metersIn
import org.meshtastic.core.model.util.toString
import org.meshtastic.core.proto.formatPositionTime
diff --git a/app/src/main/java/com/geeksville/mesh/ui/metrics/PowerMetrics.kt b/feature/node/src/main/kotlin/org/meshtastic/feature/node/metrics/PowerMetrics.kt
similarity index 98%
rename from app/src/main/java/com/geeksville/mesh/ui/metrics/PowerMetrics.kt
rename to feature/node/src/main/kotlin/org/meshtastic/feature/node/metrics/PowerMetrics.kt
index 646f6e17f..171d2cf94 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/metrics/PowerMetrics.kt
+++ b/feature/node/src/main/kotlin/org/meshtastic/feature/node/metrics/PowerMetrics.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.metrics
+package org.meshtastic.feature.node.metrics
import androidx.annotation.StringRes
import androidx.compose.foundation.Canvas
@@ -60,17 +60,15 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
-import com.geeksville.mesh.model.MetricsViewModel
-import com.geeksville.mesh.ui.metrics.CommonCharts.DATE_TIME_FORMAT
-import com.geeksville.mesh.ui.metrics.CommonCharts.MS_PER_SEC
-import com.geeksville.mesh.util.GraphUtil
-import com.geeksville.mesh.util.GraphUtil.createPath
import org.meshtastic.core.strings.R
import org.meshtastic.core.ui.component.MainAppBar
import org.meshtastic.core.ui.component.OptionLabel
import org.meshtastic.core.ui.component.SlidingSelector
import org.meshtastic.core.ui.theme.GraphColors.InfantryBlue
import org.meshtastic.core.ui.theme.GraphColors.Red
+import org.meshtastic.feature.node.metrics.CommonCharts.DATE_TIME_FORMAT
+import org.meshtastic.feature.node.metrics.CommonCharts.MS_PER_SEC
+import org.meshtastic.feature.node.metrics.GraphUtil.createPath
import org.meshtastic.feature.node.model.TimeFrame
import org.meshtastic.proto.TelemetryProtos.Telemetry
import kotlin.math.ceil
diff --git a/app/src/main/java/com/geeksville/mesh/ui/metrics/SignalMetrics.kt b/feature/node/src/main/kotlin/org/meshtastic/feature/node/metrics/SignalMetrics.kt
similarity index 97%
rename from app/src/main/java/com/geeksville/mesh/ui/metrics/SignalMetrics.kt
rename to feature/node/src/main/kotlin/org/meshtastic/feature/node/metrics/SignalMetrics.kt
index bbb04c957..d311b17f1 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/metrics/SignalMetrics.kt
+++ b/feature/node/src/main/kotlin/org/meshtastic/feature/node/metrics/SignalMetrics.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.metrics
+package org.meshtastic.feature.node.metrics
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.horizontalScroll
@@ -57,16 +57,15 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
-import com.geeksville.mesh.model.MetricsViewModel
-import com.geeksville.mesh.ui.metrics.CommonCharts.DATE_TIME_FORMAT
-import com.geeksville.mesh.ui.metrics.CommonCharts.MS_PER_SEC
-import com.geeksville.mesh.util.GraphUtil.plotPoint
import org.meshtastic.core.strings.R
import org.meshtastic.core.ui.component.LoraSignalIndicator
import org.meshtastic.core.ui.component.MainAppBar
import org.meshtastic.core.ui.component.OptionLabel
import org.meshtastic.core.ui.component.SlidingSelector
import org.meshtastic.core.ui.component.SnrAndRssi
+import org.meshtastic.feature.node.metrics.CommonCharts.DATE_TIME_FORMAT
+import org.meshtastic.feature.node.metrics.CommonCharts.MS_PER_SEC
+import org.meshtastic.feature.node.metrics.GraphUtil.plotPoint
import org.meshtastic.feature.node.model.TimeFrame
import org.meshtastic.proto.MeshProtos.MeshPacket
diff --git a/app/src/main/java/com/geeksville/mesh/ui/metrics/TracerouteLog.kt b/feature/node/src/main/kotlin/org/meshtastic/feature/node/metrics/TracerouteLog.kt
similarity index 98%
rename from app/src/main/java/com/geeksville/mesh/ui/metrics/TracerouteLog.kt
rename to feature/node/src/main/kotlin/org/meshtastic/feature/node/metrics/TracerouteLog.kt
index a7d6bfdef..0a68e16ef 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/metrics/TracerouteLog.kt
+++ b/feature/node/src/main/kotlin/org/meshtastic/feature/node/metrics/TracerouteLog.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.metrics
+package org.meshtastic.feature.node.metrics
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.combinedClickable
@@ -62,8 +62,6 @@ import androidx.compose.ui.tooling.preview.PreviewLightDark
import androidx.compose.ui.unit.dp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
-import com.geeksville.mesh.model.MetricsViewModel
-import com.geeksville.mesh.ui.metrics.CommonCharts.MS_PER_SEC
import org.meshtastic.core.model.fullRouteDiscovery
import org.meshtastic.core.model.getTracerouteResponse
import org.meshtastic.core.strings.R
@@ -75,6 +73,7 @@ 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.StatusYellow
+import org.meshtastic.feature.node.metrics.CommonCharts.MS_PER_SEC
import org.meshtastic.proto.MeshProtos
import java.text.DateFormat