From c846fc5a15254abdb368288a8c370e8890572068 Mon Sep 17 00:00:00 2001 From: igor Date: Fri, 7 Mar 2025 16:54:08 -0800 Subject: [PATCH] Cleanup. --- src/AboutViewController.swift | 96 +++++++++------------------------- src/AppDelegate.swift | 9 +--- src/CBMenuBarItem.swift | 7 +-- src/CmdManager.swift | 48 +++++------------ src/CmdViewController.swift | 33 +++--------- src/Helpers.swift | 38 ++++++-------- src/Makefile | 67 ++++++++++-------------- src/MenulessWindow.swift | 11 ++-- src/PopoverPanel.swift | 6 +-- src/UpdateManager.swift | 14 ++--- src/UpdateViewController.swift | 94 ++++++++++----------------------- 11 files changed, 136 insertions(+), 287 deletions(-) diff --git a/src/AboutViewController.swift b/src/AboutViewController.swift index 982b29c..c559c33 100644 --- a/src/AboutViewController.swift +++ b/src/AboutViewController.swift @@ -1,10 +1,3 @@ -// -// AboutLicenseView.swift -// CmdBar -// -// Created by Igor Kolokolnikov on 8/16/23. -// - import AppKit // MARK: - Constants @@ -29,10 +22,8 @@ enum Strings { class AboutViewController: NSViewController, NSTextFieldDelegate { // MARK: - Views private var appIconImage: NSImageView = { - //let image = NSImageView(image: NSApp.applicationIconImage) let image = NSImageView() - image.image = NSWorkspace.shared - .icon(forFile: Bundle.main.bundlePath) + image.image = NSWorkspace.shared.icon(forFile: Bundle.main.bundlePath) image.imageScaling = .scaleAxesIndependently image.translatesAutoresizingMaskIntoConstraints = false return image @@ -40,16 +31,12 @@ class AboutViewController: NSViewController, NSTextFieldDelegate { private var appNameLabel: NSTextField = { let textField = NSTextField() - textField.stringValue = - (Bundle.main.infoDictionary?["CFBundleName"] as? String) ?? - "NOT FOUND" + textField.stringValue = (Bundle.main.infoDictionary?["CFBundleName"] as? String) ?? "NOT FOUND" textField.isEditable = false textField.isBezeled = false textField.drawsBackground = false textField.alignment = .center - textField.font = NSFont.systemFont(ofSize: NSFontDescriptor - .preferredFontDescriptor(forTextStyle: .title1).pointSize, - weight: .bold) + textField.font = NSFont.systemFont(ofSize: NSFontDescriptor.preferredFontDescriptor(forTextStyle: .title1).pointSize, weight: .bold) textField.translatesAutoresizingMaskIntoConstraints = false return textField }() @@ -62,9 +49,7 @@ class AboutViewController: NSViewController, NSTextFieldDelegate { textField.drawsBackground = false textField.alignment = .center textField.textColor = NSColor.systemGray - textField.font = NSFont.systemFont(ofSize: NSFontDescriptor - .preferredFontDescriptor(forTextStyle: .subheadline).pointSize, - weight: .regular) + textField.font = NSFont.systemFont(ofSize: NSFontDescriptor.preferredFontDescriptor(forTextStyle: .subheadline).pointSize, weight: .regular) textField.translatesAutoresizingMaskIntoConstraints = false return textField }() @@ -79,9 +64,7 @@ class AboutViewController: NSViewController, NSTextFieldDelegate { textField.drawsBackground = false textField.alignment = .center textField.textColor = NSColor.systemGray - textField.font = NSFont.systemFont(ofSize: NSFontDescriptor - .preferredFontDescriptor(forTextStyle: .subheadline).pointSize, - weight: .regular) + textField.font = NSFont.systemFont(ofSize: NSFontDescriptor.preferredFontDescriptor(forTextStyle: .subheadline).pointSize, weight: .regular) textField.translatesAutoresizingMaskIntoConstraints = false return textField }() @@ -160,68 +143,39 @@ class AboutViewController: NSViewController, NSTextFieldDelegate { // App image. NSLayoutConstraint.activate([ appIconImage.widthAnchor.constraint(equalToConstant: 100), - appIconImage.heightAnchor - .constraint(equalTo: appIconImage.widthAnchor, - multiplier: 1), - appIconImage.topAnchor - .constraint(equalTo: view.topAnchor, - constant: ViewConstants.spacing20), - appIconImage.centerXAnchor - .constraint(equalTo: view.centerXAnchor), + appIconImage.heightAnchor.constraint(equalTo: appIconImage.widthAnchor, multiplier: 1), + appIconImage.topAnchor.constraint(equalTo: view.topAnchor, constant: ViewConstants.spacing20), + appIconImage.centerXAnchor.constraint(equalTo: view.centerXAnchor), ]) // Title NSLayoutConstraint.activate([ - appNameLabel.topAnchor - .constraint(equalTo: appIconImage.bottomAnchor, - constant: ViewConstants.spacing20), - appNameLabel.centerXAnchor - .constraint(equalTo: view.centerXAnchor), + appNameLabel.topAnchor.constraint(equalTo: appIconImage.bottomAnchor, constant: ViewConstants.spacing20), + appNameLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor), - versionLabel.topAnchor - .constraint(equalTo: appNameLabel.bottomAnchor, - constant: ViewConstants.spacing2), - versionLabel.centerXAnchor - .constraint(equalTo: view.centerXAnchor), + versionLabel.topAnchor.constraint(equalTo: appNameLabel.bottomAnchor, constant: ViewConstants.spacing2), + versionLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor), - copyrightLabel.topAnchor - .constraint(equalTo: versionLabel.bottomAnchor, - constant: ViewConstants.spacing10), - copyrightLabel.centerXAnchor - .constraint(equalTo: view.centerXAnchor), + copyrightLabel.topAnchor.constraint(equalTo: versionLabel.bottomAnchor, constant: ViewConstants.spacing10), + copyrightLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor), ]) // Buttons NSLayoutConstraint.activate([ - buttonsContainer.topAnchor - .constraint(equalTo: copyrightLabel.bottomAnchor, - constant: ViewConstants.spacing20), - buttonsContainer.bottomAnchor - .constraint(equalTo: view.bottomAnchor, - constant: -ViewConstants.spacing20), - buttonsContainer.centerXAnchor - .constraint(equalTo: view.centerXAnchor), + buttonsContainer.topAnchor.constraint(equalTo: copyrightLabel.bottomAnchor, constant: ViewConstants.spacing20), + buttonsContainer.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -ViewConstants.spacing20), + buttonsContainer.centerXAnchor.constraint(equalTo: view.centerXAnchor), - privacyButton.topAnchor - .constraint(equalTo: buttonsContainer.topAnchor), - privacyButton.bottomAnchor - .constraint(equalTo: buttonsContainer.bottomAnchor), - privacyButton.leadingAnchor - .constraint(equalTo: buttonsContainer.leadingAnchor), + privacyButton.topAnchor.constraint(equalTo: buttonsContainer.topAnchor), + privacyButton.bottomAnchor.constraint(equalTo: buttonsContainer.bottomAnchor), + privacyButton.leadingAnchor.constraint(equalTo: buttonsContainer.leadingAnchor), - documentationButton.firstBaselineAnchor - .constraint(equalTo: privacyButton.firstBaselineAnchor), - documentationButton.leadingAnchor - .constraint(equalTo: privacyButton.trailingAnchor, - constant: ViewConstants.spacing10), + documentationButton.firstBaselineAnchor.constraint(equalTo: privacyButton.firstBaselineAnchor), + documentationButton.leadingAnchor.constraint(equalTo: privacyButton.trailingAnchor, constant: ViewConstants.spacing10), - websiteButton.firstBaselineAnchor - .constraint(equalTo: privacyButton.firstBaselineAnchor), - websiteButton.leadingAnchor - .constraint(equalTo: documentationButton.trailingAnchor, - constant: ViewConstants.spacing10), - websiteButton.trailingAnchor - .constraint(equalTo: buttonsContainer.trailingAnchor), + websiteButton.firstBaselineAnchor.constraint(equalTo: privacyButton.firstBaselineAnchor), + websiteButton.leadingAnchor.constraint(equalTo: documentationButton.trailingAnchor, constant: ViewConstants.spacing10), + websiteButton.trailingAnchor.constraint(equalTo: buttonsContainer.trailingAnchor), ]) } diff --git a/src/AppDelegate.swift b/src/AppDelegate.swift index e38bf8c..fa26920 100644 --- a/src/AppDelegate.swift +++ b/src/AppDelegate.swift @@ -3,7 +3,7 @@ import ServiceManagement class AppDelegate: NSObject, NSApplicationDelegate { // MARK: - State - private var aboutWindow: MenulessWindow! + private var aboutWindow: MenulessWindow! private var updateWindow: MenulessWindow! // MARK: - Lifecycle @@ -22,11 +22,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { // MARK: - Notifications private func setupNotifications() { - NSWorkspace.shared.notificationCenter.addObserver( - self, - selector: #selector(wakeUp), - name: NSWorkspace.didWakeNotification, - object: nil) + NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(wakeUp), name: NSWorkspace.didWakeNotification, object: nil) } @objc private func wakeUp() { @@ -47,7 +43,6 @@ class AppDelegate: NSObject, NSApplicationDelegate { @objc func checkForUpdates() { NSApplication.shared.activate(ignoringOtherApps: true) updateWindow.makeKeyAndOrderFront(nil) - updateWindow.center() } // MARK: - Setup About Window diff --git a/src/CBMenuBarItem.swift b/src/CBMenuBarItem.swift index d64350a..357b086 100644 --- a/src/CBMenuBarItem.swift +++ b/src/CBMenuBarItem.swift @@ -57,11 +57,12 @@ final class CBMenuBarItem: NSObject, NSWindowDelegate { return event } - // On click and drag, the button should panel should desappear and - // un-highlight. + // On click and drag, the button should panel should desappear and un-highlight. localDragEventMonitor = LocalEventMonitor(mask: [.leftMouseDragged, .keyDown]) { [weak self] event in + let modifiers = event.modifierFlags.rawValue + if let panel = self?.panel, panel.isKeyWindow { - if event.modifierFlags.contains(.command) && event.type == .leftMouseDragged { + if modsContains(keys: OSCmd, in: modifiers) && event.type == .leftMouseDragged { self?.panel.resignKey() } } diff --git a/src/CmdManager.swift b/src/CmdManager.swift index f362b1f..7322e7a 100644 --- a/src/CmdManager.swift +++ b/src/CmdManager.swift @@ -5,8 +5,7 @@ class CmdFile { private(set) var lastExec = Int(Date().timeIntervalSince1970) var untilNextExec: Int { get { - let res = reloadTime - - (Int(Date().timeIntervalSince1970) - lastExec) + let res = reloadTime - (Int(Date().timeIntervalSince1970) - lastExec) if res <= 0 { return reloadTime } return res } @@ -15,7 +14,7 @@ class CmdFile { private(set) var url: URL private(set) var reloadTime: Int private(set) var statusItem: CBMenuBarItem = CBMenuBarItem() - + private var shouldWait = false init(url: URL, reloadTime: Int) { @@ -41,13 +40,10 @@ class CmdFile { let execResult = execute(atPath: url) DispatchQueue.main.async { if execResult.title.isEmpty { - self?.statusItem.setImage( - title: "exclamationmark.triangle.fill", - description: "Warning") + self?.statusItem.setImage(title: "exclamationmark.triangle.fill", description: "Warning") self?.statusItem.setTitle("") } else { - self?.statusItem.setImage(title: nil, - description: "") + self?.statusItem.setImage(title: nil, description: "") self?.statusItem.setTitle(execResult.0) } self?.statusItem.setContents(to: execResult.body) @@ -106,31 +102,23 @@ class CmdManager { private func getPaths() { let manager = FileManager.default - let path = manager.homeDirectoryForCurrentUser - .appending(path: ".cmdbar") - if let contents = try? manager - .contentsOfDirectory(atPath: path.path()) { + let path = manager.homeDirectoryForCurrentUser.appending(path: ".cmdbar") + if let contents = try? manager.contentsOfDirectory(atPath: path.path()) { for content in contents { let filePath = path.appending(path: content) let domains = filePath.path().components(separatedBy: ".") if (isValidTimeFormat(domains[domains.count - 1])) { - paths.append(CmdFile(url: filePath, - reloadTime: intervalToSeconds( - from: domains[domains.count - 1]))) - } else if domains.last == "sh" && - isValidTimeFormat(domains[domains.count - 2]) { - paths.append(CmdFile(url: filePath, - reloadTime: intervalToSeconds( - from: domains[domains.count - 2]))) + paths.append(CmdFile(url: filePath, reloadTime: intervalToSeconds(from: domains[domains.count - 1]))) + } else if domains.last == "sh" && isValidTimeFormat(domains[domains.count - 2]) { + paths.append(CmdFile(url: filePath, reloadTime: intervalToSeconds(from: domains[domains.count - 2]))) } } } } private func setupMenu() { - defaultStatusItem = NSStatusBar.system - .statusItem(withLength: NSStatusItem.variableLength) + defaultStatusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength) if let btn = defaultStatusItem?.button { let image = NSApp.applicationIconImage image!.size = NSSize(width: 22, height: 22) @@ -138,21 +126,13 @@ class CmdManager { } guard defaultStatusItem != nil else { return } let menu = NSMenu() - menu.addItem(NSMenuItem(title: "Reload", - action: #selector(reloadWidgets), - keyEquivalent: "")) + menu.addItem(NSMenuItem(title: "Reload", action: #selector(reloadWidgets), keyEquivalent: "")) menu.addItem(NSMenuItem.separator()) - menu.addItem(NSMenuItem(title: "About", - action: #selector(showAbout), - keyEquivalent: "")) + menu.addItem(NSMenuItem(title: "About", action: #selector(showAbout), keyEquivalent: "")) menu.addItem(NSMenuItem.separator()) - menu.addItem(NSMenuItem(title: "Check for Updates...", - action: #selector(checkForUpdates), - keyEquivalent: "")) + menu.addItem(NSMenuItem(title: "Check for Updates...", action: #selector(checkForUpdates), keyEquivalent: "")) menu.addItem(NSMenuItem.separator()) - menu.addItem(NSMenuItem(title: "Quit", - action: #selector(NSApplication.terminate(_:)), - keyEquivalent: "q")) + menu.addItem(NSMenuItem(title: "Quit", action: #selector(NSApplication.terminate(_:)), keyEquivalent: "q")) defaultStatusItem!.menu = menu } diff --git a/src/CmdViewController.swift b/src/CmdViewController.swift index 322fa26..d585aac 100644 --- a/src/CmdViewController.swift +++ b/src/CmdViewController.swift @@ -132,11 +132,7 @@ class CmdViewController: NSViewController { private var updateButton: NSButton = { let button = NSButton() - button.image = NSImage(systemSymbolName: "arrow.down.circle.fill", accessibilityDescription: nil)? - .withSymbolConfiguration( - NSImage.SymbolConfiguration(textStyle: .title2, scale: .large) - .applying(.init(paletteColors: [.white, .systemGreen])) - ) + button.image = NSImage(systemSymbolName: "arrow.down.circle.fill", accessibilityDescription: nil)?.withSymbolConfiguration(NSImage.SymbolConfiguration(textStyle: .title2, scale: .large) .applying(.init(paletteColors: [.white, .systemGreen]))) button.isBordered = false button.action = #selector(updateApp) button.sizeToFit() @@ -327,17 +323,14 @@ class CmdViewController: NSViewController { } private func resetReloadButton() { - reloadButton.image = systemImage("arrow.clockwise.circle.fill", - .title2, .large, - .init(paletteColors: [.white, - .systemBlue])) + reloadButton.image = systemImage("arrow.clockwise.circle.fill", .title2, .large, .init(paletteColors: [.white, .systemBlue])) reloadButton.action = #selector(reloadWidget) reloadButton.toolTip = "Reload Current" } private func startReloadTextTimer() { timer = DispatchSource.makeTimerSource(queue: DispatchQueue.global()) - timer?.schedule(deadline: .now(), repeating: .seconds(1)) + timer?.schedule(deadline: .now(), repeating: .milliseconds(500)) timer?.setEventHandler { [weak self] in DispatchQueue.main.async { guard let controller = self, let file = controller.cmdFile else { return } @@ -349,24 +342,16 @@ class CmdViewController: NSViewController { } private func setupKeyEvents() { - keyboardEvents = LocalEventMonitor(mask: [.flagsChanged, .keyDown], - handler: - { [weak self] event in + keyboardEvents = LocalEventMonitor(mask: [.flagsChanged, .keyDown], handler: { [weak self] event in let modifiers = event.modifierFlags.rawValue let key = event.keyCode if modsContains(keys: OSShift, in: modifiers) { - self?.reloadButton.image = - systemImage("arrow.clockwise.circle.fill", .title2, - .large,.init(paletteColors: [.white, - .systemCyan])) + self?.reloadButton.image = systemImage("arrow.clockwise.circle.fill", .title2, .large,.init(paletteColors: [.white, .systemCyan])) self?.reloadButton.action = #selector(self?.reloadWidgets) self?.reloadButton.toolTip = "Reload All" } else { - self?.reloadButton.image = - systemImage("arrow.clockwise.circle.fill", .title2, - .large, .init(paletteColors: [.white, - .systemBlue])) + self?.reloadButton.image = systemImage("arrow.clockwise.circle.fill", .title2, .large, .init(paletteColors: [.white, .systemBlue])) self?.reloadButton.action = #selector(self?.reloadWidget) self?.reloadButton.toolTip = "Reload Current" } @@ -383,10 +368,8 @@ class CmdViewController: NSViewController { } } else if modsContains(keys: OSCmd | OSShift, in: modifiers) { if key == kVK_ANSI_R { - // NOTE: We need to resign the window in order to - // prevent the program from intercepting the - // events, which result in sounds beign made for - // missing performKeyEquivalent. + // NOTE: We need to resign the window in order to prevent the program from intercepting the events, which result in sounds + // beign made for missing performKeyEquivalent. self?.view.window?.resignKey() self?.reloadWidgets() } diff --git a/src/Helpers.swift b/src/Helpers.swift index 6821267..9d1a5d6 100644 --- a/src/Helpers.swift +++ b/src/Helpers.swift @@ -17,7 +17,7 @@ func modsContainsNone(in modifiers: UInt) -> Bool { enum ViewConstants { static let spacing2: CGFloat = 2 - static let spacing5: CGFloat = 2 + static let spacing5: CGFloat = 5 static let spacing10: CGFloat = 10 static let spacing15: CGFloat = 15 static let spacing20: CGFloat = 20 @@ -27,25 +27,20 @@ enum ViewConstants { static let spacing40: CGFloat = 40 } -fileprivate extension Notification.Name { - static let beginMenuTracking = Notification.Name("com.apple.HIToolbox.beginMenuTrackingNotification") - static let endMenuTracking = Notification.Name("com.apple.HIToolbox.endMenuTrackingNotification") -} - #if(DEBUG) struct EndpointConstants { - static var versionURL = "http://localhost:8081/version" - static var appURL = "http://localhost:8081/download" - static var appURLZip = "http://localhost:8081/static/app/CmdBar.zip" - static var changelog = "http://localhost:8081/changelog" + static var versionURL = "http://localhost:8081/version" + static var appURL = "http://localhost:8081/download" + static var appURLZip = "http://localhost:8081/static/app/CmdBar.zip" + static var changelog = "http://localhost:8081/changelog" static var validateURL = "http://localhost:8081/validate" } #else struct EndpointConstants { - static var versionURL = "http://cmdbar.app/version" - static var appURL = "http://cmdbar.app/download" - static var appURLZip = "http://cmdbar.app/static/app/CmdBar.zip" - static var changelog = "http://cmdbar.app/changelog" + static var versionURL = "http://cmdbar.app/version" + static var appURL = "http://cmdbar.app/download" + static var appURLZip = "http://cmdbar.app/static/app/CmdBar.zip" + static var changelog = "http://cmdbar.app/changelog" static var validateURL = "https://cmdbar.app/validate" } #endif @@ -181,15 +176,9 @@ func getColors(_ light: NSColor, _ dark: NSColor, for appearance: NSAppearance) } // ex: systemImage("sunrise.circle.fill", .title2, .large, .init(paletteColors: [.white, .systemOrange])) -func systemImage(_ name: String, _ size: NSFont.TextStyle, - _ scale: NSImage.SymbolScale, - _ configuration: NSImage.SymbolConfiguration) -> NSImage? -{ +func systemImage(_ name: String, _ size: NSFont.TextStyle, _ scale: NSImage.SymbolScale, _ configuration: NSImage.SymbolConfiguration) -> NSImage? { return NSImage(systemSymbolName: name, accessibilityDescription: nil)? - .withSymbolConfiguration( - NSImage.SymbolConfiguration(textStyle: size, scale: scale) - .applying(configuration) - ) + .withSymbolConfiguration(NSImage.SymbolConfiguration(textStyle: size, scale: scale).applying(configuration)) } func openLink(_ url: String) { @@ -197,6 +186,11 @@ func openLink(_ url: String) { NSWorkspace.shared.open(url) } +fileprivate extension Notification.Name { + static let beginMenuTracking = Notification.Name("com.apple.HIToolbox.beginMenuTrackingNotification") + static let endMenuTracking = Notification.Name("com.apple.HIToolbox.endMenuTrackingNotification") +} + func persistMenuBar(_ state: Bool) { if state { DistributedNotificationCenter.default().post(name: .beginMenuTracking, object: nil) diff --git a/src/Makefile b/src/Makefile index a2585eb..7708e24 100644 --- a/src/Makefile +++ b/src/Makefile @@ -7,12 +7,9 @@ XCODE_PATH = $(shell xcode-select --print-path) EXEC = CmdBar -SRCMODULES = UpdateManager.swift AboutViewController.swift \ - AppDelegate.swift CBMenuBarItem.swift CircularProgressView.swift \ - CmdManager.swift CmdViewController.swift CopyableTextView.swift \ - EditableNSTextField.swift EventMonitor.swift Helpers.swift \ - MenulessWindow.swift PopoverPanel.swift QuietView.swift \ - UpdateViewController.swift main.swift +SRCMODULES = UpdateManager.swift AboutViewController.swift AppDelegate.swift CBMenuBarItem.swift CircularProgressView.swift \ + CmdManager.swift CmdViewController.swift CopyableTextView.swift EditableNSTextField.swift EventMonitor.swift Helpers.swift \ + MenulessWindow.swift PopoverPanel.swift QuietView.swift UpdateViewController.swift main.swift ARMOBJMODULES = $(addprefix ./arm64/,$(SRCMODULES:.swift=.o)) X86OBJMODULES = $(addprefix ./x86_64/,$(SRCMODULES:.swift=.o)) @@ -22,51 +19,40 @@ FRAMEWORKS = -framework AppKit -framework ServiceManagement LIBS = -lzip zip: - @$(MAKE) -C libs/Zip/Zip FLAGS=$(FLAGS) CFLAGS=$(CFLAGS) \ - MACOS_VERSION=$(MACOS_VERSION) all + @$(MAKE) -C libs/Zip/Zip FLAGS=$(FLAGS) CFLAGS=$(CFLAGS) MACOS_VERSION=$(MACOS_VERSION) all cmdbar_updater: @$(MAKE) -C updater FLAGS=$(FLAGS) all @cp updater/$@ . ./arm64/%.o: %.swift - swift -frontend -c $(if $(DEBUG), -D DEBUG,) \ - -target arm64-apple-macos$(MACOS_VERSION) $(FLAGS) \ + swift -frontend -c $(if $(DEBUG), -D DEBUG,) -target arm64-apple-macos$(MACOS_VERSION) $(FLAGS) \ -I./libs/Zip/Zip -I./libs/Zip/Zip/arm64 -L./libs/Zip/Zip/arm64 \ - -primary-file $< $(filter-out $<, $(SRCMODULES)) $(LIBS) \ - -sdk $(SDK) -module-name $(EXEC) -o $@ -emit-module && touch $@ + -primary-file $< $(filter-out $<, $(SRCMODULES)) $(LIBS) -sdk $(SDK) -module-name $(EXEC) \ + -o $@ -emit-module && touch $@ ifdef UNIVERSAL ./x86_64/%.o: %.swift - @swift -frontend -c $(if $(DEBUG), -D DEBUG,) \ - -target x86_64-apple-macos$(MACOS_VERSION) $(FLAGS) \ + @swift -frontend -c $(if $(DEBUG), -D DEBUG,) -target x86_64-apple-macos$(MACOS_VERSION) $(FLAGS) \ -I./libs/Zip/Zip -I./libs/Zip/Zip/x86_64 -L./libs/Zip/Zip/x86_64 \ - -primary-file $< $(filter-out $<, $(SRCMODULES)) $(LIBS) \ - -sdk $(SDK) -module-name $(EXEC) -o $@ -emit-module && touch $@ + -primary-file $< $(filter-out $<, $(SRCMODULES)) $(LIBS) -sdk $(SDK) -module-name $(EXEC) \ + -o $@ -emit-module && touch $@ endif ./arm64/$(EXEC): $(ARMOBJMODULES) - @ld -syslibroot $(SDK) -lSystem -arch arm64 -macos_version_min \ - $(MACOS_VERSION).0 \ + @ld -syslibroot $(SDK) -lSystem -arch arm64 -macos_version_min $(MACOS_VERSION).0 \ /Library/Developer/CommandLineTools/usr/lib/swift/macosx/libswiftCompatibilityPacks.a \ - -sectcreate __TEXT __info_plist Info.plist \ - -L /Library/Developer/CommandLineTools/usr/lib/swift/macosx -L \ - /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib/swift \ - -no_objc_category_merging -L $(XCODE_PATH) -rpath \ - Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx \ - ./arm64/main.o $(filter-out ./arm64/main.o, $(ARMOBJMODULES)) \ + -sectcreate __TEXT __info_plist Info.plist -L /Library/Developer/CommandLineTools/usr/lib/swift/macosx -L \ + /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib/swift -no_objc_category_merging -L $(XCODE_PATH) -rpath \ + Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx ./arm64/main.o $(filter-out ./arm64/main.o, $(ARMOBJMODULES)) \ ./libs/Zip/Zip/arm64/libzip.a -o $@ ifdef UNIVERSAL ./x86_64/$(EXEC): $(X86OBJMODULES) - @ld -syslibroot $(SDK) -lSystem -arch x86_64 -macos_version_min \ - $(MACOS_VERSION).0 \ + @ld -syslibroot $(SDK) -lSystem -arch x86_64 -macos_version_min $(MACOS_VERSION).0 \ /Library/Developer/CommandLineTools/usr/lib/swift/macosx/libswiftCompatibilityPacks.a \ - -sectcreate __TEXT __info_plist Info.plist \ - -L /Library/Developer/CommandLineTools/usr/lib/swift/macosx -L \ - /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib/swift \ - -no_objc_category_merging -L $(XCODE_PATH) -rpath \ - Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx \ - ./x86_64/main.o $(filter-out ./x86_64/main.o, $(X86OBJMODULES)) \ + -sectcreate __TEXT __info_plist Info.plist -L /Library/Developer/CommandLineTools/usr/lib/swift/macosx -L \ + /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib/swift -no_objc_category_merging -L $(XCODE_PATH) -rpath \ + Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx ./x86_64/main.o $(filter-out ./x86_64/main.o, $(X86OBJMODULES)) \ ./libs/Zip/Zip/x86_64/libzip.a -o $@ endif @@ -86,16 +72,19 @@ $(EXEC).app: $(EXEC) cp resources/AppIcon.icns $@/Contents/Resources/ && \ cp $(EXEC) $@/Contents/MacOS/ && \ cp cmdbar_updater $@/Contents/MacOS/ && \ - $(if $(DEBUG), \ - codesign --entitlements Grapp.entitlements \ - -s ${APPLE_DEVELOPMENT} -f --timestamp -o runtime $(EXEC).app, \ - codesign -s ${APPLE_DEVELOPER_ID_APPLICATION} -f --timestamp \ - -o runtime $(EXEC).app) + $(if $(DEBUG), codesign --entitlements Grapp.entitlements -s ${APPLE_DEVELOPMENT} -f --timestamp -o runtime $(EXEC).app, \ + codesign -s ${APPLE_DEVELOPER_ID_APPLICATION} -f --timestamp -o runtime $(EXEC).app) all: zip cmdbar_updater $(EXEC).app -run: all - @open $(EXEC).app +clear: + clear + +kill: + -pkill $(EXEC) + +run: clear kill all + ./$(EXEC) clean: rm -rf $(EXEC) $(EXEC).app cmdbar_updater arm64 x86_64 diff --git a/src/MenulessWindow.swift b/src/MenulessWindow.swift index e06a1e5..f45b604 100644 --- a/src/MenulessWindow.swift +++ b/src/MenulessWindow.swift @@ -10,23 +10,22 @@ class MenulessWindow: NSWindow { defer: false ) super.contentViewController = viewController - + title = "" titlebarAppearsTransparent = true collectionBehavior = [.managed, .fullScreenNone] isReleasedWhenClosed = false hidesOnDeactivate = false } - + override func performKeyEquivalent(with event: NSEvent) -> Bool { let modifiers = event.modifierFlags.rawValue let key = event.keyCode - + if event.type == NSEvent.EventType.keyDown { - if modsContains(keys: OSCmd, in: modifiers) && - key == kVK_ANSI_W - { + if modsContains(keys: OSCmd, in: modifiers) && key == kVK_ANSI_W { performClose(nil) + return true } } diff --git a/src/PopoverPanel.swift b/src/PopoverPanel.swift index dce4705..12d9258 100644 --- a/src/PopoverPanel.swift +++ b/src/PopoverPanel.swift @@ -6,8 +6,7 @@ class PopoverPanel: NSPanel { init(viewController: NSViewController) { super.init( contentRect: CGRect(x: 0, y: 0, width: 100, height: 100), - styleMask: [.titled, .nonactivatingPanel, .utilityWindow, - .fullSizeContentView], + styleMask: [.titled, .nonactivatingPanel, .utilityWindow, .fullSizeContentView], backing: .buffered, defer: false ) @@ -23,8 +22,7 @@ class PopoverPanel: NSPanel { titlebarAppearsTransparent = true animationBehavior = .none - collectionBehavior = [.moveToActiveSpace, .fullScreenAuxiliary, - .transient] + collectionBehavior = [.moveToActiveSpace, .fullScreenAuxiliary, .transient] isReleasedWhenClosed = false hidesOnDeactivate = false diff --git a/src/UpdateManager.swift b/src/UpdateManager.swift index 8e386b0..0a36304 100644 --- a/src/UpdateManager.swift +++ b/src/UpdateManager.swift @@ -1,10 +1,3 @@ -// -// UpdateManager.swift -// CmdBar -// -// Created by Igor Kolokolnikov on 5/23/24. -// - import Foundation import Zip @@ -27,9 +20,10 @@ final class UpdateManager { func currentVersion() -> Double? { guard let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String else { return nil } - if let version = Double(version) { - return version - } else { return nil } + if let version = Double(version) + { return version } + else + { return nil } } func latestVersion() async -> VersionModel? { diff --git a/src/UpdateViewController.swift b/src/UpdateViewController.swift index 6f1205e..72ec768 100644 --- a/src/UpdateViewController.swift +++ b/src/UpdateViewController.swift @@ -17,8 +17,7 @@ class UpdateViewController: NSViewController, UpdateManagerDelegate { private var appIconImage: NSImageView = { let image = NSImageView() - image.image = NSWorkspace.shared - .icon(forFile: Bundle.main.bundlePath) + image.image = NSWorkspace.shared.icon(forFile: Bundle.main.bundlePath) image.imageScaling = .scaleAxesIndependently image.translatesAutoresizingMaskIntoConstraints = false return image @@ -31,9 +30,7 @@ class UpdateViewController: NSViewController, UpdateManagerDelegate { textField.drawsBackground = false textField.alignment = .left textField.textColor = NSColor(name: nil) { getColors(.black, .white, for: $0) } - textField.font = NSFont.systemFont(ofSize: NSFontDescriptor - .preferredFontDescriptor(forTextStyle: .body).pointSize, - weight: .bold) + textField.font = NSFont.systemFont(ofSize: NSFontDescriptor.preferredFontDescriptor(forTextStyle: .body).pointSize, weight: .bold) textField.translatesAutoresizingMaskIntoConstraints = false return textField }() @@ -47,9 +44,7 @@ class UpdateViewController: NSViewController, UpdateManagerDelegate { textField.drawsBackground = false textField.alignment = .left textField.textColor = .gray - textField.font = NSFont.systemFont(ofSize: NSFontDescriptor - .preferredFontDescriptor(forTextStyle: .body).pointSize, - weight: .bold) + textField.font = NSFont.systemFont(ofSize: NSFontDescriptor.preferredFontDescriptor(forTextStyle: .body).pointSize, weight: .bold) textField.translatesAutoresizingMaskIntoConstraints = false return textField }() @@ -61,9 +56,7 @@ class UpdateViewController: NSViewController, UpdateManagerDelegate { (scrollableTextView.documentView as? NSTextView)?.isEditable = false (scrollableTextView.documentView as? NSTextView)?.textColor = .gray (scrollableTextView.documentView as? NSTextView)?.font = - NSFont.systemFont(ofSize: NSFontDescriptor - .preferredFontDescriptor(forTextStyle: .body).pointSize, - weight: .regular) + NSFont.systemFont(ofSize: NSFontDescriptor.preferredFontDescriptor(forTextStyle: .body).pointSize, weight: .regular) scrollableTextView.translatesAutoresizingMaskIntoConstraints = false return scrollableTextView }() @@ -132,46 +125,25 @@ class UpdateViewController: NSViewController, UpdateManagerDelegate { NSLayoutConstraint.activate([ appIconImage.widthAnchor.constraint(equalToConstant: 70), - appIconImage.heightAnchor - .constraint(equalTo: appIconImage.widthAnchor, - multiplier: 1), - appIconImage.topAnchor.constraint(equalTo: view.topAnchor, - constant: ViewConstants.spacing10), - appIconImage.leadingAnchor - .constraint(equalTo: view.leadingAnchor, - constant: ViewConstants.spacing10), + appIconImage.heightAnchor.constraint(equalTo: appIconImage.widthAnchor,multiplier: 1), + appIconImage.topAnchor.constraint(equalTo: view.topAnchor, constant: ViewConstants.spacing10), + appIconImage.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: ViewConstants.spacing10), - statusLabel.topAnchor - .constraint(equalTo: appIconImage.topAnchor, - constant: ViewConstants.spacing10), - statusLabel.leadingAnchor - .constraint(equalTo: appIconImage.trailingAnchor, - constant: ViewConstants.spacing10), + statusLabel.topAnchor.constraint(equalTo: appIconImage.topAnchor, constant: ViewConstants.spacing10), + statusLabel.leadingAnchor.constraint(equalTo: appIconImage.trailingAnchor, constant: ViewConstants.spacing10), - subStatusLabel.topAnchor - .constraint(equalTo: statusLabel.bottomAnchor, - constant: ViewConstants.spacing10), - subStatusLabel.leadingAnchor - .constraint(equalTo: statusLabel.leadingAnchor), + subStatusLabel.topAnchor.constraint(equalTo: statusLabel.bottomAnchor, constant: ViewConstants.spacing10), + subStatusLabel.leadingAnchor.constraint(equalTo: statusLabel.leadingAnchor), - changelogLabel.widthAnchor - .constraint(equalTo: stackView.widthAnchor), + changelogLabel.widthAnchor.constraint(equalTo: stackView.widthAnchor), changelogLabel.heightAnchor.constraint(equalToConstant: 150), - stackView.topAnchor - .constraint(equalTo: subStatusLabel.bottomAnchor, - constant: ViewConstants.spacing2), - stackView.leadingAnchor - .constraint(equalTo: statusLabel.leadingAnchor), - view.trailingAnchor - .constraint(equalTo: stackView.trailingAnchor, - constant: ViewConstants.spacing20), - view.bottomAnchor - .constraint(equalTo: stackView.bottomAnchor, - constant: ViewConstants.spacing20), + stackView.topAnchor.constraint(equalTo: subStatusLabel.bottomAnchor, constant: ViewConstants.spacing2), + stackView.leadingAnchor.constraint(equalTo: statusLabel.leadingAnchor), + view.trailingAnchor.constraint(equalTo: stackView.trailingAnchor, constant: ViewConstants.spacing20), + view.bottomAnchor.constraint(equalTo: stackView.bottomAnchor, constant: ViewConstants.spacing20), - buttonsStackView.heightAnchor - .constraint(equalTo: updateButton.heightAnchor), + buttonsStackView.heightAnchor.constraint(equalTo: updateButton.heightAnchor), ]) } @@ -185,6 +157,7 @@ class UpdateViewController: NSViewController, UpdateManagerDelegate { override func viewDidAppear() { super.viewDidAppear() + view.window?.center() (changelogLabel.documentView as? NSTextView)?.string = "" subStatusLabel.isHidden = true changelogLabel.isHidden = true @@ -205,44 +178,36 @@ class UpdateViewController: NSViewController, UpdateManagerDelegate { case .check: break case .latest: - self?.statusLabel.stringValue = UpdateStatus.latest - .rawValue + self?.statusLabel.stringValue = UpdateStatus.latest.rawValue break case .checking: - self?.statusLabel.stringValue = UpdateStatus.checking - .rawValue + self?.statusLabel.stringValue = UpdateStatus.checking.rawValue self?.updateButton.keyEquivalent = "" self?.updateButton.isEnabled = false case .available: self?.updateButton.title = "Download" self?.updateButton.keyEquivalent = "" - self?.statusLabel.stringValue = UpdateStatus.available - .rawValue + self?.statusLabel.stringValue = UpdateStatus.available.rawValue self?.updateButton.action = #selector(self!.downloadUpdate) case .downloading: self?.updateButton.isEnabled = false self?.updateButton.title = "Install" self?.progressIndicator.isHidden = false - self?.statusLabel.stringValue = UpdateStatus.downloading - .rawValue + self?.statusLabel.stringValue = UpdateStatus.downloading.rawValue case .extracting: self?.updateButton.isEnabled = false self?.updateButton.title = "Install" self?.progressIndicator.isHidden = false - self?.statusLabel.stringValue = UpdateStatus.extracting - .rawValue + self?.statusLabel.stringValue = UpdateStatus.extracting.rawValue case .install: self?.updateButton.title = "Install" self?.progressIndicator.isHidden = false - self?.statusLabel.stringValue = UpdateStatus.install - .rawValue + self?.statusLabel.stringValue = UpdateStatus.install.rawValue self?.updateButton.action = #selector(self!.installUpdate) case .checkFailed: - self?.statusLabel.stringValue = UpdateStatus.checkFailed - .rawValue + self?.statusLabel.stringValue = UpdateStatus.checkFailed.rawValue case .installFailed: - self?.statusLabel.stringValue = UpdateStatus.installFailed - .rawValue + self?.statusLabel.stringValue = UpdateStatus.installFailed.rawValue self?.updateButton.action = #selector(self!.checkForUpdate) } } @@ -262,12 +227,9 @@ class UpdateViewController: NSViewController, UpdateManagerDelegate { self?.subStatusLabel.isHidden = false self?.changelogLabel.isHidden = false for (i, change) in model.changes.enumerated() { - (self?.changelogLabel.documentView as? - NSTextView)?.string += - "\u{2022} \(change)" + (self?.changelogLabel.documentView as? NSTextView)?.string += "\u{2022} \(change)" if i < model.changes.count-1 { - (self?.changelogLabel.documentView as? - NSTextView)?.string += "\n" + (self?.changelogLabel.documentView as? NSTextView)?.string += "\n" } } }