mirror of
https://github.com/nicoverbruggen/phpmon.git
synced 2025-08-08 04:20:07 +02:00
👌 Improve UI and warn about spaces in folder names
This commit is contained in:
@ -34,6 +34,8 @@
|
|||||||
C41C1B4922B00A9800E7CF16 /* MenuBarImageGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41C1B4822B00A9800E7CF16 /* MenuBarImageGenerator.swift */; };
|
C41C1B4922B00A9800E7CF16 /* MenuBarImageGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41C1B4822B00A9800E7CF16 /* MenuBarImageGenerator.swift */; };
|
||||||
C41C1B4B22B019FF00E7CF16 /* ActivePhpInstallation.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41C1B4A22B019FF00E7CF16 /* ActivePhpInstallation.swift */; };
|
C41C1B4B22B019FF00E7CF16 /* ActivePhpInstallation.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41C1B4A22B019FF00E7CF16 /* ActivePhpInstallation.swift */; };
|
||||||
C41C1B4D22B0215A00E7CF16 /* Actions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41C1B4C22B0215A00E7CF16 /* Actions.swift */; };
|
C41C1B4D22B0215A00E7CF16 /* Actions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41C1B4C22B0215A00E7CF16 /* Actions.swift */; };
|
||||||
|
C41CA5ED2774F8EE00A2C80E /* SiteListVC+Actions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41CA5EC2774F8EE00A2C80E /* SiteListVC+Actions.swift */; };
|
||||||
|
C41CA5EE2774F8EE00A2C80E /* SiteListVC+Actions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41CA5EC2774F8EE00A2C80E /* SiteListVC+Actions.swift */; };
|
||||||
C41CD0292628D8EE0065BBED /* GlobalKeybindPreference.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41CD0282628D8EE0065BBED /* GlobalKeybindPreference.swift */; };
|
C41CD0292628D8EE0065BBED /* GlobalKeybindPreference.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41CD0282628D8EE0065BBED /* GlobalKeybindPreference.swift */; };
|
||||||
C41E871A2763D42300161EE0 /* SiteListVC+ContextMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41E87192763D42300161EE0 /* SiteListVC+ContextMenu.swift */; };
|
C41E871A2763D42300161EE0 /* SiteListVC+ContextMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41E87192763D42300161EE0 /* SiteListVC+ContextMenu.swift */; };
|
||||||
C41E871B2763D42300161EE0 /* SiteListVC+ContextMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41E87192763D42300161EE0 /* SiteListVC+ContextMenu.swift */; };
|
C41E871B2763D42300161EE0 /* SiteListVC+ContextMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41E87192763D42300161EE0 /* SiteListVC+ContextMenu.swift */; };
|
||||||
@ -155,6 +157,7 @@
|
|||||||
C41C1B4822B00A9800E7CF16 /* MenuBarImageGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuBarImageGenerator.swift; sourceTree = "<group>"; };
|
C41C1B4822B00A9800E7CF16 /* MenuBarImageGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuBarImageGenerator.swift; sourceTree = "<group>"; };
|
||||||
C41C1B4A22B019FF00E7CF16 /* ActivePhpInstallation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivePhpInstallation.swift; sourceTree = "<group>"; };
|
C41C1B4A22B019FF00E7CF16 /* ActivePhpInstallation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivePhpInstallation.swift; sourceTree = "<group>"; };
|
||||||
C41C1B4C22B0215A00E7CF16 /* Actions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Actions.swift; sourceTree = "<group>"; };
|
C41C1B4C22B0215A00E7CF16 /* Actions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Actions.swift; sourceTree = "<group>"; };
|
||||||
|
C41CA5EC2774F8EE00A2C80E /* SiteListVC+Actions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SiteListVC+Actions.swift"; sourceTree = "<group>"; };
|
||||||
C41CD0282628D8EE0065BBED /* GlobalKeybindPreference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalKeybindPreference.swift; sourceTree = "<group>"; };
|
C41CD0282628D8EE0065BBED /* GlobalKeybindPreference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalKeybindPreference.swift; sourceTree = "<group>"; };
|
||||||
C41E87192763D42300161EE0 /* SiteListVC+ContextMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SiteListVC+ContextMenu.swift"; sourceTree = "<group>"; };
|
C41E87192763D42300161EE0 /* SiteListVC+ContextMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SiteListVC+ContextMenu.swift"; sourceTree = "<group>"; };
|
||||||
C42295DC2358D02000E263B2 /* Command.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Command.swift; sourceTree = "<group>"; };
|
C42295DC2358D02000E263B2 /* Command.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Command.swift; sourceTree = "<group>"; };
|
||||||
@ -337,6 +340,7 @@
|
|||||||
C464ADAB275A7A3F003FCD53 /* SiteListWC.swift */,
|
C464ADAB275A7A3F003FCD53 /* SiteListWC.swift */,
|
||||||
C464ADAE275A7A69003FCD53 /* SiteListVC.swift */,
|
C464ADAE275A7A69003FCD53 /* SiteListVC.swift */,
|
||||||
C41E87192763D42300161EE0 /* SiteListVC+ContextMenu.swift */,
|
C41E87192763D42300161EE0 /* SiteListVC+ContextMenu.swift */,
|
||||||
|
C41CA5EC2774F8EE00A2C80E /* SiteListVC+Actions.swift */,
|
||||||
C464ADB1275A87CA003FCD53 /* SiteListCell.swift */,
|
C464ADB1275A87CA003FCD53 /* SiteListCell.swift */,
|
||||||
);
|
);
|
||||||
path = SiteList;
|
path = SiteList;
|
||||||
@ -597,6 +601,7 @@
|
|||||||
C48D0C9325CC804200CC7490 /* XibLoadable.swift in Sources */,
|
C48D0C9325CC804200CC7490 /* XibLoadable.swift in Sources */,
|
||||||
54FCFD2A276C8AA4004CE748 /* CheckboxPreferenceView.swift in Sources */,
|
54FCFD2A276C8AA4004CE748 /* CheckboxPreferenceView.swift in Sources */,
|
||||||
C4811D2A22D70F9A00B5F6B3 /* MainMenu.swift in Sources */,
|
C4811D2A22D70F9A00B5F6B3 /* MainMenu.swift in Sources */,
|
||||||
|
C41CA5ED2774F8EE00A2C80E /* SiteListVC+Actions.swift in Sources */,
|
||||||
C412E5FC25700D5300A1FB67 /* HomebrewPackage.swift in Sources */,
|
C412E5FC25700D5300A1FB67 /* HomebrewPackage.swift in Sources */,
|
||||||
54AB03262763858F00A29D5F /* Timer.swift in Sources */,
|
54AB03262763858F00A29D5F /* Timer.swift in Sources */,
|
||||||
C41C1B3722B0097F00E7CF16 /* AppDelegate.swift in Sources */,
|
C41C1B3722B0097F00E7CF16 /* AppDelegate.swift in Sources */,
|
||||||
@ -624,6 +629,7 @@
|
|||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
54EAC806262F212B0092D14E /* GlobalKeybindPreference.swift in Sources */,
|
54EAC806262F212B0092D14E /* GlobalKeybindPreference.swift in Sources */,
|
||||||
|
C41CA5EE2774F8EE00A2C80E /* SiteListVC+Actions.swift in Sources */,
|
||||||
C4F780C425D80B75000DBC97 /* MainMenu.swift in Sources */,
|
C4F780C425D80B75000DBC97 /* MainMenu.swift in Sources */,
|
||||||
54AB03272763858F00A29D5F /* Timer.swift in Sources */,
|
54AB03272763858F00A29D5F /* Timer.swift in Sources */,
|
||||||
54FCFD2B276C8AA4004CE748 /* CheckboxPreferenceView.swift in Sources */,
|
54FCFD2B276C8AA4004CE748 /* CheckboxPreferenceView.swift in Sources */,
|
||||||
|
@ -497,13 +497,35 @@
|
|||||||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="IconLinked" id="2ng-pK-kvv"/>
|
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="IconLinked" id="2ng-pK-kvv"/>
|
||||||
<color key="contentTintColor" name="tertiaryLabelColor" catalog="System" colorSpace="catalog"/>
|
<color key="contentTintColor" name="tertiaryLabelColor" catalog="System" colorSpace="catalog"/>
|
||||||
</imageView>
|
</imageView>
|
||||||
|
<button translatesAutoresizingMaskIntoConstraints="NO" id="ypa-iv-wLD">
|
||||||
|
<rect key="frame" x="211" y="18" width="18" height="18"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstAttribute="width" constant="18" id="jKJ-Xn-BPA"/>
|
||||||
|
<constraint firstAttribute="height" constant="18" id="lSH-of-WzD"/>
|
||||||
|
</constraints>
|
||||||
|
<buttonCell key="cell" type="square" bezelStyle="shadowlessSquare" image="NSCaution" imagePosition="only" alignment="center" imageScaling="proportionallyUpOrDown" inset="2" id="9XB-KO-aSI">
|
||||||
|
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||||
|
<font key="font" metaFont="system"/>
|
||||||
|
</buttonCell>
|
||||||
|
</button>
|
||||||
|
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" horizontalCompressionResistancePriority="150" translatesAutoresizingMaskIntoConstraints="NO" id="MD8-ef-Ht8">
|
||||||
|
<rect key="frame" x="235" y="16" width="182" height="22"/>
|
||||||
|
<textFieldCell key="cell" sendsActionOnEndEditing="YES" title="Warning: This is a warning message. Please take this into account." id="iub-KH-clf">
|
||||||
|
<font key="font" metaFont="system" size="9"/>
|
||||||
|
<color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
</textFieldCell>
|
||||||
|
</textField>
|
||||||
</subviews>
|
</subviews>
|
||||||
<constraints>
|
<constraints>
|
||||||
|
<constraint firstItem="0NQ-ZD-CqD" firstAttribute="leading" secondItem="MD8-ef-Ht8" secondAttribute="trailing" constant="20" id="1Rb-Or-Nnn"/>
|
||||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="TbX-e2-3QL" secondAttribute="trailing" constant="20" symbolic="YES" id="3vE-LR-S7N"/>
|
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="TbX-e2-3QL" secondAttribute="trailing" constant="20" symbolic="YES" id="3vE-LR-S7N"/>
|
||||||
<constraint firstItem="TbX-e2-3QL" firstAttribute="leading" secondItem="0NQ-ZD-CqD" secondAttribute="trailing" constant="8" symbolic="YES" id="4cb-D9-8d1"/>
|
<constraint firstItem="TbX-e2-3QL" firstAttribute="leading" secondItem="0NQ-ZD-CqD" secondAttribute="trailing" constant="8" symbolic="YES" id="4cb-D9-8d1"/>
|
||||||
<constraint firstItem="XJL-Uw-frD" firstAttribute="leading" secondItem="QPX-eu-eV8" secondAttribute="trailing" constant="10" id="55y-3V-RYt"/>
|
<constraint firstItem="XJL-Uw-frD" firstAttribute="leading" secondItem="QPX-eu-eV8" secondAttribute="trailing" constant="10" id="55y-3V-RYt"/>
|
||||||
<constraint firstItem="syz-LF-l6P" firstAttribute="leading" secondItem="5GY-nN-BWd" secondAttribute="leading" id="8QK-nf-Fiw"/>
|
<constraint firstItem="syz-LF-l6P" firstAttribute="leading" secondItem="5GY-nN-BWd" secondAttribute="leading" id="8QK-nf-Fiw"/>
|
||||||
<constraint firstItem="QPX-eu-eV8" firstAttribute="top" secondItem="XJL-Uw-frD" secondAttribute="top" id="9QB-jZ-k1V"/>
|
<constraint firstItem="QPX-eu-eV8" firstAttribute="top" secondItem="XJL-Uw-frD" secondAttribute="top" id="9QB-jZ-k1V"/>
|
||||||
|
<constraint firstItem="ypa-iv-wLD" firstAttribute="centerY" secondItem="5GY-nN-BWd" secondAttribute="centerY" id="9d8-P2-iSk"/>
|
||||||
|
<constraint firstItem="MD8-ef-Ht8" firstAttribute="leading" secondItem="ypa-iv-wLD" secondAttribute="trailing" constant="8" symbolic="YES" id="C90-wQ-3Gf"/>
|
||||||
<constraint firstItem="QPX-eu-eV8" firstAttribute="leading" secondItem="5GY-nN-BWd" secondAttribute="leading" constant="10" id="GOj-sw-ZlZ"/>
|
<constraint firstItem="QPX-eu-eV8" firstAttribute="leading" secondItem="5GY-nN-BWd" secondAttribute="leading" constant="10" id="GOj-sw-ZlZ"/>
|
||||||
<constraint firstItem="TbX-e2-3QL" firstAttribute="top" secondItem="jKi-Ls-7FZ" secondAttribute="bottom" constant="-1" id="J29-wT-Uex"/>
|
<constraint firstItem="TbX-e2-3QL" firstAttribute="top" secondItem="jKi-Ls-7FZ" secondAttribute="bottom" constant="-1" id="J29-wT-Uex"/>
|
||||||
<constraint firstItem="CXK-Q9-CpO" firstAttribute="leading" secondItem="XJL-Uw-frD" secondAttribute="leading" id="Ojw-VZ-3EG"/>
|
<constraint firstItem="CXK-Q9-CpO" firstAttribute="leading" secondItem="XJL-Uw-frD" secondAttribute="leading" id="Ojw-VZ-3EG"/>
|
||||||
@ -515,15 +537,19 @@
|
|||||||
<constraint firstItem="TbX-e2-3QL" firstAttribute="centerY" secondItem="5GY-nN-BWd" secondAttribute="centerY" constant="5" id="cN8-zO-fnc"/>
|
<constraint firstItem="TbX-e2-3QL" firstAttribute="centerY" secondItem="5GY-nN-BWd" secondAttribute="centerY" constant="5" id="cN8-zO-fnc"/>
|
||||||
<constraint firstAttribute="bottom" secondItem="syz-LF-l6P" secondAttribute="bottom" id="gj7-cJ-Lle"/>
|
<constraint firstAttribute="bottom" secondItem="syz-LF-l6P" secondAttribute="bottom" id="gj7-cJ-Lle"/>
|
||||||
<constraint firstItem="0NQ-ZD-CqD" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="CXK-Q9-CpO" secondAttribute="trailing" constant="8" symbolic="YES" id="iEd-Y3-zhp"/>
|
<constraint firstItem="0NQ-ZD-CqD" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="CXK-Q9-CpO" secondAttribute="trailing" constant="8" symbolic="YES" id="iEd-Y3-zhp"/>
|
||||||
|
<constraint firstItem="ypa-iv-wLD" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="XJL-Uw-frD" secondAttribute="trailing" constant="30" id="koV-Sj-tO8"/>
|
||||||
|
<constraint firstItem="MD8-ef-Ht8" firstAttribute="centerY" secondItem="ypa-iv-wLD" secondAttribute="centerY" id="lIN-pm-mCo"/>
|
||||||
<constraint firstItem="0NQ-ZD-CqD" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="XJL-Uw-frD" secondAttribute="trailing" constant="8" symbolic="YES" id="lLA-Jx-Q4W"/>
|
<constraint firstItem="0NQ-ZD-CqD" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="XJL-Uw-frD" secondAttribute="trailing" constant="8" symbolic="YES" id="lLA-Jx-Q4W"/>
|
||||||
<constraint firstItem="jKi-Ls-7FZ" firstAttribute="leading" secondItem="TbX-e2-3QL" secondAttribute="leading" id="zjN-s3-2Ww"/>
|
<constraint firstItem="jKi-Ls-7FZ" firstAttribute="leading" secondItem="TbX-e2-3QL" secondAttribute="leading" id="zjN-s3-2Ww"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<connections>
|
<connections>
|
||||||
|
<outlet property="buttonWarning" destination="ypa-iv-wLD" id="NwX-H3-8um"/>
|
||||||
<outlet property="imageViewLock" destination="QPX-eu-eV8" id="Nnh-kB-adG"/>
|
<outlet property="imageViewLock" destination="QPX-eu-eV8" id="Nnh-kB-adG"/>
|
||||||
<outlet property="imageViewType" destination="0NQ-ZD-CqD" id="Cph-FN-LaY"/>
|
<outlet property="imageViewType" destination="0NQ-ZD-CqD" id="Cph-FN-LaY"/>
|
||||||
<outlet property="labelDriver" destination="TbX-e2-3QL" id="qJh-Ak-Dge"/>
|
<outlet property="labelDriver" destination="TbX-e2-3QL" id="qJh-Ak-Dge"/>
|
||||||
<outlet property="labelPathName" destination="CXK-Q9-CpO" id="iVZ-cL-azB"/>
|
<outlet property="labelPathName" destination="CXK-Q9-CpO" id="iVZ-cL-azB"/>
|
||||||
<outlet property="labelSiteName" destination="XJL-Uw-frD" id="f0t-vd-W68"/>
|
<outlet property="labelSiteName" destination="XJL-Uw-frD" id="f0t-vd-W68"/>
|
||||||
|
<outlet property="labelWarning" destination="MD8-ef-Ht8" id="Faw-CY-9R5"/>
|
||||||
</connections>
|
</connections>
|
||||||
</tableCellView>
|
</tableCellView>
|
||||||
</prototypeCellViews>
|
</prototypeCellViews>
|
||||||
@ -573,12 +599,13 @@
|
|||||||
</viewController>
|
</viewController>
|
||||||
<customObject id="HgD-aB-bQb" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
<customObject id="HgD-aB-bQb" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||||
</objects>
|
</objects>
|
||||||
<point key="canvasLocation" x="288" y="765"/>
|
<point key="canvasLocation" x="288" y="764.5"/>
|
||||||
</scene>
|
</scene>
|
||||||
</scenes>
|
</scenes>
|
||||||
<resources>
|
<resources>
|
||||||
<image name="IconLinked" width="512" height="512"/>
|
<image name="IconLinked" width="512" height="512"/>
|
||||||
<image name="Lock" width="30" height="30"/>
|
<image name="Lock" width="30" height="30"/>
|
||||||
|
<image name="NSCaution" width="32" height="32"/>
|
||||||
<image name="arrow.clockwise" catalog="system" width="14" height="16"/>
|
<image name="arrow.clockwise" catalog="system" width="14" height="16"/>
|
||||||
</resources>
|
</resources>
|
||||||
</document>
|
</document>
|
||||||
|
@ -68,6 +68,9 @@ class Valet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns a count of how many sites are linked and parked.
|
||||||
|
*/
|
||||||
private func countPaths() -> Int {
|
private func countPaths() -> Int {
|
||||||
var count = 0
|
var count = 0
|
||||||
for path in config.paths {
|
for path in config.paths {
|
||||||
@ -81,6 +84,9 @@ class Valet {
|
|||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Resolves all paths and creates linked or parked site instances that can be referenced later.
|
||||||
|
*/
|
||||||
private func resolvePaths(tld: String) {
|
private func resolvePaths(tld: String) {
|
||||||
sites = []
|
sites = []
|
||||||
|
|
||||||
@ -92,6 +98,10 @@ class Valet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Determines whether the site can be resolved as a symbolic link or as a directory.
|
||||||
|
Regular files are ignored. Returns true if the path can be parsed.
|
||||||
|
*/
|
||||||
private func resolveSite(_ entry: String, forPath path: String) -> Bool {
|
private func resolveSite(_ entry: String, forPath path: String) -> Bool {
|
||||||
let siteDir = path + "/" + entry
|
let siteDir = path + "/" + entry
|
||||||
|
|
||||||
@ -106,6 +116,10 @@ class Valet {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Determines whether the site can be resolved as a symbolic link or as a directory.
|
||||||
|
Regular files are ignored, and the site is added to Valet's list of sites.
|
||||||
|
*/
|
||||||
private func resolvePath(_ entry: String, forPath path: String, tld: String) {
|
private func resolvePath(_ entry: String, forPath path: String, tld: String) {
|
||||||
let siteDir = path + "/" + entry
|
let siteDir = path + "/" + entry
|
||||||
|
|
||||||
@ -167,12 +181,11 @@ class Valet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func determineSecured(_ tld: String) {
|
public func determineSecured(_ tld: String) {
|
||||||
let name = self.name!.replacingOccurrences(of: " ", with: "\\ ")
|
secured = Shell.fileExists("~/.config/valet/Certificates/\(self.name!).\(tld).key")
|
||||||
secured = Shell.fileExists("~/.config/valet/Certificates/\(name).\(tld).key")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public func determineDriver() {
|
public func determineDriver() {
|
||||||
let driver = Shell.pipe("cd \"\(absolutePath!)\" && valet which", requiresPath: true)
|
let driver = Shell.pipe("cd '\(absolutePath!)' && valet which", requiresPath: true)
|
||||||
if driver.contains("This site is served by") {
|
if driver.contains("This site is served by") {
|
||||||
self.driver = driver
|
self.driver = driver
|
||||||
// TODO: Use a regular expression to retrieve the driver instead?
|
// TODO: Use a regular expression to retrieve the driver instead?
|
||||||
|
@ -19,6 +19,9 @@ class SiteListCell: NSTableCellView
|
|||||||
|
|
||||||
@IBOutlet weak var labelDriver: NSTextField!
|
@IBOutlet weak var labelDriver: NSTextField!
|
||||||
|
|
||||||
|
@IBOutlet weak var buttonWarning: NSButton!
|
||||||
|
@IBOutlet weak var labelWarning: NSTextField!
|
||||||
|
|
||||||
override func draw(_ dirtyRect: NSRect) {
|
override func draw(_ dirtyRect: NSRect) {
|
||||||
super.draw(dirtyRect)
|
super.draw(dirtyRect)
|
||||||
}
|
}
|
||||||
@ -27,6 +30,11 @@ class SiteListCell: NSTableCellView
|
|||||||
// Make sure to show the TLD
|
// Make sure to show the TLD
|
||||||
labelSiteName.stringValue = "\(site.name!).\(Valet.shared.config.tld)"
|
labelSiteName.stringValue = "\(site.name!).\(Valet.shared.config.tld)"
|
||||||
|
|
||||||
|
let isProblematic = site.name.contains(" ")
|
||||||
|
buttonWarning.isHidden = !isProblematic
|
||||||
|
labelWarning.isHidden = !isProblematic
|
||||||
|
labelWarning.stringValue = "site_list.warning.spaces".localized
|
||||||
|
|
||||||
// Show the absolute path, except make sure to replace the /Users/username segment with ~ for readability
|
// Show the absolute path, except make sure to replace the /Users/username segment with ~ for readability
|
||||||
labelPathName.stringValue = site.absolutePath
|
labelPathName.stringValue = site.absolutePath
|
||||||
.replacingOccurrences(of: "/Users/\(Paths.whoami)", with: "~")
|
.replacingOccurrences(of: "/Users/\(Paths.whoami)", with: "~")
|
||||||
|
97
phpmon/Domain/SiteList/SiteListVC+Actions.swift
Normal file
97
phpmon/Domain/SiteList/SiteListVC+Actions.swift
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
//
|
||||||
|
// SiteListVC+Actions.swift
|
||||||
|
// PHP Monitor
|
||||||
|
//
|
||||||
|
// Created by Nico Verbruggen on 23/12/2021.
|
||||||
|
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import Cocoa
|
||||||
|
|
||||||
|
extension SiteListVC {
|
||||||
|
|
||||||
|
@objc func toggleSecure() {
|
||||||
|
let rowToReload = tableView.selectedRow
|
||||||
|
let originalSecureStatus = selectedSite!.secured
|
||||||
|
let action = selectedSite!.secured ? "unsecure" : "secure"
|
||||||
|
let selectedSite = selectedSite!
|
||||||
|
let command = "cd '\(selectedSite.absolutePath!)' && sudo \(Paths.valet) \(action) && exit;"
|
||||||
|
|
||||||
|
waitAndExecute {
|
||||||
|
Shell.run(command, requiresPath: true)
|
||||||
|
} completion: { [self] in
|
||||||
|
selectedSite.determineSecured(Valet.shared.config.tld)
|
||||||
|
if selectedSite.secured == originalSecureStatus {
|
||||||
|
Alert.notify(
|
||||||
|
message: "site_list.alerts_status_not_changed.title".localized,
|
||||||
|
info: "site_list.alerts_status_not_changed.desc".localized(command)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
let newState = selectedSite.secured ? "secured" : "unsecured"
|
||||||
|
LocalNotification.send(
|
||||||
|
title: "site_list.alerts_status_changed.title".localized,
|
||||||
|
subtitle: "site_list.alerts_status_changed.desc"
|
||||||
|
.localized(
|
||||||
|
"\(selectedSite.name!).\(Valet.shared.config.tld)",
|
||||||
|
newState
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
tableView.reloadData(forRowIndexes: [rowToReload], columnIndexes: [0])
|
||||||
|
tableView.deselectRow(rowToReload)
|
||||||
|
tableView.selectRowIndexes([rowToReload], byExtendingSelection: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func openInBrowser() {
|
||||||
|
let prefix = selectedSite!.secured ? "https://" : "http://"
|
||||||
|
let url = URL(string: "\(prefix)\(selectedSite!.name!).\(Valet.shared.config.tld)")
|
||||||
|
if url != nil {
|
||||||
|
NSWorkspace.shared.open(url!)
|
||||||
|
} else {
|
||||||
|
_ = Alert.present(
|
||||||
|
messageText: "site_list.alert.invalid_folder_name".localized,
|
||||||
|
informativeText: "site_list.alert.invalid_folder_name_desc".localized
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func openInFinder() {
|
||||||
|
Shell.run("open '\(selectedSite!.absolutePath!)'")
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func openInTerminal() {
|
||||||
|
Shell.run("open -b com.apple.terminal '\(selectedSite!.absolutePath!)'")
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func openWithEditor(sender: EditorMenuItem) {
|
||||||
|
guard let editor = sender.editor else { return }
|
||||||
|
editor.openDirectory(file: selectedSite!.absolutePath!)
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func unlinkSite() {
|
||||||
|
guard let site = selectedSite else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if site.aliasPath == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
Alert.confirm(
|
||||||
|
onWindow: view.window!,
|
||||||
|
messageText: "site_list.confirm_unlink".localized(site.name),
|
||||||
|
informativeText: "site_link.confirm_link".localized,
|
||||||
|
buttonTitle: "site_list.unlink".localized,
|
||||||
|
secondButtonTitle: "Cancel",
|
||||||
|
style: .critical,
|
||||||
|
onFirstButtonPressed: {
|
||||||
|
Shell.run("valet unlink '\(site.name!)'", requiresPath: true)
|
||||||
|
self.reloadSites()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -112,12 +112,11 @@ class SiteListVC: NSViewController, NSTableViewDelegate, NSTableViewDataSource {
|
|||||||
- Parameter execute: Callback of the work that needs to happen.
|
- Parameter execute: Callback of the work that needs to happen.
|
||||||
- Parameter completion: Callback that is fired when the work is done.
|
- Parameter completion: Callback that is fired when the work is done.
|
||||||
*/
|
*/
|
||||||
private func waitAndExecute(_ execute: @escaping () -> Void, completion: @escaping () -> Void = {})
|
internal func waitAndExecute(_ execute: @escaping () -> Void, completion: @escaping () -> Void = {})
|
||||||
{
|
{
|
||||||
setUIBusy()
|
setUIBusy()
|
||||||
DispatchQueue.global(qos: .userInitiated).async { [unowned self] in
|
DispatchQueue.global(qos: .userInitiated).async { [unowned self] in
|
||||||
execute()
|
execute()
|
||||||
|
|
||||||
DispatchQueue.main.async { [self] in
|
DispatchQueue.main.async { [self] in
|
||||||
completion()
|
completion()
|
||||||
setUINotBusy()
|
setUINotBusy()
|
||||||
@ -164,92 +163,6 @@ class SiteListVC: NSViewController, NSTableViewDelegate, NSTableViewDataSource {
|
|||||||
self.openInBrowser()
|
self.openInBrowser()
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Secure & Unsecure
|
|
||||||
|
|
||||||
@objc public func toggleSecure() {
|
|
||||||
let rowToReload = tableView.selectedRow
|
|
||||||
let originalSecureStatus = selectedSite!.secured
|
|
||||||
let action = selectedSite!.secured ? "unsecure" : "secure"
|
|
||||||
let selectedSite = selectedSite!
|
|
||||||
let command = "cd '\(selectedSite.absolutePath!)' && sudo \(Paths.valet) \(action) && exit;"
|
|
||||||
|
|
||||||
waitAndExecute {
|
|
||||||
Shell.run(command, requiresPath: true)
|
|
||||||
} completion: { [self] in
|
|
||||||
selectedSite.determineSecured(Valet.shared.config.tld)
|
|
||||||
if selectedSite.secured == originalSecureStatus {
|
|
||||||
Alert.notify(
|
|
||||||
message: "site_list.alerts_status_not_changed.title".localized,
|
|
||||||
info: "site_list.alerts_status_not_changed.desc".localized(command)
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
let newState = selectedSite.secured ? "secured" : "unsecured"
|
|
||||||
LocalNotification.send(
|
|
||||||
title: "site_list.alerts_status_changed.title".localized,
|
|
||||||
subtitle: "site_list.alerts_status_changed.desc"
|
|
||||||
.localized(
|
|
||||||
"\(selectedSite.name!).\(Valet.shared.config.tld)",
|
|
||||||
newState
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
tableView.reloadData(forRowIndexes: [rowToReload], columnIndexes: [0])
|
|
||||||
tableView.deselectRow(rowToReload)
|
|
||||||
tableView.selectRowIndexes([rowToReload], byExtendingSelection: true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: Open in Browser & Finder
|
|
||||||
|
|
||||||
@objc public func openInBrowser() {
|
|
||||||
let prefix = selectedSite!.secured ? "https://" : "http://"
|
|
||||||
let url = URL(string: "\(prefix)\(selectedSite!.name!).\(Valet.shared.config.tld)")
|
|
||||||
if url != nil {
|
|
||||||
NSWorkspace.shared.open(url!)
|
|
||||||
} else {
|
|
||||||
warnAboutInvalidFolderAction()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc public func openInFinder() {
|
|
||||||
Shell.run("open '\(selectedSite!.absolutePath!)'")
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc public func openInTerminal() {
|
|
||||||
Shell.run("open -b com.apple.terminal '\(selectedSite!.absolutePath!)'")
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc public func unlinkSite() {
|
|
||||||
guard let site = selectedSite else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if site.aliasPath == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
Alert.confirm(
|
|
||||||
onWindow: view.window!,
|
|
||||||
messageText: "site_list.confirm_unlink".localized(site.name),
|
|
||||||
informativeText: "site_link.confirm_link".localized,
|
|
||||||
buttonTitle: "site_list.unlink".localized,
|
|
||||||
secondButtonTitle: "Cancel",
|
|
||||||
style: .critical,
|
|
||||||
onFirstButtonPressed: {
|
|
||||||
Shell.run("valet unlink \(site.name!)", requiresPath: true)
|
|
||||||
self.reloadSites()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func warnAboutInvalidFolderAction() {
|
|
||||||
_ = Alert.present(
|
|
||||||
messageText: "site_list.alert.invalid_folder_name".localized,
|
|
||||||
informativeText: "site_list.alert.invalid_folder_name_desc".localized
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - (Search) Text Field Delegate
|
// MARK: - (Search) Text Field Delegate
|
||||||
|
|
||||||
func searchedFor(text: String) {
|
func searchedFor(text: String) {
|
||||||
@ -269,13 +182,7 @@ class SiteListVC: NSViewController, NSTableViewDelegate, NSTableViewDataSource {
|
|||||||
|
|
||||||
tableView.reloadData()
|
tableView.reloadData()
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Context Menu
|
|
||||||
|
|
||||||
@objc func openWithEditor(sender: EditorMenuItem) {
|
|
||||||
guard let editor = sender.editor else { return }
|
|
||||||
editor.openDirectory(file: selectedSite!.absolutePath!)
|
|
||||||
}
|
|
||||||
// MARK: - Deinitialization
|
// MARK: - Deinitialization
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
|
@ -116,7 +116,8 @@ class Shell {
|
|||||||
Uses `/bin/echo` instead of the `builtin` (which does not support `-n`).
|
Uses `/bin/echo` instead of the `builtin` (which does not support `-n`).
|
||||||
*/
|
*/
|
||||||
public static func fileExists(_ path: String) -> Bool {
|
public static func fileExists(_ path: String) -> Bool {
|
||||||
return Shell.pipe("if [ -f \(path) ]; then /bin/echo -n \"0\"; fi") == "0"
|
let escapedPath = path.replacingOccurrences(of: " ", with: "\\ ")
|
||||||
|
return Shell.pipe("if [ -f \(escapedPath) ]; then /bin/echo -n \"0\"; fi") == "0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,6 +74,8 @@
|
|||||||
"site_list.detected_apps" = "Detected Applications";
|
"site_list.detected_apps" = "Detected Applications";
|
||||||
"site_list.system_apps" = "System Applications";
|
"site_list.system_apps" = "System Applications";
|
||||||
|
|
||||||
|
"site_list.warning.spaces" = "Warning! This site has a space in its folder.\nThe site will not be reachable via the browser.";
|
||||||
|
|
||||||
"site_list.alert.invalid_folder_name" = "Invalid folder name";
|
"site_list.alert.invalid_folder_name" = "Invalid folder name";
|
||||||
"site_list.alert.invalid_folder_name_desc" = "This folder could not be resolved to a valid URL. This is usually because there’s a space in the folder name. Please rename the folder, reload the list of sites, and try again.";
|
"site_list.alert.invalid_folder_name_desc" = "This folder could not be resolved to a valid URL. This is usually because there’s a space in the folder name. Please rename the folder, reload the list of sites, and try again.";
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user