diff --git a/PHP Monitor.xcodeproj/project.pbxproj b/PHP Monitor.xcodeproj/project.pbxproj index 1c7b251..b3dc014 100644 --- a/PHP Monitor.xcodeproj/project.pbxproj +++ b/PHP Monitor.xcodeproj/project.pbxproj @@ -45,7 +45,6 @@ C4080FF727BD8C6400BF2C6B /* BetterAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4080FF527BD8C6400BF2C6B /* BetterAlert.swift */; }; C4080FFA27BD956700BF2C6B /* BetterAlertVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4080FF927BD956700BF2C6B /* BetterAlertVC.swift */; }; C4080FFB27BD956700BF2C6B /* BetterAlertVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4080FF927BD956700BF2C6B /* BetterAlertVC.swift */; }; - C40B24F127A3106D0018C7D2 /* ServicesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EC1E67279DE0540010F296 /* ServicesView.swift */; }; C40B24F227A310770018C7D2 /* Events.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EC1E72279DFCF40010F296 /* Events.swift */; }; C40B24F427A310830018C7D2 /* StatusMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = C47331A1247093B7009A0597 /* StatusMenu.swift */; }; C40C5C9C2846A40600E28255 /* Preset.swift in Sources */ = {isa = PBXBuildFile; fileRef = C40C5C9B2846A40600E28255 /* Preset.swift */; }; @@ -182,7 +181,7 @@ C4B585442770FE3900DA4FBE /* Command.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4B5853D2770FE3900DA4FBE /* Command.swift */; }; C4B585452770FE3900DA4FBE /* Command.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4B5853D2770FE3900DA4FBE /* Command.swift */; }; C4B6091A2853AAD300C95265 /* MiniHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4B609192853AAD300C95265 /* MiniHeaderView.swift */; }; - C4B6091D2853AB9700C95265 /* NXServicesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4B6091C2853AB9700C95265 /* NXServicesView.swift */; }; + C4B6091D2853AB9700C95265 /* ServicesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4B6091C2853AB9700C95265 /* ServicesView.swift */; }; C4B97B75275CF08C003F3378 /* AppDelegate+MenuOutlets.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4B97B74275CF08C003F3378 /* AppDelegate+MenuOutlets.swift */; }; C4B97B76275CF08C003F3378 /* AppDelegate+MenuOutlets.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4B97B74275CF08C003F3378 /* AppDelegate+MenuOutlets.swift */; }; C4B97B78275CF1B5003F3378 /* App+ActivationPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4B97B77275CF1B5003F3378 /* App+ActivationPolicy.swift */; }; @@ -230,8 +229,6 @@ C4E0F7EE27BEBDA9007475F2 /* NSWindowExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E0F7EC27BEBDA9007475F2 /* NSWindowExtension.swift */; }; C4E4404627C56F4700D225E1 /* ValetSite.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E4404527C56F4700D225E1 /* ValetSite.swift */; }; C4E4404727C56F4700D225E1 /* ValetSite.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E4404527C56F4700D225E1 /* ValetSite.swift */; }; - C4EC1E66279DE0380010F296 /* ServicesView.xib in Resources */ = {isa = PBXBuildFile; fileRef = C4EC1E65279DE0380010F296 /* ServicesView.xib */; }; - C4EC1E68279DE0540010F296 /* ServicesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EC1E67279DE0540010F296 /* ServicesView.swift */; }; C4EC1E73279DFCF40010F296 /* Events.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EC1E72279DFCF40010F296 /* Events.swift */; }; C4EE188422D3386B00E126E5 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EE188322D3386B00E126E5 /* Constants.swift */; }; C4EED88927A48778006D7272 /* InterAppHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EED88827A48778006D7272 /* InterAppHandler.swift */; }; @@ -400,7 +397,7 @@ C4B5853C2770FE3900DA4FBE /* Shell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Shell.swift; sourceTree = ""; }; C4B5853D2770FE3900DA4FBE /* Command.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Command.swift; sourceTree = ""; }; C4B609192853AAD300C95265 /* MiniHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MiniHeaderView.swift; sourceTree = ""; }; - C4B6091C2853AB9700C95265 /* NXServicesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NXServicesView.swift; sourceTree = ""; }; + C4B6091C2853AB9700C95265 /* ServicesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServicesView.swift; sourceTree = ""; }; C4B97B74275CF08C003F3378 /* AppDelegate+MenuOutlets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppDelegate+MenuOutlets.swift"; sourceTree = ""; }; C4B97B77275CF1B5003F3378 /* App+ActivationPolicy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "App+ActivationPolicy.swift"; sourceTree = ""; }; C4B97B7A275CF20A003F3378 /* App+GlobalHotkey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "App+GlobalHotkey.swift"; sourceTree = ""; }; @@ -428,8 +425,6 @@ C4E4404527C56F4700D225E1 /* ValetSite.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ValetSite.swift; sourceTree = ""; }; C4E713562570150F00007428 /* SECURITY.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = SECURITY.md; sourceTree = ""; }; C4E713572570151400007428 /* docs */ = {isa = PBXFileReference; lastKnownFileType = folder; path = docs; sourceTree = ""; }; - C4EC1E65279DE0380010F296 /* ServicesView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ServicesView.xib; sourceTree = ""; }; - C4EC1E67279DE0540010F296 /* ServicesView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ServicesView.swift; sourceTree = ""; }; C4EC1E72279DFCF40010F296 /* Events.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Events.swift; sourceTree = ""; }; C4EE188322D3386B00E126E5 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = ""; }; C4EED88827A48778006D7272 /* InterAppHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InterAppHandler.swift; sourceTree = ""; }; @@ -774,8 +769,6 @@ C42800A928452AA10099C999 /* StatusMenu+Items.swift */, C48D0C9525CC80B100CC7490 /* HeaderView.swift */, C48D0C9925CC888B00CC7490 /* HeaderView.xib */, - C4EC1E67279DE0540010F296 /* ServicesView.swift */, - C4EC1E65279DE0380010F296 /* ServicesView.xib */, ); path = Menu; sourceTree = ""; @@ -878,7 +871,7 @@ C4B609172853AA9E00C95265 /* Menu */ = { isa = PBXGroup; children = ( - C4B6091C2853AB9700C95265 /* NXServicesView.swift */, + C4B6091C2853AB9700C95265 /* ServicesView.swift */, C4709CA128524B3400088BB8 /* StatsView.swift */, C4B609192853AAD300C95265 /* MiniHeaderView.swift */, ); @@ -1157,7 +1150,6 @@ C473319F2470923A009A0597 /* Localizable.strings in Resources */, C4F30B07278E195800755FCE /* brew-services.json in Resources */, C4068CA427B0780A00544CD5 /* CheckboxPreferenceView.xib in Resources */, - C4EC1E66279DE0380010F296 /* ServicesView.xib in Resources */, 54FCFD2D276C8D67004CE748 /* HotkeyPreferenceView.xib in Resources */, C405A4D024B9B9140062FAFA /* InternetAccessPolicy.strings in Resources */, C48D0C9A25CC888B00CC7490 /* HeaderView.xib in Resources */, @@ -1233,7 +1225,6 @@ C4C8E818276F54D8003AC782 /* App+ConfigWatch.swift in Sources */, 54FCFD30276C8DA4004CE748 /* HotkeyPreferenceView.swift in Sources */, C4E4404627C56F4700D225E1 /* ValetSite.swift in Sources */, - C4EC1E68279DE0540010F296 /* ServicesView.swift in Sources */, C4F2E43A2752F7D00020E974 /* PhpInstallation.swift in Sources */, C4D9F24B280B69E100DCD39A /* AddProxyVC.swift in Sources */, C41E871A2763D42300161EE0 /* DomainListVC+ContextMenu.swift in Sources */, @@ -1300,7 +1291,7 @@ C4709CA228524B3400088BB8 /* StatsView.swift in Sources */, C44CCD4027AFE2FC00CE40E5 /* AlertableError.swift in Sources */, C4188989275FE8CB001EF227 /* Filesystem.swift in Sources */, - C4B6091D2853AB9700C95265 /* NXServicesView.swift in Sources */, + C4B6091D2853AB9700C95265 /* ServicesView.swift in Sources */, C4B97B7B275CF20A003F3378 /* App+GlobalHotkey.swift in Sources */, C4EED88927A48778006D7272 /* InterAppHandler.swift in Sources */, C40C7F1E2772136000DDDCDC /* PhpEnv.swift in Sources */, @@ -1433,7 +1424,6 @@ C4AF9F7D275454A900D44ED0 /* ValetVersionExtractorTest.swift in Sources */, C4B56362276AB0A500F12CCB /* VersionExtractorTest.swift in Sources */, C4B585452770FE3900DA4FBE /* Command.swift in Sources */, - C40B24F127A3106D0018C7D2 /* ServicesView.swift in Sources */, C4F780C525D80B75000DBC97 /* MenuBarImageGenerator.swift in Sources */, C4F780B725D80B5D000DBC97 /* App.swift in Sources */, C4927F0C27B2DFC200C55AFD /* Errors.swift in Sources */, diff --git a/phpmon/Assets.xcassets/ServiceLoading.imageset/Contents.json b/phpmon/Assets.xcassets/ServiceLoading.imageset/Contents.json deleted file mode 100644 index b5851cb..0000000 --- a/phpmon/Assets.xcassets/ServiceLoading.imageset/Contents.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "images" : [ - { - "filename" : "ServiceLoading.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "ServiceLoading@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/ServiceLoading.imageset/ServiceLoading.png b/phpmon/Assets.xcassets/ServiceLoading.imageset/ServiceLoading.png deleted file mode 100644 index 2967845..0000000 Binary files a/phpmon/Assets.xcassets/ServiceLoading.imageset/ServiceLoading.png and /dev/null differ diff --git a/phpmon/Assets.xcassets/ServiceLoading.imageset/ServiceLoading@2x.png b/phpmon/Assets.xcassets/ServiceLoading.imageset/ServiceLoading@2x.png deleted file mode 100644 index 79ba93a..0000000 Binary files a/phpmon/Assets.xcassets/ServiceLoading.imageset/ServiceLoading@2x.png and /dev/null differ diff --git a/phpmon/Assets.xcassets/ServiceOff.imageset/Contents.json b/phpmon/Assets.xcassets/ServiceOff.imageset/Contents.json deleted file mode 100644 index 10f5302..0000000 --- a/phpmon/Assets.xcassets/ServiceOff.imageset/Contents.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "images" : [ - { - "filename" : "ServiceOff.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "ServiceOff@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/ServiceOff.imageset/ServiceOff.png b/phpmon/Assets.xcassets/ServiceOff.imageset/ServiceOff.png deleted file mode 100644 index 326901b..0000000 Binary files a/phpmon/Assets.xcassets/ServiceOff.imageset/ServiceOff.png and /dev/null differ diff --git a/phpmon/Assets.xcassets/ServiceOff.imageset/ServiceOff@2x.png b/phpmon/Assets.xcassets/ServiceOff.imageset/ServiceOff@2x.png deleted file mode 100644 index 9344277..0000000 Binary files a/phpmon/Assets.xcassets/ServiceOff.imageset/ServiceOff@2x.png and /dev/null differ diff --git a/phpmon/Assets.xcassets/ServiceOn.imageset/Contents.json b/phpmon/Assets.xcassets/ServiceOn.imageset/Contents.json deleted file mode 100644 index b1566c6..0000000 --- a/phpmon/Assets.xcassets/ServiceOn.imageset/Contents.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "images" : [ - { - "filename" : "ServiceOn.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "ServiceOn@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/ServiceOn.imageset/ServiceOn.png b/phpmon/Assets.xcassets/ServiceOn.imageset/ServiceOn.png deleted file mode 100644 index 5f424a3..0000000 Binary files a/phpmon/Assets.xcassets/ServiceOn.imageset/ServiceOn.png and /dev/null differ diff --git a/phpmon/Assets.xcassets/ServiceOn.imageset/ServiceOn@2x.png b/phpmon/Assets.xcassets/ServiceOn.imageset/ServiceOn@2x.png deleted file mode 100644 index c40fe32..0000000 Binary files a/phpmon/Assets.xcassets/ServiceOn.imageset/ServiceOn@2x.png and /dev/null differ diff --git a/phpmon/Common/PHP/Homebrew/HomebrewService.swift b/phpmon/Common/PHP/Homebrew/HomebrewService.swift index 7191016..cd1f02d 100644 --- a/phpmon/Common/PHP/Homebrew/HomebrewService.swift +++ b/phpmon/Common/PHP/Homebrew/HomebrewService.swift @@ -37,4 +37,21 @@ struct HomebrewService: Decodable, Equatable { } } } + + /** + Dummy data for preview purposes. + */ + public static func dummy(named service: String, enabled: Bool) -> Self { + return HomebrewService( + name: service, + service_name: service, + running: enabled, + loaded: enabled, + pid: nil, + user: nil, + status: nil, + log_path: nil, + error_log_path: nil + ) + } } diff --git a/phpmon/Domain/App/ServicesManager.swift b/phpmon/Domain/App/ServicesManager.swift index 6be3041..5d99b9f 100644 --- a/phpmon/Domain/App/ServicesManager.swift +++ b/phpmon/Domain/App/ServicesManager.swift @@ -17,8 +17,22 @@ class ServicesManager: ObservableObject { func loadData() { HomebrewService.loadAll { services in - self.services = Dictionary(uniqueKeysWithValues: services.map { ($0.name, $0) }) + self.services = Dictionary( + uniqueKeysWithValues: services.map { ($0.name, $0) } + ) } } + /** + Dummy data for preview purposes. + */ + func withDummyServices(_ services: [String: Bool]) -> Self { + for (service, enabled) in services { + let item = HomebrewService.dummy(named: service, enabled: enabled) + self.services[service] = item + } + + return self + } + } diff --git a/phpmon/Domain/Menu/ServicesView.swift b/phpmon/Domain/Menu/ServicesView.swift deleted file mode 100644 index 36f099c..0000000 --- a/phpmon/Domain/Menu/ServicesView.swift +++ /dev/null @@ -1,93 +0,0 @@ -// -// StatsView.swift -// PHP Monitor -// -// Created by Nico Verbruggen on 04/02/2021. -// Copyright © 2022 Nico Verbruggen. All rights reserved. -// - -import Foundation -import Cocoa - -/** - The ServicesView is an example of a view that I consider to be "poorly" set up. - Why ship it like this, then? Well, it works — that's reason number one, really. - - However, I do believe this should be refactored at some point. Here's why: - this view is responsible for retaining the information about the services status. - - The status of the services should live somewhere else, and the fetching of said - service information should also not happen in a view. Yet here we are. - */ -class ServicesView: NSView, XibLoadable { - - @IBOutlet weak var imageViewPhp: NSImageView! - @IBOutlet weak var imageViewNginx: NSImageView! - @IBOutlet weak var imageViewDnsmasq: NSImageView! - - @IBOutlet weak var textFieldPhp: NSTextField! - - static var services: [String: HomebrewService] = [:] - - static func asMenuItem() -> NSMenuItem { - let view = Self.createFromXib()! - [view.imageViewPhp, view.imageViewNginx, view.imageViewDnsmasq].forEach { imageView in - imageView?.contentTintColor = NSColor(named: "IconColorNormal") - } - let item = NSMenuItem() - item.view = view - item.target = self - NotificationCenter.default.addObserver( - view, selector: #selector(self.updateInformation), - name: Events.ServicesUpdated, - object: nil - ) - return item - } - - @objc func updateInformation() { - self.loadData() - } - - func loadData() { - self.applyAllInfoFieldsFromCachedValue() - HomebrewService.loadAll { services in - ServicesView.services = Dictionary(uniqueKeysWithValues: services.map { ($0.name, $0) }) - self.applyAllInfoFieldsFromCachedValue() - } - } - - func applyAllInfoFieldsFromCachedValue() { - if ServicesView.services.keys.isEmpty { - return - } - - DispatchQueue.main.async { - self.textFieldPhp.stringValue = PhpEnv.phpInstall.formula.uppercased() - self.applyServiceStyling(PhpEnv.phpInstall.formula, self.imageViewPhp) - self.applyServiceStyling("nginx", self.imageViewNginx) - self.applyServiceStyling("dnsmasq", self.imageViewDnsmasq) - } - } - - func applyServiceStyling(_ serviceName: String, _ imageView: NSImageView) { - if ServicesView.services[serviceName] == nil { - imageView.image = NSImage(named: "ServiceLoading") - imageView.contentTintColor = NSColor(named: "IconColorNormal") - return - } - - if ServicesView.services[serviceName]!.running { - imageView.image = NSImage(named: "ServiceOn") - imageView.contentTintColor = NSColor(named: "IconColorNormal") - return - } - - imageView.image = NSImage(named: "ServiceOff") - imageView.contentTintColor = NSColor(named: "IconColorRed") - } - - deinit { - NotificationCenter.default.removeObserver(self, name: Events.ServicesUpdated, object: nil) - } -} diff --git a/phpmon/Domain/Menu/ServicesView.xib b/phpmon/Domain/Menu/ServicesView.xib deleted file mode 100644 index 964d4b2..0000000 --- a/phpmon/Domain/Menu/ServicesView.xib +++ /dev/null @@ -1,150 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/phpmon/Domain/Menu/StatusMenu.swift b/phpmon/Domain/Menu/StatusMenu.swift index d2eeee7..5da271e 100644 --- a/phpmon/Domain/Menu/StatusMenu.swift +++ b/phpmon/Domain/Menu/StatusMenu.swift @@ -34,7 +34,7 @@ class StatusMenu: NSMenu { self.addSwitchToPhpMenuItems() self.addItem(NSMenuItem.separator()) - self.addItem(NXServicesView.asMenuItem()) + self.addItem(ServicesView.asMenuItem()) self.addItem(NSMenuItem.separator()) } diff --git a/phpmon/Domain/SwiftUI/Menu/NXServicesView.swift b/phpmon/Domain/SwiftUI/Menu/NXServicesView.swift deleted file mode 100644 index b631a42..0000000 --- a/phpmon/Domain/SwiftUI/Menu/NXServicesView.swift +++ /dev/null @@ -1,79 +0,0 @@ -// -// ServicesView.swift -// PHP Monitor -// -// Created by Nico Verbruggen on 10/06/2022. -// Copyright © 2022 Nico Verbruggen. All rights reserved. -// - -import Foundation - -import SwiftUI - -struct NXServicesView: View { - @ObservedObject var serviceManager: ServicesManager - - @State var serviceNames: [String] = { - return [ - PhpEnv.phpInstall.formula, - "nginx", - "dnsmasq" - ] - }() - - static func asMenuItem() -> NSMenuItem { - let item = NSMenuItem() - let view = NSHostingView(rootView: Self(serviceManager: ServicesManager.shared)) - view.frame = CGRect(x: 0, y: 0, width: 330, height: 55) - item.view = view - return item - } - - var body: some View { - HStack(alignment: .firstTextBaseline, spacing: 10) { - ForEach(serviceNames, id: \.self) { service in - VStack(alignment: .center, spacing: 3) { - MiniHeaderView(text: service.uppercased()) - CheckmarkView(serviceName: service).environmentObject(serviceManager) - }.frame(width: 90) - } - }.padding(10) - } -} - -struct CheckmarkView: View { - @State var serviceName: String - @EnvironmentObject var serviceManager: ServicesManager - - public func hasAnyServices() -> Bool { - return !serviceManager.services.isEmpty - } - - public func active() -> Bool { - guard let service = serviceManager.services[serviceName] else { - return false - } - - return service.running - } - - var body: some View { - if !hasAnyServices() { - Image(systemName: "questionmark.circle") - .resizable() - .frame(width: 16.0, height: 16.0) - .foregroundColor(.black) - } else { - Image(systemName: "checkmark.circle") - .resizable() - .frame(width: 16.0, height: 16.0) - .foregroundColor(active() ? Color.black : Color("IconColorRed")) - } - } -} - -struct NXServicesView_Previews: PreviewProvider { - static var previews: some View { - NXServicesView(serviceManager: ServicesManager.shared) - } -} diff --git a/phpmon/Domain/SwiftUI/Menu/ServicesView.swift b/phpmon/Domain/SwiftUI/Menu/ServicesView.swift new file mode 100644 index 0000000..dca170d --- /dev/null +++ b/phpmon/Domain/SwiftUI/Menu/ServicesView.swift @@ -0,0 +1,112 @@ +// +// ServicesView.swift +// PHP Monitor +// +// Created by Nico Verbruggen on 10/06/2022. +// Copyright © 2022 Nico Verbruggen. All rights reserved. +// + +import Foundation +import SwiftUI + +struct ServicesView: View { + @ObservedObject var serviceManager: ServicesManager + @State var servicesToDisplay: [String] + + static func asMenuItem() -> NSMenuItem { + let item = NSMenuItem() + let view = NSHostingView( + rootView: Self( + serviceManager: ServicesManager.shared, + servicesToDisplay: [ + PhpEnv.phpInstall.formula, + "nginx", + "dnsmasq" + ] + ) + ) + view.frame = CGRect(x: 0, y: 0, width: 330, height: 45) + item.view = view + return item + } + + var body: some View { + HStack(alignment: .firstTextBaseline, spacing: 10) { + ForEach(servicesToDisplay, id: \.self) { service in + VStack(alignment: .center, spacing: 3) { + MiniHeaderView(text: service.uppercased()) + CheckmarkView(serviceName: service).environmentObject(serviceManager) + }.frame(minWidth: 0, maxWidth: .infinity) + } + }.padding(10) + } +} + +struct CheckmarkView: View { + @State var serviceName: String + @EnvironmentObject var serviceManager: ServicesManager + + public func hasAnyServices() -> Bool { + return !serviceManager.services.isEmpty + } + + public func active() -> Bool { + guard let service = serviceManager.services[serviceName] else { + return false + } + + return service.running + } + + var body: some View { + if !hasAnyServices() { + Image(systemName: "questionmark.circle") + .resizable() + .frame(width: 16.0, height: 16.0) + .foregroundColor(.secondary) + } else { + Image(systemName: active() ? "checkmark.circle" : "exclamationmark.triangle") + .resizable() + .frame(width: 16.0, height: 16.0) + .foregroundColor(active() ? Color("IconColorGreen") : Color("IconColorRed")) + } + } +} + +struct ServicesView_Previews: PreviewProvider { + static var previews: some View { + ServicesView( + serviceManager: ServicesManager() + .withDummyServices([:]), + servicesToDisplay: ["php", "nginx", "dnsmasq"] + ) + .frame(width: 330.0) + .previewDisplayName("Loading") + + ServicesView( + serviceManager: ServicesManager() + .withDummyServices([ + "php": false, + "nginx": true, + "dnsmasq": true + ]), + servicesToDisplay: ["php", "nginx", "dnsmasq"] + ) + .frame(width: 330.0) + .previewDisplayName("Light Mode") + + ServicesView( + serviceManager: ServicesManager() + .withDummyServices([ + "php": false, + "nginx": true, + "dnsmasq": true, + "mysql": false + ]), + servicesToDisplay: ["php", "nginx", "dnsmasq", "mysql"] + ) + .frame(width: 330.0) + .previewDisplayName("Dark Mode") + .preferredColorScheme(.dark) + } +}