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

Add option to automatically run composer global update

This commit is contained in:
2021-12-18 19:45:50 +01:00
parent 3f0f070245
commit ed49362291
10 changed files with 328 additions and 40 deletions

View File

@ -46,6 +46,10 @@
C43A8A1A25D9CD1000591B77 /* Utility.swift in Sources */ = {isa = PBXBuildFile; fileRef = C43A8A1925D9CD1000591B77 /* Utility.swift */; }; C43A8A1A25D9CD1000591B77 /* Utility.swift in Sources */ = {isa = PBXBuildFile; fileRef = C43A8A1925D9CD1000591B77 /* Utility.swift */; };
C43A8A2025D9D1D700591B77 /* brew.json in Resources */ = {isa = PBXBuildFile; fileRef = C43A8A1F25D9D1D700591B77 /* brew.json */; }; C43A8A2025D9D1D700591B77 /* brew.json in Resources */ = {isa = PBXBuildFile; fileRef = C43A8A1F25D9D1D700591B77 /* brew.json */; };
C43A8A2425D9D20D00591B77 /* BrewJsonParserTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C43A8A2325D9D20D00591B77 /* BrewJsonParserTest.swift */; }; C43A8A2425D9D20D00591B77 /* BrewJsonParserTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C43A8A2325D9D20D00591B77 /* BrewJsonParserTest.swift */; };
C44C198D276E3A1C0072762D /* ProgressWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = C44C198C276E3A1C0072762D /* ProgressWindow.swift */; };
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 */; };
C464ADAC275A7A3F003FCD53 /* SiteListWC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C464ADAB275A7A3F003FCD53 /* SiteListWC.swift */; }; C464ADAC275A7A3F003FCD53 /* SiteListWC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C464ADAB275A7A3F003FCD53 /* SiteListWC.swift */; };
C464ADAD275A7A3F003FCD53 /* 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 */; }; C464ADAF275A7A69003FCD53 /* SiteListVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C464ADAE275A7A69003FCD53 /* SiteListVC.swift */; };
@ -164,6 +168,8 @@
C43A8A1925D9CD1000591B77 /* Utility.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Utility.swift; sourceTree = "<group>"; }; C43A8A1925D9CD1000591B77 /* Utility.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Utility.swift; sourceTree = "<group>"; };
C43A8A1F25D9D1D700591B77 /* brew.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = brew.json; sourceTree = "<group>"; }; C43A8A1F25D9D1D700591B77 /* brew.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = brew.json; sourceTree = "<group>"; };
C43A8A2325D9D20D00591B77 /* BrewJsonParserTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrewJsonParserTest.swift; sourceTree = "<group>"; }; 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>"; };
C464ADAB275A7A3F003FCD53 /* SiteListWC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SiteListWC.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>"; }; 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>"; }; C464ADB1275A87CA003FCD53 /* SiteListCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SiteListCell.swift; sourceTree = "<group>"; };
@ -325,12 +331,22 @@
C47331A0247093AC009A0597 /* Menu */, C47331A0247093AC009A0597 /* Menu */,
C464ADAA275A7A25003FCD53 /* SiteList */, C464ADAA275A7A25003FCD53 /* SiteList */,
5420395726135DB800FB00FA /* Preferences */, 5420395726135DB800FB00FA /* Preferences */,
C44C198F276E3A380072762D /* Progress */,
C4811D2822D70D9C00B5F6B3 /* Helpers */, C4811D2822D70D9C00B5F6B3 /* Helpers */,
C4F8C0A222D4F100002EFE61 /* Extensions */, C4F8C0A222D4F100002EFE61 /* Extensions */,
); );
path = Domain; path = Domain;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
C44C198F276E3A380072762D /* Progress */ = {
isa = PBXGroup;
children = (
C44C198C276E3A1C0072762D /* ProgressWindow.swift */,
C44C1990276E44CB0072762D /* ProgressWindow.storyboard */,
);
path = Progress;
sourceTree = "<group>";
};
C464ADAA275A7A25003FCD53 /* SiteList */ = { C464ADAA275A7A25003FCD53 /* SiteList */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@ -544,6 +560,7 @@
C4AF9F71275445FF00D44ED0 /* valet-config.json in Resources */, C4AF9F71275445FF00D44ED0 /* valet-config.json in Resources */,
C48D0C9025CC7FD000CC7490 /* StatsView.xib in Resources */, C48D0C9025CC7FD000CC7490 /* StatsView.xib in Resources */,
C405A4D124B9B9140062FAFA /* InternetAccessPolicy.plist in Resources */, C405A4D124B9B9140062FAFA /* InternetAccessPolicy.plist in Resources */,
C44C1991276E44CB0072762D /* ProgressWindow.storyboard in Resources */,
C4232EE52612526500158FC6 /* Credits.html in Resources */, C4232EE52612526500158FC6 /* Credits.html in Resources */,
54FCFD26276C883F004CE748 /* CheckboxPreferenceView.xib in Resources */, 54FCFD26276C883F004CE748 /* CheckboxPreferenceView.xib in Resources */,
C473319F2470923A009A0597 /* Localizable.strings in Resources */, C473319F2470923A009A0597 /* Localizable.strings in Resources */,
@ -562,6 +579,7 @@
C4F780A825D80AE8000DBC97 /* php.ini in Resources */, C4F780A825D80AE8000DBC97 /* php.ini in Resources */,
C43A8A2025D9D1D700591B77 /* brew.json in Resources */, C43A8A2025D9D1D700591B77 /* brew.json in Resources */,
C4AF9F72275445FF00D44ED0 /* valet-config.json in Resources */, C4AF9F72275445FF00D44ED0 /* valet-config.json in Resources */,
C44C1992276E44CB0072762D /* ProgressWindow.storyboard in Resources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -589,6 +607,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 */,
C44C198D276E3A1C0072762D /* ProgressWindow.swift in Sources */,
54B48B5F275F66AE006D90C5 /* Application.swift in Sources */, 54B48B5F275F66AE006D90C5 /* Application.swift in Sources */,
C4B97B78275CF1B5003F3378 /* App+ActivationPolicy.swift in Sources */, C4B97B78275CF1B5003F3378 /* App+ActivationPolicy.swift in Sources */,
C4811D2422D70A4700B5F6B3 /* App.swift in Sources */, C4811D2422D70A4700B5F6B3 /* App.swift in Sources */,
@ -661,6 +680,7 @@
C4F780BD25D80B65000DBC97 /* Constants.swift in Sources */, C4F780BD25D80B65000DBC97 /* Constants.swift in Sources */,
C4F780C325D80B75000DBC97 /* HeaderView.swift in Sources */, C4F780C325D80B75000DBC97 /* HeaderView.swift in Sources */,
C4F7809625D7FBF8000DBC97 /* Shell.swift in Sources */, C4F7809625D7FBF8000DBC97 /* Shell.swift in Sources */,
C44C198E276E3A1C0072762D /* ProgressWindow.swift in Sources */,
C4AF9F7D275454A900D44ED0 /* ValetTest.swift in Sources */, C4AF9F7D275454A900D44ED0 /* ValetTest.swift in Sources */,
C4B56362276AB0A500F12CCB /* VersionExtractorTest.swift in Sources */, C4B56362276AB0A500F12CCB /* VersionExtractorTest.swift in Sources */,
C4F780C525D80B75000DBC97 /* MenuBarImageGenerator.swift in Sources */, C4F780C525D80B75000DBC97 /* MenuBarImageGenerator.swift in Sources */,
@ -825,7 +845,7 @@
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 135; CURRENT_PROJECT_VERSION = 200;
DEVELOPMENT_TEAM = 8M54J5J787; DEVELOPMENT_TEAM = 8M54J5J787;
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = YES;
INFOPLIST_FILE = phpmon/Info.plist; INFOPLIST_FILE = phpmon/Info.plist;
@ -834,7 +854,7 @@
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MACOSX_DEPLOYMENT_TARGET = 11.0; MACOSX_DEPLOYMENT_TARGET = 11.0;
MARKETING_VERSION = "4.1-rc4"; MARKETING_VERSION = "5.0-wip";
PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon; PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
@ -850,7 +870,7 @@
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 135; CURRENT_PROJECT_VERSION = 200;
DEVELOPMENT_TEAM = 8M54J5J787; DEVELOPMENT_TEAM = 8M54J5J787;
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = YES;
INFOPLIST_FILE = phpmon/Info.plist; INFOPLIST_FILE = phpmon/Info.plist;
@ -859,7 +879,7 @@
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MACOSX_DEPLOYMENT_TARGET = 11.0; MACOSX_DEPLOYMENT_TARGET = 11.0;
MARKETING_VERSION = "4.1-rc4"; MARKETING_VERSION = "5.0-wip";
PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon; PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";

View File

@ -25,6 +25,18 @@ class PMWindowController: NSWindowController, NSWindowDelegate {
App.shared.register(window: windowName) App.shared.register(window: windowName)
} }
func windowWillClose(_ notification: Notification) {
App.shared.remove(window: windowName)
}
deinit {
print("Window controller '\(windowName)' was deinitialized")
}
}
extension NSWindowController {
public func positionWindowInTopLeftCorner() { public func positionWindowInTopLeftCorner() {
guard let frame = NSScreen.main?.frame else { return } guard let frame = NSScreen.main?.frame else { return }
guard let window = self.window else { return } guard let window = self.window else { return }
@ -37,12 +49,4 @@ class PMWindowController: NSWindowController, NSWindowDelegate {
), display: true) ), display: true)
} }
func windowWillClose(_ notification: Notification) {
App.shared.remove(window: windowName)
}
deinit {
print("Window controller '\(windowName)' was deinitialized")
}
} }

View File

@ -328,6 +328,16 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate {
} }
@objc func updateComposerDependencies() { @objc func updateComposerDependencies() {
self.updateGlobalDependencies(notify: true, completion: { _ in })
}
func updateGlobalDependencies(notify: Bool, completion: @escaping (Bool) -> Void) {
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 { DispatchQueue.global(qos: .userInitiated).async {
let output = Shell.user.executeSynchronously( let output = Shell.user.executeSynchronously(
"composer global update", requiresPath: true "composer global update", requiresPath: true
@ -335,33 +345,49 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate {
let task = Shell.user.createTask(for: "composer global update", requiresPath: true) let task = Shell.user.createTask(for: "composer global update", requiresPath: true)
DispatchQueue.main.async {
window?.addToConsole("composer global update\n")
}
Shell.captureOutput( Shell.captureOutput(
task, task,
didReceiveStdOutData: { string in didReceiveStdOutData: { string in
DispatchQueue.main.async {
window?.addToConsole(string)
}
print("\(string.trimmingCharacters(in: .newlines))") print("\(string.trimmingCharacters(in: .newlines))")
}, },
didReceiveStdErrData: { string in didReceiveStdErrData: { string in
DispatchQueue.main.async {
window?.addToConsole(string)
}
print("\(string.trimmingCharacters(in: .newlines))") print("\(string.trimmingCharacters(in: .newlines))")
} }
) )
task.launch() task.launch()
task.waitUntilExit() task.waitUntilExit()
Shell.haltCapturingOutput(task)
DispatchQueue.main.async { DispatchQueue.main.async {
if output.task.terminationStatus > 0 { if output.task.terminationStatus <= 0 {
// Error code means > 0 DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
Alert.notify( window?.close()
message: "alert.composer_failure.title".localized, if (notify) {
info: "alert.composer_failure.info".localized, LocalNotification.send(
style: .critical title: "alert.composer_success.title".localized,
) subtitle: "alert.composer_success.info".localized
)
}
window = nil
completion(true)
}
} else { } else {
// Error code -1 is OK window?.setType(info: false)
LocalNotification.send( window?.progressView?.labelTitle.stringValue = "alert.composer_failure.title".localized
title: "alert.composer_success.title".localized, window?.progressView?.labelDescription.stringValue = "alert.composer_failure.info".localized
subtitle: "alert.composer_success.info".localized window = nil
) completion(false)
} }
} }
} }
@ -406,13 +432,22 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate {
updatePhpVersionInStatusBar() updatePhpVersionInStatusBar()
update() update()
// Send a notification that the switch has been completed let sendLocalNotification = {
LocalNotification.send( LocalNotification.send(
title: String(format: "notification.version_changed_title".localized, sender.version), title: String(format: "notification.version_changed_title".localized, sender.version),
subtitle: String(format: "notification.version_changed_desc".localized, sender.version) subtitle: String(format: "notification.version_changed_desc".localized, sender.version)
) )
App.phpInstall?.notifyAboutBrokenPhpFpm()
}
App.phpInstall?.notifyAboutBrokenPhpFpm() // Run composer updates
if Preferences.preferences[.autoComposerGlobalUpdateAfterSwitch] as! Bool == true {
self.updateGlobalDependencies(notify: false, completion: { success in
sendLocalNotification()
})
} else {
sendLocalNotification()
}
} }
} }

