Set up more screens with portrait/landscape TopBar

develop
Arty Bishop 2025-07-26 14:10:01 +01:00
rodzic 761506d2a3
commit 99a63a2a1d
13 zmienionych plików z 302 dodań i 309 usunięć

Wyświetl plik

@ -1,94 +1,75 @@
package com.rtbishop.look4sat.presentation package com.rtbishop.look4sat.presentation
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.NavigationBar import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteDefaults
import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteScaffold
import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteType
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource 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.composable
import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController import androidx.navigation.compose.rememberNavController
import com.rtbishop.look4sat.R import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.presentation.common.isVerticalLayout
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) { sealed class Screen(val title: String, val icon: Int, val 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 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_satellite, "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")
} }
@Composable private val startDestination = Screen.Passes.route
fun MainScreen() {
val outerNavController: NavHostController = rememberNavController()
val navigateToRadar = { catNum: Int, aosTime: Long ->
val routeWithParams = "${Screen.Radar.route}?catNum=${catNum}&aosTime=${aosTime}"
outerNavController.navigate(routeWithParams)
}
NavHost(navController = outerNavController, startDestination = Screen.Main.route) {
mainDestination(navigateToRadar)
radarDestination { outerNavController.navigateUp() }
}
}
private fun NavGraphBuilder.mainDestination(navigateToRadar: (Int, Long) -> Unit) {
composable(Screen.Main.route) { NavBarScreen(navigateToRadar) }
}
@Composable @Composable
private fun NavBarScreen(navigateToRadar: (Int, Long) -> Unit) { fun MainScreen(navController: NavHostController = rememberNavController()) {
val innerNavController: NavHostController = rememberNavController() val items = listOf(Screen.Satellites, Screen.Passes, Screen.Radar, Screen.Map, Screen.Settings)
val navigateToPasses = { innerNavController.navigate(Screen.Passes.route) }
Scaffold(bottomBar = { MainNavBar(innerNavController) }) { innerPadding ->
NavHost(
navController = innerNavController,
startDestination = Screen.Passes.route,
modifier = Modifier.padding(innerPadding)
) {
satellitesDestination(navigateToPasses)
passesDestination(navigateToRadar)
mapDestination()
settingsDestination()
}
}
}
@Composable
private fun MainNavBar(navController: NavController) {
val items = listOf(Screen.Satellites, Screen.Passes, Screen.Map, Screen.Settings)
val destinationRoute = navController.currentBackStackEntryAsState().value?.destination?.route val destinationRoute = navController.currentBackStackEntryAsState().value?.destination?.route
NavigationBar { NavigationSuiteScaffold(
items.forEach { item -> navigationSuiteItems = {
NavigationBarItem( items.forEach {
icon = { Icon(painterResource(item.icon), item.title) }, item(
label = { Text(item.title) }, icon = { Icon(painterResource(it.icon), it.title) },
selected = item.route == destinationRoute, label = { Text(it.title) },
onClick = { selected = destinationRoute?.contains(it.route) ?: false,
if (item.route == destinationRoute) { onClick = {
// reselecting the same tab if (destinationRoute?.contains(it.route) ?: false) return@item
} else { navController.navigate(it.route) {
navController.navigate(item.route) { popUpTo(startDestination) { saveState = false }
popUpTo(Screen.Passes.route) { saveState = false }
launchSingleTop = true launchSingleTop = true
restoreState = false restoreState = false
} }
} })
} }
) }, navigationSuiteColors = NavigationSuiteDefaults.colors(
navigationRailContainerColor = MaterialTheme.colorScheme.surfaceContainer
), layoutType = when {
isVerticalLayout() -> NavigationSuiteType.NavigationBar
else -> NavigationSuiteType.NavigationRail
} }
) { MainNavHost(navController) }
}
@Composable
private fun MainNavHost(navController: NavHostController) {
val navigateToRadar = { catNum: Int, aosTime: Long ->
val routeWithParams = "${Screen.Radar.route}?catNum=${catNum}&aosTime=${aosTime}"
navController.navigate(routeWithParams)
}
NavHost(navController = navController, startDestination = startDestination) {
satellitesDestination { navController.navigateUp() }
passesDestination(navigateToRadar)
radarDestination { navController.navigateUp() }
mapDestination()
settingsDestination()
} }
} }

Wyświetl plik

@ -109,7 +109,7 @@ private val darkScheme = darkColorScheme(
// outlineVariant = Color(0xFF121212), // outlineVariant = Color(0xFF121212),
scrim = Color(0xFF000000), scrim = Color(0xFF000000),
// surfaceBright = Color(0xFF121212), // surfaceBright = Color(0xFF121212),
surfaceContainer = Color(0xFF242424), // navBar background surfaceContainer = Color(0xFF121212), // navBar background
// surfaceContainerHigh = Color(0xFF121212), // surfaceContainerHigh = Color(0xFF121212),
surfaceContainerHighest = Color(0xFF242424), // filled card background surfaceContainerHighest = Color(0xFF242424), // filled card background
surfaceContainerLow = Color(0xFF242424), // elevated card background surfaceContainerLow = Color(0xFF242424), // elevated card background

Wyświetl plik

@ -13,6 +13,7 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.CircularProgressIndicator
@ -283,3 +284,13 @@ fun isVerticalLayout(): Boolean {
val windowSizeClass = currentWindowAdaptiveInfo().windowSizeClass val windowSizeClass = currentWindowAdaptiveInfo().windowSizeClass
return windowSizeClass.windowWidthSizeClass == WindowWidthSizeClass.COMPACT return windowSizeClass.windowWidthSizeClass == WindowWidthSizeClass.COMPACT
} }
@Composable
fun Modifier.layoutPadding(): Modifier {
val statusBarMod = this.statusBarsPadding()
val spacing = LocalSpacing.current.small
return when {
isVerticalLayout() -> statusBarMod.padding(horizontal = spacing)
else -> statusBarMod.padding(start = 0.dp, top = 0.dp, end = spacing, bottom = spacing)
}
}

