mirror of
https://github.com/nicoverbruggen/phpmon.git
synced 2025-08-07 20:10:08 +02:00
♻️ Refactor waitAndExecute
→ asyncExecution
This change allows for errors to be thrown during the `asyncExecution` initial callback, and if one is thrown, allows a `failure` callback to be used. Existing instances of `waitAndExecute` have been replaced. I also added the ability to tweak the behaviours of the actions that are always performed when the asyncExecution method is called: you can now specify limited behaviours (e.g. only set busy icon). For that use case I have already created a new method: `asyncWithBusyUI`. With this change, the handling of the Homebrew Permissions flow has also been modified: when the user does not get administrative permissions an error is now thrown which results in an alert being presented to the user once the error occurs. There is now an opportunity to further refactor other parts of the app to more gracefully handle failure states using the Error and AlertableError protocols.
This commit is contained in:
@ -79,6 +79,12 @@
|
||||
C44C198E276E3A1C0072762D /* ProgressWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = C44C198C276E3A1C0072762D /* ProgressWindow.swift */; };
|
||||
C44C1991276E44CB0072762D /* ProgressWindow.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C44C1990276E44CB0072762D /* ProgressWindow.storyboard */; };
|
||||
C44C1992276E44CB0072762D /* ProgressWindow.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C44C1990276E44CB0072762D /* ProgressWindow.storyboard */; };
|
||||
C44CCD4027AFE2FC00CE40E5 /* AlertableError.swift in Sources */ = {isa = PBXBuildFile; fileRef = C44CCD3F27AFE2FC00CE40E5 /* AlertableError.swift */; };
|
||||
C44CCD4127AFE2FC00CE40E5 /* AlertableError.swift in Sources */ = {isa = PBXBuildFile; fileRef = C44CCD3F27AFE2FC00CE40E5 /* AlertableError.swift */; };
|
||||
C44CCD4227AFE2FC00CE40E5 /* AlertableError.swift in Sources */ = {isa = PBXBuildFile; fileRef = C44CCD3F27AFE2FC00CE40E5 /* AlertableError.swift */; };
|
||||
C44CCD4527AFE94900CE40E5 /* HomebrewPermissionError.swift in Sources */ = {isa = PBXBuildFile; fileRef = C44CCD4427AFE94900CE40E5 /* HomebrewPermissionError.swift */; };
|
||||
C44CCD4627AFE94900CE40E5 /* HomebrewPermissionError.swift in Sources */ = {isa = PBXBuildFile; fileRef = C44CCD4427AFE94900CE40E5 /* HomebrewPermissionError.swift */; };
|
||||
C44CCD4727AFE94900CE40E5 /* HomebrewPermissionError.swift in Sources */ = {isa = PBXBuildFile; fileRef = C44CCD4427AFE94900CE40E5 /* HomebrewPermissionError.swift */; };
|
||||
C464ADAC275A7A3F003FCD53 /* SiteListWC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C464ADAB275A7A3F003FCD53 /* SiteListWC.swift */; };
|
||||
C464ADAD275A7A3F003FCD53 /* SiteListWC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C464ADAB275A7A3F003FCD53 /* SiteListWC.swift */; };
|
||||
C464ADAF275A7A69003FCD53 /* SiteListVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C464ADAE275A7A69003FCD53 /* SiteListVC.swift */; };
|
||||
@ -264,6 +270,8 @@
|
||||
C43A8A2325D9D20D00591B77 /* BrewJsonParserTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrewJsonParserTest.swift; sourceTree = "<group>"; };
|
||||
C44C198C276E3A1C0072762D /* ProgressWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressWindow.swift; sourceTree = "<group>"; };
|
||||
C44C1990276E44CB0072762D /* ProgressWindow.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = ProgressWindow.storyboard; sourceTree = "<group>"; };
|
||||
C44CCD3F27AFE2FC00CE40E5 /* AlertableError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertableError.swift; sourceTree = "<group>"; };
|
||||
C44CCD4427AFE94900CE40E5 /* HomebrewPermissionError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomebrewPermissionError.swift; sourceTree = "<group>"; };
|
||||
C464ADAB275A7A3F003FCD53 /* SiteListWC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SiteListWC.swift; sourceTree = "<group>"; };
|
||||
C464ADAE275A7A69003FCD53 /* SiteListVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SiteListVC.swift; sourceTree = "<group>"; };
|
||||
C464ADB1275A87CA003FCD53 /* SiteListCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SiteListCell.swift; sourceTree = "<group>"; };
|
||||
@ -517,6 +525,15 @@
|
||||
path = Progress;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C44CCD4327AFE93300CE40E5 /* Errors */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C44CCD3F27AFE2FC00CE40E5 /* AlertableError.swift */,
|
||||
C44CCD4427AFE94900CE40E5 /* HomebrewPermissionError.swift */,
|
||||
);
|
||||
path = Errors;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C464ADAA275A7A25003FCD53 /* SiteList */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -617,6 +634,7 @@
|
||||
C4B5853A2770FE2500DA4FBE /* phpmon-common */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C44CCD4327AFE93300CE40E5 /* Errors */,
|
||||
C40C7F2127721F7300DDDCDC /* Core */,
|
||||
54B20EDF263AA22C00D3250E /* PHP */,
|
||||
);
|
||||
@ -872,7 +890,9 @@
|
||||
C4EC1E6E279DF87A0010F296 /* Async.swift in Sources */,
|
||||
C40C7F2327721F8200DDDCDC /* ActivePhpInstallation.swift in Sources */,
|
||||
C4B585462770FE3900DA4FBE /* Command.swift in Sources */,
|
||||
C44CCD4727AFE94900CE40E5 /* HomebrewPermissionError.swift in Sources */,
|
||||
C4D9ADCA277611A0007277F4 /* InternalSwitcher.swift in Sources */,
|
||||
C44CCD4227AFE2FC00CE40E5 /* AlertableError.swift in Sources */,
|
||||
C48D6C72279CD2AC00F26D7E /* PhpVersionNumber.swift in Sources */,
|
||||
C40C7F2527721F9800DDDCDC /* HomebrewPackage.swift in Sources */,
|
||||
C417DC76277614690015E6EE /* Helpers.swift in Sources */,
|
||||
@ -919,6 +939,7 @@
|
||||
C415937F27A1B54F00D2E1B7 /* PhpFrameworks.swift in Sources */,
|
||||
C4811D2422D70A4700B5F6B3 /* App.swift in Sources */,
|
||||
C41C1B4922B00A9800E7CF16 /* MenuBarImageGenerator.swift in Sources */,
|
||||
C44CCD4527AFE94900CE40E5 /* HomebrewPermissionError.swift in Sources */,
|
||||
C4F30B03278E16BA00755FCE /* HomebrewService.swift in Sources */,
|
||||
5420395F2613607600FB00FA /* Preferences.swift in Sources */,
|
||||
C48D0C9325CC804200CC7490 /* XibLoadable.swift in Sources */,
|
||||
@ -939,6 +960,7 @@
|
||||
C4EC1E73279DFCF40010F296 /* Events.swift in Sources */,
|
||||
C4B5853E2770FE3900DA4FBE /* Paths.swift in Sources */,
|
||||
C41C1B4B22B019FF00E7CF16 /* ActivePhpInstallation.swift in Sources */,
|
||||
C44CCD4027AFE2FC00CE40E5 /* AlertableError.swift in Sources */,
|
||||
C4188989275FE8CB001EF227 /* Filesystem.swift in Sources */,
|
||||
C4B97B7B275CF20A003F3378 /* App+GlobalHotkey.swift in Sources */,
|
||||
C4EED88927A48778006D7272 /* InterAppHandler.swift in Sources */,
|
||||
@ -1010,7 +1032,9 @@
|
||||
C417DC75277614690015E6EE /* Helpers.swift in Sources */,
|
||||
C4B97B7C275CF20A003F3378 /* App+GlobalHotkey.swift in Sources */,
|
||||
C4B97B79275CF1B5003F3378 /* App+ActivationPolicy.swift in Sources */,
|
||||
C44CCD4627AFE94900CE40E5 /* HomebrewPermissionError.swift in Sources */,
|
||||
C4F7809C25D80344000DBC97 /* CommandTest.swift in Sources */,
|
||||
C44CCD4127AFE2FC00CE40E5 /* AlertableError.swift in Sources */,
|
||||
C4F780BA25D80B62000DBC97 /* AppDelegate.swift in Sources */,
|
||||
54FCFD31276C8DA4004CE748 /* HotkeyPreferenceView.swift in Sources */,
|
||||
C4998F0B2617633900B2526E /* PrefsWC.swift in Sources */,
|
||||
@ -1215,7 +1239,7 @@
|
||||
C41C1B4422B0098000E7CF16 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIconBeta;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_ENTITLEMENTS = phpmon/phpmon.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
@ -1230,7 +1254,7 @@
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 11.0;
|
||||
MARKETING_VERSION = "5.1-dev";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon.beta;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_VERSION = 5.0;
|
||||
@ -1240,7 +1264,7 @@
|
||||
C41C1B4522B0098000E7CF16 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIconBeta;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_ENTITLEMENTS = phpmon/phpmon.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
@ -1255,7 +1279,7 @@
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 11.0;
|
||||
MARKETING_VERSION = "5.1-dev";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon.beta;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_VERSION = 5.0;
|
||||
|
@ -320,9 +320,9 @@ You can always still ask Valet using the command line, should it be necessary. I
|
||||
<details>
|
||||
<summary><strong>After running PHP Monitor, Homebrew sometimes has issues with `brew upgrade` or `brew cleanup`!</strong></summary>
|
||||
|
||||
This is a security feature of Homebrew. When you start a service as an administrator, the root user becomes the owner of relevant binaries. You will need to manually clean up those folders yourself using `rm -rf` (or by manually removing those folders via Finder).
|
||||
You can now use **First Aid & Services > Restore Homebrew Permissions** to (temporarily) resolve this issue and allow for a clean and painless `brew upgrade` or `brew cleanup` process.
|
||||
|
||||
If you would like to know more, consult [this issue](https://github.com/nicoverbruggen/phpmon/issues/85) for more information.
|
||||
If you would like to know more, consult [this issue](https://github.com/nicoverbruggen/phpmon/issues/85) for more information about why this is needed.
|
||||
|
||||
</details>
|
||||
|
||||
|
@ -34,7 +34,7 @@ class Actions {
|
||||
brew("services stop dnsmasq", sudo: true)
|
||||
}
|
||||
|
||||
public static func fixHomebrewPermissions()
|
||||
public static func fixHomebrewPermissions() throws
|
||||
{
|
||||
var servicesCommands = [
|
||||
"\(Paths.brew) services stop nginx",
|
||||
@ -65,10 +65,7 @@ class Actions {
|
||||
let eventResult: NSAppleEventDescriptor? = appleScript?.executeAndReturnError(nil)
|
||||
|
||||
if (eventResult == nil) {
|
||||
print("Oh no, that didn't work.")
|
||||
} else {
|
||||
NotificationCenter.default.post(name: Events.ServicesUpdated, object: nil)
|
||||
print("Oh, that worked.")
|
||||
throw HomebrewPermissionError(kind: .applescriptNilError)
|
||||
}
|
||||
}
|
||||
|
||||
|
13
phpmon-common/Errors/AlertableError.swift
Normal file
13
phpmon-common/Errors/AlertableError.swift
Normal file
@ -0,0 +1,13 @@
|
||||
//
|
||||
// Errors.swift
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 06/02/2022.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
protocol AlertableError {
|
||||
func getErrorMessageKey() -> String
|
||||
}
|
21
phpmon-common/Errors/HomebrewPermissionError.swift
Normal file
21
phpmon-common/Errors/HomebrewPermissionError.swift
Normal file
@ -0,0 +1,21 @@
|
||||
//
|
||||
// HomebrewPermissionError.swift
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 06/02/2022.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
struct HomebrewPermissionError: Error, AlertableError {
|
||||
enum Kind: String {
|
||||
case applescriptNilError = "homebrew_permissions.applescript_returned_nil"
|
||||
}
|
||||
|
||||
let kind: Kind
|
||||
|
||||
func getErrorMessageKey() -> String {
|
||||
return "alert.errors.\(self.kind.rawValue)"
|
||||
}
|
||||
}
|
@ -771,7 +771,7 @@ Gw
|
||||
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="600" id="iRQ-sz-oyv"/>
|
||||
</constraints>
|
||||
<scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="TDE-ff-DQT">
|
||||
<rect key="frame" x="1" y="293" width="598" height="15"/>
|
||||
<rect key="frame" x="1" y="292" width="598" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
<scroller key="verticalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="wFn-93-f10">
|
||||
@ -808,7 +808,7 @@ Gw
|
||||
</scenes>
|
||||
<resources>
|
||||
<image name="Checkmark" width="512" height="512"/>
|
||||
<image name="IconLinked" width="512" height="512"/>
|
||||
<image name="IconLinked" width="25" height="25"/>
|
||||
<image name="Lock" width="30" height="30"/>
|
||||
<image name="arrow.clockwise" catalog="system" width="14" height="16"/>
|
||||
<image name="plus" catalog="system" width="14" height="13"/>
|
||||
|
@ -60,4 +60,15 @@ class Alert {
|
||||
style: style
|
||||
)
|
||||
}
|
||||
|
||||
public static func notifyAbout(error: Error&AlertableError) {
|
||||
let key = error.getErrorMessageKey()
|
||||
_ = present(
|
||||
messageText: "\(key).title".localized,
|
||||
informativeText: "\(key).description".localized,
|
||||
buttonTitle: "OK",
|
||||
secondButtonTitle: "",
|
||||
style: .critical
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -87,29 +87,81 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate {
|
||||
|
||||
// MARK: - Nicer callbacks
|
||||
|
||||
enum AsyncBehaviour {
|
||||
case setsBusyUI
|
||||
case reloadsPhpInstallation
|
||||
case updatesMenuBarContents
|
||||
case broadcastServicesUpdate
|
||||
}
|
||||
|
||||
/**
|
||||
Executes a specific callback and fires the completion callback,
|
||||
while updating the UI as required. As long as the completion callback
|
||||
does not fire, the app is presumed to be busy and the UI reflects this.
|
||||
Attempts asynchronous execution of a callback that may throw an Error.
|
||||
While the callback is being executed, the UI will be marked as busy.
|
||||
|
||||
- Parameter execute: Callback of the work that needs to happen.
|
||||
- Parameter completion: Callback that is fired when the work is done.
|
||||
- Parameter success: Callback that is fired when all was OK.
|
||||
- Parameter failure: Callback that is fired when an Error was thrown.
|
||||
- Parameter behaviours: Various behaviours that can be tweaked, but usually best left to the default.
|
||||
*/
|
||||
private func waitAndExecute(_ execute: @escaping () -> Void, completion: @escaping () -> Void = {})
|
||||
{
|
||||
private func asyncExecution(
|
||||
_ execute: @escaping () throws -> Void,
|
||||
success: @escaping () -> Void = {},
|
||||
failure: @escaping (Error) -> Void = { _ in },
|
||||
behaviours: [AsyncBehaviour] = [
|
||||
.setsBusyUI,
|
||||
.reloadsPhpInstallation,
|
||||
.updatesMenuBarContents,
|
||||
.broadcastServicesUpdate
|
||||
]
|
||||
) {
|
||||
if behaviours.contains(.reloadsPhpInstallation) {
|
||||
PhpEnv.shared.isBusy = true
|
||||
}
|
||||
if behaviours.contains(.setsBusyUI) {
|
||||
setBusyImage()
|
||||
}
|
||||
DispatchQueue.global(qos: .userInitiated).async { [unowned self] in
|
||||
execute()
|
||||
var error: Error? = nil
|
||||
|
||||
do { try execute() } catch let e { error = e }
|
||||
|
||||
if behaviours.contains(.setsBusyUI) {
|
||||
PhpEnv.shared.isBusy = false
|
||||
}
|
||||
|
||||
DispatchQueue.main.async { [self] in
|
||||
if behaviours.contains(.reloadsPhpInstallation) {
|
||||
PhpEnv.shared.currentInstall = ActivePhpInstallation()
|
||||
}
|
||||
|
||||
if behaviours.contains(.updatesMenuBarContents) {
|
||||
// Refresh the entire menu bar menu's contents
|
||||
updatePhpVersionInStatusBar()
|
||||
} else {
|
||||
// We do still need to refresh the icon based on the busy state
|
||||
if behaviours.contains(.setsBusyUI) {
|
||||
refreshIcon()
|
||||
}
|
||||
}
|
||||
|
||||
if behaviours.contains(.broadcastServicesUpdate) {
|
||||
NotificationCenter.default.post(name: Events.ServicesUpdated, object: nil)
|
||||
}
|
||||
|
||||
error == nil ? success() : failure(error!)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func asyncWithBusyUI(
|
||||
_ execute: @escaping () throws -> Void,
|
||||
completion: @escaping () -> Void = {}
|
||||
) {
|
||||
asyncExecution({
|
||||
try! execute()
|
||||
}, success: {
|
||||
completion()
|
||||
}
|
||||
}
|
||||
}, behaviours: [.setsBusyUI])
|
||||
}
|
||||
|
||||
// MARK: - User Interface
|
||||
@ -146,14 +198,14 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate {
|
||||
}
|
||||
|
||||
@objc func reloadPhpMonitorMenuInBackground() {
|
||||
waitAndExecute {
|
||||
asyncExecution {
|
||||
// This automatically reloads the menu
|
||||
Log.info("Reloading information about the PHP installation (in the background)...")
|
||||
}
|
||||
}
|
||||
|
||||
@objc func reloadPhpMonitorMenu() {
|
||||
waitAndExecute {
|
||||
asyncExecution {
|
||||
// This automatically reloads the menu
|
||||
Log.info("Reloading information about the PHP installation...")
|
||||
}
|
||||
@ -168,21 +220,43 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate {
|
||||
// MARK: - Actions
|
||||
|
||||
@objc func fixHomebrewPermissions() {
|
||||
Actions.fixHomebrewPermissions()
|
||||
if !Alert.present(
|
||||
messageText: "alert.fix_homebrew_permissions.title".localized,
|
||||
informativeText: "alert.fix_homebrew_permissions.info".localized,
|
||||
buttonTitle: "alert.fix_homebrew_permissions.ok".localized,
|
||||
secondButtonTitle: "alert.fix_homebrew_permissions.cancel".localized,
|
||||
style: .warning
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
asyncExecution {
|
||||
try Actions.fixHomebrewPermissions()
|
||||
} success: {
|
||||
Alert.notify(
|
||||
message: "alert.fix_homebrew_permissions_done.title".localized,
|
||||
info: "alert.fix_homebrew_permissions_done.info".localized,
|
||||
style: .warning
|
||||
)
|
||||
} failure: { error in
|
||||
let error = error as! HomebrewPermissionError
|
||||
Alert.notifyAbout(error: error)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@objc func restartPhpFpm() {
|
||||
waitAndExecute {
|
||||
asyncExecution {
|
||||
Actions.restartPhpFpm()
|
||||
}
|
||||
}
|
||||
|
||||
@objc func restartAllServices() {
|
||||
waitAndExecute {
|
||||
asyncExecution {
|
||||
Actions.restartDnsMasq()
|
||||
Actions.restartPhpFpm()
|
||||
Actions.restartNginx()
|
||||
} completion: {
|
||||
} success: {
|
||||
DispatchQueue.main.async {
|
||||
LocalNotification.send(
|
||||
title: "notification.services_restarted".localized,
|
||||
@ -193,9 +267,9 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate {
|
||||
}
|
||||
|
||||
@objc func stopAllServices() {
|
||||
waitAndExecute {
|
||||
asyncExecution {
|
||||
Actions.stopAllServices()
|
||||
} completion: {
|
||||
} success: {
|
||||
DispatchQueue.main.async {
|
||||
LocalNotification.send(
|
||||
title: "notification.services_stopped".localized,
|
||||
@ -206,19 +280,19 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate {
|
||||
}
|
||||
|
||||
@objc func restartNginx() {
|
||||
waitAndExecute {
|
||||
asyncExecution {
|
||||
Actions.restartNginx()
|
||||
}
|
||||
}
|
||||
|
||||
@objc func restartDnsMasq() {
|
||||
waitAndExecute {
|
||||
asyncExecution {
|
||||
Actions.restartDnsMasq()
|
||||
}
|
||||
}
|
||||
|
||||
@objc func toggleExtension(sender: ExtensionMenuItem) {
|
||||
waitAndExecute {
|
||||
asyncExecution {
|
||||
sender.phpExtension?.toggle()
|
||||
|
||||
if Preferences.isEnabled(.autoServiceRestartAfterExtensionToggle) {
|
||||
@ -230,35 +304,33 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate {
|
||||
@objc func openPhpInfo() {
|
||||
var url: URL? = nil
|
||||
|
||||
waitAndExecute {
|
||||
asyncWithBusyUI {
|
||||
url = Actions.createTempPhpInfoFile()
|
||||
} completion: {
|
||||
// When this has been completed, open the URL to the file in the browser
|
||||
NSWorkspace.shared.open(url!)
|
||||
if url != nil { NSWorkspace.shared.open(url!) }
|
||||
}
|
||||
}
|
||||
|
||||
@objc func fixMyValet() {
|
||||
// Tell the user the switch is about to occur
|
||||
if Alert.present(
|
||||
if !Alert.present(
|
||||
messageText: "alert.fix_my_valet.title".localized,
|
||||
informativeText: "alert.fix_my_valet.info".localized(PhpEnv.brewPhpVersion),
|
||||
buttonTitle: "alert.fix_my_valet.ok".localized,
|
||||
secondButtonTitle: "alert.fix_my_valet.cancel".localized,
|
||||
style: .warning
|
||||
) {
|
||||
// Start the fix
|
||||
waitAndExecute {
|
||||
Log.info("The user has chosen to abort Fix My Valet")
|
||||
return
|
||||
}
|
||||
|
||||
asyncExecution {
|
||||
Actions.fixMyValet()
|
||||
} completion: {
|
||||
} success: {
|
||||
Alert.notify(
|
||||
message: "alert.fix_my_valet_done.title".localized,
|
||||
info: "alert.fix_my_valet_done.info".localized
|
||||
)
|
||||
}
|
||||
} else {
|
||||
Log.info("The user has chosen to abort Fix My Valet")
|
||||
}
|
||||
}
|
||||
|
||||
@objc func updateGlobalComposerDependencies() {
|
||||
@ -288,7 +360,6 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate {
|
||||
self.switchToPhpVersion(sender.version)
|
||||
}
|
||||
|
||||
// TODO (5.1): Investigate if `waitAndExecute` cannot be used here
|
||||
@objc func switchToPhpVersion(_ version: String) {
|
||||
setBusyImage()
|
||||
PhpEnv.shared.isBusy = true
|
||||
|
@ -46,19 +46,19 @@ class StatusMenu : NSMenu {
|
||||
if !PhpEnv.shared.availablePhpVersions.contains(PhpEnv.brewPhpVersion) {
|
||||
servicesMenu.addItem(NSMenuItem(
|
||||
title: "mi_fix_my_valet_unavailable".localized(PhpEnv.brewPhpVersion),
|
||||
action: nil, keyEquivalent: "f"
|
||||
))
|
||||
action: nil, keyEquivalent: "f")
|
||||
)
|
||||
} else {
|
||||
servicesMenu.addItem(NSMenuItem(
|
||||
title: "mi_fix_my_valet".localized(PhpEnv.brewPhpVersion),
|
||||
action: #selector(MainMenu.fixMyValet), keyEquivalent: ""))
|
||||
action: #selector(MainMenu.fixMyValet), keyEquivalent: "")
|
||||
)
|
||||
}
|
||||
|
||||
/*
|
||||
servicesMenu.addItem(NSMenuItem(
|
||||
title: "mi_fix_brew_permissions".localized(),
|
||||
action: #selector(MainMenu.fixHomebrewPermissions), keyEquivalent: ""))
|
||||
*/
|
||||
action: #selector(MainMenu.fixHomebrewPermissions), keyEquivalent: "")
|
||||
)
|
||||
|
||||
servicesMenu.addItem(NSMenuItem(title: "mi_services".localized, action: nil, keyEquivalent: ""))
|
||||
|
||||
|
@ -27,7 +27,7 @@
|
||||
"mi_stop_all_services" = "Stop All Services";
|
||||
"mi_fix_my_valet" = "Fix My Valet (PHP & Services)";
|
||||
"mi_fix_my_valet_unavailable" = "Fix My Valet Unavailable";
|
||||
"mi_fix_brew_permissions" = "Fix Homebrew Permissions";
|
||||
"mi_fix_brew_permissions" = "Restore Homebrew Permissions";
|
||||
"mi_php_refresh" = "Refresh Information";
|
||||
|
||||
"mi_configuration" = "PHP Configuration";
|
||||
@ -214,6 +214,15 @@ problem manually, using your own Terminal app (this just shows you the output)."
|
||||
"alert.fix_my_valet_done.title" = "Fix My Valet has completed its operations.";
|
||||
"alert.fix_my_valet_done.info" = "All appropriate services have been stopped and the correct ones restarted, and the latest version of PHP should now be active. You can now try switching to another version of PHP.\n\nIf visiting sites still does not work, you may try running `valet install` again, this can fix a 502 issue (Bad Gateway).\n\nIf Valet is broken and you cannot run `valet install`, you may need to run `composer global update`. Please consult the FAQ on GitHub if you have further issues.";
|
||||
|
||||
// Restore Homebrew Permissions
|
||||
"alert.fix_homebrew_permissions.title" = "About \"Restore Homebrew Permissions\"";
|
||||
"alert.fix_homebrew_permissions.info" = "This feature was created so you can run `brew upgrade` or `brew cleanup` without permission issues.\n\nThis will require administrative privileges, because PHP Monitor will restore your ownership of the files and folders that are currently owned by the `root` user, due to Valet services running as root.\n\n(You will be notified when this fix has been applied.)";
|
||||
"alert.fix_homebrew_permissions.ok" = "Restore Permissions";
|
||||
"alert.fix_homebrew_permissions.cancel" = "Cancel";
|
||||
|
||||
"alert.fix_homebrew_permissions_done.title" = "Permissions Fixed!";
|
||||
"alert.fix_homebrew_permissions_done.info" = "When you are done with Homebrew, you should open PHP Monitor and restart all services if you want Valet to work again. It is also recommended to restart PHP Monitor after running `brew upgrade`.";
|
||||
|
||||
// PHP FPM Broken
|
||||
"alert.php_fpm_broken.title" = "PHP-FPM configuration is incorrect";
|
||||
"alert.php_fpm_broken.info" = "PHP Monitor has determined that there are issues with your PHP-FPM config: it's not pointing to the Valet socket. This will result in 502 Bad Gateway if you visit websites linked via Valet.\n\nYou can usually fix this by running\n`valet install`, which updates your\n PHP-FPM configuration.";
|
||||
@ -279,3 +288,8 @@ You can do this by running `composer global update` in your terminal. After that
|
||||
"startup.sponsor_encouragement.desc" = "If you have already donated, then YOU are the reason why the app was able to get all these new features. In that case, this is a THANK YOU message to you.\n\nTo be 100% transparent: I plan to keep PHP Monitor open source and free. Your support makes this decision very easy.\n\n(You will only see this prompt once.)";
|
||||
"startup.sponsor_encouragement.accept" = "Yes, I would like to sponsor";
|
||||
"startup.sponsor_encouragement.skip" = "Nevermind";
|
||||
|
||||
// ERROR MESSAGES (based on AlertableError)
|
||||
|
||||
"alert.errors.homebrew_permissions.applescript_returned_nil.title" = "Restore Homebrew Permissions has been cancelled.";
|
||||
"alert.errors.homebrew_permissions.applescript_returned_nil.description" = "The outcome of the script that is executed to adjust the permissions returned nil, which usually means that you did not grant administrative permissions to PHP Monitor.\n\nIf you clicked on Cancel during the authentication prompt, this is normal. If you did actually authenticate and you are still seeing this message, something probably went wrong.";
|
||||
|
Reference in New Issue
Block a user