View File

@ -13,6 +13,7 @@ enum PreferenceName: String {
case shouldDisplayDynamicIcon = "use_dynamic_icon" case shouldDisplayDynamicIcon = "use_dynamic_icon"
case fullPhpVersionDynamicIcon = "full_php_in_menu_bar" case fullPhpVersionDynamicIcon = "full_php_in_menu_bar"
case autoServiceRestartAfterExtensionToggle = "auto_restart_after_extension_toggle" case autoServiceRestartAfterExtensionToggle = "auto_restart_after_extension_toggle"
case autoComposerGlobalUpdateAfterSwitch = "auto_composer_global_update_after_switch"
case useInternalSwitcher = "use_phpmon_switcher" case useInternalSwitcher = "use_phpmon_switcher"
case globalHotkey = "global_hotkey" case globalHotkey = "global_hotkey"
} }
@ -47,7 +48,8 @@ class Preferences {
PreferenceName.shouldDisplayDynamicIcon.rawValue: true, PreferenceName.shouldDisplayDynamicIcon.rawValue: true,
PreferenceName.fullPhpVersionDynamicIcon.rawValue: false, PreferenceName.fullPhpVersionDynamicIcon.rawValue: false,
PreferenceName.autoServiceRestartAfterExtensionToggle.rawValue: true, PreferenceName.autoServiceRestartAfterExtensionToggle.rawValue: true,
PreferenceName.useInternalSwitcher.rawValue: false PreferenceName.autoComposerGlobalUpdateAfterSwitch.rawValue: false,
PreferenceName.useInternalSwitcher.rawValue: false,
]) ])
if UserDefaults.standard.bool(forKey: PreferenceName.wasLaunchedBefore.rawValue) { if UserDefaults.standard.bool(forKey: PreferenceName.wasLaunchedBefore.rawValue) {
@ -72,6 +74,7 @@ class Preferences {
.shouldDisplayDynamicIcon: UserDefaults.standard.bool(forKey: PreferenceName.shouldDisplayDynamicIcon.rawValue) as Any, .shouldDisplayDynamicIcon: UserDefaults.standard.bool(forKey: PreferenceName.shouldDisplayDynamicIcon.rawValue) as Any,
.fullPhpVersionDynamicIcon: UserDefaults.standard.bool(forKey: PreferenceName.fullPhpVersionDynamicIcon.rawValue) as Any, .fullPhpVersionDynamicIcon: UserDefaults.standard.bool(forKey: PreferenceName.fullPhpVersionDynamicIcon.rawValue) as Any,
.autoServiceRestartAfterExtensionToggle: UserDefaults.standard.bool(forKey: PreferenceName.autoServiceRestartAfterExtensionToggle.rawValue) as Any, .autoServiceRestartAfterExtensionToggle: UserDefaults.standard.bool(forKey: PreferenceName.autoServiceRestartAfterExtensionToggle.rawValue) as Any,
.autoComposerGlobalUpdateAfterSwitch: UserDefaults.standard.bool(forKey: PreferenceName.autoComposerGlobalUpdateAfterSwitch.rawValue) as Any,
.useInternalSwitcher: UserDefaults.standard.bool(forKey: PreferenceName.useInternalSwitcher.rawValue) as Any, .useInternalSwitcher: UserDefaults.standard.bool(forKey: PreferenceName.useInternalSwitcher.rawValue) as Any,
// Part 2: Always Strings // Part 2: Always Strings

View File

@ -74,6 +74,13 @@ class PrefsVC: NSViewController {
preference: .autoServiceRestartAfterExtensionToggle, preference: .autoServiceRestartAfterExtensionToggle,
action: {} action: {}
), ),
CheckboxPreferenceView.make(
sectionText: "prefs.switcher".localized,
descriptionText: "prefs.auto_composer_update_desc".localized,
checkboxText: "prefs.auto_composer_update_title".localized,
preference: .autoComposerGlobalUpdateAfterSwitch,
action: {}
),
/* DISABLED UNTIL VALET SWITCHING IS OK (see #34) /* DISABLED UNTIL VALET SWITCHING IS OK (see #34)
CheckboxPreferenceView.make( CheckboxPreferenceView.make(
sectionText: "", sectionText: "",

View File

@ -21,12 +21,6 @@ class PrefsWC: PMWindowController {
return "Preferences" return "Preferences"
} }
// MARK: - Window Lifecycle
override func windowDidLoad() {
super.windowDidLoad()
}
// MARK: - Key Interaction // MARK: - Key Interaction
override func keyDown(with event: NSEvent) { override func keyDown(with event: NSEvent) {

View File

@ -0,0 +1,135 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="19529" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="19529"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Window Controller-->
<scene sceneID="pUZ-6w-gUX">
<objects>
<windowController storyboardIdentifier="progressWindow" id="LSr-Iw-X1T" customClass="ProgressWindowController" customModule="PHP_Monitor" customModuleProvider="target" sceneMemberID="viewController">
<window key="window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="none" frameAutosaveName="" titlebarAppearsTransparent="YES" titleVisibility="hidden" id="PD9-0p-i0S" customClass="NSPanel">
<windowStyleMask key="styleMask" titled="YES" closable="YES" utility="YES" HUD="YES"/>
<windowPositionMask key="initialPositionMask" rightStrut="YES" topStrut="YES"/>
<rect key="contentRect" x="2080" y="1145" width="480" height="270"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1415"/>
<view key="contentView" id="QOA-qf-m1l">
<rect key="frame" x="0.0" y="0.0" width="480" height="270"/>
<autoresizingMask key="autoresizingMask"/>
</view>
<connections>
<outlet property="delegate" destination="LSr-Iw-X1T" id="uEN-dQ-Jv4"/>
</connections>
</window>
<connections>
<segue destination="c01-Tm-OtR" kind="relationship" relationship="window.shadowedContentViewController" id="uNS-tY-qB9"/>
</connections>
</windowController>
<customObject id="aGV-xt-u13" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-313" y="-6"/>
</scene>
<!--Progress View Controller-->
<scene sceneID="XgN-R6-44T">
<objects>
<viewController id="c01-Tm-OtR" customClass="ProgressViewController" customModule="PHP_Monitor" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" id="0fd-qq-0ME">
<rect key="frame" x="0.0" y="0.0" width="591" height="270"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<scrollView borderType="none" autohidesScrollers="YES" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" hasVerticalScroller="NO" horizontalScrollElasticity="none" findBarPosition="aboveHorizontalRuler" translatesAutoresizingMaskIntoConstraints="NO" id="JK7-kL-1L3">
<rect key="frame" x="0.0" y="0.0" width="591" height="210"/>
<clipView key="contentView" drawsBackground="NO" id="2Mc-oy-AzN">
<rect key="frame" x="0.0" y="0.0" width="591" height="210"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textView importsGraphics="NO" richText="NO" verticallyResizable="YES" smartInsertDelete="YES" id="d1T-N1-CRe">
<rect key="frame" x="0.0" y="0.0" width="591" height="210"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<size key="minSize" width="591" height="210"/>
<size key="maxSize" width="757" height="10000000"/>
<attributedString key="textStorage">
<fragment content="$ ">
<attributes>
<color key="NSColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<font key="NSFont" size="10" name="Menlo-Regular"/>
<paragraphStyle key="NSParagraphStyle" alignment="natural" lineBreakMode="wordWrapping" baseWritingDirection="natural" tighteningFactorForTruncation="0.0"/>
</attributes>
</fragment>
</attributedString>
<color key="insertionPointColor" name="textColor" catalog="System" colorSpace="catalog"/>
</textView>
</subviews>
</clipView>
<scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="YES" id="51v-CN-AuA">
<rect key="frame" x="-100" y="-100" width="225" height="15"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="NO" id="lSO-JG-QOf">
<rect key="frame" x="-100" y="-100" width="15" height="173"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
</scrollView>
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="9c0-5U-sVK">
<rect key="frame" x="69" y="242" width="504" height="16"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="TITLE" id="oyI-D5-kEd">
<font key="font" metaFont="systemBold"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="7Be-eK-EcJ">
<rect key="frame" x="69" y="226" width="504" height="14"/>
<constraints>
<constraint firstAttribute="width" constant="500" id="0kb-4B-ZF3"/>
</constraints>
<textFieldCell key="cell" title="DESC" id="V0K-KF-leA">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<imageView horizontalHuggingPriority="750" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="LiM-ZV-F8j">
<rect key="frame" x="20" y="224" width="36" height="36"/>
<constraints>
<constraint firstAttribute="height" constant="36" id="ddK-Ha-wqT"/>
<constraint firstAttribute="width" constant="36" id="pHp-9H-nhF"/>
</constraints>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="NSInfo" id="GWi-hE-LOJ"/>
</imageView>
</subviews>
<constraints>
<constraint firstItem="9c0-5U-sVK" firstAttribute="top" secondItem="LiM-ZV-F8j" secondAttribute="top" constant="2" id="0YJ-RT-kYE"/>
<constraint firstAttribute="bottom" secondItem="JK7-kL-1L3" secondAttribute="bottom" id="5Yv-2h-nea"/>
<constraint firstItem="9c0-5U-sVK" firstAttribute="leading" secondItem="LiM-ZV-F8j" secondAttribute="trailing" constant="15" id="EUV-hs-udj"/>
<constraint firstItem="LiM-ZV-F8j" firstAttribute="top" secondItem="0fd-qq-0ME" secondAttribute="top" constant="10" id="Ovb-Nu-ftR"/>
<constraint firstItem="JK7-kL-1L3" firstAttribute="top" secondItem="7Be-eK-EcJ" secondAttribute="bottom" constant="16" id="PYn-gt-Akk"/>
<constraint firstAttribute="trailing" secondItem="9c0-5U-sVK" secondAttribute="trailing" constant="20" symbolic="YES" id="TgO-ax-DGp"/>
<constraint firstItem="LiM-ZV-F8j" firstAttribute="leading" secondItem="0fd-qq-0ME" secondAttribute="leading" constant="20" symbolic="YES" id="ang-xM-Zmh"/>
<constraint firstAttribute="trailing" secondItem="JK7-kL-1L3" secondAttribute="trailing" id="atA-67-BQF"/>
<constraint firstItem="JK7-kL-1L3" firstAttribute="leading" secondItem="0fd-qq-0ME" secondAttribute="leading" id="gwR-eH-CmM"/>
<constraint firstItem="7Be-eK-EcJ" firstAttribute="top" secondItem="9c0-5U-sVK" secondAttribute="bottom" constant="2" id="jdR-1x-xta"/>
<constraint firstItem="7Be-eK-EcJ" firstAttribute="leading" secondItem="LiM-ZV-F8j" secondAttribute="trailing" constant="15" id="loj-L6-5NK"/>
<constraint firstAttribute="trailing" secondItem="7Be-eK-EcJ" secondAttribute="trailing" constant="20" symbolic="YES" id="sgd-u4-k0O"/>
</constraints>
</view>
<connections>
<outlet property="imageViewType" destination="LiM-ZV-F8j" id="yIU-aW-YFL"/>
<outlet property="labelDescription" destination="7Be-eK-EcJ" id="qui-Ub-y5U"/>
<outlet property="labelTitle" destination="9c0-5U-sVK" id="Iy3-Ym-pA9"/>
<outlet property="textView" destination="d1T-N1-CRe" id="pWp-W1-aus"/>
</connections>
</viewController>
<customObject id="oqT-7w-frK" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="266.5" y="18"/>
</scene>
</scenes>
<resources>
<image name="NSInfo" width="32" height="32"/>
</resources>
</document>

View File

@ -0,0 +1,76 @@
//
// ProgressView.swift
// PHP Monitor
//
// Created by Nico Verbruggen on 18/12/2021.
// Copyright © 2021 Nico Verbruggen. All rights reserved.
//
import Foundation
import AppKit
class ProgressWindowController: NSWindowController, NSWindowDelegate {
static func display(title: String, description: String) -> ProgressWindowController {
let storyboard = NSStoryboard(name: "ProgressWindow" , bundle : nil)
let windowController = storyboard.instantiateController(
withIdentifier: "progressWindow"
) as! ProgressWindowController
windowController.showWindow(windowController)
windowController.window?.makeKeyAndOrderFront(nil)
windowController.positionWindowInTopLeftCorner()
windowController.progressView?.labelTitle.stringValue = title
windowController.progressView?.labelDescription.stringValue = description
NSApp.activate(ignoringOtherApps: true)
return windowController
}
var progressView: ProgressViewController? {
return self.contentViewController as? ProgressViewController
}
public func addToConsole(_ string: String) {
guard let textView = self.progressView?.textView else {
return
}
textView.string = textView.string + string
textView.scrollToEndOfDocument(nil)
}
public func setType(info: Bool = true) {
guard let imageView = self.progressView?.imageViewType else {
return
}
imageView.image = NSImage(named: info ? "NSInfo" : "NSCaution")
}
func windowWillClose(_ notification: Notification) {
self.contentViewController = nil
}
deinit {
print("Deinitializing Progress Window Controller")
}
}
class ProgressViewController: NSViewController {
@IBOutlet weak var labelTitle: NSTextField!
@IBOutlet weak var labelDescription: NSTextField!
@IBOutlet var textView: NSTextView!
@IBOutlet weak var imageViewType: NSImageView!
deinit {
print("Deinitializing Progress View Controller")
}
}

View File

@ -153,6 +153,15 @@ class Shell {
} }
} }
} }
static func haltCapturingOutput(_ task: Process) {
if let pipe = task.standardOutput as? Pipe {
NotificationCenter.default.removeObserver(pipe.fileHandleForReading)
}
if let pipe = task.standardError as? Pipe {
NotificationCenter.default.removeObserver(pipe.fileHandleForReading)
}
}
} }
class ShellOutput { class ShellOutput {

View File

@ -90,6 +90,7 @@
"prefs.global_shortcut" = "Global shortcut:"; "prefs.global_shortcut" = "Global shortcut:";
"prefs.dynamic_icon" = "Dynamic icon:"; "prefs.dynamic_icon" = "Dynamic icon:";
"prefs.services" = "Services:"; "prefs.services" = "Services:";
"prefs.switcher" = "Switcher:";
"prefs.auto_restart_services_title" = "Auto-restart PHP-FPM"; "prefs.auto_restart_services_title" = "Auto-restart PHP-FPM";
"prefs.auto_restart_services_desc" = "When checked, will automatically restart PHP-FPM when\nyou check or uncheck an extension. Slightly slower when enabled, \nbut this applies the extension change immediately for all sites \nyou're serving, no need to restart PHP-FPM manually."; "prefs.auto_restart_services_desc" = "When checked, will automatically restart PHP-FPM when\nyou check or uncheck an extension. Slightly slower when enabled, \nbut this applies the extension change immediately for all sites \nyou're serving, no need to restart PHP-FPM manually.";
@ -109,6 +110,9 @@ use PHP Monitor's own switcher which is slightly faster,
but might cause issues with permissions in your Homebrew but might cause issues with permissions in your Homebrew
directories, since PHP Monitor controls the services."; directories, since PHP Monitor controls the services.";
"prefs.auto_composer_update_title" = "Automatically run `composer global update`";
"prefs.auto_composer_update_desc" = "When checked, will automatically ask Composer to run\n`global update` whenever you switch versions. This will update\nall global dependencies every time you switch.";
"prefs.shortcut_set" = "Set global shortcut"; "prefs.shortcut_set" = "Set global shortcut";
"prefs.shortcut_listening" = "<listening for keypress>"; "prefs.shortcut_listening" = "<listening for keypress>";
"prefs.shortcut_clear" = "Clear"; "prefs.shortcut_clear" = "Clear";
@ -131,13 +135,14 @@ directories, since PHP Monitor controls the services.";
// ALERTS // ALERTS
// Composer Update // Composer Update
"alert.composer_progress.title" = "Updating global dependencies...";
"alert.composer_progress.info" = "Your global Composer dependencies are being updated. Please wait a bit!";
"alert.composer_success.title" = "Global dependencies updated"; "alert.composer_success.title" = "Global dependencies updated";
"alert.composer_success.info" = "Your global Composer dependencies have been updated."; "alert.composer_success.info" = "Your global Composer dependencies have been updated.";
"alert.composer_failure.title" = "Updating global dependencies failed"; "alert.composer_failure.title" = "Updating global dependencies failed";
"alert.composer_failure.info" = "Something went wrong updating your global Composer dependencies. "alert.composer_failure.info" = "Something went wrong updating your global Composer dependencies. You can find more information in the terminal output below. Youll have to manually fix this problem in your own terminal.";
To find out what went wrong, try running `composer global update` in a terminal window.";
// Force Reload Started // Force Reload Started
"alert.force_reload.title" = "PHP Monitor will force reload the latest version of PHP"; "alert.force_reload.title" = "PHP Monitor will force reload the latest version of PHP";