From b548a69414fcfcae1f8440860e8123456c59a869 Mon Sep 17 00:00:00 2001 From: Antoine van der Lee <4329185+AvdLee@users.noreply.github.com> Date: Wed, 26 Jun 2024 11:30:28 +0200 Subject: [PATCH 01/11] Change methods to public to allow service initialization --- Sources/Pulse/LoggerStore/LoggerStore.swift | 2 +- .../RemoteLogger-Connection.swift | 27 ++++++++++--------- .../RemoteLogger/RemoteLogger-Protocol.swift | 14 ++++++---- Sources/Pulse/RemoteLogger/RemoteLogger.swift | 10 +++---- 4 files changed, 29 insertions(+), 24 deletions(-) diff --git a/Sources/Pulse/LoggerStore/LoggerStore.swift b/Sources/Pulse/LoggerStore/LoggerStore.swift index 14fcc76a9..7b7205b9a 100644 --- a/Sources/Pulse/LoggerStore/LoggerStore.swift +++ b/Sources/Pulse/LoggerStore/LoggerStore.swift @@ -347,7 +347,7 @@ extension LoggerStore { } /// Handles event created by the current store and dispatches it to observers. - func handle(_ event: Event) { + public func handle(_ event: Event) { guard let event = configuration.willHandleEvent(event) else { return } diff --git a/Sources/Pulse/RemoteLogger/RemoteLogger-Connection.swift b/Sources/Pulse/RemoteLogger/RemoteLogger-Connection.swift index 6118a1d25..5147eb4dc 100644 --- a/Sources/Pulse/RemoteLogger/RemoteLogger-Connection.swift +++ b/Sources/Pulse/RemoteLogger/RemoteLogger-Connection.swift @@ -11,13 +11,13 @@ import OSLog import Pulse #endif -protocol RemoteLoggerConnectionDelegate: AnyObject { +public protocol RemoteLoggerConnectionDelegate: AnyObject { func connection(_ connection: RemoteLogger.Connection, didChangeState newState: NWConnection.State) func connection(_ connection: RemoteLogger.Connection, didReceiveEvent event: RemoteLogger.Connection.Event) } -extension RemoteLogger { - final class Connection { +public extension RemoteLogger { + public final class Connection { var endpoint: NWEndpoint { connection.endpoint } private let connection: NWConnection private var buffer = Data() @@ -31,14 +31,15 @@ extension RemoteLogger { self.init(NWConnection(to: endpoint, using: parameters)) } - init(_ connection: NWConnection) { + public init(_ connection: NWConnection, delegate: RemoteLoggerConnectionDelegate? = nil) { self.connection = connection + self.delegate = delegate let isLogEnabled = UserDefaults.standard.bool(forKey: "com.github.kean.pulse.debug") self.log = isLogEnabled ? OSLog(subsystem: "com.github.kean.pulse", category: "RemoteLogger") : .disabled } - - func start(on queue: DispatchQueue) { + + public func start(on queue: DispatchQueue) { connection.stateUpdateHandler = { [weak self] state in guard let self = self else { return } DispatchQueue.main.async { @@ -49,15 +50,15 @@ extension RemoteLogger { connection.start(queue: queue) } - enum Event { + public enum Event { case packet(Packet) case error(Error) case completed } - struct Packet { - let code: UInt8 - let body: Data + public struct Packet { + public let code: UInt8 + public let body: Data } private func receive() { @@ -130,7 +131,7 @@ extension RemoteLogger { } } - func send(code: UInt8, data: Data) { + public func send(code: UInt8, data: Data) { do { let data = try encode(code: code, body: data) let log = self.log @@ -144,7 +145,7 @@ extension RemoteLogger { } } - func send(code: UInt8, entity: T) { + public func send(code: UInt8, entity: T) { do { let data = try JSONEncoder().encode(entity) send(code: code, data: data) @@ -206,7 +207,7 @@ extension RemoteLogger { } } - func cancel() { + public func cancel() { connection.cancel() } } diff --git a/Sources/Pulse/RemoteLogger/RemoteLogger-Protocol.swift b/Sources/Pulse/RemoteLogger/RemoteLogger-Protocol.swift index 65ed641f0..df031d3da 100644 --- a/Sources/Pulse/RemoteLogger/RemoteLogger-Protocol.swift +++ b/Sources/Pulse/RemoteLogger/RemoteLogger-Protocol.swift @@ -8,8 +8,8 @@ import Network import Pulse #endif -extension RemoteLogger { - enum PacketCode: UInt8, Equatable { +public extension RemoteLogger { + public enum PacketCode: UInt8, Equatable { // Handshake case clientHello = 0 // PacketClientHello case serverHello = 1 // ServerHelloResponse @@ -44,7 +44,7 @@ extension RemoteLogger { init() {} } - struct PacketNetworkMessage { + public struct PacketNetworkMessage { private struct Manifest: Codable { let messageSize: UInt32 let requestBodySize: UInt32 @@ -83,7 +83,7 @@ extension RemoteLogger { return data } - static func decode(_ data: Data) throws -> LoggerStore.Event.NetworkTaskCompleted { + public static func decode(_ data: Data) throws -> LoggerStore.Event.NetworkTaskCompleted { guard data.count >= Manifest.size else { throw PacketParsingError.notEnoughData // Should never happen } @@ -195,8 +195,12 @@ extension RemoteLogger { case openTaskDetails } - struct ServerHelloResponse: Codable { + public struct ServerHelloResponse: Codable { let version: String + + public init(version: String) { + self.version = version + } } } diff --git a/Sources/Pulse/RemoteLogger/RemoteLogger.swift b/Sources/Pulse/RemoteLogger/RemoteLogger.swift index 22417a07c..de1f04337 100644 --- a/Sources/Pulse/RemoteLogger/RemoteLogger.swift +++ b/Sources/Pulse/RemoteLogger/RemoteLogger.swift @@ -322,7 +322,7 @@ public final class RemoteLogger: ObservableObject, RemoteLoggerConnectionDelegat openConnection(to: server, passcode: passcode) } - + private func connectionDidTimeout(isProtected: Bool) { os_log("Connection did timeout", log: log) connectionCompletion?(.failure(self.connectionError ?? .unknown(isProtected: isProtected))) @@ -341,7 +341,7 @@ public final class RemoteLogger: ObservableObject, RemoteLoggerConnectionDelegat } private func saveServer(named name: String) { - os_log("Save server %{private}@", log: log, name) + os_log("Save server %{private}@", log: log, name) knownServers.removeAll(where: { $0 == name }) knownServers.append(name) saveKnownServers() @@ -371,7 +371,7 @@ public final class RemoteLogger: ObservableObject, RemoteLoggerConnectionDelegat // MARK: RemoteLoggerConnectionDelegate - func connection(_ connection: Connection, didChangeState newState: NWConnection.State) { + public func connection(_ connection: Connection, didChangeState newState: NWConnection.State) { os_log("Connection did change state to %{public}@", log: log, "\(newState)") switch newState { @@ -390,7 +390,7 @@ public final class RemoteLogger: ObservableObject, RemoteLoggerConnectionDelegat } } - func connection(_ connection: Connection, didReceiveEvent event: Connection.Event) { + public func connection(_ connection: Connection, didReceiveEvent event: Connection.Event) { switch event { case .packet(let packet): do { @@ -730,5 +730,5 @@ extension RemoteLogger.ConnectionState { } extension RemoteLogger { - public static let serviceType = "_pulse._tcp" + public static var serviceType = "_pulse._tcp" } From 22eaa12009714fb1c6402f95356267cdffc75e96 Mon Sep 17 00:00:00 2001 From: Antoine van der Lee <4329185+AvdLee@users.noreply.github.com> Date: Fri, 28 Jun 2024 10:53:52 +0200 Subject: [PATCH 02/11] Fix dark mode background --- Sources/PulseUI/Features/Console/List/ConsoleListView.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Sources/PulseUI/Features/Console/List/ConsoleListView.swift b/Sources/PulseUI/Features/Console/List/ConsoleListView.swift index 4fa8b20b6..197e135a0 100644 --- a/Sources/PulseUI/Features/Console/List/ConsoleListView.swift +++ b/Sources/PulseUI/Features/Console/List/ConsoleListView.swift @@ -174,7 +174,8 @@ private struct _ConsoleListView: View { } else { ConsoleListContentView(proxy: proxy) } - } + }.scrollContentBackground(.hidden) + .background(Color.black.opacity(0.32)) } .environment(\.defaultMinListRowHeight, 1) } From 5e15e40b2c9cd9f4071ac93ccc837a2a5a94ed45 Mon Sep 17 00:00:00 2001 From: Antoine van der Lee <4329185+AvdLee@users.noreply.github.com> Date: Mon, 1 Jul 2024 08:51:37 +0200 Subject: [PATCH 03/11] Reset background --- Sources/PulseUI/Features/Console/List/ConsoleListView.swift | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Sources/PulseUI/Features/Console/List/ConsoleListView.swift b/Sources/PulseUI/Features/Console/List/ConsoleListView.swift index 197e135a0..4fa8b20b6 100644 --- a/Sources/PulseUI/Features/Console/List/ConsoleListView.swift +++ b/Sources/PulseUI/Features/Console/List/ConsoleListView.swift @@ -174,8 +174,7 @@ private struct _ConsoleListView: View { } else { ConsoleListContentView(proxy: proxy) } - }.scrollContentBackground(.hidden) - .background(Color.black.opacity(0.32)) + } } .environment(\.defaultMinListRowHeight, 1) } From 2626dcd594fc5638d83a7e40601fd520721e27a9 Mon Sep 17 00:00:00 2001 From: Antoine van der Lee <4329185+AvdLee@users.noreply.github.com> Date: Mon, 1 Jul 2024 08:59:02 +0200 Subject: [PATCH 04/11] Hide list background to allow window background to shine through --- Sources/PulseUI/Features/Console/List/ConsoleListView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/PulseUI/Features/Console/List/ConsoleListView.swift b/Sources/PulseUI/Features/Console/List/ConsoleListView.swift index 4fa8b20b6..f1571a5bd 100644 --- a/Sources/PulseUI/Features/Console/List/ConsoleListView.swift +++ b/Sources/PulseUI/Features/Console/List/ConsoleListView.swift @@ -174,7 +174,7 @@ private struct _ConsoleListView: View { } else { ConsoleListContentView(proxy: proxy) } - } + }.scrollContentBackground(.hidden) } .environment(\.defaultMinListRowHeight, 1) } From 9cc6bf827658c58a41bc18fefbb933247cb8f1b1 Mon Sep 17 00:00:00 2001 From: Antoine van der Lee <4329185+AvdLee@users.noreply.github.com> Date: Mon, 1 Jul 2024 09:01:37 +0200 Subject: [PATCH 05/11] Update documentation regarding mode --- Sources/PulseUI/Features/Console/ConsoleView.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Sources/PulseUI/Features/Console/ConsoleView.swift b/Sources/PulseUI/Features/Console/ConsoleView.swift index 7dbb0de7e..f08866616 100644 --- a/Sources/PulseUI/Features/Console/ConsoleView.swift +++ b/Sources/PulseUI/Features/Console/ConsoleView.swift @@ -12,9 +12,9 @@ extension ConsoleView { /// /// - parameters: /// - store: The store to display. By default, `LoggerStore/shared`. - /// - mode: The console mode. By default, ``ConsoleMode/all``. If you change - /// the mode to ``ConsoleMode/network``, the console will only display the - /// network messages. + /// - mode: The initial console mode. By default, ``ConsoleMode/all``. If you change + /// the mode to ``ConsoleMode/network``, the console will display the + /// network messages up on appearance. /// - delegate: The delegate that allows you to customize multiple aspects /// of the console view. public init( From 45524056b57afc442ff4db6cd47dee144acaed49 Mon Sep 17 00:00:00 2001 From: Antoine van der Lee <4329185+AvdLee@users.noreply.github.com> Date: Mon, 1 Jul 2024 09:10:20 +0200 Subject: [PATCH 06/11] Add helpers for toolbar buttons --- Sources/PulseUI/Features/Console/ConsoleView-macos.swift | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Sources/PulseUI/Features/Console/ConsoleView-macos.swift b/Sources/PulseUI/Features/Console/ConsoleView-macos.swift index 082f0c13f..174c1b4ac 100644 --- a/Sources/PulseUI/Features/Console/ConsoleView-macos.swift +++ b/Sources/PulseUI/Features/Console/ConsoleView-macos.swift @@ -60,18 +60,21 @@ private struct ConsoleMainView: View { Button(action: { isShowingFilters = true }) { Label("Show Filters", systemImage: "line.3.horizontal.decrease.circle") } + .help("Show Filters") .popover(isPresented: $isShowingFilters) { ConsoleFiltersView().frame(width: 300).fixedSize() } Button(action: { isShowingSessions = true }) { Label("Show Sessions", systemImage: "list.clipboard") } + .help("Show Sessions") .popover(isPresented: $isShowingSessions) { SessionsView().frame(width: 300, height: 420) } Button(action: { isShowingSettings = true }) { Label("Show Settings", systemImage: "gearshape") } + .help("Show Settings") .popover(isPresented: $isShowingSettings) { SettingsView().frame(width: 300, height: 420) } @@ -88,10 +91,11 @@ private struct ConsoleMainView: View { if !(environment.store.options.contains(.readonly)) { Toggle(isOn: $isNowEnabled) { Image(systemName: "clock") - } + }.help("Now Mode: Automatically scrolls to the top of the view to display newly incoming network requests.") Button(action: { isSharingStore = true }) { Image(systemName: "square.and.arrow.up") } + .help("Share a session") .popover(isPresented: $isSharingStore, arrowEdge: .bottom) { ShareStoreView(onDismiss: {}) .frame(width: 240).fixedSize() @@ -99,6 +103,7 @@ private struct ConsoleMainView: View { Button(action: { environment.store.removeAll() }) { Image(systemName: "trash") } + .help("Clear current session") } } } From d59122c6d407aede4957631ad4ca6de8e7eabc8b Mon Sep 17 00:00:00 2001 From: Antoine van der Lee <4329185+AvdLee@users.noreply.github.com> Date: Mon, 1 Jul 2024 09:35:52 +0200 Subject: [PATCH 07/11] Update console minWidth for macOS --- Sources/PulseUI/Features/Console/ConsoleView-macos.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/PulseUI/Features/Console/ConsoleView-macos.swift b/Sources/PulseUI/Features/Console/ConsoleView-macos.swift index 174c1b4ac..44613315f 100644 --- a/Sources/PulseUI/Features/Console/ConsoleView-macos.swift +++ b/Sources/PulseUI/Features/Console/ConsoleView-macos.swift @@ -51,7 +51,7 @@ private struct ConsoleMainView: View { private var contentView: some View { ConsoleListView() - .frame(minWidth: 200, idealWidth: 400, minHeight: 120, idealHeight: 480) + .frame(minWidth: 400, idealWidth: 500, minHeight: 120, idealHeight: 480) .toolbar { ToolbarItemGroup(placement: .navigation) { contentToolbarNavigationItems From d74f5fc1b33e14223d1bb58693b31f65020c2370 Mon Sep 17 00:00:00 2001 From: Antoine van der Lee <4329185+AvdLee@users.noreply.github.com> Date: Mon, 1 Jul 2024 09:44:42 +0200 Subject: [PATCH 08/11] Remove redundant public modifiers since extension is public --- Sources/Pulse/RemoteLogger/RemoteLogger-Connection.swift | 2 +- Sources/Pulse/RemoteLogger/RemoteLogger-Protocol.swift | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Sources/Pulse/RemoteLogger/RemoteLogger-Connection.swift b/Sources/Pulse/RemoteLogger/RemoteLogger-Connection.swift index 5147eb4dc..4ac99ca03 100644 --- a/Sources/Pulse/RemoteLogger/RemoteLogger-Connection.swift +++ b/Sources/Pulse/RemoteLogger/RemoteLogger-Connection.swift @@ -17,7 +17,7 @@ public protocol RemoteLoggerConnectionDelegate: AnyObject { } public extension RemoteLogger { - public final class Connection { + final class Connection { var endpoint: NWEndpoint { connection.endpoint } private let connection: NWConnection private var buffer = Data() diff --git a/Sources/Pulse/RemoteLogger/RemoteLogger-Protocol.swift b/Sources/Pulse/RemoteLogger/RemoteLogger-Protocol.swift index df031d3da..036a80cf0 100644 --- a/Sources/Pulse/RemoteLogger/RemoteLogger-Protocol.swift +++ b/Sources/Pulse/RemoteLogger/RemoteLogger-Protocol.swift @@ -9,7 +9,7 @@ import Pulse #endif public extension RemoteLogger { - public enum PacketCode: UInt8, Equatable { + enum PacketCode: UInt8, Equatable { // Handshake case clientHello = 0 // PacketClientHello case serverHello = 1 // ServerHelloResponse @@ -44,7 +44,7 @@ public extension RemoteLogger { init() {} } - public struct PacketNetworkMessage { + struct PacketNetworkMessage { private struct Manifest: Codable { let messageSize: UInt32 let requestBodySize: UInt32 @@ -195,7 +195,7 @@ public extension RemoteLogger { case openTaskDetails } - public struct ServerHelloResponse: Codable { + struct ServerHelloResponse: Codable { let version: String public init(version: String) { From 1d661f53378aaa083e9934c55ae893b3ecfa9712 Mon Sep 17 00:00:00 2001 From: Antoine van der Lee <4329185+AvdLee@users.noreply.github.com> Date: Mon, 1 Jul 2024 09:48:46 +0200 Subject: [PATCH 09/11] Remove window style for macOS demo --- Demo/macOS/Pulse_Demo_macOSApp.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/Demo/macOS/Pulse_Demo_macOSApp.swift b/Demo/macOS/Pulse_Demo_macOSApp.swift index 4e5aa62ad..8de578c90 100644 --- a/Demo/macOS/Pulse_Demo_macOSApp.swift +++ b/Demo/macOS/Pulse_Demo_macOSApp.swift @@ -11,7 +11,6 @@ struct Pulse_Demo_macOSApp: App { WindowGroup { ConsoleView(store: .demo) } - .windowStyle(.hiddenTitleBar) .windowToolbarStyle(.unified(showsTitle: false)) } } From 904aa79e302281e3b24c486fa25b78579db5f605 Mon Sep 17 00:00:00 2001 From: Antoine van der Lee <4329185+AvdLee@users.noreply.github.com> Date: Mon, 1 Jul 2024 10:14:04 +0200 Subject: [PATCH 10/11] Improve styling of macOS session view --- .../Features/Sessions/SessionListView.swift | 40 ++++++++++++------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/Sources/PulseUI/Features/Sessions/SessionListView.swift b/Sources/PulseUI/Features/Sessions/SessionListView.swift index af1b29da0..8f465cc11 100644 --- a/Sources/PulseUI/Features/Sessions/SessionListView.swift +++ b/Sources/PulseUI/Features/Sessions/SessionListView.swift @@ -27,34 +27,40 @@ struct SessionListView: View { @Environment(\.store) private var store var body: some View { - if sessions.isEmpty { - Text("No Recorded Sessions") - .frame(maxWidth: .infinity, maxHeight: .infinity) - .foregroundColor(.secondary) - } else { - content - .onAppear { refreshGroups() } - .onChange(of: sessions.count) { _ in refreshGroups() } + VStack(spacing: 0) { + Text("Recorded sessions") + .padding(.vertical, 10) + Divider() + if sessions.isEmpty { + Text("No Recorded Sessions") + .frame(maxWidth: .infinity, maxHeight: .infinity) + .foregroundColor(.secondary) + } else { + content + .onAppear { refreshGroups() } + .onChange(of: sessions.count) { _ in refreshGroups() } + } } } @ViewBuilder private var content: some View { #if os(macOS) - VStack { + VStack(spacing: 0) { list - HStack { + #if PULSE_STANDALONE_APP + HStack { NavigatorFilterBar(text: $filterTerm) .frame(maxWidth: 200) .help("Show sessions with matching name") + } #else - SearchBar(title: "Filter", imageName: "line.3.horizontal.decrease.circle", text: $filterTerm) - .frame(maxWidth: 200) - .help("Show sessions with matching name") + Divider() + SearchBar(title: "Filter", imageName: "line.3.horizontal.decrease.circle", text: $filterTerm) + .help("Show sessions with matching name") + .padding(8) #endif - Spacer() - }.padding(8) } #else list @@ -92,10 +98,14 @@ struct SessionListView: View { private func makeHeader(for startDate: Date, sessions: [LoggerSessionEntity]) -> some View { HStack { + #if os(macOS) + PlainListSectionHeaderSeparator(title: sectionTitleFormatter.string(from: startDate) + " (\(sessions.count))") + #else (Text(sectionTitleFormatter.string(from: startDate)) + Text(" (\(sessions.count))").foregroundColor(.secondary.opacity(0.5))) .font(.headline) .padding(.vertical, 6) + #endif #if os(iOS) || os(visionOS) if editMode?.wrappedValue.isEditing ?? false { From b636cf5fecf1d361c9a9b5411fc4d2b029ca3f18 Mon Sep 17 00:00:00 2001 From: Antoine van der Lee <4329185+AvdLee@users.noreply.github.com> Date: Mon, 1 Jul 2024 10:18:05 +0200 Subject: [PATCH 11/11] Hide section title on iOS since we have the navigation bar title --- Sources/PulseUI/Features/Sessions/SessionListView.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Sources/PulseUI/Features/Sessions/SessionListView.swift b/Sources/PulseUI/Features/Sessions/SessionListView.swift index 8f465cc11..90e77f761 100644 --- a/Sources/PulseUI/Features/Sessions/SessionListView.swift +++ b/Sources/PulseUI/Features/Sessions/SessionListView.swift @@ -28,9 +28,11 @@ struct SessionListView: View { var body: some View { VStack(spacing: 0) { + #if os(macOS) Text("Recorded sessions") .padding(.vertical, 10) Divider() + #endif if sessions.isEmpty { Text("No Recorded Sessions") .frame(maxWidth: .infinity, maxHeight: .infinity)