diff --git a/PHP Monitor.xcodeproj/project.pbxproj b/PHP Monitor.xcodeproj/project.pbxproj index 1d44ff5..62bbf61 100644 --- a/PHP Monitor.xcodeproj/project.pbxproj +++ b/PHP Monitor.xcodeproj/project.pbxproj @@ -33,6 +33,8 @@ 54FCFD2E276C8D67004CE748 /* HotkeyPreferenceView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 54FCFD2C276C8D67004CE748 /* HotkeyPreferenceView.xib */; }; 54FCFD30276C8DA4004CE748 /* HotkeyPreferenceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54FCFD2F276C8DA4004CE748 /* HotkeyPreferenceView.swift */; }; 54FCFD31276C8DA4004CE748 /* HotkeyPreferenceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54FCFD2F276C8DA4004CE748 /* HotkeyPreferenceView.swift */; }; + C40508AF28ADA23D008FAC1F /* NoDomainResultsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C40508AE28ADA23D008FAC1F /* NoDomainResultsView.swift */; }; + C40508B128ADAB44008FAC1F /* NSMenuItemExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C40508B028ADAB44008FAC1F /* NSMenuItemExtension.swift */; }; C405A4D024B9B9140062FAFA /* InternetAccessPolicy.strings in Resources */ = {isa = PBXBuildFile; fileRef = C405A4CE24B9B9130062FAFA /* InternetAccessPolicy.strings */; }; C405A4D124B9B9140062FAFA /* InternetAccessPolicy.plist in Resources */ = {isa = PBXBuildFile; fileRef = C405A4CF24B9B9140062FAFA /* InternetAccessPolicy.plist */; }; C4068CA427B0780A00544CD5 /* CheckboxPreferenceView.xib in Resources */ = {isa = PBXBuildFile; fileRef = C4068CA327B0780A00544CD5 /* CheckboxPreferenceView.xib */; }; @@ -314,6 +316,8 @@ 54FCFD29276C8AA4004CE748 /* CheckboxPreferenceView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckboxPreferenceView.swift; sourceTree = ""; }; 54FCFD2C276C8D67004CE748 /* HotkeyPreferenceView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = HotkeyPreferenceView.xib; sourceTree = ""; }; 54FCFD2F276C8DA4004CE748 /* HotkeyPreferenceView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HotkeyPreferenceView.swift; sourceTree = ""; }; + C40508AE28ADA23D008FAC1F /* NoDomainResultsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoDomainResultsView.swift; sourceTree = ""; }; + C40508B028ADAB44008FAC1F /* NSMenuItemExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSMenuItemExtension.swift; sourceTree = ""; }; C405A4CE24B9B9130062FAFA /* InternetAccessPolicy.strings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; path = InternetAccessPolicy.strings; sourceTree = ""; }; C405A4CF24B9B9140062FAFA /* InternetAccessPolicy.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = InternetAccessPolicy.plist; sourceTree = ""; }; C4068CA327B0780A00544CD5 /* CheckboxPreferenceView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CheckboxPreferenceView.xib; sourceTree = ""; }; @@ -944,6 +948,7 @@ isa = PBXGroup; children = ( C44264BF2850BD2A007400F1 /* VersionPopoverView.swift */, + C40508AE28ADA23D008FAC1F /* NoDomainResultsView.swift */, ); path = Domains; sourceTree = ""; @@ -1120,6 +1125,7 @@ C46FA23E246C358E00944F05 /* StringExtension.swift */, C48D0C9225CC804200CC7490 /* XibLoadable.swift */, C42759662627662800093CAE /* NSMenuExtension.swift */, + C40508B028ADAB44008FAC1F /* NSMenuItemExtension.swift */, C4E0F7EC27BEBDA9007475F2 /* NSWindowExtension.swift */, C4EB53E628553117006F9937 /* ArrayExtension.swift */, ); @@ -1375,6 +1381,7 @@ C44CCD4027AFE2FC00CE40E5 /* AlertableError.swift in Sources */, C4188989275FE8CB001EF227 /* Filesystem.swift in Sources */, C4B6091D2853AB9700C95265 /* ServicesView.swift in Sources */, + C40508B128ADAB44008FAC1F /* NSMenuItemExtension.swift in Sources */, C4B97B7B275CF20A003F3378 /* App+GlobalHotkey.swift in Sources */, C4EED88927A48778006D7272 /* InterAppHandler.swift in Sources */, C40C7F1E2772136000DDDCDC /* PhpEnv.swift in Sources */, @@ -1392,6 +1399,7 @@ C44067F927E2585E0045BD4E /* DomainListTypeCell.swift in Sources */, 54D9E0BA27E4F51E003B9AD9 /* ModifierFlagsExtension.swift in Sources */, C4C3ED412783497000AB15D8 /* MainMenu+Startup.swift in Sources */, + C40508AF28ADA23D008FAC1F /* NoDomainResultsView.swift in Sources */, C4D89BC62783C99400A02B68 /* ComposerJson.swift in Sources */, C46FA23F246C358E00944F05 /* StringExtension.swift in Sources */, C42E3BF428A9BF5100AFECFC /* Shell+PATH.swift in Sources */, @@ -1687,7 +1695,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 950; + CURRENT_PROJECT_VERSION = 955; DEBUG = YES; DEVELOPMENT_TEAM = 8M54J5J787; ENABLE_HARDENED_RUNTIME = YES; @@ -1697,7 +1705,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 5.5.0; + MARKETING_VERSION = 5.6.0; PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1714,7 +1722,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 950; + CURRENT_PROJECT_VERSION = 955; DEBUG = NO; DEVELOPMENT_TEAM = 8M54J5J787; ENABLE_HARDENED_RUNTIME = YES; @@ -1724,7 +1732,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 5.5.0; + MARKETING_VERSION = 5.6.0; PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/phpmon/Common/Extensions/NSMenuExtension.swift b/phpmon/Common/Extensions/NSMenuExtension.swift index 105beaa..23fac8f 100644 --- a/phpmon/Common/Extensions/NSMenuExtension.swift +++ b/phpmon/Common/Extensions/NSMenuExtension.swift @@ -9,43 +9,28 @@ import Cocoa extension NSMenu { - - open func addItem(_ newItem: NSMenuItem, withKeyModifier modifier: NSEvent.ModifierFlags) { + open func addItem( + _ newItem: NSMenuItem, + withKeyModifier modifier: NSEvent.ModifierFlags + ) { newItem.keyEquivalentModifierMask = modifier self.addItem(newItem) } + open func addItems(_ items: [NSMenuItem], target: NSObject? = nil) { + for item in items { + self.addItem(item) + if target != nil { + item.target = target + } + } + } } @IBDesignable class LocalizedMenuItem: NSMenuItem { - - @IBInspectable - var localizationKey: String? { + @IBInspectable var localizationKey: String? { didSet { self.title = localizationKey?.localized ?? self.title } } - -} - -// MARK: - NSMenuItem subclasses - -class PhpMenuItem: NSMenuItem { - var version: String = "" -} - -class XdebugMenuItem: NSMenuItem { - var mode: String = "" -} - -class ExtensionMenuItem: NSMenuItem { - var phpExtension: PhpExtension? -} - -class EditorMenuItem: NSMenuItem { - var editor: Application? -} - -class PresetMenuItem: NSMenuItem { - var preset: Preset? } diff --git a/phpmon/Common/Extensions/NSMenuItemExtension.swift b/phpmon/Common/Extensions/NSMenuItemExtension.swift new file mode 100644 index 0000000..8f2a27b --- /dev/null +++ b/phpmon/Common/Extensions/NSMenuItemExtension.swift @@ -0,0 +1,45 @@ +// +// NSMenuItem.swift +// PHP Monitor +// +// Created by Nico Verbruggen on 18/08/2022. +// Copyright © 2022 Nico Verbruggen. All rights reserved. +// + +import Cocoa + +extension NSMenuItem { + convenience init( + title: String, + action: Selector? = nil, + keyEquivalent: String = "", + keyModifier: NSEvent.ModifierFlags = [], + tooltip: String = "", + submenu: NSMenu? = nil + ) { + self.init(title: title, action: action, keyEquivalent: keyEquivalent) + self.keyEquivalentModifierMask = keyModifier + } +} + +// MARK: - NSMenuItem subclasses + +class PhpMenuItem: NSMenuItem { + var version: String = "" +} + +class XdebugMenuItem: NSMenuItem { + var mode: String = "" +} + +class ExtensionMenuItem: NSMenuItem { + var phpExtension: PhpExtension? +} + +class EditorMenuItem: NSMenuItem { + var editor: Application? +} + +class PresetMenuItem: NSMenuItem { + var preset: Preset? +} diff --git a/phpmon/Common/PHP/Extensions/Xdebug.swift b/phpmon/Common/PHP/Extensions/Xdebug.swift index a340a6a..3ef19c8 100644 --- a/phpmon/Common/PHP/Extensions/Xdebug.swift +++ b/phpmon/Common/PHP/Extensions/Xdebug.swift @@ -7,6 +7,7 @@ // import Foundation +import Cocoa class Xdebug { @@ -26,6 +27,26 @@ class Xdebug { return value.components(separatedBy: ",").filter { self.modes.contains($0) } } + public static func asMenuItems() -> [NSMenuItem] { + var items: [NSMenuItem] = [] + + let activeModes = Self.activeModes + + for mode in Self.modes { + let item = XdebugMenuItem( + title: mode, + action: #selector(MainMenu.toggleXdebugMode(sender:)), + keyEquivalent: "" + ) + + item.state = activeModes.contains(mode) ? .on : .off + item.mode = mode + items.append(item) + } + + return items + } + public static var modes: [String] { return [ "develop", diff --git a/phpmon/Domain/Menu/StatusMenu+Items.swift b/phpmon/Domain/Menu/StatusMenu+Items.swift index c6bfde5..b18fce6 100644 --- a/phpmon/Domain/Menu/StatusMenu+Items.swift +++ b/phpmon/Domain/Menu/StatusMenu+Items.swift @@ -13,35 +13,37 @@ extension StatusMenu { // MARK: Remaining Menu Items func addConfigurationMenuItems() { - self.addItem(HeaderView.asMenuItem(text: "mi_configuration".localized)) - self.addItem( + self.addItems([ + HeaderView.asMenuItem(text: "mi_configuration".localized), NSMenuItem(title: "mi_php_config".localized, - action: #selector(MainMenu.openActiveConfigFolder), keyEquivalent: "c") - ) - self.addItem( + action: #selector(MainMenu.openActiveConfigFolder), + keyEquivalent: "c"), NSMenuItem(title: "mi_phpmon_config".localized, - action: #selector(MainMenu.openPhpMonitorConfigurationFile), keyEquivalent: "y") - ) - self.addItem( - NSMenuItem(title: "mi_phpinfo".localized, action: #selector(MainMenu.openPhpInfo), keyEquivalent: "i") - ) + action: #selector(MainMenu.openPhpMonitorConfigurationFile), + keyEquivalent: "y"), + NSMenuItem(title: "mi_phpinfo".localized, + action: #selector(MainMenu.openPhpInfo), + keyEquivalent: "i") + ]) } func addComposerMenuItems() { - self.addItem(HeaderView.asMenuItem(text: "mi_composer".localized)) - self.addItem( - NSMenuItem(title: "mi_global_composer".localized, - action: #selector(MainMenu.openGlobalComposerFolder), keyEquivalent: "g") - ) - - let composerMenuItem = NSMenuItem( - title: "mi_update_global_composer".localized, - action: PhpEnv.shared.isBusy ? nil : #selector(MainMenu.updateGlobalComposerDependencies), - keyEquivalent: "g" - ) - composerMenuItem.keyEquivalentModifierMask = .shift - - self.addItem(composerMenuItem) + self.addItems([ + HeaderView.asMenuItem(text: "mi_composer".localized), + NSMenuItem( + title: "mi_global_composer".localized, + action: #selector(MainMenu.openGlobalComposerFolder), + keyEquivalent: "g" + ), + NSMenuItem( + title: "mi_update_global_composer".localized, + action: PhpEnv.shared.isBusy + ? nil + : #selector(MainMenu.updateGlobalComposerDependencies), + keyEquivalent: "g", + keyModifier: [.shift] + ) + ]) } func addStatsMenuItem() { @@ -157,100 +159,64 @@ extension StatusMenu { return } - self.addItem(NSMenuItem.separator()) - let xdebugSwitch = NSMenuItem( - title: "mi_xdebug_mode".localized, - action: nil, - keyEquivalent: "" - ) - let xdebugModesMenu = NSMenu() - let activeModes = Xdebug.activeModes - - xdebugModesMenu.addItem(HeaderView.asMenuItem(text: "mi_xdebug_available_modes".localized)) - - for mode in Xdebug.modes { - let item = XdebugMenuItem( - title: mode, - action: #selector(MainMenu.toggleXdebugMode(sender:)), - keyEquivalent: "" - ) - - item.state = activeModes.contains(mode) ? .on : .off - item.mode = mode - xdebugModesMenu.addItem(item) - } - - xdebugModesMenu.addItem(HeaderView.asMenuItem(text: "mi_xdebug_actions".localized)) - xdebugModesMenu.addItem( - withTitle: "mi_xdebug_disable_all".localized, - action: #selector(MainMenu.disableAllXdebugModes), - keyEquivalent: "" + let submenu = NSMenu() + submenu.addItems( + [HeaderView.asMenuItem(text: "mi_xdebug_available_modes".localized)] + + Xdebug.asMenuItems() + + [HeaderView.asMenuItem(text: "mi_xdebug_actions".localized), + NSMenuItem(title: "mi_xdebug_disable_all".localized, + action: #selector(MainMenu.disableAllXdebugModes)) + ], + target: MainMenu.shared ) - for item in xdebugModesMenu.items { - item.target = MainMenu.shared - } + let xdebugItem = NSMenuItem(title: "mi_xdebug_mode".localized) + self.setSubmenu(submenu, for: xdebugItem) - self.setSubmenu(xdebugModesMenu, for: xdebugSwitch) - self.addItem(xdebugSwitch) + self.addItems([ + NSMenuItem.separator(), + xdebugItem + ], target: MainMenu.shared) } func addFirstAidAndServicesMenuItems() { - let services = NSMenuItem(title: "mi_other".localized, action: nil, keyEquivalent: "") + let services = NSMenuItem(title: "mi_other".localized) + let servicesMenu = NSMenu() + servicesMenu.addItems([ + // FIRST AID + HeaderView.asMenuItem(text: "mi_first_aid".localized), + NSMenuItem(title: "mi_view_onboarding".localized, action: #selector(MainMenu.showWelcomeTour)), + NSMenuItem(title: "mi_fa_php_doctor".localized, action: #selector(MainMenu.openWarnings)), + NSMenuItem.separator(), + NSMenuItem(title: "mi_fix_my_valet".localized(PhpEnv.brewPhpVersion), + action: #selector(MainMenu.fixMyValet), + tooltip: "mi_fix_my_valet_tooltip".localized), + NSMenuItem(title: "mi_fix_brew_permissions".localized(), action: #selector(MainMenu.fixHomebrewPermissions), + tooltip: "mi_fix_brew_permissions_tooltip".localized), + NSMenuItem.separator(), - servicesMenu.addItem(HeaderView.asMenuItem(text: "mi_first_aid".localized)) + // SERVICES + HeaderView.asMenuItem(text: "mi_services".localized), + NSMenuItem(title: "mi_restart_dnsmasq".localized, action: #selector(MainMenu.restartDnsMasq), + keyEquivalent: "d"), + NSMenuItem(title: "mi_restart_php_fpm".localized, action: #selector(MainMenu.restartPhpFpm), + keyEquivalent: "p"), + NSMenuItem(title: "mi_restart_nginx".localized, action: #selector(MainMenu.restartNginx), + keyEquivalent: "n"), + NSMenuItem(title: "mi_restart_valet_services".localized, action: #selector(MainMenu.restartValetServices), + keyEquivalent: "s"), + NSMenuItem(title: "mi_stop_valet_services".localized, action: #selector(MainMenu.stopValetServices), + keyEquivalent: "s", + keyModifier: [.command, .shift]), + NSMenuItem.separator(), - servicesMenu.addItem(NSMenuItem(title: "mi_view_onboarding".localized, - action: #selector(MainMenu.showWelcomeTour), keyEquivalent: "")) - - servicesMenu.addItem(NSMenuItem(title: "mi_fa_php_doctor".localized, - action: #selector(MainMenu.openWarnings), keyEquivalent: "")) - servicesMenu.addItem(NSMenuItem.separator()) - - let fixMyValetMenuItem = NSMenuItem( - title: "mi_fix_my_valet".localized(PhpEnv.brewPhpVersion), - action: #selector(MainMenu.fixMyValet), keyEquivalent: "" - ) - fixMyValetMenuItem.toolTip = "mi_fix_my_valet_tooltip".localized - servicesMenu.addItem(fixMyValetMenuItem) - - let fixHomebrewMenuItem = NSMenuItem( - title: "mi_fix_brew_permissions".localized(), - action: #selector(MainMenu.fixHomebrewPermissions), keyEquivalent: "" - ) - fixHomebrewMenuItem.toolTip = "mi_fix_brew_permissions_tooltip".localized - servicesMenu.addItem(fixHomebrewMenuItem) - - servicesMenu.addItem(NSMenuItem.separator()) - servicesMenu.addItem(HeaderView.asMenuItem(text: "mi_services".localized)) - - servicesMenu.addItem(NSMenuItem(title: "mi_restart_dnsmasq".localized, - action: #selector(MainMenu.restartDnsMasq), keyEquivalent: "d")) - servicesMenu.addItem(NSMenuItem(title: "mi_restart_php_fpm".localized, - action: #selector(MainMenu.restartPhpFpm), keyEquivalent: "p")) - - servicesMenu.addItem(NSMenuItem(title: "mi_restart_nginx".localized, - action: #selector(MainMenu.restartNginx), keyEquivalent: "n")) - servicesMenu.addItem(NSMenuItem(title: "mi_restart_valet_services".localized, - action: #selector(MainMenu.restartValetServices), keyEquivalent: "s")) - servicesMenu.addItem( - NSMenuItem(title: "mi_stop_valet_services".localized, - action: #selector(MainMenu.stopValetServices), keyEquivalent: "s"), - withKeyModifier: [.command, .shift] - ) - - servicesMenu.addItem(NSMenuItem.separator()) - servicesMenu.addItem(HeaderView.asMenuItem(text: "mi_manual_actions".localized)) - - servicesMenu.addItem( + // MANUAL ACTIONS + HeaderView.asMenuItem(text: "mi_manual_actions".localized), NSMenuItem(title: "mi_php_refresh".localized, - action: #selector(MainMenu.reloadPhpMonitorMenuInForeground), keyEquivalent: "r") - ) - - for item in servicesMenu.items { - item.target = MainMenu.shared - } + action: #selector(MainMenu.reloadPhpMonitorMenuInForeground), + keyEquivalent: "r") + ], target: MainMenu.shared) self.setSubmenu(servicesMenu, for: services) self.addItem(services) diff --git a/phpmon/Domain/SwiftUI/Domains/NoDomainResultsView.swift b/phpmon/Domain/SwiftUI/Domains/NoDomainResultsView.swift new file mode 100644 index 0000000..3644fc1 --- /dev/null +++ b/phpmon/Domain/SwiftUI/Domains/NoDomainResultsView.swift @@ -0,0 +1,37 @@ +// +// NoDomainResults.swift +// PHP Monitor +// +// Created by Nico Verbruggen on 15/08/2022. +// Copyright © 2022 Nico Verbruggen. All rights reserved. +// + +import SwiftUI + +struct NoDomainResults: View { + @State var searching: Bool = false + + var body: some View { + VStack(alignment: .center, spacing: 15) { + Image(systemName: searching ? "magnifyingglass.circle.fill" : "questionmark.circle.fill") + .resizable() + .renderingMode(.template) + .frame(width: 24, height: 24) + VStack(alignment: .center) { + Text( + searching + ? "domain_list.no_domains_for_search_query".localizedForSwiftUI + : "domain_list.no_domains".localizedForSwiftUI + ) + } + } + .frame(minWidth: 0, maxWidth: .infinity) + .padding(25) + } +} + +struct NoDomainResults_Previews: PreviewProvider { + static var previews: some View { + NoDomainResults() + } +} diff --git a/phpmon/Domain/SwiftUI/Warning/NoWarningsView.swift b/phpmon/Domain/SwiftUI/Warning/NoWarningsView.swift index 3c29dff..4c22bf0 100644 --- a/phpmon/Domain/SwiftUI/Warning/NoWarningsView.swift +++ b/phpmon/Domain/SwiftUI/Warning/NoWarningsView.swift @@ -19,7 +19,6 @@ struct NoWarningsView: View { VStack(alignment: .center) { Text("warnings.none".localizedForSwiftUI) } - } .frame(minWidth: 0, maxWidth: .infinity) .padding(25) diff --git a/phpmon/Localizable.strings b/phpmon/Localizable.strings index 97957e0..bba94b1 100644 --- a/phpmon/Localizable.strings +++ b/phpmon/Localizable.strings @@ -100,6 +100,9 @@ "domain_list.title" = "Domains"; "domain_list.subtitle" = ""; +"domain_list.no_domains" = "You have not set up any domains or proxies yet."; +"domain_list.no_domains_for_search_query" = "There are no results for your search query."; + "domain_list.tooltips.isolated" = "This domain is isolated and using PHP %@ instead of the globally linked PHP."; "domain_list.tooltips.checkmark" = "This domain is being served with a version of PHP that is compatible with this requirement (PHP %@). Click on the PHP version next to this checkmark to find out more information about how this requirement was determined.";