Implemented experimental SharedElement transition API

This commit is contained in:
Arty Bishop committed 2025-12-27 15:01:47 +00:00
1 parent aa9365b2fd
commit a6cbd89ff1
7 files changed
+129 -43

No files matched your search

@@ -1,21 +1,28 @@
@file:OptIn(ExperimentalSharedTransitionApi::class)
package com.rtbishop.look4sat.presentation package com.rtbishop.look4sat.presentation
import androidx.compose.foundation.layout.padding import android.annotation.SuppressLint
import android.util.Log
import androidx.compose.animation.AnimatedVisibilityScope
import androidx.compose.animation.ExperimentalSharedTransitionApi
import androidx.compose.animation.SharedTransitionLayout
import androidx.compose.animation.SharedTransitionScope
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.NavigationBar import androidx.compose.material3.NavigationBar
import androidx.compose.material3.NavigationBarItem import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.navigation.NavController import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController import androidx.navigation.compose.rememberNavController
import androidx.navigation.navigation
import com.rtbishop.look4sat.R import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.presentation.info.infoDestination import com.rtbishop.look4sat.presentation.info.infoDestination
import com.rtbishop.look4sat.presentation.map.mapDestination import com.rtbishop.look4sat.presentation.map.mapDestination
@@ -25,69 +32,84 @@ import com.rtbishop.look4sat.presentation.satellites.satellitesDestination
import com.rtbishop.look4sat.presentation.settings.settingsDestination import com.rtbishop.look4sat.presentation.settings.settingsDestination
sealed class Screen(var title: String, var icon: Int, var route: String) { sealed class Screen(var title: String, var icon: Int, var route: String) {
data object Main : Screen("Main", R.drawable.ic_sputnik, "main")
data object Radar : Screen("Radar", R.drawable.ic_sputnik, "radar")
data object Satellites : Screen("Satellites", R.drawable.ic_sputnik, "satellites") data object Satellites : Screen("Satellites", R.drawable.ic_sputnik, "satellites")
data object PassesGraph : Screen("Passes", R.drawable.ic_passes, "passesGraph")
data object Passes : Screen("Passes", R.drawable.ic_passes, "passes") data object Passes : Screen("Passes", R.drawable.ic_passes, "passes")
data object Radar : Screen("Radar", R.drawable.ic_sputnik, "radar")
data object Map : Screen("Map", R.drawable.ic_map, "map") data object Map : Screen("Map", R.drawable.ic_map, "map")
data object Settings : Screen("Settings", R.drawable.ic_settings, "settings") data object Settings : Screen("Settings", R.drawable.ic_settings, "settings")
data object Info : Screen("Info", R.drawable.ic_info, "info") data object Info : Screen("Info", R.drawable.ic_info, "info")
} }
val LocalSharedTransitionScope = compositionLocalOf<SharedTransitionScope?> { null }
val LocalNavAnimatedVisibilityScope = compositionLocalOf<AnimatedVisibilityScope?> { null }
@Composable @Composable
fun MainScreen() { fun MainScreen() {
val outerNavController: NavHostController = rememberNavController() val navController: NavHostController = rememberNavController()
val navigateBack: () -> Unit = { navController.navigateUp() }
val navigateToRadar = { catNum: Int, aosTime: Long -> val navigateToRadar = { catNum: Int, aosTime: Long ->
val routeWithParams = "${Screen.Radar.route}?catNum=${catNum}&aosTime=${aosTime}" val routeWithParams = "${Screen.Radar.route}?catNum=${catNum}&aosTime=${aosTime}"
outerNavController.navigate(routeWithParams) navController.navigate(routeWithParams)
}
SharedTransitionLayout {
CompositionLocalProvider(LocalSharedTransitionScope provides this) {
NavHost(navController = navController, startDestination = Screen.PassesGraph.route) {
satellitesDestination(navController, navigateBack)
passesGraph(navController, navigateBack, navigateToRadar)
radarDestination(navigateBack)
mapDestination(navController)
settingsDestination(navController)
infoDestination(navController)
}
} }
NavHost(navController = outerNavController, startDestination = Screen.Main.route) {
mainDestination(navigateToRadar)
radarDestination { outerNavController.navigateUp() }
} }
} }
private fun NavGraphBuilder.mainDestination(navigateToRadar: (Int, Long) -> Unit) { private fun NavGraphBuilder.passesGraph(
composable(Screen.Main.route) { NavBarScreen(navigateToRadar) } navController: NavHostController,
navigateBack: () -> Unit,
navigateToRadar: (Int, Long) -> Unit
) {
navigation(route = Screen.PassesGraph.route, startDestination = Screen.Passes.route) {
passesDestination(navController, navigateToRadar)
radarDestination(navigateBack)
}
} }
@SuppressLint("RestrictedApi", "StateFlowValueCalledInComposition")
@Composable @Composable
private fun NavBarScreen(navigateToRadar: (Int, Long) -> Unit) { fun MainNavBar(navController: NavController) {
val innerNavController: NavHostController = rememberNavController() val sharedTransitionScope = LocalSharedTransitionScope.current
val navigateToPasses = { innerNavController.navigate(Screen.Passes.route) } ?: throw IllegalStateException("No SharedElementScope found")
Scaffold(bottomBar = { MainNavBar(innerNavController) }) { innerPadding -> val animatedVisibilityScope = LocalNavAnimatedVisibilityScope.current
NavHost( ?: throw IllegalStateException("No SharedElementScope found")
navController = innerNavController, val sharedTransitionState = sharedTransitionScope.rememberSharedContentState("bottomNav")
startDestination = Screen.Passes.route,
modifier = Modifier.padding(innerPadding)
) {
satellitesDestination(navigateToPasses)
passesDestination(navigateToRadar)
mapDestination()
settingsDestination()
infoDestination()
}
}
}
@Composable
private fun MainNavBar(navController: NavController) {
val items = listOf(Screen.Satellites, Screen.Passes, Screen.Map, Screen.Settings, Screen.Info) val items = listOf(Screen.Satellites, Screen.Passes, Screen.Map, Screen.Settings, Screen.Info)
val destinationRoute = navController.currentBackStackEntryAsState().value?.destination?.route val stack = navController.currentBackStack.value.map { it.destination.route }
NavigationBar { Log.d("NavBar", "NavStack: $stack")
with(sharedTransitionScope) {
NavigationBar(
modifier = Modifier.sharedElement(sharedTransitionState, animatedVisibilityScope)
) {
items.forEach { item -> items.forEach { item ->
NavigationBarItem( NavigationBarItem(
icon = { Icon(painterResource(item.icon), item.title) }, icon = { Icon(painterResource(item.icon), item.title) },
label = { Text(item.title) }, label = { Text(item.title) },
selected = destinationRoute?.contains(item.route) ?: false, selected = item.route == navController.currentDestination?.route,
onClick = { onClick = {
if (item.route == navController.currentDestination?.route) {
// selecting the same tab
} else {
navController.navigate(item.route) { navController.navigate(item.route) {
popUpTo(navController.graph.startDestinationId) { saveState = false } popUpTo(Screen.Passes.route) { saveState = false }
launchSingleTop = true launchSingleTop = true
restoreState = false restoreState = false
} }
} }
}
) )
} }
} }
}
} }
@@ -1,6 +1,7 @@
package com.rtbishop.look4sat.presentation.info package com.rtbishop.look4sat.presentation.info
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
@@ -10,8 +11,10 @@ import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material3.ElevatedCard import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
@@ -22,8 +25,11 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.navigation.NavGraphBuilder import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavHostController
import androidx.navigation.compose.composable import androidx.navigation.compose.composable
import com.rtbishop.look4sat.R import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.presentation.LocalNavAnimatedVisibilityScope
import com.rtbishop.look4sat.presentation.MainNavBar
import com.rtbishop.look4sat.presentation.MainTheme import com.rtbishop.look4sat.presentation.MainTheme
import com.rtbishop.look4sat.presentation.Screen import com.rtbishop.look4sat.presentation.Screen
import com.rtbishop.look4sat.presentation.components.CardButton import com.rtbishop.look4sat.presentation.components.CardButton
@@ -32,8 +38,16 @@ import com.rtbishop.look4sat.presentation.components.gotoUrl
private const val POLICY_URL = "https://sites.google.com/view/look4sat-privacy-policy/home" private const val POLICY_URL = "https://sites.google.com/view/look4sat-privacy-policy/home"
private const val LICENSE_URL = "https://www.gnu.org/licenses/gpl-3.0.html" private const val LICENSE_URL = "https://www.gnu.org/licenses/gpl-3.0.html"
fun NavGraphBuilder.infoDestination() { fun NavGraphBuilder.infoDestination(navController: NavHostController) {
composable(Screen.Info.route) { InfoScreen() } composable(Screen.Info.route) {
CompositionLocalProvider(LocalNavAnimatedVisibilityScope provides this@composable) {
Scaffold(bottomBar = { MainNavBar(navController) }) { innerPadding ->
Box(Modifier.padding(innerPadding)) {
InfoScreen()
}
}
}
}
} }
@Composable @Composable
@@ -15,8 +15,10 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ElevatedCard import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.State import androidx.compose.runtime.State
@@ -37,11 +39,14 @@ import androidx.lifecycle.compose.LocalLifecycleOwner
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavGraphBuilder import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavHostController
import androidx.navigation.compose.composable import androidx.navigation.compose.composable
import com.rtbishop.look4sat.R import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.domain.predict.GeoPos import com.rtbishop.look4sat.domain.predict.GeoPos
import com.rtbishop.look4sat.domain.predict.OrbitalObject import com.rtbishop.look4sat.domain.predict.OrbitalObject
import com.rtbishop.look4sat.domain.predict.OrbitalPos import com.rtbishop.look4sat.domain.predict.OrbitalPos
import com.rtbishop.look4sat.presentation.LocalNavAnimatedVisibilityScope
import com.rtbishop.look4sat.presentation.MainNavBar
import com.rtbishop.look4sat.presentation.Screen import com.rtbishop.look4sat.presentation.Screen
import com.rtbishop.look4sat.presentation.components.CardIcon import com.rtbishop.look4sat.presentation.components.CardIcon
import com.rtbishop.look4sat.presentation.components.NextPassRow import com.rtbishop.look4sat.presentation.components.NextPassRow
@@ -80,13 +85,19 @@ private val textPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
} }
private val labelRect = Rect() private val labelRect = Rect()
fun NavGraphBuilder.mapDestination() { fun NavGraphBuilder.mapDestination(navController: NavHostController) {
composable(Screen.Map.route) { composable(Screen.Map.route) {
val viewModel = viewModel(MapViewModel::class.java, factory = MapViewModel.Factory) val viewModel = viewModel(MapViewModel::class.java, factory = MapViewModel.Factory)
val uiState = viewModel.uiState.collectAsStateWithLifecycle() val uiState = viewModel.uiState.collectAsStateWithLifecycle()
val mapView = rememberMapViewWithLifecycle() val mapView = rememberMapViewWithLifecycle()
CompositionLocalProvider(LocalNavAnimatedVisibilityScope provides this@composable) {
Scaffold(bottomBar = { MainNavBar(navController) }) { innerPadding ->
Box(modifier = Modifier.padding(innerPadding)) {
MapScreen(uiState, mapView) MapScreen(uiState, mapView)
} }
}
}
}
} }
@Composable @Composable
@@ -3,6 +3,7 @@ package com.rtbishop.look4sat.presentation.passes
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
@@ -18,12 +19,14 @@ import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.LinearProgressIndicator import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.pulltorefresh.PullToRefreshBox import androidx.compose.material3.pulltorefresh.PullToRefreshBox
import androidx.compose.material3.pulltorefresh.PullToRefreshDefaults import androidx.compose.material3.pulltorefresh.PullToRefreshDefaults
import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
@@ -36,12 +39,15 @@ import androidx.compose.ui.unit.sp
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavGraphBuilder import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavHostController
import androidx.navigation.compose.composable import androidx.navigation.compose.composable
import com.rtbishop.look4sat.R import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.domain.predict.DeepSpaceObject import com.rtbishop.look4sat.domain.predict.DeepSpaceObject
import com.rtbishop.look4sat.domain.predict.NearEarthObject import com.rtbishop.look4sat.domain.predict.NearEarthObject
import com.rtbishop.look4sat.domain.predict.OrbitalData import com.rtbishop.look4sat.domain.predict.OrbitalData
import com.rtbishop.look4sat.domain.predict.OrbitalPass import com.rtbishop.look4sat.domain.predict.OrbitalPass
import com.rtbishop.look4sat.presentation.LocalNavAnimatedVisibilityScope
import com.rtbishop.look4sat.presentation.MainNavBar
import com.rtbishop.look4sat.presentation.MainTheme import com.rtbishop.look4sat.presentation.MainTheme
import com.rtbishop.look4sat.presentation.Screen import com.rtbishop.look4sat.presentation.Screen
import com.rtbishop.look4sat.presentation.components.CardIcon import com.rtbishop.look4sat.presentation.components.CardIcon
@@ -56,15 +62,21 @@ import java.util.Locale
private val sdfDate = SimpleDateFormat("EEE dd MMM", Locale.ENGLISH) private val sdfDate = SimpleDateFormat("EEE dd MMM", Locale.ENGLISH)
private val sdfTime = SimpleDateFormat("HH:mm:ss", Locale.ENGLISH) private val sdfTime = SimpleDateFormat("HH:mm:ss", Locale.ENGLISH)
fun NavGraphBuilder.passesDestination(navigateToRadar: (Int, Long) -> Unit) { fun NavGraphBuilder.passesDestination(navController: NavHostController, navigateToRadar: (Int, Long) -> Unit) {
composable(Screen.Passes.route) { composable(Screen.Passes.route) {
val viewModel = viewModel( val viewModel = viewModel(
modelClass = PassesViewModel::class.java, modelClass = PassesViewModel::class.java,
factory = PassesViewModel.Factory factory = PassesViewModel.Factory
) )
val uiState = viewModel.uiState.collectAsStateWithLifecycle().value val uiState = viewModel.uiState.collectAsStateWithLifecycle().value
CompositionLocalProvider(LocalNavAnimatedVisibilityScope provides this@composable) {
Scaffold(bottomBar = { MainNavBar(navController) }) { innerPadding ->
Box(modifier = Modifier.padding(innerPadding)) {
PassesScreen(uiState, navigateToRadar) PassesScreen(uiState, navigateToRadar)
} }
}
}
}
} }
@Composable @Composable
@@ -31,6 +31,7 @@ import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.alpha
@@ -51,6 +52,7 @@ import androidx.navigation.navArgument
import com.rtbishop.look4sat.R import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.domain.model.SatRadio import com.rtbishop.look4sat.domain.model.SatRadio
import com.rtbishop.look4sat.domain.utility.toDegrees import com.rtbishop.look4sat.domain.utility.toDegrees
import com.rtbishop.look4sat.presentation.LocalNavAnimatedVisibilityScope
import com.rtbishop.look4sat.presentation.MainTheme import com.rtbishop.look4sat.presentation.MainTheme
import com.rtbishop.look4sat.presentation.Screen import com.rtbishop.look4sat.presentation.Screen
import com.rtbishop.look4sat.presentation.components.CardIcon import com.rtbishop.look4sat.presentation.components.CardIcon
@@ -68,8 +70,10 @@ fun NavGraphBuilder.radarDestination(navigateBack: () -> Unit) {
composable(radarRoute, radarArgs) { composable(radarRoute, radarArgs) {
val viewModel = viewModel(RadarViewModel::class.java, factory = RadarViewModel.Factory) val viewModel = viewModel(RadarViewModel::class.java, factory = RadarViewModel.Factory)
val uiState = viewModel.uiState.collectAsStateWithLifecycle().value val uiState = viewModel.uiState.collectAsStateWithLifecycle().value
CompositionLocalProvider(LocalNavAnimatedVisibilityScope provides this@composable) {
RadarScreen(uiState, navigateBack) RadarScreen(uiState, navigateBack)
} }
}
} }
@Composable @Composable
@@ -22,9 +22,11 @@ import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
@@ -41,24 +43,33 @@ import androidx.compose.ui.unit.sp
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavGraphBuilder import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavHostController
import androidx.navigation.compose.composable import androidx.navigation.compose.composable
import com.rtbishop.look4sat.R import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.domain.model.SatItem import com.rtbishop.look4sat.domain.model.SatItem
import com.rtbishop.look4sat.presentation.LocalNavAnimatedVisibilityScope
import com.rtbishop.look4sat.presentation.MainNavBar
import com.rtbishop.look4sat.presentation.MainTheme import com.rtbishop.look4sat.presentation.MainTheme
import com.rtbishop.look4sat.presentation.Screen import com.rtbishop.look4sat.presentation.Screen
import com.rtbishop.look4sat.presentation.components.CardIcon import com.rtbishop.look4sat.presentation.components.CardIcon
import com.rtbishop.look4sat.presentation.components.CardLoadingIndicator import com.rtbishop.look4sat.presentation.components.CardLoadingIndicator
import com.rtbishop.look4sat.presentation.components.InfoDialog import com.rtbishop.look4sat.presentation.components.InfoDialog
fun NavGraphBuilder.satellitesDestination(navigateToPasses: () -> Unit) { fun NavGraphBuilder.satellitesDestination(navController: NavHostController, navigateToPasses: () -> Unit) {
composable(Screen.Satellites.route) { composable(Screen.Satellites.route) {
val viewModel = viewModel( val viewModel = viewModel(
modelClass = SatellitesViewModel::class.java, modelClass = SatellitesViewModel::class.java,
factory = SatellitesViewModel.Factory factory = SatellitesViewModel.Factory
) )
val uiState = viewModel.uiState.collectAsStateWithLifecycle().value val uiState = viewModel.uiState.collectAsStateWithLifecycle().value
CompositionLocalProvider(LocalNavAnimatedVisibilityScope provides this@composable) {
Scaffold(bottomBar = { MainNavBar(navController) }) { innerPadding ->
Box(modifier = Modifier.padding(innerPadding)) {
SatellitesScreen(uiState, navigateToPasses) SatellitesScreen(uiState, navigateToPasses)
} }
}
}
}
} }
@Composable @Composable
@@ -5,6 +5,7 @@ import android.os.Build
import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
@@ -18,9 +19,11 @@ import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.LinearProgressIndicator import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Switch import androidx.compose.material3.Switch
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
@@ -35,10 +38,13 @@ import androidx.compose.ui.unit.sp
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavGraphBuilder import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavHostController
import androidx.navigation.compose.composable import androidx.navigation.compose.composable
import com.rtbishop.look4sat.R import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.domain.model.OtherSettings import com.rtbishop.look4sat.domain.model.OtherSettings
import com.rtbishop.look4sat.domain.predict.GeoPos import com.rtbishop.look4sat.domain.predict.GeoPos
import com.rtbishop.look4sat.presentation.LocalNavAnimatedVisibilityScope
import com.rtbishop.look4sat.presentation.MainNavBar
import com.rtbishop.look4sat.presentation.MainTheme import com.rtbishop.look4sat.presentation.MainTheme
import com.rtbishop.look4sat.presentation.Screen import com.rtbishop.look4sat.presentation.Screen
import com.rtbishop.look4sat.presentation.components.CardButton import com.rtbishop.look4sat.presentation.components.CardButton
@@ -47,15 +53,21 @@ import java.text.SimpleDateFormat
import java.util.Date import java.util.Date
import java.util.Locale import java.util.Locale
fun NavGraphBuilder.settingsDestination() { fun NavGraphBuilder.settingsDestination(navController: NavHostController) {
composable(Screen.Settings.route) { composable(Screen.Settings.route) {
val viewModel = viewModel( val viewModel = viewModel(
modelClass = SettingsViewModel::class.java, modelClass = SettingsViewModel::class.java,
factory = SettingsViewModel.Factory factory = SettingsViewModel.Factory
) )
val uiState = viewModel.uiState.collectAsStateWithLifecycle().value val uiState = viewModel.uiState.collectAsStateWithLifecycle().value
CompositionLocalProvider(LocalNavAnimatedVisibilityScope provides this@composable) {
Scaffold(bottomBar = { MainNavBar(navController) }) { innerPadding ->
Box(modifier = Modifier.padding(innerPadding)) {
SettingsScreen(uiState) SettingsScreen(uiState)
} }
}
}
}
} }
@Composable @Composable