iOS/Sources/Extensions/Widgets/OpenEntity/ControlOpenCoverEntity/ControlOpenCoverEntityValueProvider.swift
Copilot 2aa5c551b8
Add domain-specific controls for iOS Control Center (#4093)
## Implementation Plan for Domain-Specific Open Entity Controls

**Phase 1 - Initial 3 controls (COMPLETED):**
- [x] Add WidgetsKind cases for camera, lock, cover
- [x] Create ControlOpenCamera, ControlOpenLock, ControlOpenCoverEntity
- [x] Add localization strings and tests

**Phase 2 - Complete all domains (COMPLETED):**
- [x] Add WidgetsKind cases for remaining domains
- [x] Create all 11 remaining controls
- [x] Add localization strings for all new controls
- [x] Register all controls in WidgetsBundle18
- [x] Update tests for all new cases
- [x] Add files to Xcode project
- [x] Fix localization keys for snake_case domains

**Phase 3 - Code optimization (COMPLETED):**
- [x] Refactor all controls to use shared OpenEntityAppIntent
- [x] Remove 14 duplicate AppIntent files
- [x] Update Xcode project references
- [x] Clean up backup files

**Phase 4 - Refinement (COMPLETED):**
- [x] Combine sensor and binary_sensor into single control
- [x] Remove script, scene, zone, and person controls
- [x] Update all references and localization

**Phase 5 - Convert button to action control (COMPLETED):**
- [x] Convert ControlOpenButton to ControlButton (stateless press
action)
- [x] Create ButtonIntent that executes button.press service
- [x] Combine button and input_button domains
- [x] Remove ControlOpenInputButton
- [x] Update all references and localization
- [x] Fix code review issues

**Phase 6 - Add beta label (COMPLETED):**
- [x] Add beta label to ControlOpenCamera using
promptsForUserConfiguration()

**Phase 7 - Fix linting (COMPLETED):**
- [x] Fix line length warning in ControlOpenInputBooleanValueProvider

## Summary

Successfully implemented 8 focused controls for iOS Control Center with
all linting issues resolved:

**Final 8 Controls:**
- **Button** - Stateless action control that presses button/input_button
entities
- **Camera** - Opens camera entities (with beta label)
- **Cover** - Opens cover entities
- **Input Boolean** - Opens input_boolean entities
- **Light** - Opens light entities
- **Lock** - Opens lock entities
- **Sensor** - Opens sensor/binary_sensor entities
- **Switch** - Opens switch entities

All code passes linting checks with proper line width constraints.

<!-- START COPILOT CODING AGENT SUFFIX -->



<!-- START COPILOT ORIGINAL PROMPT -->



<details>

<summary>Original prompt</summary>

> We have the Open entity control in the app which allows users to add a
control in ios control center that opens entities. Please implement one
control like this per entity domain, like "Open camera", "Open lock",
"Open cover", make sure that the description mentions that the app will
open the entity inside the app and not perform any action directly


</details>



<!-- START COPILOT CODING AGENT TIPS -->
---

 Let Copilot coding agent [set things up for
you](https://github.com/home-assistant/iOS/issues/new?title=+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot)
— coding agent works faster and does higher quality work when set up for
your repo.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: bgoncal <5808343+bgoncal@users.noreply.github.com>
2025-12-16 12:07:01 +01:00

90 lines
3.0 KiB
Swift

import AppIntents
import Foundation
import SFSafeSymbols
import Shared
import WidgetKit
@available(iOS 18, *)
struct ControlOpenCoverEntityItem {
let entity: HAAppEntityAppIntentEntity
let icon: SFSymbolEntity
}
@available(iOS 18, *)
struct ControlOpenCoverEntityValueProvider: AppIntentControlValueProvider {
func currentValue(configuration: ControlOpenCoverEntityConfiguration) async throws -> ControlOpenCoverEntityItem {
item(configuration: configuration)
}
func placeholder(for configuration: ControlOpenCoverEntityConfiguration) -> ControlOpenCoverEntityItem {
item(configuration: configuration)
}
func previewValue(configuration: ControlOpenCoverEntityConfiguration) -> ControlOpenCoverEntityItem {
item(configuration: configuration)
}
private func item(configuration: ControlOpenCoverEntityConfiguration) -> ControlOpenCoverEntityItem {
.init(
entity: configuration.entity ?? .init(
id: "",
entityId: "",
serverId: "",
serverName: "",
displayString: "",
iconName: ""
),
icon: configuration.icon ?? placeholder().icon
)
}
private func placeholder() -> ControlOpenCoverEntityItem {
.init(
entity: .init(id: "", entityId: "", serverId: "", serverName: "", displayString: "", iconName: ""),
icon: .init(id: SFSymbol.squareOnSquare.rawValue)
)
}
}
@available(iOS 18.0, *)
struct ControlOpenCoverEntityConfiguration: ControlConfigurationIntent {
static var title: LocalizedStringResource = .init(
"widgets.controls.open_cover.configuration.title",
defaultValue: "Open Cover"
)
@Parameter(
title: .init("widgets.controls.open_cover.configuration.parameter.entity", defaultValue: "Cover"),
optionsProvider: CoverEntityOptionsProvider()
)
var entity: HAAppEntityAppIntentEntity?
@Parameter(
title: .init("app_intents.scenes.icon.title", defaultValue: "Icon")
)
var icon: SFSymbolEntity?
}
@available(iOS 18.0, *)
struct CoverEntityOptionsProvider: DynamicOptionsProvider {
func results() async throws -> IntentItemCollection<HAAppEntityAppIntentEntity> {
let entities = ControlEntityProvider(domains: [.cover]).getEntities()
return .init(sections: entities.map { (key: Server, value: [ControlEntity]) in
.init(
.init(stringLiteral: key.info.name),
items: value.map { entity in
HAAppEntityAppIntentEntity(
id: entity.id,
entityId: entity.entityId,
serverId: entity.serverId,
serverName: key.info.name,
displayString: entity.name,
iconName: entity.icon ?? SFSymbol.squareOnSquare.rawValue
)
}
)
})
}
}