iOS/Sources/Shared/API/Webhook/Sensors/FocusSensor.swift
Bruno Pantaleão Gonçalves 6b3419ea23
Display dynamic island indication when db is updating (#4230)
<!-- Thank you for submitting a Pull Request and helping to improve Home
Assistant. Please complete the following sections to help the processing
and review of your changes. Please do not delete anything from this
template. -->

## Summary
<!-- Provide a brief summary of the changes you have made and most
importantly what they aim to achieve -->

## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->
<img width="1796" height="804" alt="CleanShot 2026-01-16 at 13 11 31@2x"
src="https://github.com/user-attachments/assets/4c0be252-f3b6-4ff5-b27e-8b11f19eaee4"
/>

## Link to pull request in Documentation repository
<!-- Pull requests that add, change or remove functionality must have a
corresponding pull request in the Companion App Documentation repository
(https://github.com/home-assistant/companion.home-assistant). Please add
the number of this pull request after the "#" -->
Documentation: home-assistant/companion.home-assistant#

## Any other notes
<!-- If there is any other information of note, like if this Pull
Request is part of a bigger change, please include it here. -->
2026-01-16 12:50:22 +00:00

89 lines
2.4 KiB
Swift

import Foundation
import HAKit
import PromiseKit
final class FocusSensorUpdateSignaler: BaseSensorUpdateSignaler, SensorProviderUpdateSignaler {
var cancellable: HACancellable?
private let signal: () -> Void
init(signal: @escaping () -> Void) {
self.signal = signal
super.init(relatedSensorsIds: [
.focus,
])
}
deinit {
cancellable?.cancel()
}
override func observe() {
super.observe()
guard !isObserving else { return }
cancellable = Current.focusStatus.trigger.observe { [weak self] _ in
#if os(watchOS)
self?.signal()
#else
// this means that we will double-update the focus sensor if the app is running
// this feels less likely to happen, but allows us to keep the in-app visual state right
if Current.isForegroundApp() {
self?.signal()
}
#endif
}
isObserving = true
#if DEBUG
notifyObservation?()
#endif
}
override func stopObserving() {
super.stopObserving()
guard isObserving else { return }
cancellable?.cancel()
isObserving = false
}
}
final class FocusSensor: SensorProvider {
public enum FocusError: Error, Equatable {
case unauthorized
case unavailable
}
let request: SensorProviderRequest
init(request: SensorProviderRequest) {
self.request = request
}
func sensors() -> Promise<[WebhookSensor]> {
guard Current.focusStatus.isAvailable() else {
return .init(error: FocusError.unavailable)
}
guard Current.focusStatus.authorizationStatus() == .authorized else {
return .init(error: FocusError.unauthorized)
}
let focusState = Current.focusStatus.status()
var sensors = [WebhookSensor]()
if let isFocused = focusState.isFocused {
sensors.append(with(WebhookSensor(
name: "Focus",
uniqueID: WebhookSensorId.focus.rawValue,
icon: "mdi:moon-waning-crescent",
state: isFocused
)) {
$0.Type = "binary_sensor"
})
}
// Set up our observer
let _: FocusSensorUpdateSignaler = request.dependencies.updateSignaler(for: self)
return .value(sensors)
}
}