Files
iOS/Sources/Extensions/Widgets/Custom/AppIntents/CustomWidgetToggleAppIntent.swift
Bruno Pantaleão Gonçalves 72f0688b95 Add more logs for custom widget interaction (#4692)
<!-- 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 -->
Some users experience their "WidgetCustom" interaction to not happen,
meanwhile the entity states in the widget update normally. This PR adds
more logs to help evaluate what's happening.
## 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. -->
2026-06-03 09:34:59 +00:00

90 lines
3.9 KiB
Swift

import AppIntents
import Foundation
import HAKit
import Shared
import SwiftUI
import WidgetKit
@available(iOS 16.4, *)
struct CustomWidgetToggleAppIntent: AppIntent {
static var title: LocalizedStringResource = "Toggle"
static var isDiscoverable: Bool = false
// No translation needed below, this is not a discoverable intent
@Parameter(title: "Server")
var serverId: String?
@Parameter(title: "Domain")
var domain: String?
@Parameter(title: "Entity ID")
var entityId: String?
@Parameter(title: "Is widget showing states?")
var widgetShowingStates: Bool?
func perform() async throws -> some IntentResult {
Current.Log.verbose(
"ToggleAppIntent: perform started, serverId: \(String(describing: serverId)), domain: \(String(describing: domain)), entityId: \(String(describing: entityId)), widgetShowingStates: \(String(describing: widgetShowingStates))"
)
guard let serverId,
let domainString = domain,
let entityId,
let widgetShowingStates else {
Current.Log
.error(
"ToggleAppIntent: missing parameters, serverId: \(String(describing: serverId)), domain: \(String(describing: domain)), entityId: \(String(describing: entityId)), widgetShowingStates: \(String(describing: widgetShowingStates))"
)
return .result()
}
guard let domain = Domain(rawValue: domainString) else {
Current.Log.error("ToggleAppIntent: unknown domain '\(domainString)', entityId: \(entityId)")
return .result()
}
guard let connection = CustomWidgetIntentHelper.resolveConnection(
serverId: serverId,
intentName: "ToggleAppIntent"
) else {
return .result()
}
guard let request = HATypedRequest<HAResponseVoid>.executeMainAction(domain: domain, entityId: entityId) else {
Current.Log
.error(
"ToggleAppIntent: no main action for domain \(domain.rawValue), entityId: \(entityId), serverId: \(serverId)"
)
return .result()
}
Current.Log.verbose(
"ToggleAppIntent: sending main action, serverId: \(serverId), domain: \(domain.rawValue), entityId: \(entityId)"
)
AppIntentHaptics.notify()
await withCheckedContinuation { continuation in
connection.send(request).promise.pipe { result in
switch result {
case .fulfilled:
Current.Log.verbose(
"ToggleAppIntent: main action succeeded, serverId: \(serverId), domain: \(domain.rawValue), entityId: \(entityId)"
)
continuation.resume()
case let .rejected(error):
Current.Log
.error(
"Failed to execute ToggleAppIntent, serverId: \(serverId), domain: \(domain), entityId: \(entityId), error: \(error)"
)
Current.notificationDispatcher.send(.init(
id: .intentToggleFailed,
title: L10n.Widgets.Custom.IntentToggleFailed.title,
body: L10n.Widgets.Custom.IntentToggleFailed.body
))
continuation.resume()
}
}
}
_ = try await ResetAllCustomWidgetConfirmationAppIntent().perform()
if widgetShowingStates {
/* Since when you toggle an entity not always it reflects the new state right away
and at the same time push notifications to update widgets are currently not working reliably
in iOS, this delay is out best effort for the user to see the correct state after finishing the interaction */
try await Task.sleep(nanoseconds: 1_000_000_000)
}
return .result()
}
}