Skip to content

Improve macOS Settings View #277

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Jul 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Demo/macOS/Pulse_Demo_macOSApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ struct Pulse_Demo_macOSApp: App {
WindowGroup {
ConsoleView(store: .demo)
}
.windowStyle(.hiddenTitleBar)
.windowToolbarStyle(.unified(showsTitle: false))
}
}
4 changes: 4 additions & 0 deletions Pulse.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@
0CFF79E229EC1FA200BE767B /* ImageProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CFF79E029EC1F7800BE767B /* ImageProcessor.swift */; };
25E740012BE0FA58008C6DC3 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 25E740002BE0FA58008C6DC3 /* PrivacyInfo.xcprivacy */; };
25E740072BE10B4C008C6DC3 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 25E740062BE10B4C008C6DC3 /* PrivacyInfo.xcprivacy */; };
849DD7D92C32A9CE002D6787 /* ConsoleConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849DD7D82C32A9CE002D6787 /* ConsoleConfiguration.swift */; };
E95D6C562B7314E6004D28E4 /* HARDocument.swift in Sources */ = {isa = PBXBuildFile; fileRef = E95D6C552B7314E6004D28E4 /* HARDocument.swift */; };
/* End PBXBuildFile section */

Expand Down Expand Up @@ -737,6 +738,7 @@
25E740062BE10B4C008C6DC3 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
49E82A8526D107A00070244F /* AlamofireIntegration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlamofireIntegration.swift; sourceTree = "<group>"; };
49E82A8826D1083D0070244F /* MoyaIntegration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoyaIntegration.swift; sourceTree = "<group>"; };
849DD7D82C32A9CE002D6787 /* ConsoleConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConsoleConfiguration.swift; sourceTree = "<group>"; };
E95D6C552B7314E6004D28E4 /* HARDocument.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HARDocument.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

Expand Down Expand Up @@ -1398,6 +1400,7 @@
0CA2632D2BFA3855003C8E97 /* ConsoleDelegate.swift */,
0CF0D60A296F189600EED9D4 /* ConsoleEnvironment.swift */,
0CECF63C2996BE12000F9CCD /* ConsoleDataSource.swift */,
849DD7D82C32A9CE002D6787 /* ConsoleConfiguration.swift */,
);
path = Console;
sourceTree = "<group>";
Expand Down Expand Up @@ -2136,6 +2139,7 @@
0CDC3BED2971B936003BD1FF /* ConsoleSearchLogLevelsCell.swift in Sources */,
0CF0D620296F189600EED9D4 /* Foundation+Extensions.swift in Sources */,
0CF0D66C296F189600EED9D4 /* NetworkRequestInfoCell.swift in Sources */,
849DD7D92C32A9CE002D6787 /* ConsoleConfiguration.swift in Sources */,
0CB63A15297438A600525165 /* ConsoleSearchViewModel.swift in Sources */,
0CF0D632296F189600EED9D4 /* ShareStoreView.swift in Sources */,
0C9751582A32CCC400DC46FF /* RemoteLoggerEnterPasswordView.swift in Sources */,
Expand Down
2 changes: 1 addition & 1 deletion Sources/Pulse/LoggerStore/LoggerStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
25 changes: 13 additions & 12 deletions Sources/Pulse/RemoteLogger/RemoteLogger-Connection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ 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 {
public extension RemoteLogger {
final class Connection {
var endpoint: NWEndpoint { connection.endpoint }
private let connection: NWConnection
Expand All @@ -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 {
Expand All @@ -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() {
Expand Down Expand Up @@ -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
Expand All @@ -144,7 +145,7 @@ extension RemoteLogger {
}
}

func send<T: Encodable>(code: UInt8, entity: T) {
public func send<T: Encodable>(code: UInt8, entity: T) {
do {
let data = try JSONEncoder().encode(entity)
send(code: code, data: data)
Expand Down Expand Up @@ -206,7 +207,7 @@ extension RemoteLogger {
}
}

func cancel() {
public func cancel() {
connection.cancel()
}
}
Expand Down
8 changes: 6 additions & 2 deletions Sources/Pulse/RemoteLogger/RemoteLogger-Protocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Network
import Pulse
#endif

extension RemoteLogger {
public extension RemoteLogger {
enum PacketCode: UInt8, Equatable {
// Handshake
case clientHello = 0 // PacketClientHello
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -197,6 +197,10 @@ extension RemoteLogger {

struct ServerHelloResponse: Codable {
let version: String

public init(version: String) {
self.version = version
}
}
}

Expand Down
10 changes: 5 additions & 5 deletions Sources/Pulse/RemoteLogger/RemoteLogger.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)))
Expand All @@ -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()
Expand Down Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down Expand Up @@ -730,5 +730,5 @@ extension RemoteLogger.ConnectionState {
}

extension RemoteLogger {
public static let serviceType = "_pulse._tcp"
public static var serviceType = "_pulse._tcp"
}
26 changes: 26 additions & 0 deletions Sources/PulseUI/Features/Console/ConsoleConfiguration.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// The MIT License (MIT)
//
// Created by A.J. van der Lee on 01/07/2024.
// Copyright © 2024 kean. All rights reserved.
//

import Foundation

/// Defines UI configurations to enable/disable elements or change behavior.
public struct ConsoleConfiguration {
public static let `default` = ConsoleConfiguration()

let shareStoreOutputs: [ShareStoreOutput]
let allowRemoteLogging: Bool

/// Creates a new `ConsoleConfiguration`
/// - Parameter shareStoreOutputs: The available store share outputs. Defaults to `allCases`.
/// - Parameter allowRemoteLogging: Enable/disable the remote logging option.
public init(
shareStoreOutputs: [ShareStoreOutput] = ShareStoreOutput.allCases,
allowRemoteLogging: Bool = true
) {
self.shareStoreOutputs = shareStoreOutputs
self.allowRemoteLogging = allowRemoteLogging
}
}
4 changes: 3 additions & 1 deletion Sources/PulseUI/Features/Console/ConsoleEnvironment.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ final class ConsoleEnvironment: ObservableObject {

let initialMode: ConsoleMode
let delegate: ConsoleViewDelegate
let configuration: ConsoleConfiguration

@Published var mode: ConsoleMode
@Published var listOptions: ConsoleListOptions = .init()
Expand All @@ -38,7 +39,7 @@ final class ConsoleEnvironment: ObservableObject {

private var cancellables: [AnyCancellable] = []

init(store: LoggerStore, mode: ConsoleMode = .all, delegate: ConsoleViewDelegate = DefaultConsoleViewDelegate()) {
init(store: LoggerStore, mode: ConsoleMode = .all, configuration: ConsoleConfiguration = .default, delegate: ConsoleViewDelegate = DefaultConsoleViewDelegate()) {
self.store = store
switch mode {
case .all: self.title = "Console"
Expand All @@ -54,6 +55,7 @@ final class ConsoleEnvironment: ObservableObject {
}

self.delegate = delegate
self.configuration = configuration

func makeDefaultOptions() -> ConsoleDataSource.PredicateOptions {
var options = ConsoleDataSource.PredicateOptions()
Expand Down
13 changes: 9 additions & 4 deletions Sources/PulseUI/Features/Console/ConsoleView-macos.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -60,20 +60,23 @@ 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")
}
.popover(isPresented: $isShowingSettings) {
SettingsView().frame(width: 300, height: 420)
.help("Show Settings")
.popover(isPresented: $isShowingSettings, arrowEdge: .bottom) {
SettingsView().frame(width: 300, height: environment.configuration.allowRemoteLogging ? 420 : 175)
}
}
}
Expand All @@ -88,17 +91,19 @@ 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()
}
Button(action: { environment.store.removeAll() }) {
Image(systemName: "trash")
}
.help("Clear current session")
}
}
}
Expand Down
12 changes: 7 additions & 5 deletions Sources/PulseUI/Features/Console/ConsoleView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,21 @@ import Combine

extension ConsoleView {
/// Initializes the console view.
///
///
/// - 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.
/// - configuration: Configuration options to alter the UI behavior and settings.
/// - delegate: The delegate that allows you to customize multiple aspects
/// of the console view.
public init(
store: LoggerStore = .shared,
mode: ConsoleMode = .all,
configuration: ConsoleConfiguration = .default,
delegate: ConsoleViewDelegate? = nil
) {
self.init(environment: .init(store: store, mode: mode, delegate: delegate ?? DefaultConsoleViewDelegate()))
self.init(environment: .init(store: store, mode: mode, configuration: configuration, delegate: delegate ?? DefaultConsoleViewDelegate()))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ private struct _ConsoleListView: View {
} else {
ConsoleListContentView(proxy: proxy)
}
}
}.scrollContentBackground(.hidden)
}
.environment(\.defaultMinListRowHeight, 1)
}
Expand Down
Loading
Loading