feat: Migrate project to Kotlin Multiplatform (KMP) architecture (#4738)

Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>
This commit is contained in:
James Rich 2026-03-06 20:43:45 -06:00 committed by GitHub
parent 182ad933f4
commit 0ce322a0f5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
163 changed files with 1837 additions and 877 deletions

View file

@ -39,8 +39,6 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.core.net.toUri
import org.jetbrains.compose.resources.stringResource
import org.meshtastic.core.barcode.rememberBarcodeScanner
import org.meshtastic.core.nfc.NfcScannerEffect
import org.meshtastic.core.resources.Res
import org.meshtastic.core.resources.cancel
import org.meshtastic.core.resources.import_label
@ -60,6 +58,8 @@ import org.meshtastic.core.resources.url
import org.meshtastic.core.ui.icon.MeshtasticIcons
import org.meshtastic.core.ui.icon.QrCode2
import org.meshtastic.core.ui.theme.AppTheme
import org.meshtastic.core.ui.util.LocalBarcodeScannerProvider
import org.meshtastic.core.ui.util.LocalNfcScannerProvider
import org.meshtastic.core.ui.util.openNfcSettings
import org.meshtastic.proto.SharedContact
@ -98,17 +98,18 @@ fun MeshtasticImportFAB(
var showNfcDisabledDialog by remember { mutableStateOf(false) }
val context = LocalContext.current
val barcodeScanner = rememberBarcodeScanner(onResult = { contents -> contents?.toUri()?.let { onImport(it) } })
val barcodeScanner = LocalBarcodeScannerProvider.current { contents -> contents?.toUri()?.let { onImport(it) } }
val nfcScanner = LocalNfcScannerProvider.current
if (isNfcScanning) {
NfcScannerEffect(
onResult = { contents ->
nfcScanner(
{ contents ->
contents?.toUri()?.let {
onImport(it)
isNfcScanning = false
}
},
onNfcDisabled = {
{
isNfcScanning = false
showNfcDisabledDialog = true
},

View file

@ -0,0 +1,21 @@
/*
* Copyright (c) 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.core.ui.util
interface BarcodeScanner {
fun startScan()
}

View file

@ -0,0 +1,22 @@
/*
* Copyright (c) 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.core.ui.util
import androidx.compose.runtime.Composable
import androidx.compose.runtime.compositionLocalOf
val LocalAnalyticsIntroProvider = compositionLocalOf<@Composable () -> Unit> { {} }

View file

@ -0,0 +1,31 @@
/*
* Copyright (c) 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.core.ui.util
import androidx.compose.runtime.Composable
import androidx.compose.runtime.compositionLocalOf
val LocalBarcodeScannerProvider =
compositionLocalOf<@Composable (onResult: (String?) -> Unit) -> BarcodeScanner> {
{
object : BarcodeScanner {
override fun startScan() {
// Default NO-OP
}
}
}
}

View file

@ -0,0 +1,23 @@
/*
* Copyright (c) 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.core.ui.util
import androidx.compose.runtime.Composable
import androidx.compose.runtime.compositionLocalOf
val LocalNfcScannerProvider =
compositionLocalOf<@Composable (onResult: (String?) -> Unit, onNfcDisabled: () -> Unit) -> Unit> { { _, _ -> } }

View file

@ -0,0 +1,43 @@
/*
* Copyright (c) 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.core.ui.util
import androidx.compose.runtime.Composable
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.ui.Modifier
/**
* Interface for providing a flavored MapView. This allows the map feature to be decoupled from specific map
* implementations (Google Maps vs osmdroid).
*/
interface MapViewProvider {
@Composable
fun MapView(
modifier: Modifier,
// We use Any here to avoid circular dependency with feature:map
viewModel: Any,
navigateToNodeDetails: (Int) -> Unit,
focusedNodeNum: Int? = null,
// Using List<Any> to avoid dependency on proto.Position if needed
nodeTracks: List<Any>? = null,
tracerouteOverlay: Any? = null,
tracerouteNodePositions: Map<Int, Any> = emptyMap(),
onTracerouteMappableCountChanged: (Int, Int) -> Unit = { _, _ -> },
)
}
val LocalMapViewProvider = compositionLocalOf<MapViewProvider?> { null }