Added several tweaks to Radar and RadioControl screens

This commit is contained in:
Arty Bishop committed 2026-04-10 12:21:03 +01:00
1 parent aadc285d7f
commit 4a3a01729b
5 files changed
+116 -125

No files matched your search

@@ -37,9 +37,9 @@ import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.material3.ElevatedCard import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
@@ -89,19 +89,23 @@ fun NavGraphBuilder.radarDestination(
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 by viewModel.uiState.collectAsStateWithLifecycle() val uiState by viewModel.uiState.collectAsStateWithLifecycle()
RadarScreen(uiState, navigateUp, navigateToRadioControl) RadarScreen(uiState, viewModel::onAction, navigateUp, navigateToRadioControl)
} }
} }
@Composable @Composable
private fun RadarScreen( private fun RadarScreen(
uiState: RadarState, uiState: RadarState,
onAction: (RadarAction) -> Unit,
navigateUp: () -> Unit, navigateUp: () -> Unit,
navigateToRadioControl: (Int, Long) -> Unit navigateToRadioControl: (Int, Long) -> Unit
) { ) {
val upcomingPass = uiState.currentPass ?: getDefaultPass()
if (upcomingPass.losTime < System.currentTimeMillis()) navigateUp()
val addToCalendar: () -> Unit = { val addToCalendar: () -> Unit = {
uiState.currentPass?.let { pass -> uiState.currentPass?.let { pass ->
uiState.sendAction(RadarAction.AddToCalendar(pass.name, pass.aosTime, pass.losTime)) onAction(RadarAction.AddToCalendar(pass.name, pass.aosTime, pass.losTime))
} }
} }
val openRadioControl: () -> Unit = { val openRadioControl: () -> Unit = {
@@ -109,8 +113,6 @@ private fun RadarScreen(
navigateToRadioControl(pass.catNum, pass.aosTime) navigateToRadioControl(pass.catNum, pass.aosTime)
} }
} }
val upcomingPass = uiState.currentPass ?: getDefaultPass()
if (upcomingPass.losTime < System.currentTimeMillis()) navigateUp()
Column( Column(
modifier = Modifier modifier = Modifier
.layoutPadding() .layoutPadding()
@@ -120,28 +122,26 @@ private fun RadarScreen(
val isVertical = isVerticalLayout() val isVertical = isVerticalLayout()
if (isVertical) { if (isVertical) {
TopBar { TopBar {
IconCard(action = navigateUp, resId = R.drawable.ic_back) IconCard(action = addToCalendar, resId = R.drawable.ic_calendar)
TimerRow(timeString = uiState.currentTime, isTimeAos = uiState.isCurrentTimeAos) TimerRow(timeString = uiState.currentTime, isTimeAos = uiState.isCurrentTimeAos)
IconCard(action = openRadioControl, resId = R.drawable.ic_radios) IconCard(action = openRadioControl, resId = R.drawable.ic_radios)
IconCard(action = addToCalendar, resId = R.drawable.ic_calendar)
} }
TopBar { NextPassRow(pass = upcomingPass, isUtc = uiState.isUtc) } TopBar { NextPassRow(pass = upcomingPass, isUtc = uiState.isUtc) }
} else { } else {
TopBar { TopBar {
IconCard(action = navigateUp, resId = R.drawable.ic_back) IconCard(action = addToCalendar, resId = R.drawable.ic_calendar)
TimerRow(timeString = uiState.currentTime, isTimeAos = uiState.isCurrentTimeAos) TimerRow(timeString = uiState.currentTime, isTimeAos = uiState.isCurrentTimeAos)
NextPassRow(pass = upcomingPass, modifier = Modifier.weight(1f), isUtc = uiState.isUtc) NextPassRow(pass = upcomingPass, modifier = Modifier.weight(1f), isUtc = uiState.isUtc)
IconCard(action = openRadioControl, resId = R.drawable.ic_radios) IconCard(action = openRadioControl, resId = R.drawable.ic_radios)
IconCard(action = addToCalendar, resId = R.drawable.ic_calendar)
} }
} }
if (isVertical) { if (isVertical) {
RadarCard(uiState, Modifier.weight(1f)) RadarCard(uiState, Modifier.weight(1f))
TransmittersCard(uiState, Modifier.weight(1f)) TransmittersCard(uiState.transmitters, uiState.selectedTransmitterUuid, onAction, Modifier.weight(1f))
} else { } else {
Row(horizontalArrangement = Arrangement.spacedBy(6.dp)) { Row(horizontalArrangement = Arrangement.spacedBy(6.dp)) {
RadarCard(uiState, Modifier.weight(1f)) RadarCard(uiState, Modifier.weight(1f))
TransmittersCard(uiState, Modifier.weight(1f)) TransmittersCard(uiState.transmitters, uiState.selectedTransmitterUuid, onAction, Modifier.weight(1f))
} }
} }
} }
@@ -255,17 +255,22 @@ private fun RadarLabel(
} }
@Composable @Composable
private fun TransmittersCard(uiState: RadarState, modifier: Modifier = Modifier) { private fun TransmittersCard(
transmitters: List<SatRadio>,
selectedUuid: String?,
onAction: (RadarAction) -> Unit,
modifier: Modifier = Modifier
) {
ElevatedCard(modifier = modifier) { ElevatedCard(modifier = modifier) {
if (uiState.transmitters.isEmpty()) { if (transmitters.isEmpty()) {
EmptyTransmittersContent() EmptyTransmittersContent()
} else { } else {
TransmittersList( TransmittersList(
transmitters = uiState.transmitters, transmitters = transmitters,
selectedUuid = uiState.selectedTransmitterUuid, selectedUuid = selectedUuid,
onSelect = { uuid -> onSelect = { uuid ->
if (uiState.selectedTransmitterUuid != null) { if (selectedUuid != null) {
uiState.sendAction(RadarAction.SelectTransmitter(uuid)) onAction(RadarAction.SelectTransmitter(uuid))
} }
} }
) )
@@ -324,7 +329,6 @@ private fun TransmitterItemPreview() {
MainTheme { TransmitterItem(transmitter, isClickable = true, isSelected = true, onClick = {}) } MainTheme { TransmitterItem(transmitter, isClickable = true, isSelected = true, onClick = {}) }
} }
@Composable @Composable
private fun TransmitterItem( private fun TransmitterItem(
radio: SatRadio, radio: SatRadio,
@@ -334,42 +338,42 @@ private fun TransmitterItem(
) { ) {
val title = if (radio.isInverted) "INVERTED: ${radio.info}" else radio.info val title = if (radio.isInverted) "INVERTED: ${radio.info}" else radio.info
val fullTitle = "$title - (${radio.downlinkMode ?: "--"}/${radio.uplinkMode ?: "--"})" val fullTitle = "$title - (${radio.downlinkMode ?: "--"}/${radio.uplinkMode ?: "--"})"
Surface( Column(
color = MaterialTheme.colorScheme.background,
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.then(if (isClickable) Modifier.clickable { onClick() } else Modifier) .then(if (isClickable) Modifier.clickable { onClick() } else Modifier)
) { ) {
Surface(modifier = Modifier.padding(bottom = 2.dp)) { Column(
Column( horizontalAlignment = Alignment.CenterHorizontally,
horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.spacedBy(6.dp),
verticalArrangement = Arrangement.spacedBy(6.dp), modifier = Modifier
modifier = Modifier .fillMaxWidth()
.background(MaterialTheme.colorScheme.surface) .background(MaterialTheme.colorScheme.surface)
.padding(horizontal = 8.dp, vertical = 6.dp) .padding(horizontal = 8.dp, vertical = 6.dp)
) { ) {
Box { Box {
Text( Text(
text = fullTitle, text = fullTitle,
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
modifier = Modifier color = MaterialTheme.colorScheme.onSurface,
.fillMaxWidth() modifier = Modifier
.padding(horizontal = 6.dp) .fillMaxWidth()
.infiniteMarquee() .padding(horizontal = 6.dp)
.infiniteMarquee()
)
if (isSelected) {
Icon(
painter = painterResource(id = R.drawable.ic_radios),
contentDescription = null,
tint = MaterialTheme.colorScheme.primary,
modifier = Modifier.background(color = MaterialTheme.colorScheme.surface)
) )
if (isSelected) {
Icon(
painter = painterResource(id = R.drawable.ic_radios),
contentDescription = null,
tint = MaterialTheme.colorScheme.primary,
modifier = Modifier.background(color = MaterialTheme.colorScheme.surface)
)
}
} }
FrequencyRow(radio = radio, isDownlink = true)
FrequencyRow(radio = radio, isDownlink = false)
} }
FrequencyRow(radio = radio, isDownlink = true)
FrequencyRow(radio = radio, isDownlink = false)
} }
HorizontalDivider(thickness = 2.dp, color = MaterialTheme.colorScheme.background)
} }
} }
@@ -22,19 +22,18 @@ import com.rtbishop.look4sat.core.domain.predict.OrbitalPass
import com.rtbishop.look4sat.core.domain.predict.OrbitalPos import com.rtbishop.look4sat.core.domain.predict.OrbitalPos
data class RadarState( data class RadarState(
val currentPass: OrbitalPass?, val currentPass: OrbitalPass? = null,
val currentTime: String, val currentTime: String = "00:00:00",
val isCurrentTimeAos: Boolean, val isCurrentTimeAos: Boolean = true,
val isUtc: Boolean, val isUtc: Boolean = false,
val orientationValues: Pair<Float, Float>, val orientationValues: Pair<Float, Float> = 0f to 0f,
val orbitalPos: OrbitalPos?, val orbitalPos: OrbitalPos? = null,
val satTrack: List<OrbitalPos>, val satTrack: List<OrbitalPos> = emptyList(),
val shouldShowSweep: Boolean, val shouldShowSweep: Boolean = false,
val shouldUseCompass: Boolean, val shouldUseCompass: Boolean = false,
val transmitters: List<SatRadio>, val transmitters: List<SatRadio> = emptyList(),
val selectedTransmitterUuid: String?, val selectedTransmitterUuid: String? = null,
val selectedFrequency: Long?, val selectedFrequency: Long? = null
val sendAction: (RadarAction) -> Unit
) )
sealed class RadarAction { sealed class RadarAction {
@@ -54,25 +54,16 @@ class RadarViewModel(
private val addToCalendar: IAddToCalendar private val addToCalendar: IAddToCalendar
) : ViewModel() { ) : ViewModel() {
private val _uiState = MutableStateFlow(
RadarState(
currentPass = null,
currentTime = "00:00:00",
isCurrentTimeAos = true,
isUtc = settingsRepo.otherSettings.value.stateOfUtc,
orientationValues = sensorsRepo.orientation.value,
orbitalPos = null,
satTrack = emptyList(),
shouldShowSweep = settingsRepo.otherSettings.value.stateOfSweep,
shouldUseCompass = settingsRepo.otherSettings.value.stateOfSensors,
selectedTransmitterUuid = null,
selectedFrequency = null,
transmitters = emptyList(),
sendAction = ::handleAction,
)
)
private val stationPos = settingsRepo.stationPosition.value private val stationPos = settingsRepo.stationPosition.value
private val magDeclination = sensorsRepo.getMagDeclination(stationPos) private val magDeclination = sensorsRepo.getMagDeclination(stationPos)
private val _uiState = MutableStateFlow(
RadarState(
isUtc = settingsRepo.otherSettings.value.stateOfUtc,
orientationValues = sensorsRepo.orientation.value,
shouldShowSweep = settingsRepo.otherSettings.value.stateOfSweep,
shouldUseCompass = settingsRepo.otherSettings.value.stateOfSensors
)
)
val uiState: StateFlow<RadarState> = _uiState val uiState: StateFlow<RadarState> = _uiState
init { init {
@@ -81,7 +72,7 @@ class RadarViewModel(
viewModelScope.launch { viewModelScope.launch {
sensorsRepo.enableSensor() sensorsRepo.enableSensor()
sensorsRepo.orientation.collect { data -> sensorsRepo.orientation.collect { data ->
val orientationValues = Pair(data.first + magDeclination, data.second) val orientationValues = (data.first + magDeclination) to data.second
_uiState.update { it.copy(orientationValues = orientationValues) } _uiState.update { it.copy(orientationValues = orientationValues) }
} }
} }
@@ -92,41 +83,29 @@ class RadarViewModel(
_uiState.update { it.copy(isUtc = settings.stateOfUtc) } _uiState.update { it.copy(isUtc = settings.stateOfUtc) }
} }
} }
// Resolve which pass we're tracking // Resolve which pass we're tracking and start the tick loop
viewModelScope.launch { viewModelScope.launch {
val catNum = savedStateHandle.get<Int>("catNum") ?: 0 val catNum = savedStateHandle.get<Int>("catNum") ?: 0
val aosTime = savedStateHandle.get<Long>("aosTime") ?: 0L val aosTime = savedStateHandle.get<Long>("aosTime") ?: 0L
val passes = satelliteRepo.passes.value val passes = satelliteRepo.passes.value
val pass = passes.find { pass -> pass.catNum == catNum && pass.aosTime == aosTime } val currentPass = passes.find { it.catNum == catNum && it.aosTime == aosTime }
val currentPass = pass ?: passes.firstOrNull() ?: passes.firstOrNull()
currentPass?.let { satPass -> currentPass?.let { satPass ->
_uiState.update { it.copy(currentPass = satPass) } _uiState.update { it.copy(currentPass = satPass) }
val transmitters = satelliteRepo.getRadiosWithId(satPass.catNum) val transmitters = satelliteRepo.getRadiosWithId(satPass.catNum)
// Compute track once (it doesn't change) // Compute track once (it doesn't change for a given pass)
if (!satPass.isDeepSpace) { if (!satPass.isDeepSpace) {
val track = satelliteRepo.getTrack( val track = satelliteRepo.getTrack(
satPass.orbitalObject, stationPos, satPass.aosTime, satPass.losTime satPass.orbitalObject, stationPos, satPass.aosTime, satPass.losTime
) )
_uiState.update { it.copy(satTrack = track) } _uiState.update { it.copy(satTrack = track) }
} }
// Local tick loop — computes position only while the radar screen is alive // Tick loop — position, timer, and radio updates every second
while (isActive) { while (isActive) {
val timeNow = System.currentTimeMillis() val timeNow = System.currentTimeMillis()
val pos = satelliteRepo.getPosition(satPass.orbitalObject, stationPos, timeNow) val pos = satelliteRepo.getPosition(satPass.orbitalObject, stationPos, timeNow)
when { val (time, isAos) = computeTimer(satPass.isDeepSpace, satPass.aosTime, satPass.losTime, timeNow)
satPass.isDeepSpace -> { _uiState.update { it.copy(currentTime = time, isCurrentTimeAos = isAos, orbitalPos = pos) }
val time = 0L.toTimerString()
_uiState.update { it.copy(currentTime = time, isCurrentTimeAos = false, orbitalPos = pos) }
}
satPass.aosTime > timeNow -> {
val time = satPass.aosTime.minus(timeNow).toTimerString()
_uiState.update { it.copy(currentTime = time, isCurrentTimeAos = true, orbitalPos = pos) }
}
else -> {
val time = satPass.losTime.minus(timeNow).toTimerString()
_uiState.update { it.copy(currentTime = time, isCurrentTimeAos = false, orbitalPos = pos) }
}
}
processRadios(transmitters, satPass.orbitalObject, timeNow) processRadios(transmitters, satPass.orbitalObject, timeNow)
sendPassData(pos) sendPassData(pos)
delay(1000) delay(1000)
@@ -140,10 +119,18 @@ class RadarViewModel(
super.onCleared() super.onCleared()
} }
private fun handleAction(action: RadarAction) { fun onAction(action: RadarAction) {
when (action) { when (action) {
is RadarAction.AddToCalendar -> addToCalendar(action.name, action.aosTime, action.losTime) is RadarAction.AddToCalendar -> addToCalendar(action.name, action.aosTime, action.losTime)
is RadarAction.SelectTransmitter -> { _uiState.update { it.copy(selectedTransmitterUuid = action.uuid) } } is RadarAction.SelectTransmitter -> _uiState.update { it.copy(selectedTransmitterUuid = action.uuid) }
}
}
private fun computeTimer(isDeepSpace: Boolean, aosTime: Long, losTime: Long, timeNow: Long): Pair<String, Boolean> {
return when {
isDeepSpace -> 0L.toTimerString() to false
aosTime > timeNow -> (aosTime - timeNow).toTimerString() to true
else -> (losTime - timeNow).toTimerString() to false
} }
} }
@@ -183,8 +170,10 @@ class RadarViewModel(
private suspend fun processRadios(radios: List<SatRadio>, orbitalObject: OrbitalObject, time: Long) { private suspend fun processRadios(radios: List<SatRadio>, orbitalObject: OrbitalObject, time: Long) {
val transmitters = satelliteRepo.getRadios(orbitalObject, stationPos, radios, time) val transmitters = satelliteRepo.getRadios(orbitalObject, stationPos, radios, time)
val isFreqEnabled =
settingsRepo.rcSettings.value.frequencyState || settingsRepo.rcSettings.value.bluetoothFrequencyState
_uiState.update { state -> _uiState.update { state ->
if (!settingsRepo.rcSettings.value.frequencyState && !settingsRepo.rcSettings.value.bluetoothFrequencyState) { if (!isFreqEnabled) {
return@update state.copy( return@update state.copy(
transmitters = transmitters, transmitters = transmitters,
selectedTransmitterUuid = null, selectedTransmitterUuid = null,
@@ -197,18 +186,12 @@ class RadarViewModel(
val low = radio.downlinkLow val low = radio.downlinkLow
val high = radio.downlinkHigh val high = radio.downlinkHigh
when { when {
low != null && high != null -> low != null && high != null -> (low + high) / 2
(low + high) / 2 low != null -> low
low != null ->
low
else -> null else -> null
} }
} }
state.copy( state.copy(transmitters = transmitters, selectedTransmitterUuid = selectedUuid, selectedFrequency = freq)
transmitters = transmitters,
selectedTransmitterUuid = selectedUuid,
selectedFrequency = freq
)
} }
} }
@@ -26,14 +26,12 @@ import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.FlowRow import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth 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.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.ElevatedCard import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.FilterChip import androidx.compose.material3.FilterChip
@@ -59,11 +57,15 @@ import androidx.navigation.navArgument
import com.rtbishop.look4sat.core.domain.model.SatRadio import com.rtbishop.look4sat.core.domain.model.SatRadio
import com.rtbishop.look4sat.core.presentation.CardButton import com.rtbishop.look4sat.core.presentation.CardButton
import com.rtbishop.look4sat.core.presentation.IconCard import com.rtbishop.look4sat.core.presentation.IconCard
import com.rtbishop.look4sat.core.presentation.NextPassRow
import com.rtbishop.look4sat.core.presentation.R import com.rtbishop.look4sat.core.presentation.R
import com.rtbishop.look4sat.core.presentation.Screen import com.rtbishop.look4sat.core.presentation.Screen
import com.rtbishop.look4sat.core.presentation.TimerRow import com.rtbishop.look4sat.core.presentation.TimerRow
import com.rtbishop.look4sat.core.presentation.TopBar import com.rtbishop.look4sat.core.presentation.TopBar
import com.rtbishop.look4sat.core.presentation.getDefaultPass
import com.rtbishop.look4sat.core.presentation.isVerticalLayout
import com.rtbishop.look4sat.core.presentation.layoutPadding import com.rtbishop.look4sat.core.presentation.layoutPadding
import java.util.Locale
fun NavGraphBuilder.radioControlDestination(navigateUp: () -> Unit) { fun NavGraphBuilder.radioControlDestination(navigateUp: () -> Unit) {
val route = "${Screen.RadioControl.route}?catNum={catNum}&aosTime={aosTime}" val route = "${Screen.RadioControl.route}?catNum={catNum}&aosTime={aosTime}"
@@ -86,16 +88,21 @@ private fun RadioControlScreen(uiState: RadioControlState, navigateUp: () -> Uni
.keepScreenOn(), .keepScreenOn(),
verticalArrangement = Arrangement.spacedBy(6.dp) verticalArrangement = Arrangement.spacedBy(6.dp)
) { ) {
TopBar { val currentPass = uiState.currentPass ?: getDefaultPass()
IconCard(action = navigateUp, resId = R.drawable.ic_back) val isVertical = isVerticalLayout()
TimerRow(timeString = uiState.currentTime, isTimeAos = uiState.isCurrentTimeAos) if (isVertical) {
uiState.currentPass?.let { pass -> TopBar {
Text( IconCard(action = navigateUp, resId = R.drawable.ic_back)
text = pass.name, TimerRow(timeString = uiState.currentTime, isTimeAos = uiState.isCurrentTimeAos)
fontSize = 16.sp, IconCard(action = navigateUp, resId = R.drawable.ic_back)
fontWeight = FontWeight.Medium, }
modifier = Modifier.padding(horizontal = 8.dp) TopBar { NextPassRow(pass = currentPass) }
) } else {
TopBar {
IconCard(action = navigateUp, resId = R.drawable.ic_back)
TimerRow(timeString = uiState.currentTime, isTimeAos = uiState.isCurrentTimeAos)
NextPassRow(pass = currentPass, modifier = Modifier.weight(1f))
IconCard(action = navigateUp, resId = R.drawable.ic_back)
} }
} }
@@ -265,7 +272,7 @@ private fun CtcssSelector(uiState: RadioControlState) {
FilterChip( FilterChip(
selected = uiState.ctcssTone == tone, selected = uiState.ctcssTone == tone,
onClick = { uiState.sendAction(RadioControlAction.SetCtcssTone(tone)) }, onClick = { uiState.sendAction(RadioControlAction.SetCtcssTone(tone)) },
label = { Text(String.format("%.1f", tone)) } label = { Text(String.format(Locale.ENGLISH, "%.1f", tone)) }
) )
} }
} }
@@ -30,11 +30,9 @@ import com.rtbishop.look4sat.core.domain.repository.IContainerProvider
import com.rtbishop.look4sat.core.domain.repository.IRadioTrackingService import com.rtbishop.look4sat.core.domain.repository.IRadioTrackingService
import com.rtbishop.look4sat.core.domain.repository.ISatelliteRepo import com.rtbishop.look4sat.core.domain.repository.ISatelliteRepo
import com.rtbishop.look4sat.core.domain.repository.ISettingsRepo import com.rtbishop.look4sat.core.domain.repository.ISettingsRepo
import com.rtbishop.look4sat.core.domain.repository.RadioTrackingState
import com.rtbishop.look4sat.core.domain.utility.toTimerString import com.rtbishop.look4sat.core.domain.utility.toTimerString
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.util.Locale import java.util.Locale
@@ -108,8 +106,8 @@ class RadioControlViewModel(
} }
val isAos = pass != null && !pass.isDeepSpace && pass.aosTime > timeNow val isAos = pass != null && !pass.isDeepSpace && pass.aosTime > timeNow
_uiState.update { _uiState.update { state ->
it.copy( state.copy(
currentTime = timeStr, currentTime = timeStr,
isCurrentTimeAos = isAos, isCurrentTimeAos = isAos,
azimuth = String.format(Locale.ENGLISH, "%.1f", svc.azimuth), azimuth = String.format(Locale.ENGLISH, "%.1f", svc.azimuth),