mirror of
https://github.com/nicoverbruggen/phpmon.git
synced 2025-08-08 04:20:07 +02:00
♻️ Cleanup and comments
This commit is contained in:
@ -59,6 +59,12 @@
|
|||||||
C4AF9F7A2754499000D44ED0 /* Valet.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4AF9F792754499000D44ED0 /* Valet.swift */; };
|
C4AF9F7A2754499000D44ED0 /* Valet.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4AF9F792754499000D44ED0 /* Valet.swift */; };
|
||||||
C4AF9F7B2754499000D44ED0 /* Valet.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4AF9F792754499000D44ED0 /* Valet.swift */; };
|
C4AF9F7B2754499000D44ED0 /* Valet.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4AF9F792754499000D44ED0 /* Valet.swift */; };
|
||||||
C4AF9F7D275454A900D44ED0 /* ValetTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4AF9F7C275454A900D44ED0 /* ValetTest.swift */; };
|
C4AF9F7D275454A900D44ED0 /* ValetTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4AF9F7C275454A900D44ED0 /* ValetTest.swift */; };
|
||||||
|
C4B97B75275CF08C003F3378 /* AppDelegate+MenuOutlets.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4B97B74275CF08C003F3378 /* AppDelegate+MenuOutlets.swift */; };
|
||||||
|
C4B97B76275CF08C003F3378 /* AppDelegate+MenuOutlets.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4B97B74275CF08C003F3378 /* AppDelegate+MenuOutlets.swift */; };
|
||||||
|
C4B97B78275CF1B5003F3378 /* App+ActivationPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4B97B77275CF1B5003F3378 /* App+ActivationPolicy.swift */; };
|
||||||
|
C4B97B79275CF1B5003F3378 /* App+ActivationPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4B97B77275CF1B5003F3378 /* App+ActivationPolicy.swift */; };
|
||||||
|
C4B97B7B275CF20A003F3378 /* App+GlobalHotkey.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4B97B7A275CF20A003F3378 /* App+GlobalHotkey.swift */; };
|
||||||
|
C4B97B7C275CF20A003F3378 /* App+GlobalHotkey.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4B97B7A275CF20A003F3378 /* App+GlobalHotkey.swift */; };
|
||||||
C4CCBA6C275C567B008C7055 /* PMWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4CCBA6B275C567B008C7055 /* PMWindowController.swift */; };
|
C4CCBA6C275C567B008C7055 /* PMWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4CCBA6B275C567B008C7055 /* PMWindowController.swift */; };
|
||||||
C4CCBA6D275C567B008C7055 /* PMWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4CCBA6B275C567B008C7055 /* PMWindowController.swift */; };
|
C4CCBA6D275C567B008C7055 /* PMWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4CCBA6B275C567B008C7055 /* PMWindowController.swift */; };
|
||||||
C4D8016622B1584700C6DA1B /* Startup.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D8016522B1584700C6DA1B /* Startup.swift */; };
|
C4D8016622B1584700C6DA1B /* Startup.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D8016522B1584700C6DA1B /* Startup.swift */; };
|
||||||
@ -150,6 +156,9 @@
|
|||||||
C4AF9F76275447F100D44ED0 /* ValetConfigParserTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ValetConfigParserTest.swift; sourceTree = "<group>"; };
|
C4AF9F76275447F100D44ED0 /* ValetConfigParserTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ValetConfigParserTest.swift; sourceTree = "<group>"; };
|
||||||
C4AF9F792754499000D44ED0 /* Valet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Valet.swift; sourceTree = "<group>"; };
|
C4AF9F792754499000D44ED0 /* Valet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Valet.swift; sourceTree = "<group>"; };
|
||||||
C4AF9F7C275454A900D44ED0 /* ValetTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ValetTest.swift; sourceTree = "<group>"; };
|
C4AF9F7C275454A900D44ED0 /* ValetTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ValetTest.swift; sourceTree = "<group>"; };
|
||||||
|
C4B97B74275CF08C003F3378 /* AppDelegate+MenuOutlets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppDelegate+MenuOutlets.swift"; sourceTree = "<group>"; };
|
||||||
|
C4B97B77275CF1B5003F3378 /* App+ActivationPolicy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "App+ActivationPolicy.swift"; sourceTree = "<group>"; };
|
||||||
|
C4B97B7A275CF20A003F3378 /* App+GlobalHotkey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "App+GlobalHotkey.swift"; sourceTree = "<group>"; };
|
||||||
C4CCBA6B275C567B008C7055 /* PMWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PMWindowController.swift; sourceTree = "<group>"; };
|
C4CCBA6B275C567B008C7055 /* PMWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PMWindowController.swift; sourceTree = "<group>"; };
|
||||||
C4D8016522B1584700C6DA1B /* Startup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Startup.swift; sourceTree = "<group>"; };
|
C4D8016522B1584700C6DA1B /* Startup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Startup.swift; sourceTree = "<group>"; };
|
||||||
C4E713562570150F00007428 /* SECURITY.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = SECURITY.md; sourceTree = "<group>"; };
|
C4E713562570150F00007428 /* SECURITY.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = SECURITY.md; sourceTree = "<group>"; };
|
||||||
@ -242,7 +251,6 @@
|
|||||||
C41C1B3522B0097F00E7CF16 /* phpmon */ = {
|
C41C1B3522B0097F00E7CF16 /* phpmon */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
C41C1B3622B0097F00E7CF16 /* AppDelegate.swift */,
|
|
||||||
C4EE188322D3386B00E126E5 /* Constants.swift */,
|
C4EE188322D3386B00E126E5 /* Constants.swift */,
|
||||||
C41E181722CB61EB0072CF09 /* Domain */,
|
C41E181722CB61EB0072CF09 /* Domain */,
|
||||||
C41C1B3F22B0098000E7CF16 /* Info.plist */,
|
C41C1B3F22B0098000E7CF16 /* Info.plist */,
|
||||||
@ -342,8 +350,12 @@
|
|||||||
C4B13B1D25C4915000548C3A /* Core */ = {
|
C4B13B1D25C4915000548C3A /* Core */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
C41C1B3622B0097F00E7CF16 /* AppDelegate.swift */,
|
||||||
|
C4B97B74275CF08C003F3378 /* AppDelegate+MenuOutlets.swift */,
|
||||||
C41C1B3C22B0098000E7CF16 /* Main.storyboard */,
|
C41C1B3C22B0098000E7CF16 /* Main.storyboard */,
|
||||||
C4811D2322D70A4700B5F6B3 /* App.swift */,
|
C4811D2322D70A4700B5F6B3 /* App.swift */,
|
||||||
|
C4B97B77275CF1B5003F3378 /* App+ActivationPolicy.swift */,
|
||||||
|
C4B97B7A275CF20A003F3378 /* App+GlobalHotkey.swift */,
|
||||||
C4D8016522B1584700C6DA1B /* Startup.swift */,
|
C4D8016522B1584700C6DA1B /* Startup.swift */,
|
||||||
C41C1B4C22B0215A00E7CF16 /* Actions.swift */,
|
C41C1B4C22B0215A00E7CF16 /* Actions.swift */,
|
||||||
);
|
);
|
||||||
@ -519,6 +531,7 @@
|
|||||||
C4CCBA6C275C567B008C7055 /* PMWindowController.swift in Sources */,
|
C4CCBA6C275C567B008C7055 /* PMWindowController.swift in Sources */,
|
||||||
C41CD0292628D8EE0065BBED /* GlobalKeybindPreference.swift in Sources */,
|
C41CD0292628D8EE0065BBED /* GlobalKeybindPreference.swift in Sources */,
|
||||||
C42295DD2358D02000E263B2 /* Command.swift in Sources */,
|
C42295DD2358D02000E263B2 /* Command.swift in Sources */,
|
||||||
|
C4B97B78275CF1B5003F3378 /* App+ActivationPolicy.swift in Sources */,
|
||||||
C4811D2422D70A4700B5F6B3 /* App.swift in Sources */,
|
C4811D2422D70A4700B5F6B3 /* App.swift in Sources */,
|
||||||
C41C1B4922B00A9800E7CF16 /* MenuBarImageGenerator.swift in Sources */,
|
C41C1B4922B00A9800E7CF16 /* MenuBarImageGenerator.swift in Sources */,
|
||||||
5420395F2613607600FB00FA /* Preferences.swift in Sources */,
|
5420395F2613607600FB00FA /* Preferences.swift in Sources */,
|
||||||
@ -530,11 +543,13 @@
|
|||||||
C464ADAF275A7A69003FCD53 /* SiteListVC.swift in Sources */,
|
C464ADAF275A7A69003FCD53 /* SiteListVC.swift in Sources */,
|
||||||
C41C1B4B22B019FF00E7CF16 /* ActivePhpInstallation.swift in Sources */,
|
C41C1B4B22B019FF00E7CF16 /* ActivePhpInstallation.swift in Sources */,
|
||||||
C49EAB46259FC305007F6C3B /* Paths.swift in Sources */,
|
C49EAB46259FC305007F6C3B /* Paths.swift in Sources */,
|
||||||
|
C4B97B7B275CF20A003F3378 /* App+GlobalHotkey.swift in Sources */,
|
||||||
C476FF9822B0DD830098105B /* Alert.swift in Sources */,
|
C476FF9822B0DD830098105B /* Alert.swift in Sources */,
|
||||||
C474B00624C0E98C00066A22 /* LocalNotification.swift in Sources */,
|
C474B00624C0E98C00066A22 /* LocalNotification.swift in Sources */,
|
||||||
C48D0C9625CC80B100CC7490 /* HeaderView.swift in Sources */,
|
C48D0C9625CC80B100CC7490 /* HeaderView.swift in Sources */,
|
||||||
C47331A2247093B7009A0597 /* StatusMenu.swift in Sources */,
|
C47331A2247093B7009A0597 /* StatusMenu.swift in Sources */,
|
||||||
C46FA23F246C358E00944F05 /* StringExtension.swift in Sources */,
|
C46FA23F246C358E00944F05 /* StringExtension.swift in Sources */,
|
||||||
|
C4B97B75275CF08C003F3378 /* AppDelegate+MenuOutlets.swift in Sources */,
|
||||||
C464ADAC275A7A3F003FCD53 /* SiteListWC.swift in Sources */,
|
C464ADAC275A7A3F003FCD53 /* SiteListWC.swift in Sources */,
|
||||||
C464ADB2275A87CA003FCD53 /* SiteListCell.swift in Sources */,
|
C464ADB2275A87CA003FCD53 /* SiteListCell.swift in Sources */,
|
||||||
C4EE188422D3386B00E126E5 /* Constants.swift in Sources */,
|
C4EE188422D3386B00E126E5 /* Constants.swift in Sources */,
|
||||||
@ -561,10 +576,13 @@
|
|||||||
C4F780AE25D80B37000DBC97 /* ExtensionParserTest.swift in Sources */,
|
C4F780AE25D80B37000DBC97 /* ExtensionParserTest.swift in Sources */,
|
||||||
C4F780C725D80B75000DBC97 /* StatusMenu.swift in Sources */,
|
C4F780C725D80B75000DBC97 /* StatusMenu.swift in Sources */,
|
||||||
C42759682627662800093CAE /* NSMenuExtension.swift in Sources */,
|
C42759682627662800093CAE /* NSMenuExtension.swift in Sources */,
|
||||||
|
C4B97B76275CF08C003F3378 /* AppDelegate+MenuOutlets.swift in Sources */,
|
||||||
C4F780CD25D80B75000DBC97 /* Alert.swift in Sources */,
|
C4F780CD25D80B75000DBC97 /* Alert.swift in Sources */,
|
||||||
C481F79726164A78004FBCFF /* PrefsVC.swift in Sources */,
|
C481F79726164A78004FBCFF /* PrefsVC.swift in Sources */,
|
||||||
C464ADB3275A87CA003FCD53 /* SiteListCell.swift in Sources */,
|
C464ADB3275A87CA003FCD53 /* SiteListCell.swift in Sources */,
|
||||||
C4AF9F78275447F100D44ED0 /* ValetConfigParserTest.swift in Sources */,
|
C4AF9F78275447F100D44ED0 /* ValetConfigParserTest.swift in Sources */,
|
||||||
|
C4B97B7C275CF20A003F3378 /* App+GlobalHotkey.swift in Sources */,
|
||||||
|
C4B97B79275CF1B5003F3378 /* App+ActivationPolicy.swift in Sources */,
|
||||||
C4F7809C25D80344000DBC97 /* CommandTest.swift in Sources */,
|
C4F7809C25D80344000DBC97 /* CommandTest.swift in Sources */,
|
||||||
C4F780BA25D80B62000DBC97 /* AppDelegate.swift in Sources */,
|
C4F780BA25D80B62000DBC97 /* AppDelegate.swift in Sources */,
|
||||||
C4998F0B2617633900B2526E /* PrefsWC.swift in Sources */,
|
C4998F0B2617633900B2526E /* PrefsWC.swift in Sources */,
|
||||||
|
@ -191,9 +191,14 @@ class Actions {
|
|||||||
// MARK: - Quick Fix
|
// MARK: - Quick Fix
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Detects all currently available PHP versions, and unlinks each and every one of them.
|
Detects all currently available PHP versions,
|
||||||
After this, the brew services are also stopped, the latest PHP version is linked, and php + nginx are restarted.
|
and unlinks each and every one of them.
|
||||||
If this does not solve the issue, the user may need to install additional extensions and/or run `composer global update`.
|
|
||||||
|
After this, the brew services are also stopped,
|
||||||
|
the latest PHP version is linked, and php + nginx are restarted.
|
||||||
|
|
||||||
|
If this does not solve the issue, the user may need to install additional
|
||||||
|
extensions and/or run `composer global update`.
|
||||||
*/
|
*/
|
||||||
public static func fixMyPhp()
|
public static func fixMyPhp()
|
||||||
{
|
{
|
||||||
@ -241,7 +246,8 @@ class Actions {
|
|||||||
let e_original = original.replacingOccurrences(of: "/", with: "\\/")
|
let e_original = original.replacingOccurrences(of: "/", with: "\\/")
|
||||||
let e_replacement = replacement.replacingOccurrences(of: "/", with: "\\/")
|
let e_replacement = replacement.replacingOccurrences(of: "/", with: "\\/")
|
||||||
|
|
||||||
// Check if gsed exists; it is able to follow symlinks, which we want to do to toggle the extension
|
// Check if gsed exists; it is able to follow symlinks,
|
||||||
|
// which we want to do to toggle the extension
|
||||||
if Shell.fileExists("\(Paths.binPath)/gsed") {
|
if Shell.fileExists("\(Paths.binPath)/gsed") {
|
||||||
Shell.run("\(Paths.binPath)/gsed -i --follow-symlinks 's/\(e_original)/\(e_replacement)/g' \(file)")
|
Shell.run("\(Paths.binPath)/gsed -i --follow-symlinks 's/\(e_original)/\(e_replacement)/g' \(file)")
|
||||||
} else {
|
} else {
|
||||||
|
44
phpmon/Domain/Core/App+ActivationPolicy.swift
Normal file
44
phpmon/Domain/Core/App+ActivationPolicy.swift
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
//
|
||||||
|
// App+ActivationPolicy.swift
|
||||||
|
// PHP Monitor
|
||||||
|
//
|
||||||
|
// Created by Nico Verbruggen on 05/12/2021.
|
||||||
|
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Cocoa
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
extension App {
|
||||||
|
|
||||||
|
// MARK: - Application State
|
||||||
|
|
||||||
|
/**
|
||||||
|
Registers a window as currently open.
|
||||||
|
*/
|
||||||
|
public func register(window name: String) {
|
||||||
|
if !openWindows.contains(name) {
|
||||||
|
openWindows.append(name)
|
||||||
|
}
|
||||||
|
updateActivationPolicy()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Removes a window, assuming it was closed.
|
||||||
|
*/
|
||||||
|
public func remove(window name: String) {
|
||||||
|
openWindows.removeAll { window in
|
||||||
|
window == name
|
||||||
|
}
|
||||||
|
updateActivationPolicy()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
If there are any open windows, the app will be a regular app.
|
||||||
|
If there are no windows open, the app will be an accessory (toolbar) app.
|
||||||
|
*/
|
||||||
|
public func updateActivationPolicy() {
|
||||||
|
NSApp.setActivationPolicy(openWindows.count > 0 ? .regular : .accessory)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
55
phpmon/Domain/Core/App+GlobalHotkey.swift
Normal file
55
phpmon/Domain/Core/App+GlobalHotkey.swift
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
//
|
||||||
|
// App+GlobalHotkey.swift
|
||||||
|
// PHP Monitor
|
||||||
|
//
|
||||||
|
// Created by Nico Verbruggen on 05/12/2021.
|
||||||
|
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import HotKey
|
||||||
|
import Cocoa
|
||||||
|
|
||||||
|
extension App {
|
||||||
|
|
||||||
|
// MARK: - Methods
|
||||||
|
|
||||||
|
/**
|
||||||
|
On startup, the preferences should be loaded from the .plist,
|
||||||
|
and we'll enable the shortcut if it is set.
|
||||||
|
*/
|
||||||
|
func loadGlobalHotkey() {
|
||||||
|
// Make sure we can retrieve the hotkey from preferences
|
||||||
|
guard let hotkey = Preferences.preferences[.globalHotkey] as? String else {
|
||||||
|
print("No global hotkey loaded")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure we can parse the JSON into the desired format
|
||||||
|
guard let keybindPref = GlobalKeybindPreference.fromJson(hotkey) else {
|
||||||
|
print("No global hotkey loaded, could not be parsed!")
|
||||||
|
self.shortcutHotkey = nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
self.shortcutHotkey = HotKey(keyCombo: KeyCombo(
|
||||||
|
carbonKeyCode: keybindPref.keyCode,
|
||||||
|
carbonModifiers: keybindPref.carbonFlags
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets up the action that needs to occur when the shortcut key is pressed
|
||||||
|
(opens the menu).
|
||||||
|
*/
|
||||||
|
func setupGlobalHotkeyListener() {
|
||||||
|
guard let hotkey = self.shortcutHotkey else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
hotkey.keyDownHandler = {
|
||||||
|
MainMenu.shared.statusItem.button?.performClick(nil)
|
||||||
|
NSApplication.shared.activate(ignoringOtherApps: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -10,10 +10,16 @@ import HotKey
|
|||||||
|
|
||||||
class App {
|
class App {
|
||||||
|
|
||||||
|
// MARK: Static Vars
|
||||||
|
|
||||||
|
/** The static app instance. Accessible at any time. */
|
||||||
static let shared = App()
|
static let shared = App()
|
||||||
|
|
||||||
init() {
|
/** Retrieve the version number from the main info dictionary, Info.plist. */
|
||||||
loadGlobalHotkey()
|
static var version: String {
|
||||||
|
let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as! String
|
||||||
|
let build = Bundle.main.infoDictionary?["CFBundleVersion"] as! String
|
||||||
|
return "\(version) (\(build))"
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Information about the currently linked PHP installation. */
|
/** Information about the currently linked PHP installation. */
|
||||||
@ -26,62 +32,46 @@ class App {
|
|||||||
return App.shared.busy
|
return App.shared.busy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - Initializer
|
||||||
|
|
||||||
|
/** When the app boots up, this code will run even before the start-up checks. */
|
||||||
|
init() {
|
||||||
|
loadGlobalHotkey()
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Variables
|
||||||
|
|
||||||
/** The list of preferences that are currently active. */
|
/** The list of preferences that are currently active. */
|
||||||
var preferences: [PreferenceName: Bool]!
|
var preferences: [PreferenceName: Bool]!
|
||||||
|
|
||||||
/**
|
/** The window controller of the currently active preferences window. */
|
||||||
The window controller of the currently active preferences window.
|
|
||||||
*/
|
|
||||||
var preferencesWindowController: PrefsWC? = nil
|
var preferencesWindowController: PrefsWC? = nil
|
||||||
|
|
||||||
/**
|
/** The window controller of the currently active site list window. */
|
||||||
The window controller of the currently active site list window.
|
|
||||||
*/
|
|
||||||
var siteListWindowController: SiteListWC? = nil
|
var siteListWindowController: SiteListWC? = nil
|
||||||
|
|
||||||
/**
|
/** Whether the application is busy switching versions. */
|
||||||
Whether the application is busy switching versions.
|
|
||||||
*/
|
|
||||||
var busy: Bool = false
|
var busy: Bool = false
|
||||||
|
|
||||||
/**
|
/** The currently active installation of PHP. */
|
||||||
The currently active installation of PHP.
|
|
||||||
*/
|
|
||||||
var currentInstall: ActivePhpInstallation? = nil
|
var currentInstall: ActivePhpInstallation? = nil
|
||||||
|
|
||||||
/**
|
/** All available versions of PHP. */
|
||||||
All available versions of PHP.
|
|
||||||
*/
|
|
||||||
var availablePhpVersions : [String] = []
|
var availablePhpVersions : [String] = []
|
||||||
|
|
||||||
/**
|
/** Cached information about the PHP installations. */
|
||||||
Cached information about the PHP installations; contains only the full version number at this point.
|
|
||||||
*/
|
|
||||||
var cachedPhpInstallations : [String: PhpInstallation] = [:]
|
var cachedPhpInstallations : [String: PhpInstallation] = [:]
|
||||||
|
|
||||||
/**
|
/** Timer that will periodically reload info about the user's PHP installation. */
|
||||||
The timer that will periodically fetch the PHP version that is currently active.
|
|
||||||
*/
|
|
||||||
var timer: Timer?
|
var timer: Timer?
|
||||||
|
|
||||||
/**
|
/** Information we were able to discern from the Homebrew info command (as JSON). */
|
||||||
Information we were able to discern from the Homebrew info command (as JSON).
|
|
||||||
*/
|
|
||||||
var brewPhpPackage: HomebrewPackage! = nil {
|
var brewPhpPackage: HomebrewPackage! = nil {
|
||||||
didSet {
|
didSet {
|
||||||
brewPhpVersion = brewPhpPackage!.version
|
brewPhpVersion = brewPhpPackage!.version
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
Retrieve the version number from the main info dictionary, Info.plist.
|
|
||||||
*/
|
|
||||||
static var version: String {
|
|
||||||
let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as! String
|
|
||||||
let build = Bundle.main.infoDictionary?["CFBundleVersion"] as! String
|
|
||||||
return "\(version) (\(build))"
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The version that the `php` formula via Brew is aliased to on the current system.
|
The version that the `php` formula via Brew is aliased to on the current system.
|
||||||
|
|
||||||
@ -93,6 +83,8 @@ class App {
|
|||||||
*/
|
*/
|
||||||
var brewPhpVersion: String = Constants.LatestStablePhpVersion
|
var brewPhpVersion: String = Constants.LatestStablePhpVersion
|
||||||
|
|
||||||
|
// MARK: - Global Hotkey
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The shortcut the user has requested.
|
The shortcut the user has requested.
|
||||||
*/
|
*/
|
||||||
@ -102,80 +94,16 @@ class App {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Methods
|
// MARK: - Activation Policy
|
||||||
|
|
||||||
/**
|
/**
|
||||||
On startup, the preferences should be loaded from the .plist, and we'll enable the shortcut if it is set.
|
Variable that keeps track of which windows are currently open.
|
||||||
*/
|
(Please note that window controllers remain open in memory once opened.)
|
||||||
private func loadGlobalHotkey() {
|
|
||||||
// Make sure we can retrieve the hotkey from preferences; if we cannot, no hotkey is set
|
|
||||||
guard let hotkey = Preferences.preferences[.globalHotkey] as? String else {
|
|
||||||
print("No global hotkey loaded")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure we can parse the JSON into the desired format; if we cannot, no hotkey is set
|
|
||||||
guard let keybindPref = GlobalKeybindPreference.fromJson(hotkey) else {
|
|
||||||
print("No global hotkey loaded, could not be parsed!")
|
|
||||||
self.shortcutHotkey = nil
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
self.shortcutHotkey = HotKey(keyCombo: KeyCombo(
|
|
||||||
carbonKeyCode: keybindPref.keyCode,
|
|
||||||
carbonModifiers: keybindPref.carbonFlags
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Sets up the action that needs to occur when the shortcut key is pressed (open the menu).
|
|
||||||
*/
|
|
||||||
private func setupGlobalHotkeyListener() {
|
|
||||||
guard let hotkey = self.shortcutHotkey else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
hotkey.keyDownHandler = {
|
|
||||||
MainMenu.shared.statusItem.button?.performClick(nil)
|
|
||||||
NSApplication.shared.activate(ignoringOtherApps: true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Application State
|
|
||||||
|
|
||||||
/**
|
|
||||||
Keep track of open windows.
|
|
||||||
When this list is updated, the app activation policy is re-evaluated.
|
When this list is updated, the app activation policy is re-evaluated.
|
||||||
The app activation policy dictates how the app runs (as a normal app or as a toolbar app).
|
The app activation policy dictates how the app runs
|
||||||
|
(as a normal app or as a toolbar app).
|
||||||
*/
|
*/
|
||||||
var openWindows: [String] = []
|
var openWindows: [String] = []
|
||||||
|
|
||||||
/**
|
|
||||||
Registers a window as currently open.
|
|
||||||
*/
|
|
||||||
public func register(window name: String) {
|
|
||||||
if !openWindows.contains(name) {
|
|
||||||
openWindows.append(name)
|
|
||||||
}
|
|
||||||
updateActivationPolicy()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Removes a window, assuming it was closed.
|
|
||||||
*/
|
|
||||||
public func remove(window name: String) {
|
|
||||||
openWindows.removeAll { window in
|
|
||||||
window == name
|
|
||||||
}
|
|
||||||
updateActivationPolicy()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
If there are any open windows, the app will be a regular app.
|
|
||||||
If there are no windows open, the app will be an accessory (toolbar) app.
|
|
||||||
*/
|
|
||||||
public func updateActivationPolicy() {
|
|
||||||
NSApp.setActivationPolicy(openWindows.count > 0 ? .regular : .accessory)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
40
phpmon/Domain/Core/AppDelegate+MenuOutlets.swift
Normal file
40
phpmon/Domain/Core/AppDelegate+MenuOutlets.swift
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
//
|
||||||
|
// AppDelegate+MenuOutlets.swift
|
||||||
|
// PHP Monitor
|
||||||
|
//
|
||||||
|
// Created by Nico Verbruggen on 05/12/2021.
|
||||||
|
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
/**
|
||||||
|
Any outlets connected to the app's main menu (not the menu that shows when the icon in
|
||||||
|
the menu bar is clicked, but the regular app's main menu) are configured here.
|
||||||
|
|
||||||
|
Default interactions like copy/paste, select all, close window etc. are wired up by
|
||||||
|
default in the storyboard and do not need to be manually added.
|
||||||
|
|
||||||
|
Extra functionality (like the menu item to reload the list of sites) does, however.
|
||||||
|
|
||||||
|
- Note: This menu is only displayed when the app is NOT running in accessory mode.
|
||||||
|
For more information about this, please see the ActivationPolicy-related extension.
|
||||||
|
*/
|
||||||
|
extension AppDelegate {
|
||||||
|
|
||||||
|
// MARK: - Menu Interactions
|
||||||
|
|
||||||
|
@IBAction func reloadSiteListPressed(_ sender: Any) {
|
||||||
|
let vc = App.shared.siteListWindowController?
|
||||||
|
.window?.contentViewController as? SiteListVC
|
||||||
|
|
||||||
|
if vc != nil {
|
||||||
|
// If the view exists, directly reload the list of sites
|
||||||
|
vc!.reloadSites()
|
||||||
|
} else {
|
||||||
|
// If the view does not exist, reload the cached data that was populated when the app initially launched.
|
||||||
|
Valet.shared.reloadSites()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -39,7 +39,8 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
|
|||||||
let paths: Paths
|
let paths: Paths
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The Valet singleton that determines all information about Valet and its current configuration.
|
The Valet singleton that determines all information
|
||||||
|
about Valet and its current configuration.
|
||||||
*/
|
*/
|
||||||
let valet: Valet
|
let valet: Valet
|
||||||
|
|
||||||
@ -74,17 +75,16 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
|
|||||||
self.menu.startup()
|
self.menu.startup()
|
||||||
}
|
}
|
||||||
|
|
||||||
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
|
/**
|
||||||
|
Ensure that the application displays notifications even when the app is active.
|
||||||
|
*/
|
||||||
|
func userNotificationCenter(
|
||||||
|
_ center: UNUserNotificationCenter,
|
||||||
|
willPresent notification: UNNotification,
|
||||||
|
withCompletionHandler completionHandler:
|
||||||
|
@escaping (UNNotificationPresentationOptions) -> Void
|
||||||
|
) {
|
||||||
completionHandler([.banner])
|
completionHandler([.banner])
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Menu Interactions
|
|
||||||
|
|
||||||
@IBAction func reloadSiteListPressed(_ sender: Any) {
|
|
||||||
let vc = App.shared.siteListWindowController?.window?.contentViewController as? SiteListVC
|
|
||||||
if vc != nil {
|
|
||||||
vc!.reloadSites()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -590,13 +590,13 @@ Gw
|
|||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<scrollView autohidesScrollers="YES" horizontalLineScroll="69" horizontalPageScroll="10" verticalLineScroll="69" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="p0j-eB-I2i">
|
<scrollView autohidesScrollers="YES" horizontalLineScroll="69" horizontalPageScroll="10" verticalLineScroll="69" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="p0j-eB-I2i">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="550" height="317"/>
|
<rect key="frame" x="0.0" y="0.0" width="550" height="313"/>
|
||||||
<clipView key="contentView" id="6IL-DW-37w">
|
<clipView key="contentView" id="6IL-DW-37w">
|
||||||
<rect key="frame" x="1" y="1" width="548" height="315"/>
|
<rect key="frame" x="1" y="1" width="548" height="311"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" multipleSelection="NO" autosaveColumns="NO" rowHeight="69" rowSizeStyle="automatic" viewBased="YES" id="cp3-34-pQj">
|
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" multipleSelection="NO" autosaveColumns="NO" rowHeight="69" rowSizeStyle="automatic" viewBased="YES" id="cp3-34-pQj">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="548" height="315"/>
|
<rect key="frame" x="0.0" y="0.0" width="548" height="311"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<size key="intercellSpacing" width="17" height="0.0"/>
|
<size key="intercellSpacing" width="17" height="0.0"/>
|
||||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||||
@ -664,15 +664,6 @@ Gw
|
|||||||
<box verticalHuggingPriority="750" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="syz-LF-l6P">
|
<box verticalHuggingPriority="750" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="syz-LF-l6P">
|
||||||
<rect key="frame" x="0.0" y="-2" width="531" height="5"/>
|
<rect key="frame" x="0.0" y="-2" width="531" height="5"/>
|
||||||
</box>
|
</box>
|
||||||
<textField hidden="YES" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="YUU-Hg-chL">
|
|
||||||
<rect key="frame" x="301" y="27" width="51" height="14"/>
|
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
|
||||||
<textFieldCell key="cell" lineBreakMode="clipping" alignment="center" title="PHP 8.0" id="d9R-tV-Dlk">
|
|
||||||
<font key="font" metaFont="smallSystem"/>
|
|
||||||
<color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/>
|
|
||||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
|
||||||
</textFieldCell>
|
|
||||||
</textField>
|
|
||||||
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="0NQ-ZD-CqD">
|
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="0NQ-ZD-CqD">
|
||||||
<rect key="frame" x="420" y="26" width="18" height="18"/>
|
<rect key="frame" x="420" y="26" width="18" height="18"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
@ -705,7 +696,6 @@ Gw
|
|||||||
<outlet property="imageViewType" destination="0NQ-ZD-CqD" id="Cph-FN-LaY"/>
|
<outlet property="imageViewType" destination="0NQ-ZD-CqD" id="Cph-FN-LaY"/>
|
||||||
<outlet property="labelDriver" destination="TbX-e2-3QL" id="qJh-Ak-Dge"/>
|
<outlet property="labelDriver" destination="TbX-e2-3QL" id="qJh-Ak-Dge"/>
|
||||||
<outlet property="labelPathName" destination="CXK-Q9-CpO" id="iVZ-cL-azB"/>
|
<outlet property="labelPathName" destination="CXK-Q9-CpO" id="iVZ-cL-azB"/>
|
||||||
<outlet property="labelPhpVersion" destination="YUU-Hg-chL" id="5Yh-vQ-ksL"/>
|
|
||||||
<outlet property="labelSiteName" destination="XJL-Uw-frD" id="f0t-vd-W68"/>
|
<outlet property="labelSiteName" destination="XJL-Uw-frD" id="f0t-vd-W68"/>
|
||||||
</connections>
|
</connections>
|
||||||
</tableCellView>
|
</tableCellView>
|
||||||
@ -724,7 +714,7 @@ Gw
|
|||||||
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="550" id="iRQ-sz-oyv"/>
|
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="550" id="iRQ-sz-oyv"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="TDE-ff-DQT">
|
<scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="TDE-ff-DQT">
|
||||||
<rect key="frame" x="1" y="328" width="548" height="15"/>
|
<rect key="frame" x="1" y="301" width="548" height="15"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
</scroller>
|
</scroller>
|
||||||
<scroller key="verticalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="wFn-93-f10">
|
<scroller key="verticalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="wFn-93-f10">
|
||||||
@ -733,7 +723,7 @@ Gw
|
|||||||
</scroller>
|
</scroller>
|
||||||
</scrollView>
|
</scrollView>
|
||||||
<progressIndicator maxValue="100" displayedWhenStopped="NO" indeterminate="YES" style="spinning" translatesAutoresizingMaskIntoConstraints="NO" id="ZiS-Gq-TLQ">
|
<progressIndicator maxValue="100" displayedWhenStopped="NO" indeterminate="YES" style="spinning" translatesAutoresizingMaskIntoConstraints="NO" id="ZiS-Gq-TLQ">
|
||||||
<rect key="frame" x="260" y="154" width="30" height="30"/>
|
<rect key="frame" x="260" y="152" width="30" height="30"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="width" constant="30" id="XK3-AR-Oc0"/>
|
<constraint firstAttribute="width" constant="30" id="XK3-AR-Oc0"/>
|
||||||
<constraint firstAttribute="height" constant="30" id="lfW-dB-Eu3"/>
|
<constraint firstAttribute="height" constant="30" id="lfW-dB-Eu3"/>
|
||||||
|
@ -13,7 +13,8 @@ import Foundation
|
|||||||
When initialized, that version's .ini files are also scanned (for active or inactive extensions).
|
When initialized, that version's .ini files are also scanned (for active or inactive extensions).
|
||||||
Integrity checks can be performed to determine whether PHP-FPM is configured correctly.
|
Integrity checks can be performed to determine whether PHP-FPM is configured correctly.
|
||||||
|
|
||||||
- Note: Each installation has a separate version number. Using `version.short` is advisable if you want to interact with Homebrew.
|
- Note: Each installation has a separate version number.
|
||||||
|
Using `version.short` is advisable if you want to interact with Homebrew.
|
||||||
*/
|
*/
|
||||||
class ActivePhpInstallation {
|
class ActivePhpInstallation {
|
||||||
|
|
||||||
@ -100,8 +101,10 @@ class ActivePhpInstallation {
|
|||||||
* 10000: an integer = amount of bytes
|
* 10000: an integer = amount of bytes
|
||||||
* 1K, 1M, 1G = shorthand for kilobytes, megabytes and gigabytes
|
* 1K, 1M, 1G = shorthand for kilobytes, megabytes and gigabytes
|
||||||
|
|
||||||
If none of these notations are used, the _fallback_ value is used. We'll show an emoji to indicate something has gone wrong here.
|
If none of these notations are used, the _fallback_ value is used.
|
||||||
To clarify, B gets appended to valid values. As a result, "5M" (valid) becomes "5MB", and "5MB" (invalid) becomes ⚠️.
|
We'll show an emoji to indicate something has gone wrong here.
|
||||||
|
To clarify, B gets appended to valid values.
|
||||||
|
As a result, "5M" (valid) becomes "5MB", and "5MB" (invalid) becomes ⚠️.
|
||||||
|
|
||||||
- Parameter key: The key of the `ini` value that needs to be retrieved. For example, you can use `memory_limit`.
|
- Parameter key: The key of the `ini` value that needs to be retrieved. For example, you can use `memory_limit`.
|
||||||
*/
|
*/
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// BrewPhpInstallation.swift
|
// PhpInstallation.swift
|
||||||
// PHP Monitor
|
// PHP Monitor
|
||||||
//
|
//
|
||||||
// Created by Nico Verbruggen on 28/11/2021.
|
// Created by Nico Verbruggen on 28/11/2021.
|
||||||
@ -13,6 +13,11 @@ class PhpInstallation {
|
|||||||
var longVersion: String
|
var longVersion: String
|
||||||
var homebrewInfo: HomebrewPackage
|
var homebrewInfo: HomebrewPackage
|
||||||
|
|
||||||
|
/**
|
||||||
|
In order to determine details about a PHP installation, we’ll simply run `php-config --version`
|
||||||
|
in the relevant directory, and we’ll also attempt to determine information about the Homebrew
|
||||||
|
formula for that particular installation.
|
||||||
|
*/
|
||||||
init(_ version: String) {
|
init(_ version: String) {
|
||||||
let phpConfigExecutablePath = "\(Paths.optPath)/php@\(version)/bin/php-config"
|
let phpConfigExecutablePath = "\(Paths.optPath)/php@\(version)/bin/php-config"
|
||||||
self.longVersion = version
|
self.longVersion = version
|
||||||
|
@ -18,7 +18,6 @@ class SiteListCell: NSTableCellView
|
|||||||
@IBOutlet weak var imageViewType: NSImageView!
|
@IBOutlet weak var imageViewType: NSImageView!
|
||||||
|
|
||||||
@IBOutlet weak var labelDriver: NSTextField!
|
@IBOutlet weak var labelDriver: NSTextField!
|
||||||
@IBOutlet weak var labelPhpVersion: NSTextField!
|
|
||||||
|
|
||||||
override func draw(_ dirtyRect: NSRect) {
|
override func draw(_ dirtyRect: NSRect) {
|
||||||
super.draw(dirtyRect)
|
super.draw(dirtyRect)
|
||||||
|
@ -128,9 +128,6 @@ class SiteListVC: NSViewController, NSTableViewDelegate, NSTableViewDataSource {
|
|||||||
/// Show the current driver
|
/// Show the current driver
|
||||||
userCell.labelDriver.stringValue = item.driver
|
userCell.labelDriver.stringValue = item.driver
|
||||||
|
|
||||||
/// TODO: Load the correct PHP version (not determined as of yet)
|
|
||||||
userCell.labelPhpVersion.stringValue = "PHP 8.0"
|
|
||||||
|
|
||||||
return userCell
|
return userCell
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ class Shell {
|
|||||||
requiresPath: Bool = false
|
requiresPath: Bool = false
|
||||||
) {
|
) {
|
||||||
// Equivalent of piping to /dev/null; don't do anything with the string
|
// Equivalent of piping to /dev/null; don't do anything with the string
|
||||||
_ = Shell.pipe(command)
|
_ = Shell.pipe(command, requiresPath: requiresPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user