mirror of
https://github.com/home-assistant/iOS.git
synced 2026-06-16 04:16:39 -05:00
<!-- 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 --> This PR adds the capability of receive a response from the perform action App Intent + some small improvements on actions list rendering ## Screenshots <!-- If this is a user-facing change not in the frontend, please include screenshots in light and dark mode. --> <img width="1792" height="1550" alt="CleanShot 2026-06-09 at 21 06 09@2x" src="https://github.com/user-attachments/assets/3036b9cd-0992-46d3-840f-275725a543ac" /> ## 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: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
49 lines
1.8 KiB
Swift
49 lines
1.8 KiB
Swift
import Foundation
|
|
import HAKit
|
|
|
|
/// Response of a websocket `call_service` performed with `return_response: true`.
|
|
///
|
|
/// Home Assistant returns `{ "context": { ... }, "response": <any> }` for actions that support a
|
|
/// response (`SupportsResponse.OPTIONAL` / `.ONLY`). The shape of `response` depends on the action,
|
|
/// so the raw value is kept untyped and can be JSON-serialized by callers.
|
|
public struct CallServiceResponse: HADataDecodable {
|
|
/// The raw `response` value returned by the action, if any.
|
|
public let response: Any?
|
|
|
|
public init(data: HAData) throws {
|
|
if case let .dictionary(dictionary) = data {
|
|
self.response = dictionary["response"]
|
|
} else {
|
|
self.response = nil
|
|
}
|
|
}
|
|
|
|
/// Whether the action returned a non-empty response value.
|
|
public var hasResponse: Bool {
|
|
switch response {
|
|
case nil, is NSNull:
|
|
return false
|
|
case let dictionary as [String: Any]:
|
|
return dictionary.isEmpty == false
|
|
case let array as [Any]:
|
|
return array.isEmpty == false
|
|
default:
|
|
return true
|
|
}
|
|
}
|
|
|
|
/// The `response` value serialized as a JSON string, or nil when there is nothing to serialize.
|
|
public func jsonString() -> String? {
|
|
guard hasResponse, let response else { return nil }
|
|
|
|
// Wrap primitives so JSONSerialization (which requires a top-level container) can encode them.
|
|
let serializable: Any = (response is [String: Any] || response is [Any]) ? response : ["response": response]
|
|
guard JSONSerialization.isValidJSONObject(serializable),
|
|
let data = try? JSONSerialization.data(withJSONObject: serializable, options: [.sortedKeys]),
|
|
let string = String(data: data, encoding: .utf8) else {
|
|
return nil
|
|
}
|
|
return string
|
|
}
|
|
}
|