From 099aea2d81655d355b5ffdc8a7a2fac447861a09 Mon Sep 17 00:00:00 2001 From: James Rich <2199651+jamesarich@users.noreply.github.com> Date: Tue, 14 Apr 2026 10:16:10 -0500 Subject: [PATCH] feat(desktop): add entitlements and wire MeshConnectionManager into orchestrator (#5127) --- .../core/service/MeshServiceOrchestrator.kt | 3 +++ .../core/service/MeshServiceOrchestratorTest.kt | 3 +++ desktop/build.gradle.kts | 5 +++++ desktop/entitlements.plist | 14 ++++++++++++++ .../main/kotlin/org/meshtastic/desktop/Main.kt | 15 +++++++-------- 5 files changed, 32 insertions(+), 8 deletions(-) create mode 100644 desktop/entitlements.plist diff --git a/core/service/src/commonMain/kotlin/org/meshtastic/core/service/MeshServiceOrchestrator.kt b/core/service/src/commonMain/kotlin/org/meshtastic/core/service/MeshServiceOrchestrator.kt index e651d95ce..50e88cc3f 100644 --- a/core/service/src/commonMain/kotlin/org/meshtastic/core/service/MeshServiceOrchestrator.kt +++ b/core/service/src/commonMain/kotlin/org/meshtastic/core/service/MeshServiceOrchestrator.kt @@ -26,6 +26,7 @@ import org.koin.core.annotation.Named import org.koin.core.annotation.Single import org.meshtastic.core.common.database.DatabaseManager import org.meshtastic.core.common.util.handledLaunch +import org.meshtastic.core.repository.MeshConnectionManager import org.meshtastic.core.repository.MeshMessageProcessor import org.meshtastic.core.repository.MeshRouter import org.meshtastic.core.repository.MeshServiceNotifications @@ -57,6 +58,7 @@ class MeshServiceOrchestrator( private val takMeshIntegration: TAKMeshIntegration, private val takPrefs: TakPrefs, private val databaseManager: DatabaseManager, + private val connectionManager: MeshConnectionManager, @Named("ServiceScope") private val scope: CoroutineScope, ) { private var serviceJob: Job? = null @@ -87,6 +89,7 @@ class MeshServiceOrchestrator( serviceJob = job serviceNotifications.initChannels() + connectionManager.updateStatusNotification() // Observe TAK server pref to start/stop takJob = diff --git a/core/service/src/commonTest/kotlin/org/meshtastic/core/service/MeshServiceOrchestratorTest.kt b/core/service/src/commonTest/kotlin/org/meshtastic/core/service/MeshServiceOrchestratorTest.kt index 48be7dbf6..ddb7b148f 100644 --- a/core/service/src/commonTest/kotlin/org/meshtastic/core/service/MeshServiceOrchestratorTest.kt +++ b/core/service/src/commonTest/kotlin/org/meshtastic/core/service/MeshServiceOrchestratorTest.kt @@ -35,6 +35,7 @@ import org.meshtastic.core.model.service.ServiceAction import org.meshtastic.core.repository.CommandSender import org.meshtastic.core.repository.MeshActionHandler import org.meshtastic.core.repository.MeshConfigHandler +import org.meshtastic.core.repository.MeshConnectionManager import org.meshtastic.core.repository.MeshMessageProcessor import org.meshtastic.core.repository.MeshRouter import org.meshtastic.core.repository.MeshServiceNotifications @@ -67,6 +68,7 @@ class MeshServiceOrchestratorTest { private val takPrefs: TakPrefs = mock(MockMode.autofill) private val cotHandler: CoTHandler = mock(MockMode.autofill) private val databaseManager: DatabaseManager = mock(MockMode.autofill) + private val connectionManager: MeshConnectionManager = mock(MockMode.autofill) private val testDispatcher = UnconfinedTestDispatcher() private val testScope = CoroutineScope(testDispatcher) @@ -111,6 +113,7 @@ class MeshServiceOrchestratorTest { takMeshIntegration = takMeshIntegration, takPrefs = takPrefs, databaseManager = databaseManager, + connectionManager = connectionManager, scope = testScope, ) } diff --git a/desktop/build.gradle.kts b/desktop/build.gradle.kts index df5122a4d..fdf7cee5c 100644 --- a/desktop/build.gradle.kts +++ b/desktop/build.gradle.kts @@ -158,9 +158,14 @@ compose.desktop { iconFile.set(project.file("src/main/resources/icon.icns")) minimumSystemVersion = "12.0" bundleID = "org.meshtastic.desktop" + entitlementsFile.set(project.file("entitlements.plist")) infoPlist { extraKeysRawXml = """ + NSBluetoothAlwaysUsageDescription + Meshtastic uses Bluetooth to communicate with your Meshtastic radio device. + NSLocalNetworkUsageDescription + Meshtastic uses your local network to discover Meshtastic devices connected via WiFi. NSUserNotificationAlertStyle alert CFBundleURLTypes diff --git a/desktop/entitlements.plist b/desktop/entitlements.plist new file mode 100644 index 000000000..f799a66e9 --- /dev/null +++ b/desktop/entitlements.plist @@ -0,0 +1,14 @@ + + + + + com.apple.security.cs.allow-jit + + com.apple.security.cs.allow-unsigned-executable-memory + + com.apple.security.cs.disable-library-validation + + com.apple.security.device.bluetooth + + + diff --git a/desktop/src/main/kotlin/org/meshtastic/desktop/Main.kt b/desktop/src/main/kotlin/org/meshtastic/desktop/Main.kt index 25a5b8ce3..8b33a3612 100644 --- a/desktop/src/main/kotlin/org/meshtastic/desktop/Main.kt +++ b/desktop/src/main/kotlin/org/meshtastic/desktop/Main.kt @@ -60,9 +60,7 @@ import kotlinx.coroutines.flow.first import okio.Path.Companion.toPath import org.jetbrains.compose.resources.decodeToSvgPainter import org.koin.compose.koinInject -import org.koin.compose.viewmodel.koinViewModel import org.koin.core.context.startKoin -import org.koin.core.context.stopKoin import org.meshtastic.core.common.BuildConfigProvider import org.meshtastic.core.common.util.MeshtasticUri import org.meshtastic.core.database.desktopDataDir @@ -107,12 +105,13 @@ private fun svgPainterResource(path: String, density: Density): Painter = rememb @OptIn(ExperimentalCoilApi::class) fun main(args: Array) = application(exitProcessOnExit = false) { - Logger.i { "Meshtastic Desktop — Starting" } - - remember { startKoin { modules(desktopPlatformModule(), desktopModule()) } } - DisposableEffect(Unit) { onDispose { stopKoin() } } - - val uiViewModel = koinViewModel() + val koinApp = remember { + Logger.i { "Meshtastic Desktop — Starting" } + startKoin { modules(desktopPlatformModule(), desktopModule()) } + } + val systemLocale = remember { Locale.getDefault() } + val uiViewModel = remember { koinApp.koin.get() } + val httpClient = remember { koinApp.koin.get() } DeepLinkHandler(args, uiViewModel) MeshServiceLifecycle()