mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
feat: enhance map navigation and waypoint handling (#4814)
Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>
This commit is contained in:
parent
802aa09aab
commit
5edb8abd05
15 changed files with 95 additions and 16 deletions
|
|
@ -17,6 +17,7 @@
|
|||
package org.meshtastic.app.map
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.ui.Modifier
|
||||
import org.koin.compose.viewmodel.koinViewModel
|
||||
import org.koin.core.annotation.Single
|
||||
|
|
@ -34,8 +35,10 @@ class FdroidMapViewProvider : MapViewProvider {
|
|||
tracerouteOverlay: Any?,
|
||||
tracerouteNodePositions: Map<Int, Any>,
|
||||
onTracerouteMappableCountChanged: (Int, Int) -> Unit,
|
||||
waypointId: Int?,
|
||||
) {
|
||||
val mapViewModel: MapViewModel = koinViewModel()
|
||||
LaunchedEffect(waypointId) { mapViewModel.setWaypointId(waypointId) }
|
||||
org.meshtastic.app.map.MapView(
|
||||
modifier = modifier,
|
||||
mapViewModel = mapViewModel,
|
||||
|
|
|
|||
|
|
@ -47,6 +47,12 @@ class MapViewModel(
|
|||
private val _selectedWaypointId = MutableStateFlow(savedStateHandle.get<Int>("waypointId"))
|
||||
val selectedWaypointId: StateFlow<Int?> = _selectedWaypointId.asStateFlow()
|
||||
|
||||
fun setWaypointId(id: Int?) {
|
||||
if (id != null) {
|
||||
_selectedWaypointId.value = id
|
||||
}
|
||||
}
|
||||
|
||||
var mapStyleId: Int
|
||||
get() = mapPrefs.mapStyle.value
|
||||
set(value) {
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
package org.meshtastic.app.map
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.ui.Modifier
|
||||
import org.koin.compose.viewmodel.koinViewModel
|
||||
import org.koin.core.annotation.Single
|
||||
|
|
@ -34,8 +35,10 @@ class GoogleMapViewProvider : MapViewProvider {
|
|||
tracerouteOverlay: Any?,
|
||||
tracerouteNodePositions: Map<Int, Any>,
|
||||
onTracerouteMappableCountChanged: (Int, Int) -> Unit,
|
||||
waypointId: Int?,
|
||||
) {
|
||||
val mapViewModel: MapViewModel = koinViewModel()
|
||||
LaunchedEffect(waypointId) { mapViewModel.setWaypointId(waypointId) }
|
||||
org.meshtastic.app.map.MapView(
|
||||
modifier = modifier,
|
||||
mapViewModel = mapViewModel,
|
||||
|
|
|
|||
|
|
@ -91,6 +91,20 @@ class MapViewModel(
|
|||
private val _selectedWaypointId = MutableStateFlow(savedStateHandle.get<Int>("waypointId"))
|
||||
val selectedWaypointId: StateFlow<Int?> = _selectedWaypointId.asStateFlow()
|
||||
|
||||
fun setWaypointId(id: Int?) {
|
||||
if (id != null && _selectedWaypointId.value != id) {
|
||||
_selectedWaypointId.value = id
|
||||
viewModelScope.launch {
|
||||
val wpMap = waypoints.first { it.containsKey(id) }
|
||||
wpMap[id]?.let { packet ->
|
||||
val waypoint = packet.waypoint!!
|
||||
val latLng = LatLng((waypoint.latitude_i ?: 0) / 1e7, (waypoint.longitude_i ?: 0) / 1e7)
|
||||
cameraPositionState.position = CameraPosition.fromLatLngZoom(latLng, 15f)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val targetLatLng =
|
||||
googleMapsPrefs.cameraTargetLat.value
|
||||
.takeIf { it != 0.0 }
|
||||
|
|
|
|||
|
|
@ -123,14 +123,30 @@ class GoogleMapsPrefsImpl(
|
|||
}
|
||||
|
||||
override val cameraTargetLat: StateFlow<Double> =
|
||||
dataStore.data.map { it[KEY_CAMERA_TARGET_LAT_PREF] ?: 0.0 }.stateIn(scope, SharingStarted.Eagerly, 0.0)
|
||||
dataStore.data
|
||||
.map {
|
||||
try {
|
||||
it[KEY_CAMERA_TARGET_LAT_PREF] ?: 0.0
|
||||
} catch (_: ClassCastException) {
|
||||
it[floatPreferencesKey(KEY_CAMERA_TARGET_LAT_PREF.name)]?.toDouble() ?: 0.0
|
||||
}
|
||||
}
|
||||
.stateIn(scope, SharingStarted.Eagerly, 0.0)
|
||||
|
||||
override fun setCameraTargetLat(value: Double) {
|
||||
scope.launch { dataStore.edit { it[KEY_CAMERA_TARGET_LAT_PREF] = value } }
|
||||
}
|
||||
|
||||
override val cameraTargetLng: StateFlow<Double> =
|
||||
dataStore.data.map { it[KEY_CAMERA_TARGET_LNG_PREF] ?: 0.0 }.stateIn(scope, SharingStarted.Eagerly, 0.0)
|
||||
dataStore.data
|
||||
.map {
|
||||
try {
|
||||
it[KEY_CAMERA_TARGET_LNG_PREF] ?: 0.0
|
||||
} catch (_: ClassCastException) {
|
||||
it[floatPreferencesKey(KEY_CAMERA_TARGET_LNG_PREF.name)]?.toDouble() ?: 0.0
|
||||
}
|
||||
}
|
||||
.stateIn(scope, SharingStarted.Eagerly, 0.0)
|
||||
|
||||
override fun setCameraTargetLng(value: Double) {
|
||||
scope.launch { dataStore.edit { it[KEY_CAMERA_TARGET_LNG_PREF] = value } }
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ private fun ContactsEntryContent(
|
|||
val requestChannelSet by uiViewModel.requestChannelSet.collectAsStateWithLifecycle()
|
||||
val contactsViewModel = koinViewModel<ContactsViewModel>()
|
||||
val messageViewModel = koinViewModel<MessageViewModel>()
|
||||
initialContactKey?.let { messageViewModel.setContactKey(it) }
|
||||
|
||||
AdaptiveContactsScreen(
|
||||
backStack = backStack,
|
||||
|
|
|
|||
|
|
@ -26,12 +26,13 @@ import org.meshtastic.feature.map.MapScreen
|
|||
import org.meshtastic.feature.map.SharedMapViewModel
|
||||
|
||||
fun EntryProviderScope<NavKey>.mapGraph(backStack: NavBackStack<NavKey>) {
|
||||
entry<MapRoutes.Map> {
|
||||
entry<MapRoutes.Map> { args ->
|
||||
val viewModel = koinViewModel<SharedMapViewModel>()
|
||||
MapScreen(
|
||||
viewModel = viewModel,
|
||||
onClickNodeChip = { backStack.add(NodesRoutes.NodeDetailGraph(it)) },
|
||||
navigateToNodeDetails = { backStack.add(NodesRoutes.NodeDetailGraph(it)) },
|
||||
waypointId = args.waypointId,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -111,6 +111,7 @@ fun EntryProviderScope<NavKey>.nodeDetailGraph(
|
|||
|
||||
entry<NodeDetailRoutes.NodeMap> { args ->
|
||||
val vm = koinViewModel<NodeMapViewModel>()
|
||||
vm.setDestNum(args.destNum)
|
||||
NodeMapScreen(vm, onNavigateUp = { backStack.removeLastOrNull() })
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -299,24 +299,36 @@ fun MainScreen(uIViewModel: UIViewModel = koinViewModel(), scanModel: ScannerVie
|
|||
TopLevelDestination.Nodes -> {
|
||||
val onNodesList = currentKey is NodesRoutes.Nodes
|
||||
if (!onNodesList) {
|
||||
backStack.clear()
|
||||
backStack.add(destination.route)
|
||||
if (backStack.isNotEmpty()) {
|
||||
backStack[0] = destination.route
|
||||
while (backStack.size > 1) backStack.removeAt(backStack.lastIndex)
|
||||
} else {
|
||||
backStack.add(destination.route)
|
||||
}
|
||||
}
|
||||
uIViewModel.emitScrollToTopEvent(ScrollToTopEvent.NodesTabPressed)
|
||||
}
|
||||
TopLevelDestination.Conversations -> {
|
||||
val onConversationsList = currentKey is ContactsRoutes.Contacts
|
||||
if (!onConversationsList) {
|
||||
backStack.clear()
|
||||
backStack.add(destination.route)
|
||||
if (backStack.isNotEmpty()) {
|
||||
backStack[0] = destination.route
|
||||
while (backStack.size > 1) backStack.removeAt(backStack.lastIndex)
|
||||
} else {
|
||||
backStack.add(destination.route)
|
||||
}
|
||||
}
|
||||
uIViewModel.emitScrollToTopEvent(ScrollToTopEvent.ConversationsTabPressed)
|
||||
}
|
||||
else -> Unit
|
||||
}
|
||||
} else {
|
||||
backStack.clear()
|
||||
backStack.add(destination.route)
|
||||
if (backStack.isNotEmpty()) {
|
||||
backStack[0] = destination.route
|
||||
while (backStack.size > 1) backStack.removeAt(backStack.lastIndex)
|
||||
} else {
|
||||
backStack.add(destination.route)
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -66,7 +66,8 @@ fun AdaptiveNodeListScreen(
|
|||
val currentKey = backStack.lastOrNull()
|
||||
val isNodesRoute = currentKey is NodesRoutes.Nodes || currentKey is NodesRoutes.NodesGraph
|
||||
val previousKey = if (backStack.size > 1) backStack[backStack.size - 2] else null
|
||||
val isFromDifferentGraph = previousKey !is NodesRoutes.NodesGraph && previousKey !is NodesRoutes.Nodes
|
||||
val isFromDifferentGraph =
|
||||
previousKey != null && previousKey !is NodesRoutes.NodesGraph && previousKey !is NodesRoutes.Nodes
|
||||
|
||||
if (isFromDifferentGraph && !isNodesRoute) {
|
||||
// Navigate back via NavController to return to the previous screen
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue