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

♻️ Refactor Preferences & PreferenceName

Also added a few new preferences related to toggling specific menu items
based on your personal choices.

(These new settings still need to be added to the UI.)
This commit is contained in:
2022-09-07 20:31:26 +02:00
parent 588398ea76
commit 4855c14d28
4 changed files with 189 additions and 139 deletions

View File

@ -130,6 +130,8 @@
C44CCD4927AFF3B700CE40E5 /* MainMenu+Async.swift in Sources */ = {isa = PBXBuildFile; fileRef = C44CCD4827AFF3B700CE40E5 /* MainMenu+Async.swift */; };
C44CCD4A27AFF3BC00CE40E5 /* MainMenu+Async.swift in Sources */ = {isa = PBXBuildFile; fileRef = C44CCD4827AFF3B700CE40E5 /* MainMenu+Async.swift */; };
C44F868E2835BD8D005C353A /* phpmon-config.json in Resources */ = {isa = PBXBuildFile; fileRef = C44F868D2835BD8D005C353A /* phpmon-config.json */; };
C450C8C628C919EC002A2B4B /* PreferenceName.swift in Sources */ = {isa = PBXBuildFile; fileRef = C450C8C528C919EC002A2B4B /* PreferenceName.swift */; };
C450C8C728C919EC002A2B4B /* PreferenceName.swift in Sources */ = {isa = PBXBuildFile; fileRef = C450C8C528C919EC002A2B4B /* PreferenceName.swift */; };
C459B4BD27F6093700E9B4B4 /* nginx-proxy.test in Resources */ = {isa = PBXBuildFile; fileRef = C459B4BC27F6093700E9B4B4 /* nginx-proxy.test */; };
C45E76142854A65300B4FE0C /* ServicesManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C45E76132854A65300B4FE0C /* ServicesManager.swift */; };
C45E76152854A65300B4FE0C /* ServicesManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C45E76132854A65300B4FE0C /* ServicesManager.swift */; };
@ -400,6 +402,7 @@
C44CCD3F27AFE2FC00CE40E5 /* AlertableError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertableError.swift; sourceTree = "<group>"; };
C44CCD4827AFF3B700CE40E5 /* MainMenu+Async.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MainMenu+Async.swift"; sourceTree = "<group>"; };
C44F868D2835BD8D005C353A /* phpmon-config.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "phpmon-config.json"; sourceTree = "<group>"; };
C450C8C528C919EC002A2B4B /* PreferenceName.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferenceName.swift; sourceTree = "<group>"; };
C459B4BC27F6093700E9B4B4 /* nginx-proxy.test */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "nginx-proxy.test"; sourceTree = "<group>"; };
C45E76132854A65300B4FE0C /* ServicesManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServicesManager.swift; sourceTree = "<group>"; };
C463E37F284930EE00422731 /* PresetHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PresetHelper.swift; sourceTree = "<group>"; };
@ -520,6 +523,7 @@
C4998F092617633900B2526E /* PreferencesWindowController.swift */,
C4FACE7F288F1C0D00FC478F /* PreferencesWindowController+Hotkey.swift */,
5420395826135DC100FB00FA /* PrefsVC.swift */,
C450C8C528C919EC002A2B4B /* PreferenceName.swift */,
5420395E2613607600FB00FA /* Preferences.swift */,
C4C3ED4227834C5200AB15D8 /* CustomPrefs.swift */,
C4068CA927B0890D00544CD5 /* MenuBarIcons.swift */,
@ -1323,6 +1327,7 @@
C4205A7E27F4D21800191A39 /* ValetProxy.swift in Sources */,
C4C8E818276F54D8003AC782 /* App+ConfigWatch.swift in Sources */,
54FCFD30276C8DA4004CE748 /* HotkeyPreferenceView.swift in Sources */,
C450C8C628C919EC002A2B4B /* PreferenceName.swift in Sources */,
C4E4404627C56F4700D225E1 /* ValetSite.swift in Sources */,
C4F2E43A2752F7D00020E974 /* PhpInstallation.swift in Sources */,
C4D9F24B280B69E100DCD39A /* AddProxyVC.swift in Sources */,
@ -1497,6 +1502,7 @@
C4FC21B128391F8E00D368BB /* MainMenu+Actions.swift in Sources */,
54D9E0B927E4F51E003B9AD9 /* KeyCombo.swift in Sources */,
C4EED88A27A48778006D7272 /* InterAppHandler.swift in Sources */,
C450C8C728C919EC002A2B4B /* PreferenceName.swift in Sources */,
C48D6C75279CD3E400F26D7E /* PhpVersionNumberTest.swift in Sources */,
C485707B28BF458900539B36 /* VersionPopoverView.swift in Sources */,
C485706E28BF451C00539B36 /* OnboardingWindowController.swift in Sources */,

View File

@ -39,3 +39,57 @@ struct CustomPrefs: Decodable {
case environmentVariables = "export"
}
}
extension Preferences {
func loadCustomPreferences() {
// Ensure the configuration directory is created if missing
Shell.run("mkdir -p ~/.config/phpmon")
// Move the legacy file
moveOutdatedConfigurationFile()
// Attempt to load the file if it exists
let url = URL(fileURLWithPath: "\(Paths.homePath)/.config/phpmon/config.json")
if Filesystem.fileExists(url.path) {
Log.info("A custom ~/.config/phpmon/config.json file was found. Attempting to parse...")
loadCustomPreferencesFile(url)
} else {
Log.info("There was no /.config/phpmon/config.json file to be loaded.")
}
}
func moveOutdatedConfigurationFile() {
if Filesystem.fileExists("~/.phpmon.conf.json") && !Filesystem.fileExists("~/.config/phpmon/config.json") {
Log.info("An outdated configuration file was found. Moving it...")
Shell.run("cp ~/.phpmon.conf.json ~/.config/phpmon/config.json")
Log.info("The configuration file was copied successfully!")
}
}
func loadCustomPreferencesFile(_ url: URL) {
do {
customPreferences = try JSONDecoder().decode(
CustomPrefs.self,
from: try! String(contentsOf: url, encoding: .utf8).data(using: .utf8)!
)
Log.info("The ~/.config/phpmon/config.json file was successfully parsed.")
if customPreferences.hasPresets() {
Log.info("There are \(customPreferences.presets!.count) custom presets.")
}
if customPreferences.hasServices() {
Log.info("There are custom services: \(customPreferences.services!)")
}
if customPreferences.hasEnvironmentVariables() {
Log.info("Configuring the additional exports...")
Shell.user.exports = customPreferences.getEnvironmentVariables()
}
} catch {
Log.warn("The ~/.config/phpmon/config.json file seems to be missing or malformed.")
}
}
}

View File

@ -0,0 +1,102 @@
//
// PreferenceName.swift
// PHP Monitor
//
// Created by Nico Verbruggen on 07/09/2022.
// Copyright © 2022 Nico Verbruggen. All rights reserved.
//
/**
These are the keys used for every preference in the app.
*/
enum PreferenceName: String {
// FIRST-TIME LAUNCH
case wasLaunchedBefore = "launched_before"
// 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"
case showPhpDoctorSuggestions = "show_php_doctor_suggestions"
// 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"
// MENU CUSTOMIZATION
case displayVersionSwitcher = "display_version_switcher"
case displayServicesManager = "display_services_manager"
case displayValetConfigFinder = "display_valet_config_finder"
case displayPhpConfigFinder = "display_php_config_finder"
case displayComposerToolkit = "display_composer_toolkit"
case displayLimitsWidget = "display_limits_widget"
case displayExtensions = "display_extensions"
/**
What type of data each preference contains.
*/
static var mapping: [PreferenceType: [PreferenceName]] = [
.boolean: [
// Preferences
.shouldDisplayDynamicIcon,
.fullPhpVersionDynamicIcon,
.autoServiceRestartAfterExtensionToggle,
.autoComposerGlobalUpdateAfterSwitch,
.allowProtocolForIntegrations,
.automaticBackgroundUpdateCheck,
.showPhpDoctorSuggestions,
// Notifications
.notifyAboutVersionChange,
.notifyAboutPhpFpmRestart,
.notifyAboutServices,
.notifyAboutPresets,
.notifyAboutSecureToggle,
.notifyAboutGlobalComposerStatus,
// UI Preferences
.displayVersionSwitcher,
.displayServicesManager,
.displayValetConfigFinder,
.displayPhpConfigFinder,
.displayComposerToolkit,
.displayLimitsWidget,
.displayExtensions
],
.string: [
.globalHotkey,
.iconTypeToDisplay
]
]
}
enum PreferenceType {
case boolean, string
}
/**
These are retired preferences that, if present, should be migrated.
*/
enum RetiredPreferenceName: String {
case shouldDisplayPhpHintInIcon = "add_php_to_icon"
}
/**
These are internal stats. They NEVER get shared.
*/
enum InternalStats: String {
case launchCount = "times_launched"
case switchCount = "times_switched_versions"
case didSeeSponsorEncouragement = "did_see_sponsor_encouragement"
}

View File

@ -8,51 +8,6 @@
import Foundation
/**
These are the keys used for every preference in the app.
*/
enum PreferenceName: String {
// FIRST-TIME LAUNCH
case wasLaunchedBefore = "launched_before"
// 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"
case showPhpDoctorSuggestions = "show_php_doctor_suggestions"
// 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"
}
/**
These are retired preferences that, if present, should be migrated.
*/
enum RetiredPreferenceName: String {
case shouldDisplayPhpHintInIcon = "add_php_to_icon"
}
/**
These are internal stats. They NEVER get shared.
*/
enum InternalStats: String {
case launchCount = "times_launched"
case switchCount = "times_switched_versions"
case didSeeSponsorEncouragement = "did_see_sponsor_encouragement"
}
class Preferences {
// MARK: - Singleton
@ -66,7 +21,12 @@ class Preferences {
public init() {
Preferences.handleFirstTimeLaunch()
cachedPreferences = Self.cache()
customPreferences = CustomPrefs(scanApps: [], presets: [], services: [], environmentVariables: [:])
customPreferences = CustomPrefs(
scanApps: [],
presets: [],
services: [],
environmentVariables: [:]
)
loadCustomPreferences()
}
@ -104,6 +64,15 @@ class Preferences {
PreferenceName.notifyAboutSecureToggle.rawValue: true,
PreferenceName.notifyAboutGlobalComposerStatus.rawValue: true,
/// Preferences: UI Preferences
PreferenceName.displayVersionSwitcher.rawValue: true,
PreferenceName.displayServicesManager.rawValue: true,
PreferenceName.displayValetConfigFinder.rawValue: true,
PreferenceName.displayPhpConfigFinder.rawValue: true,
PreferenceName.displayComposerToolkit.rawValue: true,
PreferenceName.displayLimitsWidget.rawValue: true,
PreferenceName.displayExtensions.rawValue: true,
/// Stats
InternalStats.switchCount.rawValue: 0,
InternalStats.launchCount.rawValue: 0,
@ -160,44 +129,18 @@ class Preferences {
// MARK: - Internal Functionality
private static func cache() -> [PreferenceName: Any] {
return [
// Part 1: Always Booleans
.shouldDisplayDynamicIcon:
UserDefaults.standard.bool(
forKey: PreferenceName.shouldDisplayDynamicIcon.rawValue) as Any,
.fullPhpVersionDynamicIcon: UserDefaults.standard.bool(
forKey: PreferenceName.fullPhpVersionDynamicIcon.rawValue) as Any,
.autoServiceRestartAfterExtensionToggle: UserDefaults.standard.bool(
forKey: PreferenceName.autoServiceRestartAfterExtensionToggle.rawValue) as Any,
.autoComposerGlobalUpdateAfterSwitch: UserDefaults.standard.bool(
forKey: PreferenceName.autoComposerGlobalUpdateAfterSwitch.rawValue) as Any,
.allowProtocolForIntegrations: UserDefaults.standard.bool(
forKey: PreferenceName.allowProtocolForIntegrations.rawValue) as Any,
.automaticBackgroundUpdateCheck: UserDefaults.standard.bool(
forKey: PreferenceName.automaticBackgroundUpdateCheck.rawValue) as Any,
.showPhpDoctorSuggestions: UserDefaults.standard.bool(
forKey: PreferenceName.showPhpDoctorSuggestions.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,
.iconTypeToDisplay: UserDefaults.standard.string(
forKey: PreferenceName.iconTypeToDisplay.rawValue) as Any
]
private static func cache() -> [PreferenceName: Any?] {
return Dictionary(uniqueKeysWithValues: PreferenceName.mapping
.flatMap { (key: PreferenceType, value: [PreferenceName]) in
value.map { preference -> (PreferenceName, Any?) in
return (preference, { () -> Any? in
switch key {
case .boolean: return UserDefaults.standard.bool(forKey: preference.rawValue)
case .string: return UserDefaults.standard.string(forKey: preference.rawValue)
}
}())
}
})
}
static func update(_ preference: PreferenceName, value: Any?) {
@ -211,59 +154,4 @@ class Preferences {
// Update the preferences cache in memory!
Preferences.shared.cachedPreferences = Preferences.cache()
}
// MARK: - Custom Preferences
private func loadCustomPreferences() {
// Ensure the configuration directory is created if missing
Shell.run("mkdir -p ~/.config/phpmon")
// Move the legacy file
moveOutdatedConfigurationFile()
// Attempt to load the file if it exists
let url = URL(fileURLWithPath: "\(Paths.homePath)/.config/phpmon/config.json")
if Filesystem.fileExists(url.path) {
Log.info("A custom ~/.config/phpmon/config.json file was found. Attempting to parse...")
loadCustomPreferencesFile(url)
} else {
Log.info("There was no /.config/phpmon/config.json file to be loaded.")
}
}
private func moveOutdatedConfigurationFile() {
if Filesystem.fileExists("~/.phpmon.conf.json") && !Filesystem.fileExists("~/.config/phpmon/config.json") {
Log.info("An outdated configuration file was found. Moving it...")
Shell.run("cp ~/.phpmon.conf.json ~/.config/phpmon/config.json")
Log.info("The configuration file was copied successfully!")
}
}
private func loadCustomPreferencesFile(_ url: URL) {
do {
customPreferences = try JSONDecoder().decode(
CustomPrefs.self,
from: try! String(contentsOf: url, encoding: .utf8).data(using: .utf8)!
)
Log.info("The ~/.config/phpmon/config.json file was successfully parsed.")
if customPreferences.hasPresets() {
Log.info("There are \(customPreferences.presets!.count) custom presets.")
}
if customPreferences.hasServices() {
Log.info("There are custom services: \(customPreferences.services!)")
}
if customPreferences.hasEnvironmentVariables() {
Log.info("Configuring the additional exports...")
Shell.user.exports = customPreferences.getEnvironmentVariables()
}
} catch {
Log.warn("The ~/.config/phpmon/config.json file seems to be missing or malformed.")
}
}
}