mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
refactor: leverage CMP 1.11 + Lifecycle 2.11 — v2 test API, Json privacy, dropUnlessResumed nav guards (#5112)
This commit is contained in:
parent
76386e419c
commit
938a951737
20 changed files with 114 additions and 63 deletions
|
|
@ -32,6 +32,7 @@ class DeviceHardwareJsonDataSourceImpl(private val application: Application) : D
|
|||
private val json = Json {
|
||||
ignoreUnknownKeys = true
|
||||
isLenient = true
|
||||
exceptionsWithDebugInfo = false
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ class FirmwareReleaseJsonDataSourceImpl(private val application: Application) :
|
|||
private val json = Json {
|
||||
ignoreUnknownKeys = true
|
||||
isLenient = true
|
||||
exceptionsWithDebugInfo = false
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ package org.meshtastic.core.ui.component
|
|||
import androidx.compose.ui.test.ExperimentalTestApi
|
||||
import androidx.compose.ui.test.assertIsDisplayed
|
||||
import androidx.compose.ui.test.onNodeWithText
|
||||
import androidx.compose.ui.test.runComposeUiTest
|
||||
import androidx.compose.ui.test.v2.runComposeUiTest
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.test.UnconfinedTestDispatcher
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import androidx.compose.ui.test.assertIsDisplayed
|
|||
import androidx.compose.ui.test.onNodeWithTag
|
||||
import androidx.compose.ui.test.onNodeWithText
|
||||
import androidx.compose.ui.test.performClick
|
||||
import androidx.compose.ui.test.runComposeUiTest
|
||||
import androidx.compose.ui.test.v2.runComposeUiTest
|
||||
import org.meshtastic.core.ui.util.LocalBarcodeScannerSupported
|
||||
import org.meshtastic.core.ui.util.LocalNfcScannerSupported
|
||||
import org.meshtastic.proto.SharedContact
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import androidx.compose.ui.test.ExperimentalTestApi
|
|||
import androidx.compose.ui.test.assertIsDisplayed
|
||||
import androidx.compose.ui.test.onNodeWithText
|
||||
import androidx.compose.ui.test.performClick
|
||||
import androidx.compose.ui.test.runComposeUiTest
|
||||
import androidx.compose.ui.test.v2.runComposeUiTest
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
|
|
|
|||
|
|
@ -32,8 +32,8 @@ fun EntryProviderScope<NavKey>.connectionsGraph(backStack: NavBackStack<NavKey>)
|
|||
ConnectionsScreen(
|
||||
scanModel = koinViewModel<ScannerViewModel>(),
|
||||
radioConfigViewModel = koinViewModel<RadioConfigViewModel>(),
|
||||
onClickNodeChip = { backStack.add(NodesRoute.NodeDetail(it)) },
|
||||
onNavigateToNodeDetails = { backStack.add(NodesRoute.NodeDetail(it)) },
|
||||
onClickNodeChip = { id -> backStack.add(NodesRoute.NodeDetail(id)) },
|
||||
onNavigateToNodeDetails = { id -> backStack.add(NodesRoute.NodeDetail(id)) },
|
||||
onConfigNavigate = { route -> backStack.add(route) },
|
||||
)
|
||||
}
|
||||
|
|
@ -42,8 +42,8 @@ fun EntryProviderScope<NavKey>.connectionsGraph(backStack: NavBackStack<NavKey>)
|
|||
ConnectionsScreen(
|
||||
scanModel = koinViewModel<ScannerViewModel>(),
|
||||
radioConfigViewModel = koinViewModel<RadioConfigViewModel>(),
|
||||
onClickNodeChip = { backStack.add(NodesRoute.NodeDetail(it)) },
|
||||
onNavigateToNodeDetails = { backStack.add(NodesRoute.NodeDetail(it)) },
|
||||
onClickNodeChip = { id -> backStack.add(NodesRoute.NodeDetail(id)) },
|
||||
onNavigateToNodeDetails = { id -> backStack.add(NodesRoute.NodeDetail(id)) },
|
||||
onConfigNavigate = { route -> backStack.add(route) },
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
package org.meshtastic.feature.firmware
|
||||
|
||||
import co.touchlab.kermit.Logger
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.json.Json
|
||||
import org.koin.core.annotation.Single
|
||||
import org.meshtastic.core.database.entity.FirmwareRelease
|
||||
|
|
@ -29,7 +30,11 @@ private const val FIRMWARE_BASE_URL = "https://raw.githubusercontent.com/meshtas
|
|||
/** OTA partition role in .mt.json manifests — the main application firmware. */
|
||||
private const val OTA_PART_NAME = "app0"
|
||||
|
||||
private val manifestJson = Json { ignoreUnknownKeys = true }
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
private val manifestJson = Json {
|
||||
ignoreUnknownKeys = true
|
||||
exceptionsWithDebugInfo = false
|
||||
}
|
||||
|
||||
/** Retrieves firmware files, either by direct download or by extracting from a release asset zip. */
|
||||
@Single
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
package org.meshtastic.feature.firmware.navigation
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.lifecycle.compose.dropUnlessResumed
|
||||
import androidx.navigation3.runtime.EntryProviderScope
|
||||
import androidx.navigation3.runtime.NavBackStack
|
||||
import androidx.navigation3.runtime.NavKey
|
||||
|
|
@ -27,8 +28,12 @@ import org.meshtastic.feature.firmware.FirmwareUpdateViewModel
|
|||
|
||||
/** Registers the firmware update screen entries into the Navigation 3 entry provider. */
|
||||
fun EntryProviderScope<NavKey>.firmwareGraph(backStack: NavBackStack<NavKey>) {
|
||||
entry<FirmwareRoute.FirmwareGraph> { FirmwareScreen(onNavigateUp = { backStack.removeLastOrNull() }) }
|
||||
entry<FirmwareRoute.FirmwareUpdate> { FirmwareScreen(onNavigateUp = { backStack.removeLastOrNull() }) }
|
||||
entry<FirmwareRoute.FirmwareGraph> {
|
||||
FirmwareScreen(onNavigateUp = dropUnlessResumed { backStack.removeLastOrNull() })
|
||||
}
|
||||
entry<FirmwareRoute.FirmwareUpdate> {
|
||||
FirmwareScreen(onNavigateUp = dropUnlessResumed { backStack.removeLastOrNull() })
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
|
|||
|
|
@ -21,7 +21,11 @@ import kotlinx.serialization.ExperimentalSerializationApi
|
|||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonDecodingException
|
||||
|
||||
private val json = Json { ignoreUnknownKeys = true }
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
private val json = Json {
|
||||
ignoreUnknownKeys = true
|
||||
exceptionsWithDebugInfo = false
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse pre-extracted zip entries into a [DfuZipPackage].
|
||||
|
|
|
|||
|
|
@ -26,8 +26,8 @@ fun EntryProviderScope<NavKey>.mapGraph(backStack: NavBackStack<NavKey>) {
|
|||
entry<MapRoute.Map> { args ->
|
||||
val mapScreen = org.meshtastic.core.ui.util.LocalMapMainScreenProvider.current
|
||||
mapScreen(
|
||||
{ backStack.add(NodesRoute.NodeDetail(it)) }, // onClickNodeChip
|
||||
{ backStack.add(NodesRoute.NodeDetail(it)) }, // navigateToNodeDetails
|
||||
{ id -> backStack.add(NodesRoute.NodeDetail(id)) }, // onClickNodeChip
|
||||
{ id -> backStack.add(NodesRoute.NodeDetail(id)) }, // navigateToNodeDetails
|
||||
args.waypointId,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import androidx.compose.material3.adaptive.navigation3.ListDetailSceneStrategy
|
|||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.lifecycle.compose.dropUnlessResumed
|
||||
import androidx.navigation3.runtime.EntryProviderScope
|
||||
import androidx.navigation3.runtime.NavBackStack
|
||||
import androidx.navigation3.runtime.NavKey
|
||||
|
|
@ -61,9 +62,10 @@ fun EntryProviderScope<NavKey>.contactsGraph(
|
|||
contactKey = contactKey,
|
||||
message = args.message,
|
||||
viewModel = messageViewModel,
|
||||
navigateToNodeDetails = { backStack.add(NodesRoute.NodeDetail(it)) },
|
||||
navigateToQuickChatOptions = { backStack.add(org.meshtastic.core.navigation.ContactsRoute.QuickChat) },
|
||||
onNavigateBack = { backStack.removeLastOrNull() },
|
||||
navigateToNodeDetails = { id -> backStack.add(NodesRoute.NodeDetail(id)) },
|
||||
navigateToQuickChatOptions =
|
||||
dropUnlessResumed { backStack.add(org.meshtastic.core.navigation.ContactsRoute.QuickChat) },
|
||||
onNavigateBack = dropUnlessResumed { backStack.removeLastOrNull() },
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -73,13 +75,13 @@ fun EntryProviderScope<NavKey>.contactsGraph(
|
|||
ShareScreen(
|
||||
viewModel = viewModel,
|
||||
onConfirm = { contactKey -> backStack.replaceLast(ContactsRoute.Messages(contactKey, message)) },
|
||||
onNavigateUp = { backStack.removeLastOrNull() },
|
||||
onNavigateUp = dropUnlessResumed { backStack.removeLastOrNull() },
|
||||
)
|
||||
}
|
||||
|
||||
entry<ContactsRoute.QuickChat>(metadata = { ListDetailSceneStrategy.extraPane() }) {
|
||||
val viewModel = koinViewModel<QuickChatViewModel>()
|
||||
QuickChatScreen(viewModel = viewModel, onNavigateUp = { backStack.removeLastOrNull() })
|
||||
QuickChatScreen(viewModel = viewModel, onNavigateUp = dropUnlessResumed { backStack.removeLastOrNull() })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ package org.meshtastic.feature.messaging.component
|
|||
import androidx.compose.ui.test.ExperimentalTestApi
|
||||
import androidx.compose.ui.test.assertIsDisplayed
|
||||
import androidx.compose.ui.test.onNodeWithContentDescription
|
||||
import androidx.compose.ui.test.runComposeUiTest
|
||||
import androidx.compose.ui.test.v2.runComposeUiTest
|
||||
import org.meshtastic.core.common.util.nowMillis
|
||||
import org.meshtastic.core.model.Message
|
||||
import org.meshtastic.core.model.MessageStatus
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ package org.meshtastic.feature.node.navigation
|
|||
import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
|
||||
import androidx.compose.material3.adaptive.navigation3.ListDetailSceneStrategy
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.lifecycle.compose.dropUnlessResumed
|
||||
import androidx.navigation3.runtime.EntryProviderScope
|
||||
import androidx.navigation3.runtime.NavBackStack
|
||||
import androidx.navigation3.runtime.NavKey
|
||||
|
|
@ -116,9 +117,9 @@ fun EntryProviderScope<NavKey>.nodeDetailGraph(
|
|||
nodeId = destNum,
|
||||
viewModel = nodeDetailViewModel,
|
||||
compassViewModel = compassViewModel,
|
||||
navigateToMessages = { backStack.add(ContactsRoute.Messages(it)) },
|
||||
onNavigate = { backStack.add(it) },
|
||||
onNavigateUp = { backStack.removeLastOrNull() },
|
||||
navigateToMessages = { key -> backStack.add(ContactsRoute.Messages(key)) },
|
||||
onNavigate = { route -> backStack.add(route) },
|
||||
onNavigateUp = dropUnlessResumed { backStack.removeLastOrNull() },
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -128,7 +129,7 @@ fun EntryProviderScope<NavKey>.nodeDetailGraph(
|
|||
|
||||
TracerouteLogScreen(
|
||||
viewModel = metricsViewModel,
|
||||
onNavigateUp = { backStack.removeLastOrNull() },
|
||||
onNavigateUp = dropUnlessResumed { backStack.removeLastOrNull() },
|
||||
onViewOnMap = { requestId, responseLogUuid ->
|
||||
backStack.add(
|
||||
NodeDetailRoute.TracerouteMap(
|
||||
|
|
@ -182,7 +183,7 @@ private inline fun <reified R : Route> EntryProviderScope<NavKey>.addNodeDetailS
|
|||
val metricsViewModel = koinViewModel<MetricsViewModel> { parametersOf(destNum) }
|
||||
metricsViewModel.setNodeId(destNum)
|
||||
|
||||
routeInfo.screenComposable(metricsViewModel) { backStack.removeLastOrNull() }
|
||||
routeInfo.screenComposable(metricsViewModel, dropUnlessResumed { backStack.removeLastOrNull() })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import androidx.compose.runtime.SideEffect
|
|||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.lifecycle.compose.dropUnlessResumed
|
||||
import androidx.navigation3.runtime.EntryProviderScope
|
||||
import androidx.navigation3.runtime.NavBackStack
|
||||
import androidx.navigation3.runtime.NavKey
|
||||
|
|
@ -106,7 +107,7 @@ fun EntryProviderScope<NavKey>.settingsGraph(backStack: NavBackStack<NavKey>) {
|
|||
entry<SettingsRoute.DeviceConfiguration> {
|
||||
DeviceConfigurationScreen(
|
||||
viewModel = getRadioConfigViewModel(backStack),
|
||||
onBack = { backStack.removeLastOrNull() },
|
||||
onBack = dropUnlessResumed { backStack.removeLastOrNull() },
|
||||
onNavigate = { route -> backStack.add(route) },
|
||||
)
|
||||
}
|
||||
|
|
@ -117,13 +118,16 @@ fun EntryProviderScope<NavKey>.settingsGraph(backStack: NavBackStack<NavKey>) {
|
|||
ModuleConfigurationScreen(
|
||||
viewModel = getRadioConfigViewModel(backStack),
|
||||
excludedModulesUnlocked = excludedModulesUnlocked,
|
||||
onBack = { backStack.removeLastOrNull() },
|
||||
onBack = dropUnlessResumed { backStack.removeLastOrNull() },
|
||||
onNavigate = { route -> backStack.add(route) },
|
||||
)
|
||||
}
|
||||
|
||||
entry<SettingsRoute.Administration> {
|
||||
AdministrationScreen(viewModel = getRadioConfigViewModel(backStack), onBack = { backStack.removeLastOrNull() })
|
||||
AdministrationScreen(
|
||||
viewModel = getRadioConfigViewModel(backStack),
|
||||
onBack = dropUnlessResumed { backStack.removeLastOrNull() },
|
||||
)
|
||||
}
|
||||
|
||||
entry<SettingsRoute.CleanNodeDb> {
|
||||
|
|
@ -135,16 +139,26 @@ fun EntryProviderScope<NavKey>.settingsGraph(backStack: NavBackStack<NavKey>) {
|
|||
configComposable(routeInfo.route::class, backStack) { viewModel ->
|
||||
LaunchedEffect(Unit) { viewModel.setResponseStateLoading(routeInfo) }
|
||||
when (routeInfo) {
|
||||
ConfigRoute.USER -> UserConfigScreen(viewModel, onBack = { backStack.removeLastOrNull() })
|
||||
ConfigRoute.CHANNELS -> ChannelConfigScreen(viewModel, onBack = { backStack.removeLastOrNull() })
|
||||
ConfigRoute.DEVICE -> DeviceConfigScreenCommon(viewModel, onBack = { backStack.removeLastOrNull() })
|
||||
ConfigRoute.POSITION -> PositionConfigScreenCommon(viewModel, onBack = { backStack.removeLastOrNull() })
|
||||
ConfigRoute.POWER -> PowerConfigScreen(viewModel, onBack = { backStack.removeLastOrNull() })
|
||||
ConfigRoute.NETWORK -> NetworkConfigScreen(viewModel, onBack = { backStack.removeLastOrNull() })
|
||||
ConfigRoute.DISPLAY -> DisplayConfigScreen(viewModel, onBack = { backStack.removeLastOrNull() })
|
||||
ConfigRoute.LORA -> LoRaConfigScreen(viewModel, onBack = { backStack.removeLastOrNull() })
|
||||
ConfigRoute.BLUETOOTH -> BluetoothConfigScreen(viewModel, onBack = { backStack.removeLastOrNull() })
|
||||
ConfigRoute.SECURITY -> SecurityConfigScreenCommon(viewModel, onBack = { backStack.removeLastOrNull() })
|
||||
ConfigRoute.USER ->
|
||||
UserConfigScreen(viewModel, onBack = dropUnlessResumed { backStack.removeLastOrNull() })
|
||||
ConfigRoute.CHANNELS ->
|
||||
ChannelConfigScreen(viewModel, onBack = dropUnlessResumed { backStack.removeLastOrNull() })
|
||||
ConfigRoute.DEVICE ->
|
||||
DeviceConfigScreenCommon(viewModel, onBack = dropUnlessResumed { backStack.removeLastOrNull() })
|
||||
ConfigRoute.POSITION ->
|
||||
PositionConfigScreenCommon(viewModel, onBack = dropUnlessResumed { backStack.removeLastOrNull() })
|
||||
ConfigRoute.POWER ->
|
||||
PowerConfigScreen(viewModel, onBack = dropUnlessResumed { backStack.removeLastOrNull() })
|
||||
ConfigRoute.NETWORK ->
|
||||
NetworkConfigScreen(viewModel, onBack = dropUnlessResumed { backStack.removeLastOrNull() })
|
||||
ConfigRoute.DISPLAY ->
|
||||
DisplayConfigScreen(viewModel, onBack = dropUnlessResumed { backStack.removeLastOrNull() })
|
||||
ConfigRoute.LORA ->
|
||||
LoRaConfigScreen(viewModel, onBack = dropUnlessResumed { backStack.removeLastOrNull() })
|
||||
ConfigRoute.BLUETOOTH ->
|
||||
BluetoothConfigScreen(viewModel, onBack = dropUnlessResumed { backStack.removeLastOrNull() })
|
||||
ConfigRoute.SECURITY ->
|
||||
SecurityConfigScreenCommon(viewModel, onBack = dropUnlessResumed { backStack.removeLastOrNull() })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -153,50 +167,63 @@ fun EntryProviderScope<NavKey>.settingsGraph(backStack: NavBackStack<NavKey>) {
|
|||
configComposable(routeInfo.route::class, backStack) { viewModel ->
|
||||
LaunchedEffect(Unit) { viewModel.setResponseStateLoading(routeInfo) }
|
||||
when (routeInfo) {
|
||||
ModuleRoute.MQTT -> MQTTConfigScreen(viewModel, onBack = { backStack.removeLastOrNull() })
|
||||
ModuleRoute.SERIAL -> SerialConfigScreen(viewModel, onBack = { backStack.removeLastOrNull() })
|
||||
ModuleRoute.MQTT ->
|
||||
MQTTConfigScreen(viewModel, onBack = dropUnlessResumed { backStack.removeLastOrNull() })
|
||||
ModuleRoute.SERIAL ->
|
||||
SerialConfigScreen(viewModel, onBack = dropUnlessResumed { backStack.removeLastOrNull() })
|
||||
ModuleRoute.EXT_NOTIFICATION ->
|
||||
ExternalNotificationConfigScreenCommon(
|
||||
viewModel = viewModel,
|
||||
onBack = { backStack.removeLastOrNull() },
|
||||
onBack = dropUnlessResumed { backStack.removeLastOrNull() },
|
||||
)
|
||||
ModuleRoute.STORE_FORWARD ->
|
||||
StoreForwardConfigScreen(viewModel, onBack = { backStack.removeLastOrNull() })
|
||||
ModuleRoute.RANGE_TEST -> RangeTestConfigScreen(viewModel, onBack = { backStack.removeLastOrNull() })
|
||||
ModuleRoute.TELEMETRY -> TelemetryConfigScreen(viewModel, onBack = { backStack.removeLastOrNull() })
|
||||
StoreForwardConfigScreen(viewModel, onBack = dropUnlessResumed { backStack.removeLastOrNull() })
|
||||
ModuleRoute.RANGE_TEST ->
|
||||
RangeTestConfigScreen(viewModel, onBack = dropUnlessResumed { backStack.removeLastOrNull() })
|
||||
ModuleRoute.TELEMETRY ->
|
||||
TelemetryConfigScreen(viewModel, onBack = dropUnlessResumed { backStack.removeLastOrNull() })
|
||||
ModuleRoute.CANNED_MESSAGE ->
|
||||
CannedMessageConfigScreen(viewModel, onBack = { backStack.removeLastOrNull() })
|
||||
ModuleRoute.AUDIO -> AudioConfigScreen(viewModel, onBack = { backStack.removeLastOrNull() })
|
||||
CannedMessageConfigScreen(viewModel, onBack = dropUnlessResumed { backStack.removeLastOrNull() })
|
||||
ModuleRoute.AUDIO ->
|
||||
AudioConfigScreen(viewModel, onBack = dropUnlessResumed { backStack.removeLastOrNull() })
|
||||
ModuleRoute.REMOTE_HARDWARE ->
|
||||
RemoteHardwareConfigScreen(viewModel, onBack = { backStack.removeLastOrNull() })
|
||||
RemoteHardwareConfigScreen(viewModel, onBack = dropUnlessResumed { backStack.removeLastOrNull() })
|
||||
ModuleRoute.NEIGHBOR_INFO ->
|
||||
NeighborInfoConfigScreen(viewModel, onBack = { backStack.removeLastOrNull() })
|
||||
NeighborInfoConfigScreen(viewModel, onBack = dropUnlessResumed { backStack.removeLastOrNull() })
|
||||
ModuleRoute.AMBIENT_LIGHTING ->
|
||||
AmbientLightingConfigScreen(viewModel, onBack = { backStack.removeLastOrNull() })
|
||||
AmbientLightingConfigScreen(viewModel, onBack = dropUnlessResumed { backStack.removeLastOrNull() })
|
||||
ModuleRoute.DETECTION_SENSOR ->
|
||||
DetectionSensorConfigScreen(viewModel, onBack = { backStack.removeLastOrNull() })
|
||||
ModuleRoute.PAXCOUNTER -> PaxcounterConfigScreen(viewModel, onBack = { backStack.removeLastOrNull() })
|
||||
DetectionSensorConfigScreen(viewModel, onBack = dropUnlessResumed { backStack.removeLastOrNull() })
|
||||
ModuleRoute.PAXCOUNTER ->
|
||||
PaxcounterConfigScreen(viewModel, onBack = dropUnlessResumed { backStack.removeLastOrNull() })
|
||||
ModuleRoute.STATUS_MESSAGE ->
|
||||
StatusMessageConfigScreen(viewModel, onBack = { backStack.removeLastOrNull() })
|
||||
StatusMessageConfigScreen(viewModel, onBack = dropUnlessResumed { backStack.removeLastOrNull() })
|
||||
ModuleRoute.TRAFFIC_MANAGEMENT ->
|
||||
TrafficManagementConfigScreen(viewModel, onBack = { backStack.removeLastOrNull() })
|
||||
ModuleRoute.TAK -> TAKConfigScreen(viewModel, onBack = { backStack.removeLastOrNull() })
|
||||
TrafficManagementConfigScreen(
|
||||
viewModel,
|
||||
onBack = dropUnlessResumed { backStack.removeLastOrNull() },
|
||||
)
|
||||
ModuleRoute.TAK ->
|
||||
TAKConfigScreen(viewModel, onBack = dropUnlessResumed { backStack.removeLastOrNull() })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
entry<SettingsRoute.DebugPanel> {
|
||||
val viewModel: DebugViewModel = koinViewModel()
|
||||
DebugScreen(viewModel = viewModel, onNavigateUp = { backStack.removeLastOrNull() })
|
||||
DebugScreen(viewModel = viewModel, onNavigateUp = dropUnlessResumed { backStack.removeLastOrNull() })
|
||||
}
|
||||
|
||||
entry<SettingsRoute.About> {
|
||||
AboutScreen(onNavigateUp = { backStack.removeLastOrNull() }, jsonProvider = { getAboutLibrariesJson() })
|
||||
AboutScreen(
|
||||
onNavigateUp = dropUnlessResumed { backStack.removeLastOrNull() },
|
||||
jsonProvider = { getAboutLibrariesJson() },
|
||||
)
|
||||
}
|
||||
|
||||
entry<SettingsRoute.FilterSettings> {
|
||||
val viewModel: FilterSettingsViewModel = koinViewModel()
|
||||
FilterSettingsScreen(viewModel = viewModel, onBack = { backStack.removeLastOrNull() })
|
||||
FilterSettingsScreen(viewModel = viewModel, onBack = dropUnlessResumed { backStack.removeLastOrNull() })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
*/
|
||||
package org.meshtastic.feature.settings.radio.channel
|
||||
|
||||
import androidx.lifecycle.compose.dropUnlessResumed
|
||||
import androidx.navigation3.runtime.EntryProviderScope
|
||||
import androidx.navigation3.runtime.NavBackStack
|
||||
import androidx.navigation3.runtime.NavKey
|
||||
|
|
@ -29,7 +30,7 @@ fun EntryProviderScope<NavKey>.channelsGraph(backStack: NavBackStack<NavKey>) {
|
|||
ChannelScreen(
|
||||
radioConfigViewModel = koinViewModel<RadioConfigViewModel>(),
|
||||
onNavigate = { route -> backStack.add(route) },
|
||||
onNavigateUp = { backStack.removeLastOrNull() },
|
||||
onNavigateUp = dropUnlessResumed { backStack.removeLastOrNull() },
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -37,7 +38,7 @@ fun EntryProviderScope<NavKey>.channelsGraph(backStack: NavBackStack<NavKey>) {
|
|||
ChannelScreen(
|
||||
radioConfigViewModel = koinViewModel<RadioConfigViewModel>(),
|
||||
onNavigate = { route -> backStack.add(route) },
|
||||
onNavigateUp = { backStack.removeLastOrNull() },
|
||||
onNavigateUp = dropUnlessResumed { backStack.removeLastOrNull() },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ import androidx.compose.ui.test.onNodeWithContentDescription
|
|||
import androidx.compose.ui.test.onNodeWithText
|
||||
import androidx.compose.ui.test.performClick
|
||||
import androidx.compose.ui.test.performTextInput
|
||||
import androidx.compose.ui.test.runComposeUiTest
|
||||
import androidx.compose.ui.test.v2.runComposeUiTest
|
||||
import androidx.compose.ui.unit.dp
|
||||
import org.meshtastic.core.resources.Res
|
||||
import org.meshtastic.core.resources.debug_active_filters
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import androidx.compose.ui.test.ExperimentalTestApi
|
|||
import androidx.compose.ui.test.assertIsDisplayed
|
||||
import androidx.compose.ui.test.onNodeWithText
|
||||
import androidx.compose.ui.test.performClick
|
||||
import androidx.compose.ui.test.runComposeUiTest
|
||||
import androidx.compose.ui.test.v2.runComposeUiTest
|
||||
import org.meshtastic.core.resources.Res
|
||||
import org.meshtastic.core.resources.cancel
|
||||
import org.meshtastic.core.resources.getString
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import androidx.compose.ui.test.ExperimentalTestApi
|
|||
import androidx.compose.ui.test.assertIsDisplayed
|
||||
import androidx.compose.ui.test.onNodeWithText
|
||||
import androidx.compose.ui.test.performClick
|
||||
import androidx.compose.ui.test.runComposeUiTest
|
||||
import androidx.compose.ui.test.v2.runComposeUiTest
|
||||
import org.meshtastic.core.resources.Res
|
||||
import org.meshtastic.core.resources.getString
|
||||
import org.meshtastic.core.resources.i_agree
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
*/
|
||||
package org.meshtastic.feature.wifiprovision.domain
|
||||
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.Json
|
||||
|
|
@ -33,9 +34,11 @@ import kotlinx.serialization.json.Json
|
|||
// Shared JSON codec — lenient so unknown fields are silently ignored
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
internal val NymeaJson = Json {
|
||||
ignoreUnknownKeys = true
|
||||
isLenient = true
|
||||
exceptionsWithDebugInfo = false
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
*/
|
||||
package org.meshtastic.feature.wifiprovision.navigation
|
||||
|
||||
import androidx.lifecycle.compose.dropUnlessResumed
|
||||
import androidx.navigation3.runtime.EntryProviderScope
|
||||
import androidx.navigation3.runtime.NavBackStack
|
||||
import androidx.navigation3.runtime.NavKey
|
||||
|
|
@ -31,9 +32,9 @@ import org.meshtastic.feature.wifiprovision.ui.WifiProvisionScreen
|
|||
*/
|
||||
fun EntryProviderScope<NavKey>.wifiProvisionGraph(backStack: NavBackStack<NavKey>) {
|
||||
entry<WifiProvisionRoute.WifiProvisionGraph> {
|
||||
WifiProvisionScreen(onNavigateUp = { backStack.removeLastOrNull() })
|
||||
WifiProvisionScreen(onNavigateUp = dropUnlessResumed { backStack.removeLastOrNull() })
|
||||
}
|
||||
entry<WifiProvisionRoute.WifiProvision> { key ->
|
||||
WifiProvisionScreen(onNavigateUp = { backStack.removeLastOrNull() }, address = key.address)
|
||||
WifiProvisionScreen(onNavigateUp = dropUnlessResumed { backStack.removeLastOrNull() }, address = key.address)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue