Removed Material3 NavigationBar, other minor fixes

develop
Arty Bishop 2025-07-15 17:10:10 +01:00
rodzic cb01c0ab1c
commit 688bcbca5e
9 zmienionych plików z 177 dodań i 396 usunięć

Wyświetl plik

@ -1,115 +1,32 @@
@file:OptIn(ExperimentalSharedTransitionApi::class)
package com.rtbishop.look4sat.presentation package com.rtbishop.look4sat.presentation
import android.annotation.SuppressLint import androidx.compose.foundation.layout.padding
import android.util.Log import androidx.compose.material3.Scaffold
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.NavigationBar
import androidx.compose.material3.NavigationBarItem
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.navigation.NavController
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.rememberNavController import androidx.navigation.compose.rememberNavController
import androidx.navigation.navigation
import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.presentation.info.infoDestination
import com.rtbishop.look4sat.presentation.map.mapDestination import com.rtbishop.look4sat.presentation.map.mapDestination
import com.rtbishop.look4sat.presentation.passes.passesDestination import com.rtbishop.look4sat.presentation.passes.passesDestination
import com.rtbishop.look4sat.presentation.radar.radarDestination import com.rtbishop.look4sat.presentation.radar.radarDestination
import com.rtbishop.look4sat.presentation.satellites.satellitesDestination 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) {
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 Radar : Screen("Radar", R.drawable.ic_sputnik, "radar")
data object Map : Screen("Map", R.drawable.ic_map, "map")
data object Settings : Screen("Settings", R.drawable.ic_settings, "settings")
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 navController: NavHostController = rememberNavController() val navController: NavHostController = rememberNavController()
val navigateBack: () -> Unit = { navController.navigateUp() } Scaffold { innerPadding ->
val navigateToRadar = { catNum: Int, aosTime: Long -> NavHost(
val routeWithParams = "${Screen.Radar.route}?catNum=${catNum}&aosTime=${aosTime}" navController = navController,
navController.navigate(routeWithParams) startDestination = "passes",
} modifier = Modifier.padding(innerPadding)
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)
}
}
}
}
private fun NavGraphBuilder.passesGraph(
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
fun MainNavBar(navController: NavController) {
val sharedTransitionScope = LocalSharedTransitionScope.current
?: throw IllegalStateException("No SharedElementScope found")
val animatedVisibilityScope = LocalNavAnimatedVisibilityScope.current
?: throw IllegalStateException("No SharedElementScope found")
val sharedTransitionState = sharedTransitionScope.rememberSharedContentState("bottomNav")
val items = listOf(Screen.Satellites, Screen.Passes, Screen.Map, Screen.Settings, Screen.Info)
val stack = navController.currentBackStack.value.map { it.destination.route }
Log.d("NavBar", "NavStack: $stack")
with(sharedTransitionScope) {
NavigationBar(
modifier = Modifier.sharedElement(sharedTransitionState, animatedVisibilityScope)
) { ) {
items.forEach { item -> satellitesDestination(navController)
NavigationBarItem( passesDestination(navController)
icon = { Icon(painterResource(item.icon), item.title) }, radarDestination(navController)
label = { Text(item.title) }, mapDestination(navController)
selected = item.route == navController.currentDestination?.route, settingsDestination(navController)
onClick = {
if (item.route == navController.currentDestination?.route) {
// selecting the same tab
} else {
navController.navigate(item.route) {
popUpTo(Screen.Passes.route) { saveState = false }
launchSingleTop = true
restoreState = false
}
}
}
)
}
} }
} }
} }

Wyświetl plik

