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
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.NavigationBar
import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.Text
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.compositionLocalOf
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.compose.NavHost
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.passes.passesDestination
import com.rtbishop.look4sat.presentation.radar.radarDestination
import com.rtbishop.look4sat.presentation.satellites.satellitesDestination
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
fun MainScreen() {
val navController: NavHostController = rememberNavController()
val navigateBack: () -> Unit = { navController.navigateUp() }
val navigateToRadar = { catNum: Int, aosTime: Long ->
val routeWithParams = "${Screen.Radar.route}?catNum=${catNum}&aosTime=${aosTime}"
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)
}
}
}
}
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)
Scaffold { innerPadding ->
NavHost(
navController = navController,
startDestination = "passes",
modifier = Modifier.padding(innerPadding)
) {
items.forEach { item ->
NavigationBarItem(
icon = { Icon(painterResource(item.icon), item.title) },
label = { Text(item.title) },
selected = item.route == navController.currentDestination?.route,
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
}
}
}
)
}
satellitesDestination(navController)
passesDestination(navController)
radarDestination(navController)
mapDestination(navController)
settingsDestination(navController)
}
}
}

Wyświetl plik

@ -140,12 +140,6 @@ fun NextPassRow(pass: OrbitalPass) {
horizontalArrangement = Arrangement.Start,
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 = sdfTime.format(Date(pass.aosTime)),
fontSize = 15.sp,
@ -173,12 +167,6 @@ fun NextPassRow(pass: OrbitalPass) {
horizontalArrangement = Arrangement.End,
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 = stringResource(
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.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.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
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.OrbitalObject
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.NextPassRow
import com.rtbishop.look4sat.presentation.components.TimerBar
@ -86,17 +81,11 @@ private val textPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
private val labelRect = Rect()
fun NavGraphBuilder.mapDestination(navController: NavHostController) {
composable(Screen.Map.route) {
composable("map") {
val viewModel = viewModel(MapViewModel::class.java, factory = MapViewModel.Factory)
val uiState = viewModel.uiState.collectAsStateWithLifecycle()
val mapView = rememberMapViewWithLifecycle()
CompositionLocalProvider(LocalNavAnimatedVisibilityScope provides this@composable) {
Scaffold(bottomBar = { MainNavBar(navController) }) { innerPadding ->
Box(modifier = Modifier.padding(innerPadding)) {
MapScreen(uiState, mapView)
}
}
}
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.clickable
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
@ -19,14 +18,12 @@ import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.pulltorefresh.PullToRefreshBox
import androidx.compose.material3.pulltorefresh.PullToRefreshDefaults
import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
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.OrbitalData
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.Screen
import com.rtbishop.look4sat.presentation.components.CardIcon
import com.rtbishop.look4sat.presentation.components.InfoDialog
import com.rtbishop.look4sat.presentation.components.NextPassRow
import com.rtbishop.look4sat.presentation.components.TimerBar
import com.rtbishop.look4sat.presentation.components.TimerRow
import com.rtbishop.look4sat.presentation.radar.navigateToRadar
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
@ -62,20 +57,17 @@ import java.util.Locale
private val sdfDate = SimpleDateFormat("EEE dd MMM", Locale.ENGLISH)
private val sdfTime = SimpleDateFormat("HH:mm:ss", Locale.ENGLISH)
fun NavGraphBuilder.passesDestination(navController: NavHostController, navigateToRadar: (Int, Long) -> Unit) {
composable(Screen.Passes.route) {
fun NavGraphBuilder.passesDestination(navController: NavHostController) {
composable("passes") {
val viewModel = viewModel(
modelClass = PassesViewModel::class.java,
factory = PassesViewModel.Factory
)
val uiState = viewModel.uiState.collectAsStateWithLifecycle().value
CompositionLocalProvider(LocalNavAnimatedVisibilityScope provides this@composable) {
Scaffold(bottomBar = { MainNavBar(navController) }) { innerPadding ->
Box(modifier = Modifier.padding(innerPadding)) {
PassesScreen(uiState, navigateToRadar)
}
}
val navigateToRadar = { catNum: Int, aosTime: Long ->
navController.navigateToRadar(catNum, aosTime)
}
PassesScreen(uiState, navigateToRadar)
}
}
@ -222,12 +214,6 @@ private fun DeepSpacePass(
horizontalArrangement = Arrangement.Start,
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 = "DeepSpace",
fontSize = 15.sp
@ -254,12 +240,6 @@ private fun DeepSpacePass(
horizontalArrangement = Arrangement.End,
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 = stringResource(
id = R.string.pass_aosLos,
@ -339,12 +319,6 @@ private fun NearEarthPass(
horizontalArrangement = Arrangement.Start,
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 = sdfDate.format(Date(pass.aosTime)),
fontSize = 15.sp
@ -371,12 +345,6 @@ private fun NearEarthPass(
horizontalArrangement = Arrangement.End,
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 = stringResource(
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.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
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.draw.alpha
@ -47,22 +45,21 @@ import androidx.compose.ui.unit.sp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavHostController
import androidx.navigation.compose.composable
import androidx.navigation.navArgument
import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.domain.model.SatRadio
import com.rtbishop.look4sat.domain.utility.toDegrees
import com.rtbishop.look4sat.presentation.LocalNavAnimatedVisibilityScope
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.NextPassRow
import com.rtbishop.look4sat.presentation.components.TimerBar
import com.rtbishop.look4sat.presentation.components.TimerRow
import com.rtbishop.look4sat.presentation.components.getDefaultPass
fun NavGraphBuilder.radarDestination(navigateBack: () -> Unit) {
val radarRoute = "${Screen.Radar.route}?catNum={catNum}&aosTime={aosTime}"
fun NavGraphBuilder.radarDestination(navController: NavHostController) {
val radarRoute = "radar?catNum={catNum}&aosTime={aosTime}"
val radarArgs = listOf(
navArgument("catNum") { defaultValue = 0 },
navArgument("aosTime") { defaultValue = 0L }
@ -70,12 +67,14 @@ fun NavGraphBuilder.radarDestination(navigateBack: () -> Unit) {
composable(radarRoute, radarArgs) {
val viewModel = viewModel(RadarViewModel::class.java, factory = RadarViewModel.Factory)
val uiState = viewModel.uiState.collectAsStateWithLifecycle().value
CompositionLocalProvider(LocalNavAnimatedVisibilityScope provides this@composable) {
RadarScreen(uiState, navigateBack)
}
RadarScreen(uiState) { navController.navigateUp() }
}
}
fun NavHostController.navigateToRadar(catNum: Int, aosTime: Long) {
navigate("radar?catNum=${catNum}&aosTime=${aosTime}")
}
@Composable
private fun RadarScreen(uiState: RadarState, navigateBack: () -> Unit) {
// 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))
}
}
Scaffold { innerPadding ->
val paddingMod = Modifier.padding(innerPadding)
Column(
modifier = paddingMod.padding(6.dp),
verticalArrangement = Arrangement.spacedBy(6.dp)
) {
TimerRow {
CardIcon(onClick = navigateBack, iconId = R.drawable.ic_back)
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)) {
uiState.orbitalPos?.let { position ->
ElevatedCard {
RadarViewCompose(
item = position,
items = uiState.satTrack,
azimElev = uiState.orientationValues,
shouldShowSweep = uiState.shouldShowSweep,
shouldUseCompass = uiState.shouldUseCompass
Column(
modifier = Modifier.padding(6.dp),
verticalArrangement = Arrangement.spacedBy(6.dp)
) {
TimerRow {
CardIcon(onClick = navigateBack, iconId = R.drawable.ic_back)
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)) {
uiState.orbitalPos?.let { position ->
ElevatedCard {
RadarViewCompose(
item = position,
items = uiState.satTrack,
azimElev = uiState.orientationValues,
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(
verticalArrangement = Arrangement.SpaceBetween,
modifier = Modifier
.fillMaxSize()
.padding(horizontal = 6.dp, vertical = 4.dp)
Row(
horizontalArrangement = Arrangement.SpaceBetween,
modifier = Modifier.fillMaxWidth()
) {
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
)
}
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
)
}
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()) {
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Icon(
painter = painterResource(R.drawable.ic_satellite),
contentDescription = null,
modifier = Modifier.size(64.dp)
)
Spacer(modifier = Modifier.height(16.dp))
Text(
text = "This satellite doesn't have any known transcievers...",
textAlign = TextAlign.Center,
fontSize = 18.sp,
modifier = Modifier.padding(16.dp)
)
}
} else {
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
TransmittersList(transmitters = uiState.transmitters)
if (uiState.orbitalPos?.eclipsed == true) {
EclipsedIndicator()
}
}
ElevatedCard(modifier = Modifier.fillMaxSize()) {
if (uiState.transmitters.isEmpty()) {
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Icon(
painter = painterResource(R.drawable.ic_satellite),
contentDescription = null,
modifier = Modifier.size(64.dp)
)
Spacer(modifier = Modifier.height(16.dp))
Text(
text = "This satellite doesn't have any known transcievers...",
textAlign = TextAlign.Center,
fontSize = 18.sp,
modifier = Modifier.padding(16.dp)
)
}
} else {
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
TransmittersList(transmitters = uiState.transmitters)
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.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
@ -47,28 +45,19 @@ import androidx.navigation.NavHostController
import androidx.navigation.compose.composable
import com.rtbishop.look4sat.R
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.Screen
import com.rtbishop.look4sat.presentation.components.CardIcon
import com.rtbishop.look4sat.presentation.components.CardLoadingIndicator
import com.rtbishop.look4sat.presentation.components.InfoDialog
fun NavGraphBuilder.satellitesDestination(navController: NavHostController, navigateToPasses: () -> Unit) {
composable(Screen.Satellites.route) {
fun NavGraphBuilder.satellitesDestination(navController: NavHostController) {
composable("satellites") {
val viewModel = viewModel(
modelClass = SatellitesViewModel::class.java,
factory = SatellitesViewModel.Factory
)
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) { navController.navigateUp() }
}
}

Wyświetl plik

@ -5,7 +5,6 @@ import android.os.Build
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
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
@ -19,18 +18,18 @@ import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.Icon
import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.res.painterResource
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
@ -43,30 +42,23 @@ import androidx.navigation.compose.composable
import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.domain.model.OtherSettings
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.Screen
import com.rtbishop.look4sat.presentation.components.CardButton
import org.osmdroid.library.BuildConfig
import java.text.SimpleDateFormat
import java.util.Date
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) {
composable(Screen.Settings.route) {
composable("settings") {
val viewModel = viewModel(
modelClass = SettingsViewModel::class.java,
factory = SettingsViewModel.Factory
)
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)
}
}
@ -164,6 +156,7 @@ private fun SettingsScreen(uiState: SettingsState) {
toggleLightTheme
)
}
item { CardCredits() }
}
}
@ -468,18 +461,16 @@ private fun OtherCard(
Text(text = stringResource(id = R.string.other_switch_sensors))
Switch(checked = settings.stateOfSensors, onCheckedChange = { toggleSensor(it) })
}
if (BuildConfig.DEBUG) {
Row(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxWidth()
) {
Text(text = stringResource(id = R.string.other_switch_light_theme))
Switch(
checked = settings.stateOfLightTheme,
onCheckedChange = { toggleLightTheme(it) }
)
}
Row(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxWidth()
) {
Text(text = stringResource(id = R.string.other_switch_light_theme))
Switch(
checked = settings.stateOfLightTheme,
onCheckedChange = { toggleLightTheme(it) }
)
}
}
}
@ -506,3 +497,51 @@ private fun UpdateIndicator(isUpdating: Boolean, modifier: Modifier = Modifier)
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_satId">Id:%05d</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_losAz">%.1f° - LOS</string>
<string name="pass_altitude">Altitude: %d km</string>