From 905995ab442425366c530cd994a8f4dede500a63 Mon Sep 17 00:00:00 2001
From: Lukas <77849373+qwqtoday@users.noreply.github.com>
Date: Wed, 5 Aug 2026 00:08:44 +0800
Subject: [PATCH] Added configurable Radar offset to the sensors output (#230)
---
.../core/data/repository/SettingsRepo.kt | 8 +++-
.../look4sat/core/domain/model/Settings.kt | 4 +-
.../src/main/res/values/strings.xml | 2 +
.../look4sat/feature/radar/RadarScreen.kt | 1 +
.../look4sat/feature/radar/RadarState.kt | 1 +
.../look4sat/feature/radar/RadarView.kt | 5 ++-
.../look4sat/feature/radar/RadarViewModel.kt | 10 ++++-
.../feature/settings/SettingsScreen.kt | 37 ++++++++++++++++++-
.../feature/settings/SettingsState.kt | 2 +
.../feature/settings/SettingsViewModel.kt | 2 +
gradle.properties | 3 ++
11 files changed, 68 insertions(+), 7 deletions(-)
diff --git a/core/data/src/main/java/com/rtbishop/look4sat/core/data/repository/SettingsRepo.kt b/core/data/src/main/java/com/rtbishop/look4sat/core/data/repository/SettingsRepo.kt
index fb8f863c..283142ac 100644
--- a/core/data/src/main/java/com/rtbishop/look4sat/core/data/repository/SettingsRepo.kt
+++ b/core/data/src/main/java/com/rtbishop/look4sat/core/data/repository/SettingsRepo.kt
@@ -86,6 +86,8 @@ class SettingsRepo(
private val keySstvMode = "sstvMode"
private val keyLowElevation = "lowElevation"
private val keyHighElevation = "highElevation"
+ private val keyRadarCompassOffset = "radarCompassOffset"
+ private val keyRadarCompassOffsetElev = "radarCompassOffsetElev"
private val keyUseCustomTle = "useCustomTle"
private val keyUseCustomTransceivers = "useCustomTransceivers"
private val keyTleUrl = "tleUrl"
@@ -332,6 +334,8 @@ class SettingsRepo(
putString(keySstvMode, new.sstvMode)
putLong(keyLowElevation, new.lowElevation.toRawBits())
putLong(keyHighElevation, new.highElevation.toRawBits())
+ putFloat(keyRadarCompassOffset, new.radarCompassOffset)
+ putFloat(keyRadarCompassOffsetElev, new.radarCompassOffsetElev)
}
new
}
@@ -348,7 +352,9 @@ class SettingsRepo(
shouldSeeWhatsNew = preferences.getBoolean(keyShouldSeeWhatsNew, true),
sstvMode = preferences.getString(keySstvMode, null) ?: "Auto",
lowElevation = Double.fromBits(preferences.getLong(keyLowElevation, 15.0.toRawBits())),
- highElevation = Double.fromBits(preferences.getLong(keyHighElevation, 45.0.toRawBits()))
+ highElevation = Double.fromBits(preferences.getLong(keyHighElevation, 45.0.toRawBits())),
+ radarCompassOffset = preferences.getFloat(keyRadarCompassOffset, 0f),
+ radarCompassOffsetElev = preferences.getFloat(keyRadarCompassOffsetElev, 0f)
)
//endregion
diff --git a/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/model/Settings.kt b/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/model/Settings.kt
index 1647073b..281e0c86 100644
--- a/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/model/Settings.kt
+++ b/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/model/Settings.kt
@@ -61,7 +61,9 @@ data class OtherSettings(
val shouldSeeWhatsNew: Boolean,
val sstvMode: String = "Auto",
val lowElevation: Double = 15.0,
- val highElevation: Double = 45.0
+ val highElevation: Double = 45.0,
+ val radarCompassOffset: Float = 0f,
+ val radarCompassOffsetElev: Float = 0f
)
data class DataSourcesSettings(
diff --git a/core/presentation/src/main/res/values/strings.xml b/core/presentation/src/main/res/values/strings.xml
index 492aaa2f..d571a14b 100644
--- a/core/presentation/src/main/res/values/strings.xml
+++ b/core/presentation/src/main/res/values/strings.xml
@@ -189,6 +189,8 @@
Radar sweep animation
Use sensors for radar
Red night filter
+ Radar compass offset
+ Radar compass offset (elev)
Elevation highlight
Low < %1$d°
diff --git a/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/RadarScreen.kt b/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/RadarScreen.kt
index c3d753a2..aa164b32 100644
--- a/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/RadarScreen.kt
+++ b/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/RadarScreen.kt
@@ -225,6 +225,7 @@ private fun RadarCard(uiState: RadarState, modifier: Modifier = Modifier) {
azimElev = uiState.orientationValues,
shouldShowSweep = uiState.shouldShowSweep,
shouldUseCompass = uiState.shouldUseCompass,
+ shouldFlipRadar = uiState.shouldFlipRadar,
modifier = Modifier.align(Alignment.Center),
sunPosition = uiState.sunPosition,
moonPosition = uiState.moonPosition,
diff --git a/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/RadarState.kt b/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/RadarState.kt
index bb5a0329..78aaadd9 100644
--- a/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/RadarState.kt
+++ b/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/RadarState.kt
@@ -58,6 +58,7 @@ data class RadarState(
val satTrack: List = emptyList(),
val shouldShowSweep: Boolean = false,
val shouldUseCompass: Boolean = false,
+ val shouldFlipRadar: Boolean = false,
val sunPosition: CelestialComputer.SunPosition? = null,
val moonPosition: CelestialComputer.MoonPosition? = null,
val transceivers: TransceiverSubState = TransceiverSubState(),
diff --git a/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/RadarView.kt b/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/RadarView.kt
index bedf5a7d..07f4b0c1 100644
--- a/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/RadarView.kt
+++ b/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/RadarView.kt
@@ -74,6 +74,7 @@ fun RadarViewCompose(
azimElev: Pair,
shouldShowSweep: Boolean,
shouldUseCompass: Boolean,
+ shouldFlipRadar: Boolean,
modifier: Modifier = Modifier,
sunPosition: CelestialComputer.SunPosition? = null,
moonPosition: CelestialComputer.MoonPosition? = null,
@@ -125,7 +126,9 @@ fun RadarViewCompose(
cachedSweepBrush = makeSweepBrush(center, primaryColor)
cachedSweepColor = primaryColor
}
- rotate(if (shouldUseCompass) -azimElev.first else 0f) {
+ val baseRotation = if (shouldUseCompass) -azimElev.first else 0f
+ val rotation = if (shouldFlipRadar) baseRotation + 180f else baseRotation
+ rotate(rotation) {
if (shouldShowSweep) cachedSweepBrush?.let { drawSweep(center, sweepDegrees, radius, it) }
drawRadar(radius, radarColor)
drawElevationLabels(radius, primaryColor, measurer)
diff --git a/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/RadarViewModel.kt b/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/RadarViewModel.kt
index c013022f..83d214fb 100644
--- a/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/RadarViewModel.kt
+++ b/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/RadarViewModel.kt
@@ -67,6 +67,8 @@ class RadarViewModel(
private val stationPos = settingsRepo.stationPosition.value
private val magDeclination = sensorsRepo.getMagDeclination(stationPos)
+ private var compassOffset = settingsRepo.otherSettings.value.radarCompassOffset
+ private var compassOffsetElev = settingsRepo.otherSettings.value.radarCompassOffsetElev
private var transponders: List = emptyList()
private var sstvDecoder: SstvDecoder? = null
private var sstvRecordingJob: Job? = null
@@ -99,7 +101,8 @@ class RadarViewModel(
viewModelScope.launch {
sensorsRepo.enableSensor()
sensorsRepo.sensorData.collect { data ->
- val orientationValues = (data.first + magDeclination) to data.second
+ val orientationValues =
+ (data.first + magDeclination + compassOffset) to (data.second + compassOffsetElev)
_uiState.update { it.copy(orientationValues = orientationValues) }
}
}
@@ -108,11 +111,14 @@ class RadarViewModel(
private fun collectSettingsChanges() {
viewModelScope.launch {
settingsRepo.otherSettings.collectLatest { settings ->
+ compassOffset = settings.radarCompassOffset
+ compassOffsetElev = settings.radarCompassOffsetElev
_uiState.update {
it.copy(
isUtc = settings.stateOfUtc,
shouldShowSweep = settings.stateOfSweep,
- shouldUseCompass = settings.stateOfSensors
+ shouldUseCompass = settings.stateOfSensors,
+ shouldFlipRadar = settings.radarCompassOffsetElev < 0f
)
}
}
diff --git a/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsScreen.kt b/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsScreen.kt
index 9170aa04..a32393ac 100644
--- a/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsScreen.kt
+++ b/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsScreen.kt
@@ -38,6 +38,7 @@ import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.Icon
import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Slider
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@@ -487,7 +488,7 @@ private fun OtherCard(settings: OtherSettings, onAction: (SettingsAction) -> Uni
ElevatedCard(
modifier = Modifier
.fillMaxWidth()
- .height(268.dp)
+ .height(404.dp)
) {
Column(modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp)) {
Text(
@@ -506,6 +507,16 @@ private fun OtherCard(settings: OtherSettings, onAction: (SettingsAction) -> Uni
SwitchRow(R.string.prefs_other_switch_sensors, settings.stateOfSensors) {
onAction(SettingsAction.ToggleSensor(it))
}
+ CompassOffsetRow(
+ labelResId = R.string.prefs_other_compass_offset,
+ value = settings.radarCompassOffset,
+ range = -180f..180f
+ ) { onAction(SettingsAction.SetRadarCompassOffset(it)) }
+ CompassOffsetRow(
+ labelResId = R.string.prefs_other_compass_offset_elev,
+ value = settings.radarCompassOffsetElev,
+ range = -90f..90f
+ ) { onAction(SettingsAction.SetRadarCompassOffsetElev(it)) }
SwitchRow(R.string.prefs_other_switch_night_mode, settings.stateOfNightMode) {
onAction(SettingsAction.ToggleNightMode(it))
}
@@ -513,6 +524,28 @@ private fun OtherCard(settings: OtherSettings, onAction: (SettingsAction) -> Uni
}
}
+@Composable
+private fun CompassOffsetRow(
+ labelResId: Int,
+ value: Float,
+ range: ClosedFloatingPointRange,
+ onValueChange: (Float) -> Unit
+) {
+ Row(
+ horizontalArrangement = Arrangement.SpaceBetween,
+ verticalAlignment = Alignment.CenterVertically,
+ modifier = Modifier.fillMaxWidth()
+ ) {
+ Text(text = stringResource(id = labelResId))
+ Text(text = "${value.toInt()}°")
+ }
+ Slider(
+ value = value,
+ onValueChange = onValueChange,
+ valueRange = range
+ )
+}
+
@Composable
private fun SwitchRow(labelResId: Int, checked: Boolean, onCheckedChange: (Boolean) -> Unit) {
Row(
@@ -559,7 +592,7 @@ private fun CardCredits(modifier: Modifier = Modifier) {
ElevatedCard(
modifier = modifier
.fillMaxWidth()
- .height(268.dp)
+ .height(404.dp)
) {
Column(
verticalArrangement = Arrangement.SpaceBetween,
diff --git a/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsState.kt b/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsState.kt
index d5c66f5e..c0e0917b 100644
--- a/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsState.kt
+++ b/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsState.kt
@@ -65,6 +65,8 @@ sealed interface SettingsAction {
data class ToggleSensor(val value: Boolean) : SettingsAction
data class ToggleLightTheme(val value: Boolean) : SettingsAction
data class ToggleNightMode(val value: Boolean) : SettingsAction
+ data class SetRadarCompassOffset(val value: Float) : SettingsAction
+ data class SetRadarCompassOffsetElev(val value: Float) : SettingsAction
// Remote control
data class UpdateRC(val settings: RCSettings) : SettingsAction
diff --git a/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsViewModel.kt b/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsViewModel.kt
index 33a5a5b1..adcac2ad 100644
--- a/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsViewModel.kt
+++ b/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsViewModel.kt
@@ -123,6 +123,8 @@ class SettingsViewModel(
is SettingsAction.ToggleSensor -> settingsRepo.updateOtherSettings { it.copy(stateOfSensors = action.value) }
is SettingsAction.ToggleLightTheme -> settingsRepo.updateOtherSettings { it.copy(stateOfLightTheme = action.value) }
is SettingsAction.ToggleNightMode -> settingsRepo.updateOtherSettings { it.copy(stateOfNightMode = action.value) }
+ is SettingsAction.SetRadarCompassOffset -> settingsRepo.updateOtherSettings { it.copy(radarCompassOffset = action.value) }
+ is SettingsAction.SetRadarCompassOffsetElev -> settingsRepo.updateOtherSettings { it.copy(radarCompassOffsetElev = action.value) }
// Remote control & data sources
is SettingsAction.UpdateRC -> settingsRepo.updateRCSettings(action.settings)
is SettingsAction.UpdateRadioControl -> settingsRepo.updateRadioControlSettings(action.settings)
diff --git a/gradle.properties b/gradle.properties
index 6308f0e2..8ecdada7 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -3,3 +3,6 @@ org.gradle.caching=true
org.gradle.jvmargs=-Xmx6g -XX:MaxMetaspaceSize=1g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
org.gradle.parallel=true
org.gradle.workers.max=4
+
+# Enabled parallel sync for Gradle 9.4+
+org.gradle.tooling.parallel=true