@ -140,12 +140,6 @@ fun NextPassRow(pass: OrbitalPass) {
horizontalArrangement = Arrangement.Start, horizontalArrangement = Arrangement.Start,
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {
Icon(
painter = painterResource(id = R.drawable.ic_time),
contentDescription = null,
modifier = Modifier.size(16.dp)
)
Spacer(modifier = Modifier.width(4.dp))
Text( Text(
text = sdfTime.format(Date(pass.aosTime)), text = sdfTime.format(Date(pass.aosTime)),
fontSize = 15.sp, fontSize = 15.sp,
@ -173,12 +167,6 @@ fun NextPassRow(pass: OrbitalPass) {
horizontalArrangement = Arrangement.End, horizontalArrangement = Arrangement.End,
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {
Icon(
painter = painterResource(id = R.drawable.ic_direction),
contentDescription = null,
modifier = Modifier.size(16.dp)
)
Spacer(modifier = Modifier.width(4.dp))
Text( Text(
text = stringResource( text = stringResource(
id = R.string.pass_aosLos, id = R.string.pass_aosLos,

Wyświetl plik

@ -1,105 +0,0 @@
package com.rtbishop.look4sat.presentation.info
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavHostController
import androidx.navigation.compose.composable
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.Screen
import com.rtbishop.look4sat.presentation.components.CardButton
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"
fun NavGraphBuilder.infoDestination(navController: NavHostController) {
composable(Screen.Info.route) {
CompositionLocalProvider(LocalNavAnimatedVisibilityScope provides this@composable) {
Scaffold(bottomBar = { MainNavBar(navController) }) { innerPadding ->
Box(Modifier.padding(innerPadding)) {
InfoScreen()
}
}
}
}
}
@Composable
private fun InfoScreen() {
LazyColumn(modifier = Modifier.padding(6.dp), verticalArrangement = Arrangement.spacedBy(6.dp)) {
item { CardCredits() }
}
}
@Preview(showBackground = true)
@Composable
private fun CardCreditsPreview() = MainTheme { CardCredits() }
@Composable
private fun CardCredits(modifier: Modifier = Modifier) {
val uriHandler = LocalUriHandler.current
ElevatedCard(modifier = modifier.fillMaxWidth()) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp)
) {
Text(
text = stringResource(id = R.string.outro_title),
fontSize = 18.sp,
fontWeight = FontWeight.Medium,
color = MaterialTheme.colorScheme.primary,
modifier = modifier.padding(6.dp)
)
Text(
text = stringResource(
id = R.string.outro_thanks
), fontSize = 16.sp, textAlign = TextAlign.Center
)
Text(
text = stringResource(id = R.string.outro_license),
fontSize = 18.sp,
fontWeight = FontWeight.Medium,
color = MaterialTheme.colorScheme.primary,
modifier = modifier.padding(6.dp)
)
Row(horizontalArrangement = Arrangement.SpaceEvenly) {
CardButton(
onClick = { uriHandler.openUri(LICENSE_URL) },
text = stringResource(id = R.string.btn_license),
modifier = Modifier.weight(1f)
)
Spacer(modifier = Modifier.width(6.dp))
CardButton(
onClick = { uriHandler.openUri(POLICY_URL) },
text = stringResource(id = R.string.btn_privacy),
modifier = Modifier.weight(1f)
)
}
}
}
}

Wyświetl plik

@ -15,10 +15,8 @@ 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
@ -45,9 +43,6 @@ 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.components.CardIcon import com.rtbishop.look4sat.presentation.components.CardIcon
import com.rtbishop.look4sat.presentation.components.NextPassRow import com.rtbishop.look4sat.presentation.components.NextPassRow
import com.rtbishop.look4sat.presentation.components.TimerBar import com.rtbishop.look4sat.presentation.components.TimerBar
@ -86,17 +81,11 @@ private val textPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
private val labelRect = Rect() private val labelRect = Rect()
fun NavGraphBuilder.mapDestination(navController: NavHostController) { fun NavGraphBuilder.mapDestination(navController: NavHostController) {
composable(Screen.Map.route) { composable("map") {
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) { MapScreen(uiState, mapView)
Scaffold(bottomBar = { MainNavBar(navController) }) { innerPadding ->
Box(modifier = Modifier.padding(innerPadding)) {
MapScreen(uiState, mapView)
}
}
}
} }
} }

Wyświetl plik

@ -3,7 +3,6 @@ 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
@ -19,14 +18,12 @@ 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
@ -46,15 +43,13 @@ 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.components.CardIcon import com.rtbishop.look4sat.presentation.components.CardIcon
import com.rtbishop.look4sat.presentation.components.InfoDialog import com.rtbishop.look4sat.presentation.components.InfoDialog
import com.rtbishop.look4sat.presentation.components.NextPassRow import com.rtbishop.look4sat.presentation.components.NextPassRow
import com.rtbishop.look4sat.presentation.components.TimerBar import com.rtbishop.look4sat.presentation.components.TimerBar
import com.rtbishop.look4sat.presentation.components.TimerRow import com.rtbishop.look4sat.presentation.components.TimerRow
import com.rtbishop.look4sat.presentation.radar.navigateToRadar
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Date import java.util.Date
import java.util.Locale import java.util.Locale
@ -62,20 +57,17 @@ 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(navController: NavHostController, navigateToRadar: (Int, Long) -> Unit) { fun NavGraphBuilder.passesDestination(navController: NavHostController) {
composable(Screen.Passes.route) { composable("passes") {
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) { val navigateToRadar = { catNum: Int, aosTime: Long ->
Scaffold(bottomBar = { MainNavBar(navController) }) { innerPadding -> navController.navigateToRadar(catNum, aosTime)
Box(modifier = Modifier.padding(innerPadding)) {
PassesScreen(uiState, navigateToRadar)
}
}
} }
PassesScreen(uiState, navigateToRadar)
} }
} }
@ -222,12 +214,6 @@ private fun DeepSpacePass(
horizontalArrangement = Arrangement.Start, horizontalArrangement = Arrangement.Start,
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {
Icon(
painter = painterResource(id = R.drawable.ic_arrow),
contentDescription = null,
modifier = Modifier.size(16.dp)
)
Spacer(modifier = Modifier.width(4.dp))
Text( Text(
text = "DeepSpace", text = "DeepSpace",
fontSize = 15.sp fontSize = 15.sp
@ -254,12 +240,6 @@ private fun DeepSpacePass(
horizontalArrangement = Arrangement.End, horizontalArrangement = Arrangement.End,
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {
Icon(
painter = painterResource(id = R.drawable.ic_direction),
contentDescription = null,
modifier = Modifier.size(16.dp)
)
Spacer(modifier = Modifier.width(4.dp))
Text( Text(
text = stringResource( text = stringResource(
id = R.string.pass_aosLos, id = R.string.pass_aosLos,
@ -339,12 +319,6 @@ private fun NearEarthPass(
horizontalArrangement = Arrangement.Start, horizontalArrangement = Arrangement.Start,
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {
Icon(
painter = painterResource(id = R.drawable.ic_calendar),
contentDescription = null,
modifier = Modifier.size(16.dp)
)
Spacer(modifier = Modifier.width(4.dp))
Text( Text(
text = sdfDate.format(Date(pass.aosTime)), text = sdfDate.format(Date(pass.aosTime)),
fontSize = 15.sp fontSize = 15.sp
@ -371,12 +345,6 @@ private fun NearEarthPass(
horizontalArrangement = Arrangement.End, horizontalArrangement = Arrangement.End,
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {
Icon(
painter = painterResource(id = R.drawable.ic_direction),
contentDescription = null,
modifier = Modifier.size(16.dp)
)
Spacer(modifier = Modifier.width(4.dp))
Text( Text(
text = stringResource( text = stringResource(
id = R.string.pass_aosLos, id = R.string.pass_aosLos,

Wyświetl plik

@ -27,11 +27,9 @@ import androidx.compose.foundation.lazy.items
import androidx.compose.material3.ElevatedCard import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
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.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
@ -47,22 +45,21 @@ 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 androidx.navigation.navArgument 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.components.CardIcon import com.rtbishop.look4sat.presentation.components.CardIcon
import com.rtbishop.look4sat.presentation.components.NextPassRow import com.rtbishop.look4sat.presentation.components.NextPassRow
import com.rtbishop.look4sat.presentation.components.TimerBar import com.rtbishop.look4sat.presentation.components.TimerBar
import com.rtbishop.look4sat.presentation.components.TimerRow import com.rtbishop.look4sat.presentation.components.TimerRow
import com.rtbishop.look4sat.presentation.components.getDefaultPass import com.rtbishop.look4sat.presentation.components.getDefaultPass
fun NavGraphBuilder.radarDestination(navigateBack: () -> Unit) { fun NavGraphBuilder.radarDestination(navController: NavHostController) {
val radarRoute = "${Screen.Radar.route}?catNum={catNum}&aosTime={aosTime}" val radarRoute = "radar?catNum={catNum}&aosTime={aosTime}"
val radarArgs = listOf( val radarArgs = listOf(
navArgument("catNum") { defaultValue = 0 }, navArgument("catNum") { defaultValue = 0 },
navArgument("aosTime") { defaultValue = 0L } navArgument("aosTime") { defaultValue = 0L }
@ -70,12 +67,14 @@ 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) { navController.navigateUp() }
RadarScreen(uiState, navigateBack)
}
} }
} }
fun NavHostController.navigateToRadar(catNum: Int, aosTime: Long) {
navigate("radar?catNum=${catNum}&aosTime=${aosTime}")
}
@Composable @Composable
private fun RadarScreen(uiState: RadarState, navigateBack: () -> Unit) { private fun RadarScreen(uiState: RadarState, navigateBack: () -> Unit) {
// BluetoothCIV.init(LocalContext.current) // BluetoothCIV.init(LocalContext.current)
@ -85,94 +84,91 @@ private fun RadarScreen(uiState: RadarState, navigateBack: () -> Unit) {
uiState.sendAction(RadarAction.AddToCalendar(pass.name, pass.aosTime, pass.losTime)) uiState.sendAction(RadarAction.AddToCalendar(pass.name, pass.aosTime, pass.losTime))
} }
} }
Scaffold { innerPadding -> Column(
val paddingMod = Modifier.padding(innerPadding) modifier = Modifier.padding(6.dp),
Column( verticalArrangement = Arrangement.spacedBy(6.dp)
modifier = paddingMod.padding(6.dp), ) {
verticalArrangement = Arrangement.spacedBy(6.dp) TimerRow {
) { CardIcon(onClick = navigateBack, iconId = R.drawable.ic_back)
TimerRow { TimerBar(timeString = uiState.currentTime, isTimeAos = uiState.isCurrentTimeAos)
CardIcon(onClick = navigateBack, iconId = R.drawable.ic_back) CardIcon(onClick = addToCalendar, iconId = R.drawable.ic_calendar)
TimerBar(timeString = uiState.currentTime, isTimeAos = uiState.isCurrentTimeAos) }
CardIcon(onClick = addToCalendar, iconId = R.drawable.ic_calendar) NextPassRow(pass = uiState.currentPass ?: getDefaultPass())
} Box(contentAlignment = Alignment.BottomCenter, modifier = Modifier.aspectRatio(1f)) {
NextPassRow(pass = uiState.currentPass ?: getDefaultPass()) uiState.orbitalPos?.let { position ->
Box(contentAlignment = Alignment.BottomCenter, modifier = Modifier.aspectRatio(1f)) { ElevatedCard {
uiState.orbitalPos?.let { position -> RadarViewCompose(
ElevatedCard { item = position,
RadarViewCompose( items = uiState.satTrack,
item = position, azimElev = uiState.orientationValues,
items = uiState.satTrack, shouldShowSweep = uiState.shouldShowSweep,
azimElev = uiState.orientationValues, shouldUseCompass = uiState.shouldUseCompass
shouldShowSweep = uiState.shouldShowSweep, )
shouldUseCompass = uiState.shouldUseCompass }
Column(
verticalArrangement = Arrangement.SpaceBetween,
modifier = Modifier
.fillMaxSize()
.padding(horizontal = 6.dp, vertical = 4.dp)
) {
Row(
horizontalArrangement = Arrangement.SpaceBetween,
modifier = Modifier.fillMaxWidth()
) {
RadarTextTop(
position.azimuth,
stringResource(R.string.radar_az_text),
true
)
RadarTextTop(
position.elevation,
stringResource(R.string.radar_el_text),
false
) )
} }
Column( Row(
verticalArrangement = Arrangement.SpaceBetween, horizontalArrangement = Arrangement.SpaceBetween,
modifier = Modifier modifier = Modifier.fillMaxWidth()
.fillMaxSize()
.padding(horizontal = 6.dp, vertical = 4.dp)
) { ) {
Row( RadarTextBottom(
horizontalArrangement = Arrangement.SpaceBetween, position.altitude,
modifier = Modifier.fillMaxWidth() stringResource(R.string.radar_alt_text),
) { true
RadarTextTop( )
position.azimuth, RadarTextBottom(
stringResource(R.string.radar_az_text), position.distance,
true stringResource(R.string.radar_dist_text),
) false
RadarTextTop( )
position.elevation,
stringResource(R.string.radar_el_text),
false
)
}
Row(
horizontalArrangement = Arrangement.SpaceBetween,
modifier = Modifier.fillMaxWidth()
) {
RadarTextBottom(
position.altitude,
stringResource(R.string.radar_alt_text),
true
)
RadarTextBottom(
position.distance,
stringResource(R.string.radar_dist_text),
false
)
}
} }
} }
} }
ElevatedCard(modifier = Modifier.fillMaxSize()) { }
if (uiState.transmitters.isEmpty()) { ElevatedCard(modifier = Modifier.fillMaxSize()) {
Column( if (uiState.transmitters.isEmpty()) {
modifier = Modifier.fillMaxSize(), Column(
horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center horizontalAlignment = Alignment.CenterHorizontally,
) { verticalArrangement = Arrangement.Center
Icon( ) {
painter = painterResource(R.drawable.ic_satellite), Icon(
contentDescription = null, painter = painterResource(R.drawable.ic_satellite),
modifier = Modifier.size(64.dp) contentDescription = null,
) modifier = Modifier.size(64.dp)
Spacer(modifier = Modifier.height(16.dp)) )
Text( Spacer(modifier = Modifier.height(16.dp))
text = "This satellite doesn't have any known transcievers...", Text(
textAlign = TextAlign.Center, text = "This satellite doesn't have any known transcievers...",
fontSize = 18.sp, textAlign = TextAlign.Center,
modifier = Modifier.padding(16.dp) fontSize = 18.sp,
) modifier = Modifier.padding(16.dp)
} )
} else { }
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { } else {
TransmittersList(transmitters = uiState.transmitters) Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
if (uiState.orbitalPos?.eclipsed == true) { TransmittersList(transmitters = uiState.transmitters)
EclipsedIndicator() if (uiState.orbitalPos?.eclipsed == true) {
} EclipsedIndicator()
} }
} }
} }

Wyświetl plik

@ -22,11 +22,9 @@ 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
@ -47,28 +45,19 @@ 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.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(navController: NavHostController, navigateToPasses: () -> Unit) { fun NavGraphBuilder.satellitesDestination(navController: NavHostController) {
composable(Screen.Satellites.route) { composable("satellites") {
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) { SatellitesScreen(uiState) { navController.navigateUp() }
Scaffold(bottomBar = { MainNavBar(navController) }) { innerPadding ->
Box(modifier = Modifier.padding(innerPadding)) {
SatellitesScreen(uiState, navigateToPasses)
}
}
}
} }
} }

Wyświetl plik

@ -5,7 +5,6 @@ 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
@ -19,18 +18,18 @@ 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
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.LocalUriHandler
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
@ -43,30 +42,23 @@ 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.components.CardButton import com.rtbishop.look4sat.presentation.components.CardButton
import org.osmdroid.library.BuildConfig
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Date import java.util.Date
import java.util.Locale import java.util.Locale
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"
fun NavGraphBuilder.settingsDestination(navController: NavHostController) { fun NavGraphBuilder.settingsDestination(navController: NavHostController) {
composable(Screen.Settings.route) { composable("settings") {
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) { SettingsScreen(uiState)
Scaffold(bottomBar = { MainNavBar(navController) }) { innerPadding ->
Box(modifier = Modifier.padding(innerPadding)) {
SettingsScreen(uiState)
}
}
}
} }
} }
@ -164,6 +156,7 @@ private fun SettingsScreen(uiState: SettingsState) {
toggleLightTheme toggleLightTheme
) )
} }
item { CardCredits() }
} }
} }
@ -468,18 +461,16 @@ private fun OtherCard(
Text(text = stringResource(id = R.string.other_switch_sensors)) Text(text = stringResource(id = R.string.other_switch_sensors))
Switch(checked = settings.stateOfSensors, onCheckedChange = { toggleSensor(it) }) Switch(checked = settings.stateOfSensors, onCheckedChange = { toggleSensor(it) })
} }
if (BuildConfig.DEBUG) { Row(
Row( horizontalArrangement = Arrangement.SpaceBetween,
horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically,
verticalAlignment = Alignment.CenterVertically, modifier = Modifier.fillMaxWidth()
modifier = Modifier.fillMaxWidth() ) {
) { Text(text = stringResource(id = R.string.other_switch_light_theme))
Text(text = stringResource(id = R.string.other_switch_light_theme)) Switch(
Switch( checked = settings.stateOfLightTheme,
checked = settings.stateOfLightTheme, onCheckedChange = { toggleLightTheme(it) }
onCheckedChange = { toggleLightTheme(it) } )
)
}
} }
} }
} }
@ -506,3 +497,51 @@ private fun UpdateIndicator(isUpdating: Boolean, modifier: Modifier = Modifier)
modifier = modifier.padding(start = 6.dp) modifier = modifier.padding(start = 6.dp)
) )
} }
@Preview(showBackground = true)
@Composable
private fun CardCreditsPreview() = MainTheme { CardCredits() }
@Composable
private fun CardCredits(modifier: Modifier = Modifier) {
val uriHandler = LocalUriHandler.current
ElevatedCard(modifier = modifier.fillMaxWidth()) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp)
) {
Text(
text = stringResource(id = R.string.outro_title),
fontSize = 18.sp,
fontWeight = FontWeight.Medium,
color = MaterialTheme.colorScheme.primary,
modifier = modifier.padding(6.dp)
)
Text(
text = stringResource(
id = R.string.outro_thanks
), fontSize = 16.sp, textAlign = TextAlign.Center
)
Text(
text = stringResource(id = R.string.outro_license),
fontSize = 18.sp,
fontWeight = FontWeight.Medium,
color = MaterialTheme.colorScheme.primary,
modifier = modifier.padding(6.dp)
)
Row(horizontalArrangement = Arrangement.SpaceEvenly) {
CardButton(
onClick = { uriHandler.openUri(LICENSE_URL) },
text = stringResource(id = R.string.btn_license),
modifier = Modifier.weight(1f)
)
Spacer(modifier = Modifier.width(6.dp))
CardButton(
onClick = { uriHandler.openUri(POLICY_URL) },
text = stringResource(id = R.string.btn_privacy),
modifier = Modifier.weight(1f)
)
}
}
}
}

Wyświetl plik

@ -89,7 +89,7 @@
<string name="pass_satName">%s</string> <string name="pass_satName">%s</string>
<string name="pass_satId">Id:%05d</string> <string name="pass_satId">Id:%05d</string>
<string name="pass_aosAz">AOS - %.1f°</string> <string name="pass_aosAz">AOS - %.1f°</string>
<string name="pass_aosLos" translatable="false">%03d° -> %03d°</string> <string name="pass_aosLos" translatable="false">%03d° - %03d°</string>
<string name="pass_elevation">Elevation: %.1f°</string> <string name="pass_elevation">Elevation: %.1f°</string>
<string name="pass_losAz">%.1f° - LOS</string> <string name="pass_losAz">%.1f° - LOS</string>
<string name="pass_altitude">Altitude: %d km</string> <string name="pass_altitude">Altitude: %d km</string>