Added multiple tweaks to Satellites, Passes and Map screens

This commit is contained in:
Arty Bishop committed 2026-04-10 11:50:32 +01:00
1 parent 2df0b9ba3d
commit aadc285d7f
12 files changed
+352 -328

No files matched your search

@@ -115,15 +115,12 @@ fun NavGraphBuilder.mapDestination() {
val viewModel = viewModel(MapViewModel::class.java, factory = MapViewModel.Factory)
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
val mapView = rememberMapViewWithLifecycle()
MapScreen(uiState, mapView)
MapScreen(uiState, viewModel::onAction, mapView)
}
}
@Composable
private fun MapScreen(uiState: MapState, mapView: MapView) {
val onItemClick = { item: OrbitalObject -> uiState.sendAction(MapAction.SelectItem(item)) }
val selectPrev = { uiState.sendAction(MapAction.SelectPrev) }
val selectNext = { uiState.sendAction(MapAction.SelectNext) }
private fun MapScreen(uiState: MapState, onAction: (MapAction) -> Unit, mapView: MapView) {
val rotateMod = Modifier.rotate(180f)
val timeString = uiState.mapData?.aosTime ?: "00:00:00"
val isTimeAos = uiState.mapData?.isTimeAos ?: true
@@ -136,17 +133,17 @@ private fun MapScreen(uiState: MapState, mapView: MapView) {
val isVertical = isVerticalLayout()
if (isVertical) {
TopBar {
IconCard(action = selectPrev, resId = R.drawable.ic_arrow, modifier = rotateMod)
IconCard(action = { onAction(MapAction.SelectPrev) }, resId = R.drawable.ic_arrow, modifier = rotateMod)
TimerRow(timeString = timeString, isTimeAos = isTimeAos)
IconCard(action = selectNext, resId = R.drawable.ic_arrow)
IconCard(action = { onAction(MapAction.SelectNext) }, resId = R.drawable.ic_arrow)
}
TopBar { NextPassRow(pass = uiState.orbitalPass, isUtc = uiState.isUtc) }
} else {
TopBar {
IconCard(action = selectPrev, resId = R.drawable.ic_arrow, modifier = rotateMod)
IconCard(action = { onAction(MapAction.SelectPrev) }, resId = R.drawable.ic_arrow, modifier = rotateMod)
TimerRow(timeString = timeString, isTimeAos = isTimeAos)
NextPassRow(pass = uiState.orbitalPass, modifier = Modifier.weight(1f), isUtc = uiState.isUtc)
IconCard(action = selectNext, resId = R.drawable.ic_arrow)
IconCard(action = { onAction(MapAction.SelectNext) }, resId = R.drawable.ic_arrow)
}
}
ElevatedCard(modifier = Modifier.weight(1f)) {
@@ -155,7 +152,7 @@ private fun MapScreen(uiState: MapState, mapView: MapView) {
uiState.stationPosition?.let { setStationPosition(it, view) }
uiState.track?.let { setSatelliteTrack(it, view) }
uiState.footprint?.let { setFootprint(it, view) }
uiState.positions?.let { setPositions(it, view, onItemClick) }
uiState.positions?.let { setPositions(it, view) { item -> onAction(MapAction.SelectItem(item)) } }
view.invalidate()
}
uiState.mapData?.let { mapData ->
@@ -369,7 +366,7 @@ private var footprintPoints: ArrayList<GeoPoint>? = null
private fun setFootprint(orbitalPos: OrbitalPos, mapView: MapView) {
try {
val rangeCircle = orbitalPos.getRangeCircle()
// Lazily initialise the reusable point list and polyline
// Lazily initialize the reusable point list and polyline
var pts = footprintPoints
if (pts == null || pts.size != rangeCircle.size) {
pts = ArrayList(rangeCircle.size)
@@ -23,22 +23,21 @@ import com.rtbishop.look4sat.core.domain.predict.OrbitalPass
import com.rtbishop.look4sat.core.domain.predict.OrbitalPos
data class MapState(
val mapData: MapData?,
val isLightUi: Boolean,
val isUtc: Boolean,
val stationPosition: GeoPos?,
val mapData: MapData? = null,
val isLightUi: Boolean = false,
val isUtc: Boolean = false,
val stationPosition: GeoPos? = null,
val orbitalPass: OrbitalPass,
val track: List<List<GeoPos>>?,
val footprint: OrbitalPos?,
val positions: Map<OrbitalObject, GeoPos>?,
val sendAction: (MapAction) -> Unit
val track: List<List<GeoPos>>? = null,
val footprint: OrbitalPos? = null,
val positions: Map<OrbitalObject, GeoPos>? = null
)
sealed class MapAction {
data object SelectPrev: MapAction()
data object SelectNext: MapAction()
data class SelectItem(val item: OrbitalObject): MapAction()
data class SelectDefaultItem(val catnum: Int): MapAction()
data object SelectPrev : MapAction()
data object SelectNext : MapAction()
data class SelectItem(val item: OrbitalObject) : MapAction()
data class SelectDefaultItem(val catnum: Int) : MapAction()
}
data class MapData(
@@ -56,15 +56,9 @@ class MapViewModel(private val satelliteRepo: ISatelliteRepo, private val settin
private val defaultPass = getDefaultPass()
private val _uiState = MutableStateFlow(
MapState(
mapData = null,
isLightUi = settingsRepo.otherSettings.value.stateOfLightTheme,
isUtc = settingsRepo.otherSettings.value.stateOfUtc,
stationPosition = null,
orbitalPass = defaultPass,
track = null,
footprint = null,
positions = null,
sendAction = ::handleAction
orbitalPass = defaultPass
)
)
private var allPasses = satelliteRepo.passes.value
@@ -83,7 +77,7 @@ class MapViewModel(private val satelliteRepo: ISatelliteRepo, private val settin
selectDefaultSatellite(-1)
}
private fun handleAction(action: MapAction) {
fun onAction(action: MapAction) {
when (action) {
MapAction.SelectPrev -> scrollSelection(true)
MapAction.SelectNext -> scrollSelection(false)
@@ -215,14 +209,19 @@ class MapViewModel(private val satelliteRepo: ISatelliteRepo, private val settin
?.let { satPass ->
orbitalPass = satPass
if (!satPass.isDeepSpace) {
aosTime = if (date.time < satPass.aosTime) {
val millisBeforeStart = satPass.aosTime.minus(date.time)
isTimeAos = true
millisBeforeStart.toTimerString()
} else {
val millisBeforeEnd = satPass.losTime.minus(date.time)
isTimeAos = false
millisBeforeEnd.toTimerString()
when {
date.time < satPass.aosTime -> {
// Pass hasn't started yet — count down to AOS
isTimeAos = true
aosTime = (satPass.aosTime - date.time).toTimerString()
}
date.time < satPass.losTime -> {
// Pass is in progress — count down to LOS
isTimeAos = false
aosTime = (satPass.losTime - date.time).toTimerString()
}
// else: pass has ended (losTime <= date.time) — keep default "00:00:00"
}
}
}