-
-
Notifications
You must be signed in to change notification settings - Fork 134
Migrate to App Intents #1022
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
timbms
wants to merge
774
commits into
develop
Choose a base branch
from
migrateToAppIntents2
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Migrate to App Intents #1022
Changes from 6 commits
Commits
Show all changes
774 commits
Select commit
Hold shift + click to select a range
0771e67
Send single mapping button command on touch down
timbms 1f28532
Fix single mapping button sending duplicate commands
timbms a511e8a
Merge branch 'develop' into migrateToAppIntents2
timbms b6de847
Fix search returning no items for GenericItemEntity
timbms fc0a76e
Silence linters for CommonUI directory
timbms 78a8a47
Fix crash, bugs, and duplication from PR review
timbms 9fd4930
Move PreviewList to SegmentedRowView as shared internal type
timbms 7f9e776
Reorder ButtonGridRowView declarations and remove lint suppression
timbms 9d69736
Remove empty setupActiveConnectionObserver stub
timbms 7afbc8f
Defer non-essential AppDelegate setup and add placeholder title
timbms 2167c86
Fix Task leak, hidden TextField, ignored search pref, and linked-page…
timbms 8b10413
Fix connection observer lifecycle and redacted title during loading
timbms 4ec8a52
Simplify connection observer and prevent same-URL restart loop
timbms 5154a61
Default isLoading to true to show skeleton on first render
timbms 798b5ff
Remove duplicate PreviewConstants and decouple skeleton from preview …
timbms 6c31741
Use semantic gray colors for better segmented control track contrast
timbms f909def
Add inline buttons for single and press-release mappings on watchOS
timbms 0800e10
Constrain inline button hit area with contentShape
timbms 1987513
Fix inline button hit area extending beyond visible bounds
timbms b3bad83
Validate touch coordinates to constrain button hit area on watchOS
timbms 05f15fc
Skip widgets array reassignment when list structure is unchanged
timbms b89b6fa
Copy sendCommand closure when updating existing widget instances
timbms 36fd106
Fire single-mapping button on release within bounds, not on press
timbms 3dee5cc
Put up to 2 inline buttons on same row as title on watchOS
timbms 8bc10e0
Removing unused code
timbms 07fe9eb
Sync WidgetRowViewModel for all SegmentRow branches
timbms 314bca4
Migrate WidgetRowViewModel to Observation framework
timbms 8e02461
Update project
timbms b5be93a
Adopt WidgetRowViewModel and clean up watchOS row views
timbms 8a5f408
Extract WidgetRowFactory and decouple previews from UserData
timbms ce492e4
Add PreviewNavigationContainer and use it across all row previews
timbms 50d3d76
Centralize watchOS typography with WatchTypography and WatchLabelText
timbms 30b610d
Extract WidgetCommandSender for centralized command dispatch
timbms b67e80e
Fix WidgetCommandSender cleanup and setpoint unit preservation
timbms ab7b3fe
Simplify stateless rows by removing unnecessary WidgetRowViewModel
timbms c634c23
Replace IconView with model-driven WatchIconView
timbms cf4d654
Simplify SwitchRow and SelectionRow with direct data passing
timbms 456c620
Simplify SliderRow, SetpointRow, and SegmentSelectionView with direct…
timbms b1d06bb
Restore WidgetRowViewModel for complex rows and unify stateToken pattern
timbms c37ae53
Migrate ColorSelection to WidgetCommandSender with debounce policy
timbms 0fd73d1
Decouple WatchLabelText and DetailTextLabelView from OpenHABWidget
timbms 45fb0df
Add watchTextStyle modifier and accessibility labels across watchOS v…
timbms 0bc1bcc
Adopt stateToken pattern in SegmentRow and ColorPickerRow
timbms 8b4b75d
Add dedicated watchOS test target and interactive state token previews
timbms 29fb7d6
Add unit tests for WidgetCommandSender
timbms 9d32fb7
Merge branch 'develop' into openapigen-swiftui
timbms 3fd1504
Merge branch 'develop' into migrateToAppIntents2
timbms 4b5a649
Fix scroll-to-top on long-poll updates and image flickering
timbms c7c0c95
Fix ButtonGrid commands to target parent widget item
timbms d7353da
Move test helpers above test suites for consistency
timbms e938fd2
Merge branch 'develop' into openapigen-swiftui
timbms b88f390
Fix webview authentication in SwiftUI sitemap renderer
timbms 5a558a3
Minor cleanup
timbms b9436c8
Add Player, DateTime, and Location item types to iOS Shortcuts
timbms 0e184b1
Merge branch 'develop' into migrateToAppIntents2
timbms 126de64
Lint check
timbms af10036
Merge branch 'develop' into openapigen-swiftui
timbms b5b4bfe
Merge branch 'develop' into migrateToAppIntents2
timbms 6d9e7df
Merge branch 'develop' into openapigen-swiftui
timbms 719fe96
Provide command source for SwiftUI and watchOS
timbms 44aee42
Move WidgetCommandDispatcher into OpenHABCore for shared use
timbms 74154ff
Extract WidgetDisplayState for consistent widget rendering
timbms 7e1685e
Fix watchOS commands silently failing after long poll
timbms 37a833c
Align setpoint value formatting across iOS and watchOS
timbms 9521bcc
Fix thread safety, command source, and display state consistency
timbms f53e773
Missing return
timbms fa0ce12
Refactor SwiftUI views for improved readability
timbms 694d185
Merge branch 'develop' into openapigen-swiftui
timbms 5bfbcc0
Add OHTextToken design system and improve value formatting
timbms 5bfb239
Cancel long-polling on view disappear to prevent duplicate tasks
timbms dd1760f
Add deduplication and staleness guards to page handling
timbms e72fb01
Add command lifecycle tracking and refactor page handling
timbms afacbfc
Move command lifecycle indicator to leading toolbar and hide when idle
timbms 9f352a5
Add toolbar search button with on-demand searchable field
timbms c60ecaf
Fix slider yo-yo and stale state by reconciling widget identity
timbms 20f6769
Remove legacy UIKit sitemap view controller and cell providers
timbms 96e78be
Extract SliderRowState and prefer adjustedValue for item-backed sliders
timbms e6d51d9
Add defensive resets for slider widget identity changes and stuck edi…
timbms 0d45208
Prefer widget pattern over item stateDescription for slider formatting
timbms 981fe7d
Replace persistent slider state with ephemeral drag value and version…
timbms 3f7d778
Fix command truncation for setpoint/slider with integer display format
timbms 2b32010
Update project: remove Cells group, Swift 6 for watch tests, random t…
timbms 9e7a52f
Add openHABWatch test plan and wire into scheme
timbms 5c32e51
Add optimistic selection to SegmentedRowView and SelectionRowView
timbms f5f05bc
Refactor: introduce input structs and align optimistic naming
timbms a29fb82
Move PreviewWidgetFactory to CommonUI, replace per-file preview helpers
timbms 0f6463f
Fold WatchTypography into OHTextToken, remove parallel watch type system
timbms eebbc9c
Add PreviewWidgetFactory implementation and tests to CommonUI
timbms 664d598
Add minimum hit targets to iOS buttons; replace ad-hoc fonts on watch
timbms 98ac24f
Skip copyWidgetProperties when widget is unchanged; reconcile frame c…
timbms 8d69b29
Extract *RowInput structs to WidgetRowInputs.swift; split Slider/Sele…
timbms 496ee3a
Introduce immutable row-input pipeline; drive SitemapPageView list fr…
timbms 2d21331
Migrate slider, selection, segmented rows to input-driven views
timbms 3769acd
Migrate setpoint and toggle rows to typed input pipeline; refactor sl…
timbms 8be0f39
Migrate text, rollershutter, colorPicker, buttonGrid, and input rows …
timbms cb3b415
Migrate remaining row types to typed inputs; complete BasicWidgetRowI…
timbms cacda40
Retire BasicWidgetRowInput; add FrameRowInput, TextRowInput; wire Gen…
timbms d8b9e7b
Introduce LinkedPageRowInput and .linked case; migrate media rows to …
timbms f2e7aad
Decouple icon and command dispatch from OpenHABWidget in content views
timbms 5f4c1a1
Retire legacy widget paths; replace renderSignature with Equatable sy…
timbms 773ee43
Retire widget-based row views; add icon/itemName to typed inputs
timbms d9c98b5
Add SitemapInteractionSummary; surface network status in toolbar
timbms 147382a
Rename *InputView to *RowView; add offline command queuing
timbms 039e719
Add slider override tracking; extract SitemapPageViewModel support types
timbms 9b800d0
Fix ColorPickerRowView: suppress echo sends; clamp/round HSB values
timbms a540ec5
Update AGENTS.md: iPhone 17 Pro simulator, SwiftUI-first, Swift Testi…
timbms 316d840
CI: trigger TestFlight build on push to openapigen-swiftui
timbms 923febd
Add Version.xcconfig; fix extension CFBundleVersion; update Fastfile …
timbms 089bb5c
Fix slider override change notification; reorder SupportTypes; add sw…
timbms cdf6f21
Fix ColorTemperaturePickerRowView: suppress echo sends; guard drag st…
timbms 8ca0882
Throttle onDragStateChanged to fire once per drag in CustomSliderView
timbms 9067f09
CI: remove push trigger from TestFlight workflow; keep workflow_dispa…
timbms 8135bf6
Add merge driver for Version.xcconfig to always keep ours
timbms 219466b
Merge develop into openapigen-swiftui: unify xcconfig versioning
timbms cc782b2
Merge branch 'develop' into migrateToAppIntents2
timbms 8777e88
ColorTemperaturePickerRowView layout adjustments (#1073)
DigiH 882f054
fastlane: replace missing get/update_xcconfig_value plugin with plain…
timbms 8dba571
fastlane: use absolute path for Version.xcconfig in increment_build
timbms b7f12f6
fastlane: replace remaining get/update_xcconfig_value calls with plai…
timbms 2044d56
fastlane: replace get_build_number with xcconfig read
timbms 6cf8647
openHABWatch: fix Release build failures due to #Preview type-checking
timbms f4cff9d
openHAB iOS: fix Release build failures due to #Preview type-checking
timbms b022d4b
project: pre-apply Xcode 26.2 project.pbxproj normalisations
timbms b3ecc89
fastlane: clear FL_CHANGELOG after use to reduce summary noise
timbms 514cd41
Pre-apply Xcode 26.2 project.pbxproj normalizations and fix SetpointR…
timbms 54ae0f5
committed version bump: 3.2.1 (203)
98794e0
fastlane: restore project.pbxproj after build to keep git clean
timbms 6789603
committed version bump: 3.2.2 (204)
5a10664
project: restore DADC420A PBXBuildFile to correct SDWebImage entry
timbms fcb9e84
Merge branch 'develop' into openapigen-swiftui
timbms c7a53a7
watchOS: remove duplicate decorateWidgetsWithSendCommand introduced b…
timbms dfd5a1d
iOS: fix chart widget identity and image flicker
timbms b386d6a
iOS: match UIKit alert style for text/number input rows
timbms 93c1521
committed version bump: 3.2.3 (205)
2f3e975
iOS: add input filtering and validation for text/number input widget
timbms d85d65a
Merge branch 'develop' into openapigen-swiftui
timbms c396e33
project: restore WatchTypography.swift to openHABWatch build on opena…
timbms 361600d
iOS: sync chart display URL from viewModel on appear and relevant cha…
timbms a17bc88
iOS: guard chart URL reuse with a display key to prevent stale placeh…
timbms dbae12c
iOS: converge chart rendering to stable, flicker-free architecture
timbms b45be08
iOS: refine chart state management with ChartDisplayState and task-ba…
timbms 2896b97
iOS: drive chart refresh from widget version; fix cache buster entrop…
timbms f2a9d9a
iOS: decode SVG images at full size for media/image widgets
timbms 4b8f7e2
iOS/watchOS: force page refresh when app returns from background
timbms 00d1501
iOS: keep sitemap long-polling alive across transient failures
timbms 1ac0ea1
iOS: refresh embedded sitemap images when payload changes
timbms 91f5aa3
Segmented Controls layout adjustments for iPads (#1078)
DigiH 3a4ad16
watchOS: remove PreviewConstants dependency from row previews
timbms 249f363
committed version bump: 3.2.4 (206)
f6f1fe7
Proposal to restrict the hit traget to the area after the Selection r…
DigiH 7ed5543
Merge branch 'develop' into openapigen-swiftui
timbms 1973b0e
Merge remote-tracking branch 'origin/openapigen-swiftui'
timbms 6184bae
Handle empty SVG icons without warning fallback
timbms 355d876
iOS/watchOS: fix stale widget state on background→foreground (#1075)
timbms 0cedf5c
committed version bump: 3.2.5 (208)
75ffdb6
watch: disable sitemap request caching for long-poll service
timbms 199c5df
Migrate remaining regex usage to Swift 6 regex syntax
timbms c0b12a5
watchOS: force row recreation on widget state change; update AGENTS.md
timbms c62e53d
chore: ignore Claude Code skills-lock.json and .agents/
timbms a69379b
watchOS: remove redundant item.state from WidgetRowView refreshToken
timbms e2a3bd9
committed version bump: 3.2.6 (209)
d188dbf
iOS: refresh on every scene-active transition; fix watchOS backoff ov…
timbms 40d9cac
committed version bump: 3.2.7 (210)
0cef450
Recreate number validation function from UIKit sitemap
TAKeanice eb2f202
Validate number input during typing, improve normalization
TAKeanice c38f6bf
iOS: disable URL cache for sitemap service; fix scene-active launch race
timbms 4956eaa
allow 0 as number input
TAKeanice 95a9fb3
allow multiline labels and improve layout of text or number input rows
TAKeanice 9c5232d
added flow to some more rows, hide icon if showIcon is false
TAKeanice a59b805
Improve sitemap foreground refresh and drawer resume handling
timbms bb38ac4
Remove unnecessary async wrapper and stale connection fallback
timbms 6465a0b
Handle foreground resume from App Switcher without open drawer
timbms c93af23
Fix auth challenge host matching and watch icon transient dropout
timbms 10994ce
Revmove flow in segmented control row, improved spacing for text views
TAKeanice 67d8bab
Display rollershutter value state in iOS and watchOS rows
timbms 060e603
iOS & watchOSRollershutter & Setpoint Chevrons convergence (#1094)
DigiH 0cf255f
Extract SetpointDisplayFormatter for iOS and watchOS setpoint display
timbms b27038b
Separate serverValue from currentValue in watch SetpointRow
timbms 8fc30a3
Merge branch 'develop' into openapigen-swiftui
timbms 363bfce
Update CHANGELOG with openapigen-swiftui unreleased changes
timbms 6762380
disable linting and format for swiftui auto build
TAKeanice 137f567
make DatePickerRowView not send programmatic updates of the date
TAKeanice a4c15c5
iOS & watchOS Rollershutter & Setpoint circled controls (#1096)
DigiH f28db68
committed version bump: 3.2.8 (212)
1eaaab2
Fix corrupt project.pbxproj entries
timbms a696fb8
Fix notifications back button and nav bar
timbms e291a6f
committed version bump: 3.2.9 (213)
5368628
watchOS Rollershutter Stop glyph change (#1097)
DigiH 05f9d71
Fix manage homes back button and nav bar
timbms 3111f98
Replace stale notification categories
timbms 9d48865
iOS Homes dialogs adjusments (#1099)
DigiH b5054dd
Fix screensaver layout sizing for large text (#1098)
timbms df68360
Use FormatStyle for screen saver date and 12-hour time
timbms ebfbd25
Use FormatStyle for Double.valueText and add tests
timbms a17d51b
Use FormatStyle in log and notification views
timbms f01c7b7
Migrate CGFloat(state:divisor:) to FormatStyle API; add tests
timbms 2a7f326
Migrate JSONDecoder date strategy to FormatStyle API; add DateFormatt…
timbms f8543f8
Migrate StringExtension to FormatStyle API; add StringExtensionTests
timbms 0f934d8
Fix StringExtensionTests: add @testable import OpenHABCore
timbms ce4b21f
Add plain 'Test' configuration to openHABTests test plan
timbms 045e2e5
Fix openHABTestsSwift linker errors for host-app dynamic frameworks
timbms 91793cc
Remove SDWebImageSVGCoder direct import from OpenHABSVGTests
timbms a71b306
Decouple OpenAPIRuntime from call sites via OpenAPIErrorInspector
timbms 4245189
Fix optional binding error on non-optional ClientError.underlyingError
timbms 29c718b
Fix script editor scroll truncated on iPhone (issue #1092)
timbms a7ca3cf
Associate openHABTests test plan with openHABTestsSwift scheme
timbms 683456d
Remove ASAN configuration from openHABTests test plan
timbms b1e0bc6
committed version bump: 3.2.10 (214)
0819b67
Fix empty string commands and switch sendItemCommand to JSON payload …
timbms e204de9
committed version bump: 3.2.11 (215)
3e05c4d
Merge openapigen-swiftui into migrateToAppIntents2
timbms aa37a05
improve TextInputRowView legibility and corresponding tests
TAKeanice 54e2555
Fix unbalanced brace in project.pbxproj from auto-merge
timbms 32525a8
Localisation transition to String Catalog (#1101)
DigiH 1c3938c
Remove stale references to ControlItemIntent.swift and openHABIntents…
timbms b533929
Update Package.resolved after merging openapigen-swiftui
timbms 6493c4d
Merge openapigen-swiftui into migrateToAppIntents2
timbms 7882bc2
Merge origin/develop into migrateToAppIntents2
timbms e5faf7e
Fix duplicate Localizable.xcstrings in same target
timbms 4d44453
Fix duplicate MainLaunchScreen.nib in build
timbms 91aeac6
Remove duplicate Sources/Resources entries shadowed by file system sync
timbms 5c04a72
Fix build failures caused by duplicate files and stale project refere…
timbms 4c92da6
Fix intentsLocalizations/intentsPlaceholders tests after App Intents …
timbms 5f80d53
Remove duplicate Sources/Resources entries for openHABWatch and openH…
timbms 9c704eb
Merge branch 'develop' into migrateToAppIntents2
timbms 23c8e86
Migrate AppIntents strings to Localizable.xcstrings
timbms b428138
Merge branch 'develop' into migrateToAppIntents2
timbms 96da456
Remove stale build file references from project
timbms 3428b2c
Reformat Localizable.xcstrings to Xcode style
timbms ad2fec2
Remove obsolete openHABIntents SiriKit extension artifacts
timbms 434b800
Add AppIntents validation tests
timbms e4290db
Fix App Intents localization tests after string catalog migration
timbms 877907f
Remove stale legacy PBXGroup hierarchy for openHAB target
timbms 14b24ac
Fetch live item state in GetItemStateIntent instead of using cached v…
timbms 7b767ad
Persist item stubs to UserDefaults to prevent Shortcuts losing entity…
timbms ed5fafe
Merge branch 'develop' into migrateToAppIntents2
timbms 56b7735
Adjust German App Intents state terminology
timbms e554883
Avoid localizing stored App Intents entity names
timbms 1a8d17b
Mark App Intents home name as non-translatable
timbms 89b7a14
Merge branch 'develop' into migrateToAppIntents2
timbms 461ac52
Merge branch 'develop' into migrateToAppIntents2
timbms 8abb112
Additional German translations
DigiH 267b903
Small German translation correctons and adjustments
DigiH ebcfcca
Merge branch 'develop' into migrateToAppIntents2
timbms 8b3497e
Run App Intents without opening the app
timbms 299795b
Reduce App Intent background loading
timbms f99c980
Improve shortcuts item search and unique home resolution
timbms 58791bb
Infer homes for App Intents and stop localizing home names
timbms c5a9d94
Merge branch 'develop' into migrateToAppIntents2
timbms b5ff5d5
Use stable cross-device identifier for Home AppEntity (#1163)
timbms File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,130 @@ | ||
| // Copyright (c) 2010-2025 Contributors to the openHAB project | ||
| // | ||
| // See the NOTICE file(s) distributed with this work for additional | ||
| // information. | ||
| // | ||
| // This program and the accompanying materials are made available under the | ||
| // terms of the Eclipse Public License 2.0 which is available at | ||
| // http://www.eclipse.org/legal/epl-2.0 | ||
| // | ||
| // SPDX-License-Identifier: EPL-2.0 | ||
|
|
||
| import AppIntents | ||
| import Foundation | ||
| import OpenHABCore | ||
|
|
||
| enum GetItemStateError: Error, CustomLocalizedStringResourceConvertible { | ||
| case invalidHomeIdentifier | ||
| case unknownHome | ||
| case itemNotFound(String) | ||
|
|
||
| var localizedStringResource: LocalizedStringResource { | ||
| switch self { | ||
| case .invalidHomeIdentifier: | ||
| "Invalid home identifier" | ||
| case .unknownHome: | ||
| "Unknown home" | ||
| case let .itemNotFound(itemName): | ||
| "Item '\(itemName)' not found" | ||
| } | ||
| } | ||
| } | ||
|
|
||
| @available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, *) | ||
| struct GetItemState: AppIntent, CustomIntentMigratedAppIntent, PredictableIntent { | ||
| struct StringOptionsProvider: DynamicOptionsProvider { | ||
| func results() async throws -> [String] { | ||
| let allItems = await OpenHABItemCache.instance.getAllCachedItems() | ||
| return allItems.flatMap { $0.value.map(\.name) } | ||
| } | ||
| } | ||
|
|
||
| static let intentClassName = "OpenHABGetItemStateIntent" | ||
|
|
||
| static let title: LocalizedStringResource = "Get Item State" | ||
| static let description = IntentDescription("Retrieve the current state of an item") | ||
|
|
||
| // swiftlint:disable type_contents_order | ||
| @Parameter(title: "Item", optionsProvider: StringOptionsProvider()) | ||
| var item: String | ||
|
|
||
| @Parameter(title: "Home") | ||
| var home: Home | ||
|
|
||
| static var parameterSummary: some ParameterSummary { | ||
| Summary("Get \(\.$item) State") { | ||
| \.$home | ||
| } | ||
| } | ||
|
|
||
| // swiftlint:enable type_contents_order | ||
|
|
||
| static var predictionConfiguration: some IntentPredictionConfiguration { | ||
| IntentPrediction(parameters: (\.$item, \.$home)) { item, _ in | ||
| DisplayRepresentation( | ||
| title: "Get \(item) State", | ||
| subtitle: "" | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| func perform() async throws -> some IntentResult & ReturnsValue<String> { | ||
| guard let homeId = UUID(uuidString: home.id) else { | ||
| throw GetItemStateError.invalidHomeIdentifier | ||
| } | ||
|
|
||
| let homeExists = await MainActor.run { | ||
| Preferences.shared.storedHomes[homeId] != nil | ||
| } | ||
|
|
||
| guard homeExists else { | ||
| throw GetItemStateError.unknownHome | ||
| } | ||
|
|
||
| guard let openHABItem = await OpenHABItemCache.instance.getItemUncached(name: item, home: homeId) else { | ||
| throw GetItemStateError.itemNotFound(item) | ||
| } | ||
|
|
||
| let state = openHABItem.state ?? "Unknown state" | ||
|
|
||
| return .result( | ||
| value: state, | ||
| dialog: .responseSuccess(item: item, state: state) | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| @available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, *) | ||
| private extension IntentDialog { | ||
| static var itemParameterConfiguration: Self { | ||
| "Item Name" | ||
| } | ||
|
|
||
| static var homeParameterConfiguration: Self { | ||
| "Home name" | ||
| } | ||
|
|
||
| static var homeParameterPrompt: Self { | ||
| "blabla" | ||
| } | ||
|
|
||
| static var homeParameterDisambiguationSelection: Self { | ||
| "For which home do you want to get the value?" | ||
| } | ||
|
|
||
| static func homeParameterDisambiguationIntro(count: Int, item: String) -> Self { | ||
| "There are \(count) configured homes with an item named '\(item)'’." | ||
|
timbms marked this conversation as resolved.
Outdated
|
||
| } | ||
|
|
||
| static func homeParameterConfirmation(home: Home) -> Self { | ||
| "Just to confirm, you wanted ‘\(home)’?" | ||
| } | ||
|
|
||
| static func responseSuccess(item: String, state: String) -> Self { | ||
| "The state of \(item) is \(state)" | ||
| } | ||
|
|
||
| static func responseFailureInvalidItem(item: String) -> Self { | ||
| "Sorry can't find \(item)" | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| // Copyright (c) 2010-2025 Contributors to the openHAB project | ||
| // | ||
| // See the NOTICE file(s) distributed with this work for additional | ||
| // information. | ||
| // | ||
| // This program and the accompanying materials are made available under the | ||
| // terms of the Eclipse Public License 2.0 which is available at | ||
| // http://www.eclipse.org/legal/epl-2.0 | ||
| // | ||
| // SPDX-License-Identifier: EPL-2.0 | ||
|
|
||
| import AppIntents | ||
| import Foundation | ||
| import OpenHABCore | ||
|
|
||
| @available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, *) | ||
| struct Home: AppEntity { | ||
| struct HomeQuery: EntityQuery { | ||
| @MainActor | ||
| func entities(for identifiers: [Home.ID]) async throws -> [Home] { | ||
| identifiers.compactMap { identifier in | ||
| guard let uuid = UUID(uuidString: identifier), | ||
| let homePrefs = Preferences.shared.storedHomes[uuid] else { | ||
| return nil | ||
| } | ||
| return Home(id: homePrefs.id.uuidString, displayString: homePrefs.homeName) | ||
| } | ||
| } | ||
|
|
||
| @MainActor | ||
| func suggestedEntities() async throws -> [Home] { | ||
| Preferences.shared.storedHomes.map { homePrefs in | ||
| Home(id: homePrefs.value.id.uuidString, displayString: homePrefs.value.homeName) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| static let typeDisplayRepresentation = TypeDisplayRepresentation(name: "Home") | ||
|
|
||
| static let defaultQuery = HomeQuery() | ||
|
|
||
| var id: String // if your identifier is not a String, conform the entity to EntityIdentifierConvertible. | ||
| var displayString: String | ||
| var displayRepresentation: DisplayRepresentation { | ||
| DisplayRepresentation(title: "\(displayString)") | ||
| } | ||
|
|
||
| init(id: String, displayString: String) { | ||
| self.id = id | ||
| self.displayString = displayString | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,149 @@ | ||
| // Copyright (c) 2010-2025 Contributors to the openHAB project | ||
| // | ||
| // See the NOTICE file(s) distributed with this work for additional | ||
| // information. | ||
| // | ||
| // This program and the accompanying materials are made available under the | ||
| // terms of the Eclipse Public License 2.0 which is available at | ||
| // http://www.eclipse.org/legal/epl-2.0 | ||
| // | ||
| // SPDX-License-Identifier: EPL-2.0 | ||
|
|
||
| import AppIntents | ||
| import Foundation | ||
| import OpenHABCore | ||
|
|
||
| enum SetColorValueError: Error, CustomLocalizedStringResourceConvertible { | ||
| case invalidHomeIdentifier | ||
| case unknownHome | ||
| case itemNotFound(String) | ||
| case invalidValue(String, String) | ||
|
|
||
| var localizedStringResource: LocalizedStringResource { | ||
| switch self { | ||
| case .invalidHomeIdentifier: | ||
| "Invalid home identifier" | ||
| case .unknownHome: | ||
| "Unknown home" | ||
| case let .itemNotFound(itemName): | ||
| "Item '\(itemName)' not found" | ||
| case let .invalidValue(value, itemName): | ||
| "Invalid value: \(value) for \(itemName) must be HSB (0-360,0-100,0-100)" | ||
| } | ||
| } | ||
| } | ||
|
|
||
| @available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, *) | ||
| struct SetColorValue: AppIntent, CustomIntentMigratedAppIntent, PredictableIntent { | ||
| struct StringOptionsProvider: DynamicOptionsProvider { | ||
| func results() async throws -> [String] { | ||
| let allItems = await OpenHABItemCache.instance.getAllCachedItems() | ||
| let items = allItems.flatMap(\.value).filter { $0.type == .color } | ||
| return items.map(\.name) | ||
| } | ||
| } | ||
|
|
||
| static let intentClassName = "OpenHABSetColorValueIntent" | ||
|
|
||
| static let title: LocalizedStringResource = "Set Color Control Value" | ||
| static let description = IntentDescription("Set the color of a color control item") | ||
|
|
||
| // swiftlint:disable type_contents_order | ||
| @Parameter(title: "Item", optionsProvider: StringOptionsProvider()) | ||
| var item: String | ||
|
|
||
| @Parameter(title: "Value", default: "240,100,100") | ||
| var value: String | ||
|
|
||
| @Parameter(title: "Home") | ||
| var home: Home | ||
|
|
||
| static var parameterSummary: some ParameterSummary { | ||
| Summary("Set \(\.$item) to \(\.$value) (HSB)") { | ||
| \.$home | ||
| } | ||
| } | ||
|
|
||
| // swiftlint:enable type_contents_order | ||
|
|
||
| static var predictionConfiguration: some IntentPredictionConfiguration { | ||
| IntentPrediction(parameters: (\.$item, \.$value, \.$home)) { item, value, _ in | ||
| DisplayRepresentation( | ||
| title: "Set \(item) to \(value) (HSB)", | ||
| subtitle: "" | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| func perform() async throws -> some IntentResult & ProvidesDialog { | ||
| var colorValue = value | ||
|
|
||
| guard let homeId = UUID(uuidString: home.id) else { | ||
| throw SetColorValueError.invalidHomeIdentifier | ||
| } | ||
|
|
||
| let homeExists = await MainActor.run { | ||
| Preferences.shared.storedHomes[homeId] != nil | ||
| } | ||
|
|
||
| guard homeExists else { | ||
| throw SetColorValueError.unknownHome | ||
| } | ||
|
|
||
| let hsb = colorValue.split(separator: ",") | ||
| guard hsb.count == 3, | ||
| let hue = Int(hsb[0]), (0 ... 360).contains(hue), | ||
| let sat = Int(hsb[1]), (0 ... 100).contains(sat), | ||
| let val = Int(hsb[2]), (0 ... 100).contains(val) else { | ||
| throw SetColorValueError.invalidValue(colorValue, item) | ||
| } | ||
|
|
||
| colorValue = "\(hue),\(sat),\(val)" | ||
|
|
||
| guard let items = await OpenHABItemCache.instance.getCachedItem(name: item, home: homeId), | ||
| !items.isEmpty else { | ||
| throw SetColorValueError.itemNotFound(item) | ||
| } | ||
|
|
||
| let openHABItem = items[0] | ||
|
|
||
| await OpenHABItemCache.instance.sendCommand(to: openHABItem, home: homeId, command: colorValue) | ||
|
|
||
| return .result(dialog: .responseSuccess(value: colorValue, item: item)) | ||
| } | ||
| } | ||
|
|
||
| @available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, *) | ||
| private extension IntentDialog { | ||
| static var itemParameterConfiguration: Self { | ||
| "Color Item Name" | ||
| } | ||
|
|
||
| static var homeParameterConfiguration: Self { | ||
| "Home name" | ||
| } | ||
|
|
||
| static var homeParameterDisambiguationSelection: Self { | ||
| "For which home do you want to get the value?" | ||
| } | ||
|
|
||
| static func homeParameterDisambiguationIntro(count: Int, item: String) -> Self { | ||
| "There are \(count) configured homes with an item named '\(item)'." | ||
| } | ||
|
|
||
| static func homeParameterConfirmation(home: Home) -> Self { | ||
| "Just to confirm, you wanted '\(home)'?" | ||
| } | ||
|
|
||
| static func responseSuccess(value: String, item: String) -> Self { | ||
| "Sent the color value of \(value) to \(item)" | ||
| } | ||
|
|
||
| static func responseFailureInvalidItem(item: String) -> Self { | ||
| "Sorry can't find \(item)" | ||
| } | ||
|
|
||
| static func responseFailureInvalidValue(value: String, item: String) -> Self { | ||
| "Invalid value: \(value) for \(item) must be HSB (0-360,0-100,0-100)" | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.