mirror of
https://github.com/nicoverbruggen/phpmon.git
synced 2025-08-07 20:10:08 +02:00
♻️ Big Cleanup
This commit is contained in:
@ -136,6 +136,8 @@
|
||||
C4C8E81C276F54E5003AC782 /* PhpConfigWatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C8E81A276F54E5003AC782 /* PhpConfigWatcher.swift */; };
|
||||
C4CCBA6C275C567B008C7055 /* PMWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4CCBA6B275C567B008C7055 /* PMWindowController.swift */; };
|
||||
C4CCBA6D275C567B008C7055 /* PMWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4CCBA6B275C567B008C7055 /* PMWindowController.swift */; };
|
||||
C4CE3BB827B31F2E0086CA49 /* MainMenu+Switcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4CE3BB727B31F2E0086CA49 /* MainMenu+Switcher.swift */; };
|
||||
C4CE3BBA27B31F670086CA49 /* MainMenu+Composer.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4CE3BB927B31F670086CA49 /* MainMenu+Composer.swift */; };
|
||||
C4D8016622B1584700C6DA1B /* Startup.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D8016522B1584700C6DA1B /* Startup.swift */; };
|
||||
C4D89BC62783C99400A02B68 /* ComposerJson.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D89BC52783C99400A02B68 /* ComposerJson.swift */; };
|
||||
C4D9ADBF277610E1007277F4 /* PhpSwitcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D9ADBE277610E1007277F4 /* PhpSwitcher.swift */; };
|
||||
@ -283,6 +285,8 @@
|
||||
C4C8E817276F54D8003AC782 /* App+ConfigWatch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "App+ConfigWatch.swift"; sourceTree = "<group>"; };
|
||||
C4C8E81A276F54E5003AC782 /* PhpConfigWatcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhpConfigWatcher.swift; sourceTree = "<group>"; };
|
||||
C4CCBA6B275C567B008C7055 /* PMWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PMWindowController.swift; sourceTree = "<group>"; };
|
||||
C4CE3BB727B31F2E0086CA49 /* MainMenu+Switcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MainMenu+Switcher.swift"; sourceTree = "<group>"; };
|
||||
C4CE3BB927B31F670086CA49 /* MainMenu+Composer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MainMenu+Composer.swift"; sourceTree = "<group>"; };
|
||||
C4D8016522B1584700C6DA1B /* Startup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Startup.swift; sourceTree = "<group>"; };
|
||||
C4D89BC52783C99400A02B68 /* ComposerJson.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposerJson.swift; sourceTree = "<group>"; };
|
||||
C4D9ADBE277610E1007277F4 /* PhpSwitcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhpSwitcher.swift; sourceTree = "<group>"; };
|
||||
@ -509,6 +513,8 @@
|
||||
C4811D2922D70F9A00B5F6B3 /* MainMenu.swift */,
|
||||
C44CCD4827AFF3B700CE40E5 /* MainMenu+Async.swift */,
|
||||
C4C3ED402783497000AB15D8 /* MainMenu+Startup.swift */,
|
||||
C4CE3BB727B31F2E0086CA49 /* MainMenu+Switcher.swift */,
|
||||
C4CE3BB927B31F670086CA49 /* MainMenu+Composer.swift */,
|
||||
C47331A1247093B7009A0597 /* StatusMenu.swift */,
|
||||
C48D0C9525CC80B100CC7490 /* HeaderView.swift */,
|
||||
C48D0C9925CC888B00CC7490 /* HeaderView.xib */,
|
||||
@ -847,6 +853,7 @@
|
||||
C4C3ED4327834C5200AB15D8 /* CustomPrefs.swift in Sources */,
|
||||
54B48B5F275F66AE006D90C5 /* Application.swift in Sources */,
|
||||
C4B97B78275CF1B5003F3378 /* App+ActivationPolicy.swift in Sources */,
|
||||
C4CE3BB827B31F2E0086CA49 /* MainMenu+Switcher.swift in Sources */,
|
||||
C415937F27A1B54F00D2E1B7 /* PhpFrameworks.swift in Sources */,
|
||||
C4811D2422D70A4700B5F6B3 /* App.swift in Sources */,
|
||||
C41C1B4922B00A9800E7CF16 /* MenuBarImageGenerator.swift in Sources */,
|
||||
@ -880,6 +887,7 @@
|
||||
C476FF9822B0DD830098105B /* Alert.swift in Sources */,
|
||||
C474B00624C0E98C00066A22 /* LocalNotification.swift in Sources */,
|
||||
C48D0C9625CC80B100CC7490 /* HeaderView.swift in Sources */,
|
||||
C4CE3BBA27B31F670086CA49 /* MainMenu+Composer.swift in Sources */,
|
||||
C4D9ADC8277611A0007277F4 /* InternalSwitcher.swift in Sources */,
|
||||
C4B5635E276AB09000F12CCB /* VersionExtractor.swift in Sources */,
|
||||
C47331A2247093B7009A0597 /* StatusMenu.swift in Sources */,
|
||||
|
@ -8,11 +8,6 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
protocol PhpSwitcherDelegate: AnyObject {
|
||||
func switcherDidStartSwitching()
|
||||
func switcherDidCompleteSwitch()
|
||||
}
|
||||
|
||||
class PhpEnv {
|
||||
|
||||
// MARK: - Initializer
|
||||
|
@ -8,6 +8,14 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
protocol PhpSwitcherDelegate: AnyObject {
|
||||
|
||||
func switcherDidStartSwitching(to: String)
|
||||
|
||||
func switcherDidCompleteSwitch(to: String)
|
||||
|
||||
}
|
||||
|
||||
protocol PhpSwitcher {
|
||||
|
||||
func performSwitch(to version: String, completion: @escaping () -> Void)
|
||||
|
@ -8,7 +8,7 @@
|
||||
import Cocoa
|
||||
import HotKey
|
||||
|
||||
class App: PhpSwitcherDelegate {
|
||||
class App {
|
||||
|
||||
// MARK: Static Vars
|
||||
|
||||
@ -73,20 +73,4 @@ class App: PhpSwitcherDelegate {
|
||||
The `PhpConfigWatcher` is responsible for watching the `.ini` files and the `.conf.d` folder.
|
||||
*/
|
||||
var watcher: PhpConfigWatcher!
|
||||
|
||||
// MARK: - PhpSwitcherDelegate
|
||||
|
||||
func switcherDidStartSwitching() {
|
||||
}
|
||||
|
||||
func switcherDidCompleteSwitch() {
|
||||
PhpEnv.shared.currentInstall = ActivePhpInstallation()
|
||||
handlePhpConfigWatcher()
|
||||
|
||||
if let window = siteListWindowController {
|
||||
DispatchQueue.main.async {
|
||||
window.contentVC.reloadSites()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -45,12 +45,16 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
|
||||
let valet: Valet
|
||||
|
||||
/**
|
||||
The PhpSwitcher singleton that handles PHP version
|
||||
The PhpEnv singleton that handles PHP version
|
||||
detection, as well as switching. It is initialized
|
||||
when the app is ready and passed all checks.
|
||||
*/
|
||||
var switcher: PhpEnv! = nil
|
||||
var phpEnvironment: PhpEnv! = nil
|
||||
|
||||
/**
|
||||
The logger is responsible for different levels of logging.
|
||||
You can tweak the verbosity in the `init` method here.
|
||||
*/
|
||||
var logger = Log.shared
|
||||
|
||||
// MARK: - Initializer
|
||||
@ -59,7 +63,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
|
||||
When the application initializes, create all singletons.
|
||||
*/
|
||||
override init() {
|
||||
logger.verbosity = .performance
|
||||
logger.verbosity = .info
|
||||
Log.info("==================================")
|
||||
Log.info("PHP MONITOR by Nico Verbruggen")
|
||||
Log.info("Version \(App.version)")
|
||||
@ -73,8 +77,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
|
||||
}
|
||||
|
||||
func initializeSwitcher() {
|
||||
self.switcher = PhpEnv.shared
|
||||
self.switcher.delegate = self.state
|
||||
self.phpEnvironment = PhpEnv.shared
|
||||
}
|
||||
|
||||
// MARK: - Lifecycle
|
||||
|
98
phpmon/Domain/Menu/MainMenu+Composer.swift
Normal file
98
phpmon/Domain/Menu/MainMenu+Composer.swift
Normal file
@ -0,0 +1,98 @@
|
||||
//
|
||||
// MainMenu+Composer.swift
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 08/02/2022.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension MainMenu {
|
||||
|
||||
/**
|
||||
Updates the global dependencies and runs the completion callback when done.
|
||||
This method should probably be broken up into several smaller methods at some point.
|
||||
*/
|
||||
func updateGlobalDependencies(notify: Bool, completion: @escaping (Bool) -> Void) {
|
||||
if !Shell.fileExists("/usr/local/bin/composer") {
|
||||
Alert.notify(
|
||||
message: "alert.composer_missing.title".localized,
|
||||
info: "alert.composer_missing.info".localized
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
PhpEnv.shared.isBusy = true
|
||||
setBusyImage()
|
||||
self.rebuild()
|
||||
|
||||
let noLongerBusy = {
|
||||
PhpEnv.shared.isBusy = false
|
||||
DispatchQueue.main.async { [self] in
|
||||
self.updatePhpVersionInStatusBar()
|
||||
self.rebuild()
|
||||
}
|
||||
}
|
||||
|
||||
var window: ProgressWindowController? = ProgressWindowController.display(
|
||||
title: "alert.composer_progress.title".localized,
|
||||
description: "alert.composer_progress.info".localized
|
||||
)
|
||||
window?.setType(info: true)
|
||||
|
||||
DispatchQueue.global(qos: .userInitiated).async {
|
||||
let task = Shell.user.createTask(
|
||||
for: "/usr/local/bin/composer global update", requiresPath: true
|
||||
)
|
||||
|
||||
DispatchQueue.main.async {
|
||||
window?.addToConsole("/usr/local/bin/composer global update\n")
|
||||
}
|
||||
|
||||
Shell.captureOutput(
|
||||
task,
|
||||
didReceiveStdOutData: { string in
|
||||
DispatchQueue.main.async {
|
||||
window?.addToConsole(string)
|
||||
}
|
||||
Log.perf("\(string.trimmingCharacters(in: .newlines))")
|
||||
},
|
||||
didReceiveStdErrData: { string in
|
||||
DispatchQueue.main.async {
|
||||
window?.addToConsole(string)
|
||||
}
|
||||
Log.perf("\(string.trimmingCharacters(in: .newlines))")
|
||||
}
|
||||
)
|
||||
|
||||
task.launch()
|
||||
task.waitUntilExit()
|
||||
Shell.haltCapturingOutput(task)
|
||||
|
||||
DispatchQueue.main.async {
|
||||
if task.terminationStatus <= 0 {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
|
||||
window?.close()
|
||||
if (notify) {
|
||||
LocalNotification.send(
|
||||
title: "alert.composer_success.title".localized,
|
||||
subtitle: "alert.composer_success.info".localized
|
||||
)
|
||||
}
|
||||
window = nil
|
||||
noLongerBusy()
|
||||
completion(true)
|
||||
}
|
||||
} else {
|
||||
window?.setType(info: false)
|
||||
window?.progressView?.labelTitle.stringValue = "alert.composer_failure.title".localized
|
||||
window?.progressView?.labelDescription.stringValue = "alert.composer_failure.info".localized
|
||||
window = nil
|
||||
noLongerBusy()
|
||||
completion(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
84
phpmon/Domain/Menu/MainMenu+Switcher.swift
Normal file
84
phpmon/Domain/Menu/MainMenu+Switcher.swift
Normal file
@ -0,0 +1,84 @@
|
||||
//
|
||||
// MainMenu+PhpSwitcherDelegate.swift
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 08/02/2022.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension MainMenu {
|
||||
|
||||
// MARK: - PhpSwitcherDelegate
|
||||
|
||||
func switcherDidStartSwitching(to version: String) {}
|
||||
|
||||
func switcherDidCompleteSwitch(to version: String) {
|
||||
// Update the PHP version
|
||||
PhpEnv.shared.currentInstall = ActivePhpInstallation()
|
||||
|
||||
// Ensure the config watcher gets reloaded
|
||||
App.shared.handlePhpConfigWatcher()
|
||||
|
||||
// Mark as no longer busy
|
||||
PhpEnv.shared.isBusy = false
|
||||
|
||||
// Reload the site list
|
||||
self.reloadSiteListData()
|
||||
|
||||
// Perform UI updates on main thread
|
||||
DispatchQueue.main.async { [self] in
|
||||
updatePhpVersionInStatusBar()
|
||||
rebuild()
|
||||
|
||||
if !PhpEnv.shared.validate(version) {
|
||||
self.suggestFixMyValet(failed: version)
|
||||
return
|
||||
}
|
||||
|
||||
// Run composer updates
|
||||
if Preferences.isEnabled(.autoComposerGlobalUpdateAfterSwitch) {
|
||||
self.updateGlobalDependencies(notify: false, completion: { _ in
|
||||
self.notifyAboutVersionChange(to: version)
|
||||
})
|
||||
} else {
|
||||
self.notifyAboutVersionChange(to: version)
|
||||
}
|
||||
|
||||
// Update stats
|
||||
Stats.incrementSuccessfulSwitchCount()
|
||||
Stats.evaluateSponsorMessageShouldBeDisplayed()
|
||||
}
|
||||
}
|
||||
|
||||
private func suggestFixMyValet(failed version: String) {
|
||||
let outcome = Alert.present(
|
||||
messageText: "alert.php_switch_failed.title".localized(version),
|
||||
informativeText: "alert.php_switch_failed.info".localized(version),
|
||||
buttonTitle: "alert.php_switch_failed.confirm".localized,
|
||||
secondButtonTitle: "alert.php_switch_failed.cancel".localized, style: .informational)
|
||||
if outcome {
|
||||
MainMenu.shared.fixMyValet()
|
||||
}
|
||||
}
|
||||
|
||||
private func reloadSiteListData() {
|
||||
if let window = App.shared.siteListWindowController {
|
||||
DispatchQueue.main.async {
|
||||
window.contentVC.reloadSites()
|
||||
}
|
||||
} else {
|
||||
Valet.shared.reloadSites()
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
)
|
||||
|
||||
PhpEnv.phpInstall.notifyAboutBrokenPhpFpm()
|
||||
}
|
||||
}
|
@ -7,7 +7,7 @@
|
||||
|
||||
import Cocoa
|
||||
|
||||
class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate {
|
||||
class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate, PhpSwitcherDelegate {
|
||||
|
||||
static let shared = MainMenu()
|
||||
|
||||
@ -23,46 +23,61 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate {
|
||||
// MARK: - UI related
|
||||
|
||||
/**
|
||||
Update the menu's contents, based on what's going on.
|
||||
This will rebuild the entire menu, so this can take a few moments.
|
||||
Rebuilds the menu (either asynchronously or synchronously).
|
||||
Defaults to rebuilding the menu asynchronously.
|
||||
*/
|
||||
func rebuild() {
|
||||
func rebuild(async: Bool = true) {
|
||||
if !async {
|
||||
self.rebuildMenu()
|
||||
return
|
||||
}
|
||||
|
||||
// Update the menu item on the main thread
|
||||
DispatchQueue.main.async { [self] in
|
||||
// Create a new menu
|
||||
let menu = StatusMenu()
|
||||
|
||||
// Add the PHP versions (or error messages)
|
||||
menu.addPhpVersionMenuItems()
|
||||
menu.addItem(NSMenuItem.separator())
|
||||
|
||||
// Add the possible actions
|
||||
menu.addPhpActionMenuItems()
|
||||
menu.addItem(NSMenuItem.separator())
|
||||
|
||||
// Add Valet interactions
|
||||
menu.addValetMenuItems()
|
||||
menu.addItem(NSMenuItem.separator())
|
||||
|
||||
// Add services
|
||||
menu.addPhpConfigurationMenuItems()
|
||||
menu.addItem(NSMenuItem.separator())
|
||||
|
||||
// Add about & quit menu items
|
||||
menu.addItem(NSMenuItem(title: "mi_preferences".localized, action: #selector(openPrefs), keyEquivalent: ","))
|
||||
menu.addItem(NSMenuItem(title: "mi_about".localized, action: #selector(openAbout), keyEquivalent: ""))
|
||||
menu.addItem(NSMenuItem(title: "mi_quit".localized, action: #selector(terminateApp), keyEquivalent: "q"))
|
||||
|
||||
// Make sure every item can be interacted with
|
||||
menu.items.forEach({ (item) in
|
||||
item.target = self
|
||||
})
|
||||
|
||||
statusItem.menu = menu
|
||||
statusItem.menu?.delegate = self
|
||||
self.rebuildMenu()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Update the menu's contents, based on what's going on.
|
||||
This will rebuild the entire menu, so this can take a few moments.
|
||||
|
||||
Use `rebuild(async:)` to ensure the rebuilding happens in the background.
|
||||
*/
|
||||
private func rebuildMenu() {
|
||||
// Create a new menu
|
||||
let menu = StatusMenu()
|
||||
|
||||
// Add the PHP versions (or error messages)
|
||||
menu.addPhpVersionMenuItems()
|
||||
menu.addItem(NSMenuItem.separator())
|
||||
|
||||
// Add the possible actions
|
||||
menu.addPhpActionMenuItems()
|
||||
menu.addItem(NSMenuItem.separator())
|
||||
|
||||
// Add Valet interactions
|
||||
menu.addValetMenuItems()
|
||||
menu.addItem(NSMenuItem.separator())
|
||||
|
||||
// Add services
|
||||
menu.addPhpConfigurationMenuItems()
|
||||
menu.addItem(NSMenuItem.separator())
|
||||
|
||||
// Add about & quit menu items
|
||||
menu.addItem(NSMenuItem(title: "mi_preferences".localized, action: #selector(openPrefs), keyEquivalent: ","))
|
||||
menu.addItem(NSMenuItem(title: "mi_about".localized, action: #selector(openAbout), keyEquivalent: ""))
|
||||
menu.addItem(NSMenuItem(title: "mi_quit".localized, action: #selector(terminateApp), keyEquivalent: "q"))
|
||||
|
||||
// Make sure every item can be interacted with
|
||||
menu.items.forEach({ (item) in
|
||||
item.target = self
|
||||
})
|
||||
|
||||
statusItem.menu = menu
|
||||
statusItem.menu?.delegate = self
|
||||
}
|
||||
|
||||
/**
|
||||
Sets the status bar image based on a version string.
|
||||
*/
|
||||
@ -87,6 +102,7 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate {
|
||||
|
||||
// MARK: - User Interface
|
||||
|
||||
/** Reloads which PHP versions is currently active. */
|
||||
@objc func refreshActiveInstallation() {
|
||||
if !PhpEnv.shared.isBusy {
|
||||
PhpEnv.shared.currentInstall = ActivePhpInstallation()
|
||||
@ -96,12 +112,38 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
/** Updates the icon (refresh icon) and rebuilds the menu. */
|
||||
@objc func updatePhpVersionInStatusBar() {
|
||||
refreshIcon()
|
||||
rebuild()
|
||||
}
|
||||
|
||||
func refreshIcon() {
|
||||
/**
|
||||
Reloads the menu in the foreground.
|
||||
This mimics the exact behaviours of `asyncExecution` as set in the method below.
|
||||
*/
|
||||
@objc func reloadPhpMonitorMenuInForeground() {
|
||||
refreshActiveInstallation()
|
||||
refreshIcon()
|
||||
rebuild(async: false)
|
||||
NotificationCenter.default.post(name: Events.ServicesUpdated, object: nil)
|
||||
}
|
||||
|
||||
/** Reloads the menu in the background, using `asyncExecution`. */
|
||||
@objc func reloadPhpMonitorMenuInBackground() {
|
||||
asyncExecution({
|
||||
// This automatically reloads the menu
|
||||
Log.info("Reloading information about the PHP installation (in the background)...")
|
||||
}, behaviours: [
|
||||
.setsBusyUI,
|
||||
.reloadsPhpInstallation,
|
||||
.broadcastServicesUpdate,
|
||||
.updatesMenuBarContents
|
||||
])
|
||||
}
|
||||
|
||||
/** Refreshes the icon with the PHP version. */
|
||||
@objc func refreshIcon() {
|
||||
DispatchQueue.main.async { [self] in
|
||||
if (App.busy) {
|
||||
setStatusBar(image: NSImage(named: NSImage.Name("StatusBarIcon"))!)
|
||||
@ -118,20 +160,7 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
@objc func reloadPhpMonitorMenuInBackground() {
|
||||
asyncExecution {
|
||||
// This automatically reloads the menu
|
||||
Log.info("Reloading information about the PHP installation (in the background)...")
|
||||
}
|
||||
}
|
||||
|
||||
@objc func reloadPhpMonitorMenu() {
|
||||
asyncExecution {
|
||||
// This automatically reloads the menu
|
||||
Log.info("Reloading information about the PHP installation...")
|
||||
}
|
||||
}
|
||||
|
||||
/** Updates the icon to be displayed as busy. */
|
||||
@objc func setBusyImage() {
|
||||
DispatchQueue.main.async { [self] in
|
||||
setStatusBar(image: NSImage(named: NSImage.Name("StatusBarIcon"))!)
|
||||
@ -282,66 +311,23 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate {
|
||||
@objc func switchToPhpVersion(_ version: String) {
|
||||
setBusyImage()
|
||||
PhpEnv.shared.isBusy = true
|
||||
PhpEnv.shared.delegate = self
|
||||
PhpEnv.shared.delegate?.switcherDidStartSwitching(to: version)
|
||||
|
||||
DispatchQueue.global(qos: .userInitiated).async { [unowned self] in
|
||||
// Update the PHP version in the status bar
|
||||
updatePhpVersionInStatusBar()
|
||||
|
||||
// Update the menu
|
||||
rebuild()
|
||||
|
||||
let sendLocalNotification = {
|
||||
LocalNotification.send(
|
||||
title: String(format: "notification.version_changed_title".localized, version),
|
||||
subtitle: String(format: "notification.version_changed_desc".localized, version)
|
||||
)
|
||||
PhpEnv.phpInstall.notifyAboutBrokenPhpFpm()
|
||||
}
|
||||
|
||||
let completion = {
|
||||
// Fire off the delegate method
|
||||
PhpEnv.shared.delegate?.switcherDidCompleteSwitch()
|
||||
|
||||
// Mark as no longer busy
|
||||
PhpEnv.shared.isBusy = false
|
||||
|
||||
// Perform UI updates on main thread
|
||||
DispatchQueue.main.async { [self] in
|
||||
updatePhpVersionInStatusBar()
|
||||
rebuild()
|
||||
|
||||
if !PhpEnv.shared.validate(version) {
|
||||
let outcome = Alert.present(
|
||||
messageText: "alert.php_switch_failed.title".localized(version),
|
||||
informativeText: "alert.php_switch_failed.info".localized(version),
|
||||
buttonTitle: "alert.php_switch_failed.confirm".localized,
|
||||
secondButtonTitle: "alert.php_switch_failed.cancel".localized, style: .informational)
|
||||
if outcome {
|
||||
MainMenu.shared.fixMyValet()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Run composer updates
|
||||
if Preferences.isEnabled(.autoComposerGlobalUpdateAfterSwitch) {
|
||||
self.updateGlobalDependencies(notify: false, completion: { _ in sendLocalNotification() })
|
||||
} else {
|
||||
sendLocalNotification()
|
||||
}
|
||||
|
||||
// Update stats
|
||||
Stats.incrementSuccessfulSwitchCount()
|
||||
Stats.evaluateSponsorMessageShouldBeDisplayed()
|
||||
}
|
||||
}
|
||||
|
||||
PhpEnv.switcher.performSwitch(
|
||||
to: version,
|
||||
completion: completion
|
||||
completion: {
|
||||
PhpEnv.shared.delegate?.switcherDidCompleteSwitch(to: version)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Menu Item Functionality
|
||||
|
||||
@objc func openAbout() {
|
||||
NSApplication.shared.activate(ignoringOtherApps: true)
|
||||
NSApplication.shared.orderFrontStandardAboutPanel()
|
||||
@ -374,91 +360,4 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate {
|
||||
// When the menu is closed, allow the shortcut to work again
|
||||
App.shared.shortcutHotkey?.isPaused = false
|
||||
}
|
||||
|
||||
// MARK: - Private Methods
|
||||
|
||||
/**
|
||||
Updates the global dependencies and runs the completion callback when done.
|
||||
*/
|
||||
private func updateGlobalDependencies(notify: Bool, completion: @escaping (Bool) -> Void) {
|
||||
if !Shell.fileExists("/usr/local/bin/composer") {
|
||||
Alert.notify(
|
||||
message: "alert.composer_missing.title".localized,
|
||||
info: "alert.composer_missing.info".localized
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
PhpEnv.shared.isBusy = true
|
||||
setBusyImage()
|
||||
self.rebuild()
|
||||
|
||||
let noLongerBusy = {
|
||||
PhpEnv.shared.isBusy = false
|
||||
DispatchQueue.main.async { [self] in
|
||||
self.updatePhpVersionInStatusBar()
|
||||
self.rebuild()
|
||||
}
|
||||
}
|
||||
|
||||
var window: ProgressWindowController? = ProgressWindowController.display(
|
||||
title: "alert.composer_progress.title".localized,
|
||||
description: "alert.composer_progress.info".localized
|
||||
)
|
||||
window?.setType(info: true)
|
||||
|
||||
DispatchQueue.global(qos: .userInitiated).async {
|
||||
let task = Shell.user.createTask(
|
||||
for: "/usr/local/bin/composer global update", requiresPath: true
|
||||
)
|
||||
|
||||
DispatchQueue.main.async {
|
||||
window?.addToConsole("/usr/local/bin/composer global update\n")
|
||||
}
|
||||
|
||||
Shell.captureOutput(
|
||||
task,
|
||||
didReceiveStdOutData: { string in
|
||||
DispatchQueue.main.async {
|
||||
window?.addToConsole(string)
|
||||
}
|
||||
Log.perf("\(string.trimmingCharacters(in: .newlines))")
|
||||
},
|
||||
didReceiveStdErrData: { string in
|
||||
DispatchQueue.main.async {
|
||||
window?.addToConsole(string)
|
||||
}
|
||||
Log.perf("\(string.trimmingCharacters(in: .newlines))")
|
||||
}
|
||||
)
|
||||
|
||||
task.launch()
|
||||
task.waitUntilExit()
|
||||
Shell.haltCapturingOutput(task)
|
||||
|
||||
DispatchQueue.main.async {
|
||||
if task.terminationStatus <= 0 {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
|
||||
window?.close()
|
||||
if (notify) {
|
||||
LocalNotification.send(
|
||||
title: "alert.composer_success.title".localized,
|
||||
subtitle: "alert.composer_success.info".localized
|
||||
)
|
||||
}
|
||||
window = nil
|
||||
noLongerBusy()
|
||||
completion(true)
|
||||
}
|
||||
} else {
|
||||
window?.setType(info: false)
|
||||
window?.progressView?.labelTitle.stringValue = "alert.composer_failure.title".localized
|
||||
window?.progressView?.labelDescription.stringValue = "alert.composer_failure.info".localized
|
||||
window = nil
|
||||
noLongerBusy()
|
||||
completion(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ class StatusMenu : NSMenu {
|
||||
servicesMenu.addItem(NSMenuItem.separator())
|
||||
servicesMenu.addItem(HeaderView.asMenuItem(text: "mi_manual_actions".localized))
|
||||
|
||||
servicesMenu.addItem(NSMenuItem(title: "mi_php_refresh".localized, action: #selector(MainMenu.reloadPhpMonitorMenu), keyEquivalent: "r"))
|
||||
servicesMenu.addItem(NSMenuItem(title: "mi_php_refresh".localized, action: #selector(MainMenu.reloadPhpMonitorMenuInForeground), keyEquivalent: "r"))
|
||||
|
||||
for item in servicesMenu.items {
|
||||
item.target = MainMenu.shared
|
||||
|
@ -40,8 +40,8 @@ class PhpConfigWatcher {
|
||||
self.addWatcher(for: self.url.appendingPathComponent("conf.d/\(file)"), eventMask: .write)
|
||||
}
|
||||
|
||||
Log.info("A watcher exists for the following config paths:")
|
||||
Log.info(self.watchers.map({ watcher in
|
||||
Log.perf("A watcher exists for the following config paths:")
|
||||
Log.perf(self.watchers.map({ watcher in
|
||||
return watcher.url.relativePath
|
||||
}))
|
||||
}
|
||||
@ -57,7 +57,7 @@ class PhpConfigWatcher {
|
||||
}
|
||||
|
||||
func disable() {
|
||||
Log.info("Turning off existing watchers...")
|
||||
Log.perf("Turning off all individual existing watchers...")
|
||||
self.watchers.forEach { (watcher) in
|
||||
watcher.stopMonitoring()
|
||||
}
|
||||
|
Reference in New Issue
Block a user