mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
feat: Implement iOS support and unify Compose Multiplatform infrastructure (#4876)
This commit is contained in:
parent
f04924ded5
commit
d136b162a4
170 changed files with 2208 additions and 2432 deletions
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* 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.map.navigation
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import org.koin.compose.viewmodel.koinViewModel
|
||||
import org.meshtastic.feature.map.MapScreen
|
||||
import org.meshtastic.feature.map.SharedMapViewModel
|
||||
|
||||
@Composable
|
||||
actual fun MapMainScreen(onClickNodeChip: (Int) -> Unit, navigateToNodeDetails: (Int) -> Unit, waypointId: Int?) {
|
||||
val viewModel = koinViewModel<SharedMapViewModel>()
|
||||
MapScreen(
|
||||
viewModel = viewModel,
|
||||
onClickNodeChip = onClickNodeChip,
|
||||
navigateToNodeDetails = navigateToNodeDetails,
|
||||
waypointId = waypointId,
|
||||
)
|
||||
}
|
||||
|
|
@ -18,7 +18,6 @@ package org.meshtastic.feature.map
|
|||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
|
|
@ -26,6 +25,7 @@ import kotlinx.coroutines.flow.map
|
|||
import kotlinx.coroutines.flow.mapLatest
|
||||
import kotlinx.coroutines.launch
|
||||
import org.jetbrains.compose.resources.StringResource
|
||||
import org.meshtastic.core.common.util.ioDispatcher
|
||||
import org.meshtastic.core.common.util.nowSeconds
|
||||
import org.meshtastic.core.model.DataPacket
|
||||
import org.meshtastic.core.model.Node
|
||||
|
|
@ -139,7 +139,7 @@ open class BaseMapViewModel(
|
|||
|
||||
fun getNodeOrFallback(nodeNum: Int): Node = nodeRepository.nodeDBbyNum.value[nodeNum] ?: Node(num = nodeNum)
|
||||
|
||||
fun deleteWaypoint(id: Int) = viewModelScope.launch(Dispatchers.IO) { packetRepository.deleteWaypoint(id) }
|
||||
fun deleteWaypoint(id: Int) = viewModelScope.launch(ioDispatcher) { packetRepository.deleteWaypoint(id) }
|
||||
|
||||
fun sendWaypoint(wpt: Waypoint, contactKey: String = "0${DataPacket.ID_BROADCAST}") {
|
||||
// contactKey: unique contact key filter (channel)+(nodeId)
|
||||
|
|
@ -151,7 +151,7 @@ open class BaseMapViewModel(
|
|||
}
|
||||
|
||||
private fun sendDataPacket(p: DataPacket) {
|
||||
viewModelScope.launch(Dispatchers.IO) { radioController.sendMessage(p) }
|
||||
viewModelScope.launch(ioDispatcher) { radioController.sendMessage(p) }
|
||||
}
|
||||
|
||||
fun generatePacketId(): Int = radioController.getPacketId()
|
||||
|
|
|
|||
|
|
@ -16,23 +16,22 @@
|
|||
*/
|
||||
package org.meshtastic.feature.map.navigation
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.navigation3.runtime.EntryProviderScope
|
||||
import androidx.navigation3.runtime.NavBackStack
|
||||
import androidx.navigation3.runtime.NavKey
|
||||
import org.koin.compose.viewmodel.koinViewModel
|
||||
import org.meshtastic.core.navigation.MapRoutes
|
||||
import org.meshtastic.core.navigation.NodesRoutes
|
||||
import org.meshtastic.feature.map.MapScreen
|
||||
import org.meshtastic.feature.map.SharedMapViewModel
|
||||
|
||||
fun EntryProviderScope<NavKey>.mapGraph(backStack: NavBackStack<NavKey>) {
|
||||
entry<MapRoutes.Map> { args ->
|
||||
val viewModel = koinViewModel<SharedMapViewModel>()
|
||||
MapScreen(
|
||||
viewModel = viewModel,
|
||||
MapMainScreen(
|
||||
onClickNodeChip = { backStack.add(NodesRoutes.NodeDetailGraph(it)) },
|
||||
navigateToNodeDetails = { backStack.add(NodesRoutes.NodeDetailGraph(it)) },
|
||||
waypointId = args.waypointId,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
expect fun MapMainScreen(onClickNodeChip: (Int) -> Unit, navigateToNodeDetails: (Int) -> Unit, waypointId: Int?)
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* 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.map.navigation
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
|
||||
@Composable
|
||||
actual fun MapMainScreen(onClickNodeChip: (Int) -> Unit, navigateToNodeDetails: (Int) -> Unit, waypointId: Int?) {
|
||||
// TODO: Implement iOS map main screen
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* 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.map.navigation
|
||||
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.runtime.Composable
|
||||
|
||||
@Composable
|
||||
actual fun MapMainScreen(onClickNodeChip: (Int) -> Unit, navigateToNodeDetails: (Int) -> Unit, waypointId: Int?) {
|
||||
// Desktop placeholder for now
|
||||
org.meshtastic.feature.map.navigation.PlaceholderScreen(name = "Map")
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun PlaceholderScreen(name: String) {
|
||||
androidx.compose.foundation.layout.Box(
|
||||
modifier = androidx.compose.ui.Modifier.fillMaxSize(),
|
||||
contentAlignment = androidx.compose.ui.Alignment.Center,
|
||||
) {
|
||||
androidx.compose.material3.Text(
|
||||
text = name,
|
||||
style = androidx.compose.material3.MaterialTheme.typography.headlineMedium,
|
||||
color = androidx.compose.material3.MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue