1
0
mirror of https://github.com/nicoverbruggen/phpmon.git synced 2025-08-07 12:00:09 +02:00

👌 Granular notification control

This commit is contained in:
2022-06-05 14:21:08 +02:00
parent 998bbd231a
commit e1880d9dfc
14 changed files with 390 additions and 188 deletions

View File

@ -7,7 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
5420395926135DC100FB00FA /* GeneralPreferencesVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5420395826135DC100FB00FA /* GeneralPreferencesVC.swift */; };
5420395926135DC100FB00FA /* PrefsVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5420395826135DC100FB00FA /* PrefsVC.swift */; };
5420395F2613607600FB00FA /* Preferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5420395E2613607600FB00FA /* Preferences.swift */; };
5489625828312FAD004F647A /* CreatedFromFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5489625728312FAD004F647A /* CreatedFromFile.swift */; };
5489625928313231004F647A /* CreatedFromFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5489625728312FAD004F647A /* CreatedFromFile.swift */; };
@ -143,7 +143,7 @@
C476FF9822B0DD830098105B /* Alert.swift in Sources */ = {isa = PBXBuildFile; fileRef = C476FF9722B0DD830098105B /* Alert.swift */; };
C4811D2422D70A4700B5F6B3 /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4811D2322D70A4700B5F6B3 /* App.swift */; };
C4811D2A22D70F9A00B5F6B3 /* MainMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4811D2922D70F9A00B5F6B3 /* MainMenu.swift */; };
C481F79726164A78004FBCFF /* GeneralPreferencesVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5420395826135DC100FB00FA /* GeneralPreferencesVC.swift */; };
C481F79726164A78004FBCFF /* PrefsVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5420395826135DC100FB00FA /* PrefsVC.swift */; };
C481F79A26164A7C004FBCFF /* Preferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5420395E2613607600FB00FA /* Preferences.swift */; };
C484437B2804BB560041A78A /* ValetProxyScanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = C484437A2804BB560041A78A /* ValetProxyScanner.swift */; };
C484437C2804BB560041A78A /* ValetProxyScanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = C484437A2804BB560041A78A /* ValetProxyScanner.swift */; };
@ -288,7 +288,7 @@
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
5420395826135DC100FB00FA /* GeneralPreferencesVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeneralPreferencesVC.swift; sourceTree = "<group>"; };
5420395826135DC100FB00FA /* PrefsVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrefsVC.swift; sourceTree = "<group>"; };
5420395E2613607600FB00FA /* Preferences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Preferences.swift; sourceTree = "<group>"; };
5489625728312FAD004F647A /* CreatedFromFile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreatedFromFile.swift; sourceTree = "<group>"; };
54A18D3F282A566E000A0D81 /* nginx-secure-proxy-custom-tld.test */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "nginx-secure-proxy-custom-tld.test"; sourceTree = "<group>"; };
@ -474,7 +474,7 @@
isa = PBXGroup;
children = (
C4998F092617633900B2526E /* PrefsWC.swift */,
5420395826135DC100FB00FA /* GeneralPreferencesVC.swift */,
5420395826135DC100FB00FA /* PrefsVC.swift */,
5420395E2613607600FB00FA /* Preferences.swift */,
C4C3ED4227834C5200AB15D8 /* CustomPrefs.swift */,
C4068CA927B0890D00544CD5 /* MenuBarIcons.swift */,
@ -1202,7 +1202,7 @@
C4F8C0A422D4F12C002EFE61 /* DateExtension.swift in Sources */,
C4AF9F7A2754499000D44ED0 /* Valet.swift in Sources */,
C4C0E8EA27F88B80002D32A9 /* ValetProxy+Fake.swift in Sources */,
5420395926135DC100FB00FA /* GeneralPreferencesVC.swift in Sources */,
5420395926135DC100FB00FA /* PrefsVC.swift in Sources */,
C43603A0275E67610028EFC6 /* AppDelegate+Notifications.swift in Sources */,
5489625828312FAD004F647A /* CreatedFromFile.swift in Sources */,
C4068CA727B07A1300544CD5 /* SelectPreferenceView.swift in Sources */,
@ -1368,7 +1368,7 @@
C4D936CB27E3EE4A00BD69FE /* DomainListCellProtocol.swift in Sources */,
C4B97B76275CF08C003F3378 /* AppDelegate+MenuOutlets.swift in Sources */,
C4F780CD25D80B75000DBC97 /* Alert.swift in Sources */,
C481F79726164A78004FBCFF /* GeneralPreferencesVC.swift in Sources */,
C481F79726164A78004FBCFF /* PrefsVC.swift in Sources */,
C41E871B2763D42300161EE0 /* DomainListVC+ContextMenu.swift in Sources */,
C40C7F3127722E8D00DDDCDC /* Logger.swift in Sources */,
C4068CAB27B0890D00544CD5 /* MenuBarIcons.swift in Sources */,

View File

@ -10,7 +10,11 @@ import UserNotifications
class LocalNotification {
public static func send(title: String, subtitle: String) {
public static func send(title: String, subtitle: String, preference: PreferenceName) {
if !Preferences.isEnabled(preference) {
return
}
let content = UNMutableNotificationContent()
content.title = title
content.body = subtitle

View File

@ -378,7 +378,7 @@
</viewController>
<customObject id="eQC-8B-FkX" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="835" y="-28"/>
<point key="canvasLocation" x="844" y="-153"/>
</scene>
<!--Tab View Controller-->
<scene sceneID="B5x-d3-c7D">

View File

@ -69,7 +69,8 @@ extension DomainListVC {
.localized(
"\(selectedSite.name).\(Valet.shared.config.tld)",
newState
)
),
preference: .notifyAboutSecureToggle
)
}

View File

@ -83,7 +83,8 @@ class ComposerWindow {
if shouldNotify {
LocalNotification.send(
title: "alert.composer_success.title".localized,
subtitle: "alert.composer_success.info".localized
subtitle: "alert.composer_success.info".localized,
preference: .notifyAboutGlobalComposerStatus
)
}
window = nil

View File

@ -56,7 +56,8 @@ extension MainMenu {
DispatchQueue.main.async {
LocalNotification.send(
title: "notification.services_restarted".localized,
subtitle: "notification.services_restarted_desc".localized
subtitle: "notification.services_restarted_desc".localized,
preference: .notifyAboutServices
)
}
}
@ -69,7 +70,8 @@ extension MainMenu {
DispatchQueue.main.async {
LocalNotification.send(
title: "notification.services_stopped".localized,
subtitle: "notification.services_stopped_desc".localized
subtitle: "notification.services_stopped_desc".localized,
preference: .notifyAboutServices
)
}
}
@ -165,8 +167,8 @@ extension MainMenu {
)
)
.withPrimary(text: "alert.revert_description.ok".localized, action: { alert in
self.performRollback()
alert.close(with: .OK)
self.performRollback()
})
.withSecondary(text: "alert.revert_description.cancel".localized)
.show()

View File

@ -77,7 +77,8 @@ extension MainMenu {
private func notifyAboutVersionChange(to version: String) {
LocalNotification.send(
title: String(format: "notification.version_changed_title".localized, version),
subtitle: String(format: "notification.version_changed_desc".localized, version)
subtitle: String(format: "notification.version_changed_desc".localized, version),
preference: .notifyAboutVersionChange
)
PhpEnv.phpInstall.notifyAboutBrokenPhpFpm()

View File

@ -1,156 +0,0 @@
//
// GeneralPreferencesVC.swift
// PHP Monitor
//
// Created by Nico Verbruggen on 30/03/2021.
// Copyright © 2022 Nico Verbruggen. All rights reserved.
//
import Cocoa
import Carbon
class GenericPreferenceVC: NSViewController {
// MARK: - Content
@IBOutlet weak var stackView: NSStackView!
var views: [NSView] = []
override func viewDidLoad() {
super.viewDidLoad()
self.views.forEach({ self.stackView.addArrangedSubview($0) })
}
// MARK: - Deinitialization
deinit {
Log.perf("PrefsVC deallocated")
}
}
class GeneralPreferencesVC: GenericPreferenceVC {
// MARK: - Icon and title
var icon: String = "gear"
// MARK: - Lifecycle
public static func fromStoryboard() -> GenericPreferenceVC {
let vc = NSStoryboard(name: "Main", bundle: nil)
.instantiateController(withIdentifier: "preferencesTemplateVC") as! GenericPreferenceVC
vc.views = [
getDynamicIconPreferenceView(),
getIconOptionsPreferenceView(),
getIconDensityPreferenceView(),
getAutoRestartPreferenceView(),
getAutomaticComposerUpdatePreferenceView(),
// getShortcutPreferenceView(),
getIntegrationsPreferenceView(),
getAutomaticUpdateCheckPreferenceView()
]
return vc
}
private static func getDynamicIconPreferenceView() -> NSView {
return 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()
}
)
}
private static func getIconOptionsPreferenceView() -> NSView {
return SelectPreferenceView.make(
sectionText: "",
descriptionText: "prefs.icon_options_desc".localized,
options: MenuBarIcon.allCases.map({ return $0.rawValue }),
localizationPrefix: "prefs.icon_options",
preference: .iconTypeToDisplay,
action: {
MainMenu.shared.refreshIcon()
}
)
}
private static func getIconDensityPreferenceView() -> NSView {
return CheckboxPreferenceView.make(
sectionText: "prefs.info_density".localized,
descriptionText: "prefs.display_full_php_version_desc".localized,
checkboxText: "prefs.display_full_php_version".localized,
preference: .fullPhpVersionDynamicIcon,
action: {
MainMenu.shared.refreshIcon()
MainMenu.shared.rebuild()
}
)
}
private static func getAutoRestartPreferenceView() -> NSView {
return CheckboxPreferenceView.make(
sectionText: "prefs.services".localized,
descriptionText: "prefs.auto_restart_services_desc".localized,
checkboxText: "prefs.auto_restart_services_title".localized,
preference: .autoServiceRestartAfterExtensionToggle,
action: {}
)
}
private static func getAutomaticComposerUpdatePreferenceView() -> NSView {
CheckboxPreferenceView.make(
sectionText: "prefs.switcher".localized,
descriptionText: "prefs.auto_composer_update_desc".localized,
checkboxText: "prefs.auto_composer_update_title".localized,
preference: .autoComposerGlobalUpdateAfterSwitch,
action: {}
)
}
/*
private static func getShortcutPreferenceView() -> NSView {
return HotkeyPreferenceView.make(
sectionText: "prefs.global_shortcut".localized,
descriptionText: "prefs.shortcut_desc".localized,
self
)
}
*/
private static func getIntegrationsPreferenceView() -> NSView {
return CheckboxPreferenceView.make(
sectionText: "prefs.integrations".localized,
descriptionText: "prefs.open_protocol_desc".localized,
checkboxText: "prefs.open_protocol_title".localized,
preference: .allowProtocolForIntegrations,
action: {}
)
}
private static func getAutomaticUpdateCheckPreferenceView() -> NSView {
return CheckboxPreferenceView.make(
sectionText: "prefs.updates".localized,
descriptionText: "prefs.automatic_update_check_desc".localized,
checkboxText: "prefs.automatic_update_check_title".localized,
preference: .automaticBackgroundUpdateCheck,
action: {}
)
}
// MARK: - Listening for hotkey delegate
var listeningForHotkeyView: HotkeyPreferenceView?
override func viewWillDisappear() {
if listeningForHotkeyView !== nil {
listeningForHotkeyView = nil
}
}
}

View File

@ -12,15 +12,28 @@ import Foundation
These are the keys used for every preference in the app.
*/
enum PreferenceName: String {
// FIRST-TIME LAUNCH
case wasLaunchedBefore = "launched_before"
case shouldDisplayDynamicIcon = "use_dynamic_icon"
case iconTypeToDisplay = "icon_type_to_display"
case fullPhpVersionDynamicIcon = "full_php_in_menu_bar"
// GENERAL
case autoServiceRestartAfterExtensionToggle = "auto_restart_after_extension_toggle"
case autoComposerGlobalUpdateAfterSwitch = "auto_composer_global_update_after_switch"
case allowProtocolForIntegrations = "allow_protocol_for_integrations"
case globalHotkey = "global_hotkey"
case automaticBackgroundUpdateCheck = "backgroundUpdateCheck"
// APPEARANCE
case shouldDisplayDynamicIcon = "use_dynamic_icon"
case iconTypeToDisplay = "icon_type_to_display"
case fullPhpVersionDynamicIcon = "full_php_in_menu_bar"
// NOTIFICATIONS
case notifyAboutVersionChange = "notify_about_version_change"
case notifyAboutPhpFpmRestart = "notify_about_php_fpm_restart"
case notifyAboutServices = "notify_about_services_restart"
case notifyAboutPresets = "notify_about_presets"
case notifyAboutSecureToggle = "notify_about_secure_toggle"
case notifyAboutGlobalComposerStatus = "notify_about_composer_status"
}
/**
@ -70,14 +83,25 @@ class Preferences {
*/
static func handleFirstTimeLaunch() {
UserDefaults.standard.register(defaults: [
/// Preferences
PreferenceName.shouldDisplayDynamicIcon.rawValue: true,
PreferenceName.iconTypeToDisplay.rawValue: MenuBarIcon.iconPhp.rawValue,
PreferenceName.fullPhpVersionDynamicIcon.rawValue: false,
/// Preferences: General
PreferenceName.autoServiceRestartAfterExtensionToggle.rawValue: true,
PreferenceName.autoComposerGlobalUpdateAfterSwitch.rawValue: false,
PreferenceName.allowProtocolForIntegrations.rawValue: true,
PreferenceName.automaticBackgroundUpdateCheck.rawValue: true,
/// Preferences: Appearance
PreferenceName.shouldDisplayDynamicIcon.rawValue: true,
PreferenceName.iconTypeToDisplay.rawValue: MenuBarIcon.iconPhp.rawValue,
PreferenceName.fullPhpVersionDynamicIcon.rawValue: false,
/// Preferences: Notifications
PreferenceName.notifyAboutVersionChange.rawValue: true,
PreferenceName.notifyAboutPhpFpmRestart.rawValue: true,
PreferenceName.notifyAboutServices.rawValue: true,
PreferenceName.notifyAboutPresets.rawValue: true,
PreferenceName.notifyAboutSecureToggle.rawValue: true,
PreferenceName.notifyAboutGlobalComposerStatus.rawValue: true,
/// Stats
InternalStats.switchCount.rawValue: 0,
InternalStats.launchCount.rawValue: 0,
@ -137,7 +161,8 @@ class Preferences {
private static func cache() -> [PreferenceName: Any] {
return [
// Part 1: Always Booleans
.shouldDisplayDynamicIcon: UserDefaults.standard.bool(
.shouldDisplayDynamicIcon:
UserDefaults.standard.bool(
forKey: PreferenceName.shouldDisplayDynamicIcon.rawValue) as Any,
.fullPhpVersionDynamicIcon: UserDefaults.standard.bool(
forKey: PreferenceName.fullPhpVersionDynamicIcon.rawValue) as Any,
@ -150,6 +175,19 @@ class Preferences {
.automaticBackgroundUpdateCheck: UserDefaults.standard.bool(
forKey: PreferenceName.automaticBackgroundUpdateCheck.rawValue) as Any,
.notifyAboutVersionChange: UserDefaults.standard.bool(
forKey: PreferenceName.notifyAboutVersionChange.rawValue) as Any,
.notifyAboutPhpFpmRestart: UserDefaults.standard.bool(
forKey: PreferenceName.notifyAboutPhpFpmRestart.rawValue) as Any,
.notifyAboutServices: UserDefaults.standard.bool(
forKey: PreferenceName.notifyAboutServices.rawValue) as Any,
.notifyAboutPresets: UserDefaults.standard.bool(
forKey: PreferenceName.notifyAboutPresets.rawValue) as Any,
.notifyAboutSecureToggle: UserDefaults.standard.bool(
forKey: PreferenceName.notifyAboutSecureToggle.rawValue) as Any,
.notifyAboutGlobalComposerStatus: UserDefaults.standard.bool(
forKey: PreferenceName.notifyAboutGlobalComposerStatus.rawValue) as Any,
// Part 2: Always Strings
.globalHotkey: UserDefaults.standard.string(
forKey: PreferenceName.globalHotkey.rawValue) as Any,

View File

@ -0,0 +1,244 @@
//
// PrefsVC.swift
// PHP Monitor
//
// Created by Nico Verbruggen on 30/03/2021.
// Copyright © 2022 Nico Verbruggen. All rights reserved.
//
import Cocoa
import Carbon
class GenericPreferenceVC: NSViewController {
// MARK: - Content
@IBOutlet weak var stackView: NSStackView!
var views: [NSView] = []
override func viewDidLoad() {
super.viewDidLoad()
self.views.forEach({ self.stackView.addArrangedSubview($0) })
}
// MARK: - Deinitialization
deinit {
Log.perf("PrefsVC deallocated")
}
func getDynamicIconPV() -> NSView {
return 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()
}
)
}
func getIconOptionsPV() -> NSView {
return SelectPreferenceView.make(
sectionText: "",
descriptionText: "prefs.icon_options_desc".localized,
options: MenuBarIcon.allCases.map({ return $0.rawValue }),
localizationPrefix: "prefs.icon_options",
preference: .iconTypeToDisplay,
action: {
MainMenu.shared.refreshIcon()
}
)
}
func getIconDensityPV() -> NSView {
return CheckboxPreferenceView.make(
sectionText: "prefs.info_density".localized,
descriptionText: "prefs.display_full_php_version_desc".localized,
checkboxText: "prefs.display_full_php_version".localized,
preference: .fullPhpVersionDynamicIcon,
action: {
MainMenu.shared.refreshIcon()
MainMenu.shared.rebuild()
}
)
}
func getAutoRestartPV() -> NSView {
return CheckboxPreferenceView.make(
sectionText: "prefs.services".localized,
descriptionText: "prefs.auto_restart_services_desc".localized,
checkboxText: "prefs.auto_restart_services_title".localized,
preference: .autoServiceRestartAfterExtensionToggle,
action: {}
)
}
func getAutomaticComposerUpdatePV() -> NSView {
CheckboxPreferenceView.make(
sectionText: "prefs.switcher".localized,
descriptionText: "prefs.auto_composer_update_desc".localized,
checkboxText: "prefs.auto_composer_update_title".localized,
preference: .autoComposerGlobalUpdateAfterSwitch,
action: {}
)
}
func getShortcutPV() -> NSView {
return HotkeyPreferenceView.make(
sectionText: "prefs.global_shortcut".localized,
descriptionText: "prefs.shortcut_desc".localized,
self
)
}
func getIntegrationsPV() -> NSView {
return CheckboxPreferenceView.make(
sectionText: "prefs.integrations".localized,
descriptionText: "prefs.open_protocol_desc".localized,
checkboxText: "prefs.open_protocol_title".localized,
preference: .allowProtocolForIntegrations,
action: {}
)
}
func getAutomaticUpdateCheckPV() -> NSView {
return CheckboxPreferenceView.make(
sectionText: "prefs.updates".localized,
descriptionText: "prefs.automatic_update_check_desc".localized,
checkboxText: "prefs.automatic_update_check_title".localized,
preference: .automaticBackgroundUpdateCheck,
action: {}
)
}
func getNotifyAboutVersionChangePV() -> NSView {
return CheckboxPreferenceView.make(
sectionText: "prefs.notifications".localized,
descriptionText: "prefs.notify_about_version_change_desc".localized,
checkboxText: "prefs.notify_about_version_change".localized,
preference: .notifyAboutVersionChange,
action: {}
)
}
func getNotifyAboutPhpFpmChangePV() -> NSView {
return CheckboxPreferenceView.make(
sectionText: "",
descriptionText: "prefs.notify_about_php_fpm_change_desc".localized,
checkboxText: "prefs.notify_about_php_fpm_change".localized,
preference: .notifyAboutPhpFpmRestart,
action: {}
)
}
func getNotifyAboutServicesPV() -> NSView {
return CheckboxPreferenceView.make(
sectionText: "",
descriptionText: "prefs.notify_about_services_desc".localized,
checkboxText: "prefs.notify_about_services".localized,
preference: .notifyAboutServices,
action: {}
)
}
func getNotifyAboutPresetsPV() -> NSView {
return CheckboxPreferenceView.make(
sectionText: "",
descriptionText: "prefs.notify_about_presets_desc".localized,
checkboxText: "prefs.notify_about_presets".localized,
preference: .notifyAboutPresets,
action: {}
)
}
func getNotifyAboutSecureTogglePV() -> NSView {
return CheckboxPreferenceView.make(
sectionText: "",
descriptionText: "prefs.notify_about_secure_status_desc".localized,
checkboxText: "prefs.notify_about_secure_status".localized,
preference: .notifyAboutSecureToggle,
action: {}
)
}
func getNotifyAboutGlobalComposerStatusPV() -> NSView {
return CheckboxPreferenceView.make(
sectionText: "",
descriptionText: "prefs.notify_about_composer_success_desc".localized,
checkboxText: "prefs.notify_about_composer_success".localized,
preference: .notifyAboutGlobalComposerStatus,
action: {}
)
}
// MARK: - Listening for hotkey delegate
var listeningForHotkeyView: HotkeyPreferenceView?
override func viewWillDisappear() {
if listeningForHotkeyView !== nil {
listeningForHotkeyView = nil
}
}
}
class GeneralPreferencesVC: GenericPreferenceVC {
// MARK: - Lifecycle
public static func fromStoryboard() -> GenericPreferenceVC {
let vc = NSStoryboard(name: "Main", bundle: nil)
.instantiateController(withIdentifier: "preferencesTemplateVC") as! GenericPreferenceVC
vc.views = [
vc.getAutoRestartPV(),
vc.getAutomaticComposerUpdatePV(),
vc.getShortcutPV(),
vc.getIntegrationsPV(),
vc.getAutomaticUpdateCheckPV()
]
return vc
}
}
class NotificationPreferencesVC: GenericPreferenceVC {
public static func fromStoryboard() -> GenericPreferenceVC {
let vc = NSStoryboard(name: "Main", bundle: nil)
.instantiateController(withIdentifier: "preferencesTemplateVC") as! GenericPreferenceVC
vc.views = [
vc.getNotifyAboutVersionChangePV(),
vc.getNotifyAboutPresetsPV(),
vc.getNotifyAboutSecureTogglePV(),
vc.getNotifyAboutGlobalComposerStatusPV(),
vc.getNotifyAboutServicesPV(),
vc.getNotifyAboutPhpFpmChangePV()
]
return vc
}
}
class AppearancePreferencesVC: GenericPreferenceVC {
// MARK: - Lifecycle
public static func fromStoryboard() -> GenericPreferenceVC {
let vc = NSStoryboard(name: "Main", bundle: nil)
.instantiateController(withIdentifier: "preferencesTemplateVC") as! GenericPreferenceVC
vc.views = [
vc.getDynamicIconPV(),
vc.getIconOptionsPV(),
vc.getIconDensityPV()
]
return vc
}
}

View File

@ -38,6 +38,8 @@ class PrefsWC: PMWindowController {
}
public static func show(delegate: NSWindowDelegate? = nil) {
var justCreated = false
if App.shared.preferencesWindowController == nil {
Self.create(delegate: delegate)
@ -60,9 +62,16 @@ class PrefsWC: PMWindowController {
width: tabVC.view.frame.size.width,
height: tabVC.view.frame.size.height
)
justCreated = true
}
App.shared.preferencesWindowController?.showWindow(self)
if justCreated {
App.shared.preferencesWindowController?.positionWindowInTopLeftCorner()
}
NSApp.activate(ignoringOtherApps: true)
}
@ -77,7 +86,17 @@ class PrefsWC: PMWindowController {
PrefTabView(
viewController: GeneralPreferencesVC.fromStoryboard(),
label: "General",
icon: "gear"
icon: "gearshape"
),
PrefTabView(
viewController: AppearancePreferencesVC.fromStoryboard(),
label: "Appearance",
icon: "paintbrush"
),
PrefTabView(
viewController: NotificationPreferencesVC.fromStoryboard(),
label: "Notifications",
icon: "bell.badge"
)
]
}()
@ -87,18 +106,24 @@ class PrefsWC: PMWindowController {
override func keyDown(with event: NSEvent) {
super.keyDown(with: event)
/*
if let vc = contentViewController as? PrefsVC {
guard let tabVC = self.contentViewController as? NSTabViewController else {
return
}
guard let selected = tabVC.tabViewItems[tabVC.selectedTabViewItemIndex].viewController else {
return
}
if let vc = selected as? GenericPreferenceVC {
if vc.listeningForHotkeyView != nil {
if event.keyCode == Keys.Escape || event.keyCode == Keys.Space {
Log.info("A blacklisted key was pressed, canceling listen!")
vc.listeningForHotkeyView = nil
vc.listeningForHotkeyView!.unregister(nil)
} else {
vc.listeningForHotkeyView!.updateShortcut(event)
}
}
}
*/
}
}

View File

@ -11,8 +11,7 @@ import Cocoa
class HotkeyPreferenceView: NSView, XibLoadable {
#warning("Refactor so this applies to any given preferences VC")
weak var delegate: GeneralPreferencesVC?
weak var delegate: GenericPreferenceVC?
@IBOutlet weak var labelSection: NSTextField!
@IBOutlet weak var labelDescription: NSTextField!
@ -20,7 +19,7 @@ class HotkeyPreferenceView: NSView, XibLoadable {
@IBOutlet weak var buttonSetShortcut: NSButton!
@IBOutlet weak var buttonClearShortcut: NSButton!
static func make(sectionText: String, descriptionText: String, _ prefsVC: GeneralPreferencesVC) -> NSView {
static func make(sectionText: String, descriptionText: String, _ prefsVC: GenericPreferenceVC) -> NSView {
let view = Self.createFromXib()!
view.labelSection.stringValue = sectionText
view.labelDescription.stringValue = descriptionText

View File

@ -8,7 +8,7 @@
import Foundation
struct Preset: Codable {
struct Preset: Codable, Equatable {
let name: String
let version: String?
let extensions: [String: Bool]
@ -69,6 +69,9 @@ struct Preset: Codable {
*/
public func apply() {
Task {
// Was this a rollback?
let wasRollback = (self.name == "AutomaticRevertSnapshot")
// Save the preset that would revert this preset
self.persistRevert()
@ -101,6 +104,21 @@ struct Preset: Codable {
// Restart PHP FPM process (also reloads menu, which will show the preset rollback)
Actions.restartPhpFpm()
// Show the correct notification
if wasRollback {
LocalNotification.send(
title: "notification.preset_reverted_title".localized,
subtitle: "notification.preset_reverted_desc".localized,
preference: .notifyAboutPresets
)
} else {
LocalNotification.send(
title: "notification.preset_applied_title".localized,
subtitle: "notification.preset_applied_desc".localized(self.name),
preference: .notifyAboutPresets
)
}
}
}
@ -178,7 +196,7 @@ struct Preset: Codable {
public var revertSnapshot: Preset {
return Preset(
name: "Revert",
name: "AutomaticRevertSnapshot",
version: diffVersion(),
extensions: diffExtensions(),
configuration: diffConfiguration()

View File

@ -193,6 +193,7 @@
"prefs.switcher" = "Switcher:";
"prefs.integrations" = "Integrations:";
"prefs.updates" = "Updates:";
"prefs.notifications" = "Notifications:";
"prefs.icon_options.php" = "Display PHP Icon";
"prefs.icon_options.elephant" = "Display Elephant Icon";
@ -223,6 +224,24 @@
"prefs.shortcut_clear" = "Clear";
"prefs.shortcut_desc" = "If a shortcut combination is set up, you can toggle PHP Monitor wherever you are by pressing the key combination you chose. (Cancel choosing a shortcut by pressing the spacebar.)";
"prefs.notify_about_version_change_desc" = "Displays a notification whenever the active PHP version changes.";
"prefs.notify_about_version_change" = "Notify about PHP version switch";
"prefs.notify_about_php_fpm_change_desc" = "Displays a notification whenever the active PHP-FPM process has restarted due to a configuration change.";
"prefs.notify_about_php_fpm_change" = "Notify about PHP-FPM restart";
"prefs.notify_about_services_desc" = "Displays a notification whenever any of the Homebrew services (installed and configured by Valet) have been restarted or stopped.";
"prefs.notify_about_services" = "Notify about services status";
"prefs.notify_about_presets_desc" = "Displays a notification whenever a preset has been successfully applied or reverted.";
"prefs.notify_about_presets" = "Notify about applied presets";
"prefs.notify_about_secure_status_desc" = "Displays a notification when a domain has been secured or unsecured.";
"prefs.notify_about_secure_status" = "Notify about secure/unsecure status";
"prefs.notify_about_composer_success_desc" = "Displays a notification when the global composer configuration was successfully updated.";
"prefs.notify_about_composer_success" = "Notify about global composer update";
// NOTIFICATIONS
"notification.version_changed_title" = "PHP %@ now active";
@ -237,6 +256,12 @@
"notification.services_restarted" = "Valet services restarted";
"notification.services_restarted_desc" = "All services have been successfully restarted.";
"notification.preset_applied_title" = "Preset applied";
"notification.preset_applied_desc" = "The preset '%@' has been successfully applied.";
"notification.preset_reverted_title" = "Preset reverted";
"notification.preset_reverted_desc" = "The last preset you applied has been undone. Your previous configuration is now active.";
// Composer Update
"alert.composer_missing.title" = "Composer not found!";
"alert.composer_missing.subtitle" = "PHP Monitor could not find Composer. Make sure that Composer is installed and try again.";