mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
Migrate App Intro to Navigation 3 (#2983)
This commit is contained in:
parent
0cb0b19128
commit
4ab588cdaa
4 changed files with 84 additions and 84 deletions
|
|
@ -232,6 +232,7 @@ dependencies {
|
|||
implementation(libs.bundles.adaptive)
|
||||
implementation(libs.bundles.lifecycle)
|
||||
implementation(libs.bundles.navigation)
|
||||
implementation(libs.bundles.navigation3)
|
||||
implementation(libs.bundles.coroutines)
|
||||
implementation(libs.bundles.datastore)
|
||||
implementation(libs.bundles.room)
|
||||
|
|
|
|||
|
|
@ -23,14 +23,17 @@ import android.os.Build
|
|||
import android.provider.Settings
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import androidx.navigation3.runtime.NavKey
|
||||
import androidx.navigation3.runtime.entry
|
||||
import androidx.navigation3.runtime.entryProvider
|
||||
import androidx.navigation3.runtime.rememberNavBackStack
|
||||
import androidx.navigation3.ui.NavDisplay
|
||||
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||
import com.google.accompanist.permissions.PermissionState
|
||||
import com.google.accompanist.permissions.isGranted
|
||||
import com.google.accompanist.permissions.rememberMultiplePermissionsState
|
||||
import com.google.accompanist.permissions.rememberPermissionState
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
* Composable function for the main application introduction screen. This screen guides the user through initial setup
|
||||
|
|
@ -43,7 +46,6 @@ import com.google.accompanist.permissions.rememberPermissionState
|
|||
@Composable
|
||||
fun AppIntroductionScreen(onDone: () -> Unit) {
|
||||
val context = LocalContext.current
|
||||
val navController = rememberNavController()
|
||||
|
||||
val notificationPermissionState: PermissionState? =
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
|
|
@ -56,56 +58,76 @@ fun AppIntroductionScreen(onDone: () -> Unit) {
|
|||
listOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION)
|
||||
val locationPermissionState = rememberMultiplePermissionsState(permissions = locationPermissions)
|
||||
|
||||
NavHost(navController = navController, startDestination = IntroRoute.Welcome.route) {
|
||||
composable(IntroRoute.Welcome.route) {
|
||||
WelcomeScreen(onGetStarted = { navController.navigate(IntroRoute.Notifications.route) })
|
||||
}
|
||||
composable(IntroRoute.Notifications.route) {
|
||||
val notificationsAlreadyGranted = notificationPermissionState?.status?.isGranted ?: true
|
||||
NotificationsScreen(
|
||||
showNextButton = notificationsAlreadyGranted,
|
||||
onSkip = { navController.navigate(IntroRoute.Location.route) },
|
||||
onConfigure = {
|
||||
if (notificationsAlreadyGranted) {
|
||||
navController.navigate(IntroRoute.CriticalAlerts.route)
|
||||
} else {
|
||||
// For Android Tiramisu (API 33) and above, this requests POST_NOTIFICATIONS
|
||||
// For lower versions, notificationPermissionState will be null, and this branch isn't taken.
|
||||
notificationPermissionState.launchPermissionRequest()
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
composable(IntroRoute.CriticalAlerts.route) {
|
||||
CriticalAlertsScreen(
|
||||
onSkip = { navController.navigate(IntroRoute.Location.route) },
|
||||
onConfigure = {
|
||||
// Intent to open the specific notification channel settings for "my_alerts"
|
||||
// This allows the user to enable critical alerts if they were initially denied
|
||||
// or to adjust settings for notifications that can bypass Do Not Disturb.
|
||||
val intent =
|
||||
Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS).apply {
|
||||
putExtra(Settings.EXTRA_APP_PACKAGE, context.packageName)
|
||||
putExtra(Settings.EXTRA_CHANNEL_ID, "my_alerts")
|
||||
val backStack = rememberNavBackStack(Welcome)
|
||||
|
||||
NavDisplay(
|
||||
backStack = backStack,
|
||||
onBack = { backStack.removeLastOrNull() },
|
||||
entryProvider =
|
||||
entryProvider {
|
||||
entry<Welcome> { WelcomeScreen(onGetStarted = { backStack.add(Notifications) }) }
|
||||
|
||||
entry<Notifications> {
|
||||
val notificationsAlreadyGranted = notificationPermissionState?.status?.isGranted ?: true
|
||||
NotificationsScreen(
|
||||
showNextButton = notificationsAlreadyGranted,
|
||||
onSkip = {
|
||||
// Skip this screen and the Critical Alerts screen. Proceed to Location screen.
|
||||
backStack.add(Location)
|
||||
},
|
||||
onConfigure = {
|
||||
if (notificationsAlreadyGranted) {
|
||||
backStack.add(CriticalAlerts)
|
||||
} else {
|
||||
// For Android Tiramisu (API 33) and above, this requests POST_NOTIFICATIONS
|
||||
// For lower versions, notificationPermissionState will be null, and this branch isn't
|
||||
// taken.
|
||||
notificationPermissionState?.launchPermissionRequest()
|
||||
}
|
||||
context.startActivity(intent)
|
||||
navController.navigate(IntroRoute.Location.route)
|
||||
},
|
||||
)
|
||||
}
|
||||
composable(IntroRoute.Location.route) {
|
||||
val locationAlreadyGranted = locationPermissionState.allPermissionsGranted
|
||||
LocationScreen(
|
||||
showNextButton = locationAlreadyGranted,
|
||||
onSkip = onDone, // Callback to signify completion of the intro flow
|
||||
onConfigure = {
|
||||
if (locationAlreadyGranted) {
|
||||
onDone() // Permissions already granted, proceed to finish
|
||||
} else {
|
||||
locationPermissionState.launchMultiplePermissionRequest()
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
entry<CriticalAlerts> {
|
||||
CriticalAlertsScreen(
|
||||
onSkip = { backStack.add(Location) },
|
||||
onConfigure = {
|
||||
// Intent to open the specific notification channel settings for "my_alerts"
|
||||
// This allows the user to enable critical alerts if they were initially denied
|
||||
// or to adjust settings for notifications that can bypass Do Not Disturb.
|
||||
val intent =
|
||||
Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS).apply {
|
||||
putExtra(Settings.EXTRA_APP_PACKAGE, context.packageName)
|
||||
putExtra(Settings.EXTRA_CHANNEL_ID, "my_alerts")
|
||||
}
|
||||
context.startActivity(intent)
|
||||
backStack.add(Location)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
entry<Location> {
|
||||
val locationAlreadyGranted = locationPermissionState.allPermissionsGranted
|
||||
LocationScreen(
|
||||
showNextButton = locationAlreadyGranted,
|
||||
onSkip = onDone, // Callback to signify completion of the intro flow
|
||||
onConfigure = {
|
||||
if (locationAlreadyGranted) {
|
||||
onDone() // Permissions already granted, proceed to finish
|
||||
} else {
|
||||
locationPermissionState.launchMultiplePermissionRequest()
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@Serializable private data object Welcome : NavKey
|
||||
|
||||
@Serializable private data object Notifications : NavKey
|
||||
|
||||
@Serializable private data object CriticalAlerts : NavKey
|
||||
|
||||
@Serializable private data object Location : NavKey
|
||||
|
|
|
|||
|
|
@ -1,29 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2025 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 com.geeksville.mesh.ui.intro
|
||||
|
||||
/** Sealed class defining type-safe navigation routes for the app introduction flow. */
|
||||
sealed class IntroRoute(val route: String) {
|
||||
object Welcome : IntroRoute("welcome")
|
||||
|
||||
object Notifications : IntroRoute("notifications")
|
||||
|
||||
object Location : IntroRoute("location")
|
||||
|
||||
object CriticalAlerts : IntroRoute("critical_alerts")
|
||||
}
|
||||
|
|
@ -38,6 +38,7 @@ material = "1.13.0"
|
|||
material3 = "1.5.0-alpha03"
|
||||
mgrs = "2.1.3"
|
||||
navigation = "2.9.3"
|
||||
navigation3 = "1.0.0-alpha08"
|
||||
okhttp = "5.1.0"
|
||||
org-eclipse-paho-client-mqttv3 = "1.2.5"
|
||||
osmbonuspack = "6.9.0"
|
||||
|
|
@ -129,6 +130,8 @@ material = { group = "com.google.android.material", name = "material", version.r
|
|||
mgrs = { group = "mil.nga", name = "mgrs", version.ref = "mgrs" }
|
||||
navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigation" }
|
||||
navigation-testing = { group = "androidx.navigation", name = "navigation-testing", version.ref = "navigation" }
|
||||
navigation3-runtime = { group = "androidx.navigation3", name = "navigation3-runtime", version.ref = "navigation3" }
|
||||
navigation3-ui = { group = "androidx.navigation3", name = "navigation3-ui", version.ref = "navigation3" }
|
||||
okhttp3 = { group = "com.squareup.okhttp3", name = "okhttp", version.ref = "okhttp" }
|
||||
okhttp3-logging-interceptor = { group = "com.squareup.okhttp3", name = "logging-interceptor", version.ref = "okhttp" }
|
||||
org-eclipse-paho-client-mqttv3 = { group = "org.eclipse.paho", name = "org.eclipse.paho.client.mqttv3", version.ref = "org-eclipse-paho-client-mqttv3" }
|
||||
|
|
@ -166,6 +169,9 @@ lifecycle = ["lifecycle-runtime-ktx", "lifecycle-livedata-ktx", "lifecycle-viewm
|
|||
# Navigation
|
||||
navigation = ["navigation-compose"]
|
||||
|
||||
# Navigation 3
|
||||
navigation3 = ["navigation3-runtime", "navigation3-ui"]
|
||||
|
||||
# Coroutines
|
||||
coroutines = ["kotlinx-coroutines-android", "kotlinx-coroutines-guava"]
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue