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

View File

@ -25,6 +25,18 @@ class PMWindowController: NSWindowController, NSWindowDelegate {
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() {
guard let frame = NSScreen.main?.frame else { return }
guard let window = self.window else { return }
@ -37,12 +49,4 @@ class PMWindowController: NSWindowController, NSWindowDelegate {
), 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() {
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 {
let output = Shell.user.executeSynchronously(
"composer global update", requiresPath: true
@ -335,34 +345,50 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate {
let task = Shell.user.createTask(for: "composer global update", requiresPath: true)
DispatchQueue.main.async {
window?.addToConsole("composer global update\n")
}
Shell.captureOutput(
task,
didReceiveStdOutData: { string in
DispatchQueue.main.async {
window?.addToConsole(string)
}
print("\(string.trimmingCharacters(in: .newlines))")
},
didReceiveStdErrData: { string in
DispatchQueue.main.async {
window?.addToConsole(string)
}
print("\(string.trimmingCharacters(in: .newlines))")
}
)
task.launch()
task.waitUntilExit()
Shell.haltCapturingOutput(task)
DispatchQueue.main.async {
if output.task.terminationStatus > 0 {
// Error code means > 0
Alert.notify(
message: "alert.composer_failure.title".localized,
info: "alert.composer_failure.info".localized,
style: .critical
)
} else {
// Error code -1 is OK
if output.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
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
completion(false)
}
}
}
}
@ -406,14 +432,23 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate {
updatePhpVersionInStatusBar()
update()
// Send a notification that the switch has been completed
let sendLocalNotification = {
LocalNotification.send(
title: String(format: "notification.version_changed_title".localized, sender.version),
subtitle: String(format: "notification.version_changed_desc".localized, sender.version)
)
App.phpInstall?.notifyAboutBrokenPhpFpm()
}
// Run composer updates
if Preferences.preferences[.autoComposerGlobalUpdateAfterSwitch] as! Bool == true {
self.updateGlobalDependencies(notify: false, completion: { success in
sendLocalNotification()
})
} else {
sendLocalNotification()
}
}
}
/* DISABLED UNTIL VALET SWITCHING IS OK (see #34)

View File

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

View File

@ -74,6 +74,13 @@ class PrefsVC: NSViewController {
preference: .autoServiceRestartAfterExtensionToggle,
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)
CheckboxPreferenceView.make(
sectionText: "",

View File

@ -21,12 +21,6 @@ class PrefsWC: PMWindowController {
return "Preferences"
}
// MARK: - Window Lifecycle
override func windowDidLoad() {
super.windowDidLoad()
}
// MARK: - Key Interaction
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 {

View File

@ -90,6 +90,7 @@
"prefs.global_shortcut" = "Global shortcut:";
"prefs.dynamic_icon" = "Dynamic icon:";
"prefs.services" = "Services:";
"prefs.switcher" = "Switcher:";
"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.";
@ -109,6 +110,9 @@ use PHP Monitor's own switcher which is slightly faster,
but might cause issues with permissions in your Homebrew
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_listening" = "<listening for keypress>";
"prefs.shortcut_clear" = "Clear";
@ -131,13 +135,14 @@ directories, since PHP Monitor controls the services.";
// ALERTS
// 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.info" = "Your global Composer dependencies have been updated.";
"alert.composer_failure.title" = "Updating global dependencies failed";
"alert.composer_failure.info" = "Something went wrong updating your global Composer dependencies.
To find out what went wrong, try running `composer global update` in a terminal window.";
"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.";
// Force Reload Started
"alert.force_reload.title" = "PHP Monitor will force reload the latest version of PHP";