fix: preserve settings state when combine flow re-fires (#688)#712
fix: preserve settings state when combine flow re-fires (#688)#712torlando-tech merged 2 commits intomainfrom
Conversation
The loadSettings() combine block constructs a new SettingsState on every emission, but four fields managed by separate collectors were not being preserved — causing them to silently revert to defaults whenever any of the 15 combined flows emitted. Fixes: incomingMessageSizeLimitKb, blockUnknownSenders, sortMessagesBySentTime, tryPropagationOnFail. Closes #688 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Greptile SummaryThis PR fixes a state-clobbering bug in The fix follows the well-established pattern already used for ~30 other fields: read Key changes:
Confidence Score: 4/5Safe to merge — the bug fix is correct and complete; the only remaining issue is a minor organisational concern about where the new collector lives. The four-field state-preservation fix is correct and matches the established pattern for the rest of the combine block. The previously-flagged cold-start gap for
Important Files Changed
Sequence DiagramsequenceDiagram
participant DS as DataStore
participant SC as Separate Collector<br/>(loadLocationSharingSettings)
participant CB as combine block<br/>(loadSettings)
participant ST as _state
Note over DS,ST: Before fix — race condition clobbers separate collector
DS->>SC: tryPropagationOnFailFlow emits saved=false
SC->>ST: _state.update { tryPropagationOnFail = false }
DS->>CB: any of 15 flows emits
CB->>ST: SettingsState(..., tryPropagationOnFail = default(true)) ❌
Note over DS,ST: After fix — combine preserves current state value
DS->>SC: tryPropagationOnFailFlow emits saved=false
SC->>ST: _state.update { tryPropagationOnFail = false }
DS->>CB: any of 15 flows emits
CB->>ST: SettingsState(..., tryPropagationOnFail = _state.value.tryPropagationOnFail = false) ✅
Prompt To Fix All With AIThis is a comment left during a code review.
Path: app/src/main/java/com/lxmf/messenger/viewmodel/SettingsViewModel.kt
Line: 1576-1580
Comment:
**`tryPropagationOnFail` collector misplaced in `loadLocationSharingSettings()`**
The new collector for `tryPropagationOnFail` was added inside `loadLocationSharingSettings()`, but `tryPropagationOnFail` is a message-delivery setting, not a location-sharing one. A future developer looking for where this setting is loaded would not think to look here.
This is consistent with the pre-existing placement of `incomingMessageSizeLimitKb` and `sortMessagesBySentTime` collectors in the same function, but adding a third unrelated setting compounds the confusion. Ideally these three collectors — and the `combine`-block comments "from `loadLocationSharingSettings()`" on lines 444/446 — would move to a dedicated `loadMessageDeliverySettings()` function mirroring the pattern used for `loadPrivacySettings()` and `loadNotificationsSettings()`.
This doesn't affect runtime correctness because `loadLocationSharingSettings()` is always called unconditionally from `init {}`, but it will make the next contributor's grep for where `tryPropagationOnFail` is initialised misleading.
How can I resolve this? If you propose a fix, please make it concise.Reviews (2): Last reviewed commit: "fix: load tryPropagationOnFail from Data..." | Re-trigger Greptile |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Adds a flow collector so tryPropagationOnFail is restored from DataStore on startup, not just preserved within-session. Without this, a user who disabled retry-via-relay would see it revert to enabled on every app restart. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
blockUnknownSenders,sortMessagesBySentTime, andtryPropagationOnFailRoot Cause
SettingsViewModel.loadSettings()has acombineblock watching 15 DataStore flows. Whenever any flow emits, it constructs a newSettingsStateobject. Four fields managed by separate collectors were not preserved in this constructor, so they silently reverted to their data class defaults every time the combine re-fired.The "briefly flashes then reverts" behavior reported in #688 is the telltale: the separate collector fires first (correct value), then the combine fires and overwrites with the default.
Fix
Added
_state.value.xxxpreservation for all four affected fields, matching the pattern already used for ~30 other fields in the same block.Test plan
🤖 Generated with Claude Code