Files
iOS/Sources/Extensions/AppIntents/Action/PerformAction.swift
Bruno Pantaleão Gonçalves 1da8113507 Sync network info before performing intents (#4147)
Added calls to syncNetworkInformation() at the start of various
perform() methods for AppIntents and widget controls to ensure
up-to-date connectivity data before executing actions. Also refactored
ConnectivityWrapper to support async network info synchronization.

<!-- 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-12-29 12:50:47 +00:00

96 lines
3.4 KiB
Swift

import AppIntents
import Foundation
import PromiseKit
import Shared
@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, *)
struct PerformAction: AppIntent, CustomIntentMigratedAppIntent, PredictableIntent {
static let intentClassName = "PerformActionIntent"
static let title: LocalizedStringResource = "Perform Action"
static let description = IntentDescription("Performs an action defined in the app")
@Parameter(title: "Action")
var action: IntentActionAppEntity?
static var parameterSummary: some ParameterSummary {
Summary("Perform \(\.$action)")
}
static var predictionConfiguration: some IntentPredictionConfiguration {
IntentPrediction(parameters: \.$action) { action in
DisplayRepresentation(
title: "\(action ?? .init(id: "-1", displayString: "Uknown action"))",
subtitle: "Perform the action"
)
}
}
@Parameter(
title: LocalizedStringResource(
"app_intents.scripts.haptic_confirmation.title",
defaultValue: "Haptic confirmation"
),
default: false
)
var hapticConfirmation: Bool
func perform() async throws -> some IntentResult {
await Current.connectivity.syncNetworkInformation()
guard let intentAction = $action.wrappedValue,
let action = Current.realm().object(ofType: Action.self, forPrimaryKey: intentAction.id),
let server = Current.servers.server(for: action),
let api = Current.api(for: server) else {
Current.Log.warning("ActionID either does not exist or is not a string in the payload")
return .result()
}
if hapticConfirmation {
AppIntentHaptics.notify()
}
try await withCheckedThrowingContinuation { continuation in
api.HandleAction(actionID: action.ID, source: .AppShortcut).pipe { result in
switch result {
case .fulfilled:
continuation.resume()
case let .rejected(error):
Current.Log
.error(
"Failed to run action \(intentAction.displayString), error: \(error.localizedDescription)"
)
continuation.resume(throwing: error)
}
}
}
return .result()
}
}
@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, *)
private extension IntentDialog {
static func actionParameterDisambiguationIntro(count: Int, action: IntentActionAppEntity) -> Self {
.init(stringLiteral: L10n.AppIntents.PerformAction.actionParameterDisambiguationIntro(
count,
action.displayString
))
}
static func actionParameterConfirmation(action: IntentActionAppEntity) -> Self {
.init(stringLiteral: L10n.AppIntents.PerformAction.actionParameterConfirmation(action.displayString))
}
static var actionParameterConfiguration: Self {
.init(stringLiteral: L10n.AppIntents.PerformAction.actionParameterConfiguration)
}
static func responseSuccess(action: IntentActionAppEntity) -> Self {
.init(stringLiteral: L10n.AppIntents.PerformAction.responseSuccess)
}
static func responseFailure(error: String) -> Self {
.init(stringLiteral: L10n.AppIntents.PerformAction.responseFailure(error))
}
}