Implemented landscape support for MapScreen

This commit is contained in:
Arty Bishop committed 2025-12-27 15:01:47 +00:00
1 parent 5a0ff019e9
commit 609c83ed34
13 files changed
+87 -48

No files matched your search

@@ -113,7 +113,7 @@ private val darkScheme = darkColorScheme(
// surfaceContainerHigh = Color(0xFF121212),
surfaceContainerHighest = Color(0xFF242424), // filled card background
surfaceContainerLow = Color(0xFF202020), // elevated card background
// surfaceContainerLowest = Color(0xFF121212),
surfaceContainerLowest = Color(0xCC121212),
// surfaceDim = Color(0xFF121212),
)
@@ -1,6 +1,7 @@
package com.rtbishop.look4sat.presentation.common
import androidx.compose.foundation.background
import androidx.compose.foundation.basicMarquee
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
@@ -117,7 +118,8 @@ fun NextPassRow(pass: OrbitalPass, modifier: Modifier = Modifier) {
text = pass.name,
modifier = Modifier
.weight(1f)
.padding(end = 6.dp),
.padding(end = 6.dp)
.basicMarquee(),
fontWeight = FontWeight.Medium,
maxLines = 1,
overflow = TextOverflow.Ellipsis
@@ -11,8 +11,12 @@ 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.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
@@ -26,7 +30,6 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.rotate
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.viewinterop.AndroidView
@@ -99,7 +102,11 @@ private fun MapScreen(uiState: State<MapState>, mapView: MapView) {
val rotateMod = Modifier.rotate(180f)
val timeString = uiState.value.mapData?.aosTime ?: "00:00:00"
val isTimeAos = uiState.value.mapData?.isTimeAos ?: true
val osmInfo = "© OpenStreetMap contributors"
LaunchedEffect(uiState.value.track) {
val latitude = uiState.value.track?.get(0)?.get(0)?.latitude ?: 0.0
val longitude = uiState.value.track?.get(0)?.get(0)?.longitude ?: 0.0
mapView.controller.animateTo(GeoPoint(latitude, longitude))
}
Column(modifier = Modifier.layoutPadding(), verticalArrangement = Arrangement.spacedBy(6.dp)) {
if (isVerticalLayout()) {
TopBar {
@@ -118,50 +125,80 @@ private fun MapScreen(uiState: State<MapState>, mapView: MapView) {
}
ElevatedCard(modifier = Modifier.weight(1f)) {
Box(contentAlignment = Alignment.BottomCenter) {
LaunchedEffect(uiState.value.track) {
val latitude = uiState.value.track?.get(0)?.get(0)?.latitude ?: 0.0
val longitude = uiState.value.track?.get(0)?.get(0)?.longitude ?: 0.0
mapView.controller.animateTo(GeoPoint(latitude, longitude))
}
AndroidView({ mapView }) { mapView ->
uiState.value.stationPosition?.let { setStationPosition(it, mapView) }
uiState.value.positions?.let { setPositions(it, mapView, onItemClick) }
uiState.value.track?.let { setSatelliteTrack(it, mapView) }
uiState.value.footprint?.let { setFootprint(it, mapView) }
}
Text(text = osmInfo, textAlign = TextAlign.Center, fontSize = 14.sp)
}
}
uiState.value.mapData?.let { mapData ->
ElevatedCard {
MapDataCard(mapData)
uiState.value.mapData?.let { mapData ->
if (isVerticalLayout()) MapDataCard(mapData) else MapDataCards(mapData)
}
}
}
}
}
@Composable
private fun MapDataCard(mapData: MapData) {
Column(modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp)) {
Row(horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth()) {
Text(text = stringResource(R.string.map_period, mapData.period), color = MaterialTheme.colorScheme.primary)
Text(text = stringResource(R.string.map_phase, mapData.phase), color = MaterialTheme.colorScheme.primary)
private fun MapDataCard(data: MapData) {
val textColor = MaterialTheme.colorScheme.primary
val cardColors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surfaceContainerLowest)
Column(horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.SpaceBetween) {
Text(text = "© OpenStreetMap contributors", fontSize = 14.sp)
Card(colors = cardColors) {
Column(modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp)) {
Row(horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth()) {
Text(text = stringResource(R.string.map_azimuth, data.azimuth))
Text(text = stringResource(R.string.map_elevation, data.elevation))
}
Row(horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth()) {
Text(text = stringResource(R.string.map_altitude, data.altitude), color = textColor)
Text(text = stringResource(R.string.map_distance, data.range), color = textColor)
}
Row(horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth()) {
Text(text = stringResource(R.string.map_latitude, data.osmPos.latitude))
Text(text = stringResource(R.string.map_longitude, data.osmPos.longitude))
}
Row(horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth()) {
Text(text = stringResource(R.string.map_qth, data.qthLoc), color = textColor)
Text(text = stringResource(R.string.map_phase, data.phase), color = textColor)
}
}
}
Row(horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth()) {
Text(text = stringResource(R.string.map_azimuth, mapData.azimuth))
Text(text = stringResource(R.string.map_elevation, mapData.elevation))
}
}
@Composable
private fun MapDataCards(data: MapData) {
val cardColors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surfaceContainerLowest)
val paddingMod = Modifier.padding(horizontal = 8.dp, vertical = 4.dp).width(160.dp)
val osmText = "© OpenStreetMap contributors"
val textColor = MaterialTheme.colorScheme.primary
Box(modifier = Modifier.fillMaxSize()) {
Card(colors = cardColors, modifier = Modifier.align(Alignment.TopStart)) {
Column(horizontalAlignment = Alignment.Start, modifier = paddingMod) {
Text(text = stringResource(R.string.map_azimuth, data.azimuth))
Text(text = stringResource(R.string.map_elevation, data.elevation), color = textColor)
}
}
Row(horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth()) {
Text(text = stringResource(R.string.map_altitude, mapData.altitude), color = MaterialTheme.colorScheme.primary)
Text(text = stringResource(R.string.map_distance, mapData.range), color = MaterialTheme.colorScheme.primary)
Card(colors = cardColors, modifier = Modifier.align(Alignment.TopEnd)) {
Column(horizontalAlignment = Alignment.End, modifier = paddingMod) {
Text(text = stringResource(R.string.map_altitude, data.altitude))
Text(text = stringResource(R.string.map_distance, data.range), color = textColor)
}
}
Row(horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth()) {
Text(text = stringResource(R.string.map_latitude, mapData.osmPos.latitude))
Text(text = stringResource(R.string.map_longitude, mapData.osmPos.longitude))
Card(colors = cardColors, modifier = Modifier.align(Alignment.BottomStart)) {
Column(horizontalAlignment = Alignment.Start, modifier = paddingMod) {
Text(text = stringResource(R.string.map_phase, data.phase))
Text(text = stringResource(R.string.map_qth, data.qthLoc), color = textColor)
}
}
Row(horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth()) {
Text(text = stringResource(R.string.map_qth, mapData.qthLoc), color = MaterialTheme.colorScheme.primary)
Text(text = stringResource(R.string.map_velocity, mapData.velocity), color = MaterialTheme.colorScheme.primary)
Text(text = osmText, fontSize = 14.sp, modifier = Modifier.align(Alignment.BottomCenter))
Card(colors = cardColors, modifier = Modifier.align(Alignment.BottomEnd)) {
Column(horizontalAlignment = Alignment.End, modifier = paddingMod) {
Text(text = stringResource(R.string.map_latitude, data.osmPos.latitude))
Text(text = stringResource(R.string.map_longitude, data.osmPos.longitude), color = textColor)
}
}
}
}
@@ -306,6 +343,8 @@ private fun getColorFilter(): ColorMatrixColorFilter {
return ColorMatrixColorFilter(negative)
}
@Composable
private fun getMinZoom(screenHeight: Int): Double {
if (!isVerticalLayout()) return 3.5
return MapView.getTileSystem().getLatitudeZoom(maxLat, minLat, screenHeight)
}
@@ -148,7 +148,7 @@ fun RadiosDialog(modes: List<String>, cancel: () -> Unit, accept: (List<String>)
val onAccept = { accept(selected.toList()).also { cancel() } }
SharedDialog(title = "Radios", onCancel = cancel, onAccept = onAccept) {
LazyVerticalGrid(
columns = GridCells.Fixed(1),
columns = GridCells.Adaptive(240.dp),
modifier = Modifier
.fillMaxHeight(0.69f)
.background(MaterialTheme.colorScheme.background),
@@ -1,6 +1,7 @@
package com.rtbishop.look4sat.presentation.passes
import androidx.compose.foundation.background
import androidx.compose.foundation.basicMarquee
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
@@ -201,7 +202,8 @@ private fun NearEarthPass(
text = pass.name,
modifier = Modifier
.weight(1f)
.padding(end = 6.dp),
.padding(end = 6.dp)
.basicMarquee(),
fontWeight = FontWeight.Medium,
maxLines = 1,
overflow = TextOverflow.Ellipsis
@@ -82,6 +82,7 @@ private fun RadarScreen(uiState: RadarState, navigateUp: () -> Unit) {
}
}
val upcomingPass = uiState.currentPass ?: getDefaultPass()
if (upcomingPass.losTime < System.currentTimeMillis()) navigateUp()
Column(modifier = Modifier.layoutPadding(), verticalArrangement = Arrangement.spacedBy(6.dp)) {
if (isVerticalLayout()) {
TopBar {
@@ -13,11 +13,9 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
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.text.BasicTextField
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.Checkbox
@@ -13,7 +13,6 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
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
-1
View File
@@ -117,7 +117,6 @@
<string name="map_elevation">Элевация: %.1f°</string>
<string name="map_latitude">Широта: %.1f°</string>
<string name="map_longitude">Долгота: %.1f°</string>
<string name="map_qth">QTH Локатор: %s</string>
<string name="map_visible">Видимый</string>
<string name="map_eclipsed">В тени</string>
<string name="map_visibility">Видимость: %s</string>
-1
View File
@@ -117,7 +117,6 @@
<string name="map_elevation">උත්තෝලනය: %.1f°</string>
<string name="map_latitude">අක්‍ෂාංශ: %.1f°</string>
<string name="map_longitude">දේශාංශ: %.1f°</string>
<string name="map_qth">QTH Locator: %s</string>
<string name="map_visible">දෘශ්‍ය</string>
<string name="map_eclipsed">අදෘශ්‍ය</string>
<string name="map_visibility">දෘශ්‍යතාව: %s</string>
@@ -117,7 +117,6 @@
<string name="map_elevation">仰角:%.1f°</string>
<string name="map_latitude">纬度:%.1f°</string>
<string name="map_longitude">经度:%.1f°</string>
<string name="map_qth">QTH 网格:%s</string>
<string name="map_visible">日照中</string>
<string name="map_eclipsed">地影中</string>
<string name="map_visibility">能见度:%s</string>
+1 -1
View File
@@ -130,7 +130,7 @@
<string name="map_elevation">Elevation: %.1f°</string>
<string name="map_latitude">Latitude: %.1f°</string>
<string name="map_longitude">Longitude: %.1f°</string>
<string name="map_qth">QTH Locator: %s</string>
<string name="map_qth" translatable="false">QTH: %s</string>
<string name="map_visible">Visible</string>
<string name="map_eclipsed">Eclipsed</string>
<string name="map_visibility">Visibility: %s</string>
@@ -51,7 +51,8 @@ class SatelliteRepo(
settingsRepo.selectedIds.collect { selectedIds ->
_satellites.update { localStorage.getEntriesWithIds(selectedIds) }
val (hoursAhead, minElevation, modes) = settingsRepo.passesSettings.value
calculatePasses(System.currentTimeMillis(), hoursAhead, minElevation, modes)
val timeNow = 1000 * ((System.currentTimeMillis() + 500) / 1000)
calculatePasses(timeNow, hoursAhead, minElevation, modes)
}
}
@@ -195,10 +196,10 @@ class SatelliteRepo(
}
} while (satPos.elevation < 0.0)
// refine to 3 seconds
// refine to 1 second
calendarTimeMillis += -60L * 1000L
do {
calendarTimeMillis += 3L * 1000L
calendarTimeMillis += 1L * 500L
satPos = sat.getPosition(pos, calendarTimeMillis)
elevation = satPos.elevation
if (elevation > maxElevation) {
@@ -207,7 +208,7 @@ class SatelliteRepo(
}
} while (satPos.elevation < 0.0)
val aos = satPos.time
val aos = 1000 * ((satPos.time + 500) / 1000)
val aosAz = satPos.azimuth.toDegrees().round(1)
// find when sat goes below
@@ -221,10 +222,10 @@ class SatelliteRepo(
}
} while (satPos.elevation > 0.0)
// refine to 3 seconds
// refine to 1 second
calendarTimeMillis += -30L * 1000L
do {
calendarTimeMillis += 3L * 1000L
calendarTimeMillis += 1L * 500L
satPos = sat.getPosition(pos, calendarTimeMillis)
elevation = satPos.elevation
if (elevation > maxElevation) {
@@ -233,7 +234,7 @@ class SatelliteRepo(
}
} while (satPos.elevation > 0.0)
val los = satPos.time // val tca = (aos + los) / 2
val los = 1000 * ((satPos.time + 500) / 1000) // val tca = (aos + los) / 2
val losAz = satPos.azimuth.toDegrees().round(1)
val elev = maxElevation.toDegrees().round(1)
return OrbitalPass(aos, aosAz, los, losAz, alt.toInt(), elev, sat)