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