diff --git a/README.md b/README.md index b5bcef9..222e1a0 100644 --- a/README.md +++ b/README.md @@ -79,16 +79,28 @@ If you're still having issues, here's a few common questions & answers, as well
Which versions of PHP are supported? +The following versions of PHP are officially supported: + + + +The following versions have some support via backport and/or dev version: + + + +Additionally, the following dev version is also available: + @@ -96,6 +108,8 @@ For more details, consult the [constants file](https://github.com/nicoverbruggen Backports are available via [this tap](https://github.com/shivammathur/homebrew-php). For more information about those backports, please see the next FAQ entry. +For maximum compatibility with older PHP versions, you may wish to keep using Valet 2 or 3. +
diff --git a/SECURITY.md b/SECURITY.md index e9a4382..4543d3e 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -6,7 +6,7 @@ Generally speaking, only the latest version of **PHP Monitor** is supported, exc | Version | Apple Silicon | Supported | Supported macOS | Deployment Target | Detected PHP Versions | Recommended Valet Version | | ------- | ------------- | ------------------ | ----- | ----- | ----- | ---- -| 6.x | ✅ Universal binary | ✅ Yes | Big Sur (11.0)
Monterey (12.0)
Ventura (13.0) | macOS 11+ | PHP 5.6—PHP 8.2 (w/ Valet 2.x)
PHP 7.0—PHP 8.2 (w/ Valet 3.x) | 3.0 recommended
2.16.2 minimum | +| 6.x | ✅ Universal binary | ✅ Yes | Big Sur (11.0)
Monterey (12.0)
Ventura (13.0) | macOS 11+ | PHP 5.6—PHP 8.2 (w/ Valet 2.x)
PHP 7.0—PHP 8.2 (w/ Valet 3.x)
PHP 7.4-PHP 8.2 (w/ Valet 4.x) | 3.0 or higher recommended
2.16.2 minimum | ## Legacy versions diff --git a/phpmon/Common/Core/Actions.swift b/phpmon/Common/Core/Actions.swift index 4851993..072463c 100644 --- a/phpmon/Common/Core/Actions.swift +++ b/phpmon/Common/Core/Actions.swift @@ -71,7 +71,7 @@ class Actions { "services stop \(name)", sudo: ServicesManager.shared[name]?.formula.elevated ?? false ) - await ServicesManager.shared.updateServices() + await ServicesManager.shared.reloadServicesStatus() } public static func startService(name: String) async { @@ -79,7 +79,7 @@ class Actions { "services start \(name)", sudo: ServicesManager.shared[name]?.formula.elevated ?? false ) - await ServicesManager.shared.updateServices() + await ServicesManager.shared.reloadServicesStatus() } // MARK: - Finding Config Files diff --git a/phpmon/Domain/App/Services/FakeServicesManager.swift b/phpmon/Domain/App/Services/FakeServicesManager.swift index 0601028..0c4b9dc 100644 --- a/phpmon/Domain/App/Services/FakeServicesManager.swift +++ b/phpmon/Domain/App/Services/FakeServicesManager.swift @@ -40,7 +40,7 @@ class FakeServicesManager: ServicesManager { } } - override func updateServices() async { + override func reloadServicesStatus() async { await delay(seconds: 0.3) for formula in self.serviceWrappers { @@ -48,7 +48,29 @@ class FakeServicesManager: ServicesManager { formula.isBusy = false } - print("Sending the update!") broadcastServicesUpdated() } + + override func toggleService(named: String) async { + guard let wrapper = self[named] else { + return Log.err("The wrapper for service \(named) does not exist.") + } + + wrapper.isBusy = true + Task { @MainActor in + wrapper.objectWillChange.send() + } + + guard let service = wrapper.service else { + return Log.err("The actual service for wrapper \(named) is nil.") + } + + await delay(seconds: 2) + service.running = !service.running + wrapper.isBusy = false + Task { @MainActor in + wrapper.objectWillChange.send() + self.objectWillChange.send() + } + } } diff --git a/phpmon/Domain/App/Services/ServicesManager.swift b/phpmon/Domain/App/Services/ServicesManager.swift index b8d124b..0cd58ca 100644 --- a/phpmon/Domain/App/Services/ServicesManager.swift +++ b/phpmon/Domain/App/Services/ServicesManager.swift @@ -17,7 +17,7 @@ class ServicesManager: ObservableObject { public static func useFake() { ServicesManager.shared = FakeServicesManager.init( - formulae: ["php", "nginx", "dnsmasq"], + formulae: ["php", "nginx", "dnsmasq", "mysql"], status: .loading ) } @@ -38,6 +38,7 @@ class ServicesManager: ObservableObject { } let statuses = self.serviceWrappers[0...2].map { $0.status } + if statuses.contains(.loading) { return "Determining Valet status..." } @@ -70,16 +71,25 @@ class ServicesManager: ObservableObject { return .green } - @available(*, deprecated, message: "Use a more specific method instead") - static func loadHomebrewServices() { - // print(self.shared) - print("This method must be updated") + /** + This method is called when the system configuration has changed + and all the status of one or more services may need to be determined. + */ + public func reloadServicesStatus() async { + fatalError("This method `\(#function)` has not been implemented") } - public func updateServices() async { - fatalError("Must be implemented in child class") + /** + This method is called when a service needs to be toggled (on/off). + */ + public func toggleService(named: String) async { + fatalError("This method `\(#function)` has not been implemented") } + /** + This method will notify all publishers that subscribe to notifiable objects. + The notified objects include this very ServicesManager as well as any individual service instances. + */ public func broadcastServicesUpdated() { Task { @MainActor in self.serviceWrappers.forEach { wrapper in diff --git a/phpmon/Domain/App/Services/ValetServicesManager.swift b/phpmon/Domain/App/Services/ValetServicesManager.swift index 9ffff96..be5531c 100644 --- a/phpmon/Domain/App/Services/ValetServicesManager.swift +++ b/phpmon/Domain/App/Services/ValetServicesManager.swift @@ -13,10 +13,10 @@ class ValetServicesManager: ServicesManager { super.init() // Load the initial services state - Task { await self.updateServices() } + Task { await self.reloadServicesStatus() } } - override func updateServices() async { + override func reloadServicesStatus() async { // TODO } } diff --git a/phpmon/Domain/Menu/MainMenu+Async.swift b/phpmon/Domain/Menu/MainMenu+Async.swift index ca9b766..013913a 100644 --- a/phpmon/Domain/Menu/MainMenu+Async.swift +++ b/phpmon/Domain/Menu/MainMenu+Async.swift @@ -74,7 +74,7 @@ extension MainMenu { } if behaviours.contains(.broadcastServicesUpdate) { - Task { await ServicesManager.shared.updateServices() } + Task { await ServicesManager.shared.reloadServicesStatus() } } if error != nil { diff --git a/phpmon/Domain/Menu/MainMenu.swift b/phpmon/Domain/Menu/MainMenu.swift index 727e54a..b411efc 100644 --- a/phpmon/Domain/Menu/MainMenu.swift +++ b/phpmon/Domain/Menu/MainMenu.swift @@ -94,7 +94,7 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate, PhpSwitcherDelegate self.refreshActiveInstallation() self.refreshIcon() self.rebuild() - await ServicesManager.shared.updateServices() + await ServicesManager.shared.reloadServicesStatus() Log.perf("The menu has been reloaded!") } } @@ -184,7 +184,7 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate, PhpSwitcherDelegate // Make sure the shortcut key does not trigger this when the menu is open App.shared.shortcutHotkey?.isPaused = true Task { // Reload Homebrew services information asynchronously - await ServicesManager.shared.updateServices() + await ServicesManager.shared.reloadServicesStatus() } } diff --git a/phpmon/Domain/SwiftUI/Menu/ServicesView.swift b/phpmon/Domain/SwiftUI/Menu/ServicesView.swift index 606c894..566dffc 100644 --- a/phpmon/Domain/SwiftUI/Menu/ServicesView.swift +++ b/phpmon/Domain/SwiftUI/Menu/ServicesView.swift @@ -119,27 +119,19 @@ struct ServiceView: View { // .buttonStyle(BlueButton()) .frame(minWidth: 70, alignment: .center) } - if service.status == .active { + if service.status == .active || service.status == .inactive { Button { - // TODO - print("you pressed the button") + Task { await ServicesManager.shared.toggleService(named: service.name) } } label: { - Image(systemName: "checkmark") - .resizable() - .frame(width: 12.0, height: 12.0) - .foregroundColor(Color("IconColorGreen")) - } - .frame(width: 25, height: 25) - } - if service.status == .inactive { - Button { - // TODO - } label: { - Image(systemName: "xmark") - .resizable() - .frame(width: 12.0, height: 12.0) - .foregroundColor(Color("IconColorRed")) - } + Image( + systemName: service.status == .active ? "checkmark" : "xmark" + ) + .resizable() + .frame(width: 12.0, height: 12.0) + .foregroundColor( + service.status == .active ? Color("IconColorGreen") : Color("IconColorRed") + ) + }.frame(width: 25, height: 25) } }.frame(minWidth: 70) }