iOS/Sources/Shared/API/PeriodicUpdateManager.swift
Bruno Pantaleão Gonçalves 64839bbac5
Move background task keys to enum and add tests (#3673)
<!-- 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. -->

## 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. -->

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-06-25 15:03:30 +02:00

67 lines
2.3 KiB
Swift

#if os(iOS)
import Foundation
import PromiseKit
import UIKit
public class PeriodicUpdateManager {
public let applicationStateGetter: () -> UIApplication.State
public init(applicationStateGetter: @escaping () -> UIApplication.State) {
self.applicationStateGetter = applicationStateGetter
}
private var periodicUpdateTimer: Timer? {
willSet {
if periodicUpdateTimer != newValue {
periodicUpdateTimer?.invalidate()
}
}
}
public static var supportsBackgroundPeriodicUpdates: Bool {
Current.isCatalyst || Current.isAppExtension
}
public func invalidatePeriodicUpdateTimer(forBackground: Bool = false) {
if !Self.supportsBackgroundPeriodicUpdates || !forBackground {
periodicUpdateTimer = nil
}
}
private func schedulePeriodicUpdateTimer() {
guard periodicUpdateTimer == nil || periodicUpdateTimer?.isValid == false else {
return
}
guard Self.supportsBackgroundPeriodicUpdates || applicationStateGetter() != .background else {
// it's fine to schedule, but we don't wanna fire two when we come back to foreground later
Current.Log.info("not scheduling periodic update; backgrounded")
return
}
guard let interval = Current.settingsStore.periodicUpdateInterval else {
Current.Log.info("not scheduling periodic update; disabled")
return
}
periodicUpdateTimer = Timer.scheduledTimer(withTimeInterval: interval, repeats: false) { [weak self] _ in
self?.connectAPI(reason: .periodic)
}
}
public func connectAPI(reason: HomeAssistantAPI.ConnectReason) {
Current.backgroundTask(withName: BackgroundTask.connectApi.rawValue) { _ in
when(resolved: Current.apis.map { api in
api.Connect(reason: reason)
}).asVoid()
}.done {
Current.Log.info("Connect finished for reason \(reason)")
}.catch { error in
// if the error is e.g. token is invalid, we'll force onboarding through status-code-watching mechanisms
Current.Log.error("Couldn't connect for reason \(reason): \(error)")
}.finally {
self.schedulePeriodicUpdateTimer()
}
}
}
#endif