Repository navigation
Fix Focus sensors reporting a stale state - #6129
Merged
Merged
Conversation
The push provider extension could not ask iOS for the Focus status and rebuilt the sensors from an old push, reporting off while a Focus was on. The Focus name could also be cleared while the paired Focus was still on. Each source now keeps its newest reading in the app group, and every process reports from those. The app asks iOS for the status and for the Focus filter's current values on every read.
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved observation-ordering, timeout task accumulation, foreground refresh, and name-deletion issues can undermine reliable Focus reporting.
4 open issues
What changed in this PR
This PR addresses stale Focus reporting across the app and its extensions, including the Focus name behavior reported in #5467.
Changes:
- Stores filter runs, status pushes, and app readings separately, resolving reports from the newest observations.
- Adds timeout-bounded reads of the Focus filter’s current values and updates sensor subscriptions.
- Reworks regression tests and corrects three Focus help texts.
| File | Description |
|---|---|
| Tests/Shared/Sensors/FocusSensor.test.swift | Tests stored status ordering and sensor signaling. |
| Tests/Shared/Sensors/FocusNameSensor.test.swift | Tests name resolution, timeouts, and legacy stored data. |
| Tests/App/Settings/FocusNameFocusFilterAppIntent.test.swift | Tests current-values reading and error handling. |
| Sources/Shared/Resources/Swiftgen/Strings.swift | Updates generated help-text comments. |
| Sources/Shared/Intents/FocusStatusIntentHandler.swift | Records status received through the intent. |
| Sources/Shared/Environment/FocusStatusWrapper.swift | Separates status pushes from app readings. |
| Sources/Shared/Environment/FocusStatusObservation.swift | Adds a timestamped status model. |
| Sources/Shared/Environment/FocusReport.swift | Resolves both sensors from stored observations. |
| Sources/Shared/Environment/FocusFilterWrapper.swift | Adds current-values reads, timeouts, and observation selection. |
| Sources/Shared/Environment/FocusFilterState.swift | Extracts the simplified filter-state model. |
| Sources/Shared/Environment/FocusFilterLiveConfirmation.swift | Removes the obsolete confirmation model. |
| Sources/Shared/API/Webhook/Sensors/FocusSensor.swift | Uses asynchronous reports and updated subscriptions. |
| Sources/Shared/API/Webhook/Sensors/FocusNameSensor.swift | Uses asynchronous reports and removes status observation. |
| Sources/App/Settings/Sensors/Permissions/SensorPermission.swift | Clarifies the permission comment; mapping is unchanged. |
| Sources/App/Settings/Focus/FocusSettingsViewModel.swift | Clarifies the permission comment only. |
| Sources/App/Settings/Focus/FocusNameFocusFilterAppIntent.swift | Bridges current filter values into Shared. |
| Sources/App/Resources/en.lproj/Localizable.strings | Corrects three English Focus help texts. |
| Sources/App/AppDelegate.swift | Registers the current-values reader during launch. |
| HomeAssistant.xcodeproj/project.pbxproj | Adds target-membership entries for the extracted models. |
Review effort: Balanced
Comment on lines
+54
to
+56
| switch await Self.withTimeout(Self.currentValuesTimeout, reader) { | ||
| case let .some(.success(name)): | ||
| readings.value = FocusFilterState(name: name, date: Current.date()) |
Comment on lines
+24
to
+28
| // Only the filter's runs change the name. A status push changes the "Is focused" | ||
| // attribute too, but the Intents extension that received it reports both Focus sensors | ||
| // itself, and signalling here would add a full update of every sensor to that extension's | ||
| // short run. | ||
| focusFilterCancellable = Current.focusFilter.runs.observe { [weak self] _ in |
Comment on lines
+129
to
+131
| Task { | ||
| do { | ||
| let value = try await operation() |
Date each reading of the filter's current values by when it was asked, share one request between concurrent reads, and stop asking again while a timed-out request is still unanswered. Deleting a Focus name keeps the date of the answer it clears. The Focus name sensor refreshes again on a status push while the app is in the foreground.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #6129 +/- ##
=======================================
Coverage 57.48% 57.49%
=======================================
Files 1278 1279 +1
Lines 84565 84556 -9
=======================================
- Hits 48614 48612 -2
+ Misses 35951 35944 -7
☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


AI Policy
Select exactly one option that describes AI usage in this contribution:
Summary
The Focus sensor could report off while a Focus was on, and the Focus name could be cleared while its Focus was still on.
Screenshots
No UI changes, only the wording of three Focus help texts.
Link to pull request in Documentation repository
Documentation: home-assistant/companion.home-assistant#
Any other notes
Related to #5467.