diff --git a/PHP Monitor.xcodeproj/project.pbxproj b/PHP Monitor.xcodeproj/project.pbxproj index db38866..ccbf60a 100644 --- a/PHP Monitor.xcodeproj/project.pbxproj +++ b/PHP Monitor.xcodeproj/project.pbxproj @@ -14,6 +14,14 @@ 54B48B5F275F66AE006D90C5 /* Application.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54B48B5E275F66AE006D90C5 /* Application.swift */; }; 54B48B60275F66AE006D90C5 /* Application.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54B48B5E275F66AE006D90C5 /* Application.swift */; }; 54EAC806262F212B0092D14E /* GlobalKeybindPreference.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41CD0282628D8EE0065BBED /* GlobalKeybindPreference.swift */; }; + 54FCFD26276C883F004CE748 /* CheckboxPreferenceView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 54FCFD25276C883F004CE748 /* CheckboxPreferenceView.xib */; }; + 54FCFD27276C883F004CE748 /* CheckboxPreferenceView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 54FCFD25276C883F004CE748 /* CheckboxPreferenceView.xib */; }; + 54FCFD2A276C8AA4004CE748 /* CheckboxPreferenceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54FCFD29276C8AA4004CE748 /* CheckboxPreferenceView.swift */; }; + 54FCFD2B276C8AA4004CE748 /* CheckboxPreferenceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54FCFD29276C8AA4004CE748 /* CheckboxPreferenceView.swift */; }; + 54FCFD2D276C8D67004CE748 /* HotkeyPreferenceView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 54FCFD2C276C8D67004CE748 /* HotkeyPreferenceView.xib */; }; + 54FCFD2E276C8D67004CE748 /* HotkeyPreferenceView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 54FCFD2C276C8D67004CE748 /* HotkeyPreferenceView.xib */; }; + 54FCFD30276C8DA4004CE748 /* HotkeyPreferenceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54FCFD2F276C8DA4004CE748 /* HotkeyPreferenceView.swift */; }; + 54FCFD31276C8DA4004CE748 /* HotkeyPreferenceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54FCFD2F276C8DA4004CE748 /* HotkeyPreferenceView.swift */; }; C405A4D024B9B9140062FAFA /* InternetAccessPolicy.strings in Resources */ = {isa = PBXBuildFile; fileRef = C405A4CE24B9B9130062FAFA /* InternetAccessPolicy.strings */; }; C405A4D124B9B9140062FAFA /* InternetAccessPolicy.plist in Resources */ = {isa = PBXBuildFile; fileRef = C405A4CF24B9B9140062FAFA /* InternetAccessPolicy.plist */; }; C412E5FC25700D5300A1FB67 /* HomebrewPackage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C412E5FB25700D5300A1FB67 /* HomebrewPackage.swift */; }; @@ -129,6 +137,10 @@ 5420395E2613607600FB00FA /* Preferences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Preferences.swift; sourceTree = ""; }; 54AB03252763858F00A29D5F /* Timer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Timer.swift; sourceTree = ""; }; 54B48B5E275F66AE006D90C5 /* Application.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Application.swift; sourceTree = ""; }; + 54FCFD25276C883F004CE748 /* CheckboxPreferenceView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CheckboxPreferenceView.xib; sourceTree = ""; }; + 54FCFD29276C8AA4004CE748 /* CheckboxPreferenceView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckboxPreferenceView.swift; sourceTree = ""; }; + 54FCFD2C276C8D67004CE748 /* HotkeyPreferenceView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = HotkeyPreferenceView.xib; sourceTree = ""; }; + 54FCFD2F276C8DA4004CE748 /* HotkeyPreferenceView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HotkeyPreferenceView.swift; sourceTree = ""; }; C405A4CE24B9B9130062FAFA /* InternetAccessPolicy.strings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; path = InternetAccessPolicy.strings; sourceTree = ""; }; C405A4CF24B9B9140062FAFA /* InternetAccessPolicy.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = InternetAccessPolicy.plist; sourceTree = ""; }; C412E5FB25700D5300A1FB67 /* HomebrewPackage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomebrewPackage.swift; sourceTree = ""; }; @@ -223,6 +235,7 @@ 5420395826135DC100FB00FA /* PrefsVC.swift */, 5420395E2613607600FB00FA /* Preferences.swift */, C41CD0272628D8E20065BBED /* Keybinds */, + 54FCFD28276C88C0004CE748 /* Views */, ); path = Preferences; sourceTree = ""; @@ -237,6 +250,17 @@ path = PHP; sourceTree = ""; }; + 54FCFD28276C88C0004CE748 /* Views */ = { + isa = PBXGroup; + children = ( + 54FCFD25276C883F004CE748 /* CheckboxPreferenceView.xib */, + 54FCFD29276C8AA4004CE748 /* CheckboxPreferenceView.swift */, + 54FCFD2C276C8D67004CE748 /* HotkeyPreferenceView.xib */, + 54FCFD2F276C8DA4004CE748 /* HotkeyPreferenceView.swift */, + ); + path = Views; + sourceTree = ""; + }; C405A4CD24B9B9070062FAFA /* IAP */ = { isa = PBXGroup; children = ( @@ -521,7 +545,9 @@ C48D0C9025CC7FD000CC7490 /* StatsView.xib in Resources */, C405A4D124B9B9140062FAFA /* InternetAccessPolicy.plist in Resources */, C4232EE52612526500158FC6 /* Credits.html in Resources */, + 54FCFD26276C883F004CE748 /* CheckboxPreferenceView.xib in Resources */, C473319F2470923A009A0597 /* Localizable.strings in Resources */, + 54FCFD2D276C8D67004CE748 /* HotkeyPreferenceView.xib in Resources */, C405A4D024B9B9140062FAFA /* InternetAccessPolicy.strings in Resources */, C48D0C9A25CC888B00CC7490 /* HeaderView.xib in Resources */, ); @@ -531,6 +557,8 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 54FCFD27276C883F004CE748 /* CheckboxPreferenceView.xib in Resources */, + 54FCFD2E276C8D67004CE748 /* HotkeyPreferenceView.xib in Resources */, C4F780A825D80AE8000DBC97 /* php.ini in Resources */, C43A8A2025D9D1D700591B77 /* brew.json in Resources */, C4AF9F72275445FF00D44ED0 /* valet-config.json in Resources */, @@ -551,6 +579,7 @@ C4AF9F7A2754499000D44ED0 /* Valet.swift in Sources */, 5420395926135DC100FB00FA /* PrefsVC.swift in Sources */, C43603A0275E67610028EFC6 /* AppDelegate+Notifications.swift in Sources */, + 54FCFD30276C8DA4004CE748 /* HotkeyPreferenceView.swift in Sources */, C41C1B4722B009A400E7CF16 /* Shell.swift in Sources */, C4F2E43A2752F7D00020E974 /* PhpInstallation.swift in Sources */, C41C1B4D22B0215A00E7CF16 /* Actions.swift in Sources */, @@ -566,6 +595,7 @@ C41C1B4922B00A9800E7CF16 /* MenuBarImageGenerator.swift in Sources */, 5420395F2613607600FB00FA /* Preferences.swift in Sources */, C48D0C9325CC804200CC7490 /* XibLoadable.swift in Sources */, + 54FCFD2A276C8AA4004CE748 /* CheckboxPreferenceView.swift in Sources */, C4811D2A22D70F9A00B5F6B3 /* MainMenu.swift in Sources */, C412E5FC25700D5300A1FB67 /* HomebrewPackage.swift in Sources */, 54AB03262763858F00A29D5F /* Timer.swift in Sources */, @@ -596,6 +626,7 @@ 54EAC806262F212B0092D14E /* GlobalKeybindPreference.swift in Sources */, C4F780C425D80B75000DBC97 /* MainMenu.swift in Sources */, 54AB03272763858F00A29D5F /* Timer.swift in Sources */, + 54FCFD2B276C8AA4004CE748 /* CheckboxPreferenceView.swift in Sources */, 54B48B60275F66AE006D90C5 /* Application.swift in Sources */, C4F780C825D80B75000DBC97 /* DateExtension.swift in Sources */, C4F780CC25D80B75000DBC97 /* ActivePhpInstallation.swift in Sources */, @@ -623,6 +654,7 @@ C4B97B79275CF1B5003F3378 /* App+ActivationPolicy.swift in Sources */, C4F7809C25D80344000DBC97 /* CommandTest.swift in Sources */, C4F780BA25D80B62000DBC97 /* AppDelegate.swift in Sources */, + 54FCFD31276C8DA4004CE748 /* HotkeyPreferenceView.swift in Sources */, C4998F0B2617633900B2526E /* PrefsWC.swift in Sources */, C4F780A225D804AA000DBC97 /* Paths.swift in Sources */, C4F2E43B27530F750020E974 /* PhpInstallation.swift in Sources */, diff --git a/phpmon/Domain/Core/Base.lproj/Main.storyboard b/phpmon/Domain/Core/Base.lproj/Main.storyboard index f733de3..3182914 100644 --- a/phpmon/Domain/Core/Base.lproj/Main.storyboard +++ b/phpmon/Domain/Core/Base.lproj/Main.storyboard @@ -1,8 +1,8 @@ - + - + @@ -334,223 +334,22 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - - - - - - - - - - - - + @@ -578,12 +377,12 @@ Gw - + - + - + @@ -593,7 +392,7 @@ Gw - + @@ -601,7 +400,7 @@ Gw - + @@ -700,6 +499,7 @@ Gw + @@ -714,6 +514,8 @@ Gw + + diff --git a/phpmon/Domain/Preferences/PrefsVC.swift b/phpmon/Domain/Preferences/PrefsVC.swift index 4aa1f80..c816bec 100644 --- a/phpmon/Domain/Preferences/PrefsVC.swift +++ b/phpmon/Domain/Preferences/PrefsVC.swift @@ -14,34 +14,7 @@ class PrefsVC: NSViewController { // MARK: - Window Identifier - // Labels on the left - @IBOutlet weak var leftLabelDynamicIcon: NSTextField! - @IBOutlet weak var leftLabelServices: NSTextField! - @IBOutlet weak var leftLabelGlobalShortcut: NSTextField! - - // Dynamic icon - @IBOutlet weak var buttonDynamicIcon: NSButton! - @IBOutlet weak var labelDynamicIcon: NSTextField! - - // Full PHP version - @IBOutlet weak var buttonDisplayFullPhpVersion: NSButton! - @IBOutlet weak var labelDisplayFullPhpVersion: NSTextField! - - // Auto-restart services - @IBOutlet weak var buttonAutoRestartServices: NSButton! - @IBOutlet weak var labelAutoRestartServices: NSTextField! - - // Use own services - @IBOutlet weak var buttonUseInternalSwitcher: NSButton! - @IBOutlet weak var labelUseInternalSwitcher: NSTextField! - - // Shortcut - @IBOutlet weak var buttonSetShortcut: NSButton! - @IBOutlet weak var buttonClearShortcut: NSButton! - @IBOutlet weak var labelShortcut: NSTextField! - - // Close button (bottom right) - @IBOutlet weak var buttonClose: NSButton! + @IBOutlet weak var stackView: NSStackView! // MARK: - Display @@ -73,183 +46,59 @@ class PrefsVC: NSViewController { // MARK: - Lifecycle - override func viewWillAppear() { - loadLocalization() - loadDynamicIconFromPreferences() - loadFullPhpVersionFromPreferences() - loadGlobalKeybindFromPreferences() - loadUseInternalSwitcherFromPreferences() + override func viewDidLoad() { + [ + CheckboxPreferenceView.make( + sectionText: "prefs.dynamic_icon".localized, + descriptionText: "prefs.dynamic_icon_desc".localized, + checkboxText: "prefs.dynamic_icon_title".localized, + preference: .shouldDisplayDynamicIcon, + action: { + MainMenu.shared.refreshIcon() + } + ), + CheckboxPreferenceView.make( + sectionText: "", + descriptionText: "prefs.display_full_php_version_desc".localized, + checkboxText: "prefs.display_full_php_version".localized, + preference: .fullPhpVersionDynamicIcon, + action: { + MainMenu.shared.refreshIcon() + MainMenu.shared.update() + } + ), + CheckboxPreferenceView.make( + sectionText: "prefs.services".localized, + descriptionText: "prefs.auto_restart_services_desc".localized, + checkboxText: "prefs.auto_restart_services_title".localized, + preference: .autoServiceRestartAfterExtensionToggle, + action: {} + ), + CheckboxPreferenceView.make( + sectionText: "", + descriptionText: "prefs.use_internal_switcher_desc".localized, + checkboxText: "prefs.use_internal_switcher".localized, + preference: .useInternalSwitcher, + action: {} + ), + HotkeyPreferenceView.make( + sectionText: "prefs.global_shortcut".localized, + descriptionText: "prefs.shortcut_desc".localized, + self + ) + ].forEach({ self.stackView.addArrangedSubview($0) }) } + // MARK: - Listening for hotkey dleegate + + var listeningForHotkeyView: HotkeyPreferenceView? = nil + override func viewWillDisappear() { - if listeningForGlobalHotkey { - listeningForGlobalHotkey = false + if listeningForHotkeyView !== nil { + listeningForHotkeyView = nil } } - - private func loadLocalization() { - // Dynamic icon - leftLabelDynamicIcon.stringValue = "prefs.dynamic_icon".localized - labelDynamicIcon.stringValue = "prefs.dynamic_icon_desc".localized - buttonDynamicIcon.title = "prefs.dynamic_icon_title".localized - - // Full PHP version - buttonDisplayFullPhpVersion.title = "prefs.display_full_php_version".localized - labelDisplayFullPhpVersion.stringValue = "prefs.display_full_php_version_desc".localized - - // Services - leftLabelServices.stringValue = "prefs.services".localized - buttonAutoRestartServices.title = "prefs.auto_restart_services_title".localized - labelAutoRestartServices.stringValue = "prefs.auto_restart_services_desc".localized - - // Switcher - buttonUseInternalSwitcher.title = "prefs.use_internal_switcher".localized - labelUseInternalSwitcher.stringValue = "prefs.use_internal_switcher_desc".localized - - // Global Shortcut - leftLabelGlobalShortcut.stringValue = "prefs.global_shortcut".localized - labelShortcut.stringValue = "prefs.shortcut_desc".localized - buttonSetShortcut.title = "prefs.shortcut_set".localized - buttonClearShortcut.title = "prefs.shortcut_clear".localized - - // Close button - buttonClose.title = "prefs.close".localized - } - - // MARK: - Loading Preferences - - func loadDynamicIconFromPreferences() { - let shouldDisplay = Preferences.preferences[.shouldDisplayDynamicIcon] as! Bool == true - self.buttonDynamicIcon.state = shouldDisplay ? .on : .off - } - - func loadFullPhpVersionFromPreferences() { - let shouldDisplay = Preferences.preferences[.fullPhpVersionDynamicIcon] as! Bool == true - self.buttonDisplayFullPhpVersion.state = shouldDisplay ? .on : .off - } - - func loadAutoRestartServicesFromPreferences() { - let shouldDisplay = Preferences.preferences[.autoServiceRestartAfterExtensionToggle] as! Bool == true - self.buttonAutoRestartServices.state = shouldDisplay ? .on : .off - } - - func loadUseInternalSwitcherFromPreferences() { - let shouldDisplay = Preferences.preferences[.useInternalSwitcher] as! Bool == true - self.buttonUseInternalSwitcher.state = shouldDisplay ? .on : .off - } - - // MARK: - Actions - - @IBAction func toggledDynamicIcon(_ sender: Any) { - Preferences.update(.shouldDisplayDynamicIcon, value: buttonDynamicIcon.state == .on) - MainMenu.shared.refreshIcon() - } - - @IBAction func toggledFullPhpVersion(_ sender: Any) { - Preferences.update(.fullPhpVersionDynamicIcon, value: buttonDisplayFullPhpVersion.state == .on) - MainMenu.shared.refreshIcon() - MainMenu.shared.update() - } - - @IBAction func toggledAutoRestartServices(_ sender: Any) { - Preferences.update(.autoServiceRestartAfterExtensionToggle, value: buttonAutoRestartServices.state == .on) - } - - @IBAction func toggledUseInternalSwitcher(_ sender: Any) { - Preferences.update(.useInternalSwitcher, value: buttonUseInternalSwitcher.state == .on) - } - - // MARK: - Shortcut Preference - // Adapted from: https://dev.to/mitchartemis/creating-a-global-configurable-shortcut-for-macos-apps-in-swift-25e9 - - var listeningForGlobalHotkey = false { - didSet { - if listeningForGlobalHotkey { - DispatchQueue.main.async { [weak self] in - self?.buttonSetShortcut.highlight(true) - self?.buttonSetShortcut.title = "prefs.shortcut_listening".localized - } - } else { - DispatchQueue.main.async { [weak self] in - self?.buttonSetShortcut.highlight(false) - self?.loadGlobalKeybindFromPreferences() - } - } - } - } - - func loadGlobalKeybindFromPreferences() { - let globalKeybind = GlobalKeybindPreference.fromJson(Preferences.preferences[.globalHotkey] as! String?) - - if (globalKeybind != nil) { - updateKeybindButton(globalKeybind!) - } else { - buttonSetShortcut.title = "prefs.shortcut_set".localized - } - - buttonClearShortcut.isEnabled = globalKeybind != nil - } - - func updateGlobalShortcut(_ event : NSEvent) { - self.listeningForGlobalHotkey = false - - if let characters = event.charactersIgnoringModifiers { - let newGlobalKeybind = GlobalKeybindPreference.init( - function: event.modifierFlags.contains(.function), - control: event.modifierFlags.contains(.control), - command: event.modifierFlags.contains(.command), - shift: event.modifierFlags.contains(.shift), - option: event.modifierFlags.contains(.option), - capsLock: event.modifierFlags.contains(.capsLock), - carbonFlags: event.modifierFlags.carbonFlags, - characters: characters, - keyCode: UInt32(event.keyCode) - ) - - Preferences.update(.globalHotkey, value: newGlobalKeybind.toJson()) - - updateKeybindButton(newGlobalKeybind) - buttonClearShortcut.isEnabled = true - - App.shared.shortcutHotkey = HotKey( - keyCombo: KeyCombo( - carbonKeyCode: UInt32(event.keyCode), - carbonModifiers: event.modifierFlags.carbonFlags - ) - ) - } - } - - @IBAction func register(_ sender: Any) { - unregister(nil) - listeningForGlobalHotkey = true - view.window?.makeFirstResponder(nil) - } - - @IBAction func unregister(_ sender: Any?) { - listeningForGlobalHotkey = false - App.shared.shortcutHotkey = nil - buttonSetShortcut.title = "" - - Preferences.update(.globalHotkey, value: nil) - } - - func updateClearButton(_ globalKeybindPreference: GlobalKeybindPreference?) { - if globalKeybindPreference != nil { - buttonClearShortcut.isEnabled = true - } else { - buttonClearShortcut.isEnabled = false - } - } - - func updateKeybindButton(_ globalKeybindPreference: GlobalKeybindPreference) { - buttonSetShortcut.title = globalKeybindPreference.description - } - - @IBAction func pressed(_ sender: Any) { - self.view.window?.windowController?.close() - } - + // MARK: - Deinitialization deinit { diff --git a/phpmon/Domain/Preferences/PrefsWC.swift b/phpmon/Domain/Preferences/PrefsWC.swift index b04199f..a2c69c3 100644 --- a/phpmon/Domain/Preferences/PrefsWC.swift +++ b/phpmon/Domain/Preferences/PrefsWC.swift @@ -33,12 +33,12 @@ class PrefsWC: PMWindowController { super.keyDown(with: event) if let vc = contentViewController as? PrefsVC { - if vc.listeningForGlobalHotkey { + if vc.listeningForHotkeyView != nil { if event.keyCode == Keys.Escape || event.keyCode == Keys.Space { print("A blacklisted key was pressed, canceling listen") - vc.listeningForGlobalHotkey = false + vc.listeningForHotkeyView = nil } else { - vc.updateGlobalShortcut(event) + vc.listeningForHotkeyView!.updateShortcut(event) } } } diff --git a/phpmon/Domain/Preferences/Views/CheckboxPreferenceView.swift b/phpmon/Domain/Preferences/Views/CheckboxPreferenceView.swift new file mode 100644 index 0000000..2736e08 --- /dev/null +++ b/phpmon/Domain/Preferences/Views/CheckboxPreferenceView.swift @@ -0,0 +1,44 @@ +// +// CheckboxPreferenceView.swift +// PHP Monitor +// +// Created by Nico Verbruggen on 17/12/2021. +// Copyright © 2021 Nico Verbruggen. All rights reserved. +// + +import Foundation + +import Foundation +import Cocoa + +class CheckboxPreferenceView: NSView, XibLoadable { + + @IBOutlet weak var labelSection: NSTextField! + @IBOutlet weak var labelDescription: NSTextField! + @IBOutlet weak var buttonCheckbox: NSButton! + + var action: (() -> Void)! + + var preference: PreferenceName! { + didSet { + let shouldDisplay = Preferences.preferences[self.preference] as! Bool == true + self.buttonCheckbox.state = shouldDisplay ? .on : .off + } + } + + static func make(sectionText: String, descriptionText: String, checkboxText: String, preference: PreferenceName, action: @escaping () -> Void) -> NSView { + let view = Self.createFromXib()! + view.labelSection.stringValue = sectionText + view.labelDescription.stringValue = descriptionText + view.buttonCheckbox.title = checkboxText + view.preference = preference + view.action = action + return view + } + + @IBAction func toggled(_ sender: Any) { + Preferences.update(self.preference, value: buttonCheckbox.state == .on) + self.action() + } + +} diff --git a/phpmon/Domain/Preferences/Views/CheckboxPreferenceView.xib b/phpmon/Domain/Preferences/Views/CheckboxPreferenceView.xib new file mode 100644 index 0000000..02aa72b --- /dev/null +++ b/phpmon/Domain/Preferences/Views/CheckboxPreferenceView.xib @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/phpmon/Domain/Preferences/Views/HotkeyPreferenceView.swift b/phpmon/Domain/Preferences/Views/HotkeyPreferenceView.swift new file mode 100644 index 0000000..717be58 --- /dev/null +++ b/phpmon/Domain/Preferences/Views/HotkeyPreferenceView.swift @@ -0,0 +1,97 @@ +// +// HotkeyPreferenceView.swift +// PHP Monitor +// +// Created by Nico Verbruggen on 17/12/2021. +// Copyright © 2021 Nico Verbruggen. All rights reserved. +// + +import Foundation + +import Foundation +import HotKey +import Cocoa + +class HotkeyPreferenceView: NSView, XibLoadable { + + weak var delegate: PrefsVC? + + @IBOutlet weak var labelSection: NSTextField! + @IBOutlet weak var labelDescription: NSTextField! + + @IBOutlet weak var buttonSetShortcut: NSButton! + @IBOutlet weak var buttonClearShortcut: NSButton! + + static func make(sectionText: String, descriptionText: String, _ prefsVC: PrefsVC) -> NSView { + let view = Self.createFromXib()! + view.labelSection.stringValue = sectionText + view.labelDescription.stringValue = descriptionText + view.buttonClearShortcut.title = "prefs.shortcut_clear".localized + view.delegate = prefsVC + view.loadGlobalKeybindFromPreferences() + return view + } + + // MARK: - Shortcut Functionality + + // Adapted from: https://dev.to/mitchartemis/creating-a-global-configurable-shortcut-for-macos-apps-in-swift-25e9 + + func updateShortcut(_ event: NSEvent) { + guard let characters = event.charactersIgnoringModifiers else { return } + + let newGlobalKeybind = GlobalKeybindPreference.init( + function: event.modifierFlags.contains(.function), + control: event.modifierFlags.contains(.control), + command: event.modifierFlags.contains(.command), + shift: event.modifierFlags.contains(.shift), + option: event.modifierFlags.contains(.option), + capsLock: event.modifierFlags.contains(.capsLock), + carbonFlags: event.modifierFlags.carbonFlags, + characters: characters, + keyCode: UInt32(event.keyCode) + ) + + Preferences.update(.globalHotkey, value: newGlobalKeybind.toJson()) + + updateKeybindButton(newGlobalKeybind) + buttonClearShortcut.isEnabled = true + + App.shared.shortcutHotkey = HotKey( + keyCombo: KeyCombo( + carbonKeyCode: UInt32(event.keyCode), + carbonModifiers: event.modifierFlags.carbonFlags + ) + ) + } + + func loadGlobalKeybindFromPreferences() { + let globalKeybind = GlobalKeybindPreference.fromJson(Preferences.preferences[.globalHotkey] as! String?) + + if (globalKeybind != nil) { + updateKeybindButton(globalKeybind!) + } else { + buttonSetShortcut.title = "prefs.shortcut_set".localized + } + + buttonClearShortcut.isEnabled = globalKeybind != nil + } + + func updateKeybindButton(_ globalKeybindPreference: GlobalKeybindPreference) { + buttonSetShortcut.title = globalKeybindPreference.description + } + + @IBAction func register(_ sender: Any) { + unregister(nil) + delegate?.listeningForHotkeyView = self + delegate?.view.window?.makeFirstResponder(nil) + buttonSetShortcut.title = "prefs.shortcut_listening".localized + } + + @IBAction func unregister(_ sender: Any?) { + delegate?.listeningForHotkeyView = nil + App.shared.shortcutHotkey = nil + buttonSetShortcut.title = "prefs.shortcut_set".localized + Preferences.update(.globalHotkey, value: nil) + } + +} diff --git a/phpmon/Domain/Preferences/Views/HotkeyPreferenceView.xib b/phpmon/Domain/Preferences/Views/HotkeyPreferenceView.xib new file mode 100644 index 0000000..08ea47d --- /dev/null +++ b/phpmon/Domain/Preferences/Views/HotkeyPreferenceView.xib @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +