From 61c9e34488cf57ab67ebe34b40bc8a25b9845f9c Mon Sep 17 00:00:00 2001 From: Tim Bert <5411131+timbms@users.noreply.github.com> Date: Thu, 31 Oct 2024 15:29:30 +0100 Subject: [PATCH 1/7] Add log viewer to watch app Signed-off-by: Tim Bert <5411131+timbms@users.noreply.github.com> --- openHAB.xcodeproj/project.pbxproj | 4 + openHABWatch/OpenHABWatch.swift | 4 + openHABWatch/Views/LogsViewer.swift | 111 +++++++++++++++++++++++ openHABWatch/Views/Rows/LogsViewer.swift | 43 +++++++++ 4 files changed, 162 insertions(+) create mode 100644 openHABWatch/Views/LogsViewer.swift create mode 100644 openHABWatch/Views/Rows/LogsViewer.swift diff --git a/openHAB.xcodeproj/project.pbxproj b/openHAB.xcodeproj/project.pbxproj index ae72cb94..3fc9f5af 100644 --- a/openHAB.xcodeproj/project.pbxproj +++ b/openHAB.xcodeproj/project.pbxproj @@ -79,6 +79,7 @@ DA0776F0234788010086C685 /* UserData.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA0776EF234788010086C685 /* UserData.swift */; }; DA0F37D023D4ACC7007EAB48 /* SliderRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA0F37CF23D4ACC7007EAB48 /* SliderRow.swift */; }; DA15BFBD23C6726400BD8ADA /* ObservableOpenHABDataObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA15BFBC23C6726400BD8ADA /* ObservableOpenHABDataObject.swift */; }; + DA162BEC2CD3B53E0040DAE5 /* LogsViewer.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA162BEB2CD3B53E0040DAE5 /* LogsViewer.swift */; }; DA19E25B22FD801D002F8F2F /* OpenHABGeneralTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA19E25A22FD801D002F8F2F /* OpenHABGeneralTests.swift */; }; DA21EAE22339621C001AB415 /* Throttler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA21EAE12339621C001AB415 /* Throttler.swift */; }; DA242C622C83588600AFB10D /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA242C612C83588600AFB10D /* SettingsView.swift */; }; @@ -346,6 +347,7 @@ DA0776EF234788010086C685 /* UserData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserData.swift; sourceTree = ""; }; DA0F37CF23D4ACC7007EAB48 /* SliderRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SliderRow.swift; sourceTree = ""; }; DA15BFBC23C6726400BD8ADA /* ObservableOpenHABDataObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObservableOpenHABDataObject.swift; sourceTree = ""; }; + DA162BEB2CD3B53E0040DAE5 /* LogsViewer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogsViewer.swift; sourceTree = ""; }; DA19E25A22FD801D002F8F2F /* OpenHABGeneralTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenHABGeneralTests.swift; sourceTree = ""; }; DA1C2E4B230DC28F00FACFB0 /* Appfile */ = {isa = PBXFileReference; lastKnownFileType = text; path = Appfile; sourceTree = ""; }; DA1C2E4C230DC28F00FACFB0 /* SnapshotHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnapshotHelper.swift; sourceTree = ""; }; @@ -775,6 +777,7 @@ isa = PBXGroup; children = ( DA0775262346705F0086C685 /* ContentView.swift */, + DA162BEB2CD3B53E0040DAE5 /* LogsViewer.swift */, DAC6608C236F771600F4501E /* PreferencesSwiftUIView.swift */, DAF457A323DB7A820018B495 /* Rows */, DAF457A723DBA2C40018B495 /* Utils */, @@ -1460,6 +1463,7 @@ DA32D1B42C8C98C40018D974 /* IconWithAction.swift in Sources */, DA07764A234683BC0086C685 /* SwitchRow.swift in Sources */, DA2E0AA423DC96E9009B0A99 /* ImageWithAction.swift in Sources */, + DA162BEC2CD3B53E0040DAE5 /* LogsViewer.swift in Sources */, DAF4578723D798A50018B495 /* TextLabelView.swift in Sources */, DA0749DE23E0B5950057FA83 /* ColorPickerRow.swift in Sources */, DA7224D223828D3400712D20 /* PreviewConstants.swift in Sources */, diff --git a/openHABWatch/OpenHABWatch.swift b/openHABWatch/OpenHABWatch.swift index 3a207800..0aaf26ed 100644 --- a/openHABWatch/OpenHABWatch.swift +++ b/openHABWatch/OpenHABWatch.swift @@ -32,6 +32,10 @@ struct OpenHABWatch: App { .tabItem { Label("Preferences", systemSymbol: .circleFill) } + LogsViewer() + .tabItem { + Label("Debug", systemSymbol: .circleFill) + } } .tabViewStyle(.page) .environmentObject(settings) diff --git a/openHABWatch/Views/LogsViewer.swift b/openHABWatch/Views/LogsViewer.swift new file mode 100644 index 00000000..d4ac8cbc --- /dev/null +++ b/openHABWatch/Views/LogsViewer.swift @@ -0,0 +1,111 @@ +// +// LogView.swift +// openHABWatch +// +// Created by Tim Müller-Seydlitz on 31.10.24. +// Copyright © 2024 openHAB e.V. All rights reserved. +// + +import Foundation +import OSLog +import SwiftUI + +// Thanks to https://useyourloaf.com/blog/fetching-oslog-messages-in-swift/ + +extension OSLogEntryLog.Level { + fileprivate var description: String { + switch self { + case .undefined: "undefined" + case .debug: "debug" + case .info: "info" + case .notice: "notice" + case .error: "error" + case .fault: "fault" + @unknown default: "default" + } + } +} + +extension Logger { + static public func fetch(since date: Date, + predicateFormat: String) async throws -> [String] { + let store = try OSLogStore(scope: .currentProcessIdentifier) + let position = store.position(date: date) + let predicate = NSPredicate(format: predicateFormat) + let entries = try store.getEntries( + at: position, + matching: predicate + ) + + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss" + + var logs: [String] = [] + for entry in entries { + try Task.checkCancellation() + if let log = entry as? OSLogEntryLog { + var attributedMessage = AttributedString(dateFormatter.string(from: entry.date)) + attributedMessage.font = .headline + + logs.append(""" + \(dateFormatter.string(from: entry.date)): \ + \(log.category):\(log.level.description): \ + \(entry.composedMessage)\n + """) + } else { + logs.append("\(entry.date): \(entry.composedMessage)\n") + } + } + + if logs.isEmpty { logs = ["Nothing found"] } + return logs + } +} + +struct LogsViewer: View { + @State private var text = "Loading..." + + static private let template = NSPredicate(format: + "(subsystem BEGINSWITH $PREFIX)") + + let myFont = Font + .system(size: 10) + .monospaced() + + private func fetchLogs() async -> String { + let calendar = Calendar.current + guard let dayAgo = calendar.date(byAdding: .day, + value: -1, to: Date.now) else { + return "Invalid calendar" + } + + do { + let predicate = Self.template.withSubstitutionVariables( + [ + "PREFIX": "org.openhab" + ]) + + let logs = try await Logger.fetch(since: dayAgo, + predicateFormat: predicate.predicateFormat) + return logs.joined() + } catch { + return error.localizedDescription + } + } + + var body: some View { + + ScrollView { + Text(text) + .font(myFont) + .padding() + } + .task { + text = await fetchLogs() + } + } +} + +#Preview { + LogsViewer() +} diff --git a/openHABWatch/Views/Rows/LogsViewer.swift b/openHABWatch/Views/Rows/LogsViewer.swift new file mode 100644 index 00000000..4a0944d8 --- /dev/null +++ b/openHABWatch/Views/Rows/LogsViewer.swift @@ -0,0 +1,43 @@ +// +// LogView.swift +// openHABWatch +// +// Created by Tim Müller-Seydlitz on 31.10.24. +// Copyright © 2024 openHAB e.V. All rights reserved. +// + +import Foundation +import OSLog +import SwiftUI + +struct LogsViewer: View { + let logs: [OSLogEntryLog] + + init() { + let logStore = try! OSLogStore(scope: .currentProcessIdentifier) + self.logs = try! logStore.getEntries().compactMap { entry in + guard let logEntry = entry as? OSLogEntryLog, + logEntry.subsystem.starts(with: "com.donnywals") == true else { + return nil + } + + return logEntry + } + } + + var body: some View { + List(logs, id: \.self) { log in + VStack(alignment: .leading) { + Text(log.composedMessage) + HStack { + Text(log.subsystem) + Text(log.date, format: .dateTime) + }.bold() + } + } + } +} + +#Preview { + LogsViewer() +} From 1575a8c9c508bf67314e419ab0407e48c197b32d Mon Sep 17 00:00:00 2001 From: Tim Bert <5411131+timbms@users.noreply.github.com> Date: Thu, 31 Oct 2024 15:59:39 +0100 Subject: [PATCH 2/7] Remove LogsViewer.swift in openHABWatch/Views/Rows Signed-off-by: Tim Bert <5411131+timbms@users.noreply.github.com> --- openHABWatch/Views/Rows/LogsViewer.swift | 43 ------------------------ 1 file changed, 43 deletions(-) delete mode 100644 openHABWatch/Views/Rows/LogsViewer.swift diff --git a/openHABWatch/Views/Rows/LogsViewer.swift b/openHABWatch/Views/Rows/LogsViewer.swift deleted file mode 100644 index 4a0944d8..00000000 --- a/openHABWatch/Views/Rows/LogsViewer.swift +++ /dev/null @@ -1,43 +0,0 @@ -// -// LogView.swift -// openHABWatch -// -// Created by Tim Müller-Seydlitz on 31.10.24. -// Copyright © 2024 openHAB e.V. All rights reserved. -// - -import Foundation -import OSLog -import SwiftUI - -struct LogsViewer: View { - let logs: [OSLogEntryLog] - - init() { - let logStore = try! OSLogStore(scope: .currentProcessIdentifier) - self.logs = try! logStore.getEntries().compactMap { entry in - guard let logEntry = entry as? OSLogEntryLog, - logEntry.subsystem.starts(with: "com.donnywals") == true else { - return nil - } - - return logEntry - } - } - - var body: some View { - List(logs, id: \.self) { log in - VStack(alignment: .leading) { - Text(log.composedMessage) - HStack { - Text(log.subsystem) - Text(log.date, format: .dateTime) - }.bold() - } - } - } -} - -#Preview { - LogsViewer() -} From 358aaeecf9830f47f622e5d4a791f5542cbe3593 Mon Sep 17 00:00:00 2001 From: Tim Bert <5411131+timbms@users.noreply.github.com> Date: Thu, 31 Oct 2024 16:35:53 +0100 Subject: [PATCH 3/7] OpenHABOptions label as optional string Signed-off-by: Tim Bert <5411131+timbms@users.noreply.github.com> --- OpenHABCore/Sources/OpenHABCore/Model/OpenHABOptions.swift | 2 +- OpenHABCore/Sources/OpenHABCore/Model/OpenHABWidget.swift | 2 +- openHABWatch/Model/ObservableOpenHABWidget.swift | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/OpenHABCore/Sources/OpenHABCore/Model/OpenHABOptions.swift b/OpenHABCore/Sources/OpenHABCore/Model/OpenHABOptions.swift index c98f5e1b..c4766ed8 100644 --- a/OpenHABCore/Sources/OpenHABCore/Model/OpenHABOptions.swift +++ b/OpenHABCore/Sources/OpenHABCore/Model/OpenHABOptions.swift @@ -13,5 +13,5 @@ import Foundation public class OpenHABOptions: Decodable { public var value = "" - public var label = "" + public var label: String? } diff --git a/OpenHABCore/Sources/OpenHABCore/Model/OpenHABWidget.swift b/OpenHABCore/Sources/OpenHABCore/Model/OpenHABWidget.swift index 028cd555..66488044 100644 --- a/OpenHABCore/Sources/OpenHABCore/Model/OpenHABWidget.swift +++ b/OpenHABCore/Sources/OpenHABCore/Model/OpenHABWidget.swift @@ -119,7 +119,7 @@ public class OpenHABWidget: NSObject, MKAnnotation, Identifiable { if mappings.isEmpty, let commandOptions = item?.commandDescription?.commandOptions { commandOptions.map { OpenHABWidgetMapping(command: $0.command, label: $0.label ?? "") } } else if mappings.isEmpty, let stateOptions = item?.stateDescription?.options { - stateOptions.map { OpenHABWidgetMapping(command: $0.value, label: $0.label) } + stateOptions.map { OpenHABWidgetMapping(command: $0.value, label: $0.label ?? "") } } else { mappings } diff --git a/openHABWatch/Model/ObservableOpenHABWidget.swift b/openHABWatch/Model/ObservableOpenHABWidget.swift index 051ea2e2..ee4c9b87 100644 --- a/openHABWatch/Model/ObservableOpenHABWidget.swift +++ b/openHABWatch/Model/ObservableOpenHABWidget.swift @@ -97,7 +97,7 @@ class ObservableOpenHABWidget: NSObject, MKAnnotation, Identifiable, ObservableO if mappings.isEmpty, let commandOptions = item?.commandDescription?.commandOptions { commandOptions.map { OpenHABWidgetMapping(command: $0.command, label: $0.label ?? "") } } else if mappings.isEmpty, let stateOptions = item?.stateDescription?.options { - stateOptions.map { OpenHABWidgetMapping(command: $0.value, label: $0.label) } + stateOptions.map { OpenHABWidgetMapping(command: $0.value, label: $0.label ?? "") } } else { mappings } From 974c9e9e29080fea21d95f52266abf7317ce6eaa Mon Sep 17 00:00:00 2001 From: Tim Bert <5411131+timbms@users.noreply.github.com> Date: Thu, 31 Oct 2024 18:40:03 +0100 Subject: [PATCH 4/7] Setup a generic log viewer Signed-off-by: Tim Bert <5411131+timbms@users.noreply.github.com> --- .../Sources/OpenHABCore/Util/Logger.swift | 101 ++++++++++++++++ openHAB.xcodeproj/project.pbxproj | 18 +++ openHABWatch/OpenHABWatch.swift | 3 +- openHABWatch/Views/LogsViewer.swift | 114 +++++------------- 4 files changed, 148 insertions(+), 88 deletions(-) create mode 100644 OpenHABCore/Sources/OpenHABCore/Util/Logger.swift diff --git a/OpenHABCore/Sources/OpenHABCore/Util/Logger.swift b/OpenHABCore/Sources/OpenHABCore/Util/Logger.swift new file mode 100644 index 00000000..c54fdfb4 --- /dev/null +++ b/OpenHABCore/Sources/OpenHABCore/Util/Logger.swift @@ -0,0 +1,101 @@ +// 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 OSLog + +// swiftlint:disable:next file_types_order +private extension OSLogEntryLog.Level { + var description: String { + switch self { + case .undefined: "undefined" + case .debug: "debug" + case .info: "info" + case .notice: "notice" + case .error: "error" + case .fault: "fault" + @unknown default: "default" + } + } +} + +public extension Logger { + static func fetch(since date: Date, + predicateFormat: String) async throws -> [String] { + let store = try OSLogStore(scope: .currentProcessIdentifier) + let position = store.position(date: date) + let predicate = NSPredicate(format: predicateFormat) + + let entries = try store + .getEntries( + at: position, + matching: predicate + ) + + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss" + + var logs: [String] = [] + for entry in entries { + try Task.checkCancellation() + if let log = entry as? OSLogEntryLog { + var attributedMessage = AttributedString(dateFormatter.string(from: entry.date)) + attributedMessage.font = .headline + + logs.append(""" + \(entry.date.formatted(.iso8601)): \ + \(log.category):\(log.level.description): \ + \(entry.composedMessage)\n + """) + } else { + logs.append("\(entry.date): \(entry.composedMessage)\n") + } + } + + if logs.isEmpty { logs = ["Nothing found"] } + return logs + } +} + +public protocol LogServiceProtocol { + func fetchLogs(with template: NSPredicate) async -> String +} + +public struct LogService { + public init() {} +} + +extension LogService: LogServiceProtocol { + public func fetchLogs(with template: NSPredicate) async -> String { + let calendar = Calendar.current + guard let dayAgo = calendar.date( + byAdding: .day, + value: -1, + to: Date.now + ) else { + return "Invalid calendar" + } + + do { + let predicate = template.withSubstitutionVariables( + [ + "PREFIX": "org.openhab" + ]) + + let logs = try await Logger.fetch( + since: dayAgo, + predicateFormat: predicate.predicateFormat + ) + return logs.joined() + } catch { + return error.localizedDescription + } + } +} diff --git a/openHAB.xcodeproj/project.pbxproj b/openHAB.xcodeproj/project.pbxproj index 3fc9f5af..5e733355 100644 --- a/openHAB.xcodeproj/project.pbxproj +++ b/openHAB.xcodeproj/project.pbxproj @@ -1093,6 +1093,7 @@ 39C91164B60A5677322E8DE2 /* Frameworks */, DA07751D2346705F0086C685 /* Sources */, 93F38C61238034AE001B1451 /* Embed Frameworks */, + DA162BEE2CD3EDFE0040DAE5 /* ShellScript */, ); buildRules = ( ); @@ -1397,6 +1398,23 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + DA162BEE2CD3EDFE0040DAE5 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "cd BuildTools\nSDKROOT=(xcrun --sdk macosx --show-sdk-path)\n\nswift package plugin --allow-writing-to-package-directory --allow-writing-to-directory \"$SRCROOT\" swiftformat \"$SRCROOT\" --config ./.swiftformat --cache /private/tmp/\nswift package plugin --allow-writing-to-package-directory --allow-writing-to-directory ../ swiftlint --cache-path /private/tmp/\n# Type a script or drag a script file from your workspace to insert its path.\n"; + }; DAF0A2902C56FE9F00A14A6A /* Run swiftformat & swiftlint */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; diff --git a/openHABWatch/OpenHABWatch.swift b/openHABWatch/OpenHABWatch.swift index 0aaf26ed..5d4d9543 100644 --- a/openHABWatch/OpenHABWatch.swift +++ b/openHABWatch/OpenHABWatch.swift @@ -9,6 +9,7 @@ // // SPDX-License-Identifier: EPL-2.0 +import OpenHABCore import SDWebImage import SDWebImageSVGCoder import SwiftUI @@ -32,7 +33,7 @@ struct OpenHABWatch: App { .tabItem { Label("Preferences", systemSymbol: .circleFill) } - LogsViewer() + LogsViewer(logService: LogService()) .tabItem { Label("Debug", systemSymbol: .circleFill) } diff --git a/openHABWatch/Views/LogsViewer.swift b/openHABWatch/Views/LogsViewer.swift index d4ac8cbc..9e0549b4 100644 --- a/openHABWatch/Views/LogsViewer.swift +++ b/openHABWatch/Views/LogsViewer.swift @@ -1,111 +1,51 @@ +// Copyright (c) 2010-2024 Contributors to the openHAB project // -// LogView.swift -// openHABWatch +// See the NOTICE file(s) distributed with this work for additional +// information. // -// Created by Tim Müller-Seydlitz on 31.10.24. -// Copyright © 2024 openHAB e.V. All rights reserved. +// 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 OSLog import SwiftUI // Thanks to https://useyourloaf.com/blog/fetching-oslog-messages-in-swift/ -extension OSLogEntryLog.Level { - fileprivate var description: String { - switch self { - case .undefined: "undefined" - case .debug: "debug" - case .info: "info" - case .notice: "notice" - case .error: "error" - case .fault: "fault" - @unknown default: "default" - } - } -} - -extension Logger { - static public func fetch(since date: Date, - predicateFormat: String) async throws -> [String] { - let store = try OSLogStore(scope: .currentProcessIdentifier) - let position = store.position(date: date) - let predicate = NSPredicate(format: predicateFormat) - let entries = try store.getEntries( - at: position, - matching: predicate - ) - - let dateFormatter = DateFormatter() - dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss" - - var logs: [String] = [] - for entry in entries { - try Task.checkCancellation() - if let log = entry as? OSLogEntryLog { - var attributedMessage = AttributedString(dateFormatter.string(from: entry.date)) - attributedMessage.font = .headline - - logs.append(""" - \(dateFormatter.string(from: entry.date)): \ - \(log.category):\(log.level.description): \ - \(entry.composedMessage)\n - """) - } else { - logs.append("\(entry.date): \(entry.composedMessage)\n") - } - } - - if logs.isEmpty { logs = ["Nothing found"] } - return logs - } -} - struct LogsViewer: View { - @State private var text = "Loading..." - - static private let template = NSPredicate(format: - "(subsystem BEGINSWITH $PREFIX)") - + let template = NSPredicate( + format: "(subsystem BEGINSWITH $PREFIX)" + ) let myFont = Font - .system(size: 10) - .monospaced() - - private func fetchLogs() async -> String { - let calendar = Calendar.current - guard let dayAgo = calendar.date(byAdding: .day, - value: -1, to: Date.now) else { - return "Invalid calendar" - } - - do { - let predicate = Self.template.withSubstitutionVariables( - [ - "PREFIX": "org.openhab" - ]) + .system(size: 10) + .monospaced() - let logs = try await Logger.fetch(since: dayAgo, - predicateFormat: predicate.predicateFormat) - return logs.joined() - } catch { - return error.localizedDescription - } - } + var logService: LogServiceProtocol var body: some View { - ScrollView { - Text(text) - .font(myFont) - .padding() + Text(text) + .font(myFont) + .padding() } .task { - text = await fetchLogs() + text = await logService.fetchLogs(with: template) } } + + @State private var text = "Loading..." +} + +struct MockLogService: LogServiceProtocol { + func fetchLogs(with template: NSPredicate) async -> String { + "Mocked Data" + } } #Preview { - LogsViewer() + LogsViewer(logService: MockLogService()) } From 91922f66750257b2ced04d70a23cb576408ccf16 Mon Sep 17 00:00:00 2001 From: Tim Bert <5411131+timbms@users.noreply.github.com> Date: Fri, 1 Nov 2024 12:02:34 +0100 Subject: [PATCH 5/7] Add ShareLink on watch app Signed-off-by: Tim Bert <5411131+timbms@users.noreply.github.com> --- openHAB.xcodeproj/project.pbxproj | 4 ++++ openHAB/LogView.swift | 34 +++++++++++++++++++++++++++++ openHAB/SettingsView.swift | 15 +++++++++++++ openHABWatch/Views/LogsViewer.swift | 14 ++++++++---- 4 files changed, 63 insertions(+), 4 deletions(-) create mode 100644 openHAB/LogView.swift diff --git a/openHAB.xcodeproj/project.pbxproj b/openHAB.xcodeproj/project.pbxproj index 5e733355..0836d0c3 100644 --- a/openHAB.xcodeproj/project.pbxproj +++ b/openHAB.xcodeproj/project.pbxproj @@ -80,6 +80,7 @@ DA0F37D023D4ACC7007EAB48 /* SliderRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA0F37CF23D4ACC7007EAB48 /* SliderRow.swift */; }; DA15BFBD23C6726400BD8ADA /* ObservableOpenHABDataObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA15BFBC23C6726400BD8ADA /* ObservableOpenHABDataObject.swift */; }; DA162BEC2CD3B53E0040DAE5 /* LogsViewer.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA162BEB2CD3B53E0040DAE5 /* LogsViewer.swift */; }; + DA162BF02CD4CC730040DAE5 /* LogView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA162BEF2CD4CC730040DAE5 /* LogView.swift */; }; DA19E25B22FD801D002F8F2F /* OpenHABGeneralTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA19E25A22FD801D002F8F2F /* OpenHABGeneralTests.swift */; }; DA21EAE22339621C001AB415 /* Throttler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA21EAE12339621C001AB415 /* Throttler.swift */; }; DA242C622C83588600AFB10D /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA242C612C83588600AFB10D /* SettingsView.swift */; }; @@ -348,6 +349,7 @@ DA0F37CF23D4ACC7007EAB48 /* SliderRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SliderRow.swift; sourceTree = ""; }; DA15BFBC23C6726400BD8ADA /* ObservableOpenHABDataObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObservableOpenHABDataObject.swift; sourceTree = ""; }; DA162BEB2CD3B53E0040DAE5 /* LogsViewer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogsViewer.swift; sourceTree = ""; }; + DA162BEF2CD4CC730040DAE5 /* LogView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogView.swift; sourceTree = ""; }; DA19E25A22FD801D002F8F2F /* OpenHABGeneralTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenHABGeneralTests.swift; sourceTree = ""; }; DA1C2E4B230DC28F00FACFB0 /* Appfile */ = {isa = PBXFileReference; lastKnownFileType = text; path = Appfile; sourceTree = ""; }; DA1C2E4C230DC28F00FACFB0 /* SnapshotHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnapshotHelper.swift; sourceTree = ""; }; @@ -871,6 +873,7 @@ 653B54BF285C0AC700298ECD /* OpenHABRootViewController.swift */, 65570A7C2476D16A00D524EA /* OpenHABWebViewController.swift */, DFB2624318830A3600D3244D /* OpenHABSitemapViewController.swift */, + DA162BEF2CD4CC730040DAE5 /* LogView.swift */, DAC65FC6236EDF3900F4501E /* SpinnerViewController.swift */, DA6B2EF62C8B92E800DF77CF /* SelectionView.swift */, DA242C612C83588600AFB10D /* SettingsView.swift */, @@ -1558,6 +1561,7 @@ 1224F78F228A89FD00750965 /* WatchMessageService.swift in Sources */, DAA42BAC21DC984A00244B2A /* WebUITableViewCell.swift in Sources */, DF4B84131886DAC400F34902 /* FrameUITableViewCell.swift in Sources */, + DA162BF02CD4CC730040DAE5 /* LogView.swift in Sources */, DF4B84161886EACA00F34902 /* GenericUITableViewCell.swift in Sources */, 935B484625342B8E00E44CF0 /* URL+Static.swift in Sources */, B7D5ECE121499E55001B0EC6 /* MapViewTableViewCell.swift in Sources */, diff --git a/openHAB/LogView.swift b/openHAB/LogView.swift new file mode 100644 index 00000000..62bc4177 --- /dev/null +++ b/openHAB/LogView.swift @@ -0,0 +1,34 @@ +// 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 OSLog +import SwiftUI + +struct LogView: View { + let logs: [OSLogEntryLog] + + var body: some View { + List(logs, id: \.self) { log in + VStack(alignment: .leading) { + Text(log.composedMessage) + HStack { + Text(log.subsystem) + Text(log.date, format: .dateTime) + }.bold() + } + } + } +} + +#Preview { + LogView(logs: .init([])) +} diff --git a/openHAB/SettingsView.swift b/openHAB/SettingsView.swift index cd728014..6729a9e2 100644 --- a/openHAB/SettingsView.swift +++ b/openHAB/SettingsView.swift @@ -43,6 +43,8 @@ struct SettingsView: View { @State private var sitemaps: [OpenHABSitemap] = [] + @State private var exportShown = false + @Environment(\.dismiss) private var dismiss var appData: OpenHABDataObject? { @@ -287,6 +289,19 @@ struct SettingsView: View { } } +// Section(header: Text(LocalizedStringKey("debug"))) { +// ShareLink(items: [logs.entries.joined(separator: "\n")]) { +// Text("Share Logs") +// } +// Button("exportLogs") { +// logs.export() +// exportShown.toggle() +// } +// .sheet(isPresented: $exportShown) { +// ShareView(items: [logs.entries.joined(separator: "\n")]) +// } +// } + Section(header: Text(LocalizedStringKey("about_settings"))) { LabeledContent("App Version", value: appVersion) diff --git a/openHABWatch/Views/LogsViewer.swift b/openHABWatch/Views/LogsViewer.swift index 9e0549b4..916ef5b0 100644 --- a/openHABWatch/Views/LogsViewer.swift +++ b/openHABWatch/Views/LogsViewer.swift @@ -16,6 +16,7 @@ import SwiftUI // Thanks to https://useyourloaf.com/blog/fetching-oslog-messages-in-swift/ +// swiftlint:disable:next file_types_order struct LogsViewer: View { let template = NSPredicate( format: "(subsystem BEGINSWITH $PREFIX)" @@ -27,10 +28,15 @@ struct LogsViewer: View { var logService: LogServiceProtocol var body: some View { - ScrollView { - Text(text) - .font(myFont) - .padding() + VStack { + ShareLink(item: text) { + Label("Share Logs", systemSymbol: .squareAndArrowUp) + } + ScrollView { + Text(text) + .font(myFont) + .padding() + } } .task { text = await logService.fetchLogs(with: template) From 73a1305635c3f1466c0ea35535e752ce61ac0f6a Mon Sep 17 00:00:00 2001 From: Tim Bert <5411131+timbms@users.noreply.github.com> Date: Wed, 13 Nov 2024 16:04:11 +0100 Subject: [PATCH 6/7] Reworked SitemapView Signed-off-by: Tim Bert <5411131+timbms@users.noreply.github.com> --- .../Sources/OpenHABCore/Util/Logger.swift | 20 ++++- openHAB.xcodeproj/project.pbxproj | 20 +++-- openHAB/LogView.swift | 34 -------- openHAB/LogsViewer.swift | 87 +++++++++++++++++++ openHAB/SettingsView.swift | 19 ++-- openHABWatch/ContentView.swift | 48 ++++++++++ openHABWatch/OpenHABWatch.swift | 30 ++----- openHABWatch/Views/LogsViewer.swift | 21 +++-- .../Views/PreferencesSwiftUIView.swift | 11 ++- .../{ContentView.swift => SitemapView.swift} | 36 ++++---- 10 files changed, 218 insertions(+), 108 deletions(-) delete mode 100644 openHAB/LogView.swift create mode 100644 openHAB/LogsViewer.swift create mode 100644 openHABWatch/ContentView.swift rename openHABWatch/Views/{ContentView.swift => SitemapView.swift} (86%) diff --git a/OpenHABCore/Sources/OpenHABCore/Util/Logger.swift b/OpenHABCore/Sources/OpenHABCore/Util/Logger.swift index c54fdfb4..c178f315 100644 --- a/OpenHABCore/Sources/OpenHABCore/Util/Logger.swift +++ b/OpenHABCore/Sources/OpenHABCore/Util/Logger.swift @@ -9,8 +9,11 @@ // // SPDX-License-Identifier: EPL-2.0 +import CoreTransferable import OSLog +// Thanks to https://useyourloaf.com/blog/fetching-oslog-messages-in-swift/ + // swiftlint:disable:next file_types_order private extension OSLogEntryLog.Level { var description: String { @@ -75,8 +78,8 @@ public struct LogService { extension LogService: LogServiceProtocol { public func fetchLogs(with template: NSPredicate) async -> String { let calendar = Calendar.current - guard let dayAgo = calendar.date( - byAdding: .day, + guard let hourAgo = calendar.date( + byAdding: .hour, value: -1, to: Date.now ) else { @@ -90,7 +93,7 @@ extension LogService: LogServiceProtocol { ]) let logs = try await Logger.fetch( - since: dayAgo, + since: hourAgo, predicateFormat: predicate.predicateFormat ) return logs.joined() @@ -99,3 +102,14 @@ extension LogService: LogServiceProtocol { } } } + +// extension LogService: Transferable { +// +// static var containerUrl = FileManager.default.url(forUbiquityContainerIdentifier: nil)?.appendingPathComponent("Documents", isDirectory: true) +// +// public static var transferRepresentation: some TransferRepresentation { +// FileRepresentation(exportedContentType: .commaSeparatedText) { csvFile in +// SentTransferredFile(csvFile.url) +// } +// } +// } diff --git a/openHAB.xcodeproj/project.pbxproj b/openHAB.xcodeproj/project.pbxproj index 0836d0c3..6f1dcbed 100644 --- a/openHAB.xcodeproj/project.pbxproj +++ b/openHAB.xcodeproj/project.pbxproj @@ -80,7 +80,7 @@ DA0F37D023D4ACC7007EAB48 /* SliderRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA0F37CF23D4ACC7007EAB48 /* SliderRow.swift */; }; DA15BFBD23C6726400BD8ADA /* ObservableOpenHABDataObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA15BFBC23C6726400BD8ADA /* ObservableOpenHABDataObject.swift */; }; DA162BEC2CD3B53E0040DAE5 /* LogsViewer.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA162BEB2CD3B53E0040DAE5 /* LogsViewer.swift */; }; - DA162BF02CD4CC730040DAE5 /* LogView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA162BEF2CD4CC730040DAE5 /* LogView.swift */; }; + DA162BF02CD4CC730040DAE5 /* LogsViewer.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA162BEF2CD4CC730040DAE5 /* LogsViewer.swift */; }; DA19E25B22FD801D002F8F2F /* OpenHABGeneralTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA19E25A22FD801D002F8F2F /* OpenHABGeneralTests.swift */; }; DA21EAE22339621C001AB415 /* Throttler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA21EAE12339621C001AB415 /* Throttler.swift */; }; DA242C622C83588600AFB10D /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA242C612C83588600AFB10D /* SettingsView.swift */; }; @@ -111,13 +111,14 @@ 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 */; }; + DA8F986B2CDA4CAA001F5E8A /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA8F986A2CDA4CAA001F5E8A /* ContentView.swift */; }; 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 */; }; + DAAC30872CBBF0420041927F /* SitemapView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA0775262346705F0086C685 /* SitemapView.swift */; }; DAC65FC7236EDF3900F4501E /* SpinnerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAC65FC6236EDF3900F4501E /* SpinnerViewController.swift */; }; DAC6608D236F771600F4501E /* PreferencesSwiftUIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAC6608C236F771600F4501E /* PreferencesSwiftUIView.swift */; }; DAC9395522B00E7600C5F423 /* XCTestCaseExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAC9395422B00E7600C5F423 /* XCTestCaseExtension.swift */; }; @@ -337,7 +338,7 @@ DA0775152346705D0086C685 /* openHABWatch.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = openHABWatch.app; sourceTree = BUILT_PRODUCTS_DIR; }; 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 = ""; }; + DA0775262346705F0086C685 /* SitemapView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SitemapView.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 = ""; }; @@ -349,7 +350,7 @@ DA0F37CF23D4ACC7007EAB48 /* SliderRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SliderRow.swift; sourceTree = ""; }; DA15BFBC23C6726400BD8ADA /* ObservableOpenHABDataObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObservableOpenHABDataObject.swift; sourceTree = ""; }; DA162BEB2CD3B53E0040DAE5 /* LogsViewer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogsViewer.swift; sourceTree = ""; }; - DA162BEF2CD4CC730040DAE5 /* LogView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogView.swift; sourceTree = ""; }; + DA162BEF2CD4CC730040DAE5 /* LogsViewer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogsViewer.swift; sourceTree = ""; }; DA19E25A22FD801D002F8F2F /* OpenHABGeneralTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenHABGeneralTests.swift; sourceTree = ""; }; DA1C2E4B230DC28F00FACFB0 /* Appfile */ = {isa = PBXFileReference; lastKnownFileType = text; path = Appfile; sourceTree = ""; }; DA1C2E4C230DC28F00FACFB0 /* SnapshotHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnapshotHelper.swift; sourceTree = ""; }; @@ -410,6 +411,7 @@ DA7E1E47222EB00B002AEFD8 /* PlayerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerView.swift; 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 = ""; }; + DA8F986A2CDA4CAA001F5E8A /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; 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 = ""; }; @@ -668,6 +670,7 @@ isa = PBXGroup; children = ( DAD0855F2AE47824001D36BE /* OpenHABWatch.swift */, + DA8F986A2CDA4CAA001F5E8A /* ContentView.swift */, DA0775252346705F0086C685 /* Extension */, 1224F7C9228A8ED100750965 /* External */, 1224F7C8228A8EC600750965 /* Domain */, @@ -778,7 +781,7 @@ DA658720236F841F007E2E7F /* Views */ = { isa = PBXGroup; children = ( - DA0775262346705F0086C685 /* ContentView.swift */, + DA0775262346705F0086C685 /* SitemapView.swift */, DA162BEB2CD3B53E0040DAE5 /* LogsViewer.swift */, DAC6608C236F771600F4501E /* PreferencesSwiftUIView.swift */, DAF457A323DB7A820018B495 /* Rows */, @@ -873,7 +876,7 @@ 653B54BF285C0AC700298ECD /* OpenHABRootViewController.swift */, 65570A7C2476D16A00D524EA /* OpenHABWebViewController.swift */, DFB2624318830A3600D3244D /* OpenHABSitemapViewController.swift */, - DA162BEF2CD4CC730040DAE5 /* LogView.swift */, + DA162BEF2CD4CC730040DAE5 /* LogsViewer.swift */, DAC65FC6236EDF3900F4501E /* SpinnerViewController.swift */, DA6B2EF62C8B92E800DF77CF /* SelectionView.swift */, DA242C612C83588600AFB10D /* SettingsView.swift */, @@ -1501,8 +1504,9 @@ 9350F17A23814FAC00054BA8 /* ObservableOpenHABSitemapPage.swift in Sources */, DAF457A023DA3E1C0018B495 /* SegmentRow.swift in Sources */, DAF4578923D79AA50018B495 /* DetailTextLabelView.swift in Sources */, - DAAC30872CBBF0420041927F /* ContentView.swift in Sources */, + DAAC30872CBBF0420041927F /* SitemapView.swift in Sources */, DA15BFBD23C6726400BD8ADA /* ObservableOpenHABDataObject.swift in Sources */, + DA8F986B2CDA4CAA001F5E8A /* ContentView.swift in Sources */, DAC9AF4924F966FA006DAE93 /* LazyView.swift in Sources */, DA0776F0234788010086C685 /* UserData.swift in Sources */, DAC6608D236F771600F4501E /* PreferencesSwiftUIView.swift in Sources */, @@ -1561,7 +1565,7 @@ 1224F78F228A89FD00750965 /* WatchMessageService.swift in Sources */, DAA42BAC21DC984A00244B2A /* WebUITableViewCell.swift in Sources */, DF4B84131886DAC400F34902 /* FrameUITableViewCell.swift in Sources */, - DA162BF02CD4CC730040DAE5 /* LogView.swift in Sources */, + DA162BF02CD4CC730040DAE5 /* LogsViewer.swift in Sources */, DF4B84161886EACA00F34902 /* GenericUITableViewCell.swift in Sources */, 935B484625342B8E00E44CF0 /* URL+Static.swift in Sources */, B7D5ECE121499E55001B0EC6 /* MapViewTableViewCell.swift in Sources */, diff --git a/openHAB/LogView.swift b/openHAB/LogView.swift deleted file mode 100644 index 62bc4177..00000000 --- a/openHAB/LogView.swift +++ /dev/null @@ -1,34 +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 OSLog -import SwiftUI - -struct LogView: View { - let logs: [OSLogEntryLog] - - var body: some View { - List(logs, id: \.self) { log in - VStack(alignment: .leading) { - Text(log.composedMessage) - HStack { - Text(log.subsystem) - Text(log.date, format: .dateTime) - }.bold() - } - } - } -} - -#Preview { - LogView(logs: .init([])) -} diff --git a/openHAB/LogsViewer.swift b/openHAB/LogsViewer.swift new file mode 100644 index 00000000..04ba49c1 --- /dev/null +++ b/openHAB/LogsViewer.swift @@ -0,0 +1,87 @@ +// 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 LogView: View { +// let logs: [OSLogEntryLog] +// +// var body: some View { +// List(logs, id: \.self) { log in +// VStack(alignment: .leading) { +// Text(log.composedMessage) +// HStack { +// Text(log.subsystem) +// Text(log.date, format: .dateTime) +// }.bold() +// } +// } +// } +// } +// +// #Preview { +// LogView(logs: .init([])) +// } + +import Foundation +import OpenHABCore +import OSLog +import SwiftUI + +// swiftlint:disable:next file_types_order +struct LogsViewer: View { + let template = NSPredicate( + format: "(subsystem BEGINSWITH $PREFIX)" + ) + let myFont = Font + .system(size: 10) + .monospaced() + + var logService: LogServiceProtocol + + var body: some View { + List { + Text(text) + .font(myFont) + } + .toolbar { + ToolbarItem(placement: .primaryAction) { + ShareLink( + item: text, + preview: SharePreview("Logs", image: Image(.openHABIcon)) + ) { + Label("Share Logs", systemSymbol: .squareAndArrowUp) + } + } + } + .navigationTitle("Logs") + .task { + text = await logService.fetchLogs(with: template) + } + } + + @State private var text = "Loading..." +} + +#if DEBUG +struct MockLogService: LogServiceProtocol { + func fetchLogs(with template: NSPredicate) async -> String { + """ + Mocked Data + Test data + """ + } +} +#endif + +#Preview { + LogsViewer(logService: MockLogService()) +} diff --git a/openHAB/SettingsView.swift b/openHAB/SettingsView.swift index 6729a9e2..5adf27cb 100644 --- a/openHAB/SettingsView.swift +++ b/openHAB/SettingsView.swift @@ -289,18 +289,13 @@ struct SettingsView: View { } } -// Section(header: Text(LocalizedStringKey("debug"))) { -// ShareLink(items: [logs.entries.joined(separator: "\n")]) { -// Text("Share Logs") -// } -// Button("exportLogs") { -// logs.export() -// exportShown.toggle() -// } -// .sheet(isPresented: $exportShown) { -// ShareView(items: [logs.entries.joined(separator: "\n")]) -// } -// } + Section(header: Text(LocalizedStringKey("debug"))) { + NavigationLink { + LogsViewer(logService: LogService()) + } label: { + Text("Logs") + } + } Section(header: Text(LocalizedStringKey("about_settings"))) { LabeledContent("App Version", value: appVersion) diff --git a/openHABWatch/ContentView.swift b/openHABWatch/ContentView.swift new file mode 100644 index 00000000..ffb693f0 --- /dev/null +++ b/openHABWatch/ContentView.swift @@ -0,0 +1,48 @@ +// 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 + +struct ContentView: View { + @ObservedObject var viewModel: UserData + @EnvironmentObject var settings: ObservableOpenHABDataObject + @State var title = "openHAB" + + var body: some View { + TabView { + NavigationStack { + SitemapView(viewModel: viewModel) + } + .tabItem { + Label("Sitemap", systemSymbol: .circleFill) + } + NavigationStack { + PreferencesSwiftUIView() + } + .tabItem { + Label("Preferences", systemSymbol: .circleFill) + } + NavigationStack { + LogsViewer(logService: LogService()) + } + .tabItem { + Label("Debug", systemSymbol: .circleFill) + } + } + .tabViewStyle(.page) + } +} + +#Preview { + ContentView(viewModel: .init()) + .environmentObject(ObservableOpenHABDataObject()) +} diff --git a/openHABWatch/OpenHABWatch.swift b/openHABWatch/OpenHABWatch.swift index 5d4d9543..8fb89e2d 100644 --- a/openHABWatch/OpenHABWatch.swift +++ b/openHABWatch/OpenHABWatch.swift @@ -24,28 +24,14 @@ struct OpenHABWatch: App { var body: some Scene { WindowGroup { - TabView { - ContentView(viewModel: userData) - .tabItem { - Label("Sitemap", systemSymbol: .circleFill) - } - PreferencesSwiftUIView() - .tabItem { - Label("Preferences", systemSymbol: .circleFill) - } - LogsViewer(logService: LogService()) - .tabItem { - Label("Debug", systemSymbol: .circleFill) - } - } - .tabViewStyle(.page) - .environmentObject(settings) - .task { - let center = UNUserNotificationCenter.current() - _ = try? await center.requestAuthorization( - options: [.alert, .sound, .badge] - ) - } + ContentView(viewModel: userData) + .environmentObject(settings) + .task { + let center = UNUserNotificationCenter.current() + _ = try? await center.requestAuthorization( + options: [.alert, .sound, .badge] + ) + } } WKNotificationScene(controller: NotificationController.self, category: "openHABNotification") } diff --git a/openHABWatch/Views/LogsViewer.swift b/openHABWatch/Views/LogsViewer.swift index 916ef5b0..36b5bed5 100644 --- a/openHABWatch/Views/LogsViewer.swift +++ b/openHABWatch/Views/LogsViewer.swift @@ -28,16 +28,21 @@ struct LogsViewer: View { var logService: LogServiceProtocol var body: some View { - VStack { - ShareLink(item: text) { - Label("Share Logs", systemSymbol: .squareAndArrowUp) - } - ScrollView { - Text(text) - .font(myFont) - .padding() + List { + Text(text) + .font(myFont) + } + .toolbar { + ToolbarItem(placement: .primaryAction) { + ShareLink( + item: text, + preview: SharePreview("Logs") + ) { + Label("Share Logs", systemSymbol: .squareAndArrowUp) + } } } + .navigationTitle("Logs") .task { text = await logService.fetchLogs(with: template) } diff --git a/openHABWatch/Views/PreferencesSwiftUIView.swift b/openHABWatch/Views/PreferencesSwiftUIView.swift index 2629d9e9..9cd020a3 100644 --- a/openHABWatch/Views/PreferencesSwiftUIView.swift +++ b/openHABWatch/Views/PreferencesSwiftUIView.swift @@ -32,11 +32,14 @@ struct PreferencesSwiftUIView: View { LabeledContent(LocalizedStringKey("username"), value: settings.openHABUsername) LabeledContent(LocalizedStringKey("version"), value: applicationVersionNumber) } - - Button { AppMessageService.singleton.requestApplicationContext() - } label: { Label("sync_prefs", systemSymbol: .arrowTriangle2Circlepath) + .toolbar { + ToolbarItem(placement: .primaryAction) { + Button { AppMessageService.singleton.requestApplicationContext() + } label: { Label("sync_prefs", systemSymbol: .arrowTriangle2Circlepath) + } + } } - .buttonStyle(.borderedProminent) + .navigationTitle("Preferences") } } diff --git a/openHABWatch/Views/ContentView.swift b/openHABWatch/Views/SitemapView.swift similarity index 86% rename from openHABWatch/Views/ContentView.swift rename to openHABWatch/Views/SitemapView.swift index 96b4565f..e6899794 100644 --- a/openHABWatch/Views/ContentView.swift +++ b/openHABWatch/Views/SitemapView.swift @@ -13,7 +13,7 @@ import OpenHABCore import os.log import SwiftUI -struct ContentView: View { +struct SitemapView: View { @ObservedObject var viewModel: UserData @EnvironmentObject var settings: ObservableOpenHABDataObject @State var title = "openHAB" @@ -21,17 +21,16 @@ struct ContentView: View { 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) } + + if viewModel.widgets.isEmpty { + Text("No sitemap to show") + .foregroundStyle(.gray) + } } - .navigationBarTitle(Text(title)) + .navigationTitle(Text(title)) .actionSheet(isPresented: $viewModel.showCertificateAlert) { ActionSheet( title: Text(NSLocalizedString("warning", comment: "")), @@ -111,15 +110,18 @@ struct ContentView: View { } #Preview { - Group { - ContentView(viewModel: UserData()) + SitemapView(viewModel: UserData()) - .environmentObject({ () -> UserData in - let envObj = UserData() - return envObj - }()) + .environmentObject({ () -> UserData in + let envObj = UserData() + return envObj + }()) - ContentView(viewModel: UserData()) - } - .environmentObject(ObservableOpenHABDataObject()) + .environmentObject(ObservableOpenHABDataObject()) +} + +#Preview { + SitemapView(viewModel: UserData()) + + .environmentObject(ObservableOpenHABDataObject()) } From fbee614b8b2ee7ffc219c0357f9413855bf5fa9f Mon Sep 17 00:00:00 2001 From: Tim Bert <5411131+timbms@users.noreply.github.com> Date: Sun, 8 Dec 2024 18:24:09 +0100 Subject: [PATCH 7/7] Some preparatory work Signed-off-by: Tim Bert <5411131+timbms@users.noreply.github.com> --- .../Sources/OpenHABCore/Util/Logger.swift | 127 ++++++++++++++++-- openHAB.xcodeproj/project.pbxproj | 52 +++---- openHAB/LogsViewer.swift | 22 --- openHABWatch/Domain/UserData.swift | 2 +- .../Extension/OpenHABWatchAppDelegate.swift | 2 +- ... => WatchConnectivitySessionManager.swift} | 18 ++- .../Views/PreferencesSwiftUIView.swift | 2 +- 7 files changed, 153 insertions(+), 72 deletions(-) rename openHABWatch/External/{AppMessageService.swift => WatchConnectivitySessionManager.swift} (92%) diff --git a/OpenHABCore/Sources/OpenHABCore/Util/Logger.swift b/OpenHABCore/Sources/OpenHABCore/Util/Logger.swift index c178f315..3eea80b5 100644 --- a/OpenHABCore/Sources/OpenHABCore/Util/Logger.swift +++ b/OpenHABCore/Sources/OpenHABCore/Util/Logger.swift @@ -71,8 +71,120 @@ public protocol LogServiceProtocol { func fetchLogs(with template: NSPredicate) async -> String } -public struct LogService { - public init() {} +public class LogService { + static let shared = Logger() + private var fileHandle: FileHandle! + + // Return the folder URL, and create the folder if it doesn't exist yet. + // Return nil to trigger a crash if the folder creation fails. + // + private var _folderURL: URL? + private var folderURL: URL! { + guard _folderURL == nil else { return _folderURL } + + var folderURL = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).last! + folderURL.appendPathComponent("Logs") + + if !FileManager.default.fileExists(atPath: folderURL.path) { + do { + try FileManager.default.createDirectory(at: folderURL, withIntermediateDirectories: true) + } catch { + print("Failed to create the log folder: \(folderURL)! \n\(error)") + return nil // To trigger crash. + } + } + _folderURL = folderURL + return folderURL + } + + // Return the file URL, and create the file if it doesn't exist yet. + // Return nil to trigger a crash if the file creation fails. + // + private var _fileURL: URL? + private var fileURL: URL! { + guard _fileURL == nil else { return _fileURL } + + let dateFormatter = DateFormatter() + dateFormatter.dateStyle = .medium + let dateString = dateFormatter.string(from: Date()) + + var fileURL: URL = folderURL + fileURL.appendPathComponent("\(dateString).log") + + if !FileManager.default.fileExists(atPath: fileURL.path) { + if !FileManager.default.createFile(atPath: fileURL.path, contents: nil, attributes: nil) { + print("Failed to create the log file: \(fileURL)!") + return nil // To trigger crash. + } + } + _fileURL = fileURL + return fileURL + } + + // Use this dispatch queue to make the log file access thread-safe. + // Public methods use performBlockAndWait to access the resource; private methods don't. + // + private lazy var ioQueue: DispatchQueue = .init(label: "ioQueue") + + public init() { + fileHandle = try? FileHandle(forUpdating: fileURL) + assert(fileHandle != nil, "Failed to create the file handle!") + } + + private func performBlockAndWait(_ block: () -> T) -> T { + ioQueue.sync { + block() + } + } + + // Get the current log file URL. + // + func getFileURL() -> URL { + performBlockAndWait { fileURL } + } + + func writeLogs() async { + let template = NSPredicate( + format: "(subsystem BEGINSWITH $PREFIX)" + ) + + let logData = await fetchLogs(with: template) + + if let data = logData.data(using: .utf8) { + performBlockAndWait { + self.fileHandle.write(data) + } + } + } + + // Read the file content and return it as a string. + // + func content() -> String { + performBlockAndWait { + fileHandle.seek(toFileOffset: 0) // Read from the very beginning. + return String(data: fileHandle.availableData, encoding: .utf8) ?? "" + } + } + + // Clear all logs. Reset the folder and file URL for later use. + // + func clearLogs() { + performBlockAndWait { + self.fileHandle.closeFile() + do { + try FileManager.default.removeItem(at: self.folderURL) + } catch { + print("Failed to clear the log folder!\n\(error)") + } + + // Create a new file handle. + // + self._folderURL = nil + self._fileURL = nil + self.fileHandle = try? FileHandle(forUpdating: self.fileURL) + assert(self.fileHandle != nil, "Failed to create the file handle!") + } + } } extension LogService: LogServiceProtocol { @@ -102,14 +214,3 @@ extension LogService: LogServiceProtocol { } } } - -// extension LogService: Transferable { -// -// static var containerUrl = FileManager.default.url(forUbiquityContainerIdentifier: nil)?.appendingPathComponent("Documents", isDirectory: true) -// -// public static var transferRepresentation: some TransferRepresentation { -// FileRepresentation(exportedContentType: .commaSeparatedText) { csvFile in -// SentTransferredFile(csvFile.url) -// } -// } -// } diff --git a/openHAB.xcodeproj/project.pbxproj b/openHAB.xcodeproj/project.pbxproj index 6f1dcbed..abcd9ca5 100644 --- a/openHAB.xcodeproj/project.pbxproj +++ b/openHAB.xcodeproj/project.pbxproj @@ -107,7 +107,7 @@ 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 */; }; + DA72E1B8236DEA0900B8EF3A /* WatchConnectivitySessionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA72E1B5236DEA0900B8EF3A /* WatchConnectivitySessionManager.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 */; }; @@ -407,7 +407,7 @@ 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 = ""; }; - DA72E1B5236DEA0900B8EF3A /* AppMessageService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppMessageService.swift; sourceTree = ""; }; + DA72E1B5236DEA0900B8EF3A /* WatchConnectivitySessionManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WatchConnectivitySessionManager.swift; sourceTree = ""; }; DA7E1E47222EB00B002AEFD8 /* PlayerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerView.swift; 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 = ""; }; @@ -593,7 +593,7 @@ 1224F7C9228A8ED100750965 /* External */ = { isa = PBXGroup; children = ( - DA72E1B5236DEA0900B8EF3A /* AppMessageService.swift */, + DA72E1B5236DEA0900B8EF3A /* WatchConnectivitySessionManager.swift */, ); name = External; path = openHABWatch/External; @@ -1498,7 +1498,7 @@ DA0749E023E0BF510057FA83 /* ColorSelection.swift in Sources */, DA65871F236F83CE007E2E7F /* UserDefaultsExtension.swift in Sources */, DA9721C324E29A8F0092CCFD /* UserDefaultsBacked.swift in Sources */, - DA72E1B8236DEA0900B8EF3A /* AppMessageService.swift in Sources */, + DA72E1B8236DEA0900B8EF3A /* WatchConnectivitySessionManager.swift in Sources */, DA07752B2346705F0086C685 /* OpenHABWatchAppDelegate.swift in Sources */, DAF4581623DC48400018B495 /* GenericRow.swift in Sources */, 9350F17A23814FAC00054BA8 /* ObservableOpenHABSitemapPage.swift in Sources */, @@ -1708,13 +1708,11 @@ CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_ENTITLEMENTS = openHABIntents/openHABIntents.entitlements; - CODE_SIGN_IDENTITY = "Apple Distribution"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Distribution"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 29; DEBUG_INFORMATION_FORMAT = dwarf; - DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = PBAPXHRAM9; + DEVELOPMENT_TEAM = PBAPXHRAM9; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; @@ -1731,8 +1729,7 @@ MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = org.openhab.app.openHABIntents; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = "match AppStore org.openhab.app.openHABIntents"; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore org.openhab.app.openHABIntents"; + PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -1795,13 +1792,11 @@ CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; - CODE_SIGN_IDENTITY = "Apple Distribution"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Distribution"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 29; DEBUG_INFORMATION_FORMAT = dwarf; - DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = PBAPXHRAM9; + DEVELOPMENT_TEAM = PBAPXHRAM9; ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu17; GCC_NO_COMMON_BLOCKS = YES; @@ -1823,8 +1818,7 @@ MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = org.openhab.app.NotificationService; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = "match AppStore org.openhab.app.NotificationService"; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore org.openhab.app.NotificationService"; + PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; SWIFT_EMIT_LOC_STRINGS = YES; @@ -1979,13 +1973,11 @@ CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_ENTITLEMENTS = "openHABWatch Extension/openHABWatch Extension.entitlements"; - CODE_SIGN_IDENTITY = "Apple Distribution"; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = "Apple Distribution"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 29; DEBUG_INFORMATION_FORMAT = dwarf; - DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=watchos*]" = PBAPXHRAM9; + DEVELOPMENT_TEAM = PBAPXHRAM9; GCC_C_LANGUAGE_STANDARD = "compiler-default"; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; @@ -2007,8 +1999,7 @@ MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = org.openhab.app.watchkitapp; 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_ACTIVE_COMPILATION_CONDITIONS = DEBUG; @@ -2435,12 +2426,10 @@ CLANG_CXX_LANGUAGE_STANDARD = "$(inherited)"; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = openHAB/openHAB.entitlements; - CODE_SIGN_IDENTITY = "Apple Distribution"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Distribution"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 29; - DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = PBAPXHRAM9; + DEVELOPMENT_TEAM = PBAPXHRAM9; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "openHAB/openHAB-Prefix.pch"; INFOPLIST_FILE = "openHAB/openHAB-Info.plist"; @@ -2462,8 +2451,7 @@ PRODUCT_BUNDLE_IDENTIFIER = org.openhab.app; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = ""; - PROVISIONING_PROFILE_SPECIFIER = "match AppStore org.openhab.app"; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore org.openhab.app"; + PROVISIONING_PROFILE_SPECIFIER = ""; SUPPORTS_MACCATALYST = NO; SWIFT_INSTALL_OBJC_HEADER = NO; SWIFT_OBJC_BRIDGING_HEADER = ""; diff --git a/openHAB/LogsViewer.swift b/openHAB/LogsViewer.swift index 04ba49c1..f2bf252b 100644 --- a/openHAB/LogsViewer.swift +++ b/openHAB/LogsViewer.swift @@ -9,28 +9,6 @@ // // SPDX-License-Identifier: EPL-2.0 -// import SwiftUI -// -// struct LogView: View { -// let logs: [OSLogEntryLog] -// -// var body: some View { -// List(logs, id: \.self) { log in -// VStack(alignment: .leading) { -// Text(log.composedMessage) -// HStack { -// Text(log.subsystem) -// Text(log.date, format: .dateTime) -// }.bold() -// } -// } -// } -// } -// -// #Preview { -// LogView(logs: .init([])) -// } - import Foundation import OpenHABCore import OSLog diff --git a/openHABWatch/Domain/UserData.swift b/openHABWatch/Domain/UserData.swift index e4009828..ddd913c9 100644 --- a/openHABWatch/Domain/UserData.swift +++ b/openHABWatch/Domain/UserData.swift @@ -76,7 +76,7 @@ final class UserData: ObservableObject { self?.logger.error("openHABTracked: \(activeConnection.configuration.url)") if !ObservableOpenHABDataObject.shared.haveReceivedAppContext { - AppMessageService.singleton.requestApplicationContext() + WatchConnectivitySessionManager.singleton.requestApplicationContext() self?.errorDescription = NSLocalizedString("settings_not_received", comment: "") self?.showAlert = true return diff --git a/openHABWatch/Extension/OpenHABWatchAppDelegate.swift b/openHABWatch/Extension/OpenHABWatchAppDelegate.swift index 584d2f42..5cdb8be1 100644 --- a/openHABWatch/Extension/OpenHABWatchAppDelegate.swift +++ b/openHABWatch/Extension/OpenHABWatchAppDelegate.swift @@ -20,7 +20,7 @@ class OpenHABWatchAppDelegate: NSObject { let delegate: WCSessionDelegate override init() { - delegate = AppMessageService.singleton + delegate = WatchConnectivitySessionManager.singleton session = .default session.delegate = delegate session.activate() diff --git a/openHABWatch/External/AppMessageService.swift b/openHABWatch/External/WatchConnectivitySessionManager.swift similarity index 92% rename from openHABWatch/External/AppMessageService.swift rename to openHABWatch/External/WatchConnectivitySessionManager.swift index c29c1e78..9f1da0c2 100644 --- a/openHABWatch/External/AppMessageService.swift +++ b/openHABWatch/External/WatchConnectivitySessionManager.swift @@ -16,8 +16,8 @@ import WatchConnectivity import WatchKit // This class handles values that are passed from the ios app. -class AppMessageService: NSObject, WCSessionDelegate { - static let singleton = AppMessageService() +class WatchConnectivitySessionManager: NSObject, WCSessionDelegate { + static let singleton = WatchConnectivitySessionManager() private let logger = Logger(subsystem: "org.openhab.app.watchkitapp", category: "AppMessageService") @@ -130,3 +130,17 @@ class AppMessageService: NSObject, WCSessionDelegate { } } } + + +extension WatchConnectivitySessionManager { + + func transferFile(file: URL, metadata: [String : AnyObject]) -> WCSessionFileTransfer? { + return WCSession.default.transferFile(file, metadata: metadata) + } + + func session(_ session: WCSession, didFinish fileTransfer: WCSessionFileTransfer, error: Error?) { + // handle filed transfer completion + } + +} + diff --git a/openHABWatch/Views/PreferencesSwiftUIView.swift b/openHABWatch/Views/PreferencesSwiftUIView.swift index 9cd020a3..af312a82 100644 --- a/openHABWatch/Views/PreferencesSwiftUIView.swift +++ b/openHABWatch/Views/PreferencesSwiftUIView.swift @@ -34,7 +34,7 @@ struct PreferencesSwiftUIView: View { } .toolbar { ToolbarItem(placement: .primaryAction) { - Button { AppMessageService.singleton.requestApplicationContext() + Button { WatchConnectivitySessionManager.singleton.requestApplicationContext() } label: { Label("sync_prefs", systemSymbol: .arrowTriangle2Circlepath) } }