From ad970eec775348c50535b573d7a9cf57f1305ab6 Mon Sep 17 00:00:00 2001 From: atsunatsu Date: Mon, 5 Oct 2026 20:42:08 +0800 Subject: [PATCH] =?UTF-8?q?fix(radar):=20=E8=AE=A1=E7=AE=97=E5=99=A8=20off?= =?UTF-8?q?set=20=E6=94=B9=E4=B8=BA=E8=B7=9F=E9=9A=8F=E9=A9=B1=E5=8A=A8?= =?UTF-8?q?=E8=AE=A1=E7=AE=97=E5=99=A8=E7=9A=84=E8=BD=AC=E5=8F=91=E5=99=A8?= =?UTF-8?q?=E8=AF=BB=E5=86=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit per-satellite offset 原先只在 SelectTransmitter 里载入、并按 selectedUuid 的 catnum 保存:重开雷达页读不回(看起来"没保存"),选中被 toggle 掉后 catnum 为 null 静默丢写;且计算器页 chip 仅在 dedupe 后多于一条时渲染, 单转发器卫星(JO-97/RS-44/FO-29/AO-73/QO-100/TO-108/FO-82/QB50P1/ UKUBE-1)根本没有 chip 可点,永远触发不了载入——上游 rt-bishop 在 PR #237 评审时预言过这个加载问题。 改为 offset 跟随"驱动计算器的转发器":该转发器变化(打开/换星)即载入 已存值,按其 catnum 保存,与收发机选中状态解耦;同时删掉 loadPassData 里 的 workaround 载入与 SelectTransmitter 里的 offset 读写,单一来源、与上游 PR #265 同形便于后续合并。存储格式(satelliteOffsets 单 JSON)不变, 已存的值补丁后直接生效。 验证::feature:radar:compileDebugKotlin 与 :feature:radar:test 通过; :core:domain:test up-to-date(domain 未改动)。 --- .../look4sat/feature/radar/RadarState.kt | 7 ++++++ .../look4sat/feature/radar/RadarViewModel.kt | 25 ++++++++----------- .../feature/radar/TransceiversPage.kt | 7 ++++++ 3 files changed, 25 insertions(+), 14 deletions(-) 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 7ab37096..e1c99882 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 @@ -132,5 +132,12 @@ sealed interface RadarAction { // Calculator actions data class ChangeCalculatorOffset(val offsetKHz: String) : RadarAction + + /** + * The transponder currently driving the calculator (null when the satellite has + * no linear transponder). The per-satellite offset follows it instead of the + * transceiver selection, so it loads and saves even when nothing is selected. + */ + data class CalculatorTransponderChanged(val catnum: Int?) : RadarAction data class UpdateCalculatorFrequency(val txHz: Long?, val rxHz: Long?) : RadarAction } 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 642acc00..d7debb68 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 @@ -69,6 +69,7 @@ class RadarViewModel( private val stationPos = settingsRepo.stationPosition.value private val magDeclination = sensorsRepo.getMagDeclination(stationPos) private var transponders: List = emptyList() + private var calculatorCatnum: Int? = null private var sstvDecoder: SstvDecoder? = null private var sstvRecordingJob: Job? = null private var cwDecoder: CwDecoder? = null @@ -158,12 +159,8 @@ class RadarViewModel( transponders = allRadios.filter { it.downlinkLow != null } if (allRadios.isNotEmpty()) { val firstUuid = allRadios.first().uuid - val offsetKHz = allRadios.first().catnum?.let { settingsRepo.getSatelliteOffset(it) } ?: "" _uiState.update { - it.copy( - transceivers = it.transceivers.copy(selectedUuid = firstUuid), - calculatorOffsetKHz = offsetKHz - ) + it.copy(transceivers = it.transceivers.copy(selectedUuid = firstUuid)) } transponders.find { it.uuid == firstUuid }?.let { trackingService.setTransponder(it) } } @@ -241,15 +238,8 @@ class RadarViewModel( // Compute toggle state before the update so we don't read post-update value val isTogglingOff = _uiState.value.transceivers.selectedUuid == action.uuid val newUuid = if (isTogglingOff) null else action.uuid - val offsetKHz = if (!isTogglingOff) { - transponders.find { it.uuid == action.uuid } - ?.catnum?.let { settingsRepo.getSatelliteOffset(it) } ?: "" - } else "" _uiState.update { - it.copy( - transceivers = it.transceivers.copy(selectedUuid = newUuid), - calculatorOffsetKHz = offsetKHz - ) + it.copy(transceivers = it.transceivers.copy(selectedUuid = newUuid)) } // Only update the tracking service when selecting a different transponder to // avoid resetting a user-adjusted TX base on re-expand @@ -319,7 +309,9 @@ class RadarViewModel( _uiState.update { it.copy(cw = it.cw.copy(isExpanded = action.expanded)) } } is RadarAction.ChangeCalculatorOffset -> { - val catnum = _uiState.value.transceivers.selectedUuid?.let { uuid -> + // Keyed by the transponder driving the calculator, so the offset saves + // even when no transceiver is selected (or selection was toggled off) + val catnum = calculatorCatnum ?: _uiState.value.transceivers.selectedUuid?.let { uuid -> transponders.find { it.uuid == uuid }?.catnum } if (catnum != null) { @@ -327,6 +319,11 @@ class RadarViewModel( } _uiState.update { it.copy(calculatorOffsetKHz = action.offsetKHz) } } + is RadarAction.CalculatorTransponderChanged -> { + calculatorCatnum = action.catnum + val offsetKHz = action.catnum?.let { settingsRepo.getSatelliteOffset(it) } ?: "" + _uiState.update { it.copy(calculatorOffsetKHz = offsetKHz) } + } is RadarAction.UpdateCalculatorFrequency -> { _uiState.update { if (it.calculatorTxHz == action.txHz && it.calculatorRxHz == action.rxHz) it diff --git a/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/TransceiversPage.kt b/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/TransceiversPage.kt index c5f9cc85..a6f8b9cf 100644 --- a/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/TransceiversPage.kt +++ b/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/TransceiversPage.kt @@ -176,6 +176,13 @@ fun CalculatorPage( ?: calculatorTransceivers.firstOrNull() } + // Keep the per-satellite offset in sync with the transponder driving the + // calculator: load the saved value on open/satellite change, and remember + // its catnum so editing saves even when no transceiver is selected + LaunchedEffect(selectedTransceiver?.uuid) { + onAction(RadarAction.CalculatorTransponderChanged(selectedTransceiver?.catnum)) + } + if (selectedTransceiver == null) { EmptyTransceiversContent(modifier) return