diff --git a/PHP Monitor.xcodeproj/project.pbxproj b/PHP Monitor.xcodeproj/project.pbxproj
index 48eb530..5071de3 100644
--- a/PHP Monitor.xcodeproj/project.pbxproj
+++ b/PHP Monitor.xcodeproj/project.pbxproj
@@ -737,6 +737,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
+ MACOSX_DEPLOYMENT_TARGET = 11.0;
MARKETING_VERSION = "4.1-beta2";
PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -761,6 +762,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
+ MACOSX_DEPLOYMENT_TARGET = 11.0;
MARKETING_VERSION = "4.1-beta2";
PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon;
PRODUCT_NAME = "$(TARGET_NAME)";
diff --git a/phpmon/Assets.xcassets/GreenLock.imageset/GreenLock.svg b/phpmon/Assets.xcassets/GreenLock.imageset/GreenLock.svg
deleted file mode 100644
index d81604f..0000000
--- a/phpmon/Assets.xcassets/GreenLock.imageset/GreenLock.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
diff --git a/phpmon/Assets.xcassets/GreenLock.imageset/Contents.json b/phpmon/Assets.xcassets/IconLinked.imageset/Contents.json
similarity index 73%
rename from phpmon/Assets.xcassets/GreenLock.imageset/Contents.json
rename to phpmon/Assets.xcassets/IconLinked.imageset/Contents.json
index 6501997..6cb3d9a 100644
--- a/phpmon/Assets.xcassets/GreenLock.imageset/Contents.json
+++ b/phpmon/Assets.xcassets/IconLinked.imageset/Contents.json
@@ -5,7 +5,7 @@
"scale" : "1x"
},
{
- "filename" : "GreenLock.svg",
+ "filename" : "link.svg",
"idiom" : "universal",
"scale" : "2x"
},
@@ -17,5 +17,8 @@
"info" : {
"author" : "xcode",
"version" : 1
+ },
+ "properties" : {
+ "template-rendering-intent" : "template"
}
}
diff --git a/phpmon/Assets.xcassets/IconLinked.imageset/link.svg b/phpmon/Assets.xcassets/IconLinked.imageset/link.svg
new file mode 100644
index 0000000..f0fdbf4
--- /dev/null
+++ b/phpmon/Assets.xcassets/IconLinked.imageset/link.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/phpmon/Assets.xcassets/RedLock.imageset/Contents.json b/phpmon/Assets.xcassets/IconParked.imageset/Contents.json
similarity index 72%
rename from phpmon/Assets.xcassets/RedLock.imageset/Contents.json
rename to phpmon/Assets.xcassets/IconParked.imageset/Contents.json
index 116378f..24b6de7 100644
--- a/phpmon/Assets.xcassets/RedLock.imageset/Contents.json
+++ b/phpmon/Assets.xcassets/IconParked.imageset/Contents.json
@@ -5,7 +5,7 @@
"scale" : "1x"
},
{
- "filename" : "RedLock.svg",
+ "filename" : "car-alt.svg",
"idiom" : "universal",
"scale" : "2x"
},
@@ -17,5 +17,8 @@
"info" : {
"author" : "xcode",
"version" : 1
+ },
+ "properties" : {
+ "template-rendering-intent" : "template"
}
}
diff --git a/phpmon/Assets.xcassets/IconParked.imageset/car-alt.svg b/phpmon/Assets.xcassets/IconParked.imageset/car-alt.svg
new file mode 100644
index 0000000..90a786e
--- /dev/null
+++ b/phpmon/Assets.xcassets/IconParked.imageset/car-alt.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/phpmon/Assets.xcassets/Search.imageset/Contents.json b/phpmon/Assets.xcassets/Lock.imageset/Contents.json
similarity index 73%
rename from phpmon/Assets.xcassets/Search.imageset/Contents.json
rename to phpmon/Assets.xcassets/Lock.imageset/Contents.json
index 44e7f88..9069859 100644
--- a/phpmon/Assets.xcassets/Search.imageset/Contents.json
+++ b/phpmon/Assets.xcassets/Lock.imageset/Contents.json
@@ -5,7 +5,7 @@
"scale" : "1x"
},
{
- "filename" : "search.svg",
+ "filename" : "lock.svg",
"idiom" : "universal",
"scale" : "2x"
},
@@ -17,5 +17,8 @@
"info" : {
"author" : "xcode",
"version" : 1
+ },
+ "properties" : {
+ "template-rendering-intent" : "template"
}
}
diff --git a/phpmon/Assets.xcassets/Lock.imageset/lock.svg b/phpmon/Assets.xcassets/Lock.imageset/lock.svg
new file mode 100644
index 0000000..86a172a
--- /dev/null
+++ b/phpmon/Assets.xcassets/Lock.imageset/lock.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/phpmon/Assets.xcassets/RedLock.imageset/RedLock.svg b/phpmon/Assets.xcassets/RedLock.imageset/RedLock.svg
deleted file mode 100644
index cedd503..0000000
--- a/phpmon/Assets.xcassets/RedLock.imageset/RedLock.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
diff --git a/phpmon/Assets.xcassets/Search.imageset/search.svg b/phpmon/Assets.xcassets/Search.imageset/search.svg
deleted file mode 100644
index 7e46970..0000000
--- a/phpmon/Assets.xcassets/Search.imageset/search.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
diff --git a/phpmon/Domain/Core/Base.lproj/Main.storyboard b/phpmon/Domain/Core/Base.lproj/Main.storyboard
index 9ce73da..4c6a3e8 100644
--- a/phpmon/Domain/Core/Base.lproj/Main.storyboard
+++ b/phpmon/Domain/Core/Base.lproj/Main.storyboard
@@ -3,6 +3,7 @@
+
@@ -518,7 +519,7 @@ Gw
-
+
@@ -528,34 +529,54 @@ Gw
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
-
+
-
+
-
-
+
+
@@ -599,46 +620,73 @@ Gw
-
+
-
-
-
-
-
-
-
-
-
-
+
+
-
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
+
-
+
+
-
+
+
+
+
+
-
@@ -656,7 +704,7 @@ Gw
-
+
@@ -664,50 +712,25 @@ Gw
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
+
-
-
+
+
diff --git a/phpmon/Domain/Integrations/Valet/Valet.swift b/phpmon/Domain/Integrations/Valet/Valet.swift
index 48cfe8f..615e345 100644
--- a/phpmon/Domain/Integrations/Valet/Valet.swift
+++ b/phpmon/Domain/Integrations/Valet/Valet.swift
@@ -66,35 +66,48 @@ class Valet {
// MARK: - Structs
class Site {
- var name: String
+ var name: String!
- var absolutePath: String
+ var absolutePath: String!
var aliasPath: String?
- var secured: Bool
- init(absolutePath: String, tld: String) {
+ var secured: Bool!
+ var driver: String = "???"
+
+ init() {}
+
+ convenience init(absolutePath: String, tld: String) {
+ self.init()
self.absolutePath = absolutePath
- self.aliasPath = nil
self.name = URL(string: absolutePath)!.lastPathComponent
- self.secured = Shell.fileExists("~/.config/valet/Certificates/\(self.name).\(tld).key")
+ self.aliasPath = nil
+ determineSecured(tld)
+ determineDriver()
}
convenience init(aliasPath: String, tld: String) {
- // Resolve the symlink
- let absolutePath = try! FileManager.default
- .destinationOfSymbolicLink(atPath: aliasPath)
- self.init(absolutePath: absolutePath, tld: tld)
-
- // TODO: Make sure the destination is a valid directory!
-
- // The name should be identical to the alias' name
+ self.init()
+ self.absolutePath = try! FileManager.default.destinationOfSymbolicLink(atPath: aliasPath)
self.name = URL(string: aliasPath)!.lastPathComponent
-
- // Update the alias' path
self.aliasPath = aliasPath
-
- // Make sure we check again, this time for the aliased file
- self.secured = Shell.fileExists("~/.config/valet/Certificates/\(self.name).\(tld).key")
+ determineSecured(tld)
+ determineDriver()
+ }
+
+ public func determineSecured(_ tld: String) {
+ self.secured = Shell.fileExists("~/.config/valet/Certificates/\(self.name!).\(tld).key")
+ }
+
+ public func determineDriver() {
+ let driver = Shell.pipe("cd \(absolutePath!) && valet which", requiresPath: true)
+ if driver.contains("This site is served by") {
+ self.driver = driver
+ // TODO: Use a regular expression to retrieve the driver instead?
+ .replacingOccurrences(of: "This site is served by [", with: "")
+ .replacingOccurrences(of: "ValetDriver].\n", with: "")
+ } else {
+ self.driver = "???"
+ }
}
}
diff --git a/phpmon/Domain/SiteList/SiteListCell.swift b/phpmon/Domain/SiteList/SiteListCell.swift
index 1cd7c5d..c514b80 100644
--- a/phpmon/Domain/SiteList/SiteListCell.swift
+++ b/phpmon/Domain/SiteList/SiteListCell.swift
@@ -15,9 +15,10 @@ class SiteListCell: NSTableCellView
@IBOutlet weak var labelPathName: NSTextField!
@IBOutlet weak var imageViewLock: NSImageView!
+ @IBOutlet weak var imageViewType: NSImageView!
+ @IBOutlet weak var labelDriver: NSTextField!
@IBOutlet weak var labelPhpVersion: NSTextField!
- @IBOutlet weak var labelSiteType: NSTextField!
override func draw(_ dirtyRect: NSRect) {
super.draw(dirtyRect)
diff --git a/phpmon/Domain/SiteList/SiteListVC.swift b/phpmon/Domain/SiteList/SiteListVC.swift
index 5bc4109..c44261a 100644
--- a/phpmon/Domain/SiteList/SiteListVC.swift
+++ b/phpmon/Domain/SiteList/SiteListVC.swift
@@ -10,12 +10,10 @@ import Cocoa
import HotKey
import Carbon
-class SiteListVC: NSViewController, NSTableViewDelegate, NSTableViewDataSource, NSTextFieldDelegate {
+class SiteListVC: NSViewController, NSTableViewDelegate, NSTableViewDataSource {
// MARK: - Outlets
- @IBOutlet weak var textFieldSearch: NSTextField!
-
@IBOutlet weak var tableView: NSTableView!
public var editorAvailability: [String] = []
@@ -26,15 +24,15 @@ class SiteListVC: NSViewController, NSTableViewDelegate, NSTableViewDataSource,
public static func show(delegate: NSWindowDelegate? = nil) {
if (App.shared.siteListWindowController == nil) {
- let vc = NSStoryboard(name: "Main", bundle: nil)
- .instantiateController(withIdentifier: "siteList") as! SiteListVC
- let window = NSWindow(contentViewController: vc)
+ let storyboard = NSStoryboard(name: "Main" , bundle : nil)
+ let windowController = (storyboard.instantiateController(withIdentifier: "siteListWindow")) as! SiteListWC
- window.title = "site_list.title".localized
- window.delegate = delegate
- window.styleMask = [.titled, .closable, .resizable]
+ windowController.window!.title = "site_list.title".localized
+ windowController.window!.delegate = delegate
+ windowController.window!.styleMask = [.titled, .closable, .resizable]
+ windowController.window!.maxSize = NSSize(width: 800, height: 10000)
- App.shared.siteListWindowController = SiteListWC(window: window)
+ App.shared.siteListWindowController = windowController
}
App.shared.siteListWindowController!.showWindow(self)
@@ -70,19 +68,26 @@ class SiteListVC: NSViewController, NSTableViewDelegate, NSTableViewDataSource,
let item = self.sites[row]
/// Make sure to show the TLD
- userCell.labelSiteName.stringValue = "\(item.name).\(Valet.shared.config.tld)"
+ userCell.labelSiteName.stringValue = "\(item.name!).\(Valet.shared.config.tld)"
/// Show the absolute path, except make sure to replace the /Users/username segment with ~ for readability
userCell.labelPathName.stringValue = item.absolutePath
.replacingOccurrences(of: "/Users/\(Paths.whoami)", with: "~")
/// If the `aliasPath` is nil, we're dealing with a parked site. Otherwise, it's a link that was explicitly created.
- userCell.labelSiteType.stringValue = item.aliasPath == nil
- ? "Parked Site"
- : "Linked Site"
+ userCell.imageViewType.image = NSImage(
+ named: item.aliasPath == nil
+ ? "IconParked"
+ : "IconLinked"
+ )
+ userCell.imageViewType.contentTintColor = NSColor.tertiaryLabelColor
/// Show the green or red lock based on whether the site was secured
- userCell.imageViewLock.image = NSImage(named: item.secured ? "GreenLock" : "RedLock")
+ userCell.imageViewLock.contentTintColor = item.secured ? NSColor.systemGreen
+ : NSColor.red
+
+ /// Show the current driver
+ userCell.labelDriver.stringValue = item.driver
/// TODO: Load the correct PHP version (not determined as of yet)
userCell.labelPhpVersion.stringValue = "PHP 8.0"
@@ -104,7 +109,7 @@ class SiteListVC: NSViewController, NSTableViewDelegate, NSTableViewDataSource,
withTitle: site.secured
? "site_list.unsecure".localized
: "site_list.secure".localized,
- action: nil,
+ action: #selector(toggleSecure),
keyEquivalent: "L"
)
@@ -146,19 +151,43 @@ class SiteListVC: NSViewController, NSTableViewDelegate, NSTableViewDataSource,
// MARK: Secure / unsecure
@objc public func toggleSecure() {
- // TODO
+ let rowToReload = self.tableView.selectedRow
+ let site = self.sites[self.tableView.selectedRow]
+ let previous = site.secured
+ let action = site.secured ? "unsecure" : "secure"
+
+ let command = "cd \(site.absolutePath!) && sudo \(Paths.valet) \(action) && exit;"
+ let _ = Shell.pipe(command, requiresPath: true)
+
+ site.determineSecured(Valet.shared.config.tld)
+
+ if site.secured == previous {
+ Alert.notify(
+ message: "SSL status not changed",
+ info: "Something went wrong. Try running the command in your terminal manually: `\(command)`")
+ } else {
+ let newState = site.secured ? "secured" : "unsecured"
+ LocalNotification.send(
+ title: "SSL status changed",
+ subtitle: "The domain '\(site.name!).\(Valet.shared.config.tld)' is now \(newState)."
+ )
+ }
+
+ tableView.reloadData(forRowIndexes: [rowToReload], columnIndexes: [0])
+ tableView.deselectRow(rowToReload)
+ tableView.selectRowIndexes([rowToReload], byExtendingSelection: true)
}
// MARK: Open with IDE / Editor
@objc public func openWithPhpStorm() {
let site = self.sites[self.tableView.selectedRow]
- Shell.run("open -a /Applications/PhpStorm.app \(site.absolutePath)")
+ Shell.run("open -a /Applications/PhpStorm.app \(site.absolutePath!)")
}
@objc public func openWithVSCode() {
let site = self.sites[self.tableView.selectedRow]
- Shell.run("/usr/local/bin/code \(site.absolutePath)")
+ Shell.run("/usr/local/bin/code \(site.absolutePath!)")
}
// MARK: Open in Browser & Finder
@@ -166,19 +195,19 @@ class SiteListVC: NSViewController, NSTableViewDelegate, NSTableViewDataSource,
@objc public func openInBrowser() {
let site = self.sites[self.tableView.selectedRow]
let prefix = site.secured ? "https://" : "http://"
- let url = "\(prefix)\(site.name).\(Valet.shared.config.tld)"
+ let url = "\(prefix)\(site.name!).\(Valet.shared.config.tld)"
NSWorkspace.shared.open(URL(string: url)!)
}
@objc public func openInFinder() {
let site = self.sites[self.tableView.selectedRow]
- Shell.run("open \(site.absolutePath)")
+ Shell.run("open \(site.absolutePath!)")
}
// MARK: - (Search) Text Field Delegate
- func controlTextDidChange(_ obj: Notification) {
- let searchString = self.textFieldSearch.stringValue.lowercased()
+ func searchedFor(text: String) {
+ let searchString = text.lowercased()
if searchString.isEmpty {
self.sites = Valet.shared.sites
diff --git a/phpmon/Domain/SiteList/SiteListWC.swift b/phpmon/Domain/SiteList/SiteListWC.swift
index 2a3122a..0e3ac47 100644
--- a/phpmon/Domain/SiteList/SiteListWC.swift
+++ b/phpmon/Domain/SiteList/SiteListWC.swift
@@ -8,10 +8,24 @@
import Cocoa
-class SiteListWC: NSWindowController {
+class SiteListWC: NSWindowController, NSSearchFieldDelegate {
+
+ @IBOutlet weak var searchToolbarItem: NSSearchToolbarItem!
override func windowDidLoad() {
super.windowDidLoad()
+ self.searchToolbarItem.searchField.delegate = self
+ self.searchToolbarItem.searchField.becomeFirstResponder()
+ }
+
+ func controlTextDidChange(_ notification: Notification) {
+ guard let searchField = notification.object as? NSSearchField else {
+ print("Unexpected control in update notification")
+ return
+ }
+
+ let window = self.contentViewController as! SiteListVC
+ window.searchedFor(text: searchField.stringValue)
}
}
diff --git a/phpmon/Localizable.strings b/phpmon/Localizable.strings
index fd91fcf..cbfd71d 100644
--- a/phpmon/Localizable.strings
+++ b/phpmon/Localizable.strings
@@ -50,7 +50,7 @@
// SITE LIST
-"site_list.title" = "Linked & Parked Domains";
+"site_list.title" = "Domains";
// SITE LIST ACTIONS