From f823734a3f9ffe5036081bdcb04f4ab9df9435ed Mon Sep 17 00:00:00 2001 From: Tim Bert <5411131+timbms@users.noreply.github.com> Date: Wed, 30 Oct 2024 07:32:39 +0100 Subject: [PATCH] Migrate from WatchKit storyboard to SwiftUI and its lifecycle (#739) * Migration of watch app to SwiftUI and its lifecycle * Handling of svg images on watchOS with SDWebImage, removed Kingfisher as dependency in watch app. * Replace watch tracker with global network tracker Co-authored-by: Dan Cunningham Signed-off-by: Tim Bert <5411131+timbms@users.noreply.github.com> --- .gitignore | 2 + BuildTools/.swiftformat | 1 + BuildTools/Package.resolved | 4 +- BuildTools/Package.swift | 2 +- .../OpenHABCore/Model/OpenHABWidget.swift | 1 - .../Util/ClientCertificateManager.swift | 2 +- .../OpenHABCore/Util/NetworkTracker.swift | 1 + .../OpenHABCore/Util/Preferences.swift | 1 + .../OpenHABCoreTests/UserDefaultsTests.swift | 2 + openHAB.xcodeproj/project.pbxproj | 528 +++++++++++++++--- .../contents.xcworkspacedata | 2 +- .../xcshareddata/swiftpm/Package.resolved | 249 +++++++++ .../openHABWatch (Notification).xcscheme | 4 +- .../xcschemes/openHABWatch.xcscheme | 15 +- .../xcshareddata/swiftpm/Package.resolved | 27 + openHAB/DrawerView.swift | 221 +++++--- openHAB/OpenHABSitemapViewController.swift | 2 + openHAB/SettingsView.swift | 36 ++ openHAB/WatchMessageService.swift | 7 +- openHABTestsSwift/OpenHABWatchTests.swift | 1 + openHABUITests/OpenHABUITests.swift | 1 - .../ExtensionDelegate.swift | 163 ------ .../HostingController.swift | 31 - .../OpenHABWatchTracker.swift | 317 ----------- .../PreferencesHostingController.swift | 20 - .../Views/PreferencesSwiftUIView.swift | 46 -- .../Views/Rows/FrameRow.swift | 38 -- .../Views/Rows/ImageRow.swift | 52 -- .../Views/Rows/SegmentRow.swift | 63 --- .../Views/Rows/SliderRow.swift | 67 --- .../Views/Utils/IconView.swift | 61 -- .../Views/Utils/Unwrap.swift | 28 - .../openHABWatch Extension/UserData.swift | 249 --------- .../openHABWatch Extension/app/AppState.swift | 18 - .../AppIcon.appiconset/Contents.json | 92 +-- .../AppIcon.appiconset/Icon-24@2x.png | Bin 2716 -> 0 bytes .../AppIcon.appiconset/Icon-27.5@2x.png | Bin 3131 -> 0 bytes .../AppIcon.appiconset/Icon-29@2x.png | Bin 3451 -> 0 bytes .../AppIcon.appiconset/Icon-29@3x.png | Bin 5556 -> 0 bytes .../AppIcon.appiconset/Icon-40@2x.png | Bin 4959 -> 0 bytes .../AppIcon.appiconset/Icon-86@2x.png | Bin 14007 -> 0 bytes .../AppIcon.appiconset/Icon-98@2x.png | Bin 17356 -> 0 bytes .../AppIcon.appiconset/ItunesArtwork@2x 1.png | Bin 0 -> 194977 bytes .../AppIcon.appiconset/icon-100.png | Bin 14812 -> 0 bytes .../AppIcon.appiconset/icon-216@2x.png | Bin 20415 -> 0 bytes .../AppIcon.appiconset/icon-88.png | Bin 14377 -> 0 bytes openHABWatch/Assets.xcassets/Contents.json | 6 +- openHABWatch/Domain/UserData.swift | 185 ++++++ .../Circular.imageset/Contents.json | 0 .../Contents.json | 25 +- .../Extra Large.imageset/Contents.json | 0 .../Graphic Bezel.imageset/Contents.json | 0 .../Graphic Circular.imageset/Contents.json | 0 .../Graphic Corner.imageset/Contents.json | 0 .../Contents.json | 25 + .../Contents.json | 0 .../Modular.imageset/Contents.json | 0 .../Utilitarian.imageset/Contents.json | 0 .../Extension}/Assets.xcassets/Contents.json | 0 .../OHIcon.imageset/Contents.json | 0 .../Assets.xcassets/OHIcon.imageset/Icon.png | Bin .../OHTemplateIcon.imageset/Contents.json | 0 .../oh_logo_template.pdf | Bin .../Extension}/ComplicationController.swift | 0 .../Extension}/Info.plist | 2 +- .../Extension}/NotificationController.swift | 0 .../Extension}/NotificationView.swift | 12 +- .../OpenHABImageDownloaderOperation.swift | 26 + .../Extension/OpenHABWatchAppDelegate.swift | 80 +++ .../Extension}/PushNotificationPayload.apns | 6 +- .../Extension}/UserDefaultsExtension.swift | 2 +- .../Circular.imageset/Contents.json | 0 .../Circular.imageset/Icon-32@2x.png | Bin .../Circular.imageset/Icon-36@2x.png | Bin .../Contents.json | 0 .../Extra Large.imageset/Contents.json | 0 .../Graphic Bezel.imageset/Contents.json | 0 .../Graphic Circular.imageset/Contents.json | 0 .../Graphic Circular.imageset/openhab84.png | Bin .../Graphic Circular.imageset/openhab94.png | Bin .../Graphic Corner.imageset/Contents.json | 0 .../Contents.json | 0 .../Modular.imageset/Contents.json | 0 .../Modular.imageset/Icon-52@2x.png | Bin .../Modular.imageset/Icon-58@2x.png | Bin .../Utilitarian.imageset/Contents.json | 0 .../Utilitarian.imageset/Icon-40@2x.png | Bin .../Utilitarian.imageset/Icon-44@2x.png | Bin .../Assets.xcassets/Contents.json | 0 .../ButtonTableRowController.swift | 0 .../ComplicationController.swift | 0 .../ExtensionDelegate.swift | 0 .../openHABWatch Extension/Info.plist | 0 .../InterfaceController.swift | 0 .../NotificationController.swift | 0 .../PrefsInterfaceController.swift | 0 .../PushNotificationPayload.apns | 0 .../UserDefaultsExtension.swift | 0 .../external/OpenHabService.swift | 0 .../External}/AppMessageService.swift | 34 +- openHABWatch/Info.plist | 29 +- .../Model/LazyView.swift | 0 .../Model/ObservableOpenHABDataObject.swift | 14 + .../Model/ObservableOpenHABSitemapPage.swift | 0 .../Model/ObservableOpenHABWidget.swift | 0 .../ObservableOpenHABWidgetExtension.swift | 5 +- .../Model/UserDefaultsBacked.swift | 2 +- openHABWatch/OpenHABWatch.swift | 68 +++ .../Preview Assets.xcassets/Contents.json | 6 + .../Views/ContentView.swift | 32 +- .../Views/PreferencesSwiftUIView.swift | 46 ++ .../Views/Rows/ColorPickerRow.swift | 15 +- openHABWatch/Views/Rows/FrameRow.swift | 31 + .../Views/Rows/GenericRow.swift | 11 +- .../Views/Rows/ImageRawRow.swift | 12 +- openHABWatch/Views/Rows/ImageRow.swift | 53 ++ .../Views/Rows/MapViewRow.swift | 11 +- .../Views/Rows/RollershutterRow.swift | 22 +- openHABWatch/Views/Rows/SegmentRow.swift | 63 +++ .../Views/Rows/SetpointRow.swift | 15 +- openHABWatch/Views/Rows/SliderRow.swift | 61 ++ .../Rows/SliderWithSwitchSupportRow.swift | 17 +- .../Views/Rows/SwitchRow.swift | 46 +- .../Views/Utils/Color+Extension.swift | 0 .../Views/Utils/ColorSelection.swift | 6 +- .../Views/Utils/DetailTextLabelView.swift | 12 +- openHABWatch/Views/Utils/IconView.swift | 53 ++ .../Views/Utils/IconWithAction.swift | 10 +- .../Views/Utils/ImageWithAction.swift | 25 +- .../Views/Utils/MapView.swift | 9 +- .../Views/Utils/PreviewConstants.swift | 6 +- .../Views/Utils/TextLabelView.swift | 8 +- openHABWatch/openHABWatch.entitlements | 5 - .../OpenHABWatchAppTests.swift | 49 ++ .../OpenHABWatchLaunchTests.swift | 46 ++ .../OpenHABWatchUITests.swift | 55 ++ 136 files changed, 1980 insertions(+), 1620 deletions(-) create mode 100644 openHAB.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved delete mode 100644 openHABWatch Extension/ExtensionDelegate.swift delete mode 100644 openHABWatch Extension/HostingController.swift delete mode 100644 openHABWatch Extension/OpenHABWatchTracker.swift delete mode 100644 openHABWatch Extension/PreferencesHostingController.swift delete mode 100644 openHABWatch Extension/Views/PreferencesSwiftUIView.swift delete mode 100644 openHABWatch Extension/Views/Rows/FrameRow.swift delete mode 100644 openHABWatch Extension/Views/Rows/ImageRow.swift delete mode 100644 openHABWatch Extension/Views/Rows/SegmentRow.swift delete mode 100644 openHABWatch Extension/Views/Rows/SliderRow.swift delete mode 100644 openHABWatch Extension/Views/Utils/IconView.swift delete mode 100644 openHABWatch Extension/Views/Utils/Unwrap.swift delete mode 100644 openHABWatch Extension/openHABWatch Extension/UserData.swift delete mode 100644 openHABWatch Extension/openHABWatch Extension/app/AppState.swift delete mode 100644 openHABWatch/Assets.xcassets/AppIcon.appiconset/Icon-24@2x.png delete mode 100644 openHABWatch/Assets.xcassets/AppIcon.appiconset/Icon-27.5@2x.png delete mode 100644 openHABWatch/Assets.xcassets/AppIcon.appiconset/Icon-29@2x.png delete mode 100644 openHABWatch/Assets.xcassets/AppIcon.appiconset/Icon-29@3x.png delete mode 100644 openHABWatch/Assets.xcassets/AppIcon.appiconset/Icon-40@2x.png delete mode 100644 openHABWatch/Assets.xcassets/AppIcon.appiconset/Icon-86@2x.png delete mode 100644 openHABWatch/Assets.xcassets/AppIcon.appiconset/Icon-98@2x.png create mode 100644 openHABWatch/Assets.xcassets/AppIcon.appiconset/ItunesArtwork@2x 1.png delete mode 100644 openHABWatch/Assets.xcassets/AppIcon.appiconset/icon-100.png delete mode 100644 openHABWatch/Assets.xcassets/AppIcon.appiconset/icon-216@2x.png delete mode 100644 openHABWatch/Assets.xcassets/AppIcon.appiconset/icon-88.png create mode 100644 openHABWatch/Domain/UserData.swift rename {openHABWatch Extension => openHABWatch/Extension}/Assets.xcassets/Complication.complicationset/Circular.imageset/Contents.json (100%) rename {openHABWatch Extension/openHABWatch Extension => openHABWatch/Extension}/Assets.xcassets/Complication.complicationset/Contents.json (84%) rename {openHABWatch Extension => openHABWatch/Extension}/Assets.xcassets/Complication.complicationset/Extra Large.imageset/Contents.json (100%) rename {openHABWatch Extension => openHABWatch/Extension}/Assets.xcassets/Complication.complicationset/Graphic Bezel.imageset/Contents.json (100%) rename {openHABWatch Extension => openHABWatch/Extension}/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/Contents.json (100%) rename {openHABWatch Extension => openHABWatch/Extension}/Assets.xcassets/Complication.complicationset/Graphic Corner.imageset/Contents.json (100%) create mode 100644 openHABWatch/Extension/Assets.xcassets/Complication.complicationset/Graphic Extra Large.imageset/Contents.json rename {openHABWatch Extension => openHABWatch/Extension}/Assets.xcassets/Complication.complicationset/Graphic Large Rectangular.imageset/Contents.json (100%) rename {openHABWatch Extension => openHABWatch/Extension}/Assets.xcassets/Complication.complicationset/Modular.imageset/Contents.json (100%) rename {openHABWatch Extension => openHABWatch/Extension}/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json (100%) rename {openHABWatch Extension => openHABWatch/Extension}/Assets.xcassets/Contents.json (100%) rename {openHABWatch Extension => openHABWatch/Extension}/Assets.xcassets/OHIcon.imageset/Contents.json (100%) rename {openHABWatch Extension => openHABWatch/Extension}/Assets.xcassets/OHIcon.imageset/Icon.png (100%) rename {openHABWatch Extension => openHABWatch/Extension}/Assets.xcassets/OHTemplateIcon.imageset/Contents.json (100%) rename {openHABWatch Extension => openHABWatch/Extension}/Assets.xcassets/OHTemplateIcon.imageset/oh_logo_template.pdf (100%) rename {openHABWatch Extension => openHABWatch/Extension}/ComplicationController.swift (100%) rename {openHABWatch Extension => openHABWatch/Extension}/Info.plist (96%) rename {openHABWatch Extension => openHABWatch/Extension}/NotificationController.swift (100%) rename {openHABWatch Extension => openHABWatch/Extension}/NotificationView.swift (78%) create mode 100644 openHABWatch/Extension/OpenHABImageDownloaderOperation.swift create mode 100644 openHABWatch/Extension/OpenHABWatchAppDelegate.swift rename {openHABWatch Extension => openHABWatch/Extension}/PushNotificationPayload.apns (72%) rename {openHABWatch Extension => openHABWatch/Extension}/UserDefaultsExtension.swift (87%) rename {openHABWatch Extension => openHABWatch/Extension}/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Contents.json (100%) rename {openHABWatch Extension => openHABWatch/Extension}/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Icon-32@2x.png (100%) rename {openHABWatch Extension => openHABWatch/Extension}/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Icon-36@2x.png (100%) rename {openHABWatch Extension => openHABWatch/Extension/openHABWatch Extension}/Assets.xcassets/Complication.complicationset/Contents.json (100%) rename {openHABWatch Extension => openHABWatch/Extension}/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Extra Large.imageset/Contents.json (100%) rename {openHABWatch Extension => openHABWatch/Extension}/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Graphic Bezel.imageset/Contents.json (100%) rename {openHABWatch Extension => openHABWatch/Extension}/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/Contents.json (100%) rename {openHABWatch Extension => openHABWatch/Extension}/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/openhab84.png (100%) rename {openHABWatch Extension => openHABWatch/Extension}/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/openhab94.png (100%) rename {openHABWatch Extension => openHABWatch/Extension}/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Graphic Corner.imageset/Contents.json (100%) rename {openHABWatch Extension => openHABWatch/Extension}/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Graphic Large Rectangular.imageset/Contents.json (100%) rename {openHABWatch Extension => openHABWatch/Extension}/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Contents.json (100%) rename {openHABWatch Extension => openHABWatch/Extension}/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Icon-52@2x.png (100%) rename {openHABWatch Extension => openHABWatch/Extension}/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Icon-58@2x.png (100%) rename {openHABWatch Extension => openHABWatch/Extension}/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json (100%) rename {openHABWatch Extension => openHABWatch/Extension}/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Icon-40@2x.png (100%) rename {openHABWatch Extension => openHABWatch/Extension}/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Icon-44@2x.png (100%) rename {openHABWatch Extension => openHABWatch/Extension}/openHABWatch Extension/Assets.xcassets/Contents.json (100%) rename {openHABWatch Extension => openHABWatch/Extension}/openHABWatch Extension/ButtonTableRowController.swift (100%) rename {openHABWatch Extension => openHABWatch/Extension}/openHABWatch Extension/ComplicationController.swift (100%) rename {openHABWatch Extension => openHABWatch/Extension}/openHABWatch Extension/ExtensionDelegate.swift (100%) rename {openHABWatch Extension => openHABWatch/Extension}/openHABWatch Extension/Info.plist (100%) rename {openHABWatch Extension => openHABWatch/Extension}/openHABWatch Extension/InterfaceController.swift (100%) rename {openHABWatch Extension => openHABWatch/Extension}/openHABWatch Extension/NotificationController.swift (100%) rename {openHABWatch Extension => openHABWatch/Extension}/openHABWatch Extension/PrefsInterfaceController.swift (100%) rename {openHABWatch Extension => openHABWatch/Extension}/openHABWatch Extension/PushNotificationPayload.apns (100%) rename {openHABWatch Extension => openHABWatch/Extension}/openHABWatch Extension/UserDefaultsExtension.swift (100%) rename {openHABWatch Extension => openHABWatch/Extension}/openHABWatch Extension/external/OpenHabService.swift (100%) rename {openHABWatch Extension/openHABWatch Extension/external => openHABWatch/External}/AppMessageService.swift (78%) rename {openHABWatch Extension/openHABWatch Extension => openHABWatch}/Model/LazyView.swift (100%) rename {openHABWatch Extension/openHABWatch Extension => openHABWatch}/Model/ObservableOpenHABDataObject.swift (88%) rename {openHABWatch Extension/openHABWatch Extension => openHABWatch}/Model/ObservableOpenHABSitemapPage.swift (100%) rename {openHABWatch Extension/openHABWatch Extension => openHABWatch}/Model/ObservableOpenHABWidget.swift (100%) rename {openHABWatch Extension/openHABWatch Extension => openHABWatch}/Model/ObservableOpenHABWidgetExtension.swift (83%) rename {openHABWatch Extension/openHABWatch Extension => openHABWatch}/Model/UserDefaultsBacked.swift (94%) create mode 100644 openHABWatch/OpenHABWatch.swift create mode 100644 openHABWatch/Preview Content/Preview Assets.xcassets/Contents.json rename {openHABWatch Extension => openHABWatch}/Views/ContentView.swift (84%) create mode 100644 openHABWatch/Views/PreferencesSwiftUIView.swift rename {openHABWatch Extension => openHABWatch}/Views/Rows/ColorPickerRow.swift (84%) create mode 100644 openHABWatch/Views/Rows/FrameRow.swift rename {openHABWatch Extension => openHABWatch}/Views/Rows/GenericRow.swift (75%) rename {openHABWatch Extension => openHABWatch}/Views/Rows/ImageRawRow.swift (77%) create mode 100644 openHABWatch/Views/Rows/ImageRow.swift rename {openHABWatch Extension => openHABWatch}/Views/Rows/MapViewRow.swift (73%) rename {openHABWatch Extension => openHABWatch}/Views/Rows/RollershutterRow.swift (69%) create mode 100644 openHABWatch/Views/Rows/SegmentRow.swift rename {openHABWatch Extension => openHABWatch}/Views/Rows/SetpointRow.swift (86%) create mode 100644 openHABWatch/Views/Rows/SliderRow.swift rename {openHABWatch Extension => openHABWatch}/Views/Rows/SliderWithSwitchSupportRow.swift (85%) rename {openHABWatch Extension => openHABWatch}/Views/Rows/SwitchRow.swift (51%) rename {openHABWatch Extension => openHABWatch}/Views/Utils/Color+Extension.swift (100%) rename {openHABWatch Extension => openHABWatch}/Views/Utils/ColorSelection.swift (97%) rename {openHABWatch Extension => openHABWatch}/Views/Utils/DetailTextLabelView.swift (73%) create mode 100644 openHABWatch/Views/Utils/IconView.swift rename openHABWatch Extension/Views/Utils/EncircledIconWithAction.swift => openHABWatch/Views/Utils/IconWithAction.swift (76%) rename openHABWatch Extension/Views/Rows/PreferencesRowUIView.swift => openHABWatch/Views/Utils/ImageWithAction.swift (52%) rename {openHABWatch Extension => openHABWatch}/Views/Utils/MapView.swift (82%) rename {openHABWatch Extension => openHABWatch}/Views/Utils/PreviewConstants.swift (98%) rename {openHABWatch Extension => openHABWatch}/Views/Utils/TextLabelView.swift (79%) delete mode 100644 openHABWatch/openHABWatch.entitlements create mode 100644 openHABWatchSwiftUI Watch AppTests/OpenHABWatchAppTests.swift create mode 100644 openHABWatchSwiftUI Watch AppUITests/OpenHABWatchLaunchTests.swift create mode 100644 openHABWatchSwiftUI Watch AppUITests/OpenHABWatchUITests.swift diff --git a/.gitignore b/.gitignore index b449fc8f4..2f6482f77 100644 --- a/.gitignore +++ b/.gitignore @@ -17,4 +17,6 @@ openHAB.ipa build/ BuildTools/.build OpenHABCore/Package.resolved + +swift-openapi-generator/ OpenHABCore/swift-openapi-generator/ diff --git a/BuildTools/.swiftformat b/BuildTools/.swiftformat index 02b391a94..39e42a458 100644 --- a/BuildTools/.swiftformat +++ b/BuildTools/.swiftformat @@ -2,6 +2,7 @@ --exclude ../fastlane --exclude ../OpenHABCore/.build --exclude ./build +--exclude ../OpenHABCore/swift-openapi-generator --symlinks ignore # disabled rules diff --git a/BuildTools/Package.resolved b/BuildTools/Package.resolved index 8fc218a3c..75f44d322 100644 --- a/BuildTools/Package.resolved +++ b/BuildTools/Package.resolved @@ -5,8 +5,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/weakfl/SwiftFormatPlugin", "state" : { - "revision" : "29d6c0bc4c078f819504d92fb5b359e63fd32046", - "version" : "0.53.2" + "revision" : "65e4f4aaba165f03f311bd1472b771988f11828e", + "version" : "0.54.3" } }, { diff --git a/BuildTools/Package.swift b/BuildTools/Package.swift index 22d14bb4b..7699a1ec8 100644 --- a/BuildTools/Package.swift +++ b/BuildTools/Package.swift @@ -5,7 +5,7 @@ let package = Package( name: "BuildTools", platforms: [.macOS(.v10_13)], dependencies: [ - .package(url: "https://github.com/weakfl/SwiftFormatPlugin", exact: "0.53.2"), + .package(url: "https://github.com/weakfl/SwiftFormatPlugin", exact: "0.54.3"), .package(url: "https://github.com/weakfl/SwiftLintPlugin.git", exact: "0.54.0") ], targets: [ diff --git a/OpenHABCore/Sources/OpenHABCore/Model/OpenHABWidget.swift b/OpenHABCore/Sources/OpenHABCore/Model/OpenHABWidget.swift index f0fe55112..028cd555a 100644 --- a/OpenHABCore/Sources/OpenHABCore/Model/OpenHABWidget.swift +++ b/OpenHABCore/Sources/OpenHABCore/Model/OpenHABWidget.swift @@ -9,7 +9,6 @@ // // SPDX-License-Identifier: EPL-2.0 -import Alamofire import Foundation import MapKit import os.log diff --git a/OpenHABCore/Sources/OpenHABCore/Util/ClientCertificateManager.swift b/OpenHABCore/Sources/OpenHABCore/Util/ClientCertificateManager.swift index 42cbadc5c..591dfe31b 100644 --- a/OpenHABCore/Sources/OpenHABCore/Util/ClientCertificateManager.swift +++ b/OpenHABCore/Sources/OpenHABCore/Util/ClientCertificateManager.swift @@ -13,7 +13,7 @@ import Foundation import os.log import Security -public protocol ClientCertificateManagerDelegate: NSObjectProtocol { +public protocol ClientCertificateManagerDelegate: AnyObject { // delegate should ask user for a decision on whether to import the client certificate into the keychain func askForClientCertificateImport(_ clientCertificateManager: ClientCertificateManager?) // delegate should ask user for the export password used to decode the PKCS#12 diff --git a/OpenHABCore/Sources/OpenHABCore/Util/NetworkTracker.swift b/OpenHABCore/Sources/OpenHABCore/Util/NetworkTracker.swift index 21b7a5ab7..2ada699fb 100644 --- a/OpenHABCore/Sources/OpenHABCore/Util/NetworkTracker.swift +++ b/OpenHABCore/Sources/OpenHABCore/Util/NetworkTracker.swift @@ -71,6 +71,7 @@ public final class NetworkTracker: ObservableObject { public func startTracking(connectionConfigurations: [ConnectionConfiguration], username: String, password: String, alwaysSendBasicAuth: Bool) { self.connectionConfigurations = connectionConfigurations httpClient = HTTPClient(username: username, password: password, alwaysSendBasicAuth: alwaysSendBasicAuth) + setActiveConnection(nil) attemptConnection() } diff --git a/OpenHABCore/Sources/OpenHABCore/Util/Preferences.swift b/OpenHABCore/Sources/OpenHABCore/Util/Preferences.swift index 379471de7..3ccc9f59a 100644 --- a/OpenHABCore/Sources/OpenHABCore/Util/Preferences.swift +++ b/OpenHABCore/Sources/OpenHABCore/Util/Preferences.swift @@ -113,6 +113,7 @@ public enum Preferences { @UserDefault("sortSitemapsBy", defaultValue: 0) public static var sortSitemapsby: Int @UserDefault("defaultMainUIPath", defaultValue: "") public static var defaultMainUIPath: String @UserDefault("alwaysAllowWebRTC", defaultValue: false) public static var alwaysAllowWebRTC: Bool + @UserDefault("sitemapForWatch", defaultValue: "watch") public static var sitemapForWatch: String // MARK: - Private diff --git a/OpenHABCore/Tests/OpenHABCoreTests/UserDefaultsTests.swift b/OpenHABCore/Tests/OpenHABCoreTests/UserDefaultsTests.swift index 4e62de2ca..da317cb1a 100644 --- a/OpenHABCore/Tests/OpenHABCoreTests/UserDefaultsTests.swift +++ b/OpenHABCore/Tests/OpenHABCoreTests/UserDefaultsTests.swift @@ -30,6 +30,7 @@ final class UserDefaultsTests: XCTestCase { Preferences.idleOff = Preferences.idleOff Preferences.iconType = Preferences.iconType Preferences.defaultSitemap = Preferences.defaultSitemap + Preferences.sitemapForWatch = Preferences.sitemapForWatch } // Testing the consistency between properties of Preferences and the corresponding entry in UserDefaults @@ -45,5 +46,6 @@ final class UserDefaultsTests: XCTestCase { XCTAssertEqual(Preferences.idleOff, data.bool(forKey: "idleOff")) XCTAssertEqual(Preferences.iconType, data.integer(forKey: "iconType")) XCTAssertEqual(Preferences.defaultSitemap, data.string(forKey: "defaultSitemap")) + XCTAssertEqual(Preferences.sitemapForWatch, data.string(forKey: "sitemapForWatch")) } } diff --git a/openHAB.xcodeproj/project.pbxproj b/openHAB.xcodeproj/project.pbxproj index 64f59ac3e..6a53d6b96 100644 --- a/openHAB.xcodeproj/project.pbxproj +++ b/openHAB.xcodeproj/project.pbxproj @@ -66,16 +66,12 @@ 93F8064A27AE7A2E0035A6B0 /* FlexColorPicker in Frameworks */ = {isa = PBXBuildFile; productRef = 93F8064927AE7A2E0035A6B0 /* FlexColorPicker */; }; 93F8065027AE7A830035A6B0 /* SideMenu in Frameworks */ = {isa = PBXBuildFile; productRef = 93F8064F27AE7A830035A6B0 /* SideMenu */; }; 93F8065327AE7B580035A6B0 /* SVGKit in Frameworks */ = {isa = PBXBuildFile; productRef = 93F8065227AE7B580035A6B0 /* SVGKit */; }; - A07ED02E2402EE6E006588FE /* OpenHABWatchTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = A07ED02D2402EE6E006588FE /* OpenHABWatchTracker.swift */; }; A3F4C3A51A49A5940019A09F /* MainLaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = A3F4C3A41A49A5940019A09F /* MainLaunchScreen.xib */; }; B7D5ECE121499E55001B0EC6 /* MapViewTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7D5ECE021499E55001B0EC6 /* MapViewTableViewCell.swift */; }; DA0749DE23E0B5950057FA83 /* ColorPickerRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA0749DD23E0B5950057FA83 /* ColorPickerRow.swift */; }; DA0749E023E0BF510057FA83 /* ColorSelection.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA0749DF23E0BF510057FA83 /* ColorSelection.swift */; }; - DA0775192346705D0086C685 /* Interface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DA0775172346705D0086C685 /* Interface.storyboard */; }; DA07751B2346705F0086C685 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DA07751A2346705F0086C685 /* Assets.xcassets */; }; - DA0775272346705F0086C685 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA0775262346705F0086C685 /* ContentView.swift */; }; - DA0775292346705F0086C685 /* HostingController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA0775282346705F0086C685 /* HostingController.swift */; }; - DA07752B2346705F0086C685 /* ExtensionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA07752A2346705F0086C685 /* ExtensionDelegate.swift */; }; + DA07752B2346705F0086C685 /* OpenHABWatchAppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA07752A2346705F0086C685 /* OpenHABWatchAppDelegate.swift */; }; DA07752D2346705F0086C685 /* NotificationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA07752C2346705F0086C685 /* NotificationController.swift */; }; DA07752F2346705F0086C685 /* NotificationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA07752E2346705F0086C685 /* NotificationView.swift */; }; DA0775312346705F0086C685 /* ComplicationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA0775302346705F0086C685 /* ComplicationController.swift */; }; @@ -87,10 +83,15 @@ DA21EAE22339621C001AB415 /* Throttler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA21EAE12339621C001AB415 /* Throttler.swift */; }; DA242C622C83588600AFB10D /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA242C612C83588600AFB10D /* SettingsView.swift */; }; DA28C362225241DE00AB409C /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA28C361225241DE00AB409C /* WebKit.framework */; settings = {ATTRIBUTES = (Required, ); }; }; + DA2C4FCD2B4F55D700D1C533 /* SDWebImage in Frameworks */ = {isa = PBXBuildFile; productRef = DA2C4FCC2B4F55D700D1C533 /* SDWebImage */; }; + DA2C4FCF2B4F55D700D1C533 /* SDWebImageMapKit in Frameworks */ = {isa = PBXBuildFile; productRef = DA2C4FCE2B4F55D700D1C533 /* SDWebImageMapKit */; }; + DA2C4FD22B4F56D000D1C533 /* SDWebImageSwiftUI in Frameworks */ = {isa = PBXBuildFile; productRef = DA2C4FD12B4F56D000D1C533 /* SDWebImageSwiftUI */; }; + DA2C4FD52B4F573300D1C533 /* SDWebImageSVGCoder in Frameworks */ = {isa = PBXBuildFile; productRef = DA2C4FD42B4F573300D1C533 /* SDWebImageSVGCoder */; }; DA2DC23221F2736C00830730 /* OpenHABJSONParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA2DC23121F2736C00830730 /* OpenHABJSONParserTests.swift */; }; - DA2E0AA423DC96E9009B0A99 /* EncircledIconWithAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA2E0AA323DC96E9009B0A99 /* EncircledIconWithAction.swift */; }; + DA2E0AA423DC96E9009B0A99 /* ImageWithAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA2E0AA323DC96E9009B0A99 /* ImageWithAction.swift */; }; DA2E0B0E23DCC153009B0A99 /* MapView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA2E0B0D23DCC152009B0A99 /* MapView.swift */; }; DA2E0B1023DCC439009B0A99 /* MapViewRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA2E0B0F23DCC439009B0A99 /* MapViewRow.swift */; }; + DA32D1B42C8C98C40018D974 /* IconWithAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA32D1B32C8C98C40018D974 /* IconWithAction.swift */; }; DA3B75AE2C59741800E219AB /* SFSafeSymbols in Frameworks */ = {isa = PBXBuildFile; productRef = DA3B75AD2C59741800E219AB /* SFSafeSymbols */; }; DA3B75B02C59742A00E219AB /* SFSafeSymbols in Frameworks */ = {isa = PBXBuildFile; productRef = DA3B75AF2C59742A00E219AB /* SFSafeSymbols */; }; DA4D4DB5233F9ACB00B37E37 /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = DA4D4DB4233F9ACB00B37E37 /* README.md */; }; @@ -99,28 +100,31 @@ DA5ED9BE2C850955004875E0 /* ClientCertificatesViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA5ED9BD2C850955004875E0 /* ClientCertificatesViewModel.swift */; }; DA5ED9C02C8509C2004875E0 /* ClientCertificatesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA5ED9BF2C8509C2004875E0 /* ClientCertificatesView.swift */; }; DA65871F236F83CE007E2E7F /* UserDefaultsExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA65871E236F83CD007E2E7F /* UserDefaultsExtension.swift */; }; - DA6587222370C9D8007E2E7F /* PreferencesHostingController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA6587212370C9D8007E2E7F /* PreferencesHostingController.swift */; }; DA6B2EEF2C861BC900DF77CF /* DrawerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA6B2EEE2C861BC900DF77CF /* DrawerView.swift */; }; DA6B2EF12C87B59000DF77CF /* NotificationsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA6B2EF02C87B59000DF77CF /* NotificationsView.swift */; }; DA6B2EF52C89F8F200DF77CF /* ColorPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA6B2EF42C89F8F200DF77CF /* ColorPickerView.swift */; }; DA6B2EF72C8B92E800DF77CF /* SelectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA6B2EF62C8B92E800DF77CF /* SelectionView.swift */; }; DA7224D223828D3400712D20 /* PreviewConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA7224D123828D3300712D20 /* PreviewConstants.swift */; }; DA72E1B8236DEA0900B8EF3A /* AppMessageService.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA72E1B5236DEA0900B8EF3A /* AppMessageService.swift */; }; - DA7649DE23FC81A20085CE46 /* Unwrap.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA7649DD23FC81A20085CE46 /* Unwrap.swift */; }; DA7E1E4B2233986E002AEFD8 /* PlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA7E1E47222EB00B002AEFD8 /* PlayerView.swift */; }; DA817E7A234BF39B00C91824 /* CHANGELOG.md in Resources */ = {isa = PBXBuildFile; fileRef = DA817E79234BF39B00C91824 /* CHANGELOG.md */; }; DA88F8C622EC377200B408E5 /* ReleaseNotes.md in Resources */ = {isa = PBXBuildFile; fileRef = DA88F8C522EC377100B408E5 /* ReleaseNotes.md */; }; DA9721C324E29A8F0092CCFD /* UserDefaultsBacked.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9721C224E29A8F0092CCFD /* UserDefaultsBacked.swift */; }; DA9F81872C85020F00B47B72 /* RTFTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9F81862C85020F00B47B72 /* RTFTextView.swift */; }; + DAA070932B5181210060BB0E /* OpenHABImageDownloaderOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAA070922B5181210060BB0E /* OpenHABImageDownloaderOperation.swift */; }; DAA42BA821DC97E000244B2A /* NotificationTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAA42BA721DC97DF00244B2A /* NotificationTableViewCell.swift */; }; DAA42BAA21DC983B00244B2A /* VideoUITableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAA42BA921DC983B00244B2A /* VideoUITableViewCell.swift */; }; DAA42BAC21DC984A00244B2A /* WebUITableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAA42BAB21DC984A00244B2A /* WebUITableViewCell.swift */; }; + DAAC30872CBBF0420041927F /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA0775262346705F0086C685 /* ContentView.swift */; }; DAC65FC7236EDF3900F4501E /* SpinnerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAC65FC6236EDF3900F4501E /* SpinnerViewController.swift */; }; DAC6608D236F771600F4501E /* PreferencesSwiftUIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAC6608C236F771600F4501E /* PreferencesSwiftUIView.swift */; }; - DAC6608F236F80BA00F4501E /* PreferencesRowUIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAC6608E236F80BA00F4501E /* PreferencesRowUIView.swift */; }; DAC9395522B00E7600C5F423 /* XCTestCaseExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAC9395422B00E7600C5F423 /* XCTestCaseExtension.swift */; }; DAC9AF4724F9669F006DAE93 /* ObservableOpenHABWidgetExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAC9AF4624F9669F006DAE93 /* ObservableOpenHABWidgetExtension.swift */; }; DAC9AF4924F966FA006DAE93 /* LazyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAC9AF4824F966FA006DAE93 /* LazyView.swift */; }; + DAD085712AE4782D001D36BE /* OpenHABWatchAppTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAD085702AE4782D001D36BE /* OpenHABWatchAppTests.swift */; }; + DAD0857B2AE4782F001D36BE /* OpenHABWatchUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAD0857A2AE4782F001D36BE /* OpenHABWatchUITests.swift */; }; + DAD0857D2AE4782F001D36BE /* OpenHABWatchLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAD0857C2AE4782F001D36BE /* OpenHABWatchLaunchTests.swift */; }; + DAD0858B2AE56F0E001D36BE /* OpenHABWatch.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAD0855F2AE47824001D36BE /* OpenHABWatch.swift */; }; DAEAA89D21E6B06400267EA3 /* ReusableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAEAA89C21E6B06300267EA3 /* ReusableView.swift */; }; DAEAA89F21E6B16600267EA3 /* UITableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAEAA89E21E6B16600267EA3 /* UITableView.swift */; }; DAF0A28B2C56E3A300A14A6A /* RollershutterCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAF0A28A2C56E3A300A14A6A /* RollershutterCell.swift */; }; @@ -139,7 +143,6 @@ DAF457A223DB6C640018B495 /* RollershutterRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAF457A123DB6C640018B495 /* RollershutterRow.swift */; }; DAF457A623DB9CE00018B495 /* SetpointRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAF457A523DB9CE00018B495 /* SetpointRow.swift */; }; DAF457A923DBA4990018B495 /* FrameRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAF457A823DBA4990018B495 /* FrameRow.swift */; }; - DAF4581423DC1F5D0018B495 /* AppState.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA72E1B0236DE9F200B8EF3A /* AppState.swift */; }; DAF4581623DC48400018B495 /* GenericRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAF4581523DC483F0018B495 /* GenericRow.swift */; }; DAF4581823DC4A050018B495 /* ImageRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAF4581723DC4A050018B495 /* ImageRow.swift */; }; DAF4581E23DC60020018B495 /* ImageRawRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAF4581D23DC60020018B495 /* ImageRawRow.swift */; }; @@ -201,6 +204,20 @@ remoteGlobalIDString = DFB2622618830A3600D3244D; remoteInfo = openHAB; }; + DAA0708C2B504B280060BB0E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DFB2621F18830A3600D3244D /* Project object */; + proxyType = 1; + remoteGlobalIDString = DA0775142346705D0086C685; + remoteInfo = openHABWatch; + }; + DAA0708E2B504B2C0060BB0E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DFB2621F18830A3600D3244D /* Project object */; + proxyType = 1; + remoteGlobalIDString = DA0775142346705D0086C685; + remoteInfo = openHABWatch; + }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -311,18 +328,15 @@ 938BF9CF24EFCCC000E6B52F /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/InfoPlist.strings; sourceTree = ""; }; 938BF9D224EFD0B700E6B52F /* UIViewController+Localization.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+Localization.swift"; sourceTree = ""; }; 938EDCE022C4FEB800661CA1 /* ScaleAspectFitImageView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScaleAspectFitImageView.swift; sourceTree = ""; }; - A07ED02D2402EE6E006588FE /* OpenHABWatchTracker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = OpenHABWatchTracker.swift; path = "openHABWatch Extension/OpenHABWatchTracker.swift"; sourceTree = SOURCE_ROOT; }; A3F4C3A41A49A5940019A09F /* MainLaunchScreen.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = MainLaunchScreen.xib; path = ../MainLaunchScreen.xib; sourceTree = ""; }; B7D5ECE021499E55001B0EC6 /* MapViewTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapViewTableViewCell.swift; sourceTree = ""; }; DA0749DD23E0B5950057FA83 /* ColorPickerRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorPickerRow.swift; sourceTree = ""; }; DA0749DF23E0BF510057FA83 /* ColorSelection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorSelection.swift; sourceTree = ""; }; DA0775152346705D0086C685 /* openHABWatch.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = openHABWatch.app; sourceTree = BUILT_PRODUCTS_DIR; }; - DA0775182346705D0086C685 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Interface.storyboard; sourceTree = ""; }; DA07751A2346705F0086C685 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; DA07751C2346705F0086C685 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; DA0775262346705F0086C685 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; - DA0775282346705F0086C685 /* HostingController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HostingController.swift; sourceTree = ""; }; - DA07752A2346705F0086C685 /* ExtensionDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionDelegate.swift; sourceTree = ""; }; + DA07752A2346705F0086C685 /* OpenHABWatchAppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenHABWatchAppDelegate.swift; sourceTree = ""; }; DA07752C2346705F0086C685 /* NotificationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationController.swift; sourceTree = ""; }; DA07752E2346705F0086C685 /* NotificationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationView.swift; sourceTree = ""; }; DA0775302346705F0086C685 /* ComplicationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComplicationController.swift; sourceTree = ""; }; @@ -372,9 +386,10 @@ DA2DC22F21F2736C00830730 /* openHABTestsSwift.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = openHABTestsSwift.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; DA2DC23121F2736C00830730 /* OpenHABJSONParserTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenHABJSONParserTests.swift; sourceTree = ""; }; DA2DC23321F2736C00830730 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - DA2E0AA323DC96E9009B0A99 /* EncircledIconWithAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncircledIconWithAction.swift; sourceTree = ""; }; + DA2E0AA323DC96E9009B0A99 /* ImageWithAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageWithAction.swift; sourceTree = ""; }; DA2E0B0D23DCC152009B0A99 /* MapView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MapView.swift; sourceTree = ""; }; DA2E0B0F23DCC439009B0A99 /* MapViewRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapViewRow.swift; sourceTree = ""; }; + DA32D1B32C8C98C40018D974 /* IconWithAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconWithAction.swift; sourceTree = ""; }; DA4D4DB4233F9ACB00B37E37 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; DA4D4E0E2340A00200B37E37 /* Changes.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = Changes.md; sourceTree = ""; }; DA50C7BC2B0A51BD0009F716 /* SliderWithSwitchSupportRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SliderWithSwitchSupportRow.swift; sourceTree = ""; }; @@ -382,34 +397,36 @@ DA5ED9BD2C850955004875E0 /* ClientCertificatesViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientCertificatesViewModel.swift; sourceTree = ""; }; DA5ED9BF2C8509C2004875E0 /* ClientCertificatesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientCertificatesView.swift; sourceTree = ""; }; DA65871E236F83CD007E2E7F /* UserDefaultsExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefaultsExtension.swift; sourceTree = ""; }; - DA6587212370C9D8007E2E7F /* PreferencesHostingController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesHostingController.swift; sourceTree = ""; }; DA6B2EEE2C861BC900DF77CF /* DrawerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DrawerView.swift; sourceTree = ""; }; DA6B2EF02C87B59000DF77CF /* NotificationsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsView.swift; sourceTree = ""; }; DA6B2EF42C89F8F200DF77CF /* ColorPickerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorPickerView.swift; sourceTree = ""; }; DA6B2EF62C8B92E800DF77CF /* SelectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectionView.swift; sourceTree = ""; }; DA7224D123828D3300712D20 /* PreviewConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreviewConstants.swift; sourceTree = ""; }; - DA72E1B0236DE9F200B8EF3A /* AppState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AppState.swift; path = "openHABWatch Extension/app/AppState.swift"; sourceTree = ""; }; - DA72E1B5236DEA0900B8EF3A /* AppMessageService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AppMessageService.swift; path = "openHABWatch Extension/external/AppMessageService.swift"; sourceTree = ""; }; - DA7649DD23FC81A20085CE46 /* Unwrap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Unwrap.swift; sourceTree = ""; }; + DA72E1B5236DEA0900B8EF3A /* AppMessageService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppMessageService.swift; sourceTree = ""; }; DA7E1E47222EB00B002AEFD8 /* PlayerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerView.swift; sourceTree = ""; }; - DA7EB1C3259BC8C00072A7D9 /* openHABWatch.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = openHABWatch.entitlements; sourceTree = ""; }; - DA7EB1C4259BC9230072A7D9 /* openHABWatch Extension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "openHABWatch Extension.entitlements"; sourceTree = ""; }; DA817E79234BF39B00C91824 /* CHANGELOG.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = CHANGELOG.md; sourceTree = ""; }; DA88F8C522EC377100B408E5 /* ReleaseNotes.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = ReleaseNotes.md; sourceTree = ""; }; DA9721C224E29A8F0092CCFD /* UserDefaultsBacked.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefaultsBacked.swift; sourceTree = ""; }; DA9F81862C85020F00B47B72 /* RTFTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RTFTextView.swift; sourceTree = ""; }; + DAA070922B5181210060BB0E /* OpenHABImageDownloaderOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenHABImageDownloaderOperation.swift; sourceTree = ""; }; DAA42BA721DC97DF00244B2A /* NotificationTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NotificationTableViewCell.swift; sourceTree = ""; }; DAA42BA921DC983B00244B2A /* VideoUITableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VideoUITableViewCell.swift; sourceTree = ""; }; DAA42BAB21DC984A00244B2A /* WebUITableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebUITableViewCell.swift; sourceTree = ""; }; DAC65FC6236EDF3900F4501E /* SpinnerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpinnerViewController.swift; sourceTree = ""; }; DAC6608B236F6F4200F4501E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; DAC6608C236F771600F4501E /* PreferencesSwiftUIView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesSwiftUIView.swift; sourceTree = ""; }; - DAC6608E236F80BA00F4501E /* PreferencesRowUIView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesRowUIView.swift; sourceTree = ""; }; DAC9394322AD4A7A00C5F423 /* OpenHABWatchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenHABWatchTests.swift; sourceTree = ""; }; DAC9395422B00E7600C5F423 /* XCTestCaseExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCTestCaseExtension.swift; sourceTree = ""; }; DAC9AF4624F9669F006DAE93 /* ObservableOpenHABWidgetExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObservableOpenHABWidgetExtension.swift; sourceTree = ""; }; DAC9AF4824F966FA006DAE93 /* LazyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LazyView.swift; sourceTree = ""; }; - DAD488B2287DDDFE00414693 /* nb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb; path = nb.lproj/Interface.strings; sourceTree = ""; }; + DACB636127D3FC6500041931 /* error.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = error.png; sourceTree = ""; }; + DAD0855F2AE47824001D36BE /* OpenHABWatch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenHABWatch.swift; sourceTree = ""; }; + DAD085662AE4782A001D36BE /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; + DAD0856C2AE4782B001D36BE /* openHABWatchSwiftUI Watch AppTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "openHABWatchSwiftUI Watch AppTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + DAD085702AE4782D001D36BE /* OpenHABWatchAppTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenHABWatchAppTests.swift; sourceTree = ""; }; + DAD085762AE4782E001D36BE /* openHABWatchSwiftUI Watch AppUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "openHABWatchSwiftUI Watch AppUITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + DAD0857A2AE4782F001D36BE /* OpenHABWatchUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenHABWatchUITests.swift; sourceTree = ""; }; + DAD0857C2AE4782F001D36BE /* OpenHABWatchLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenHABWatchLaunchTests.swift; sourceTree = ""; }; DAD488B3287DDDFE00414693 /* nb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb; path = Resources/nb.lproj/Intents.strings; sourceTree = ""; }; DAD488B4287DDDFF00414693 /* nb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb; path = nb.lproj/Localizable.strings; sourceTree = ""; }; DAD488B5287DDDFF00414693 /* nb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb; path = nb.lproj/InfoPlist.strings; sourceTree = ""; }; @@ -467,9 +484,13 @@ 937E4473270B36DD00A98C26 /* OpenHABCore in Frameworks */, 934E592B28F16EBA00162004 /* Alamofire in Frameworks */, DA3B75B02C59742A00E219AB /* SFSafeSymbols in Frameworks */, + DA2C4FD52B4F573300D1C533 /* SDWebImageSVGCoder in Frameworks */, 934E592528F16EBA00162004 /* OpenHABCore in Frameworks */, 93F8062F27AE63620035A6B0 /* Alamofire in Frameworks */, 937E448E270B37D200A98C26 /* DeviceKit in Frameworks */, + DA2C4FCF2B4F55D700D1C533 /* SDWebImageMapKit in Frameworks */, + DA2C4FCD2B4F55D700D1C533 /* SDWebImage in Frameworks */, + DA2C4FD22B4F56D000D1C533 /* SDWebImageSwiftUI in Frameworks */, 934E592928F16EBA00162004 /* DeviceKit in Frameworks */, 937E448C270B37CA00A98C26 /* Kingfisher in Frameworks */, ); @@ -506,6 +527,20 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + DAD085692AE4782A001D36BE /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DAD085732AE4782D001D36BE /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; DFB2622418830A3600D3244D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -541,23 +576,12 @@ name = Watch; sourceTree = ""; }; - 1224F7C0228A8E9A00750965 /* App */ = { - isa = PBXGroup; - children = ( - DA72E1B0236DE9F200B8EF3A /* AppState.swift */, - ); - name = App; - path = "../openHABWatch Extension"; - sourceTree = ""; - }; 1224F7C8228A8EC600750965 /* Domain */ = { isa = PBXGroup; children = ( - A07ED02D2402EE6E006588FE /* OpenHABWatchTracker.swift */, DA0776EF234788010086C685 /* UserData.swift */, ); - name = Domain; - path = "openHABWatch Extension"; + path = Domain; sourceTree = ""; }; 1224F7C9228A8ED100750965 /* External */ = { @@ -566,8 +590,8 @@ DA72E1B5236DEA0900B8EF3A /* AppMessageService.swift */, ); name = External; - path = "../openHABWatch Extension"; - sourceTree = ""; + path = openHABWatch/External; + sourceTree = SOURCE_ROOT; }; 4D6470D42561F935007B03FC /* openHABIntents */ = { isa = PBXGroup; @@ -633,33 +657,29 @@ DAC9AF4624F9669F006DAE93 /* ObservableOpenHABWidgetExtension.swift */, DAC9AF4824F966FA006DAE93 /* LazyView.swift */, ); - name = Model; - path = "openHABWatch Extension/Model"; + path = Model; sourceTree = ""; }; DA0775162346705D0086C685 /* openHABWatch */ = { isa = PBXGroup; children = ( - DA7EB1C3259BC8C00072A7D9 /* openHABWatch.entitlements */, - DA0775172346705D0086C685 /* Interface.storyboard */, + DAD0855F2AE47824001D36BE /* OpenHABWatch.swift */, + DA0775252346705F0086C685 /* Extension */, + 1224F7C9228A8ED100750965 /* External */, + 1224F7C8228A8EC600750965 /* Domain */, + 93F38D4623803731001B1451 /* Model */, + DA658720236F841F007E2E7F /* Views */, + DAD0858A2AE52126001D36BE /* Preview Content */, DA07751A2346705F0086C685 /* Assets.xcassets */, DA07751C2346705F0086C685 /* Info.plist */, ); path = openHABWatch; sourceTree = ""; }; - DA0775252346705F0086C685 /* openHABWatch Extension */ = { + DA0775252346705F0086C685 /* Extension */ = { isa = PBXGroup; children = ( - DA7EB1C4259BC9230072A7D9 /* openHABWatch Extension.entitlements */, - 1224F7C0228A8E9A00750965 /* App */, - 1224F7C8228A8EC600750965 /* Domain */, - 1224F7C9228A8ED100750965 /* External */, - 93F38D4623803731001B1451 /* Model */, - DA658720236F841F007E2E7F /* Views */, - DA0775282346705F0086C685 /* HostingController.swift */, - DA6587212370C9D8007E2E7F /* PreferencesHostingController.swift */, - DA07752A2346705F0086C685 /* ExtensionDelegate.swift */, + DA07752A2346705F0086C685 /* OpenHABWatchAppDelegate.swift */, DA07752C2346705F0086C685 /* NotificationController.swift */, DA07752E2346705F0086C685 /* NotificationView.swift */, DA0775302346705F0086C685 /* ComplicationController.swift */, @@ -667,8 +687,9 @@ DA0775372346705F0086C685 /* Info.plist */, DA65871E236F83CD007E2E7F /* UserDefaultsExtension.swift */, DA0775382346705F0086C685 /* PushNotificationPayload.apns */, + DAA070922B5181210060BB0E /* OpenHABImageDownloaderOperation.swift */, ); - path = "openHABWatch Extension"; + path = Extension; sourceTree = ""; }; DA1C2E4A230DC28F00FACFB0 /* fastlane */ = { @@ -761,9 +782,35 @@ path = Views; sourceTree = ""; }; + DAD0856F2AE4782D001D36BE /* openHABWatchSwiftUI Watch AppTests */ = { + isa = PBXGroup; + children = ( + DAD085702AE4782D001D36BE /* OpenHABWatchAppTests.swift */, + ); + path = "openHABWatchSwiftUI Watch AppTests"; + sourceTree = ""; + }; + DAD085792AE4782F001D36BE /* openHABWatchSwiftUI Watch AppUITests */ = { + isa = PBXGroup; + children = ( + DAD0857A2AE4782F001D36BE /* OpenHABWatchUITests.swift */, + DAD0857C2AE4782F001D36BE /* OpenHABWatchLaunchTests.swift */, + ); + path = "openHABWatchSwiftUI Watch AppUITests"; + sourceTree = ""; + }; + DAD0858A2AE52126001D36BE /* Preview Content */ = { + isa = PBXGroup; + children = ( + DAD085662AE4782A001D36BE /* Preview Assets.xcassets */, + ); + path = "Preview Content"; + sourceTree = ""; + }; DAE238252806E5C800196467 /* Recovered References */ = { isa = PBXGroup; children = ( + DACB636127D3FC6500041931 /* error.png */, ); name = "Recovered References"; sourceTree = ""; @@ -788,7 +835,6 @@ DAF457A123DB6C640018B495 /* RollershutterRow.swift */, DAF4579F23DA3E1C0018B495 /* SegmentRow.swift */, DAF457A523DB9CE00018B495 /* SetpointRow.swift */, - DAC6608E236F80BA00F4501E /* PreferencesRowUIView.swift */, DAF457A823DBA4990018B495 /* FrameRow.swift */, DAF4581523DC483F0018B495 /* GenericRow.swift */, DAF4581723DC4A050018B495 /* ImageRow.swift */, @@ -807,10 +853,10 @@ DAF4578123D630C70018B495 /* IconView.swift */, DAF4578623D798A50018B495 /* TextLabelView.swift */, DAF4578823D79AA50018B495 /* DetailTextLabelView.swift */, - DA2E0AA323DC96E9009B0A99 /* EncircledIconWithAction.swift */, + DA2E0AA323DC96E9009B0A99 /* ImageWithAction.swift */, DA2E0B0D23DCC152009B0A99 /* MapView.swift */, DA0749DF23E0BF510057FA83 /* ColorSelection.swift */, - DA7649DD23FC81A20085CE46 /* Unwrap.swift */, + DA32D1B32C8C98C40018D974 /* IconWithAction.swift */, ); path = Utils; sourceTree = ""; @@ -883,8 +929,9 @@ DA2DC23021F2736C00830730 /* openHABTestsSwift */, 933D7F0522E7015000621A03 /* openHABUITests */, DA0775162346705D0086C685 /* openHABWatch */, - DA0775252346705F0086C685 /* openHABWatch Extension */, 4D6470D42561F935007B03FC /* openHABIntents */, + DAD0856F2AE4782D001D36BE /* openHABWatchSwiftUI Watch AppTests */, + DAD085792AE4782F001D36BE /* openHABWatchSwiftUI Watch AppUITests */, 6571444F2C1E438700C8A1F3 /* NotificationService */, DFB2622818830A3600D3244D /* Products */, DFB2622918830A3600D3244D /* Frameworks */, @@ -901,6 +948,8 @@ 933D7F0422E7015000621A03 /* openHABUITests.xctest */, DA0775152346705D0086C685 /* openHABWatch.app */, 4D6470D32561F935007B03FC /* openHABIntents.appex */, + DAD0856C2AE4782B001D36BE /* openHABWatchSwiftUI Watch AppTests.xctest */, + DAD085762AE4782E001D36BE /* openHABWatchSwiftUI Watch AppUITests.xctest */, 6571444E2C1E438700C8A1F3 /* NotificationService.appex */, ); name = Products; @@ -1053,6 +1102,10 @@ 934E592828F16EBA00162004 /* DeviceKit */, 934E592A28F16EBA00162004 /* Alamofire */, DA3B75AF2C59742A00E219AB /* SFSafeSymbols */, + DA2C4FCC2B4F55D700D1C533 /* SDWebImage */, + DA2C4FCE2B4F55D700D1C533 /* SDWebImageMapKit */, + DA2C4FD12B4F56D000D1C533 /* SDWebImageSwiftUI */, + DA2C4FD42B4F573300D1C533 /* SDWebImageSVGCoder */, ); productName = openHABWatchSwift2; productReference = DA0775152346705D0086C685 /* openHABWatch.app */; @@ -1076,6 +1129,42 @@ productReference = DA2DC22F21F2736C00830730 /* openHABTestsSwift.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; + DAD0856B2AE4782A001D36BE /* openHABWatchSwiftUI Watch AppTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = DAD085842AE47831001D36BE /* Build configuration list for PBXNativeTarget "openHABWatchSwiftUI Watch AppTests" */; + buildPhases = ( + DAD085682AE4782A001D36BE /* Sources */, + DAD085692AE4782A001D36BE /* Frameworks */, + DAD0856A2AE4782A001D36BE /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + DAA0708D2B504B280060BB0E /* PBXTargetDependency */, + ); + name = "openHABWatchSwiftUI Watch AppTests"; + productName = "openHABWatchSwiftUI Watch AppTests"; + productReference = DAD0856C2AE4782B001D36BE /* openHABWatchSwiftUI Watch AppTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + DAD085752AE4782D001D36BE /* openHABWatchSwiftUI Watch AppUITests */ = { + isa = PBXNativeTarget; + buildConfigurationList = DAD085872AE47831001D36BE /* Build configuration list for PBXNativeTarget "openHABWatchSwiftUI Watch AppUITests" */; + buildPhases = ( + DAD085722AE4782D001D36BE /* Sources */, + DAD085732AE4782D001D36BE /* Frameworks */, + DAD085742AE4782D001D36BE /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + DAA0708F2B504B2C0060BB0E /* PBXTargetDependency */, + ); + name = "openHABWatchSwiftUI Watch AppUITests"; + productName = "openHABWatchSwiftUI Watch AppUITests"; + productReference = DAD085762AE4782E001D36BE /* openHABWatchSwiftUI Watch AppUITests.xctest */; + productType = "com.apple.product-type.bundle.ui-testing"; + }; DFB2622618830A3600D3244D /* openHAB */ = { isa = PBXNativeTarget; buildConfigurationList = DFB2625C18830A3600D3244D /* Build configuration list for PBXNativeTarget "openHAB" */; @@ -1145,6 +1234,14 @@ ProvisioningStyle = Automatic; TestTargetID = DFB2622618830A3600D3244D; }; + DAD0856B2AE4782A001D36BE = { + CreatedOnToolsVersion = 15.0; + TestTargetID = DA0775142346705D0086C685; + }; + DAD085752AE4782D001D36BE = { + CreatedOnToolsVersion = 15.0; + TestTargetID = DA0775142346705D0086C685; + }; DFB2622618830A3600D3244D = { LastSwiftMigration = ""; SystemCapabilities = { @@ -1195,6 +1292,9 @@ 93F8064E27AE7A820035A6B0 /* XCRemoteSwiftPackageReference "SideMenu" */, 93F8065127AE7B580035A6B0 /* XCRemoteSwiftPackageReference "SVGKit" */, DA3B75AC2C59729200E219AB /* XCRemoteSwiftPackageReference "SFSafeSymbols" */, + DA2C4FCB2B4F55D600D1C533 /* XCRemoteSwiftPackageReference "SDWebImage" */, + DA2C4FD02B4F56CF00D1C533 /* XCRemoteSwiftPackageReference "SDWebImageSwiftUI" */, + DA2C4FD32B4F573300D1C533 /* XCRemoteSwiftPackageReference "SDWebImageSVGCoder" */, ); productRefGroup = DFB2622818830A3600D3244D /* Products */; projectDirPath = ""; @@ -1205,6 +1305,8 @@ 933D7F0322E7015000621A03 /* openHABUITests */, DA0775142346705D0086C685 /* openHABWatch */, 4D6470D22561F935007B03FC /* openHABIntents */, + DAD0856B2AE4782A001D36BE /* openHABWatchSwiftUI Watch AppTests */, + DAD085752AE4782D001D36BE /* openHABWatchSwiftUI Watch AppUITests */, 6571444D2C1E438700C8A1F3 /* NotificationService */, ); }; @@ -1240,7 +1342,6 @@ 6557AF902C0241C10094D0C8 /* PrivacyInfo.xcprivacy in Resources */, DA07751B2346705F0086C685 /* Assets.xcassets in Resources */, 938BF9D524EFD5B100E6B52F /* Localizable.strings in Resources */, - DA0775192346705D0086C685 /* Interface.storyboard in Resources */, 932602EE2382892B00EAD685 /* Assets.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1256,6 +1357,20 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + DAD0856A2AE4782A001D36BE /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DAD085742AE4782D001D36BE /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; DFB2622518830A3600D3244D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -1338,40 +1453,37 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - DA7649DE23FC81A20085CE46 /* Unwrap.swift in Sources */, DAC9AF4724F9669F006DAE93 /* ObservableOpenHABWidgetExtension.swift in Sources */, - DAF4581423DC1F5D0018B495 /* AppState.swift in Sources */, DA2E0B0E23DCC153009B0A99 /* MapView.swift in Sources */, DA2E0B1023DCC439009B0A99 /* MapViewRow.swift in Sources */, DA0F37D023D4ACC7007EAB48 /* SliderRow.swift in Sources */, - DA0775292346705F0086C685 /* HostingController.swift in Sources */, + DA32D1B42C8C98C40018D974 /* IconWithAction.swift in Sources */, DA07764A234683BC0086C685 /* SwitchRow.swift in Sources */, - DA2E0AA423DC96E9009B0A99 /* EncircledIconWithAction.swift in Sources */, + DA2E0AA423DC96E9009B0A99 /* ImageWithAction.swift in Sources */, DAF4578723D798A50018B495 /* TextLabelView.swift in Sources */, DA0749DE23E0B5950057FA83 /* ColorPickerRow.swift in Sources */, - DA0775272346705F0086C685 /* ContentView.swift in Sources */, DA7224D223828D3400712D20 /* PreviewConstants.swift in Sources */, DAF4581E23DC60020018B495 /* ImageRawRow.swift in Sources */, - A07ED02E2402EE6E006588FE /* OpenHABWatchTracker.swift in Sources */, + DAD0858B2AE56F0E001D36BE /* OpenHABWatch.swift in Sources */, DAF4578223D630C70018B495 /* IconView.swift in Sources */, DA07752D2346705F0086C685 /* NotificationController.swift in Sources */, DA0749E023E0BF510057FA83 /* ColorSelection.swift in Sources */, DA65871F236F83CE007E2E7F /* UserDefaultsExtension.swift in Sources */, DA9721C324E29A8F0092CCFD /* UserDefaultsBacked.swift in Sources */, DA72E1B8236DEA0900B8EF3A /* AppMessageService.swift in Sources */, - DA07752B2346705F0086C685 /* ExtensionDelegate.swift in Sources */, + DA07752B2346705F0086C685 /* OpenHABWatchAppDelegate.swift in Sources */, DAF4581623DC48400018B495 /* GenericRow.swift in Sources */, - DAC6608F236F80BA00F4501E /* PreferencesRowUIView.swift in Sources */, 9350F17A23814FAC00054BA8 /* ObservableOpenHABSitemapPage.swift in Sources */, DAF457A023DA3E1C0018B495 /* SegmentRow.swift in Sources */, DAF4578923D79AA50018B495 /* DetailTextLabelView.swift in Sources */, + DAAC30872CBBF0420041927F /* ContentView.swift in Sources */, DA15BFBD23C6726400BD8ADA /* ObservableOpenHABDataObject.swift in Sources */, DAC9AF4924F966FA006DAE93 /* LazyView.swift in Sources */, DA0776F0234788010086C685 /* UserData.swift in Sources */, - DA6587222370C9D8007E2E7F /* PreferencesHostingController.swift in Sources */, DAC6608D236F771600F4501E /* PreferencesSwiftUIView.swift in Sources */, DA50C7BD2B0A51BD0009F716 /* SliderWithSwitchSupportRow.swift in Sources */, DAF457A623DB9CE00018B495 /* SetpointRow.swift in Sources */, + DAA070932B5181210060BB0E /* OpenHABImageDownloaderOperation.swift in Sources */, DAF4581823DC4A050018B495 /* ImageRow.swift in Sources */, 9350F17923814FAC00054BA8 /* ObservableOpenHABWidget.swift in Sources */, DA07752F2346705F0086C685 /* NotificationView.swift in Sources */, @@ -1394,6 +1506,23 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + DAD085682AE4782A001D36BE /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DAD085712AE4782D001D36BE /* OpenHABWatchAppTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DAD085722AE4782D001D36BE /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DAD0857D2AE4782F001D36BE /* OpenHABWatchLaunchTests.swift in Sources */, + DAD0857B2AE4782F001D36BE /* OpenHABWatchUITests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; DFB2622318830A3600D3244D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -1472,6 +1601,16 @@ target = DFB2622618830A3600D3244D /* openHAB */; targetProxy = DA2DC23421F2736C00830730 /* PBXContainerItemProxy */; }; + DAA0708D2B504B280060BB0E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DA0775142346705D0086C685 /* openHABWatch */; + targetProxy = DAA0708C2B504B280060BB0E /* PBXContainerItemProxy */; + }; + DAA0708F2B504B2C0060BB0E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DA0775142346705D0086C685 /* openHABWatch */; + targetProxy = DAA0708E2B504B2C0060BB0E /* PBXContainerItemProxy */; + }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ @@ -1524,15 +1663,6 @@ name = InfoPlist.strings; sourceTree = ""; }; - DA0775172346705D0086C685 /* Interface.storyboard */ = { - isa = PBXVariantGroup; - children = ( - DA0775182346705D0086C685 /* Base */, - DAD488B2287DDDFE00414693 /* nb */, - ); - name = Interface.storyboard; - sourceTree = ""; - }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ @@ -1725,6 +1855,7 @@ GCC_C_LANGUAGE_STANDARD = gnu11; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; INFOPLIST_FILE = openHABUITests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -1769,6 +1900,7 @@ GCC_C_LANGUAGE_STANDARD = gnu11; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; INFOPLIST_FILE = openHABUITests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -1811,22 +1943,31 @@ CURRENT_PROJECT_VERSION = 23; DEBUG_INFORMATION_FORMAT = dwarf; GCC_C_LANGUAGE_STANDARD = "compiler-default"; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = openHABWatch/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = openHAB; + INFOPLIST_KEY_CLKComplicationPrincipalClass = openHABWatch.ComplicationController; + INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown"; + INFOPLIST_KEY_WKCompanionAppBundleIdentifier = org.openhab.app; IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; MARKETING_VERSION = 3.0.6; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = org.openhab.app.watchkitapp; + PRODUCT_BUNDLE_IDENTIFIER = org.openhab.app.watch; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = "match AppStore org.openhab.app.watchkitapp"; SDKROOT = watchos; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = 4; @@ -1855,22 +1996,29 @@ CURRENT_PROJECT_VERSION = 23; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; GCC_C_LANGUAGE_STANDARD = "compiler-default"; + GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = openHABWatch/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = openHAB; + INFOPLIST_KEY_CLKComplicationPrincipalClass = openHABWatch.ComplicationController; + INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown"; + INFOPLIST_KEY_WKCompanionAppBundleIdentifier = org.openhab.app; IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; MARKETING_VERSION = 3.0.6; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = org.openhab.app.watchkitapp; + PRODUCT_BUNDLE_IDENTIFIER = org.openhab.app.watch; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = "match AppStore org.openhab.app.watchkitapp"; - "PROVISIONING_PROFILE_SPECIFIER[sdk=watchos*]" = "match AppStore org.openhab.app.watchkitapp"; + PROVISIONING_PROFILE_SPECIFIER = ""; SDKROOT = watchos; SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_OPTIMIZATION_LEVEL = "-O"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = 4; @@ -1898,6 +2046,7 @@ GCC_C_LANGUAGE_STANDARD = gnu11; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; INFOPLIST_FILE = openHABTestsSwift/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -1939,6 +2088,7 @@ GCC_C_LANGUAGE_STANDARD = gnu11; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; INFOPLIST_FILE = openHABTestsSwift/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -1960,6 +2110,150 @@ }; name = Release; }; + DAD085852AE47831001D36BE /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = D6A95UZXVC; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GENERATE_INFOPLIST_FILE = YES; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "com.reg-labs.openHABWatchSwiftUI-Watch-AppTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = watchos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 4; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/openHABWatch.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/openHABWatch"; + WATCHOS_DEPLOYMENT_TARGET = 9.0; + }; + name = Debug; + }; + DAD085862AE47831001D36BE /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = D6A95UZXVC; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GENERATE_INFOPLIST_FILE = YES; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "com.reg-labs.openHABWatchSwiftUI-Watch-AppTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = watchos; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 4; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/openHABWatch.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/openHABWatch"; + WATCHOS_DEPLOYMENT_TARGET = 9.0; + }; + name = Release; + }; + DAD085882AE47831001D36BE /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = D6A95UZXVC; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GENERATE_INFOPLIST_FILE = YES; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "com.reg-labs.openHABWatchSwiftUI-Watch-AppUITests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = watchos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 4; + TEST_TARGET_NAME = openHABWatch; + WATCHOS_DEPLOYMENT_TARGET = 9.0; + }; + name = Debug; + }; + DAD085892AE47831001D36BE /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = D6A95UZXVC; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GENERATE_INFOPLIST_FILE = YES; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "com.reg-labs.openHABWatchSwiftUI-Watch-AppUITests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = watchos; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 4; + TEST_TARGET_NAME = openHABWatch; + WATCHOS_DEPLOYMENT_TARGET = 9.0; + }; + name = Release; + }; DFB2625A18830A3600D3244D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -1994,6 +2288,7 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development"; COPY_PHASE_STRIP = NO; DEVELOPMENT_TEAM = PBAPXHRAM9; + ENABLE_PREVIEWS = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; ENABLE_USER_SCRIPT_SANDBOXING = NO; @@ -2019,7 +2314,7 @@ SWIFT_VERSION = ""; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; - WATCHOS_DEPLOYMENT_TARGET = 8.0; + WATCHOS_DEPLOYMENT_TARGET = 9.0; }; name = Debug; }; @@ -2058,6 +2353,7 @@ COPY_PHASE_STRIP = NO; DEVELOPMENT_TEAM = PBAPXHRAM9; ENABLE_NS_ASSERTIONS = NO; + ENABLE_PREVIEWS = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_USER_SCRIPT_SANDBOXING = NO; EXCLUDED_ARCHS = i386; @@ -2078,7 +2374,7 @@ TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; - WATCHOS_DEPLOYMENT_TARGET = 8.0; + WATCHOS_DEPLOYMENT_TARGET = 9.0; }; name = Release; }; @@ -2097,6 +2393,8 @@ GCC_PREFIX_HEADER = "openHAB/openHAB-Prefix.pch"; INFOPLIST_FILE = "openHAB/openHAB-Info.plist"; INFOPLIST_KEY_CFBundleDisplayName = openHAB; + INFOPLIST_KEY_WKCompanionAppBundleIdentifier = ""; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -2140,6 +2438,8 @@ GCC_PREFIX_HEADER = "openHAB/openHAB-Prefix.pch"; INFOPLIST_FILE = "openHAB/openHAB-Info.plist"; INFOPLIST_KEY_CFBundleDisplayName = openHAB; + INFOPLIST_KEY_WKCompanionAppBundleIdentifier = ""; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -2215,6 +2515,24 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + DAD085842AE47831001D36BE /* Build configuration list for PBXNativeTarget "openHABWatchSwiftUI Watch AppTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DAD085852AE47831001D36BE /* Debug */, + DAD085862AE47831001D36BE /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DAD085872AE47831001D36BE /* Build configuration list for PBXNativeTarget "openHABWatchSwiftUI Watch AppUITests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DAD085882AE47831001D36BE /* Debug */, + DAD085892AE47831001D36BE /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; DFB2622218830A3600D3244D /* Build configuration list for PBXProject "openHAB" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -2265,7 +2583,7 @@ repositoryURL = "https://github.com/Alamofire/AlamofireNetworkActivityIndicator.git"; requirement = { kind = upToNextMajorVersion; - minimumVersion = 3.0.0; + minimumVersion = 3.1.0; }; }; 93F8063327AE6C620035A6B0 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */ = { @@ -2297,7 +2615,7 @@ repositoryURL = "https://github.com/jonkykong/SideMenu.git"; requirement = { kind = upToNextMajorVersion; - minimumVersion = 6.0.0; + minimumVersion = 6.5.0; }; }; 93F8065127AE7B580035A6B0 /* XCRemoteSwiftPackageReference "SVGKit" */ = { @@ -2308,6 +2626,30 @@ kind = branch; }; }; + DA2C4FCB2B4F55D600D1C533 /* XCRemoteSwiftPackageReference "SDWebImage" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/SDWebImage/SDWebImage.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 5.19.7; + }; + }; + DA2C4FD02B4F56CF00D1C533 /* XCRemoteSwiftPackageReference "SDWebImageSwiftUI" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/SDWebImage/SDWebImageSwiftUI.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 3.1.2; + }; + }; + DA2C4FD32B4F573300D1C533 /* XCRemoteSwiftPackageReference "SDWebImageSVGCoder" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/SDWebImage/SDWebImageSVGCoder.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 1.7.0; + }; + }; DA3B75AC2C59729200E219AB /* XCRemoteSwiftPackageReference "SFSafeSymbols" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/SFSafeSymbols/SFSafeSymbols"; @@ -2424,6 +2766,26 @@ package = 93F8065127AE7B580035A6B0 /* XCRemoteSwiftPackageReference "SVGKit" */; productName = SVGKit; }; + DA2C4FCC2B4F55D700D1C533 /* SDWebImage */ = { + isa = XCSwiftPackageProductDependency; + package = DA2C4FCB2B4F55D600D1C533 /* XCRemoteSwiftPackageReference "SDWebImage" */; + productName = SDWebImage; + }; + DA2C4FCE2B4F55D700D1C533 /* SDWebImageMapKit */ = { + isa = XCSwiftPackageProductDependency; + package = DA2C4FCB2B4F55D600D1C533 /* XCRemoteSwiftPackageReference "SDWebImage" */; + productName = SDWebImageMapKit; + }; + DA2C4FD12B4F56D000D1C533 /* SDWebImageSwiftUI */ = { + isa = XCSwiftPackageProductDependency; + package = DA2C4FD02B4F56CF00D1C533 /* XCRemoteSwiftPackageReference "SDWebImageSwiftUI" */; + productName = SDWebImageSwiftUI; + }; + DA2C4FD42B4F573300D1C533 /* SDWebImageSVGCoder */ = { + isa = XCSwiftPackageProductDependency; + package = DA2C4FD32B4F573300D1C533 /* XCRemoteSwiftPackageReference "SDWebImageSVGCoder" */; + productName = SDWebImageSVGCoder; + }; DA3B75AD2C59741800E219AB /* SFSafeSymbols */ = { isa = XCSwiftPackageProductDependency; package = DA3B75AC2C59729200E219AB /* XCRemoteSwiftPackageReference "SFSafeSymbols" */; diff --git a/openHAB.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/openHAB.xcodeproj/project.xcworkspace/contents.xcworkspacedata index 359ae18aa..919434a62 100644 --- a/openHAB.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ b/openHAB.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -2,6 +2,6 @@ + location = "self:"> diff --git a/openHAB.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/openHAB.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 000000000..9056b4ae4 --- /dev/null +++ b/openHAB.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,249 @@ +{ + "originHash" : "3e04d0efd248e4773eeea4bddf4c08890d8cb5b0c615e3a2ff865ffe7b192275", + "pins" : [ + { + "identity" : "abseil-cpp-binary", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/abseil-cpp-binary.git", + "state" : { + "revision" : "194a6706acbd25e4ef639bcaddea16e8758a3e27", + "version" : "1.2024011602.0" + } + }, + { + "identity" : "alamofire", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Alamofire/Alamofire.git", + "state" : { + "revision" : "f455c2975872ccd2d9c81594c658af65716e9b9a", + "version" : "5.9.1" + } + }, + { + "identity" : "alamofirenetworkactivityindicator", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Alamofire/AlamofireNetworkActivityIndicator.git", + "state" : { + "revision" : "392bed083e8d193aca16bfa684ee24e4bcff0510", + "version" : "3.1.0" + } + }, + { + "identity" : "app-check", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/app-check.git", + "state" : { + "revision" : "3b62f154d00019ae29a71e9738800bb6f18b236d", + "version" : "10.19.2" + } + }, + { + "identity" : "cocoalumberjack", + "kind" : "remoteSourceControl", + "location" : "https://github.com/CocoaLumberjack/CocoaLumberjack.git", + "state" : { + "revision" : "4b8714a7fb84d42393314ce897127b3939885ec3", + "version" : "3.8.5" + } + }, + { + "identity" : "devicekit", + "kind" : "remoteSourceControl", + "location" : "https://github.com/devicekit/DeviceKit.git", + "state" : { + "revision" : "d37e70cb2646666dcf276d7d3d4a9760a41ff8a6", + "version" : "4.9.0" + } + }, + { + "identity" : "firebase-ios-sdk", + "kind" : "remoteSourceControl", + "location" : "https://github.com/firebase/firebase-ios-sdk.git", + "state" : { + "revision" : "eca84fd638116dd6adb633b5a3f31cc7befcbb7d", + "version" : "10.29.0" + } + }, + { + "identity" : "flexcolorpicker", + "kind" : "remoteSourceControl", + "location" : "https://github.com/RastislavMirek/FlexColorPicker.git", + "state" : { + "revision" : "72a5c2c5e28074e6c5f13efe3c98eb780ae2f906", + "version" : "1.4.4" + } + }, + { + "identity" : "googleappmeasurement", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/GoogleAppMeasurement.git", + "state" : { + "revision" : "fe727587518729046fc1465625b9afd80b5ab361", + "version" : "10.28.0" + } + }, + { + "identity" : "googledatatransport", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/GoogleDataTransport.git", + "state" : { + "revision" : "a637d318ae7ae246b02d7305121275bc75ed5565", + "version" : "9.4.0" + } + }, + { + "identity" : "googleutilities", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/GoogleUtilities.git", + "state" : { + "revision" : "57a1d307f42df690fdef2637f3e5b776da02aad6", + "version" : "7.13.3" + } + }, + { + "identity" : "grpc-binary", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/grpc-binary.git", + "state" : { + "revision" : "e9fad491d0673bdda7063a0341fb6b47a30c5359", + "version" : "1.62.2" + } + }, + { + "identity" : "gtm-session-fetcher", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/gtm-session-fetcher.git", + "state" : { + "revision" : "a2ab612cb980066ee56d90d60d8462992c07f24b", + "version" : "3.5.0" + } + }, + { + "identity" : "interop-ios-for-google-sdks", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/interop-ios-for-google-sdks.git", + "state" : { + "revision" : "2d12673670417654f08f5f90fdd62926dc3a2648", + "version" : "100.0.0" + } + }, + { + "identity" : "kingfisher", + "kind" : "remoteSourceControl", + "location" : "https://github.com/onevcat/Kingfisher.git", + "state" : { + "revision" : "2ef543ee21d63734e1c004ad6c870255e8716c50", + "version" : "7.12.0" + } + }, + { + "identity" : "leveldb", + "kind" : "remoteSourceControl", + "location" : "https://github.com/firebase/leveldb.git", + "state" : { + "revision" : "a0bc79961d7be727d258d33d5a6b2f1023270ba1", + "version" : "1.22.5" + } + }, + { + "identity" : "nanopb", + "kind" : "remoteSourceControl", + "location" : "https://github.com/firebase/nanopb.git", + "state" : { + "revision" : "b7e1104502eca3a213b46303391ca4d3bc8ddec1", + "version" : "2.30910.0" + } + }, + { + "identity" : "promises", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/promises.git", + "state" : { + "revision" : "540318ecedd63d883069ae7f1ed811a2df00b6ac", + "version" : "2.4.0" + } + }, + { + "identity" : "sdwebimage", + "kind" : "remoteSourceControl", + "location" : "https://github.com/SDWebImage/SDWebImage.git", + "state" : { + "revision" : "8a1be70a625683bc04d6903e2935bf23f3c6d609", + "version" : "5.19.7" + } + }, + { + "identity" : "sdwebimagesvgcoder", + "kind" : "remoteSourceControl", + "location" : "https://github.com/SDWebImage/SDWebImageSVGCoder.git", + "state" : { + "revision" : "950167445ab703740569869c8b7510efc9d09a26", + "version" : "1.7.0" + } + }, + { + "identity" : "sdwebimageswiftui", + "kind" : "remoteSourceControl", + "location" : "https://github.com/SDWebImage/SDWebImageSwiftUI.git", + "state" : { + "revision" : "53573d6dd017e354c0e7d8f1c86b77ef1383c996", + "version" : "2.2.7" + } + }, + { + "identity" : "sfsafesymbols", + "kind" : "remoteSourceControl", + "location" : "https://github.com/SFSafeSymbols/SFSafeSymbols", + "state" : { + "revision" : "e2e28f4e56e1769c2ec3c61c9355fc64eb7a535a", + "version" : "5.3.0" + } + }, + { + "identity" : "sidemenu", + "kind" : "remoteSourceControl", + "location" : "https://github.com/jonkykong/SideMenu.git", + "state" : { + "revision" : "8bd4fd128923cf5494fa726839af8afe12908ad9", + "version" : "6.5.0" + } + }, + { + "identity" : "svgkit", + "kind" : "remoteSourceControl", + "location" : "https://github.com/SVGKit/SVGKit.git", + "state" : { + "branch" : "3.x", + "revision" : "1b8a3cf210ab4681c18fbb62059bbdbb37dd649a" + } + }, + { + "identity" : "swift-log", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-log", + "state" : { + "revision" : "9cb486020ebf03bfa5b5df985387a14a98744537", + "version" : "1.6.1" + } + }, + { + "identity" : "swift-protobuf", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-protobuf.git", + "state" : { + "revision" : "edb6ed4919f7756157fe02f2552b7e3850a538e5", + "version" : "1.28.1" + } + }, + { + "identity" : "swiftmessages", + "kind" : "remoteSourceControl", + "location" : "https://github.com/SwiftKickMobile/SwiftMessages.git", + "state" : { + "revision" : "62e12e138fc3eedf88c7553dd5d98712aa119f40", + "version" : "9.0.9" + } + } + ], + "version" : 3 +} diff --git a/openHAB.xcodeproj/xcshareddata/xcschemes/openHABWatch (Notification).xcscheme b/openHAB.xcodeproj/xcshareddata/xcschemes/openHABWatch (Notification).xcscheme index 0ae68e971..45cfdeb6b 100644 --- a/openHAB.xcodeproj/xcshareddata/xcschemes/openHABWatch (Notification).xcscheme +++ b/openHAB.xcodeproj/xcshareddata/xcschemes/openHABWatch (Notification).xcscheme @@ -55,7 +55,7 @@ debugServiceExtension = "internal" allowLocationSimulation = "YES" launchAutomaticallySubstyle = "8" - notificationPayloadFile = "openHABWatch Extension/PushNotificationPayload.apns"> + notificationPayloadFile = "openHABWatch/Extension/PushNotificationPayload.apns"> + notificationPayloadFile = "openHABWatch/Extension/PushNotificationPayload.apns"> + buildForTesting = "NO" + buildForRunning = "NO" + buildForProfiling = "NO" + buildForArchiving = "NO" + buildForAnalyzing = "NO"> + notificationPayloadFile = "openHABWatch/Extension/PushNotificationPayload.apns"> + debugDocumentVersioning = "YES"> Void - @Environment(\.dismiss) private var dismiss + struct MainSectionView: View { + var openHABIconwidth: CGFloat + var onDismiss: (TargetController) -> Void + var dismiss: DismissAction - // App wide data access - var appData: OpenHABDataObject? { - AppDelegate.appDelegate.appData + var body: some View { + Section(header: Text("Main")) { + HStack { + Image("openHABIcon") + .resizable() + .aspectRatio(contentMode: .fit) + .frame(width: openHABIconwidth) + Text("Home") + } + .onTapGesture { + dismiss() + onDismiss(.webview) + } + } + } } - @ScaledMetric var openHABIconwidth = 20.0 - @ScaledMetric var tilesIconwidth = 20.0 - @ScaledMetric var sitemapIconwidth = 20.0 + struct TilesSectionView: View { + var uiTiles: [OpenHABUiTile] + var tilesIconwidth: CGFloat + var onDismiss: (TargetController) -> Void + var dismiss: DismissAction - var body: some View { - VStack { - List { - Section(header: Text("Main")) { + var body: some View { + Section(header: Text("Tiles")) { + ForEach(uiTiles, id: \.url) { tile in HStack { - Image("openHABIcon") - .resizable() + ImageView(url: tile.imageUrl) .aspectRatio(contentMode: .fit) - .frame(width: openHABIconwidth) - Text("Home") + .frame(width: tilesIconwidth) + Text(tile.name) } .onTapGesture { dismiss() - onDismiss(.webview) + onDismiss(.tile(tile.url)) } } + } + } + } - Section(header: Text("Tiles")) { - ForEach(uiTiles, id: \.url) { tile in - HStack { - ImageView(url: tile.imageUrl) - .aspectRatio(contentMode: .fit) - .frame(width: tilesIconwidth) - Text(tile.name) - } - .onTapGesture { - dismiss() - onDismiss(.tile(tile.url)) + // Handle double-tap gesture for selecting or deselecting the sitemap for the watch + struct SitemapsSectionView: View { + var sitemaps: [OpenHABSitemap] + var sitemapIconwidth: CGFloat + var appData: OpenHABDataObject? + @Binding var sitemapForWatch: String? + var onDismiss: (TargetController) -> Void + var dismiss: DismissAction + + var body: some View { + Section(header: Text("Sitemaps")) { + ForEach(sitemaps, id: \.name) { sitemap in + SitemapRowView( + sitemap: sitemap, + sitemapIconwidth: sitemapIconwidth, + appData: appData, + isWatchSitemap: sitemap.name == sitemapForWatch, + onDismiss: onDismiss, + dismiss: dismiss + ) + .onTapGesture(count: 2) { + if sitemap.name == sitemapForWatch { + sitemapForWatch = nil + Preferences.sitemapForWatch = "" + } else { + sitemapForWatch = sitemap.name + Preferences.sitemapForWatch = sitemap.name } } } + } + } + } - Section(header: Text("Sitemaps")) { - ForEach(sitemaps, id: \.name) { sitemap in - HStack { - let url = Endpoint.iconForDrawer(rootUrl: appData?.openHABRootUrl ?? "", icon: sitemap.icon).url - KFImage(url).placeholder { Image("openHABIcon").resizable() } - .resizable() - .aspectRatio(contentMode: .fit) - .frame(width: sitemapIconwidth) - Text(sitemap.label) - } - .onTapGesture { - dismiss() - onDismiss(.sitemap(sitemap.name)) - } - } + struct SitemapRowView: View { + var sitemap: OpenHABSitemap + var sitemapIconwidth: CGFloat + var appData: OpenHABDataObject? + var isWatchSitemap: Bool + var onDismiss: (TargetController) -> Void + var dismiss: DismissAction + + var body: some View { + HStack { + let url = Endpoint.iconForDrawer(rootUrl: appData?.openHABRootUrl ?? "", icon: sitemap.icon).url + KFImage(url).placeholder { Image("openHABIcon").resizable() } + .resizable() + .aspectRatio(contentMode: .fit) + .frame(width: sitemapIconwidth) + Text(sitemap.label) + if isWatchSitemap { + Spacer() + Image(systemSymbol: .applewatchWatchface) + } + } + .onTapGesture { + dismiss() + onDismiss(.sitemap(sitemap.name)) + } + } + } + + struct SystemSectionView: View { + var openHABIconwidth: CGFloat + var onDismiss: (TargetController) -> Void + var dismiss: DismissAction + + var body: some View { + Section(header: Text("System")) { + HStack { + Image(systemSymbol: .gear) + .resizable() + .aspectRatio(contentMode: .fit) + .frame(width: openHABIconwidth) + Text(LocalizedStringKey("settings")) + } + .onTapGesture { + dismiss() + onDismiss(.settings) } - Section(header: Text("System")) { + if Preferences.remoteUrl.contains("openhab.org"), !Preferences.demomode { HStack { - Image(systemSymbol: .gear) + Image(systemSymbol: .bell) .resizable() .aspectRatio(contentMode: .fit) .frame(width: openHABIconwidth) - Text(LocalizedStringKey("settings")) + Text(LocalizedStringKey("notifications")) } .onTapGesture { dismiss() - onDismiss(.settings) - } - - if Preferences.remoteUrl.contains("openhab.org"), !Preferences.demomode { - HStack { - Image(systemSymbol: .bell) - .resizable() - .aspectRatio(contentMode: .fit) - .frame(width: openHABIconwidth) - Text(LocalizedStringKey("notifications")) - } - .onTapGesture { - dismiss() - onDismiss(.notifications) - } + onDismiss(.notifications) } } } + } + } + + @State private var sitemaps: [OpenHABSitemap] = [] + @State private var uiTiles: [OpenHABUiTile] = [] + @State private var selectedSection: Int? + @State private var connectedUrl: String = "Not connected" // Default label text + @ObservedObject private var networkTracker = NetworkTracker.shared + + var openHABUsername = "" + var openHABPassword = "" + + var onDismiss: (TargetController) -> Void + @Environment(\.dismiss) private var dismiss + + // App wide data access + var appData: OpenHABDataObject? { + AppDelegate.appDelegate.appData + } + + @ScaledMetric var openHABIconwidth = 20.0 + @ScaledMetric var tilesIconwidth = 20.0 + @ScaledMetric var sitemapIconwidth = 20.0 + + @State private var sitemapForWatch: String? + + var body: some View { + VStack { + List { + MainSectionView(openHABIconwidth: openHABIconwidth, onDismiss: onDismiss, dismiss: dismiss) + + TilesSectionView(uiTiles: uiTiles, tilesIconwidth: tilesIconwidth, onDismiss: onDismiss, dismiss: dismiss) + + SitemapsSectionView(sitemaps: sitemaps, sitemapIconwidth: sitemapIconwidth, appData: appData, sitemapForWatch: $sitemapForWatch, onDismiss: onDismiss, dismiss: dismiss) + + SystemSectionView(openHABIconwidth: openHABIconwidth, onDismiss: onDismiss, dismiss: dismiss) + } .listStyle(.inset) .onAppear(perform: loadData) @@ -196,6 +276,7 @@ struct DrawerView: View { private func loadData() { loadSitemaps() loadUiTiles() + sitemapForWatch = Preferences.sitemapForWatch } private func loadSitemaps() { diff --git a/openHAB/OpenHABSitemapViewController.swift b/openHAB/OpenHABSitemapViewController.swift index 70e30d8a8..56a452621 100644 --- a/openHAB/OpenHABSitemapViewController.swift +++ b/openHAB/OpenHABSitemapViewController.swift @@ -179,6 +179,8 @@ class OpenHABSitemapViewController: OpenHABViewController, GenericUITableViewCel case .notConnected: os_log("Tracking error", log: .viewCycle, type: .info) self.showPopupMessage(seconds: 60, title: NSLocalizedString("error", comment: ""), message: NSLocalizedString("network_not_available", comment: ""), theme: .error) + case .connected: + self.hidePopupMessages() case _: break } diff --git a/openHAB/SettingsView.swift b/openHAB/SettingsView.swift index 44b247456..cd728014a 100644 --- a/openHAB/SettingsView.swift +++ b/openHAB/SettingsView.swift @@ -33,6 +33,7 @@ struct SettingsView: View { @State var settingsSortSitemapsBy: SortSitemapsOrder = .label @State var settingsDefaultMainUIPath = "" @State var settingsAlwaysAllowWebRTC = true + @State var settingsSitemapForWatch = "" @State private var showingCacheAlert = false @State private var showCrashReportingAlert = false @@ -40,6 +41,8 @@ struct SettingsView: View { @State private var hasBeenLoaded = false + @State private var sitemaps: [OpenHABSitemap] = [] + @Environment(\.dismiss) private var dismiss var appData: OpenHABDataObject? { @@ -154,6 +157,7 @@ struct SettingsView: View { // Setting .onAppear of view required here because onAppear of entire view is run after onChange is active // when migrating to iOS17 this settingsSendCrashReports = Preferences.sendCrashReports + loadSitemaps() hasBeenLoaded = true } .onChange(of: settingsSendCrashReports) { newValue in @@ -273,6 +277,14 @@ struct SettingsView: View { } label: { Text("Sort sitemaps by") } + + Picker(selection: $settingsSitemapForWatch) { + ForEach(sitemaps, id: \.name) { sitemap in + Text(sitemap.label) + } + } label: { + Text("Sitemap For Apple Watch") + } } Section(header: Text(LocalizedStringKey("about_settings"))) { @@ -344,6 +356,7 @@ struct SettingsView: View { settingsSortSitemapsBy = SortSitemapsOrder(rawValue: Preferences.sortSitemapsby) ?? .label settingsDefaultMainUIPath = Preferences.defaultMainUIPath settingsAlwaysAllowWebRTC = Preferences.alwaysAllowWebRTC + settingsSitemapForWatch = Preferences.sitemapForWatch } func saveSettings() { @@ -361,10 +374,33 @@ struct SettingsView: View { Preferences.sortSitemapsby = settingsSortSitemapsBy.rawValue Preferences.defaultMainUIPath = settingsDefaultMainUIPath Preferences.alwaysAllowWebRTC = settingsAlwaysAllowWebRTC + Preferences.sitemapForWatch = settingsSitemapForWatch WatchMessageService.singleton.syncPreferencesToWatch() Crashlytics.crashlytics().setCrashlyticsCollectionEnabled(settingsSendCrashReports) logger.debug("setCrashlyticsCollectionEnabled to \(settingsSendCrashReports)") } + + private func loadSitemaps() { + NetworkConnection.sitemaps(openHABRootUrl: appData?.openHABRootUrl ?? "") { response in + switch response.result { + case let .success(data): + os_log("Sitemap response", log: .viewCycle, type: .info) + + sitemaps = deriveSitemaps(data) + + if sitemaps.last?.name == "_default", sitemaps.count > 1 { + sitemaps = Array(sitemaps.dropLast()) + } + + switch SortSitemapsOrder(rawValue: Preferences.sortSitemapsby) ?? .label { + case .label: sitemaps.sort { $0.label < $1.label } + case .name: sitemaps.sort { $0.name < $1.name } + } + case let .failure(error): + os_log("%{PUBLIC}@", log: .default, type: .error, error.localizedDescription) + } + } + } } extension UIApplication { diff --git a/openHAB/WatchMessageService.swift b/openHAB/WatchMessageService.swift index 5de90ff2f..864039093 100644 --- a/openHAB/WatchMessageService.swift +++ b/openHAB/WatchMessageService.swift @@ -21,7 +21,6 @@ class WatchMessageService: NSObject, WCSessionDelegate { // This method gets called when the watch requests the data func session(_ session: WCSession, didReceiveMessage message: [String: Any], replyHandler: @escaping ([String: Any]) -> Void) { - // TODO: Use RemoteUrl, TOO os_log("didReceiveMessage %{PUBLIC}@", log: .watch, type: .info, "\(message)") if message["request"] != nil { @@ -54,9 +53,11 @@ class WatchMessageService: NSObject, WCSessionDelegate { "username": Preferences.username, "password": Preferences.password, "alwaysSendCreds": Preferences.alwaysSendCreds, - "defaultSitemap": "watch", + "defaultSitemap": Preferences.defaultSitemap, "ignoreSSL": Preferences.ignoreSSL, - "trustedCertificates": NetworkConnection.shared.serverCertificateManager.trustedCertificates + "trustedCertificates": NetworkConnection.shared.serverCertificateManager.trustedCertificates, + "sitemapForWatch": Preferences.sitemapForWatch, + "iconType": Preferences.iconType ] return applicationDict diff --git a/openHABTestsSwift/OpenHABWatchTests.swift b/openHABTestsSwift/OpenHABWatchTests.swift index 2ed97ef2b..4da9c2fe1 100644 --- a/openHABTestsSwift/OpenHABWatchTests.swift +++ b/openHABTestsSwift/OpenHABWatchTests.swift @@ -9,6 +9,7 @@ // // SPDX-License-Identifier: EPL-2.0 +@testable import openHAB import XCTest class OpenHABWatchTests: XCTestCase { diff --git a/openHABUITests/OpenHABUITests.swift b/openHABUITests/OpenHABUITests.swift index ee432f070..6175da357 100644 --- a/openHABUITests/OpenHABUITests.swift +++ b/openHABUITests/OpenHABUITests.swift @@ -66,7 +66,6 @@ class OpenHABUITests: XCTestCase { menuStaticText?.tap() sleep(1) - // openHAB logo in left menu webViewsQuery.links.allElementsBoundByIndex[1].tap() sleep(2) diff --git a/openHABWatch Extension/ExtensionDelegate.swift b/openHABWatch Extension/ExtensionDelegate.swift deleted file mode 100644 index d48589338..000000000 --- a/openHABWatch Extension/ExtensionDelegate.swift +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright (c) 2010-2024 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 Kingfisher -import OpenHABCore -import os.log -import WatchConnectivity -import WatchKit - -@main -class ExtensionDelegate: NSObject, WKApplicationDelegate { - static var extensionDelegate: ExtensionDelegate! - - var appData: ObservableOpenHABDataObject - - var session: WCSession? { - didSet { - if let session { - session.delegate = AppMessageService.singleton - session.activate() - } - } - } - - var viewModel: UserData? - - override init() { - appData = ObservableOpenHABDataObject.shared - super.init() - ExtensionDelegate.extensionDelegate = self - - ImageDownloader.default.authenticationChallengeResponder = self - } - - func applicationDidFinishLaunching() { - // Perform any final initialization of your application. - activateWatchConnectivity() - - NetworkConnection.initialize(ignoreSSL: Preferences.ignoreSSL, interceptor: OpenHABAccessTokenAdapter(appData: ExtensionDelegate.extensionDelegate.appData)) - - NetworkConnection.shared.assignDelegates(serverDelegate: self, clientDelegate: self) - - KingfisherManager.shared.defaultOptions = [.requestModifier(OpenHABAccessTokenAdapter(appData: ExtensionDelegate.extensionDelegate.appData))] - } - - func activateWatchConnectivity() { - // WCSession.isSupported is always supported on a Watch - session = WCSession.default - } - - func applicationDidBecomeActive() { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. - AppState.singleton.active = true - } - - func applicationWillResignActive() { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, etc. - AppState.singleton.active = false - } - - func handle(_ backgroundTasks: Set) { - // Sent when the system needs to launch the application in the background to process tasks. Tasks arrive in a set, so loop through and process each one. - for task in backgroundTasks { - // Use a switch statement to check the task type - switch task { - case let backgroundTask as WKApplicationRefreshBackgroundTask: - // Be sure to complete the background task once you’re done. - backgroundTask.setTaskCompletedWithSnapshot(false) - case let snapshotTask as WKSnapshotRefreshBackgroundTask: - // Snapshot tasks have a unique completion call, make sure to set your expiration date - snapshotTask.setTaskCompleted(restoredDefaultState: true, estimatedSnapshotExpiration: Date.distantFuture, userInfo: nil) - case let connectivityTask as WKWatchConnectivityRefreshBackgroundTask: - // Be sure to complete the connectivity task once you’re done. - connectivityTask.setTaskCompletedWithSnapshot(false) - case let urlSessionTask as WKURLSessionRefreshBackgroundTask: - // Be sure to complete the URL session task once you’re done. - urlSessionTask.setTaskCompletedWithSnapshot(false) - case let relevantShortcutTask as WKRelevantShortcutRefreshBackgroundTask: - // Be sure to complete the relevant-shortcut task once you're done. - relevantShortcutTask.setTaskCompletedWithSnapshot(false) - case let intentDidRunTask as WKIntentDidRunRefreshBackgroundTask: - // Be sure to complete the intent-did-run task once you're done. - intentDidRunTask.setTaskCompletedWithSnapshot(false) - default: - // make sure to complete unhandled task types - task.setTaskCompletedWithSnapshot(false) - } - } - } -} - -// MARK: Kingfisher authentication with NSURLCredential - -extension ExtensionDelegate: AuthenticationChallengeResponsible { - // sessionDelegate.onReceiveSessionTaskChallenge - func downloader(_ downloader: ImageDownloader, - task: URLSessionTask, - didReceive challenge: URLAuthenticationChallenge, - completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { - let (disposition, credential) = onReceiveSessionTaskChallenge(with: challenge) - completionHandler(disposition, credential) - } - - // sessionDelegate.onReceiveSessionChallenge - func downloader(_ downloader: ImageDownloader, - didReceive challenge: URLAuthenticationChallenge, - completionHandler: (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { - let (disposition, credential) = onReceiveSessionChallenge(with: challenge) - completionHandler(disposition, credential) - } -} - -// MARK: - ServerCertificateManagerDelegate - -extension ExtensionDelegate: ServerCertificateManagerDelegate { - // delegate should ask user for a decision on what to do with invalid certificate - func evaluateServerTrust(_ policy: ServerCertificateManager?, summary certificateSummary: String?, forDomain domain: String?) { - guard viewModel != nil else { - policy!.evaluateResult = .deny - return - } - DispatchQueue.main.async { - self.viewModel?.showCertificateAlert = true - self.viewModel?.certificateErrorDescription = String(format: NSLocalizedString("ssl_certificate_invalid", comment: ""), certificateSummary ?? "", domain ?? "") - } - } - - // certificate received from openHAB doesn't match our record, ask user for a decision - func evaluateCertificateMismatch(_ policy: ServerCertificateManager?, summary certificateSummary: String?, forDomain domain: String?) { - guard viewModel != nil else { - policy!.evaluateResult = .deny - return - } - DispatchQueue.main.async { - self.viewModel?.showCertificateAlert = true - self.viewModel?.certificateErrorDescription = String(format: NSLocalizedString("ssl_certificate_no_match", comment: ""), certificateSummary ?? "", domain ?? "") - } - } - - func acceptedServerCertificatesChanged(_ policy: ServerCertificateManager?) {} -} - -// MARK: - ClientCertificateManagerDelegate - -extension ExtensionDelegate: ClientCertificateManagerDelegate { - // delegate should ask user for a decision on whether to import the client certificate into the keychain - func askForClientCertificateImport(_ clientCertificateManager: ClientCertificateManager?) {} - - // delegate should ask user for the export password used to decode the PKCS#12 - func askForCertificatePassword(_ clientCertificateManager: ClientCertificateManager?) {} - - // delegate should alert the user that an error occured importing the certificate - func alertClientCertificateError(_ clientCertificateManager: ClientCertificateManager?, errMsg: String) {} -} diff --git a/openHABWatch Extension/HostingController.swift b/openHABWatch Extension/HostingController.swift deleted file mode 100644 index 9885e092f..000000000 --- a/openHABWatch Extension/HostingController.swift +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2010-2024 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 Foundation -import Kingfisher -import OpenHABCore -import os.log -import SwiftUI -import WatchKit - -class HostingController: WKHostingController { - @ObservedObject var settings = ObservableOpenHABDataObject.shared - let userData = UserData(sitemapName: ObservableOpenHABDataObject.shared.sitemapName) - - override var body: ContentView { - ContentView(viewModel: userData, settings: settings) - } - - override init() { - super.init() - ExtensionDelegate.extensionDelegate.viewModel = userData - } -} diff --git a/openHABWatch Extension/OpenHABWatchTracker.swift b/openHABWatch Extension/OpenHABWatchTracker.swift deleted file mode 100644 index 7dc6fcf10..000000000 --- a/openHABWatch Extension/OpenHABWatchTracker.swift +++ /dev/null @@ -1,317 +0,0 @@ -// Copyright (c) 2010-2024 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 Alamofire -import Foundation -import Network -import OpenHABCore -import os.log - -protocol OpenHABWatchTrackerDelegate: AnyObject { - func openHABTracked(_ openHABUrl: URL?) - func openHABTrackingProgress(_ message: String?) - func openHABTrackingError(_ error: Error) -} - -protocol OpenHABWatchTrackerExtendedDelegate: OpenHABWatchTrackerDelegate { - func openHABTrackingNetworkChange(_ networkStatus: NWPath) -} - -class OpenHABWatchTracker: NSObject { - var oldReachabilityStatus: NWPath? - - weak var delegate: OpenHABWatchTrackerDelegate? - var netBrowser: NWBrowser? - var pathMonitor = NWPathMonitor() - var connectivityTask: DataRequest? - - let backgroundQueue = DispatchQueue.global(qos: .background) - - override init() { - super.init() - } - - func start() { - #if !os(watchOS) - oldReachabilityStatus = pathMonitor.currentPath - pathMonitor.pathUpdateHandler = { [weak self] path in - guard let self else { return } - - let nStatus = path - if nStatus != oldReachabilityStatus { - if let oldReachabilityStatus { - os_log("Network status changed from %{PUBLIC}@ to %{PUBLIC}@", log: OSLog.remoteAccess, type: .info, oldReachabilityStatus.debugDescription, nStatus.debugDescription) - } - oldReachabilityStatus = nStatus - (delegate as? OpenHABWatchTrackerExtendedDelegate)?.openHABTrackingNetworkChange(nStatus) - if isNetworkConnected() { - pathMonitor.cancel() - selectUrl() - } - } - } - pathMonitor.start(queue: backgroundQueue) - #endif - selectUrl() - } - - func start(URL: URL?) { - trackedUrl(URL) - } - - func selectUrl() { - #if os(watchOS) - if ObservableOpenHABDataObject.shared.localUrl.isEmpty { - os_log("Starting discovery", log: .default, type: .debug) - startDiscovery() - } else { - if let connectivityTask { - connectivityTask.cancel() - } - let request = URLRequest(url: URL(string: ObservableOpenHABDataObject.shared.localUrl)!, cachePolicy: .reloadIgnoringCacheData, timeoutInterval: 2.0) - connectivityTask = NetworkConnection.shared.manager.request(request) - .validate() - .responseData { response in - switch response.result { - case .success: - os_log("Tracking local URL", log: .default, type: .debug) - self.trackedLocalUrl() - case .failure: - os_log("Tracking remote URL", log: .default, type: .debug) - self.trackedRemoteUrl() - } - } - connectivityTask?.resume() - } - #else - - // Check if any network is available - if isNetworkConnected() { - // Check if network is WiFi. If not, go for remote URL - if !isNetworkWiFi() { - os_log("OpenHABWatchTracker network is not WiFi", log: .default, type: .info) - trackedRemoteUrl() - // If it is WiFi - } else { - os_log("OpenHABWatchTracker network is Wifi", log: .default, type: .info) - // Check if local URL is configured - if ObservableOpenHABDataObject.shared.localUrl.isEmpty { - startDiscovery() - } else { - if let connectivityTask { - connectivityTask.cancel() - } - let request = URLRequest(url: URL(string: ObservableOpenHABDataObject.shared.localUrl)!, cachePolicy: .reloadIgnoringCacheData, timeoutInterval: 2.0) - connectivityTask = NetworkConnection.shared.manager.request(request) - .validate() - .responseData { response in - switch response.result { - case .success: - self.trackedLocalUrl() - case .failure: - self.trackedRemoteUrl() - } - } - connectivityTask?.resume() - } - } - } else { - var errorDetail: [AnyHashable: Any] = [:] - errorDetail[NSLocalizedDescriptionKey] = NSLocalizedString("network_not_available", comment: "") - let trackingError = NSError(domain: "openHAB", code: 100, userInfo: errorDetail as? [String: Any]) - delegate?.openHABTrackingError(trackingError) - } - #endif - } - - func trackedLocalUrl() { - delegate?.openHABTrackingProgress(NSLocalizedString("connecting_local", comment: "")) - let openHABUrl = normalizeUrl(ObservableOpenHABDataObject.shared.localUrl) - trackedUrl(URL(string: openHABUrl!)) - } - - func trackedRemoteUrl() { - let openHABUrl = normalizeUrl(ObservableOpenHABDataObject.shared.remoteUrl) - if !(openHABUrl ?? "").isEmpty { - // delegate?.openHABTrackingProgress("Connecting to remote URL") - trackedUrl(URL(string: openHABUrl!)) - } else { - var errorDetail: [AnyHashable: Any] = [:] - errorDetail[NSLocalizedDescriptionKey] = NSLocalizedString("remote_url_not_configured", comment: "") - let trackingError = NSError(domain: "openHAB", code: 101, userInfo: errorDetail as? [String: Any]) - delegate?.openHABTrackingError(trackingError) - } - } - - func trackedDiscoveryUrl(_ discoveryUrl: URL?) { - delegate?.openHABTrackingProgress(NSLocalizedString("connecting_discovered", comment: "")) - trackedUrl(discoveryUrl) - } - - func trackedDemoMode() { - delegate?.openHABTrackingProgress(NSLocalizedString("running_demo_mode", comment: "")) - trackedUrl(URL(staticString: "https://demo.openhab.org:8443")) - } - - func trackedUrl(_ trackedUrl: URL?) { - delegate?.openHABTracked(trackedUrl) - } - - func startDiscovery() { - os_log("OpenHABTracking starting Bonjour discovery", log: .default, type: .info) - - delegate?.openHABTrackingProgress(NSLocalizedString("discovering_oh", comment: "")) - let parameters = NWParameters() - netBrowser = NWBrowser(for: .bonjour(type: "_openhab-server-ssl._tcp.", domain: "local."), using: parameters) - netBrowser?.stateUpdateHandler = { state in - switch state { - case .ready: - os_log("OpenHABWatchTracker discovery ready", log: .default, type: .info) - case let .failed(error): - os_log("OpenHABWatchTracker discovery failed: %{PUBLIC}@", log: .default, type: .info, error.localizedDescription) - self.trackedRemoteUrl() - default: - break - } - } - netBrowser?.browseResultsChangedHandler = { results, _ in - guard !results.isEmpty else { return } - guard let result = results.first else { return } - - switch result.endpoint { - case let .service(name, type, domain, interface): - os_log("OpenHABWatchTracker discovered service: name=%{PUBLIC}@ type=%{PUBLIC}@ domain=%{PUBLIC}@", log: OSLog.remoteAccess, type: .info, name, type, domain) - let params = NWParameters.tcp - let endpoint = NWEndpoint.service(name: name, type: type, domain: domain, interface: interface) - let connection = NWConnection(to: endpoint, using: params) - connection.stateUpdateHandler = { state in - switch state { - case .ready: - let path = connection.currentPath! - switch path.remoteEndpoint { - case let .hostPort(host, port): - var components = URLComponents() - components.scheme = "https" - components.port = Int(port.rawValue) - switch host { - case let .name(name, _): - components.host = name - case let .ipv4(ipv4): - components.host = self.getStringIp(addressFamily: AF_INET, fromAddressData: ipv4.rawValue) - case let .ipv6(ipv6): - components.host = self.getStringIp(addressFamily: AF_INET6, fromAddressData: ipv6.rawValue) - default: - components.host = nil - } - if components.host == nil { - os_log("OpenHABWatchTracker unable to build URL from discovered endpoint, using remote URL instead", log: OSLog.remoteAccess, type: .info) - self.trackedRemoteUrl() - } else { - os_log("OpenHABWatchTracker discovered: %{PUBLIC}@ ", log: OSLog.remoteAccess, type: .info, components.url?.description ?? "") - self.trackedDiscoveryUrl(components.url) - } - return - default: - os_log("OpenHABWatchTracker unhandled endpoint type", log: OSLog.remoteAccess, type: .info) - connection.cancel() - } - case .preparing, .setup, .waiting: - break - default: - // Error establishing the connection or other unknown condition - connection.cancel() - os_log("OpenHABWatchTracker unable establish connection to discovered endpoint, using remote URL instead", log: OSLog.remoteAccess, type: .info) - self.trackedRemoteUrl() - } - } - self.netBrowser!.cancel() - connection.start(queue: .main) - return - default: - os_log("OpenHABWatchTracker discovered unhandled endpoint type", log: OSLog.remoteAccess, type: .info) - } - - self.netBrowser!.cancel() - - // Unable to discover local endpoint - os_log("OpenHABWatchTracker unable to discover local server, using remote URL", log: OSLog.remoteAccess, type: .info) - self.trackedRemoteUrl() - } - netBrowser?.start(queue: .main) - } - - func getStringIp(addressFamily: Int32, fromAddressData dataIn: Data?) -> String? { - let data = dataIn! as NSData - var sockAddr: in_addr = data.castToCPointer() - var ipAddressString: [CChar] = Array(repeating: 0, count: Int(INET6_ADDRSTRLEN)) - inet_ntop( - addressFamily, - &sockAddr, - &ipAddressString, - socklen_t(INET_ADDRSTRLEN) - ) - - return String(cString: ipAddressString) - } - - func normalizeUrl(_ url: String?) -> String? { - if let url, url.hasSuffix("/") { - return String(url.dropLast()) - } - return url - } - - func isNetworkConnected() -> Bool { - pathMonitor.currentPath.status == .satisfied - } - - func isNetworkWiFi() -> Bool { - (pathMonitor.currentPath.status == .satisfied && !pathMonitor.currentPath.isExpensive) - } -} - -extension NWPath: CustomStringConvertible { - public var description: String { - switch status { - case .unsatisfied, .requiresConnection: - return "unreachable" - case .satisfied: - var str = "reachable:" - for interface in availableInterfaces { - switch interface.type { - case .wifi: - str += " wifi" - case .cellular: - str += " cellular" - case .wiredEthernet: - str += " wiredEthernet" - case .loopback: - str += " loopback" - case .other: - str += " other" - default: - str += " (unknown)" - } - } - return str - default: - return "(unknown)" - } - } -} - -extension NSData { - func castToCPointer() -> T { - let mem = UnsafeMutablePointer.allocate(capacity: MemoryLayout.size) - getBytes(mem, length: MemoryLayout.size) - return mem.move() - } -} diff --git a/openHABWatch Extension/PreferencesHostingController.swift b/openHABWatch Extension/PreferencesHostingController.swift deleted file mode 100644 index bdbbf3d15..000000000 --- a/openHABWatch Extension/PreferencesHostingController.swift +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2010-2024 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 OpenHABCore -import SwiftUI -import WatchKit - -class PreferencesHostingController: WKHostingController { - override var body: PreferencesSwiftUIView { - PreferencesSwiftUIView() - } -} diff --git a/openHABWatch Extension/Views/PreferencesSwiftUIView.swift b/openHABWatch Extension/Views/PreferencesSwiftUIView.swift deleted file mode 100644 index 0badaa99a..000000000 --- a/openHABWatch Extension/Views/PreferencesSwiftUIView.swift +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2010-2024 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 OpenHABCore -import os.log -import SwiftUI -import WatchConnectivity - -struct PreferencesSwiftUIView: View { - @ObservedObject var settings = ObservableOpenHABDataObject.shared - - var applicationVersionNumber: String = { - let versionNumber: String = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as! String - let buildNumber: String = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as! String - - return "V\(versionNumber).\(buildNumber)" - }() - - var body: some View { - List { - PreferencesRowUIView(label: NSLocalizedString("version", comment: ""), content: applicationVersionNumber).font(.footnote) - PreferencesRowUIView(label: NSLocalizedString("active_url", comment: ""), content: settings.openHABRootUrl).font(.footnote) - PreferencesRowUIView(label: NSLocalizedString("local_url", comment: ""), content: settings.localUrl).font(.footnote) - PreferencesRowUIView(label: NSLocalizedString("remote_url", comment: ""), content: settings.remoteUrl).font(.footnote) - PreferencesRowUIView(label: NSLocalizedString("sitemap", comment: ""), content: settings.sitemapName).font(.footnote) - PreferencesRowUIView(label: NSLocalizedString("username", comment: ""), content: settings.openHABUsername).font(.footnote) - HStack { - Button(action: { AppMessageService.singleton.requestApplicationContext() }, label: { Text(NSLocalizedString("sync_prefs", comment: "")) }) - } - } - } -} - -struct PreferencesSwiftUIView_Previews: PreviewProvider { - static var previews: some View { - PreferencesSwiftUIView() - } -} diff --git a/openHABWatch Extension/Views/Rows/FrameRow.swift b/openHABWatch Extension/Views/Rows/FrameRow.swift deleted file mode 100644 index 1048b6c91..000000000 --- a/openHABWatch Extension/Views/Rows/FrameRow.swift +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2010-2024 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 SwiftUI - -struct FrameRow: View { - @ObservedObject var widget: ObservableOpenHABWidget - @ObservedObject var settings = ObservableOpenHABDataObject.shared - var body: some View { - let gray = Color(UIColor.darkGray) - return VStack { - HStack { - Text(widget.labelText?.uppercased() ?? "") - .font(.callout) - .lineLimit(1) - Spacer() - } - } - .background(gray.edgesIgnoringSafeArea(.all)) - // .background(SwiftUI.Color.yellow.edgesIgnoringSafeArea(.all)) - // .background( Color(color:.systemGray)) - } -} - -struct FrameRow_Previews: PreviewProvider { - static var previews: some View { - let widget = UserData().widgets[6] - return FrameRow(widget: widget) - } -} diff --git a/openHABWatch Extension/Views/Rows/ImageRow.swift b/openHABWatch Extension/Views/Rows/ImageRow.swift deleted file mode 100644 index c80362f46..000000000 --- a/openHABWatch Extension/Views/Rows/ImageRow.swift +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2010-2024 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 Kingfisher -import OpenHABCore -import os.log -import SwiftUI - -struct ImageRow: View { - @State var URL: URL? - - var body: some View { - KFImage(URL) - .onSuccess { retrieveImageResult in - os_log("Success loading icon: %{PUBLIC}s", log: .notifications, type: .debug, "\(retrieveImageResult)") - } - .onFailure { kingfisherError in - os_log("Failure loading icon: %{PUBLIC}s", log: .notifications, type: .debug, kingfisherError.localizedDescription) - } - .placeholder { - Image(systemSymbol: .arrowTriangle2Circlepath) - .font(.callout) - .opacity(0.3) - } - .cancelOnDisappear(true) - .resizable() - .scaledToFit() - } -} - -struct ImageRow_Previews: PreviewProvider { - static var previews: some View { - let iconURL = Endpoint.icon( - rootUrl: PreviewConstants.remoteURLString, - version: 2, - icon: "Switch", - state: "ON", - iconType: .png, - iconColor: "" - ).url - // let widget = UserData().widgets[8] - return ImageRow(URL: iconURL) - } -} diff --git a/openHABWatch Extension/Views/Rows/SegmentRow.swift b/openHABWatch Extension/Views/Rows/SegmentRow.swift deleted file mode 100644 index 3ec61e2a3..000000000 --- a/openHABWatch Extension/Views/Rows/SegmentRow.swift +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) 2010-2024 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 OpenHABCore -import os.log -import SwiftUI - -struct SegmentRow: View { - @ObservedObject var widget: ObservableOpenHABWidget - @ObservedObject var settings = ObservableOpenHABDataObject.shared - - @State private var favoriteColor = 0 - var body: some View { - let valueBinding = Binding( - get: { - guard case let .segmented(value) = widget.stateEnumBinding else { return 0 } - return value - }, - set: { - os_log("Slider new value = %g", log: .default, type: .info, $0) - // self.widget.sendCommand($0) - widget.stateEnumBinding = .segmented($0) - } - ) - return - VStack { - HStack { - IconView(widget: widget, settings: settings) - TextLabelView(widget: widget) - Spacer() - DetailTextLabelView(widget: widget) - } - Picker("Picker", selection: valueBinding) { - ForEach(0 ..< widget.mappingsOrItemOptions.count, id: \.self) { - Text(widget.mappingsOrItemOptions[$0].label).tag($0) - } - } - .labelsHidden() - .frame(height: 100) - .padding(.top, 0) - } - } -} - -struct SegmentRow_Previews: PreviewProvider { - static var previews: some View { - let widget = UserData().widgets[4] - return Group { - SegmentRow(widget: widget) - .previewLayout(.fixed(width: 300, height: 70)) - SegmentRow(widget: widget) - .previewDevice("Apple Watch Series 4 - 44mm") - } - } -} diff --git a/openHABWatch Extension/Views/Rows/SliderRow.swift b/openHABWatch Extension/Views/Rows/SliderRow.swift deleted file mode 100644 index 44cb1ae17..000000000 --- a/openHABWatch Extension/Views/Rows/SliderRow.swift +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) 2010-2024 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 OpenHABCore -import os.log -import SwiftUI - -struct SliderRow: View { - @ObservedObject var widget: ObservableOpenHABWidget - @ObservedObject var settings = ObservableOpenHABDataObject.shared - - var body: some View { - let valueBinding = Binding( - get: { - widget.adjustedValue - }, - set: { - os_log("Slider new value = %g", log: .default, type: .info, $0) - widget.sendCommand($0.valueText(step: widget.step)) - - // self.widget.stateEnumBinding = .slider($0) - } - ) - - return - VStack(spacing: 3) { - HStack { - IconView(widget: widget, settings: settings) - TextLabelView(widget: widget) - Spacer() - DetailTextLabelView(widget: widget) - }.padding(.top, 8) - - Slider(value: valueBinding, in: widget.minValue ... widget.maxValue, step: widget.step) - .labelsHidden() - .focusable(true) - .digitalCrownRotation( - valueBinding, - from: widget.minValue, - through: widget.maxValue, - by: widget.step, - sensitivity: .medium, - isHapticFeedbackEnabled: true - ) - } - } -} - -struct SliderRow_Previews: PreviewProvider { - static var previews: some View { - let widget = UserData().widgets[3] - return Group { - SliderRow(widget: widget) - .previewLayout(.fixed(width: 300, height: 70)) - SliderRow(widget: widget) - .previewDevice("Apple Watch Series 4 - 44mm") - } - } -} diff --git a/openHABWatch Extension/Views/Utils/IconView.swift b/openHABWatch Extension/Views/Utils/IconView.swift deleted file mode 100644 index 55dd1ca89..000000000 --- a/openHABWatch Extension/Views/Utils/IconView.swift +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) 2010-2024 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 Kingfisher -import OpenHABCore -import os.log -import SwiftUI - -struct IconView: View { - @ObservedObject var widget: ObservableOpenHABWidget - @ObservedObject var settings = ObservableOpenHABDataObject.shared - - var iconURL: URL? { - Endpoint.icon( - rootUrl: settings.openHABRootUrl, - version: 2, - icon: widget.icon, - state: widget.item?.state ?? "", - iconType: .png, - iconColor: "" - ).url - } - - var body: some View { - let image = iconURL != nil ? KFImage(source: .network(KF.ImageResource( - downloadURL: iconURL!, - cacheKey: iconURL!.path + (iconURL!.query ?? "") - ))) : KFImage(iconURL) - return image - .onSuccess { retrieveImageResult in - os_log("Success loading icon: %{PUBLIC}s", log: .notifications, type: .debug, "\(retrieveImageResult)") - } - .onFailure { kingfisherError in - os_log("Failure loading icon: %{PUBLIC}s", log: .notifications, type: .debug, kingfisherError.localizedDescription) - } - .placeholder { - Image(systemSymbol: .arrowTriangle2CirclepathCircle) - .font(.callout) - .opacity(0.3) - } - .cancelOnDisappear(true) - .resizable() - .scaledToFit() - .frame(width: 20.0, height: 20.0) - } -} - -struct IconView_Previews: PreviewProvider { - static var previews: some View { - let widget = UserData().widgets[3] - return IconView(widget: widget, settings: ObservableOpenHABDataObject(openHABRootUrl: PreviewConstants.remoteURLString)) - } -} diff --git a/openHABWatch Extension/Views/Utils/Unwrap.swift b/openHABWatch Extension/Views/Utils/Unwrap.swift deleted file mode 100644 index d268726c8..000000000 --- a/openHABWatch Extension/Views/Utils/Unwrap.swift +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2010-2024 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 SwiftUI - -// As explained in https://www.swiftbysundell.com/tips/optional-swiftui-views/ -struct Unwrap: View { - private let value: Value? - private let contentProvider: (Value) -> Content - - var body: some View { - value.map(contentProvider) - } - - init(_ value: Value?, - @ViewBuilder content: @escaping (Value) -> Content) { - self.value = value - contentProvider = content - } -} diff --git a/openHABWatch Extension/openHABWatch Extension/UserData.swift b/openHABWatch Extension/openHABWatch Extension/UserData.swift deleted file mode 100644 index adb06236f..000000000 --- a/openHABWatch Extension/openHABWatch Extension/UserData.swift +++ /dev/null @@ -1,249 +0,0 @@ -// Copyright (c) 2010-2024 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 Alamofire -import Combine -import Foundation -import OpenHABCore -import os.log -import SwiftUI - -// swiftlint:disable:next file_types_order -extension OpenHABCore.Future where Value == ObservableOpenHABSitemapPage.CodingData { - func trafo() -> OpenHABCore.Future { - transformed { data in - data.openHABSitemapPage - } - } -} - -final class UserData: ObservableObject { - @Published var widgets: [ObservableOpenHABWidget] = [] - @Published var showAlert = false - @Published var errorDescription = "" - @Published var showCertificateAlert = false - @Published var certificateErrorDescription = "" - - let decoder = JSONDecoder() - - var openHABSitemapPage: ObservableOpenHABSitemapPage? - - private var commandOperation: Alamofire.Request? - private var currentPageOperation: Alamofire.Request? - private var tracker: OpenHABWatchTracker? - private var dataObjectCancellable: AnyCancellable? - - // Demo - init() { - decoder.dateDecodingStrategy = .formatted(DateFormatter.iso8601Full) - - let data = PreviewConstants.sitemapJson - - do { - // Self-executing closure - // Inspired by https://www.swiftbysundell.com/posts/inline-types-and-functions-in-swift - openHABSitemapPage = try { - let sitemapPageCodingData = try data.decoded(as: ObservableOpenHABSitemapPage.CodingData.self) - return sitemapPageCodingData.openHABSitemapPage - }() - } catch { - os_log("Should not throw %{PUBLIC}@", log: OSLog.remoteAccess, type: .error, error.localizedDescription) - } - - widgets = openHABSitemapPage?.widgets ?? [] - - openHABSitemapPage?.sendCommand = { [weak self] item, command in - self?.sendCommand(item, commandToSend: command) - } - } - - init(url: URL?, refresh: Bool = true) { - loadPage( - url: url, - longPolling: true, - refresh: refresh - ) - } - - init(url: URL?) { - tracker = OpenHABWatchTracker() - tracker?.delegate = self - tracker?.trackedUrl(url) - -// dataObjectCancellable = ObservableOpenHABDataObject.shared.objectRefreshed.sink { _ in -// // New settings updates from the phone app to start a reconnect -// os_log("Settings update received, starting reconnect", log: .remoteAccess, type: .info) -// self.refreshUrl() -// } -// refreshUrl() - } - - init(sitemapName: String = "watch") { - tracker = OpenHABWatchTracker() - tracker?.delegate = self - tracker?.start() - - dataObjectCancellable = ObservableOpenHABDataObject.shared.objectRefreshed.sink { _ in - // New settings updates from the phone app to start a reconnect - os_log("Settings update received, starting reconnect", log: .remoteAccess, type: .info) - self.refreshUrl() - } - refreshUrl() - } - - func request(_ endpoint: Endpoint) -> OpenHABCore.Future { - // Start by constructing a Promise, that will later be - // returned as a Future - let promise = Promise() - - // Immediately reject the promise in case the passed - // endpoint can't be converted into a valid URL - guard let url = endpoint.url else { - promise.reject(with: NetworkingError.invalidURL) - return promise - } - - if currentPageOperation != nil { - currentPageOperation?.cancel() - currentPageOperation = nil - } - - currentPageOperation = NetworkConnection.page( - url: url, - longPolling: true - ) { [weak self] response in - guard self != nil else { return } - - switch response.result { - case let .success(data): - os_log("openHAB 2", log: OSLog.remoteAccess, type: .info) - promise.resolve(with: data) - - case let .failure(error): - os_log("On LoadPage %{PUBLIC}@ code: %d ", log: .remoteAccess, type: .error, error.localizedDescription, response.response?.statusCode ?? 0) - promise.reject(with: error) - } - } - currentPageOperation?.resume() - - return promise - } - - func loadPage(url: URL?, - longPolling: Bool, - refresh: Bool) { - if currentPageOperation != nil { - currentPageOperation?.cancel() - currentPageOperation = nil - } - - currentPageOperation = NetworkConnection.page( - url: url, - longPolling: longPolling - ) { [weak self] response in - guard let self else { return } - - switch response.result { - case let .success(data): - os_log("Page loaded with success", log: OSLog.remoteAccess, type: .info) - do { - // Self-executing closure - // Inspired by https://www.swiftbysundell.com/posts/inline-types-and-functions-in-swift - openHABSitemapPage = try { - let sitemapPageCodingData = try data.decoded(as: ObservableOpenHABSitemapPage.CodingData.self) - return sitemapPageCodingData.openHABSitemapPage - }() - } catch { - os_log("Should not throw %{PUBLIC}@", log: OSLog.remoteAccess, type: .error, error.localizedDescription) - } - - openHABSitemapPage?.sendCommand = { [weak self] item, command in - self?.sendCommand(item, commandToSend: command) - } - - widgets = openHABSitemapPage?.widgets ?? [] - - showAlert = widgets.isEmpty ? true : false - if refresh { loadPage( - url: url, - longPolling: true, - refresh: true - ) } - - case let .failure(error): - os_log("On LoadPage %{PUBLIC}@ code: %d ", log: .remoteAccess, type: .error, error.localizedDescription, response.response?.statusCode ?? 0) - errorDescription = error.localizedDescription - widgets = [] - showAlert = true - } - } - currentPageOperation?.resume() - } - - func sendCommand(_ item: OpenHABItem?, commandToSend command: String?) { - if commandOperation != nil { - commandOperation?.cancel() - commandOperation = nil - } - if let item, let command { - commandOperation = NetworkConnection.sendCommand(item: item, commandToSend: command) - commandOperation?.resume() - } - } - - func refreshUrl() { - if ObservableOpenHABDataObject.shared.haveReceivedAppContext { - showAlert = false - tracker?.selectUrl() - } - } - - func loadPage(_ endpoint: Endpoint) { - request(endpoint) - .decoded(as: ObservableOpenHABSitemapPage.CodingData.self) - .trafo() - .observe { result in - switch result { - case let .failure(error): - os_log("On LoadPage %{PUBLIC}@", log: .remoteAccess, type: .error, error.localizedDescription) - case let .success(page): - self.openHABSitemapPage = page - } - } - } -} - -extension UserData: OpenHABWatchTrackerDelegate { - func openHABTracked(_ openHABUrl: URL?) { - guard let urlString = openHABUrl?.absoluteString else { return } - os_log("openHABTracked: %{PUBLIC}@", log: .remoteAccess, type: .error, urlString) - - if !ObservableOpenHABDataObject.shared.haveReceivedAppContext { - AppMessageService.singleton.requestApplicationContext() - errorDescription = NSLocalizedString("settings_not_received", comment: "") - showAlert = true - return - } - - ObservableOpenHABDataObject.shared.openHABRootUrl = urlString - - let url = Endpoint.watchSitemap(openHABRootUrl: urlString, sitemapName: ObservableOpenHABDataObject.shared.sitemapName).url - loadPage(url: url, longPolling: false, refresh: true) - } - - func openHABTrackingProgress(_ message: String?) { - os_log("openHABTrackingProgress: %{PUBLIC}@", log: .remoteAccess, type: .error, message ?? "") - } - - func openHABTrackingError(_ error: Error) { - os_log("openHABTrackingError: %{PUBLIC}@", log: .remoteAccess, type: .error, error.localizedDescription) - } -} diff --git a/openHABWatch Extension/openHABWatch Extension/app/AppState.swift b/openHABWatch Extension/openHABWatch Extension/app/AppState.swift deleted file mode 100644 index 111317713..000000000 --- a/openHABWatch Extension/openHABWatch Extension/app/AppState.swift +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) 2010-2024 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 Foundation - -class AppState { - static let singleton = AppState() - - var active = false -} diff --git a/openHABWatch/Assets.xcassets/AppIcon.appiconset/Contents.json b/openHABWatch/Assets.xcassets/AppIcon.appiconset/Contents.json index 83075e829..5471514b4 100644 --- a/openHABWatch/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/openHABWatch/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,92 +1,20 @@ { "images" : [ { - "size" : "24x24", - "idiom" : "watch", - "filename" : "Icon-24@2x.png", - "scale" : "2x", - "role" : "notificationCenter", - "subtype" : "38mm" + "filename" : "ItunesArtwork@2x 1.png", + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" }, { - "size" : "27.5x27.5", - "idiom" : "watch", - "filename" : "Icon-27.5@2x.png", - "scale" : "2x", - "role" : "notificationCenter", - "subtype" : "42mm" - }, - { - "size" : "29x29", - "idiom" : "watch", - "filename" : "Icon-29@2x.png", - "role" : "companionSettings", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "watch", - "filename" : "Icon-29@3x.png", - "role" : "companionSettings", - "scale" : "3x" - }, - { - "size" : "40x40", - "idiom" : "watch", - "filename" : "Icon-40@2x.png", - "scale" : "2x", - "role" : "appLauncher", - "subtype" : "38mm" - }, - { - "size" : "44x44", - "idiom" : "watch", - "filename" : "icon-88.png", - "scale" : "2x", - "role" : "appLauncher", - "subtype" : "40mm" - }, - { - "size" : "50x50", - "idiom" : "watch", - "filename" : "icon-100.png", - "scale" : "2x", - "role" : "appLauncher", - "subtype" : "44mm" - }, - { - "size" : "86x86", - "idiom" : "watch", - "filename" : "Icon-86@2x.png", - "scale" : "2x", - "role" : "quickLook", - "subtype" : "38mm" - }, - { - "size" : "98x98", - "idiom" : "watch", - "filename" : "Icon-98@2x.png", - "scale" : "2x", - "role" : "quickLook", - "subtype" : "42mm" - }, - { - "size" : "108x108", - "idiom" : "watch", - "filename" : "icon-216@2x.png", - "scale" : "2x", - "role" : "quickLook", - "subtype" : "44mm" - }, - { - "size" : "1024x1024", - "idiom" : "watch-marketing", "filename" : "ItunesArtwork@2x.png", - "scale" : "1x" + "idiom" : "universal", + "platform" : "watchos", + "size" : "1024x1024" } ], "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 } -} \ No newline at end of file +} diff --git a/openHABWatch/Assets.xcassets/AppIcon.appiconset/Icon-24@2x.png b/openHABWatch/Assets.xcassets/AppIcon.appiconset/Icon-24@2x.png deleted file mode 100644 index ddaeb8a83717940cd1b9357ec9cc468147160ba8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2716 zcmV;N3S;$&P)()&+wT(2TH5xV9e?+Z;6c^%>*j5QO;m3QBLcTP?YBqh2+tX~JxwWDd;z`#InZ|{{WR|0_mrBo0Ep67L$F=eT$s;Vl- zaRmhhn>TOXwr$%z_uK=SqB_v-zo~o_gk)XLz1Z)&44g*s|f_ z;bX^+{qoB%4u>O=NQ6S6qN1X$TesHL)m2nf7>&k^Yv}*Fz$Kc?g)9I9DxwyFa?YG}vw{Bg!jV}UZuYEq> z>#x5~Ddl-ymgVN==H}*Rgb*Qw((!x0Ds9(?e@=bn3xJzrih6o3N4fN&NjcCgWCJb3V6ZfgnU8p3uCqD(`32zkEKF?d+O>5mIQ%$7YK&v)N_XR%l!k;o&DJR*wXvUw+!rspjzxj<8a)EjUyKl3e{Aq#DL?lUD?!+Runj@7Ds; zzzf)5$gVqf+@?*NL{S8Qa5y|VI;zWs*TpzKJ}wA?qA2C%<(YHxO`1asG)jyjctfeYjB%3!mMg!nzJ8iCg3{({eu|IoM-18Edn+A@_DYHE>KQ|hUg@uLeD(Cfj z^|uS`kw_#GiLd~;ZrwUq5_{5QLzOrMuH6or3Oo;#0wMNij{rcZyHl4F09e!H z#N5T{bZVN$5)>poePL1}k~F z0L*4HJ24uK>K>h;3|f?2mZdqph$g9wRHjgOC;l}iNW0W7yk@sxCZ}*X%;qgi(|+1q zlSY$?DZ8BXgDe({&a~i1R;!iWiveJ2YHE4e0Q0HLG&&PPjLEj=CBkAsN_?V(u;cxH zKgV&JrrGUwT{D>3yv1U1xm>J>nVg&iX4DyI&X{W-%SMyNwBUEbg5O0xzko1C2t^{1 z$;nAU5C|db*RO}vz{q};mzU4Z&fay`UAv!tngYcf$9!s$rqbm33uhWsvl1UI(hEsHmu@_*+LuUVc6Wn1A7VTJa0l@HohojLb&+~S>edETBi-1@FsIIQQ|Nc#RdHEDTe)mu)m8Sj7s%e%o z9R-e;-)R>cTMeZZ2}S9@bjfHm#$vIms;Yv5f<neC5%wg2TGmfFYsQ{GdjPO$|`ij`ZT;W)qF z|H><`#N%ZI)40{Z@wuhDf#r%Puttu=jZ2H z&9Ev_vB@0AUAuN||Ni|y{`jLLNi#Du)z#H4EiD=E?3s!Rgb>D0KKW#BZmulLPN%c4 zuW#SJeM3V-tTfiYEF%PyvR>>GLO%NFqZeO%(c|&h?e>|OnS1ZO_weDvCX)#=ReYJ- zF^v7{)vHI29P#`8k|c%0VM^)44?o<{&~WFScP^0uO=-&NXAnXL2M2q4dcOVkTdUQ| z^Ze}W?B>mzj~+eBJZq)x7=1g8vB%>%cI?>j@UY!(XPpqU+5Er*57gJ!-*?}A1qB7^ zo5thupMU;&czC$4uWw{z1R-Rz*&>lhJRaYFc|dv{Sy-tUavP43K@+?v)Ro0ZY3opO-)UY zKKdx6-N;q}l)89qZ0y{*a{~hdp-{+VG8v6VLP#Q!NF)->J7B@~upkJmRUM1P6h+C; z&)>FfTSG&GBuVcw(^_LWtuyy*I*)owW%>Q7kVn zudAzj=%I&PE*C8Bbgv1Bjnww9q9|iyW22*^Znt}CYAP5EDvE*-GMP-0Bo!7GmY0`r z+_;gIQ?TL=_3D7qu~LVss!Uo-p0BnAxN0Ca^r)Kt56jJfyGo8V0cAvlHUBZi#{U4- WaQl_Z1A8F=0000K4|V52Y37q<`P#K> z-+%x8&6_uUKA$Yhx~|7J4I#_24u>NzFYl2@9;vLXEGa3Wd>G?7>6$F1(XQX`KXc~H z*I$3_^?EVJJkRqy&oB(_-e}FB(KIawOW@gTjqAVtE#Fj77Hzzq^LKwjE?l^f2?m3|{PN3%3m4kj+I&7AWyKhej*jN!HLF*zwpc8*Fvi#zlDWFsodbcu znKNfvTU!HxfFwx>Az79ghI#3wm)vgm%%F)W=^u4nKXBl{mtTIFmX-zpkY!mAgxcEL zXP$XR5CmFa)_pr}XZ`cfKaU+d_SIKk34*|JoT4bPSZw?D?Hf04oB=d3C9TlZ)a3Da zC}J=eT)1#yeSLjNNeP(OwnqrT7&8n50BCJ(J$m%0rfGs8sHz%^#TptKHf-219cThd zTC}C5<-PabGZ4$l%69MGot~bq>pDVc-iMyC>9)7G@7uR86bf0bRz*=Dgm1t7c1cM| zLeTi%X`%M^_K!dQ*x_&(h_Ai&8bvg=#`zh95Fw=NdRbZ7fddCbQH(~TJkKkN($v%x z3lGLIA;Fwmq0(7+u#Ne)!>6 zUU>yVsH&dMN>U@%BszPY)Xy5_W$0D#uk*8cu}i^U?#a%pMl(@#I0 zl!{mfh*59D_8E`y(5+T;$zHVrD0A0hO5$T1!j@s=g)tSDpng2@_9vw75 z2WM22YL=6elbM;RC<@1Me!suJzu!=Bg0i=_*TBlp&j-`IUni;9=QSZVIyS!yFa}sh z_SE#fC;0MpX3!ZFrH LRMCmrfCergu~&1fq?{+LqkLKgJGDAj0}))0~$vhG^-e< zi1h&L078HmfHAVCr0+Yym&YqQ9Vn$SZZoQ?8a$IIWm%?UVp&!c#Tiws(fx*sqtaFb z5dk_dgvLRe`IYOEpL$7>s5myZW-!KzqJXJ0PUjawsO!3U9FtURsKI?^#61&;V9N5CQ1k@9GO4N8G;O>pqR)Y` zQ`9J7x7&@kPAC*gfVis~_jN-tWwN_WgBY)9^VBsub?Qe(M(Cd&U<)U*t zK}prl&CPW<94?pZ_19l7C@6r8p`sVrQ{vqvNfoD4^e^l1=paN4;w)GW0)zkn9UUE! zNQ54K4?Xmd`NlpLWhI1g9Jg`f#+55qW@l$(0QB2k0}Y#We;ne=^F*AY=)m5;EA8h2 zWJLF~2r;^lq(dSjGS*iD-@0RRX^+*PCdy=baO&l@oww7Gxh-$*!U zS+xNG(0Su}S67$SYK_HWSy@@jmoEpV!*5c=nqVCuM!WsvF;$j80fkz%O8C3 z0RVtum{2IRcJ125ix(hGZ}&Girf#IXO3bPFZ~GR%h` ze)#LJzlx$5i^Wn?Q)_E$!IVqmf1VD%#9FLA)EyPaQX7(hK7dp^z^2tru_W; z`vPhNw9cMA`_@};aU92S+{nmCMMcG%Z@x*-zqqUIH1SISAR+($_S-k!cmrdss_Fv| zJkZ$KSX^8@zf_1}hE5)j=iPVTrHHaDJDtwMhY!14uDEC|wZxAvf-!*b?%lh?!@~^2 zSglsS-(O!}|HT(y(6Q3s?_BweEW)8fhYlV*$n!kMagj*GX0tUmHo9D{sj(MovqY>v z`Q(#h$BxFw=xI2;HeMNwo~PD@K$xpL*> zk3U{qTht;DfB*gS=g$KGL{T(YA%tmZY1!G?+1c4nr<2a3qA0_|!+}7cr>Do~^MyhomSwG0 ztC8h!I2_g0)pd1sEX&?&z9$Y80C4f*#g>+qpMLs@5Ms00Xdp=)x45PdLLA5OJkPQ$ zAtV-yQAc^=i6`pn>J}|p1WYNV`#=dyNi6 zG&%qXVPd=&*8q%XnUcx<%(|`4YV)Tw%>1t#artrc&wH`^K>0tg{{YoH VO4Yvtk7ED;002ovPDHLkV1k=f6h#04 diff --git a/openHABWatch/Assets.xcassets/AppIcon.appiconset/Icon-29@2x.png b/openHABWatch/Assets.xcassets/AppIcon.appiconset/Icon-29@2x.png deleted file mode 100644 index fb09d700b5b51ff2b2863174febbd7cadcf49613..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3451 zcmV->4TSQEP);&@o_lBRygGHJ540V`E=z=gDX}J{f>yR6O)w-RplhldD8`_%U8C$KwrFA# zqC^TQKC+mINC71hW7utrrGH?ISrz-hg*Gv^KqSR>O3OU%z4N&DoU?zN&h7L)l)B0O z{%D%aJ?DJx?|jei{LcAZ#2ADB9}^d)7yi!af4L!q_+S3d-5a_a?=r@Cb3qX1eV9@T zca6S4Tt2o*sq6Z!TepJ2;OOY6s;ZPy#+W2Y+1c4%uQx9*&*Sl=w_Pyw9pk1CHZn5O z)6>(_)6?JI9}EUnRn>K!5Hj91LZT>2lH_)~3knKWu3TACQsVdfZ8qD2q3-~fKgkE^ z?(S}HZ}05v92ptmjub^v6h%Q0Oad+yN~vKOx~?0BVX;`2E?v4|!-mSrN}tcip)(QE z9pjq)c6WE5K7G2Yt1FpI%Cc;+SOh^}jBzGH2v-94oFEANH892qAwozz9#1Bd_uO+& zMMcHaPd~k6$rAoz8M-+mT+TW=I(qcz(f0Os!!Yc2JI0tXmPjNLi3CE(<#KsE9*@W4 za=GkwJEc@nlyEpaIyxE(g)~jW7|XIONfH1glSxg}^78Vks;aha+lCOz(9QGX@{Yd$ z{`?b@{^B_%6XtjNpDb2uDR+J?j7n>TOv_V#vl zbzQk~B^(ahY&MI3@a^&R6lTN3T&wex-Ehs2>_St7ED=YcTngMk>pV<%ZivJo62G5*1bN1|6 zUDxe)I{?IDF~vaZ1;9 zQ50W$?X~jq^1IoSrjG&uhYue9J$SqS5Gd9}80&6GBd%I>q7Q@wm_D+r4|Yxt!-`MTk){w*Q6b7ykex044J_;$HN4 zJhip8lu}Bm&1SoL^=fNt>s+{e4Rv*OUAlCM@1nY{S65eOXJ==$r!xi!7%@TzYP8l* zB1c|V|8)!moH=n>S=q*o8x=)C2wAPxmX;PpQMklsz~w+~ZEc2OV2m|Q3j_iiH*U$)tbQ@|JjC3K%a<=ND=X79jr;EF zufK-L;cNmI06IH6$HvAaNs7ngg@uKWJn{(46#QmmRojjW*&d(_CQS!Q;4`>C&Z3{6!Oq#KR9i>~gudpyy+yp~hOR?KpOO zfdSJKfJH_K5W}KJdb_bkZ9Oiyy#T-xF|a#5`#y92242gNxYq#6|et$BVyt9mb0 z!ocVRaZ5%zUbSi!cOu64`t|GSYkl0i05CK(#B+XK*K>1odCoPbUrFddjn>wTvpnN| zb+|kYC#}UBfEYljd*@!~&N`}aA7jBHhnrqiGtlw<_up@|S}CQXCTNh_4Xg)30E>W7inyLCA(MC_y3OQcKAhL< zwcG7{t5Q`p5{Z}(Oo$;GjdDIpDNh<_2w`b@)!Jrb#eC!xalLa#JyF8IAf<{uO3Pe6 zb~>Fln~i4#{D3qGm%o#FKfoB9a^y<)Du@yLQwOC6tP8)^Jlw z$1@RQj3r6plGSxR9*;x17^WMUK2xcfb-S@vZ96Vxc>tx>R=NhJ*aY!j*SL;TK5m*n zR`A(Q-%~{soFBXZKoA5~RUthrm}{%CCf3%Bv%CPn;;FTju7T;sJE7FQb1wi=K6y)U zy3JSt0M0GdKnVyF%?-ogmjV33#cH*hFcV^MyWM;zL$gcsLr30sy0w>-F}58m(<& zFF={IP9@&!+EGU*bext~r0z3$@Ztv$i%XU)aX1`|F+xZ(nbdV180B#w z)L5gPJ1)4rre5dQz#PQYdtH-#9O63&LX1)XxOVMYGMU5}8-|gepD)X@8B!;3b8~a= zyYIeeH0pM{Uw{2|kH^CR5T&8U8nyL=kkab{Stk=`?cD1ck8b08UZ`nL;y?cuL=gab zdwb1bRa8_2Q*s6Xpp;6Iv~1Zj*=pUlZ(kq~V3Z=tcs_trG3%~ar~0^lJXQb$0GyqJ zy!Rr2+hb#WeSLga!x;Ph{`A&jsuKhNk3ar+MMZ_*?$K%Dt#U76*Jr|f1*cqe17*INP@a0(R@!yLzotUw#U3;x- zAH{!IgAnTM>gwt4;U`6maYaQ1Ouqe{d=dsg0uFufTCC-mko|kIn#2epK=MQ7NDvG{ zPMkQwGn-f}#)|_mxlS{A6J`Jag3SpSBSAD-ErIoHNpWWTv4u^wM zN(kAuZ5ux;q(3&j%LCD5Y4G1_lO>9zANa z*$_gis;*tTw!FN2`XPK8E~VJ*bv?5OIkP zswznmAw-g-=bwL`CuLKfpO%pc0x)LVxGnb|7p!X@0f3g4mKR@q@zYN~2KjzdZ+_hSA#A*3{G_iefUEtgf!!v113^d39+<<4YPFW!W$cRaLia*-~3u z%TxUY-}0Jm2L=ZA@88ca&;dYElx5479Xxn2CnsmNYp%I!6991T+_?h>4oH&3l@y6Y z{C@vSFTE591YlaJb#60DEL>D)&z}AGprF8X*m!rdlv2_U1>N1P%9Ua5N!=fn4vMh=sUppz1}rz)>KqftXsE^pKpJ!4+Kn0uRKyp2L=W%U%uSe z*LUN_jj^#YP1BOeBzKq~2(m0Y9FDxayrQC_)vH&pUcEX$KYz-b-;piwr|JLz diff --git a/openHABWatch/Assets.xcassets/AppIcon.appiconset/Icon-29@3x.png b/openHABWatch/Assets.xcassets/AppIcon.appiconset/Icon-29@3x.png deleted file mode 100644 index 2ad0f8e390f21e4e61c3acdc9612652efa852134..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5556 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 diff --git a/openHABWatch/Assets.xcassets/AppIcon.appiconset/Icon-40@2x.png b/openHABWatch/Assets.xcassets/AppIcon.appiconset/Icon-40@2x.png deleted file mode 100644 index b3e172f3be8ada3c44c9b13cd55b08853762a18c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4959 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 Lv>#U^tls<|iR`G_ diff --git a/openHABWatch/Assets.xcassets/AppIcon.appiconset/Icon-86@2x.png b/openHABWatch/Assets.xcassets/AppIcon.appiconset/Icon-86@2x.png deleted file mode 100644 index 17f389b20a6b2677e79e342f850b48eabc24a6d8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14007 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 diff --git a/openHABWatch/Assets.xcassets/AppIcon.appiconset/Icon-98@2x.png b/openHABWatch/Assets.xcassets/AppIcon.appiconset/Icon-98@2x.png deleted file mode 100644 index d0247b851f2ccac276280d43f2c40affe3847cdc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17356 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 Qzoi2rFRcQrlr#@!A)vL*XYifkFi8pbjqJK6Uw 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 literal 0 HcmV?d00001 diff --git a/openHABWatch/Assets.xcassets/AppIcon.appiconset/icon-100.png b/openHABWatch/Assets.xcassets/AppIcon.appiconset/icon-100.png deleted file mode 100644 index ecef5b4bf9d4bfb909255f2cee6670ce4d31d433..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14812 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 diff --git a/openHABWatch/Assets.xcassets/AppIcon.appiconset/icon-216@2x.png b/openHABWatch/Assets.xcassets/AppIcon.appiconset/icon-216@2x.png deleted file mode 100644 index acdc92b1ed85c633df9ca0bd7d69e1f02076e9d5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20415 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 diff --git a/openHABWatch/Assets.xcassets/AppIcon.appiconset/icon-88.png b/openHABWatch/Assets.xcassets/AppIcon.appiconset/icon-88.png deleted file mode 100644 index 7b493dff38f776b10c20b67f5d60fa3d3612da98..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14377 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 gjIrWguQ OpenHABCore.Future { + transformed { data in + data.openHABSitemapPage + } + } +} + +final class UserData: ObservableObject { + static let shared = UserData() + @Published var widgets: [ObservableOpenHABWidget] = [] + @Published var showAlert = false + @Published var errorDescription = "" + @Published var showCertificateAlert = false + @Published var certificateErrorDescription = "" + + let decoder = JSONDecoder() + + var openHABSitemapPage: ObservableOpenHABSitemapPage? + + private var commandOperation: Alamofire.Request? + private var currentPageOperation: Alamofire.Request? + private var cancellables = Set() + + private let logger = Logger(subsystem: "org.openhab.app.watch", category: "UserData") + + // Demo + init() { + decoder.dateDecodingStrategy = .formatted(DateFormatter.iso8601Full) + + let data = PreviewConstants.sitemapJson + + do { + // Self-executing closure + // Inspired by https://www.swiftbysundell.com/posts/inline-types-and-functions-in-swift + openHABSitemapPage = try { + let sitemapPageCodingData = try data.decoded(as: ObservableOpenHABSitemapPage.CodingData.self) + return sitemapPageCodingData.openHABSitemapPage + }() + } catch { + logger.error("Should not throw \(error.localizedDescription)") + } + + widgets = openHABSitemapPage?.widgets ?? [] + + openHABSitemapPage?.sendCommand = { [weak self] item, command in + self?.sendCommand(item, commandToSend: command) + } + } + + init(sitemapName: String = "watch") { + updateNetworkTracker() + NetworkTracker.shared.$activeConnection + .receive(on: DispatchQueue.main) + .sink { [weak self] activeConnection in + if let activeConnection { + self?.logger.error("openHABTracked: \(activeConnection.configuration.url)") + + if !ObservableOpenHABDataObject.shared.haveReceivedAppContext { + AppMessageService.singleton.requestApplicationContext() + self?.errorDescription = NSLocalizedString("settings_not_received", comment: "") + self?.showAlert = true + return + } + + ObservableOpenHABDataObject.shared.openHABRootUrl = activeConnection.configuration.url + ObservableOpenHABDataObject.shared.openHABVersion = activeConnection.version + + let url = Endpoint.watchSitemap(openHABRootUrl: activeConnection.configuration.url, sitemapName: ObservableOpenHABDataObject.shared.sitemapForWatch).url + self?.loadPage(url: url, longPolling: false, refresh: true) + } + } + .store(in: &cancellables) + + ObservableOpenHABDataObject.shared.objectRefreshed.sink { _ in + // New settings updates from the phone app to start a reconnect + self.logger.info("Settings update received, starting reconnect") + self.updateNetworkTracker() + } + .store(in: &cancellables) + } + + func updateNetworkTracker() { + if !ObservableOpenHABDataObject.shared.localUrl.isEmpty || !ObservableOpenHABDataObject.shared.remoteUrl.isEmpty { + let connection1 = ConnectionConfiguration( + url: ObservableOpenHABDataObject.shared.localUrl, + priority: 0 + ) + let connection2 = ConnectionConfiguration( + url: ObservableOpenHABDataObject.shared.remoteUrl, + priority: 1 + ) + NetworkTracker.shared.startTracking(connectionConfigurations: [connection1, connection2], username: ObservableOpenHABDataObject.shared.openHABUsername, password: ObservableOpenHABDataObject.shared.openHABPassword, alwaysSendBasicAuth: ObservableOpenHABDataObject.shared.openHABAlwaysSendCreds) + } + } + + func loadPage(url: URL?, + longPolling: Bool, + refresh: Bool) { + if currentPageOperation != nil { + currentPageOperation?.cancel() + currentPageOperation = nil + } + + currentPageOperation = NetworkConnection.page( + url: url, + longPolling: longPolling + ) { [weak self] response in + guard let self else { return } + + switch response.result { + case let .success(data): + logger.info("Page loaded with success") + do { + // Self-executing closure + // Inspired by https://www.swiftbysundell.com/posts/inline-types-and-functions-in-swift + openHABSitemapPage = try { + let sitemapPageCodingData = try data.decoded(as: ObservableOpenHABSitemapPage.CodingData.self) + return sitemapPageCodingData.openHABSitemapPage + }() + } catch { + logger.error("Should not throw \(error.localizedDescription)") + } + + openHABSitemapPage?.sendCommand = { [weak self] item, command in + self?.sendCommand(item, commandToSend: command) + } + + widgets = openHABSitemapPage?.widgets ?? [] + + showAlert = widgets.isEmpty ? true : false + if refresh { loadPage( + url: url, + longPolling: true, + refresh: true + ) } + + case let .failure(error): + logger.error("On LoadPage \"\(error.localizedDescription)\" with code: \(response.response?.statusCode ?? 0)") + errorDescription = error.localizedDescription + widgets = [] + showAlert = true + } + } + currentPageOperation?.resume() + } + + func sendCommand(_ item: OpenHABItem?, commandToSend command: String?) { + if commandOperation != nil { + commandOperation?.cancel() + commandOperation = nil + } + if let item, let command { + commandOperation = NetworkConnection.sendCommand(item: item, commandToSend: command) + commandOperation?.resume() + } + } + + func refreshUrl() { + if ObservableOpenHABDataObject.shared.haveReceivedAppContext, !ObservableOpenHABDataObject.shared.openHABRootUrl.isEmpty { + showAlert = false + let url = Endpoint.watchSitemap(openHABRootUrl: ObservableOpenHABDataObject.shared.openHABRootUrl, sitemapName: ObservableOpenHABDataObject.shared.sitemapForWatch).url + loadPage(url: url, longPolling: false, refresh: true) + } + } +} diff --git a/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Contents.json b/openHABWatch/Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Contents.json similarity index 100% rename from openHABWatch Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Contents.json rename to openHABWatch/Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Contents.json diff --git a/openHABWatch Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Contents.json b/openHABWatch/Extension/Assets.xcassets/Complication.complicationset/Contents.json similarity index 84% rename from openHABWatch Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Contents.json rename to openHABWatch/Extension/Assets.xcassets/Complication.complicationset/Contents.json index 1571c7e53..e8b3252e3 100644 --- a/openHABWatch Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Contents.json +++ b/openHABWatch/Extension/Assets.xcassets/Complication.complicationset/Contents.json @@ -1,48 +1,53 @@ { "assets" : [ { - "idiom" : "watch", "filename" : "Circular.imageset", + "idiom" : "watch", "role" : "circular" }, { - "idiom" : "watch", "filename" : "Extra Large.imageset", + "idiom" : "watch", "role" : "extra-large" }, { - "idiom" : "watch", "filename" : "Graphic Bezel.imageset", + "idiom" : "watch", "role" : "graphic-bezel" }, { - "idiom" : "watch", "filename" : "Graphic Circular.imageset", + "idiom" : "watch", "role" : "graphic-circular" }, { - "idiom" : "watch", "filename" : "Graphic Corner.imageset", + "idiom" : "watch", "role" : "graphic-corner" }, { + "filename" : "Graphic Extra Large.imageset", "idiom" : "watch", + "role" : "graphic-extra-large" + }, + { "filename" : "Graphic Large Rectangular.imageset", + "idiom" : "watch", "role" : "graphic-large-rectangular" }, { - "idiom" : "watch", "filename" : "Modular.imageset", + "idiom" : "watch", "role" : "modular" }, { - "idiom" : "watch", "filename" : "Utilitarian.imageset", + "idiom" : "watch", "role" : "utilitarian" } ], "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 } -} \ No newline at end of file +} diff --git a/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Extra Large.imageset/Contents.json b/openHABWatch/Extension/Assets.xcassets/Complication.complicationset/Extra Large.imageset/Contents.json similarity index 100% rename from openHABWatch Extension/Assets.xcassets/Complication.complicationset/Extra Large.imageset/Contents.json rename to openHABWatch/Extension/Assets.xcassets/Complication.complicationset/Extra Large.imageset/Contents.json diff --git a/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Graphic Bezel.imageset/Contents.json b/openHABWatch/Extension/Assets.xcassets/Complication.complicationset/Graphic Bezel.imageset/Contents.json similarity index 100% rename from openHABWatch Extension/Assets.xcassets/Complication.complicationset/Graphic Bezel.imageset/Contents.json rename to openHABWatch/Extension/Assets.xcassets/Complication.complicationset/Graphic Bezel.imageset/Contents.json diff --git a/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/Contents.json b/openHABWatch/Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/Contents.json similarity index 100% rename from openHABWatch Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/Contents.json rename to openHABWatch/Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/Contents.json diff --git a/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Graphic Corner.imageset/Contents.json b/openHABWatch/Extension/Assets.xcassets/Complication.complicationset/Graphic Corner.imageset/Contents.json similarity index 100% rename from openHABWatch Extension/Assets.xcassets/Complication.complicationset/Graphic Corner.imageset/Contents.json rename to openHABWatch/Extension/Assets.xcassets/Complication.complicationset/Graphic Corner.imageset/Contents.json diff --git a/openHABWatch/Extension/Assets.xcassets/Complication.complicationset/Graphic Extra Large.imageset/Contents.json b/openHABWatch/Extension/Assets.xcassets/Complication.complicationset/Graphic Extra Large.imageset/Contents.json new file mode 100644 index 000000000..26454cac8 --- /dev/null +++ b/openHABWatch/Extension/Assets.xcassets/Complication.complicationset/Graphic Extra Large.imageset/Contents.json @@ -0,0 +1,25 @@ +{ + "images" : [ + { + "idiom" : "watch", + "scale" : "2x" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : "<=145" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">183" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "auto-scaling" : "auto" + } +} diff --git a/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Graphic Large Rectangular.imageset/Contents.json b/openHABWatch/Extension/Assets.xcassets/Complication.complicationset/Graphic Large Rectangular.imageset/Contents.json similarity index 100% rename from openHABWatch Extension/Assets.xcassets/Complication.complicationset/Graphic Large Rectangular.imageset/Contents.json rename to openHABWatch/Extension/Assets.xcassets/Complication.complicationset/Graphic Large Rectangular.imageset/Contents.json diff --git a/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Contents.json b/openHABWatch/Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Contents.json similarity index 100% rename from openHABWatch Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Contents.json rename to openHABWatch/Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Contents.json diff --git a/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json b/openHABWatch/Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json similarity index 100% rename from openHABWatch Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json rename to openHABWatch/Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json diff --git a/openHABWatch Extension/Assets.xcassets/Contents.json b/openHABWatch/Extension/Assets.xcassets/Contents.json similarity index 100% rename from openHABWatch Extension/Assets.xcassets/Contents.json rename to openHABWatch/Extension/Assets.xcassets/Contents.json diff --git a/openHABWatch Extension/Assets.xcassets/OHIcon.imageset/Contents.json b/openHABWatch/Extension/Assets.xcassets/OHIcon.imageset/Contents.json similarity index 100% rename from openHABWatch Extension/Assets.xcassets/OHIcon.imageset/Contents.json rename to openHABWatch/Extension/Assets.xcassets/OHIcon.imageset/Contents.json diff --git a/openHABWatch Extension/Assets.xcassets/OHIcon.imageset/Icon.png b/openHABWatch/Extension/Assets.xcassets/OHIcon.imageset/Icon.png similarity index 100% rename from openHABWatch Extension/Assets.xcassets/OHIcon.imageset/Icon.png rename to openHABWatch/Extension/Assets.xcassets/OHIcon.imageset/Icon.png diff --git a/openHABWatch Extension/Assets.xcassets/OHTemplateIcon.imageset/Contents.json b/openHABWatch/Extension/Assets.xcassets/OHTemplateIcon.imageset/Contents.json similarity index 100% rename from openHABWatch Extension/Assets.xcassets/OHTemplateIcon.imageset/Contents.json rename to openHABWatch/Extension/Assets.xcassets/OHTemplateIcon.imageset/Contents.json diff --git a/openHABWatch Extension/Assets.xcassets/OHTemplateIcon.imageset/oh_logo_template.pdf b/openHABWatch/Extension/Assets.xcassets/OHTemplateIcon.imageset/oh_logo_template.pdf similarity index 100% rename from openHABWatch Extension/Assets.xcassets/OHTemplateIcon.imageset/oh_logo_template.pdf rename to openHABWatch/Extension/Assets.xcassets/OHTemplateIcon.imageset/oh_logo_template.pdf diff --git a/openHABWatch Extension/ComplicationController.swift b/openHABWatch/Extension/ComplicationController.swift similarity index 100% rename from openHABWatch Extension/ComplicationController.swift rename to openHABWatch/Extension/ComplicationController.swift diff --git a/openHABWatch Extension/Info.plist b/openHABWatch/Extension/Info.plist similarity index 96% rename from openHABWatch Extension/Info.plist rename to openHABWatch/Extension/Info.plist index 7682d34a1..722d3a373 100644 --- a/openHABWatch Extension/Info.plist +++ b/openHABWatch/Extension/Info.plist @@ -32,7 +32,7 @@ NSExtensionAttributes WKAppBundleIdentifier - org.openhab.app.watchkitapp + org.openhab.app.watch NSExtensionPointIdentifier com.apple.watchkit diff --git a/openHABWatch Extension/NotificationController.swift b/openHABWatch/Extension/NotificationController.swift similarity index 100% rename from openHABWatch Extension/NotificationController.swift rename to openHABWatch/Extension/NotificationController.swift diff --git a/openHABWatch Extension/NotificationView.swift b/openHABWatch/Extension/NotificationView.swift similarity index 78% rename from openHABWatch Extension/NotificationView.swift rename to openHABWatch/Extension/NotificationView.swift index 7f569e3b7..05d9aad56 100644 --- a/openHABWatch Extension/NotificationView.swift +++ b/openHABWatch/Extension/NotificationView.swift @@ -33,13 +33,9 @@ struct NotificationView: View { } } -struct NotificationView_Previews: PreviewProvider { - static var previews: some View { - Group { - NotificationView() - - NotificationView(customTextLabel: "Light 2", customDetailTextLabel: "Off") - } - .previewLayout(.sizeThatFits) +#Preview { + Group { + NotificationView() + NotificationView(customTextLabel: "Light 2", customDetailTextLabel: "Off") } } diff --git a/openHABWatch/Extension/OpenHABImageDownloaderOperation.swift b/openHABWatch/Extension/OpenHABImageDownloaderOperation.swift new file mode 100644 index 000000000..2532af296 --- /dev/null +++ b/openHABWatch/Extension/OpenHABImageDownloaderOperation.swift @@ -0,0 +1,26 @@ +// Copyright (c) 2010-2024 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 Foundation +import OpenHABCore +import SDWebImage + +class OpenHABImageDownloaderOperation: SDWebImageDownloaderOperation, @unchecked Sendable { + override func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { + let (disposition, credential) = onReceiveSessionChallenge(with: challenge) + completionHandler(disposition, credential) + } + + override func urlSession(_ session: URLSession, task: URLSessionTask, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { + let (disposition, credential) = onReceiveSessionTaskChallenge(with: challenge) + completionHandler(disposition, credential) + } +} diff --git a/openHABWatch/Extension/OpenHABWatchAppDelegate.swift b/openHABWatch/Extension/OpenHABWatchAppDelegate.swift new file mode 100644 index 000000000..584d2f42f --- /dev/null +++ b/openHABWatch/Extension/OpenHABWatchAppDelegate.swift @@ -0,0 +1,80 @@ +// Copyright (c) 2010-2024 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 OpenHABCore +import os.log + +import WatchConnectivity +import WatchKit + +class OpenHABWatchAppDelegate: NSObject { + var session: WCSession + let delegate: WCSessionDelegate + + override init() { + delegate = AppMessageService.singleton + session = .default + session.delegate = delegate + session.activate() + super.init() + } +} + +extension OpenHABWatchAppDelegate: WKApplicationDelegate { + func handle(_ backgroundTasks: Set) { + // Sent when the system needs to launch the application in the background to process tasks. Tasks arrive in a set, so loop through and process each one. + for task in backgroundTasks { + // Use a switch statement to check the task type + switch task { + case let backgroundTask as WKApplicationRefreshBackgroundTask: + // Be sure to complete the background task once you’re done. + backgroundTask.setTaskCompletedWithSnapshot(false) + case let snapshotTask as WKSnapshotRefreshBackgroundTask: + // Snapshot tasks have a unique completion call, make sure to set your expiration date + snapshotTask.setTaskCompleted(restoredDefaultState: true, estimatedSnapshotExpiration: Date.distantFuture, userInfo: nil) + case let connectivityTask as WKWatchConnectivityRefreshBackgroundTask: + // Be sure to complete the connectivity task once you’re done. + connectivityTask.setTaskCompletedWithSnapshot(false) + case let urlSessionTask as WKURLSessionRefreshBackgroundTask: + // Be sure to complete the URL session task once you’re done. + urlSessionTask.setTaskCompletedWithSnapshot(false) + case let relevantShortcutTask as WKRelevantShortcutRefreshBackgroundTask: + // Be sure to complete the relevant-shortcut task once you're done. + relevantShortcutTask.setTaskCompletedWithSnapshot(false) + case let intentDidRunTask as WKIntentDidRunRefreshBackgroundTask: + // Be sure to complete the intent-did-run task once you're done. + intentDidRunTask.setTaskCompletedWithSnapshot(false) + default: + // make sure to complete unhandled task types + task.setTaskCompletedWithSnapshot(false) + } + } + } + + func applicationDidFinishLaunching() { +// // Kingfisher setup +// ImageDownloader.default.authenticationChallengeResponder = self +// KingfisherManager.shared.defaultOptions = [.requestModifier(OpenHABAccessTokenAdapter(appData: ObservableOpenHABDataObject.shared))] + } +} + +// MARK: - ClientCertificateManagerDelegate + +extension OpenHABWatchAppDelegate: ClientCertificateManagerDelegate { + // delegate should ask user for a decision on whether to import the client certificate into the keychain + func askForClientCertificateImport(_ clientCertificateManager: ClientCertificateManager?) {} + + // delegate should ask user for the export password used to decode the PKCS#12 + func askForCertificatePassword(_ clientCertificateManager: ClientCertificateManager?) {} + + // delegate should alert the user that an error occured importing the certificate + func alertClientCertificateError(_ clientCertificateManager: ClientCertificateManager?, errMsg: String) {} +} diff --git a/openHABWatch Extension/PushNotificationPayload.apns b/openHABWatch/Extension/PushNotificationPayload.apns similarity index 72% rename from openHABWatch Extension/PushNotificationPayload.apns rename to openHABWatch/Extension/PushNotificationPayload.apns index 666b72191..b652d9056 100644 --- a/openHABWatch Extension/PushNotificationPayload.apns +++ b/openHABWatch/Extension/PushNotificationPayload.apns @@ -9,6 +9,8 @@ "thread-id": "5280" }, - "openHABMessageIndexKey": 1 - + "openHABMessageIndexKey": 1, + + "Simulator Target Bundle": "org.openhab.app.watch" + } diff --git a/openHABWatch Extension/UserDefaultsExtension.swift b/openHABWatch/Extension/UserDefaultsExtension.swift similarity index 87% rename from openHABWatch Extension/UserDefaultsExtension.swift rename to openHABWatch/Extension/UserDefaultsExtension.swift index 6d00c18e3..cd704394d 100644 --- a/openHABWatch Extension/UserDefaultsExtension.swift +++ b/openHABWatch/Extension/UserDefaultsExtension.swift @@ -13,6 +13,6 @@ import Foundation extension UserDefaults { static var shared: UserDefaults { - UserDefaults(suiteName: "group.org.openhab.openhabwatch")! + UserDefaults(suiteName: "group.org.openhab.app.watch")! } } diff --git a/openHABWatch Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Contents.json b/openHABWatch/Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Contents.json similarity index 100% rename from openHABWatch Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Contents.json rename to openHABWatch/Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Contents.json diff --git a/openHABWatch Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Icon-32@2x.png b/openHABWatch/Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Icon-32@2x.png similarity index 100% rename from openHABWatch Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Icon-32@2x.png rename to openHABWatch/Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Icon-32@2x.png diff --git a/openHABWatch Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Icon-36@2x.png b/openHABWatch/Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Icon-36@2x.png similarity index 100% rename from openHABWatch Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Icon-36@2x.png rename to openHABWatch/Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Icon-36@2x.png diff --git a/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Contents.json b/openHABWatch/Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Contents.json similarity index 100% rename from openHABWatch Extension/Assets.xcassets/Complication.complicationset/Contents.json rename to openHABWatch/Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Contents.json diff --git a/openHABWatch Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Extra Large.imageset/Contents.json b/openHABWatch/Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Extra Large.imageset/Contents.json similarity index 100% rename from openHABWatch Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Extra Large.imageset/Contents.json rename to openHABWatch/Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Extra Large.imageset/Contents.json diff --git a/openHABWatch Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Graphic Bezel.imageset/Contents.json b/openHABWatch/Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Graphic Bezel.imageset/Contents.json similarity index 100% rename from openHABWatch Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Graphic Bezel.imageset/Contents.json rename to openHABWatch/Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Graphic Bezel.imageset/Contents.json diff --git a/openHABWatch Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/Contents.json b/openHABWatch/Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/Contents.json similarity index 100% rename from openHABWatch Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/Contents.json rename to openHABWatch/Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/Contents.json diff --git a/openHABWatch Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/openhab84.png b/openHABWatch/Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/openhab84.png similarity index 100% rename from openHABWatch Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/openhab84.png rename to openHABWatch/Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/openhab84.png diff --git a/openHABWatch Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/openhab94.png b/openHABWatch/Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/openhab94.png similarity index 100% rename from openHABWatch Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/openhab94.png rename to openHABWatch/Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/openhab94.png diff --git a/openHABWatch Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Graphic Corner.imageset/Contents.json b/openHABWatch/Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Graphic Corner.imageset/Contents.json similarity index 100% rename from openHABWatch Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Graphic Corner.imageset/Contents.json rename to openHABWatch/Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Graphic Corner.imageset/Contents.json diff --git a/openHABWatch Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Graphic Large Rectangular.imageset/Contents.json b/openHABWatch/Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Graphic Large Rectangular.imageset/Contents.json similarity index 100% rename from openHABWatch Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Graphic Large Rectangular.imageset/Contents.json rename to openHABWatch/Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Graphic Large Rectangular.imageset/Contents.json diff --git a/openHABWatch Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Contents.json b/openHABWatch/Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Contents.json similarity index 100% rename from openHABWatch Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Contents.json rename to openHABWatch/Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Contents.json diff --git a/openHABWatch Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Icon-52@2x.png b/openHABWatch/Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Icon-52@2x.png similarity index 100% rename from openHABWatch Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Icon-52@2x.png rename to openHABWatch/Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Icon-52@2x.png diff --git a/openHABWatch Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Icon-58@2x.png b/openHABWatch/Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Icon-58@2x.png similarity index 100% rename from openHABWatch Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Icon-58@2x.png rename to openHABWatch/Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Icon-58@2x.png diff --git a/openHABWatch Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json b/openHABWatch/Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json similarity index 100% rename from openHABWatch Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json rename to openHABWatch/Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json diff --git a/openHABWatch Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Icon-40@2x.png b/openHABWatch/Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Icon-40@2x.png similarity index 100% rename from openHABWatch Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Icon-40@2x.png rename to openHABWatch/Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Icon-40@2x.png diff --git a/openHABWatch Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Icon-44@2x.png b/openHABWatch/Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Icon-44@2x.png similarity index 100% rename from openHABWatch Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Icon-44@2x.png rename to openHABWatch/Extension/openHABWatch Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Icon-44@2x.png diff --git a/openHABWatch Extension/openHABWatch Extension/Assets.xcassets/Contents.json b/openHABWatch/Extension/openHABWatch Extension/Assets.xcassets/Contents.json similarity index 100% rename from openHABWatch Extension/openHABWatch Extension/Assets.xcassets/Contents.json rename to openHABWatch/Extension/openHABWatch Extension/Assets.xcassets/Contents.json diff --git a/openHABWatch Extension/openHABWatch Extension/ButtonTableRowController.swift b/openHABWatch/Extension/openHABWatch Extension/ButtonTableRowController.swift similarity index 100% rename from openHABWatch Extension/openHABWatch Extension/ButtonTableRowController.swift rename to openHABWatch/Extension/openHABWatch Extension/ButtonTableRowController.swift diff --git a/openHABWatch Extension/openHABWatch Extension/ComplicationController.swift b/openHABWatch/Extension/openHABWatch Extension/ComplicationController.swift similarity index 100% rename from openHABWatch Extension/openHABWatch Extension/ComplicationController.swift rename to openHABWatch/Extension/openHABWatch Extension/ComplicationController.swift diff --git a/openHABWatch Extension/openHABWatch Extension/ExtensionDelegate.swift b/openHABWatch/Extension/openHABWatch Extension/ExtensionDelegate.swift similarity index 100% rename from openHABWatch Extension/openHABWatch Extension/ExtensionDelegate.swift rename to openHABWatch/Extension/openHABWatch Extension/ExtensionDelegate.swift diff --git a/openHABWatch Extension/openHABWatch Extension/Info.plist b/openHABWatch/Extension/openHABWatch Extension/Info.plist similarity index 100% rename from openHABWatch Extension/openHABWatch Extension/Info.plist rename to openHABWatch/Extension/openHABWatch Extension/Info.plist diff --git a/openHABWatch Extension/openHABWatch Extension/InterfaceController.swift b/openHABWatch/Extension/openHABWatch Extension/InterfaceController.swift similarity index 100% rename from openHABWatch Extension/openHABWatch Extension/InterfaceController.swift rename to openHABWatch/Extension/openHABWatch Extension/InterfaceController.swift diff --git a/openHABWatch Extension/openHABWatch Extension/NotificationController.swift b/openHABWatch/Extension/openHABWatch Extension/NotificationController.swift similarity index 100% rename from openHABWatch Extension/openHABWatch Extension/NotificationController.swift rename to openHABWatch/Extension/openHABWatch Extension/NotificationController.swift diff --git a/openHABWatch Extension/openHABWatch Extension/PrefsInterfaceController.swift b/openHABWatch/Extension/openHABWatch Extension/PrefsInterfaceController.swift similarity index 100% rename from openHABWatch Extension/openHABWatch Extension/PrefsInterfaceController.swift rename to openHABWatch/Extension/openHABWatch Extension/PrefsInterfaceController.swift diff --git a/openHABWatch Extension/openHABWatch Extension/PushNotificationPayload.apns b/openHABWatch/Extension/openHABWatch Extension/PushNotificationPayload.apns similarity index 100% rename from openHABWatch Extension/openHABWatch Extension/PushNotificationPayload.apns rename to openHABWatch/Extension/openHABWatch Extension/PushNotificationPayload.apns diff --git a/openHABWatch Extension/openHABWatch Extension/UserDefaultsExtension.swift b/openHABWatch/Extension/openHABWatch Extension/UserDefaultsExtension.swift similarity index 100% rename from openHABWatch Extension/openHABWatch Extension/UserDefaultsExtension.swift rename to openHABWatch/Extension/openHABWatch Extension/UserDefaultsExtension.swift diff --git a/openHABWatch Extension/openHABWatch Extension/external/OpenHabService.swift b/openHABWatch/Extension/openHABWatch Extension/external/OpenHabService.swift similarity index 100% rename from openHABWatch Extension/openHABWatch Extension/external/OpenHabService.swift rename to openHABWatch/Extension/openHABWatch Extension/external/OpenHabService.swift diff --git a/openHABWatch Extension/openHABWatch Extension/external/AppMessageService.swift b/openHABWatch/External/AppMessageService.swift similarity index 78% rename from openHABWatch Extension/openHABWatch Extension/external/AppMessageService.swift rename to openHABWatch/External/AppMessageService.swift index 5d3040c64..8596e32ee 100644 --- a/openHABWatch Extension/openHABWatch Extension/external/AppMessageService.swift +++ b/openHABWatch/External/AppMessageService.swift @@ -19,7 +19,12 @@ import WatchKit class AppMessageService: NSObject, WCSessionDelegate { static let singleton = AppMessageService() + private let logger = Logger(subsystem: "org.openhab.app.watch", category: "AppMessageService") + func updateValuesFromApplicationContext(_ applicationContext: [String: AnyObject]) { + if NetworkConnection.shared == nil { + NetworkConnection.initialize(ignoreSSL: Preferences.ignoreSSL, interceptor: nil) + } if !applicationContext.isEmpty { if let localUrl = applicationContext["localUrl"] as? String { ObservableOpenHABDataObject.shared.localUrl = localUrl @@ -33,6 +38,10 @@ class AppMessageService: NSObject, WCSessionDelegate { ObservableOpenHABDataObject.shared.sitemapName = sitemapName } + if let sitemapForWatch = applicationContext["sitemapForWatch"] as? String { + ObservableOpenHABDataObject.shared.sitemapForWatch = sitemapForWatch + } + if let username = applicationContext["username"] as? String { ObservableOpenHABDataObject.shared.openHABUsername = username } @@ -54,6 +63,10 @@ class AppMessageService: NSObject, WCSessionDelegate { ObservableOpenHABDataObject.shared.openHABAlwaysSendCreds = alwaysSendCreds } + if let iconType = applicationContext["iconType"] as? IconType { + ObservableOpenHABDataObject.shared.iconType = iconType + } + ObservableOpenHABDataObject.shared.haveReceivedAppContext = true } } @@ -65,57 +78,52 @@ class AppMessageService: NSObject, WCSessionDelegate { ["request": "Preferences"], replyHandler: { (response) in let filteredMessages = response.filter { ["remoteUrl", "localUrl", "username"].contains($0.key) } - os_log("Received %{PUBLIC}@", log: .watch, type: .info, "\(filteredMessages)") + self.logger.info("Received \(filteredMessages)") DispatchQueue.main.async { () in - AppMessageService.singleton.updateValuesFromApplicationContext(response as [String: AnyObject]) + self.updateValuesFromApplicationContext(response as [String: AnyObject]) } }, errorHandler: { (error) in - os_log("Error sending message %{PUBLIC}@", log: .watch, type: .info, "\(error)") + self.logger.error("Error sending message \(error.localizedDescription)") } ) } - @available(watchOSApplicationExtension 2.2, *) func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) { - os_log("activationDidCompleteWith activationState %{PUBLIC}@ error: %{PUBLIC}@", log: .watch, type: .info, "\(activationState)", "\(String(describing: error))") + logger.info("activationDidCompleteWith activationState \(activationState.rawValue) error: \(String(describing: error))") DispatchQueue.main.async { () in self.updateValuesFromApplicationContext(session.receivedApplicationContext as [String: AnyObject]) } } /** Called on the delegate of the receiver. Will be called on startup if an applicationContext is available. */ - @available(watchOS 2.0, *) func session(_ session: WCSession, didReceiveApplicationContext applicationContext: [String: Any]) { - os_log("didReceiveApplicationContext %{PUBLIC}@", log: .watch, type: .info, "\(applicationContext)") + logger.info("didReceiveApplicationContext \(applicationContext)") DispatchQueue.main.async { () in self.updateValuesFromApplicationContext(applicationContext as [String: AnyObject]) } } /** Called on the delegate of the receiver. Will be called on startup if the user info finished transferring when the receiver was not running. */ - @available(watchOS 2.0, *) func session(_ session: WCSession, didReceiveUserInfo userInfo: [String: Any]) { - os_log("didReceiveUserInfo %{PUBLIC}@", log: .watch, type: .info, "\(userInfo)") + logger.info("didReceiveUserInfo \(userInfo)") DispatchQueue.main.async { () in self.updateValuesFromApplicationContext(userInfo as [String: AnyObject]) } } - @available(watchOS 2.0, *) func session(_ session: WCSession, didReceiveMessage message: [String: Any]) { let filteredMessages = message.filter { ["remoteUrl", "localUrl", "username"].contains($0.key) } - os_log("didReceiveMessage some filtered messages: %{PUBLIC}@", log: .watch, type: .info, "\(filteredMessages)") + logger.info("didReceiveMessage some filtered messages: \(filteredMessages)") DispatchQueue.main.async { () in self.updateValuesFromApplicationContext(message as [String: AnyObject]) } } - @available(watchOS 2.0, *) func session(_ session: WCSession, didReceiveMessage message: [String: Any], replyHandler: @escaping ([String: Any]) -> Swift.Void) { let filteredMessages = message.filter { ["remoteUrl", "localUrl", "username", "defaultSitemap"].contains($0.key) } - os_log("didReceiveMessage some filtered messages: %{PUBLIC}@ with reply handler", log: .watch, type: .info, "\(filteredMessages)") + logger.info("didReceiveMessage some filtered messages: \(filteredMessages) with reply handler") DispatchQueue.main.async { () in self.updateValuesFromApplicationContext(message as [String: AnyObject]) diff --git a/openHABWatch/Info.plist b/openHABWatch/Info.plist index 89efe3b21..2bc276815 100644 --- a/openHABWatch/Info.plist +++ b/openHABWatch/Info.plist @@ -2,39 +2,12 @@ - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleDisplayName - openHAB - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - $(PRODUCT_BUNDLE_PACKAGE_TYPE) - CFBundleShortVersionString - $(MARKETING_VERSION) - CFBundleVersion - $(CURRENT_PROJECT_VERSION) - CLKComplicationPrincipalClass - $(PRODUCT_MODULE_NAME).ComplicationController NSAppTransportSecurity NSAllowsArbitraryLoads - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - WKApplication - - WKCompanionAppBundleIdentifier - org.openhab.app + diff --git a/openHABWatch Extension/openHABWatch Extension/Model/LazyView.swift b/openHABWatch/Model/LazyView.swift similarity index 100% rename from openHABWatch Extension/openHABWatch Extension/Model/LazyView.swift rename to openHABWatch/Model/LazyView.swift diff --git a/openHABWatch Extension/openHABWatch Extension/Model/ObservableOpenHABDataObject.swift b/openHABWatch/Model/ObservableOpenHABDataObject.swift similarity index 88% rename from openHABWatch Extension/openHABWatch Extension/Model/ObservableOpenHABDataObject.swift rename to openHABWatch/Model/ObservableOpenHABDataObject.swift index d26753537..749419206 100644 --- a/openHABWatch Extension/openHABWatch Extension/Model/ObservableOpenHABDataObject.swift +++ b/openHABWatch/Model/ObservableOpenHABDataObject.swift @@ -49,6 +49,13 @@ final class ObservableOpenHABDataObject: DataObject, ObservableObject { } } + @UserDefaultsBacked(key: "sitemapForWatch", defaultValue: "") + var sitemapForWatch: String { + willSet { + objectWillChange.send() + } + } + @UserDefaultsBacked(key: "username", defaultValue: "") var openHABUsername: String { willSet { @@ -84,6 +91,13 @@ final class ObservableOpenHABDataObject: DataObject, ObservableObject { objectRefreshed.send() } } + + @UserDefaultsBacked(key: "iconType", defaultValue: .svg) + var iconType: IconType { + didSet { + objectRefreshed.send() + } + } } extension ObservableOpenHABDataObject { diff --git a/openHABWatch Extension/openHABWatch Extension/Model/ObservableOpenHABSitemapPage.swift b/openHABWatch/Model/ObservableOpenHABSitemapPage.swift similarity index 100% rename from openHABWatch Extension/openHABWatch Extension/Model/ObservableOpenHABSitemapPage.swift rename to openHABWatch/Model/ObservableOpenHABSitemapPage.swift diff --git a/openHABWatch Extension/openHABWatch Extension/Model/ObservableOpenHABWidget.swift b/openHABWatch/Model/ObservableOpenHABWidget.swift similarity index 100% rename from openHABWatch Extension/openHABWatch Extension/Model/ObservableOpenHABWidget.swift rename to openHABWatch/Model/ObservableOpenHABWidget.swift diff --git a/openHABWatch Extension/openHABWatch Extension/Model/ObservableOpenHABWidgetExtension.swift b/openHABWatch/Model/ObservableOpenHABWidgetExtension.swift similarity index 83% rename from openHABWatch Extension/openHABWatch Extension/Model/ObservableOpenHABWidgetExtension.swift rename to openHABWatch/Model/ObservableOpenHABWidgetExtension.swift index d9402387d..8ca301af4 100644 --- a/openHABWatch Extension/openHABWatch Extension/Model/ObservableOpenHABWidgetExtension.swift +++ b/openHABWatch/Model/ObservableOpenHABWidgetExtension.swift @@ -21,7 +21,10 @@ extension ObservableOpenHABWidget { // os_log("Selected %{PUBLIC}@", log: .viewCycle, type: .info, pageUrl) NavigationLink(destination: LazyView( - ContentView(viewModel: UserData(url: URL(string: pageUrl)), settings: settings, title: title)) + // TODO: + EmptyView() + // ContentView(viewModel: UserData(url: URL(string: pageUrl)), settings: settings, title: title) + ) ) { Image(systemSymbol: .chevronRight) } diff --git a/openHABWatch Extension/openHABWatch Extension/Model/UserDefaultsBacked.swift b/openHABWatch/Model/UserDefaultsBacked.swift similarity index 94% rename from openHABWatch Extension/openHABWatch Extension/Model/UserDefaultsBacked.swift rename to openHABWatch/Model/UserDefaultsBacked.swift index e57aef06f..0f3d5f3de 100644 --- a/openHABWatch Extension/openHABWatch Extension/Model/UserDefaultsBacked.swift +++ b/openHABWatch/Model/UserDefaultsBacked.swift @@ -28,7 +28,7 @@ struct UserDefaultsBacked { } } -/// Convenience initializer when UserDefaults is optional. +// Convenience initializer when UserDefaults is optional. extension UserDefaultsBacked where T: ExpressibleByNilLiteral { init(key: String, storage: UserDefaults = .standard) { self.init(key: key, defaultValue: nil, storage: storage) diff --git a/openHABWatch/OpenHABWatch.swift b/openHABWatch/OpenHABWatch.swift new file mode 100644 index 000000000..8cb8ac1d8 --- /dev/null +++ b/openHABWatch/OpenHABWatch.swift @@ -0,0 +1,68 @@ +// Copyright (c) 2010-2024 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 SDWebImage +import SDWebImageSVGCoder +import SwiftUI +import UserNotifications + +@main +struct OpenHABWatch: App { + @ObservedObject var settings = ObservableOpenHABDataObject.shared + // https://developer.apple.com/documentation/watchkit/wkapplicationdelegate + @WKApplicationDelegateAdaptor(OpenHABWatchAppDelegate.self) var appDelegate + @ObservedObject var userData = UserData(sitemapName: ObservableOpenHABDataObject.shared.sitemapName) + + var body: some Scene { + WindowGroup { + TabView { + ContentView(viewModel: userData) + .tabItem { + Label("Received", systemImage: "tray.and.arrow.down.fill") + } + PreferencesSwiftUIView() + .tabItem { + Label("Preferences", systemImage: "person.crop.circle.fill") + } + } + .environmentObject(settings) + .task { + let center = UNUserNotificationCenter.current() + _ = try? await center.requestAuthorization( + options: [.alert, .sound, .badge] + ) + } + } + WKNotificationScene(controller: NotificationController.self, category: "openHABNotification") + } + + init() { + // Initialize SVGCoder + let SVGCoder = SDImageSVGCoder.shared + SDImageCodersManager.shared.addCoder(SVGCoder) + SDWebImageDownloader.shared.config.operationClass = OpenHABImageDownloaderOperation.self + let alwaysSendCreds = settings.openHABAlwaysSendCreds + let openHABUsername = settings.openHABUsername + let openHABPassword = settings.openHABPassword + let requestModifier = SDWebImageDownloaderRequestModifier { (request) -> URLRequest? in + guard alwaysSendCreds || request.url?.host?.hasSuffix("myopenhab.org") == true else { + return request + } + guard !openHABUsername.isEmpty, !openHABPassword.isEmpty else { + return request + } + var request = request + request.headers.add(.authorization(username: openHABUsername, password: openHABPassword)) + return request + } + SDWebImageDownloader.shared.requestModifier = requestModifier + } +} diff --git a/openHABWatch/Preview Content/Preview Assets.xcassets/Contents.json b/openHABWatch/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 000000000..73c00596a --- /dev/null +++ b/openHABWatch/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/openHABWatch Extension/Views/ContentView.swift b/openHABWatch/Views/ContentView.swift similarity index 84% rename from openHABWatch Extension/Views/ContentView.swift rename to openHABWatch/Views/ContentView.swift index 893b78c88..96b4565fe 100644 --- a/openHABWatch Extension/Views/ContentView.swift +++ b/openHABWatch/Views/ContentView.swift @@ -15,15 +15,20 @@ import SwiftUI struct ContentView: View { @ObservedObject var viewModel: UserData - @ObservedObject var settings = ObservableOpenHABDataObject.shared + @EnvironmentObject var settings: ObservableOpenHABDataObject @State var title = "openHAB" var body: some View { ZStack { ScrollView { + HStack { + Text(viewModel.openHABSitemapPage?.title ?? "Sitemap without title") + .font(.body) + .lineLimit(1) + Spacer() + } ForEach(viewModel.widgets) { widget in rowWidget(widget: widget) - .environmentObject(settings) } } .navigationBarTitle(Text(title)) @@ -81,7 +86,7 @@ struct ContentView: View { if widget.item != nil { ImageRawRow(widget: widget) } else { - ImageRow(URL: URL(string: widget.url)) + ImageRow(url: URL(string: widget.url)) } case .chart: let url = Endpoint.chart( @@ -94,7 +99,7 @@ struct ContentView: View { theme: .dark, forceAsItem: widget.forceAsItem ).url - ImageRow(URL: url) + ImageRow(url: url) case .mapview: MapViewRow(widget: widget) case .colorpicker: @@ -105,13 +110,16 @@ struct ContentView: View { } } -struct ContentView_Previews: PreviewProvider { - static var previews: some View { - Group { - ContentView(viewModel: UserData()) - .previewDevice("Apple Watch Series 4 - 44mm") - ContentView(viewModel: UserData()) - .previewDevice("Apple Watch Series 2 - 38mm") - } +#Preview { + Group { + ContentView(viewModel: UserData()) + + .environmentObject({ () -> UserData in + let envObj = UserData() + return envObj + }()) + + ContentView(viewModel: UserData()) } + .environmentObject(ObservableOpenHABDataObject()) } diff --git a/openHABWatch/Views/PreferencesSwiftUIView.swift b/openHABWatch/Views/PreferencesSwiftUIView.swift new file mode 100644 index 000000000..2629d9e98 --- /dev/null +++ b/openHABWatch/Views/PreferencesSwiftUIView.swift @@ -0,0 +1,46 @@ +// Copyright (c) 2010-2024 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 OpenHABCore +import os.log +import SwiftUI +import WatchConnectivity + +struct PreferencesSwiftUIView: View { + @EnvironmentObject var settings: ObservableOpenHABDataObject + + var applicationVersionNumber: String = { + let appBuildString = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as? String + let appVersionString = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String + return "\(appVersionString ?? "") (\(appBuildString ?? ""))" + }() + + var body: some View { + List { + LabeledContent(LocalizedStringKey("active_url"), value: settings.openHABRootUrl) + LabeledContent(LocalizedStringKey("local_url"), value: settings.localUrl) + LabeledContent(LocalizedStringKey("remote_url"), value: settings.remoteUrl) + LabeledContent(LocalizedStringKey("sitemap"), value: settings.sitemapForWatch) + LabeledContent(LocalizedStringKey("username"), value: settings.openHABUsername) + LabeledContent(LocalizedStringKey("version"), value: applicationVersionNumber) + } + + Button { AppMessageService.singleton.requestApplicationContext() + } label: { Label("sync_prefs", systemSymbol: .arrowTriangle2Circlepath) + } + .buttonStyle(.borderedProminent) + } +} + +#Preview { + PreferencesSwiftUIView() + .environmentObject(ObservableOpenHABDataObject()) +} diff --git a/openHABWatch Extension/Views/Rows/ColorPickerRow.swift b/openHABWatch/Views/Rows/ColorPickerRow.swift similarity index 84% rename from openHABWatch Extension/Views/Rows/ColorPickerRow.swift rename to openHABWatch/Views/Rows/ColorPickerRow.swift index 86ded1134..b6ee4bb51 100644 --- a/openHABWatch Extension/Views/Rows/ColorPickerRow.swift +++ b/openHABWatch/Views/Rows/ColorPickerRow.swift @@ -14,7 +14,7 @@ import SwiftUI struct ColorPickerRow: View { @ObservedObject var widget: ObservableOpenHABWidget - @ObservedObject var settings = ObservableOpenHABDataObject.shared + @EnvironmentObject var settings: ObservableOpenHABDataObject var body: some View { let uiColor = widget.item?.stateAsUIColor() @@ -27,7 +27,7 @@ struct ColorPickerRow: View { } HStack { Spacer() - EncircledIconWithAction( + IconWithAction( systemSymbol: .chevronDownCircleFill, action: downButtonPressed ) @@ -42,7 +42,7 @@ struct ColorPickerRow: View { Spacer() - EncircledIconWithAction( + IconWithAction( systemSymbol: .chevronUpCircleFill, action: upButtonPressed @@ -63,9 +63,8 @@ struct ColorPickerRow: View { } } -struct ColorRow_Previews: PreviewProvider { - static var previews: some View { - let widget = UserData().widgets[10] - return ColorPickerRow(widget: widget) - } +#Preview { + let widget = UserData().widgets[10] + return ColorPickerRow(widget: widget) + .environmentObject(ObservableOpenHABDataObject()) } diff --git a/openHABWatch/Views/Rows/FrameRow.swift b/openHABWatch/Views/Rows/FrameRow.swift new file mode 100644 index 000000000..1fa3a8da2 --- /dev/null +++ b/openHABWatch/Views/Rows/FrameRow.swift @@ -0,0 +1,31 @@ +// Copyright (c) 2010-2024 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 SwiftUI + +struct FrameRow: View { + @ObservedObject var widget: ObservableOpenHABWidget + @EnvironmentObject var settings: ObservableOpenHABDataObject + var body: some View { + HStack { + Text(widget.labelText?.uppercased() ?? "") + .font(.callout) + .lineLimit(1) + Spacer() + } + } +} + +#Preview { + let widget = UserData().widgets[6] + return FrameRow(widget: widget) + .environmentObject(ObservableOpenHABDataObject()) +} diff --git a/openHABWatch Extension/Views/Rows/GenericRow.swift b/openHABWatch/Views/Rows/GenericRow.swift similarity index 75% rename from openHABWatch Extension/Views/Rows/GenericRow.swift rename to openHABWatch/Views/Rows/GenericRow.swift index e8bf6c46a..f062f0059 100644 --- a/openHABWatch Extension/Views/Rows/GenericRow.swift +++ b/openHABWatch/Views/Rows/GenericRow.swift @@ -14,7 +14,7 @@ import SwiftUI struct GenericRow: View { @ObservedObject var widget: ObservableOpenHABWidget - @ObservedObject var settings = ObservableOpenHABDataObject.shared + @EnvironmentObject var settings: ObservableOpenHABDataObject var body: some View { HStack { @@ -27,9 +27,8 @@ struct GenericRow: View { } } -struct GenericRow_Previews: PreviewProvider { - static var previews: some View { - let widget = UserData().widgets[6] - return GenericRow(widget: widget) - } +#Preview { + let widget = UserData().widgets[6] + return GenericRow(widget: widget) + .environmentObject(ObservableOpenHABDataObject()) } diff --git a/openHABWatch Extension/Views/Rows/ImageRawRow.swift b/openHABWatch/Views/Rows/ImageRawRow.swift similarity index 77% rename from openHABWatch Extension/Views/Rows/ImageRawRow.swift rename to openHABWatch/Views/Rows/ImageRawRow.swift index 77869abaa..2d69a2a48 100644 --- a/openHABWatch Extension/Views/Rows/ImageRawRow.swift +++ b/openHABWatch/Views/Rows/ImageRawRow.swift @@ -9,14 +9,13 @@ // // SPDX-License-Identifier: EPL-2.0 -import Kingfisher import OpenHABCore import os.log import SwiftUI struct ImageRawRow: View { @ObservedObject var widget: ObservableOpenHABWidget - @ObservedObject var settings = ObservableOpenHABDataObject.shared + @EnvironmentObject var settings: ObservableOpenHABDataObject var body: some View { if let data = widget.item?.state?.components(separatedBy: ",")[safe: 1], @@ -31,9 +30,8 @@ struct ImageRawRow: View { } } -struct ImageRawRow_Previews: PreviewProvider { - static var previews: some View { - let widget = UserData().widgets[4] - return ImageRawRow(widget: widget) - } +#Preview { + let widget = UserData().widgets[4] + return ImageRawRow(widget: widget) + .environmentObject(ObservableOpenHABDataObject()) } diff --git a/openHABWatch/Views/Rows/ImageRow.swift b/openHABWatch/Views/Rows/ImageRow.swift new file mode 100644 index 000000000..c0d15d519 --- /dev/null +++ b/openHABWatch/Views/Rows/ImageRow.swift @@ -0,0 +1,53 @@ +// Copyright (c) 2010-2024 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 OpenHABCore +import os.log +import SDWebImageSwiftUI +import SwiftUI + +struct ImageRow: View { + @State var url: URL? + @EnvironmentObject var settings: ObservableOpenHABDataObject + + var body: some View { + WebImage( + url: url, + options: settings.ignoreSSL ? [.allowInvalidSSLCertificates] : [], + context: [ + .imageThumbnailPixelSize: CGSize.zero + ] + ) { image in + image.resizable() + + } placeholder: { + Image(systemSymbol: .arrowTriangle2CirclepathCircle) + .font(.callout) + .opacity(0.3) + } + .cancelOnDisappear(true) + .transition(.fade(duration: 0.3)) + .scaledToFit() + } +} + +#Preview { + let iconUrl = Endpoint.icon( + rootUrl: PreviewConstants.remoteURLString, + version: 2, + icon: "Switch", + state: "ON", + iconType: .svg, + iconColor: "" + ).url + return ImageRow(url: iconUrl) + .environmentObject(ObservableOpenHABDataObject()) +} diff --git a/openHABWatch Extension/Views/Rows/MapViewRow.swift b/openHABWatch/Views/Rows/MapViewRow.swift similarity index 73% rename from openHABWatch Extension/Views/Rows/MapViewRow.swift rename to openHABWatch/Views/Rows/MapViewRow.swift index dfb178b83..1c5b41f9a 100644 --- a/openHABWatch Extension/Views/Rows/MapViewRow.swift +++ b/openHABWatch/Views/Rows/MapViewRow.swift @@ -13,7 +13,7 @@ import SwiftUI struct MapViewRow: View { @ObservedObject var widget: ObservableOpenHABWidget - @ObservedObject var settings = ObservableOpenHABDataObject.shared + @EnvironmentObject var settings: ObservableOpenHABDataObject var body: some View { VStack { @@ -25,9 +25,8 @@ struct MapViewRow: View { } } -struct MapViewRow_Previews: PreviewProvider { - static var previews: some View { - let widget = UserData().widgets[9] - return MapViewRow(widget: widget) - } +#Preview { + let widget = UserData().widgets[9] + return MapViewRow(widget: widget) + .environmentObject(ObservableOpenHABDataObject()) } diff --git a/openHABWatch Extension/Views/Rows/RollershutterRow.swift b/openHABWatch/Views/Rows/RollershutterRow.swift similarity index 69% rename from openHABWatch Extension/Views/Rows/RollershutterRow.swift rename to openHABWatch/Views/Rows/RollershutterRow.swift index f68974e04..2ae0c0083 100644 --- a/openHABWatch Extension/Views/Rows/RollershutterRow.swift +++ b/openHABWatch/Views/Rows/RollershutterRow.swift @@ -13,7 +13,7 @@ import SwiftUI struct RollershutterRow: View { @ObservedObject var widget: ObservableOpenHABWidget - @ObservedObject var settings = ObservableOpenHABDataObject.shared + @EnvironmentObject var settings: ObservableOpenHABDataObject var body: some View { VStack(spacing: -5) { @@ -24,23 +24,18 @@ struct RollershutterRow: View { } HStack { Spacer() - - EncircledIconWithAction(systemSymbol: .chevronUpCircleFill) { + IconWithAction(systemSymbol: .chevronUpCircleFill) { widget.sendCommand("UP") } - Spacer() - - EncircledIconWithAction(systemSymbol: .square) { + IconWithAction(systemSymbol: .square) { widget.sendCommand("STOP") } - Spacer() - EncircledIconWithAction(systemSymbol: .chevronDownCircleFill) { + IconWithAction(systemSymbol: .chevronDownCircleFill) { widget.sendCommand("DOWN") } - Spacer() } .frame(height: 50) @@ -48,9 +43,8 @@ struct RollershutterRow: View { } } -struct Rollershutter_Previews: PreviewProvider { - static var previews: some View { - let widget = UserData().widgets[5] - return RollershutterRow(widget: widget) - } +#Preview { + let widget = UserData().widgets[5] + return RollershutterRow(widget: widget) + .environmentObject(ObservableOpenHABDataObject()) } diff --git a/openHABWatch/Views/Rows/SegmentRow.swift b/openHABWatch/Views/Rows/SegmentRow.swift new file mode 100644 index 000000000..8bb247b3f --- /dev/null +++ b/openHABWatch/Views/Rows/SegmentRow.swift @@ -0,0 +1,63 @@ +// Copyright (c) 2010-2024 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 OpenHABCore +import os.log +import SwiftUI + +struct SegmentRow: View { + @ObservedObject var widget: ObservableOpenHABWidget + @EnvironmentObject var settings: ObservableOpenHABDataObject + + @State private var favoriteColor = 0 + + var valueBinding: Binding { + .init( + get: { + guard case let .segmented(value) = widget.stateEnumBinding else { return 0 } + return value + }, + set: { + os_log("Slider new value = %g", log: .default, type: .info, $0) + // self.widget.sendCommand($0) + widget.stateEnumBinding = .segmented($0) + } + ) + } + + var body: some View { + VStack { + HStack { + IconView(widget: widget, settings: settings) + TextLabelView(widget: widget) + Spacer() + DetailTextLabelView(widget: widget) + } + Picker("Picker", selection: valueBinding) { + ForEach(0 ..< widget.mappingsOrItemOptions.count, id: \.self) { + Text(widget.mappingsOrItemOptions[$0].label).tag($0) + } + } + .labelsHidden() + .frame(height: 100) + .padding(.top, 0) + } + } +} + +#Preview { + let widget = UserData().widgets[4] + return Group { + SegmentRow(widget: widget) + SegmentRow(widget: widget) + } + .environmentObject(ObservableOpenHABDataObject()) +} diff --git a/openHABWatch Extension/Views/Rows/SetpointRow.swift b/openHABWatch/Views/Rows/SetpointRow.swift similarity index 86% rename from openHABWatch Extension/Views/Rows/SetpointRow.swift rename to openHABWatch/Views/Rows/SetpointRow.swift index a63cda591..0514c608e 100644 --- a/openHABWatch Extension/Views/Rows/SetpointRow.swift +++ b/openHABWatch/Views/Rows/SetpointRow.swift @@ -14,7 +14,7 @@ import SwiftUI struct SetpointRow: View { @ObservedObject var widget: ObservableOpenHABWidget - @ObservedObject var settings = ObservableOpenHABDataObject.shared + @EnvironmentObject var settings: ObservableOpenHABDataObject private var isIntStep: Bool { widget.step.truncatingRemainder(dividingBy: 1) == 0 @@ -34,7 +34,7 @@ struct SetpointRow: View { HStack { Spacer() - EncircledIconWithAction( + IconWithAction( systemSymbol: .chevronDownCircleFill, action: decreaseValue ) @@ -46,7 +46,7 @@ struct SetpointRow: View { Spacer() - EncircledIconWithAction( + IconWithAction( systemSymbol: .chevronUpCircleFill, action: increaseValue ) @@ -80,9 +80,8 @@ struct SetpointRow: View { } } -struct SetpointRow_Previews: PreviewProvider { - static var previews: some View { - let widget = UserData().widgets[3] - return SetpointRow(widget: widget) - } +#Preview { + let widget = UserData().widgets[3] + return SetpointRow(widget: widget) + .environmentObject(ObservableOpenHABDataObject()) } diff --git a/openHABWatch/Views/Rows/SliderRow.swift b/openHABWatch/Views/Rows/SliderRow.swift new file mode 100644 index 000000000..bfdc818ab --- /dev/null +++ b/openHABWatch/Views/Rows/SliderRow.swift @@ -0,0 +1,61 @@ +// Copyright (c) 2010-2024 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 OpenHABCore +import os.log +import SwiftUI + +struct SliderRow: View { + @ObservedObject var widget: ObservableOpenHABWidget + @EnvironmentObject var settings: ObservableOpenHABDataObject + + var valueBinding: Binding { + .init( + get: { widget.adjustedValue }, + set: { + os_log("Slider new value = %g", log: .default, type: .info, $0) + widget.sendCommand($0.valueText(step: widget.step)) + } + ) + } + + var body: some View { + VStack(spacing: 3) { + HStack { + IconView(widget: widget, settings: settings) + TextLabelView(widget: widget) + Spacer() + DetailTextLabelView(widget: widget) + }.padding(.top, 8) + + Slider(value: valueBinding, in: widget.minValue ... widget.maxValue, step: widget.step) + .labelsHidden() + .focusable(true) + .digitalCrownRotation( + valueBinding, + from: widget.minValue, + through: widget.maxValue, + by: widget.step, + sensitivity: .medium, + isHapticFeedbackEnabled: true + ) + } + } +} + +#Preview { + let widget = UserData().widgets[3] + return Group { + SliderRow(widget: widget) + SliderRow(widget: widget) + } + .environmentObject(ObservableOpenHABDataObject()) +} diff --git a/openHABWatch Extension/Views/Rows/SliderWithSwitchSupportRow.swift b/openHABWatch/Views/Rows/SliderWithSwitchSupportRow.swift similarity index 85% rename from openHABWatch Extension/Views/Rows/SliderWithSwitchSupportRow.swift rename to openHABWatch/Views/Rows/SliderWithSwitchSupportRow.swift index af0fea029..a1c9192ce 100644 --- a/openHABWatch Extension/Views/Rows/SliderWithSwitchSupportRow.swift +++ b/openHABWatch/Views/Rows/SliderWithSwitchSupportRow.swift @@ -15,7 +15,7 @@ import SwiftUI struct SliderWithSwitchSupportRow: View { @ObservedObject var widget: ObservableOpenHABWidget - @ObservedObject var settings = ObservableOpenHABDataObject.shared + @EnvironmentObject var settings: ObservableOpenHABDataObject var body: some View { let valueBinding = Binding( @@ -79,14 +79,11 @@ struct SliderWithSwitchSupportRow: View { } } -struct SliderWithSwitchSupportRow_Previews: PreviewProvider { - static var previews: some View { - let widget = UserData().widgets[3] - return Group { - SliderRow(widget: widget) - .previewLayout(.fixed(width: 300, height: 70)) - SliderRow(widget: widget) - .previewDevice("Apple Watch Series 4 - 44mm") - } +#Preview { + let widget = UserData().widgets[3] + return Group { + SliderRow(widget: widget) + SliderRow(widget: widget) } + .environmentObject(ObservableOpenHABDataObject()) } diff --git a/openHABWatch Extension/Views/Rows/SwitchRow.swift b/openHABWatch/Views/Rows/SwitchRow.swift similarity index 51% rename from openHABWatch Extension/Views/Rows/SwitchRow.swift rename to openHABWatch/Views/Rows/SwitchRow.swift index a593a42e2..272b8a3af 100644 --- a/openHABWatch Extension/Views/Rows/SwitchRow.swift +++ b/openHABWatch/Views/Rows/SwitchRow.swift @@ -9,21 +9,18 @@ // // SPDX-License-Identifier: EPL-2.0 -import Kingfisher import OpenHABCore import os.log import SwiftUI struct SwitchRow: View { @ObservedObject var widget: ObservableOpenHABWidget - @ObservedObject var settings = ObservableOpenHABDataObject.shared + @EnvironmentObject var settings: ObservableOpenHABDataObject - var body: some View { - // https://stackoverflow.com/questions/59395501/do-something-when-toggle-state-changes - let stateBinding = Binding( - get: { - widget.stateEnumBinding.boolState - }, + // https://stackoverflow.com/questions/59395501/do-something-when-toggle-state-changes + var stateBinding: Binding { + .init( + get: { widget.stateEnumBinding.boolState }, set: { if $0 { os_log("Switch to ON", log: .viewCycle, type: .info) @@ -35,27 +32,26 @@ struct SwitchRow: View { widget.stateEnumBinding = .switcher($0) } ) + } - return - Toggle(isOn: stateBinding) { - HStack { - IconView(widget: widget, settings: settings) - VStack { - TextLabelView(widget: widget) - DetailTextLabelView(widget: widget) - } + var body: some View { + Toggle(isOn: stateBinding) { + HStack { + IconView(widget: widget, settings: settings) + VStack { + TextLabelView(widget: widget) + DetailTextLabelView(widget: widget) } } - .focusable(true) - .padding(.trailing) - .cornerRadius(5) + } + .focusable(true) + .padding(.trailing) + .cornerRadius(5) } } -struct SwitchRow_Previews: PreviewProvider { - static var previews: some View { - let widget = UserData().widgets[2] - return SwitchRow(widget: widget) - .previewLayout(.fixed(width: 300, height: 70)) - } +#Preview { + let widget = UserData().widgets[2] + return SwitchRow(widget: widget) + .environmentObject(ObservableOpenHABDataObject()) } diff --git a/openHABWatch Extension/Views/Utils/Color+Extension.swift b/openHABWatch/Views/Utils/Color+Extension.swift similarity index 100% rename from openHABWatch Extension/Views/Utils/Color+Extension.swift rename to openHABWatch/Views/Utils/Color+Extension.swift diff --git a/openHABWatch Extension/Views/Utils/ColorSelection.swift b/openHABWatch/Views/Utils/ColorSelection.swift similarity index 97% rename from openHABWatch Extension/Views/Utils/ColorSelection.swift rename to openHABWatch/Views/Utils/ColorSelection.swift index 3ff08fc7a..3163f44ee 100644 --- a/openHABWatch Extension/Views/Utils/ColorSelection.swift +++ b/openHABWatch/Views/Utils/ColorSelection.swift @@ -122,8 +122,6 @@ struct ColorSelection: View { } } -struct ColorSelection_Previews: PreviewProvider { - static var previews: some View { - ColorSelection() - } +#Preview { + ColorSelection() } diff --git a/openHABWatch Extension/Views/Utils/DetailTextLabelView.swift b/openHABWatch/Views/Utils/DetailTextLabelView.swift similarity index 73% rename from openHABWatch Extension/Views/Utils/DetailTextLabelView.swift rename to openHABWatch/Views/Utils/DetailTextLabelView.swift index a6a0d84a2..1d6a29c47 100644 --- a/openHABWatch Extension/Views/Utils/DetailTextLabelView.swift +++ b/openHABWatch/Views/Utils/DetailTextLabelView.swift @@ -15,8 +15,8 @@ struct DetailTextLabelView: View { @ObservedObject var widget: ObservableOpenHABWidget var body: some View { - Unwrap(widget.labelValue) { - Text($0) + if let label = widget.labelValue { + Text(label) .font(.footnote) .lineLimit(1) .foregroundColor(!widget.valuecolor.isEmpty ? Color(fromString: widget.valuecolor) : .secondary) @@ -24,9 +24,7 @@ struct DetailTextLabelView: View { } } -struct DetailTextLabelView_Previews: PreviewProvider { - static var previews: some View { - let widget = UserData().widgets[2] - return DetailTextLabelView(widget: widget) - } +#Preview { + let widget = UserData().widgets[2] + return DetailTextLabelView(widget: widget) } diff --git a/openHABWatch/Views/Utils/IconView.swift b/openHABWatch/Views/Utils/IconView.swift new file mode 100644 index 000000000..b6c606318 --- /dev/null +++ b/openHABWatch/Views/Utils/IconView.swift @@ -0,0 +1,53 @@ +// Copyright (c) 2010-2024 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 OpenHABCore +import os.log +import SDWebImageSwiftUI +import SwiftUI + +struct IconView: View { + @ObservedObject var widget: ObservableOpenHABWidget + @ObservedObject var settings = ObservableOpenHABDataObject.shared + + var iconURL: URL? { + var iconColor = widget.iconColor + if iconColor.isEmpty { + iconColor = "white" + } + return Endpoint.icon( + rootUrl: settings.openHABRootUrl, + version: settings.openHABVersion, + icon: widget.icon, + state: widget.item?.state ?? "", + iconType: settings.iconType, + iconColor: iconColor + ).url + } + + var body: some View { + // Inspired by https://anoop4real.medium.com/display-svg-in-swiftui-ios-watchos-260120557e3a + WebImage( + url: iconURL, + options: settings.ignoreSSL ? [.allowInvalidSSLCertificates] : [], + context: [.imageThumbnailPixelSize: CGSize.zero] + ) + .cancelOnDisappear(true) + .resizable() + .scaledToFit() + .frame(width: 20.0, height: 20.0) + } +} + +#Preview { + let widget = UserData().widgets[3] + return IconView(widget: widget, settings: ObservableOpenHABDataObject(openHABRootUrl: PreviewConstants.remoteURLString)) +} diff --git a/openHABWatch Extension/Views/Utils/EncircledIconWithAction.swift b/openHABWatch/Views/Utils/IconWithAction.swift similarity index 76% rename from openHABWatch Extension/Views/Utils/EncircledIconWithAction.swift rename to openHABWatch/Views/Utils/IconWithAction.swift index 098f4d015..b111c1ed0 100644 --- a/openHABWatch Extension/Views/Utils/EncircledIconWithAction.swift +++ b/openHABWatch/Views/Utils/IconWithAction.swift @@ -12,7 +12,7 @@ import SFSafeSymbols import SwiftUI -struct EncircledIconWithAction: View { +struct IconWithAction: View { var systemSymbol: SFSymbol var action: () -> Void var body: some View { @@ -26,9 +26,7 @@ struct EncircledIconWithAction: View { } } -struct EncircledIconWithAction_Previews: PreviewProvider { - static var previews: some View { - EncircledIconWithAction(systemSymbol: - .chevronUpCircleFill) {} - } +#Preview { + IconWithAction(systemSymbol: + .chevronUpCircleFill) {} } diff --git a/openHABWatch Extension/Views/Rows/PreferencesRowUIView.swift b/openHABWatch/Views/Utils/ImageWithAction.swift similarity index 52% rename from openHABWatch Extension/Views/Rows/PreferencesRowUIView.swift rename to openHABWatch/Views/Utils/ImageWithAction.swift index fa52f7bac..84440a1ab 100644 --- a/openHABWatch Extension/Views/Rows/PreferencesRowUIView.swift +++ b/openHABWatch/Views/Utils/ImageWithAction.swift @@ -9,22 +9,23 @@ // // SPDX-License-Identifier: EPL-2.0 +import SFSafeSymbols import SwiftUI -struct PreferencesRowUIView: View { - var label: String - var content: String +struct ImageWithAction: View { + var systemName: String + var action: () -> Void var body: some View { - HStack { - Text("\(label)") - .fontWeight(.bold) - Text(content) - } + Image(systemName: systemName) + .font(.system(size: 25)) + .colorMultiply(.blue) + .saturation(0.8) + .onTapGesture { + action() + } } } -struct PreferencesRowUIView_Previews: PreviewProvider { - static var previews: some View { - PreferencesRowUIView(label: "Label", content: "v02.2002") - } +#Preview { + ImageWithAction(systemName: "chevron.up.circle.fill") {} } diff --git a/openHABWatch Extension/Views/Utils/MapView.swift b/openHABWatch/Views/Utils/MapView.swift similarity index 82% rename from openHABWatch Extension/Views/Utils/MapView.swift rename to openHABWatch/Views/Utils/MapView.swift index a57e7c0aa..53e7dc6a8 100644 --- a/openHABWatch Extension/Views/Utils/MapView.swift +++ b/openHABWatch/Views/Utils/MapView.swift @@ -38,10 +38,7 @@ struct MapView: View { } } -struct MapView_Previews: PreviewProvider { - static var previews: some View { - let widget = UserData().widgets[9] - return MapView(widget: widget) - .previewDevice("Apple Watch Series 5 - 44mm") - } +#Preview { + let widget = UserData().widgets[9] + return MapView(widget: widget) } diff --git a/openHABWatch Extension/Views/Utils/PreviewConstants.swift b/openHABWatch/Views/Utils/PreviewConstants.swift similarity index 98% rename from openHABWatch Extension/Views/Utils/PreviewConstants.swift rename to openHABWatch/Views/Utils/PreviewConstants.swift index 517c51f6c..8047f2083 100644 --- a/openHABWatch Extension/Views/Utils/PreviewConstants.swift +++ b/openHABWatch/Views/Utils/PreviewConstants.swift @@ -12,13 +12,13 @@ import Foundation enum PreviewConstants { - static let remoteURLString = "http://192.168.2.15:8081" + static let remoteURLString = "http://192.168.2.10:8080" static let sitemapJson = """ { "id": "watch", "title": "watch", - "link": "http://192.168.2.15:8081/rest/sitemaps/watch/watch", + "link": "http://192.168.2.10:8080/rest/sitemaps/watch/watch", "leaf": true, "timeout": false, "widgets": [ @@ -102,7 +102,7 @@ enum PreviewConstants { "switchSupport": false, "sendFrequency": 0, "item": { - "link": "http://192.168.2.15:8081/rest/items/lcnLightDimmer", + "link": "http://192.168.2.10:8080/rest/items/lcnLightDimmer", "state": "100", "stateDescription": { "pattern": "%s", diff --git a/openHABWatch Extension/Views/Utils/TextLabelView.swift b/openHABWatch/Views/Utils/TextLabelView.swift similarity index 79% rename from openHABWatch Extension/Views/Utils/TextLabelView.swift rename to openHABWatch/Views/Utils/TextLabelView.swift index d4cdc2ae4..5e492fbb5 100644 --- a/openHABWatch Extension/Views/Utils/TextLabelView.swift +++ b/openHABWatch/Views/Utils/TextLabelView.swift @@ -22,9 +22,7 @@ struct TextLabelView: View { } } -struct TextLabelView_Previews: PreviewProvider { - static var previews: some View { - let widget = UserData().widgets[2] - return TextLabelView(widget: widget) - } +#Preview { + let widget = UserData().widgets[2] + return TextLabelView(widget: widget) } diff --git a/openHABWatch/openHABWatch.entitlements b/openHABWatch/openHABWatch.entitlements deleted file mode 100644 index 0c67376eb..000000000 --- a/openHABWatch/openHABWatch.entitlements +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/openHABWatchSwiftUI Watch AppTests/OpenHABWatchAppTests.swift b/openHABWatchSwiftUI Watch AppTests/OpenHABWatchAppTests.swift new file mode 100644 index 000000000..52d1412f8 --- /dev/null +++ b/openHABWatchSwiftUI Watch AppTests/OpenHABWatchAppTests.swift @@ -0,0 +1,49 @@ +// Copyright (c) 2010-2024 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 + +// Copyright (c) 2010-2023 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 + +@testable import openHABWatch +import XCTest + +final class OpenHABWatchAppTests: XCTestCase { + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testExample() throws { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. + // Any test you write for XCTest can be annotated as throws and async. + // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error. + // Tests marked async will run the test method on an arbitrary thread managed by the Swift runtime. + } + + func testPerformanceExample() throws { + // This is an example of a performance test case. + measure { + // Put the code you want to measure the time of here. + } + } +} diff --git a/openHABWatchSwiftUI Watch AppUITests/OpenHABWatchLaunchTests.swift b/openHABWatchSwiftUI Watch AppUITests/OpenHABWatchLaunchTests.swift new file mode 100644 index 000000000..5c124e0ab --- /dev/null +++ b/openHABWatchSwiftUI Watch AppUITests/OpenHABWatchLaunchTests.swift @@ -0,0 +1,46 @@ +// Copyright (c) 2010-2024 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 + +// Copyright (c) 2010-2023 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 XCTest + +final class OpenHABWatchLaunchTests: XCTestCase { + override class var runsForEachTargetApplicationUIConfiguration: Bool { + true + } + + override func setUpWithError() throws { + continueAfterFailure = false + } + + func testLaunch() throws { + let app = XCUIApplication() + app.launch() + + // Insert steps here to perform after app launch but before taking a screenshot, + // such as logging into a test account or navigating somewhere in the app + + let attachment = XCTAttachment(screenshot: app.screenshot()) + attachment.name = "Launch Screen" + attachment.lifetime = .keepAlways + add(attachment) + } +} diff --git a/openHABWatchSwiftUI Watch AppUITests/OpenHABWatchUITests.swift b/openHABWatchSwiftUI Watch AppUITests/OpenHABWatchUITests.swift new file mode 100644 index 000000000..efbe6008c --- /dev/null +++ b/openHABWatchSwiftUI Watch AppUITests/OpenHABWatchUITests.swift @@ -0,0 +1,55 @@ +// Copyright (c) 2010-2024 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 + +// Copyright (c) 2010-2023 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 XCTest + +final class OpenHABWatchUITests: XCTestCase { + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + + // In UI tests it is usually best to stop immediately when a failure occurs. + continueAfterFailure = false + + // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testExample() throws { + // UI tests must launch the application that they test. + let app = XCUIApplication() + app.launch() + + // Use XCTAssert and related functions to verify your tests produce the correct results. + } + + func testLaunchPerformance() throws { + if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) { + // This measures how long it takes to launch your application. + measure(metrics: [XCTApplicationLaunchMetric()]) { + XCUIApplication().launch() + } + } + } +}