diff --git a/assets/affinity/icons.afdesign b/assets/affinity/icons.afdesign index 3d67e03..2fd0e2c 100644 Binary files a/assets/affinity/icons.afdesign and b/assets/affinity/icons.afdesign differ diff --git a/phpmon-tests/Parsers/ValetConfigParserTest.swift b/phpmon-tests/Parsers/ValetConfigParserTest.swift index c0a61e5..76259fe 100644 --- a/phpmon-tests/Parsers/ValetConfigParserTest.swift +++ b/phpmon-tests/Parsers/ValetConfigParserTest.swift @@ -32,6 +32,7 @@ class ValetConfigParserTest: XCTestCase { "/Users/username/.config/valet/Sites", "/Users/username/Sites" ]) + XCTAssertEqual(config.defaultSite, "/Users/username/default-site") XCTAssertEqual(config.loopback, "127.0.0.1") } diff --git a/phpmon-tests/Test Files/valet-config.json b/phpmon-tests/Test Files/valet-config.json index 713f006..be362c4 100644 --- a/phpmon-tests/Test Files/valet-config.json +++ b/phpmon-tests/Test Files/valet-config.json @@ -4,5 +4,6 @@ "/Users/username/.config/valet/Sites", "/Users/username/Sites" ], - "loopback": "127.0.0.1" + "loopback": "127.0.0.1", + "default": "/Users/username/default-site" } diff --git a/phpmon/Assets.xcassets/IconDefault.imageset/Contents.json b/phpmon/Assets.xcassets/IconDefault.imageset/Contents.json new file mode 100644 index 0000000..faa7509 --- /dev/null +++ b/phpmon/Assets.xcassets/IconDefault.imageset/Contents.json @@ -0,0 +1,25 @@ +{ + "images" : [ + { + "filename" : "Default.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Default@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/phpmon/Assets.xcassets/IconDefault.imageset/Default.png b/phpmon/Assets.xcassets/IconDefault.imageset/Default.png new file mode 100644 index 0000000..482c766 Binary files /dev/null and b/phpmon/Assets.xcassets/IconDefault.imageset/Default.png differ diff --git a/phpmon/Assets.xcassets/IconDefault.imageset/Default@2x.png b/phpmon/Assets.xcassets/IconDefault.imageset/Default@2x.png new file mode 100644 index 0000000..af331b0 Binary files /dev/null and b/phpmon/Assets.xcassets/IconDefault.imageset/Default@2x.png differ diff --git a/phpmon/Domain/Integrations/Valet/SiteScanner.swift b/phpmon/Domain/Integrations/Valet/SiteScanner.swift index 02265bc..5e963cb 100644 --- a/phpmon/Domain/Integrations/Valet/SiteScanner.swift +++ b/phpmon/Domain/Integrations/Valet/SiteScanner.swift @@ -13,6 +13,8 @@ protocol SiteScanner func resolveSiteCount(paths: [String]) -> Int func resolveSitesFrom(paths: [String]) -> [ValetSite] + + func resolveSite(path: String) -> ValetSite? } class FakeSiteScanner: SiteScanner @@ -41,6 +43,10 @@ class FakeSiteScanner: SiteScanner func resolveSitesFrom(paths: [String]) -> [ValetSite] { return fakes } + + func resolveSite(path: String) -> ValetSite? { + return nil + } } class ValetSiteScanner: SiteScanner @@ -67,7 +73,7 @@ class ValetSiteScanner: SiteScanner .contentsOfDirectory(atPath: path) return entries.forEach { - if let site = self.getSite($0, forPath: path, tld: Valet.shared.config.tld) { + if let site = self.resolveSite(path: "\($0)/\(path))") { sites.append(site) } } @@ -76,6 +82,35 @@ class ValetSiteScanner: SiteScanner return sites } + /** + 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. + */ + func resolveSite(path: String) -> ValetSite? { + // Get the TLD from the global Valet object + let tld = Valet.shared.config.tld + + // See if the file is a symlink, if so, resolve it + let attrs = try! FileManager.default.attributesOfItem(atPath: path) + + // We can also determine whether the thing at the path is a directory, too + let type = attrs[FileAttributeKey.type] as! FileAttributeType + + // We should also check that we can interpret the path correctly + if URL(fileURLWithPath: path).lastPathComponent == "" { + Log.warn("Could not parse the site: \(path), skipping!") + return nil + } + + if type == FileAttributeType.typeSymbolicLink { + return ValetSite(aliasPath: path, tld: tld) + } else if type == FileAttributeType.typeDirectory { + return ValetSite(absolutePath: path, tld: tld) + } + + return nil + } + /** 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. @@ -93,32 +128,4 @@ class ValetSiteScanner: SiteScanner 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 getSite(_ entry: String, forPath path: String, tld: String) -> ValetSite? { - let siteDir = path + "/" + entry - - // See if the file is a symlink, if so, resolve it - let attrs = try! FileManager.default.attributesOfItem(atPath: siteDir) - - // We can also determine whether the thing at the path is a directory, too - let type = attrs[FileAttributeKey.type] as! FileAttributeType - - // We should also check that we can interpret the path correctly - if URL(fileURLWithPath: siteDir).lastPathComponent == "" { - Log.warn("Could not parse the site: \(siteDir), skipping!") - return nil - } - - if type == FileAttributeType.typeSymbolicLink { - return ValetSite(aliasPath: siteDir, tld: tld) - } else if type == FileAttributeType.typeDirectory { - return ValetSite(absolutePath: siteDir, tld: tld) - } - - return nil - } } diff --git a/phpmon/Domain/Integrations/Valet/Valet.swift b/phpmon/Domain/Integrations/Valet/Valet.swift index 5c9f264..98a5940 100644 --- a/phpmon/Domain/Integrations/Valet/Valet.swift +++ b/phpmon/Domain/Integrations/Valet/Valet.swift @@ -98,6 +98,8 @@ class Valet { We don't want to do duplicate or parallel work! */ public func reloadSites() { + loadConfiguration() + if (isBusy) { return } @@ -155,6 +157,11 @@ class Valet { .resolveSitesFrom(paths: config.paths) .sorted { $0.absolutePath < $1.absolutePath } + if let defaultPath = Valet.shared.config.defaultSite, + let site = ValetSiteScanner().resolveSite(path: defaultPath) { + sites.insert(site, at: 0) + } + isBusy = false } diff --git a/phpmon/Domain/SiteList/Cells/SiteListKindCell.swift b/phpmon/Domain/SiteList/Cells/SiteListKindCell.swift index b12982b..9ca7346 100644 --- a/phpmon/Domain/SiteList/Cells/SiteListKindCell.swift +++ b/phpmon/Domain/SiteList/Cells/SiteListKindCell.swift @@ -15,6 +15,8 @@ class SiteListKindCell: NSTableCellView, SiteListCellProtocol func populateCell(with site: ValetSite) { + + // If the `aliasPath` is nil, we're dealing with a parked site (otherwise: linked). imageViewType.image = NSImage( named: site.aliasPath == nil @@ -22,6 +24,11 @@ class SiteListKindCell: NSTableCellView, SiteListCellProtocol : "IconLinked" ) + // Unless, of course, this is a default site + if site.absolutePath == Valet.shared.config.defaultSite { + imageViewType.image = NSImage(named: "IconDefault") + } + imageViewType.contentTintColor = NSColor.tertiaryLabelColor } } diff --git a/phpmon/Domain/SiteList/SiteListVC+Actions.swift b/phpmon/Domain/SiteList/SiteListVC+Actions.swift index dfab717..2cdf79e 100644 --- a/phpmon/Domain/SiteList/SiteListVC+Actions.swift +++ b/phpmon/Domain/SiteList/SiteListVC+Actions.swift @@ -78,8 +78,21 @@ extension SiteListVC { } @objc func isolateSite(sender: PhpMenuItem) { - self.performAction(command: "cd '\(selectedSite!.absolutePath)' && sudo \(Paths.valet) isolate php@\(sender.version) && exit;") { + let command = "cd '\(selectedSite!.absolutePath)' && sudo \(Paths.valet) isolate php@\(sender.version) && exit;" + + self.performAction(command: command) { self.selectedSite!.determineIsolated() + + if self.selectedSite!.isolatedPhpVersion == nil { + BetterAlert() + .withInformation( + title: "site_list.alerts_isolation_failed.title".localized, + subtitle: "site_list.alerts_isolation_failed.subtitle".localized, + description: "site_list.alerts_isolation_failed.desc".localized(command) + ) + .withPrimary(text: "OK") + .show() + } } } diff --git a/phpmon/Localizable.strings b/phpmon/Localizable.strings index 1be1503..baec93f 100644 --- a/phpmon/Localizable.strings +++ b/phpmon/Localizable.strings @@ -67,7 +67,11 @@ "site_list.title" = "Domains"; "site_list.subtitle" = "Linked & Parked"; -"site_list.alerts_status_not_changed.title" = "SSL Status Not Changed"; +"site_list.alerts_isolation_failed.title" = "Oops! Site Not Isolated"; +"site_list.alerts_isolation_failed.subtitle" = "Something went wrong trying to isolate this site. If this is your default site but it is not linked, I recommend manually linking the site prior to setting up isolation."; +"site_list.alerts_isolation_failed.desc" = "To find out what goes wrong, you can try running the command in your terminal manually: %@"; + +"site_list.alerts_status_not_changed.title" = "Oops! SSL Status Not Changed"; "site_list.alerts_status_not_changed.desc" = "Something went wrong. Try running the command in your terminal manually: %@"; "site_list.alerts_status_changed.title" = "SSL Status Changed";