Wyświetl plik

@ -57,6 +57,8 @@ import org.osmdroid.views.overlay.Polyline
import androidx.core.graphics.toColorInt import androidx.core.graphics.toColorInt
import androidx.core.graphics.createBitmap import androidx.core.graphics.createBitmap
import androidx.core.graphics.drawable.toDrawable import androidx.core.graphics.drawable.toDrawable
import com.rtbishop.look4sat.presentation.common.isVerticalLayout
import com.rtbishop.look4sat.presentation.common.layoutPadding
private val minLat = MapView.getTileSystem().minLatitude private val minLat = MapView.getTileSystem().minLatitude
private val maxLat = MapView.getTileSystem().maxLatitude private val maxLat = MapView.getTileSystem().maxLatitude
@ -98,13 +100,22 @@ private fun MapScreen(uiState: State<MapState>, mapView: MapView) {
val timeString = uiState.value.mapData?.aosTime ?: "00:00:00" val timeString = uiState.value.mapData?.aosTime ?: "00:00:00"
val isTimeAos = uiState.value.mapData?.isTimeAos ?: true val isTimeAos = uiState.value.mapData?.isTimeAos ?: true
val osmInfo = "© OpenStreetMap contributors" val osmInfo = "© OpenStreetMap contributors"
Column(modifier = Modifier.padding(6.dp), verticalArrangement = Arrangement.spacedBy(6.dp)) { Column(modifier = Modifier.layoutPadding(), verticalArrangement = Arrangement.spacedBy(6.dp)) {
TopBar { if (isVerticalLayout()) {
IconCard(onClick = selectPrev, iconId = R.drawable.ic_arrow, modifier = rotateMod) TopBar {
TimerRow(timeString = timeString, isTimeAos = isTimeAos) IconCard(onClick = selectPrev, iconId = R.drawable.ic_arrow, modifier = rotateMod)
IconCard(onClick = selectNext, iconId = R.drawable.ic_arrow) TimerRow(timeString = timeString, isTimeAos = isTimeAos)
IconCard(onClick = selectNext, iconId = R.drawable.ic_arrow)
}
NextPassRow(pass = uiState.value.orbitalPass)
} else {
TopBar {
IconCard(onClick = selectPrev, iconId = R.drawable.ic_arrow, modifier = rotateMod)
TimerRow(timeString = timeString, isTimeAos = isTimeAos)
NextPassRow(pass = uiState.value.orbitalPass, modifier = Modifier.weight(1f))
IconCard(onClick = selectNext, iconId = R.drawable.ic_arrow)
}
} }
NextPassRow(pass = uiState.value.orbitalPass)
ElevatedCard(modifier = Modifier.weight(1f)) { ElevatedCard(modifier = Modifier.weight(1f)) {
Box(contentAlignment = Alignment.BottomCenter) { Box(contentAlignment = Alignment.BottomCenter) {
LaunchedEffect(uiState.value.track) { LaunchedEffect(uiState.value.track) {

Wyświetl plik

@ -11,8 +11,9 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.items
import androidx.compose.material3.ElevatedCard import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
@ -50,6 +51,7 @@ import com.rtbishop.look4sat.presentation.common.NextPassRow
import com.rtbishop.look4sat.presentation.common.TimerRow import com.rtbishop.look4sat.presentation.common.TimerRow
import com.rtbishop.look4sat.presentation.common.TopBar import com.rtbishop.look4sat.presentation.common.TopBar
import com.rtbishop.look4sat.presentation.common.isVerticalLayout import com.rtbishop.look4sat.presentation.common.isVerticalLayout
import com.rtbishop.look4sat.presentation.common.layoutPadding
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Date import java.util.Date
import java.util.Locale import java.util.Locale
@ -91,7 +93,7 @@ private fun PassesScreen(uiState: PassesState, navigateToRadar: (Int, Long) -> U
uiState.takeAction(PassesAction.DismissWelcome) uiState.takeAction(PassesAction.DismissWelcome)
} }
} }
Column(modifier = Modifier.padding(6.dp), verticalArrangement = Arrangement.spacedBy(6.dp)) { Column(modifier = Modifier.layoutPadding(), verticalArrangement = Arrangement.spacedBy(6.dp)) {
if (isVerticalLayout()) { if (isVerticalLayout()) {
TopBar { TopBar {
IconCard(onClick = { showPassesDialog() }, iconId = R.drawable.ic_filter) IconCard(onClick = { showPassesDialog() }, iconId = R.drawable.ic_filter)
@ -135,21 +137,16 @@ private fun PassesList(
) )
} }
) { ) {
LazyColumn(modifier = Modifier.fillMaxSize()) { LazyVerticalGrid(
columns = GridCells.Adaptive(320.dp),
modifier = Modifier.fillMaxSize()
) {
items(items = passes, key = { item -> item.catNum + item.aosTime }) { pass -> items(items = passes, key = { item -> item.catNum + item.aosTime }) { pass ->
if (pass.isDeepSpace) { NearEarthPass(
DeepSpacePass( pass = pass,
pass = pass, navigateToRadar = navigateToRadar,
navigateToRadar = navigateToRadar, modifier = Modifier.animateItem()
modifier = Modifier.animateItem() )
)
} else {
NearEarthPass(
pass = pass,
navigateToRadar = navigateToRadar,
modifier = Modifier.animateItem()
)
}
} }
} }
} }
@ -159,114 +156,16 @@ private fun PassesList(
@Preview(showBackground = true) @Preview(showBackground = true)
@Composable @Composable
private fun DeepSpacePassPreview() { private fun DeepSpacePassPreview() {
val data = OrbitalData( val data = OrbitalData("Satellite", 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 45000, 0.0)
"Satellite", 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 45000, 0.0
)
val satellite = DeepSpaceObject(data) val satellite = DeepSpaceObject(data)
val pass = OrbitalPass(1L, 180.0, 10L, 360.0, 36650, 45.0, satellite, 0.5f) val pass = OrbitalPass(1L, 180.0, 10L, 360.0, 36650, 45.0, satellite, 0.5f)
MainTheme { DeepSpacePass(pass = pass, { _, _ -> }) } MainTheme { NearEarthPass(pass = pass, { _, _ -> }) }
}
@Composable
private fun DeepSpacePass(
pass: OrbitalPass,
navigateToRadar: (Int, Long) -> Unit,
modifier: Modifier = Modifier
) {
val passSatId = stringResource(id = R.string.pass_satId, pass.catNum)
Surface(color = MaterialTheme.colorScheme.background, modifier = modifier) {
Surface(modifier = Modifier
.padding(bottom = 2.dp)
.clickable { navigateToRadar(pass.catNum, pass.aosTime) }) {
Column(
verticalArrangement = Arrangement.spacedBy(1.dp),
modifier = Modifier
.background(color = MaterialTheme.colorScheme.surface)
.padding(horizontal = 6.dp, vertical = 4.dp)
) {
Row(verticalAlignment = Alignment.CenterVertically) {
Text(
text = "$passSatId - ",
color = MaterialTheme.colorScheme.primary
)
Text(
text = pass.name,
modifier = Modifier
.weight(1f)
.padding(end = 6.dp),
fontWeight = FontWeight.Medium,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
Icon(
painter = painterResource(id = R.drawable.ic_elevation),
contentDescription = null,
tint = MaterialTheme.colorScheme.primary,
modifier = Modifier.size(16.dp)
)
Spacer(modifier = Modifier.width(4.dp))
Text(
text = "${pass.maxElevation}°",
color = MaterialTheme.colorScheme.primary
)
}
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween,
modifier = Modifier.fillMaxWidth()
) {
Row(
modifier = Modifier.weight(1f),
horizontalArrangement = Arrangement.Start,
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = "DeepSpace",
fontSize = 15.sp
)
}
Row(
modifier = Modifier.weight(1f),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically
) {
Icon(
painter = painterResource(id = R.drawable.ic_altitude),
contentDescription = null,
modifier = Modifier.size(16.dp)
)
Spacer(modifier = Modifier.width(4.dp))
Text(
text = "${pass.altitude} km",
fontSize = 15.sp
)
}
Row(
modifier = Modifier.weight(1f),
horizontalArrangement = Arrangement.End,
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = stringResource(
id = R.string.pass_aosLos,
pass.aosAzimuth.toInt(),
pass.losAzimuth.toInt()
),
fontSize = 15.sp
)
}
}
}
}
}
} }
@Preview(showBackground = true) @Preview(showBackground = true)
@Composable @Composable
private fun NearEarthPassPreview() { private fun NearEarthPassPreview() {
val data = OrbitalData( val data = OrbitalData("Satellite", 0.0, 15.0, 0.0, 0.0, 0.0, 0.0, 0.0, 45000, 0.0)
"Satellite", 0.0, 15.0, 0.0, 0.0, 0.0, 0.0, 0.0, 45000, 0.0
)
val satellite = NearEarthObject(data) val satellite = NearEarthObject(data)
val pass = OrbitalPass(1L, 180.0, 10L, 360.0, 36650, 45.0, satellite, 0.5f) val pass = OrbitalPass(1L, 180.0, 10L, 360.0, 36650, 45.0, satellite, 0.5f)
MainTheme { NearEarthPass(pass = pass, { _, _ -> }) } MainTheme { NearEarthPass(pass = pass, { _, _ -> }) }
@ -281,7 +180,7 @@ private fun NearEarthPass(
val passSatId = stringResource(id = R.string.pass_satId, pass.catNum) val passSatId = stringResource(id = R.string.pass_satId, pass.catNum)
Surface(color = MaterialTheme.colorScheme.background, modifier = modifier) { Surface(color = MaterialTheme.colorScheme.background, modifier = modifier) {
Surface(modifier = Modifier Surface(modifier = Modifier
.padding(bottom = 2.dp) .padding(bottom = 2.dp, start = 1.dp, end = 1.dp)
.clickable { navigateToRadar(pass.catNum, pass.aosTime) }) { .clickable { navigateToRadar(pass.catNum, pass.aosTime) }) {
Column( Column(
verticalArrangement = Arrangement.spacedBy(1.dp), verticalArrangement = Arrangement.spacedBy(1.dp),
@ -325,10 +224,14 @@ private fun NearEarthPass(
horizontalArrangement = Arrangement.Start, horizontalArrangement = Arrangement.Start,
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {
Text( if (pass.isDeepSpace) {
text = sdfDate.format(Date(pass.aosTime)), Text(text = "DeepSpace", fontSize = 15.sp)
fontSize = 15.sp } else {
) Text(
text = sdfDate.format(Date(pass.aosTime)),
fontSize = 15.sp
)
}
} }
Row( Row(
modifier = Modifier.weight(1f), modifier = Modifier.weight(1f),

Wyświetl plik

@ -27,7 +27,6 @@ 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
@ -58,8 +57,10 @@ import com.rtbishop.look4sat.presentation.common.NextPassRow
import com.rtbishop.look4sat.presentation.common.TimerRow import com.rtbishop.look4sat.presentation.common.TimerRow
import com.rtbishop.look4sat.presentation.common.TopBar import com.rtbishop.look4sat.presentation.common.TopBar
import com.rtbishop.look4sat.presentation.common.getDefaultPass import com.rtbishop.look4sat.presentation.common.getDefaultPass
import com.rtbishop.look4sat.presentation.common.isVerticalLayout
import com.rtbishop.look4sat.presentation.common.layoutPadding
fun NavGraphBuilder.radarDestination(navigateBack: () -> Unit) { fun NavGraphBuilder.radarDestination(navigateUp: () -> Unit) {
val radarRoute = "${Screen.Radar.route}?catNum={catNum}&aosTime={aosTime}" val radarRoute = "${Screen.Radar.route}?catNum={catNum}&aosTime={aosTime}"
val radarArgs = listOf( val radarArgs = listOf(
navArgument("catNum") { defaultValue = 0 }, navArgument("catNum") { defaultValue = 0 },
@ -68,31 +69,36 @@ 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
RadarScreen(uiState, navigateBack) RadarScreen(uiState, navigateUp)
} }
} }
@Composable @Composable
private fun RadarScreen(uiState: RadarState, navigateBack: () -> Unit) { private fun RadarScreen(uiState: RadarState, navigateUp: () -> Unit) {
// BluetoothCIV.init(LocalContext.current) // BluetoothCIV.init(LocalContext.current)
val addToCalendar: () -> Unit = { val addToCalendar: () -> Unit = {
uiState.currentPass?.let { pass -> uiState.currentPass?.let { pass ->
uiState.sendAction(RadarAction.AddToCalendar(pass.name, pass.aosTime, pass.losTime)) uiState.sendAction(RadarAction.AddToCalendar(pass.name, pass.aosTime, pass.losTime))
} }
} }
Scaffold { innerPadding -> val upcomingPass = uiState.currentPass ?: getDefaultPass()
val paddingMod = Modifier.padding(innerPadding) Column(modifier = Modifier.layoutPadding(), verticalArrangement = Arrangement.spacedBy(6.dp)) {
Column( if (isVerticalLayout()) {
modifier = paddingMod.padding(6.dp),
verticalArrangement = Arrangement.spacedBy(6.dp)
) {
TopBar { TopBar {
IconCard(onClick = navigateBack, iconId = R.drawable.ic_back) IconCard(onClick = navigateUp, iconId = R.drawable.ic_back)
TimerRow(timeString = uiState.currentTime, isTimeAos = uiState.isCurrentTimeAos) TimerRow(timeString = uiState.currentTime, isTimeAos = uiState.isCurrentTimeAos)
IconCard(onClick = addToCalendar, iconId = R.drawable.ic_calendar) IconCard(onClick = addToCalendar, iconId = R.drawable.ic_calendar)
} }
NextPassRow(pass = uiState.currentPass ?: getDefaultPass()) NextPassRow(pass = upcomingPass)
} else {
TopBar {
IconCard(onClick = navigateUp, iconId = R.drawable.ic_back)
TimerRow(timeString = uiState.currentTime, isTimeAos = uiState.isCurrentTimeAos)
NextPassRow(pass = upcomingPass, modifier = Modifier.weight(1f))
IconCard(onClick = addToCalendar, iconId = R.drawable.ic_calendar)
}
}
if(isVerticalLayout()) {
Box(contentAlignment = Alignment.BottomCenter, modifier = Modifier.aspectRatio(1f)) { Box(contentAlignment = Alignment.BottomCenter, modifier = Modifier.aspectRatio(1f)) {
uiState.orbitalPos?.let { position -> uiState.orbitalPos?.let { position ->
ElevatedCard { ElevatedCard {
@ -172,6 +178,88 @@ private fun RadarScreen(uiState: RadarState, navigateBack: () -> Unit) {
} }
} }
} }
} else {
Row(horizontalArrangement = Arrangement.spacedBy(6.dp)) {
Box(contentAlignment = Alignment.BottomCenter, modifier = Modifier.weight(1f)) {
uiState.orbitalPos?.let { position ->
ElevatedCard {
RadarViewCompose(
item = position,
items = uiState.satTrack,
azimElev = uiState.orientationValues,
shouldShowSweep = uiState.shouldShowSweep,
shouldUseCompass = false
)
}
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
)
}
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().weight(1f)) {
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

@ -14,6 +14,9 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.items
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.text.BasicTextField import androidx.compose.foundation.text.BasicTextField
import androidx.compose.material3.CardDefaults import androidx.compose.material3.CardDefaults
@ -46,23 +49,25 @@ import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.domain.model.SatItem import com.rtbishop.look4sat.domain.model.SatItem
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.common.IconCard
import com.rtbishop.look4sat.presentation.common.CardLoadingIndicator import com.rtbishop.look4sat.presentation.common.CardLoadingIndicator
import com.rtbishop.look4sat.presentation.common.IconCard
import com.rtbishop.look4sat.presentation.common.InfoDialog import com.rtbishop.look4sat.presentation.common.InfoDialog
import com.rtbishop.look4sat.presentation.common.TopBar
import com.rtbishop.look4sat.presentation.common.isVerticalLayout
import com.rtbishop.look4sat.presentation.common.layoutPadding
fun NavGraphBuilder.satellitesDestination(navigateToPasses: () -> Unit) { fun NavGraphBuilder.satellitesDestination(navigateUp: () -> 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
SatellitesScreen(uiState, navigateToPasses) SatellitesScreen(uiState, navigateUp)
} }
} }
@Composable @Composable
private fun SatellitesScreen(uiState: SatellitesState, navigateToPasses: () -> Unit) { private fun SatellitesScreen(uiState: SatellitesState, navigateUp: () -> Unit) {
val toggleDialog = { uiState.takeAction(SatellitesAction.ToggleTypesDialog) } val toggleDialog = { uiState.takeAction(SatellitesAction.ToggleTypesDialog) }
if (uiState.isDialogShown) { if (uiState.isDialogShown) {
MultiTypesDialog(allTypes = uiState.typesList, types = uiState.currentTypes, toggleDialog) { MultiTypesDialog(allTypes = uiState.typesList, types = uiState.currentTypes, toggleDialog) {
@ -79,14 +84,28 @@ private fun SatellitesScreen(uiState: SatellitesState, navigateToPasses: () -> U
} }
val unselectAll = { uiState.takeAction(SatellitesAction.UnselectAll) } val unselectAll = { uiState.takeAction(SatellitesAction.UnselectAll) }
val selectAll = { uiState.takeAction(SatellitesAction.SelectAll) } val selectAll = { uiState.takeAction(SatellitesAction.SelectAll) }
Column(modifier = Modifier.padding(6.dp), verticalArrangement = Arrangement.spacedBy(6.dp)) { val setQuery = { newQuery: String -> uiState.takeAction(SatellitesAction.SearchFor(newQuery)) }
TopBar(setQuery = { newQuery: String -> val saveSelection = { uiState.takeAction(SatellitesAction.SaveSelection).also { navigateUp() } }
uiState.takeAction(SatellitesAction.SearchFor(newQuery)) Column(modifier = Modifier.layoutPadding(), verticalArrangement = Arrangement.spacedBy(6.dp)) {
}, saveSelection = { if (isVerticalLayout()) {
uiState.takeAction(SatellitesAction.SaveSelection) TopBar {
navigateToPasses() TypeCard(types = uiState.currentTypes, toggleDialog, modifier = Modifier.weight(1f))
}) SaveButton(saveSelection = saveSelection, modifier = Modifier.height(48.dp))
MiddleBar(uiState.currentTypes, { toggleDialog() }, { unselectAll() }, { selectAll() }) }
TopBar {
SearchBar(setQuery = { setQuery(it) }, modifier = Modifier.weight(1f))
IconCard(onClick = unselectAll, iconId = R.drawable.ic_check_off)
IconCard(onClick = selectAll, iconId = R.drawable.ic_check_on)
}
} else {
TopBar {
SaveButton(saveSelection = saveSelection, modifier = Modifier.height(48.dp))
TypeCard(types = uiState.currentTypes, toggleDialog, modifier = Modifier.weight(1f))
SearchBar(setQuery = { setQuery(it) }, modifier = Modifier.weight(1f))
IconCard(onClick = unselectAll, iconId = R.drawable.ic_check_off)
IconCard(onClick = selectAll, iconId = R.drawable.ic_check_on)
}
}
ElevatedCard(modifier = Modifier.fillMaxSize()) { ElevatedCard(modifier = Modifier.fillMaxSize()) {
if (uiState.isLoading) { if (uiState.isLoading) {
CardLoadingIndicator() CardLoadingIndicator()
@ -99,18 +118,6 @@ private fun SatellitesScreen(uiState: SatellitesState, navigateToPasses: () -> U
} }
} }
@Preview(showBackground = true)
@Composable
private fun TopBarPreview() = MainTheme { TopBar({}, {}) }
@Composable
private fun TopBar(setQuery: (String) -> Unit, saveSelection: () -> Unit) {
Row(horizontalArrangement = Arrangement.spacedBy(6.dp), modifier = Modifier.height(48.dp)) {
SearchBar(setQuery = { setQuery(it) }, modifier = Modifier.weight(1f))
SaveButton(saveSelection = { saveSelection() }, modifier = Modifier.height(48.dp))
}
}
@Composable @Composable
private fun SearchBar(setQuery: (String) -> Unit, modifier: Modifier = Modifier) { private fun SearchBar(setQuery: (String) -> Unit, modifier: Modifier = Modifier) {
val currentQuery = rememberSaveable { mutableStateOf("") } val currentQuery = rememberSaveable { mutableStateOf("") }
@ -168,26 +175,12 @@ private fun SaveButton(saveSelection: () -> Unit, modifier: Modifier = Modifier)
} }
} }
@Preview(showBackground = true)
@Composable
private fun MiddleBarPreview() = MainTheme { MiddleBar(listOf("Amateur"), {}, {}, {}) }
@Composable
private fun MiddleBar(
types: List<String>, navigate: () -> Unit, uncheck: () -> Unit, check: () -> Unit
) {
Row(horizontalArrangement = Arrangement.spacedBy(6.dp), modifier = Modifier.height(48.dp)) {
TypeCard(types = types, { navigate() }, modifier = Modifier.weight(1f))
IconCard(onClick = { uncheck() }, iconId = R.drawable.ic_check_off)
IconCard(onClick = { check() }, iconId = R.drawable.ic_check_on)
}
}
@Composable @Composable
private fun TypeCard(types: List<String>, onClick: () -> Unit, modifier: Modifier = Modifier) { private fun TypeCard(types: List<String>, onClick: () -> Unit, modifier: Modifier = Modifier) {
val typesText = if (types.isEmpty()) "All" else types.joinToString(", ") val typesText = if (types.isEmpty()) "All" else types.joinToString(", ")
ElevatedCard(modifier = modifier) { ElevatedCard(modifier = modifier) {
Row(horizontalArrangement = Arrangement.spacedBy(12.dp), Row(
horizontalArrangement = Arrangement.spacedBy(12.dp),
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
modifier = Modifier modifier = Modifier
.height(48.dp) .height(48.dp)
@ -221,7 +214,8 @@ private fun SatellitePreview() {
@Composable @Composable
private fun Satellite(item: SatItem, onSelected: (Int, Boolean) -> Unit, modifier: Modifier) { private fun Satellite(item: SatItem, onSelected: (Int, Boolean) -> Unit, modifier: Modifier) {
val passSatId = stringResource(id = R.string.pass_satId, item.catnum) val passSatId = stringResource(id = R.string.pass_satId, item.catnum)
Surface(color = MaterialTheme.colorScheme.background, Surface(
color = MaterialTheme.colorScheme.background,
modifier = modifier.clickable { onSelected(item.catnum, item.isSelected) }) { modifier = modifier.clickable { onSelected(item.catnum, item.isSelected) }) {
Surface(modifier = Modifier.padding(bottom = 1.dp)) { Surface(modifier = Modifier.padding(bottom = 1.dp)) {
Row( Row(
@ -263,7 +257,7 @@ private fun SatellitesPreview() {
@Composable @Composable
fun SatellitesCard(items: List<SatItem>, onSelected: (Int, Boolean) -> Unit) { fun SatellitesCard(items: List<SatItem>, onSelected: (Int, Boolean) -> Unit) {
LazyColumn { LazyVerticalGrid(columns = GridCells.Adaptive(320.dp)) {
items(items = items, key = { item -> item.catnum }) { entry -> items(items = items, key = { item -> item.catnum }) { entry ->
Satellite(entry, onSelected, Modifier.animateItem()) Satellite(entry, onSelected, Modifier.animateItem())
} }

Wyświetl plik

@ -14,6 +14,8 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.material3.ElevatedCard 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
@ -44,6 +46,7 @@ import com.rtbishop.look4sat.domain.predict.GeoPos
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.common.CardButton import com.rtbishop.look4sat.presentation.common.CardButton
import com.rtbishop.look4sat.presentation.common.layoutPadding
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Date import java.util.Date
import java.util.Locale import java.util.Locale
@ -130,8 +133,10 @@ private fun SettingsScreen(uiState: SettingsState) {
} }
// Screen setup // Screen setup
LazyColumn( LazyVerticalGrid(
modifier = Modifier.padding(6.dp), columns = GridCells.Adaptive(320.dp),
modifier = Modifier.layoutPadding(),
horizontalArrangement = Arrangement.spacedBy(6.dp),
verticalArrangement = Arrangement.spacedBy(6.dp) verticalArrangement = Arrangement.spacedBy(6.dp)
) { ) {
item { CardAbout(uiState.appVersionName, uiState.sendSystemAction) } item { CardAbout(uiState.appVersionName, uiState.sendSystemAction) }
@ -461,17 +466,17 @@ 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) })
} }
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) }
) // )
} // }
} }
} }
} }

Wyświetl plik

@ -158,24 +158,24 @@
<string name="BTremote_output_hint">Формат данных</string> <string name="BTremote_output_hint">Формат данных</string>
<string name="BTremote_perm_error">Нет разрешения использовать bluetooth</string> <string name="BTremote_perm_error">Нет разрешения использовать bluetooth</string>
<string name="other_switch_utc">Показывать время по UTC</string> <string name="other_switch_utc">Показывать время по UTC</string>
<string name="other_switch_update">Обновлять данные автоматически</string> <string name="other_switch_update">Обновлять данные автоматически</string>
<string name="other_switch_sweep">Показывать анимацию радара</string> <string name="other_switch_sweep">Показывать анимацию радара</string>
<string name="other_switch_sensors">Использовать сенсоры устройства</string> <string name="other_switch_sensors">Использовать сенсоры устройства</string>
<string name="other_switch_light_theme">Использовать светлую тему</string> <string name="other_switch_light_theme">Использовать светлую тему</string>
<string name="outro_title">Я хотел бы сказать спасибо:</string> <string name="outro_title">Я хотел бы сказать спасибо:</string>
<string name="outro_thanks">Вам за использование этого приложения! \nЖелаю всегда чистого неба над головой! <string name="outro_thanks">Вам за использование этого приложения! \nЖелаю всегда чистого неба над головой!
\n<a href="https://github.com/g4dpz">David A. B. Johnson</a> и \n<a href="https://github.com/g4dpz">David A. B. Johnson</a> и
<a href="https://github.com/davidmoten">Dave Moten</a> за работу над predict4java и доступ <a href="https://github.com/davidmoten">Dave Moten</a> за работу над predict4java и доступ
к ней по <a href="https://gnu.org/licenses/old-licenses/gpl-2.0.en.html">GNU GPLv2</a> к ней по <a href="https://gnu.org/licenses/old-licenses/gpl-2.0.en.html">GNU GPLv2</a>
\n<a href="https://github.com/csete">Alexandru Csete</a> за его программу \n<a href="https://github.com/csete">Alexandru Csete</a> за его программу
Gpredict, которая послужила для меня вдохновением. Gpredict, которая послужила для меня вдохновением.
\n<a href="https://celestrak.com/webmaster.php">Доктору T.S. Kelso</a> за его сайт \n<a href="https://celestrak.com/webmaster.php">Доктору T.S. Kelso</a> за его сайт
<a href="https://celestrak.com/">Celestrak</a> и доступ к файлам орбит Two-Line Element. <a href="https://celestrak.com/">Celestrak</a> и доступ к файлам орбит Two-Line Element.
\n<a href="https://libre.space/">Libre Space Foundation</a> за проект \n<a href="https://libre.space/">Libre Space Foundation</a> за проект
<a href="https://db.satnogs.org/">SatNOGS</a>, API и базу данных с информацией о спутниках. <a href="https://db.satnogs.org/">SatNOGS</a>, API и базу данных с информацией о спутниках.
\n<a href="https://appoftheday.downloadastro.com/app/look4sat-satellite-tracker/">DownloadAstro</a> \n<a href="https://appoftheday.downloadastro.com/app/look4sat-satellite-tracker/">DownloadAstro</a>
за интерес к приложению и публикацию интервью на сайте. за интерес к приложению и публикацию интервью на сайте.
</string> </string>
<string name="outro_license">Это ПО поставляется без гарантий.</string> <string name="outro_license">Это ПО поставляется без гарантий.</string>

Wyświetl plik

@ -158,22 +158,22 @@
<string name="BTremote_output_hint">දත්ත අකාරය</string> <string name="BTremote_output_hint">දත්ත අකාරය</string>
<string name="BTremote_perm_error">Bluetooth අවසර පරික්‍ෂා ක°</string> <string name="BTremote_perm_error">Bluetooth අවසර පරික්‍ෂා ක°</string>
<string name="other_switch_utc">පසුකර වේලාවන් UTC මගින්</string> <string name="other_switch_utc">පසුකර වේලාවන් UTC මගින්</string>
<string name="other_switch_update">ස්වයං දත්ත යාවත්කාලීනය</string> <string name="other_switch_update">ස්වයං දත්ත යාවත්කාලීනය</string>
<string name="other_switch_sweep">radar sweep සජීවිකරණය සබල කරන්න</string> <string name="other_switch_sweep">radar sweep සජීවිකරණය සබල කරන්න</string>
<string name="other_switch_sensors">Radar දර්ශනය කරකැවීමට සංවේදක භාවිතා කරන්න </string> <string name="other_switch_sensors">Radar දර්ශනය කරකැවීමට සංවේදක භාවිතා කරන්න </string>
<string name="other_switch_light_theme">සැහැල්ලු තේමාව භාවිතා කරන්න</string> <string name="other_switch_light_theme">සැහැල්ලු තේමාව භාවිතා කරන්න</string>
<string name="outro_title">මම ස්තුති කිරීමට කැමති:</string> <string name="outro_title">මම ස්තුති කිරීමට කැමති:</string>
<string name="outro_thanks">බාගෙන භාවිතා කළ ඔබට! \nඅහස සදා ඔබ වෙනුවෙන් පැහැදිලියි! <string name="outro_thanks">බාගෙන භාවිතා කළ ඔබට! \nඅහස සදා ඔබ වෙනුවෙන් පැහැදිලියි!
\n<a href="https://github.com/g4dpz">David A. B. Johnson</a> \n<a href="https://github.com/g4dpz">David A. B. Johnson</a>
සහ <a href="https://github.com/davidmoten">Dave Moten</a>ඔවුනට ප්‍රයෝජනවත් predict4java පුස්තකාලය නිර්මාණයට. සහ <a href="https://github.com/davidmoten">Dave Moten</a>ඔවුනට ප්‍රයෝජනවත් predict4java පුස්තකාලය නිර්මාණයට.
\nසහ <a href="https://github.com/csete">Alexandru Csete</a> සඳහා Gpredict නිර්මාණයට සහ \nසහ <a href="https://github.com/csete">Alexandru Csete</a> සඳහා Gpredict නිර්මාණයට සහ
Look4Sat නිර්මාණය⁣ට පෙළඹවීමට. Look4Sat නිර්මාණය⁣ට පෙළඹවීමට.
\n<a href="https://celestrak.com/webmaster.php">Dr T.S. Kelso</a>ට TLE දත්ත සැපයීමට, ඔහුගේ නඩත්තුවෙන් ක්‍රියාත්මක WEB අඩවිට ප්‍රවේශය සැපයීම වෙනුවෙන් \n<a href="https://celestrak.com/webmaster.php">Dr T.S. Kelso</a>ට TLE දත්ත සැපයීමට, ඔහුගේ නඩත්තුවෙන් ක්‍රියාත්මක WEB අඩවිට ප්‍රවේශය සැපයීම වෙනුවෙන්
<a href="https://celestrak.com/"> (Celestrak)</a>. <a href="https://celestrak.com/"> (Celestrak)</a>.
\n<a href="https://libre.space/">Libre Space Foundation</a>ට ඔවුන්ගේ \n<a href="https://libre.space/">Libre Space Foundation</a>ට ඔවුන්ගේ
<a href="https://db.satnogs.org/">SatNOGS</a>Web අඩවියට API හා DB විශාල දත්ත ප්‍රමාණයක් ලබාදීම සඳහා. <a href="https://db.satnogs.org/">SatNOGS</a>Web අඩවියට API හා DB විශාල දත්ත ප්‍රමාණයක් ලබාදීම සඳහා.
\n<a href="https://appoftheday.downloadastro.com/app/look4sat-satellite-tracker/">DownloadAstro</a> කණ්ඩායමට යෙදුම පිළිබඳ ඔවුන්ගේ උනන්දුව සහ කැපවීම ලැබිම සම්බන්ධයෙන්.</string> \n<a href="https://appoftheday.downloadastro.com/app/look4sat-satellite-tracker/">DownloadAstro</a> කණ්ඩායමට යෙදුම පිළිබඳ ඔවුන්ගේ උනන්දුව සහ කැපවීම ලැබිම සම්බන්ධයෙන්.</string>
<string name="outro_license">මෘදුකාංගය වගකීමක් සමග නොලැබේ</string> <string name="outro_license">මෘදුකාංගය වගකීමක් සමග නොලැබේ</string>
</resources> </resources>

Wyświetl plik

@ -158,25 +158,25 @@
<string name="BTremote_output_hint">数据格式</string> <string name="BTremote_output_hint">数据格式</string>
<string name="BTremote_perm_error">请检查蓝牙权限</string> <string name="BTremote_perm_error">请检查蓝牙权限</string>
<string name="other_switch_utc">以 UTC 时间显示</string> <string name="other_switch_utc">以 UTC 时间显示</string>
<string name="other_switch_update">启用卫星数据自动更新</string> <string name="other_switch_update">启用卫星数据自动更新</string>
<string name="other_switch_sweep">启用雷达扫描动画</string> <string name="other_switch_sweep">启用雷达扫描动画</string>
<string name="other_switch_sensors">使用传感器旋转雷达视图</string> <string name="other_switch_sensors">使用传感器旋转雷达视图</string>
<string name="other_switch_light_theme">使用旧版配色方案</string> <string name="other_switch_light_theme">使用旧版配色方案</string>
<string name="outro_title">我要感谢:</string> <string name="outro_title">我要感谢:</string>
<string name="outro_thanks">感谢下载和使用 Look4Sat愿你的天空永远晴朗 <string name="outro_thanks">感谢下载和使用 Look4Sat愿你的天空永远晴朗
\n简体中文版翻译由 <a href="https://github.com/BA7LWN">BA7LWN</a> 于 2022.5.10 创建。 \n简体中文版翻译由 <a href="https://github.com/BA7LWN">BA7LWN</a> 于 2022.5.10 创建。
\n<a href="https://github.com/g4dpz">David A. B. Johnson</a> \n<a href="https://github.com/g4dpz">David A. B. Johnson</a>
and <a href="https://github.com/davidmoten">Dave Moten</a> for creating predict4java lib and <a href="https://github.com/davidmoten">Dave Moten</a> for creating predict4java lib
under the <a href="https://gnu.org/licenses/old-licenses/gpl-2.0.en.html">GNU GPLv2</a>. under the <a href="https://gnu.org/licenses/old-licenses/gpl-2.0.en.html">GNU GPLv2</a>.
\n<a href="https://github.com/csete">Alexandru Csete</a> for creating Gpredict \n<a href="https://github.com/csete">Alexandru Csete</a> for creating Gpredict
satellite tracker that inspired the creation of Look4Sat. satellite tracker that inspired the creation of Look4Sat.
\n<a href="https://celestrak.com/webmaster.php">Dr T.S. Kelso</a> for maintaining his \n<a href="https://celestrak.com/webmaster.php">Dr T.S. Kelso</a> for maintaining his
<a href="https://celestrak.com/">Celestrak</a> website that provides access to the TLE data. <a href="https://celestrak.com/">Celestrak</a> website that provides access to the TLE data.
\n<a href="https://libre.space/">Libre Space Foundation</a> for their \n<a href="https://libre.space/">Libre Space Foundation</a> for their
<a href="https://db.satnogs.org/">SatNOGS</a> API and DB providing a huge amount of satellite data. <a href="https://db.satnogs.org/">SatNOGS</a> API and DB providing a huge amount of satellite data.
\n<a href="https://appoftheday.downloadastro.com/app/look4sat-satellite-tracker/">DownloadAstro</a> \n<a href="https://appoftheday.downloadastro.com/app/look4sat-satellite-tracker/">DownloadAstro</a>
team for their interest to the app and the interview published. team for their interest to the app and the interview published.
</string> </string>
<string name="outro_license">该应用程序不提供任何保修.</string> <string name="outro_license">该应用程序不提供任何保修.</string>

Wyświetl plik

@ -173,23 +173,23 @@
<string name="BTremote_output_hint">Data format</string> <string name="BTremote_output_hint">Data format</string>
<string name="BTremote_perm_error">Check your bluetooth permission</string> <string name="BTremote_perm_error">Check your bluetooth permission</string>
<string name="other_switch_utc">Show pass time in UTC</string> <string name="other_switch_utc">Show pass time in UTC</string>
<string name="other_switch_update">Enable automatic data update</string> <string name="other_switch_update">Enable automatic data update</string>
<string name="other_switch_sweep">Enable radar sweep animation</string> <string name="other_switch_sweep">Enable radar sweep animation</string>
<string name="other_switch_sensors">Use sensors to rotate radar view</string> <string name="other_switch_sensors">Use sensors to rotate radar view</string>
<string name="other_switch_light_theme">Use light theme</string> <string name="other_switch_light_theme">Use light theme</string>
<string name="outro_title">I would like to say thanks to:</string> <string name="outro_title">I would like to say thanks to:</string>
<string name="outro_thanks">You for downloading and using Look4Sat! \nMay your sky always be clear! <string name="outro_thanks">You for downloading and using Look4Sat! \nMay your sky always be clear!
\n<a href="https://github.com/g4dpz">David A. B. Johnson</a> \n<a href="https://github.com/g4dpz">David A. B. Johnson</a>
and <a href="https://github.com/davidmoten">Dave Moten</a> for creating a super useful predict4java library. and <a href="https://github.com/davidmoten">Dave Moten</a> for creating a super useful predict4java library.
\n<a href="https://github.com/csete">Alexandru Csete</a> for creating Gpredict \n<a href="https://github.com/csete">Alexandru Csete</a> for creating Gpredict
tracker that inspired the creation of Look4Sat. tracker that inspired the creation of Look4Sat.
\n<a href="https://celestrak.com/webmaster.php">Dr T.S. Kelso</a> for maintaining his \n<a href="https://celestrak.com/webmaster.php">Dr T.S. Kelso</a> for maintaining his
<a href="https://celestrak.com/">Celestrak</a> website that provides access to the TLE data. <a href="https://celestrak.com/">Celestrak</a> website that provides access to the TLE data.
\n<a href="https://libre.space/">Libre Space Foundation</a> for their \n<a href="https://libre.space/">Libre Space Foundation</a> for their
<a href="https://db.satnogs.org/">SatNOGS</a> API and DB providing a huge amount of data. <a href="https://db.satnogs.org/">SatNOGS</a> API and DB providing a huge amount of data.
\n<a href="https://appoftheday.downloadastro.com/app/look4sat-satellite-tracker/">DownloadAstro</a> \n<a href="https://appoftheday.downloadastro.com/app/look4sat-satellite-tracker/">DownloadAstro</a>
team for their interest to the app and the interview published. team for their interest to the app and the interview published.
</string> </string>
<string name="outro_license">The app comes with no warranty.</string> <string name="outro_license">The app comes with no warranty.</string>

Wyświetl plik

@ -33,7 +33,7 @@ androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "
compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "compose-bom" } compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "compose-bom" }
compose-animation = { group = "androidx.compose.animation", name = "animation" } compose-animation = { group = "androidx.compose.animation", name = "animation" }
compose-material3 = { group = "androidx.compose.material3", name = "material3" } compose-material3 = { group = "androidx.compose.material3", name = "material3" }
compose-material3-adaptive = { group = "androidx.compose.material3.adaptive", name = "adaptive" } compose-material3-navigation = { group = "androidx.compose.material3", name = "material3-adaptive-navigation-suite" }
compose-runtime = { group = "androidx.compose.runtime", name = "runtime" } compose-runtime = { group = "androidx.compose.runtime", name = "runtime" }
compose-tooling = { group = "androidx.compose.ui", name = "ui-tooling" } compose-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
@ -68,7 +68,7 @@ kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
[bundles] [bundles]
composeAll = [ composeAll = [
"compose-animation", "compose-runtime", "compose-tooling", "compose-activity", "compose-animation", "compose-runtime", "compose-tooling", "compose-activity",
"compose-lifecycle", "compose-material3", "compose-material3-adaptive", "compose-lifecycle", "compose-material3", "compose-material3-navigation",
"compose-navigation", "compose-viewmodel" "compose-navigation", "compose-viewmodel"
] ]
composeDebug = ["compose-debug-manifest", "compose-debug-tooling"] composeDebug = ["compose-debug-manifest", "compose-debug-tooling"]