mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-03-28 02:32:24 -04:00
refactor: streamline main screen navigation and ViewModel injection
- Update `MainScreen` (Android) and `DesktopMainScreen` to manage their own `NavBackStack` initialization internally. - Refactor `MainScreen` to obtain `UIViewModel` via Koin injection instead of receiving it as a parameter from `MainActivity`. - Remove default bottom padding from `MeshtasticAppShell` and associated screen-level modifiers to allow for more flexible layout orchestration. - Simplify `DesktopMainScreen` by moving backstack management inside the composable and cleaning up the navigation provider logic. - Remove redundant lint suppressions in `Main.kt` following the simplification of the main screen composable structure. - Clean up imports and normalize the usage of `MeshtasticNavDisplay` and `MeshtasticNavigationSuite` across platforms.
This commit is contained in:
@@ -139,7 +139,7 @@ class MainActivity : ComponentActivity() {
|
||||
ReportDrawnWhen { true }
|
||||
|
||||
if (appIntroCompleted) {
|
||||
MainScreen(uIViewModel = model)
|
||||
MainScreen()
|
||||
} else {
|
||||
val introViewModel = koinViewModel<IntroViewModel>()
|
||||
AppIntroductionScreen(onDone = { model.onAppIntroCompleted() }, viewModel = introViewModel)
|
||||
|
||||
@@ -19,15 +19,12 @@
|
||||
package org.meshtastic.app.ui
|
||||
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.recalculateWindowInsets
|
||||
import androidx.compose.foundation.layout.safeDrawingPadding
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.navigation3.runtime.NavKey
|
||||
import androidx.navigation3.runtime.entryProvider
|
||||
@@ -43,6 +40,7 @@ import org.meshtastic.core.resources.app_too_old
|
||||
import org.meshtastic.core.resources.must_update
|
||||
import org.meshtastic.core.ui.component.MeshtasticAppShell
|
||||
import org.meshtastic.core.ui.component.MeshtasticNavDisplay
|
||||
import org.meshtastic.core.ui.component.MeshtasticNavigationSuite
|
||||
import org.meshtastic.core.ui.viewmodel.UIViewModel
|
||||
import org.meshtastic.feature.connections.navigation.connectionsGraph
|
||||
import org.meshtastic.feature.firmware.navigation.firmwareGraph
|
||||
@@ -52,38 +50,36 @@ import org.meshtastic.feature.node.navigation.nodesGraph
|
||||
import org.meshtastic.feature.settings.navigation.settingsGraph
|
||||
import org.meshtastic.feature.settings.radio.channel.channelsGraph
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Suppress("LongMethod", "CyclomaticComplexMethod")
|
||||
@Composable
|
||||
fun MainScreen(uIViewModel: UIViewModel = koinViewModel()) {
|
||||
fun MainScreen() {
|
||||
val viewModel: UIViewModel = koinViewModel()
|
||||
val backStack = rememberNavBackStack(MeshtasticNavSavedStateConfig, NodesRoutes.NodesGraph as NavKey)
|
||||
|
||||
AndroidAppVersionCheck(uIViewModel)
|
||||
AndroidAppVersionCheck(viewModel)
|
||||
|
||||
MeshtasticAppShell(
|
||||
backStack = backStack,
|
||||
uiViewModel = uIViewModel,
|
||||
hostModifier = Modifier.safeDrawingPadding().padding(bottom = 16.dp),
|
||||
uiViewModel = viewModel,
|
||||
hostModifier = Modifier,
|
||||
) {
|
||||
org.meshtastic.core.ui.component.MeshtasticNavigationSuite(
|
||||
MeshtasticNavigationSuite(
|
||||
backStack = backStack,
|
||||
uiViewModel = uIViewModel,
|
||||
uiViewModel = viewModel,
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
) {
|
||||
val provider =
|
||||
entryProvider<NavKey> {
|
||||
contactsGraph(backStack, uIViewModel.scrollToTopEventFlow)
|
||||
nodesGraph(
|
||||
backStack = backStack,
|
||||
scrollToTopEvents = uIViewModel.scrollToTopEventFlow,
|
||||
onHandleDeepLink = uIViewModel::handleDeepLink,
|
||||
)
|
||||
mapGraph(backStack)
|
||||
channelsGraph(backStack)
|
||||
connectionsGraph(backStack)
|
||||
settingsGraph(backStack)
|
||||
firmwareGraph(backStack)
|
||||
}
|
||||
val provider = entryProvider<NavKey> {
|
||||
contactsGraph(backStack, viewModel.scrollToTopEventFlow)
|
||||
nodesGraph(
|
||||
backStack = backStack,
|
||||
scrollToTopEvents = viewModel.scrollToTopEventFlow,
|
||||
onHandleDeepLink = viewModel::handleDeepLink,
|
||||
)
|
||||
mapGraph(backStack)
|
||||
channelsGraph(backStack)
|
||||
connectionsGraph(backStack)
|
||||
settingsGraph(backStack)
|
||||
firmwareGraph(backStack)
|
||||
}
|
||||
MeshtasticNavDisplay(
|
||||
backStack = backStack,
|
||||
entryProvider = provider,
|
||||
@@ -99,7 +95,6 @@ private fun AndroidAppVersionCheck(viewModel: UIViewModel) {
|
||||
val connectionState by viewModel.connectionState.collectAsStateWithLifecycle()
|
||||
val myNodeInfo by viewModel.myNodeInfo.collectAsStateWithLifecycle()
|
||||
|
||||
// Check if the device is running an old app version
|
||||
LaunchedEffect(connectionState, myNodeInfo) {
|
||||
if (connectionState == ConnectionState.Connected) {
|
||||
myNodeInfo?.let { info ->
|
||||
@@ -120,4 +115,4 @@ private fun AndroidAppVersionCheck(viewModel: UIViewModel) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,11 +16,9 @@
|
||||
*/
|
||||
package org.meshtastic.core.ui.component
|
||||
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation3.runtime.NavBackStack
|
||||
import androidx.navigation3.runtime.NavKey
|
||||
import org.meshtastic.core.navigation.NodeDetailRoutes
|
||||
@@ -36,7 +34,7 @@ import org.meshtastic.core.ui.viewmodel.UIViewModel
|
||||
fun MeshtasticAppShell(
|
||||
backStack: NavBackStack<NavKey>,
|
||||
uiViewModel: UIViewModel,
|
||||
hostModifier: Modifier = Modifier.padding(bottom = 16.dp),
|
||||
hostModifier: Modifier = Modifier,
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
LaunchedEffect(uiViewModel) {
|
||||
|
||||
@@ -321,7 +321,7 @@ fun main(args: Array<String>) = application(exitProcessOnExit = false) {
|
||||
// re-reads Locale.current and all stringResource() calls update. Unlike key(), this
|
||||
// preserves remembered state (including the navigation backstack).
|
||||
CompositionLocalProvider(LocalAppLocale provides localePref) {
|
||||
AppTheme(darkTheme = isDarkTheme) { DesktopMainScreen(backStack) }
|
||||
AppTheme(darkTheme = isDarkTheme) { DesktopMainScreen(uiViewModel) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,41 +18,37 @@ package org.meshtastic.desktop.ui
|
||||
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation3.runtime.NavBackStack
|
||||
import androidx.navigation3.runtime.NavKey
|
||||
import androidx.navigation3.runtime.entryProvider
|
||||
import org.koin.compose.viewmodel.koinViewModel
|
||||
import org.meshtastic.core.navigation.MeshtasticNavSavedStateConfig
|
||||
import org.meshtastic.core.navigation.NodesRoutes
|
||||
import org.meshtastic.core.ui.component.MeshtasticAppShell
|
||||
import org.meshtastic.core.ui.component.MeshtasticNavDisplay
|
||||
import org.meshtastic.core.ui.component.MeshtasticNavigationSuite
|
||||
import org.meshtastic.core.ui.viewmodel.UIViewModel
|
||||
import org.meshtastic.desktop.navigation.desktopNavGraph
|
||||
|
||||
/**
|
||||
* Desktop main screen — Navigation 3 shell with adaptive navigation and shared [MeshtasticNavDisplay].
|
||||
*
|
||||
* Uses the same shared routes from `core:navigation` and the same `MeshtasticNavDisplay` + `entryProvider` pattern as
|
||||
* the Android app, proving the shared backstack architecture works across targets.
|
||||
* Desktop main screen — uses shared navigation components.
|
||||
*/
|
||||
@Composable
|
||||
@Suppress("LongMethod")
|
||||
fun DesktopMainScreen(backStack: NavBackStack<NavKey>, uiViewModel: UIViewModel = koinViewModel()) {
|
||||
Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) {
|
||||
fun DesktopMainScreen(uiViewModel: UIViewModel) {
|
||||
val backStack = androidx.navigation3.runtime.rememberNavBackStack(MeshtasticNavSavedStateConfig, NodesRoutes.NodesGraph as NavKey)
|
||||
|
||||
Surface(modifier = Modifier.fillMaxSize()) {
|
||||
MeshtasticAppShell(
|
||||
backStack = backStack,
|
||||
uiViewModel = uiViewModel,
|
||||
hostModifier = Modifier.padding(bottom = 24.dp),
|
||||
) {
|
||||
org.meshtastic.core.ui.component.MeshtasticNavigationSuite(
|
||||
backStack = backStack,
|
||||
uiViewModel = uiViewModel,
|
||||
) {
|
||||
val provider = entryProvider<NavKey> { desktopNavGraph(backStack, uiViewModel) }
|
||||
|
||||
MeshtasticNavigationSuite(backStack = backStack, uiViewModel = uiViewModel, modifier = Modifier.fillMaxSize()) {
|
||||
val provider = entryProvider<NavKey> {
|
||||
desktopNavGraph(backStack, uiViewModel)
|
||||
}
|
||||
MeshtasticNavDisplay(backStack = backStack, entryProvider = provider, modifier = Modifier.fillMaxSize())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||
import com.google.accompanist.permissions.PermissionState
|
||||
import com.google.accompanist.permissions.rememberMultiplePermissionsState
|
||||
import com.google.accompanist.permissions.rememberPermissionState
|
||||
import org.meshtastic.core.ui.component.MeshtasticNavDisplay
|
||||
|
||||
/**
|
||||
* Main application introduction screen. This Composable hosts the navigation flow and hoists the permission states.
|
||||
@@ -56,7 +57,7 @@ fun AppIntroductionScreen(onDone: () -> Unit, viewModel: IntroViewModel) {
|
||||
|
||||
val backStack = rememberNavBackStack(Welcome)
|
||||
|
||||
org.meshtastic.core.ui.component.MeshtasticNavDisplay(
|
||||
MeshtasticNavDisplay(
|
||||
backStack = backStack,
|
||||
entryProvider =
|
||||
introNavGraph(
|
||||
|
||||
Reference in New Issue
Block a user