mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-03-27 18:21:58 -04:00
feat/decoupling (#4685)
Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Meshtastic LLC
|
||||
* Copyright (c) 2025-2026 Meshtastic LLC
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -14,12 +14,11 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.meshtastic.feature.node.component
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.model.Node
|
||||
|
||||
@Composable
|
||||
internal fun InlineMap(node: Node, modifier: Modifier = Modifier) {
|
||||
|
||||
@@ -31,7 +31,7 @@ import com.google.maps.android.compose.MapsComposeExperimentalApi
|
||||
import com.google.maps.android.compose.MarkerComposable
|
||||
import com.google.maps.android.compose.rememberCameraPositionState
|
||||
import com.google.maps.android.compose.rememberUpdatedMarkerState
|
||||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.model.Node
|
||||
import org.meshtastic.core.ui.component.NodeChip
|
||||
import org.meshtastic.core.ui.component.precisionBitsToMeters
|
||||
|
||||
|
||||
@@ -33,8 +33,8 @@ import org.meshtastic.core.common.util.bearing
|
||||
import org.meshtastic.core.common.util.latLongToMeter
|
||||
import org.meshtastic.core.common.util.nowMillis
|
||||
import org.meshtastic.core.common.util.nowSeconds
|
||||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.di.CoroutineDispatchers
|
||||
import org.meshtastic.core.model.Node
|
||||
import org.meshtastic.core.model.util.toDistanceString
|
||||
import org.meshtastic.core.ui.component.precisionBitsToMeters
|
||||
import org.meshtastic.proto.Config
|
||||
|
||||
@@ -29,8 +29,9 @@ import androidx.compose.ui.graphics.Color
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.database.entity.FirmwareRelease
|
||||
import org.meshtastic.core.database.entity.asDeviceVersion
|
||||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.model.DeviceVersion
|
||||
import org.meshtastic.core.model.Node
|
||||
import org.meshtastic.core.model.service.ServiceAction
|
||||
import org.meshtastic.core.navigation.SettingsRoutes
|
||||
import org.meshtastic.core.resources.Res
|
||||
import org.meshtastic.core.resources.administration
|
||||
@@ -41,7 +42,6 @@ import org.meshtastic.core.resources.latest_alpha_firmware
|
||||
import org.meshtastic.core.resources.latest_stable_firmware
|
||||
import org.meshtastic.core.resources.remote_admin
|
||||
import org.meshtastic.core.resources.request_metadata
|
||||
import org.meshtastic.core.service.ServiceAction
|
||||
import org.meshtastic.core.ui.component.ListItem
|
||||
import org.meshtastic.core.ui.theme.StatusColors.StatusGreen
|
||||
import org.meshtastic.core.ui.theme.StatusColors.StatusOrange
|
||||
|
||||
@@ -46,7 +46,7 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.model.Node
|
||||
import org.meshtastic.core.resources.Res
|
||||
import org.meshtastic.core.resources.actions
|
||||
import org.meshtastic.core.resources.direct_message
|
||||
|
||||
@@ -35,7 +35,7 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.model.Node
|
||||
import org.meshtastic.core.model.util.UnitConversions
|
||||
import org.meshtastic.core.model.util.UnitConversions.toTempString
|
||||
import org.meshtastic.core.model.util.toSmallDistanceString
|
||||
|
||||
@@ -41,7 +41,7 @@ import co.touchlab.kermit.Logger
|
||||
import kotlinx.coroutines.launch
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.common.util.GPSFormat
|
||||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.model.Node
|
||||
import org.meshtastic.core.model.util.metersIn
|
||||
import org.meshtastic.core.model.util.toString
|
||||
import org.meshtastic.core.resources.Res
|
||||
|
||||
@@ -55,8 +55,8 @@ import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import androidx.compose.ui.unit.dp
|
||||
import kotlinx.coroutines.launch
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.model.DataPacket
|
||||
import org.meshtastic.core.model.Node
|
||||
import org.meshtastic.core.model.util.formatUptime
|
||||
import org.meshtastic.core.resources.Res
|
||||
import org.meshtastic.core.resources.copy
|
||||
|
||||
@@ -60,7 +60,7 @@ import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import androidx.compose.ui.unit.dp
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.database.model.NodeSortOption
|
||||
import org.meshtastic.core.model.NodeSortOption
|
||||
import org.meshtastic.core.resources.Res
|
||||
import org.meshtastic.core.resources.desc_node_filter_clear
|
||||
import org.meshtastic.core.resources.node_filter_exclude_infrastructure
|
||||
|
||||
@@ -51,9 +51,9 @@ import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.unit.dp
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.database.model.isUnmessageableRole
|
||||
import org.meshtastic.core.model.ConnectionState
|
||||
import org.meshtastic.core.model.Node
|
||||
import org.meshtastic.core.model.isUnmessageableRole
|
||||
import org.meshtastic.core.model.util.UnitConversions.celsiusToFahrenheit
|
||||
import org.meshtastic.core.model.util.toDistanceString
|
||||
import org.meshtastic.core.resources.Res
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
package org.meshtastic.feature.node.component
|
||||
|
||||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.model.Node
|
||||
import org.meshtastic.core.model.TelemetryType
|
||||
|
||||
sealed class NodeMenuAction {
|
||||
|
||||
@@ -43,7 +43,7 @@ import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.unit.dp
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.model.Node
|
||||
import org.meshtastic.core.resources.Res
|
||||
import org.meshtastic.core.resources.add_a_note
|
||||
import org.meshtastic.core.resources.notes
|
||||
|
||||
@@ -46,7 +46,7 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.model.Node
|
||||
import org.meshtastic.core.model.util.toDistanceString
|
||||
import org.meshtastic.core.resources.Res
|
||||
import org.meshtastic.core.resources.exchange_position
|
||||
|
||||
@@ -26,7 +26,7 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.model.Node
|
||||
import org.meshtastic.core.resources.Res
|
||||
import org.meshtastic.core.resources.channel_1
|
||||
import org.meshtastic.core.resources.channel_2
|
||||
|
||||
@@ -47,7 +47,7 @@ import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import org.jetbrains.compose.resources.StringResource
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.model.Node
|
||||
import org.meshtastic.core.model.TelemetryType
|
||||
import org.meshtastic.core.resources.Res
|
||||
import org.meshtastic.core.resources.logs
|
||||
|
||||
@@ -59,7 +59,7 @@ import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.database.entity.FirmwareRelease
|
||||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.model.Node
|
||||
import org.meshtastic.core.navigation.Route
|
||||
import org.meshtastic.core.resources.Res
|
||||
import org.meshtastic.core.resources.details
|
||||
|
||||
@@ -32,12 +32,12 @@ import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.launch
|
||||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.model.DataPacket
|
||||
import org.meshtastic.core.model.Node
|
||||
import org.meshtastic.core.model.service.ServiceAction
|
||||
import org.meshtastic.core.navigation.NodesRoutes
|
||||
import org.meshtastic.core.repository.ServiceRepository
|
||||
import org.meshtastic.core.resources.UiText
|
||||
import org.meshtastic.core.service.ServiceAction
|
||||
import org.meshtastic.core.service.ServiceRepository
|
||||
import org.meshtastic.feature.node.component.NodeMenuAction
|
||||
import org.meshtastic.feature.node.domain.usecase.GetNodeDetailsUseCase
|
||||
import org.meshtastic.feature.node.metrics.EnvironmentMetricsState
|
||||
|
||||
@@ -16,14 +16,16 @@
|
||||
*/
|
||||
package org.meshtastic.feature.node.detail
|
||||
|
||||
import android.os.RemoteException
|
||||
import co.touchlab.kermit.Logger
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import org.jetbrains.compose.resources.getString
|
||||
import org.meshtastic.core.data.repository.NodeRepository
|
||||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.model.Node
|
||||
import org.meshtastic.core.model.RadioController
|
||||
import org.meshtastic.core.model.service.ServiceAction
|
||||
import org.meshtastic.core.repository.NodeRepository
|
||||
import org.meshtastic.core.repository.ServiceRepository
|
||||
import org.meshtastic.core.resources.Res
|
||||
import org.meshtastic.core.resources.favorite
|
||||
import org.meshtastic.core.resources.favorite_add
|
||||
@@ -37,8 +39,6 @@ import org.meshtastic.core.resources.mute_remove
|
||||
import org.meshtastic.core.resources.remove
|
||||
import org.meshtastic.core.resources.remove_node_text
|
||||
import org.meshtastic.core.resources.unmute
|
||||
import org.meshtastic.core.service.ServiceAction
|
||||
import org.meshtastic.core.service.ServiceRepository
|
||||
import org.meshtastic.core.ui.util.AlertManager
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
@@ -49,6 +49,7 @@ class NodeManagementActions
|
||||
constructor(
|
||||
private val nodeRepository: NodeRepository,
|
||||
private val serviceRepository: ServiceRepository,
|
||||
private val radioController: RadioController,
|
||||
private val alertManager: AlertManager,
|
||||
) {
|
||||
fun requestRemoveNode(scope: CoroutineScope, node: Node) {
|
||||
@@ -62,13 +63,9 @@ constructor(
|
||||
fun removeNode(scope: CoroutineScope, nodeNum: Int) {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
Logger.i { "Removing node '$nodeNum'" }
|
||||
try {
|
||||
val packetId = serviceRepository.meshService?.packetId ?: return@launch
|
||||
serviceRepository.meshService?.removeByNodenum(packetId, nodeNum)
|
||||
nodeRepository.deleteNode(nodeNum)
|
||||
} catch (ex: RemoteException) {
|
||||
Logger.e { "Remove node error: ${ex.message}" }
|
||||
}
|
||||
val packetId = radioController.getPacketId()
|
||||
radioController.removeByNodenum(packetId, nodeNum)
|
||||
nodeRepository.deleteNode(nodeNum)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,13 +85,7 @@ constructor(
|
||||
}
|
||||
|
||||
fun ignoreNode(scope: CoroutineScope, node: Node) {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
try {
|
||||
serviceRepository.onServiceAction(ServiceAction.Ignore(node))
|
||||
} catch (ex: RemoteException) {
|
||||
Logger.e(ex) { "Ignore node error" }
|
||||
}
|
||||
}
|
||||
scope.launch(Dispatchers.IO) { serviceRepository.onServiceAction(ServiceAction.Ignore(node)) }
|
||||
}
|
||||
|
||||
fun requestMuteNode(scope: CoroutineScope, node: Node) {
|
||||
@@ -110,13 +101,7 @@ constructor(
|
||||
}
|
||||
|
||||
fun muteNode(scope: CoroutineScope, node: Node) {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
try {
|
||||
serviceRepository.onServiceAction(ServiceAction.Mute(node))
|
||||
} catch (ex: RemoteException) {
|
||||
Logger.e(ex) { "Mute node error" }
|
||||
}
|
||||
}
|
||||
scope.launch(Dispatchers.IO) { serviceRepository.onServiceAction(ServiceAction.Mute(node)) }
|
||||
}
|
||||
|
||||
fun requestFavoriteNode(scope: CoroutineScope, node: Node) {
|
||||
@@ -135,13 +120,7 @@ constructor(
|
||||
}
|
||||
|
||||
fun favoriteNode(scope: CoroutineScope, node: Node) {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
try {
|
||||
serviceRepository.onServiceAction(ServiceAction.Favorite(node))
|
||||
} catch (ex: RemoteException) {
|
||||
Logger.e(ex) { "Favorite node error" }
|
||||
}
|
||||
}
|
||||
scope.launch(Dispatchers.IO) { serviceRepository.onServiceAction(ServiceAction.Favorite(node)) }
|
||||
}
|
||||
|
||||
fun setNodeNotes(scope: CoroutineScope, nodeNum: Int, notes: String) {
|
||||
|
||||
@@ -29,6 +29,7 @@ import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import org.meshtastic.core.common.util.nowMillis
|
||||
import org.meshtastic.core.model.Position
|
||||
import org.meshtastic.core.model.RadioController
|
||||
import org.meshtastic.core.model.TelemetryType
|
||||
import org.meshtastic.core.resources.Res
|
||||
import org.meshtastic.core.resources.UiText
|
||||
@@ -44,7 +45,6 @@ import org.meshtastic.core.resources.requesting_from
|
||||
import org.meshtastic.core.resources.signal_quality
|
||||
import org.meshtastic.core.resources.traceroute
|
||||
import org.meshtastic.core.resources.user_info
|
||||
import org.meshtastic.core.service.ServiceRepository
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@@ -53,7 +53,7 @@ sealed class NodeRequestEffect {
|
||||
}
|
||||
|
||||
@Singleton
|
||||
class NodeRequestActions @Inject constructor(private val serviceRepository: ServiceRepository) {
|
||||
class NodeRequestActions @Inject constructor(private val radioController: RadioController) {
|
||||
|
||||
private val _effects = MutableSharedFlow<NodeRequestEffect>()
|
||||
val effects: SharedFlow<NodeRequestEffect> = _effects.asSharedFlow()
|
||||
@@ -67,34 +67,26 @@ class NodeRequestActions @Inject constructor(private val serviceRepository: Serv
|
||||
fun requestUserInfo(scope: CoroutineScope, destNum: Int, longName: String) {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
Logger.i { "Requesting UserInfo for '$destNum'" }
|
||||
try {
|
||||
serviceRepository.meshService?.requestUserInfo(destNum)
|
||||
_effects.emit(
|
||||
NodeRequestEffect.ShowFeedback(
|
||||
UiText.Resource(Res.string.requesting_from, Res.string.user_info, longName),
|
||||
),
|
||||
)
|
||||
} catch (ex: android.os.RemoteException) {
|
||||
Logger.e { "Request NodeInfo error: ${ex.message}" }
|
||||
}
|
||||
radioController.requestUserInfo(destNum)
|
||||
_effects.emit(
|
||||
NodeRequestEffect.ShowFeedback(
|
||||
UiText.Resource(Res.string.requesting_from, Res.string.user_info, longName),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun requestNeighborInfo(scope: CoroutineScope, destNum: Int, longName: String) {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
Logger.i { "Requesting NeighborInfo for '$destNum'" }
|
||||
try {
|
||||
val packetId = serviceRepository.meshService?.packetId ?: return@launch
|
||||
serviceRepository.meshService?.requestNeighborInfo(packetId, destNum)
|
||||
_lastRequestNeighborTimes.update { it + (destNum to nowMillis) }
|
||||
_effects.emit(
|
||||
NodeRequestEffect.ShowFeedback(
|
||||
UiText.Resource(Res.string.requesting_from, Res.string.neighbor_info, longName),
|
||||
),
|
||||
)
|
||||
} catch (ex: android.os.RemoteException) {
|
||||
Logger.e { "Request NeighborInfo error: ${ex.message}" }
|
||||
}
|
||||
val packetId = radioController.getPacketId()
|
||||
radioController.requestNeighborInfo(packetId, destNum)
|
||||
_lastRequestNeighborTimes.update { it + (destNum to nowMillis) }
|
||||
_effects.emit(
|
||||
NodeRequestEffect.ShowFeedback(
|
||||
UiText.Resource(Res.string.requesting_from, Res.string.neighbor_info, longName),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,61 +98,49 @@ class NodeRequestActions @Inject constructor(private val serviceRepository: Serv
|
||||
) {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
Logger.i { "Requesting position for '$destNum'" }
|
||||
try {
|
||||
serviceRepository.meshService?.requestPosition(destNum, position)
|
||||
_effects.emit(
|
||||
NodeRequestEffect.ShowFeedback(
|
||||
UiText.Resource(Res.string.requesting_from, Res.string.position, longName),
|
||||
),
|
||||
)
|
||||
} catch (ex: android.os.RemoteException) {
|
||||
Logger.e { "Request position error: ${ex.message}" }
|
||||
}
|
||||
radioController.requestPosition(destNum, position)
|
||||
_effects.emit(
|
||||
NodeRequestEffect.ShowFeedback(
|
||||
UiText.Resource(Res.string.requesting_from, Res.string.position, longName),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun requestTelemetry(scope: CoroutineScope, destNum: Int, longName: String, type: TelemetryType) {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
Logger.i { "Requesting telemetry for '$destNum'" }
|
||||
try {
|
||||
val packetId = serviceRepository.meshService?.packetId ?: return@launch
|
||||
serviceRepository.meshService?.requestTelemetry(packetId, destNum, type.ordinal)
|
||||
val packetId = radioController.getPacketId()
|
||||
radioController.requestTelemetry(packetId, destNum, type.ordinal)
|
||||
|
||||
val typeRes =
|
||||
when (type) {
|
||||
TelemetryType.DEVICE -> Res.string.request_device_metrics
|
||||
TelemetryType.ENVIRONMENT -> Res.string.request_environment_metrics
|
||||
TelemetryType.AIR_QUALITY -> Res.string.request_air_quality_metrics
|
||||
TelemetryType.POWER -> Res.string.request_power_metrics
|
||||
TelemetryType.LOCAL_STATS -> Res.string.signal_quality
|
||||
TelemetryType.HOST -> Res.string.request_host_metrics
|
||||
TelemetryType.PAX -> Res.string.request_pax_metrics
|
||||
}
|
||||
val typeRes =
|
||||
when (type) {
|
||||
TelemetryType.DEVICE -> Res.string.request_device_metrics
|
||||
TelemetryType.ENVIRONMENT -> Res.string.request_environment_metrics
|
||||
TelemetryType.AIR_QUALITY -> Res.string.request_air_quality_metrics
|
||||
TelemetryType.POWER -> Res.string.request_power_metrics
|
||||
TelemetryType.LOCAL_STATS -> Res.string.signal_quality
|
||||
TelemetryType.HOST -> Res.string.request_host_metrics
|
||||
TelemetryType.PAX -> Res.string.request_pax_metrics
|
||||
}
|
||||
|
||||
_effects.emit(
|
||||
NodeRequestEffect.ShowFeedback(UiText.Resource(Res.string.requesting_from, typeRes, longName)),
|
||||
)
|
||||
} catch (ex: android.os.RemoteException) {
|
||||
Logger.e { "Request telemetry error: ${ex.message}" }
|
||||
}
|
||||
_effects.emit(
|
||||
NodeRequestEffect.ShowFeedback(UiText.Resource(Res.string.requesting_from, typeRes, longName)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun requestTraceroute(scope: CoroutineScope, destNum: Int, longName: String) {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
Logger.i { "Requesting traceroute for '$destNum'" }
|
||||
try {
|
||||
val packetId = serviceRepository.meshService?.packetId ?: return@launch
|
||||
serviceRepository.meshService?.requestTraceroute(packetId, destNum)
|
||||
_lastTracerouteTimes.update { it + (destNum to nowMillis) }
|
||||
_effects.emit(
|
||||
NodeRequestEffect.ShowFeedback(
|
||||
UiText.Resource(Res.string.requesting_from, Res.string.traceroute, longName),
|
||||
),
|
||||
)
|
||||
} catch (ex: android.os.RemoteException) {
|
||||
Logger.e { "Request traceroute error: ${ex.message}" }
|
||||
}
|
||||
val packetId = radioController.getPacketId()
|
||||
radioController.requestTraceroute(packetId, destNum)
|
||||
_lastTracerouteTimes.update { it + (destNum to nowMillis) }
|
||||
_effects.emit(
|
||||
NodeRequestEffect.ShowFeedback(
|
||||
UiText.Resource(Res.string.requesting_from, Res.string.traceroute, longName),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,9 +18,9 @@ package org.meshtastic.feature.node.domain.usecase
|
||||
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import org.meshtastic.core.data.repository.NodeRepository
|
||||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.database.model.NodeSortOption
|
||||
import org.meshtastic.core.model.Node
|
||||
import org.meshtastic.core.model.NodeSortOption
|
||||
import org.meshtastic.core.repository.NodeRepository
|
||||
import org.meshtastic.feature.node.list.NodeFilterState
|
||||
import org.meshtastic.feature.node.model.isEffectivelyUnmessageable
|
||||
import org.meshtastic.proto.Config
|
||||
|
||||
@@ -23,17 +23,17 @@ import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onStart
|
||||
import org.meshtastic.core.data.repository.DeviceHardwareRepository
|
||||
import org.meshtastic.core.data.repository.FirmwareReleaseRepository
|
||||
import org.meshtastic.core.data.repository.MeshLogRepository
|
||||
import org.meshtastic.core.data.repository.NodeRepository
|
||||
import org.meshtastic.core.data.repository.RadioConfigRepository
|
||||
import org.meshtastic.core.database.entity.FirmwareRelease
|
||||
import org.meshtastic.core.database.entity.MeshLog
|
||||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.model.MyNodeInfo
|
||||
import org.meshtastic.core.model.Node
|
||||
import org.meshtastic.core.model.util.hasValidEnvironmentMetrics
|
||||
import org.meshtastic.core.model.util.isDirectSignal
|
||||
import org.meshtastic.core.repository.DeviceHardwareRepository
|
||||
import org.meshtastic.core.repository.NodeRepository
|
||||
import org.meshtastic.core.repository.RadioConfigRepository
|
||||
import org.meshtastic.core.resources.Res
|
||||
import org.meshtastic.core.resources.UiText
|
||||
import org.meshtastic.core.resources.fallback_node_name
|
||||
@@ -110,7 +110,7 @@ constructor(
|
||||
nodeRepository.myNodeInfo,
|
||||
radioConfigRepository.deviceProfileFlow.onStart { emit(DeviceProfile()) },
|
||||
) { ourNode, myInfo, profile ->
|
||||
IdentityGroup(ourNode, myInfo?.toMyNodeInfo(), profile)
|
||||
IdentityGroup(ourNode, myInfo, profile)
|
||||
}
|
||||
|
||||
// 3. Metadata & Request Timestamps
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Meshtastic LLC
|
||||
* Copyright (c) 2025-2026 Meshtastic LLC
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -14,12 +14,11 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.meshtastic.feature.node.list
|
||||
|
||||
import kotlinx.coroutines.flow.map
|
||||
import org.meshtastic.core.database.model.NodeSortOption
|
||||
import org.meshtastic.core.datastore.UiPreferencesDataSource
|
||||
import org.meshtastic.core.model.NodeSortOption
|
||||
import javax.inject.Inject
|
||||
|
||||
class NodeFilterPreferences @Inject constructor(private val uiPreferencesDataSource: UiPreferencesDataSource) {
|
||||
|
||||
@@ -67,8 +67,8 @@ import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.launch
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.model.ConnectionState
|
||||
import org.meshtastic.core.model.Node
|
||||
import org.meshtastic.core.resources.Res
|
||||
import org.meshtastic.core.resources.add_favorite
|
||||
import org.meshtastic.core.resources.channel_invalid
|
||||
|
||||
@@ -17,11 +17,9 @@
|
||||
package org.meshtastic.feature.node.list
|
||||
|
||||
import android.net.Uri
|
||||
import android.os.RemoteException
|
||||
import androidx.lifecycle.SavedStateHandle
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import co.touchlab.kermit.Logger
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
@@ -30,12 +28,13 @@ import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.launch
|
||||
import org.meshtastic.core.data.repository.NodeRepository
|
||||
import org.meshtastic.core.data.repository.RadioConfigRepository
|
||||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.database.model.NodeSortOption
|
||||
import org.meshtastic.core.model.Node
|
||||
import org.meshtastic.core.model.NodeSortOption
|
||||
import org.meshtastic.core.model.RadioController
|
||||
import org.meshtastic.core.model.util.dispatchMeshtasticUri
|
||||
import org.meshtastic.core.service.ServiceRepository
|
||||
import org.meshtastic.core.repository.NodeRepository
|
||||
import org.meshtastic.core.repository.RadioConfigRepository
|
||||
import org.meshtastic.core.repository.ServiceRepository
|
||||
import org.meshtastic.core.ui.viewmodel.stateInWhileSubscribed
|
||||
import org.meshtastic.feature.node.detail.NodeManagementActions
|
||||
import org.meshtastic.feature.node.domain.usecase.GetFilteredNodesUseCase
|
||||
@@ -53,6 +52,7 @@ constructor(
|
||||
private val nodeRepository: NodeRepository,
|
||||
private val radioConfigRepository: RadioConfigRepository,
|
||||
private val serviceRepository: ServiceRepository,
|
||||
private val radioController: RadioController,
|
||||
val nodeManagementActions: NodeManagementActions,
|
||||
private val getFilteredNodesUseCase: GetFilteredNodesUseCase,
|
||||
val nodeFilterPreferences: NodeFilterPreferences,
|
||||
@@ -154,11 +154,7 @@ constructor(
|
||||
radioConfigRepository.replaceAllSettings(channelSet.settings)
|
||||
val newLoraConfig = channelSet.lora_config
|
||||
if (newLoraConfig != null) {
|
||||
try {
|
||||
serviceRepository.meshService?.setConfig(Config(lora = newLoraConfig).encode())
|
||||
} catch (ex: RemoteException) {
|
||||
Logger.e(ex) { "Set config error" }
|
||||
}
|
||||
radioController.setLocalConfig(Config(lora = newLoraConfig))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,20 +46,20 @@ import org.meshtastic.core.common.util.nowSeconds
|
||||
import org.meshtastic.core.common.util.toDate
|
||||
import org.meshtastic.core.common.util.toInstant
|
||||
import org.meshtastic.core.data.repository.MeshLogRepository
|
||||
import org.meshtastic.core.data.repository.NodeRepository
|
||||
import org.meshtastic.core.data.repository.TracerouteSnapshotRepository
|
||||
import org.meshtastic.core.database.entity.MeshLog
|
||||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.di.CoroutineDispatchers
|
||||
import org.meshtastic.core.model.Node
|
||||
import org.meshtastic.core.model.TelemetryType
|
||||
import org.meshtastic.core.model.evaluateTracerouteMapAvailability
|
||||
import org.meshtastic.core.model.util.UnitConversions
|
||||
import org.meshtastic.core.navigation.NodesRoutes
|
||||
import org.meshtastic.core.repository.NodeRepository
|
||||
import org.meshtastic.core.repository.ServiceRepository
|
||||
import org.meshtastic.core.resources.Res
|
||||
import org.meshtastic.core.resources.okay
|
||||
import org.meshtastic.core.resources.traceroute
|
||||
import org.meshtastic.core.resources.view_on_map
|
||||
import org.meshtastic.core.service.ServiceRepository
|
||||
import org.meshtastic.core.ui.util.AlertManager
|
||||
import org.meshtastic.core.ui.util.toMessageRes
|
||||
import org.meshtastic.core.ui.viewmodel.stateInWhileSubscribed
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
*/
|
||||
package org.meshtastic.feature.node.model
|
||||
|
||||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.database.model.isUnmessageableRole
|
||||
import org.meshtastic.core.model.Node
|
||||
import org.meshtastic.core.model.isUnmessageableRole
|
||||
|
||||
val Node.isEffectivelyUnmessageable: Boolean
|
||||
get() = user.is_unmessagable ?: (user.role?.isUnmessageableRole() == true)
|
||||
|
||||
@@ -18,8 +18,8 @@ package org.meshtastic.feature.node.model
|
||||
|
||||
import org.meshtastic.core.database.entity.FirmwareRelease
|
||||
import org.meshtastic.core.database.entity.MeshLog
|
||||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.model.DeviceHardware
|
||||
import org.meshtastic.core.model.Node
|
||||
import org.meshtastic.proto.Config
|
||||
import org.meshtastic.proto.FirmwareEdition
|
||||
import org.meshtastic.proto.MeshPacket
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
*/
|
||||
package org.meshtastic.feature.node.model
|
||||
|
||||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.model.Node
|
||||
import org.meshtastic.core.model.service.ServiceAction
|
||||
import org.meshtastic.core.navigation.Route
|
||||
import org.meshtastic.core.service.ServiceAction
|
||||
import org.meshtastic.feature.node.component.NodeMenuAction
|
||||
import org.meshtastic.proto.Config
|
||||
|
||||
|
||||
@@ -23,9 +23,10 @@ import kotlinx.coroutines.test.StandardTestDispatcher
|
||||
import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
import org.meshtastic.core.data.repository.NodeRepository
|
||||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.service.ServiceRepository
|
||||
import org.meshtastic.core.model.Node
|
||||
import org.meshtastic.core.model.RadioController
|
||||
import org.meshtastic.core.repository.NodeRepository
|
||||
import org.meshtastic.core.repository.ServiceRepository
|
||||
import org.meshtastic.core.ui.util.AlertManager
|
||||
import org.meshtastic.proto.User
|
||||
|
||||
@@ -34,6 +35,7 @@ class NodeManagementActionsTest {
|
||||
|
||||
private val nodeRepository = mockk<NodeRepository>(relaxed = true)
|
||||
private val serviceRepository = mockk<ServiceRepository>(relaxed = true)
|
||||
private val radioController = mockk<RadioController>(relaxed = true)
|
||||
private val alertManager = mockk<AlertManager>(relaxed = true)
|
||||
private val testDispatcher = StandardTestDispatcher()
|
||||
private val testScope = TestScope(testDispatcher)
|
||||
@@ -42,6 +44,7 @@ class NodeManagementActionsTest {
|
||||
NodeManagementActions(
|
||||
nodeRepository = nodeRepository,
|
||||
serviceRepository = serviceRepository,
|
||||
radioController = radioController,
|
||||
alertManager = alertManager,
|
||||
)
|
||||
|
||||
|
||||
@@ -24,9 +24,9 @@ import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.meshtastic.core.data.repository.NodeRepository
|
||||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.database.model.NodeSortOption
|
||||
import org.meshtastic.core.model.Node
|
||||
import org.meshtastic.core.model.NodeSortOption
|
||||
import org.meshtastic.core.repository.NodeRepository
|
||||
import org.meshtastic.feature.node.list.NodeFilterState
|
||||
import org.meshtastic.proto.Config
|
||||
import org.meshtastic.proto.User
|
||||
|
||||
Reference in New Issue
Block a user