1
0
mirror of https://github.com/nicoverbruggen/phpmon.git synced 2025-08-07 12:00:09 +02:00

Compare commits

...

22 Commits
v7.2 ... main

Author SHA1 Message Date
80bcbd085e 🚀 Version 25.07 2025-07-28 11:23:01 +02:00
ca65fca77d 🐛 Fix issue with securing domains
If you serve a single folder locally multiple times, e.g. as
`cdn.mydomain.test` and `mydomain.test`, securing would fail
for domain that came alphabetically last.

This has been resolved if you are running Valet 3 or newer by
leveraging the `valet secure $domain` syntax.
2025-07-28 11:22:23 +02:00
96975f8e57 ♻️ Clean up startup timers 2025-07-24 12:32:22 +02:00
729c1e8f2f Add driver to main menu 2025-07-23 17:24:54 +02:00
e94377ebb1 🐛 Prevent timeout message from showing incorrectly 2025-07-23 16:49:54 +02:00
769779970b 🔧 Bump build for EAP 2025-06-27 21:05:19 +02:00
2a27989a96 Detect Tempest framework 2025-06-27 20:59:26 +02:00
79430f7581 🚀 Version 25.06 2025-06-27 19:35:10 +02:00
76f585a50e 🍱 Updated icon asset 2025-06-21 20:38:36 +02:00
1bbc77967b 🍱 New EAP icon for new build 2025-06-20 16:00:58 +02:00
1e4e2afe68 🔧 Bump build 2025-06-20 15:21:14 +02:00
3caf90b0cd 🔧 Update schemas 2025-06-20 15:19:57 +02:00
445acffa4c 🍱 Further design tweaks 2025-06-20 12:56:58 +02:00
e90c068e95 🍱 Tweak design of icon, unify 2025-06-20 12:18:57 +02:00
c9428c300c 🍱 Apply fill to icon 2025-06-20 11:41:02 +02:00
807d9c55a4 🔧 Bump build for EAP 2025-06-19 13:29:52 +02:00
ca167537cf 🍱 Add icons to context menu 2025-06-19 13:28:58 +02:00
8ae2031ba5 🍱 Add icons to main menu 2025-06-19 12:50:04 +02:00
ec0ad13ad0 🔧 Bump build for EAP 2025-06-17 12:12:37 +02:00
9988b775c9 🐛 Add spinner back to domain list 2025-06-17 12:01:25 +02:00
8e24851014 🍱 Add icon w/ Icon Composer 2025-06-10 19:45:43 +02:00
c1d90cb909 🔧 Plan for version 25 later this year
PHP Monitor 25 will use a new numbering scheme, following the format:

25.06 = 25 . 06 . 0
        M    m    p

(Minor, minor and patch.)

So what was supposed to be PHP Monitor 7.3 will now be version 25, with
the minor version number decided by the release month.

The cut-off date for PHP Monitor 7.2 is currently 2025-11-30, so I have
time but I'd prefer to have two releases out this year:

- One release migrating to the new numbering scheme
- One release with full support for macOS 26

Since I plan on only doing maintenance releases with no patches except
when bugs pop up, the major/minor version notation combination should
suffice.

With this release, the minimum supported version of macOS will become
macOS Ventura 13.5.

That means that support is dropped for Monterey and Ventura's older
builds. Since Homebrew is also changing with built-in service management
I think it's time to drop support for these older versions of macOS,
which I no longer intend to test for.

Older versions of PHP Monitor will, of course, remain functional, but
since Homebrew is an ever-changing thing, I cannot guarantee nothing
will break in those older versions with the newer API.
2025-06-10 18:33:50 +02:00
78 changed files with 485 additions and 182 deletions

View File

@ -21,6 +21,14 @@
033D45A02B0D513900070080 /* RemovePhpExtensionCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 033D459D2B0D513900070080 /* RemovePhpExtensionCommand.swift */; };
033D45A12B0D513900070080 /* RemovePhpExtensionCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 033D459D2B0D513900070080 /* RemovePhpExtensionCommand.swift */; };
033D45A32B0D531D00070080 /* PhpExtensionManagerView+Actions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 033D45A22B0D531D00070080 /* PhpExtensionManagerView+Actions.swift */; };
03BFF5272E312C3D007F96FA /* Startup+Timers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03BFF5262E312C39007F96FA /* Startup+Timers.swift */; };
03BFF5282E312C3D007F96FA /* Startup+Timers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03BFF5262E312C39007F96FA /* Startup+Timers.swift */; };
03BFF5292E312C3D007F96FA /* Startup+Timers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03BFF5262E312C39007F96FA /* Startup+Timers.swift */; };
03BFF52A2E312C3D007F96FA /* Startup+Timers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03BFF5262E312C39007F96FA /* Startup+Timers.swift */; };
03BFF52C2E313244007F96FA /* StatusMenu+Driver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03BFF52B2E313240007F96FA /* StatusMenu+Driver.swift */; };
03BFF52D2E313244007F96FA /* StatusMenu+Driver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03BFF52B2E313240007F96FA /* StatusMenu+Driver.swift */; };
03BFF52E2E313244007F96FA /* StatusMenu+Driver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03BFF52B2E313240007F96FA /* StatusMenu+Driver.swift */; };
03BFF52F2E313244007F96FA /* StatusMenu+Driver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03BFF52B2E313240007F96FA /* StatusMenu+Driver.swift */; };
03E36FE728D9219000636F7F /* ActiveShell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E36FE628D9219000636F7F /* ActiveShell.swift */; };
03E36FE828D9219000636F7F /* ActiveShell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E36FE628D9219000636F7F /* ActiveShell.swift */; };
5420395926135DC100FB00FA /* PreferencesVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5420395826135DC100FB00FA /* PreferencesVC.swift */; };
@ -920,6 +928,8 @@
033D45972B0D4EC600070080 /* InstallPhpExtensionCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstallPhpExtensionCommand.swift; sourceTree = "<group>"; };
033D459D2B0D513900070080 /* RemovePhpExtensionCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemovePhpExtensionCommand.swift; sourceTree = "<group>"; };
033D45A22B0D531D00070080 /* PhpExtensionManagerView+Actions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PhpExtensionManagerView+Actions.swift"; sourceTree = "<group>"; };
03BFF5262E312C39007F96FA /* Startup+Timers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Startup+Timers.swift"; sourceTree = "<group>"; };
03BFF52B2E313240007F96FA /* StatusMenu+Driver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "StatusMenu+Driver.swift"; sourceTree = "<group>"; };
03E36FE628D9219000636F7F /* ActiveShell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActiveShell.swift; sourceTree = "<group>"; };
5420395826135DC100FB00FA /* PreferencesVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesVC.swift; sourceTree = "<group>"; };
5420395E2613607600FB00FA /* Preferences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Preferences.swift; sourceTree = "<group>"; };
@ -1850,6 +1860,7 @@
C4F361602836BFD9003598CC /* MainMenu+Actions.swift */,
C47331A1247093B7009A0597 /* StatusMenu.swift */,
C4C3643828AE4FCE00C0770E /* StatusMenu+Items.swift */,
03BFF52B2E313240007F96FA /* StatusMenu+Driver.swift */,
C4821C592C2DEDE200357A68 /* AppMenu.swift */,
);
path = Menu;
@ -1938,6 +1949,7 @@
C4B97B7A275CF20A003F3378 /* App+GlobalHotkey.swift */,
C4EED88827A48778006D7272 /* InterAppHandler.swift */,
C4D8016522B1584700C6DA1B /* Startup.swift */,
03BFF5262E312C39007F96FA /* Startup+Timers.swift */,
C495F5AE28A42E080087F70A /* EnvironmentCheck.swift */,
C40FE736282ABA4F00A302C2 /* AppVersion.swift */,
C409349C298EE8E900D25014 /* AppUpdater.swift */,
@ -2350,7 +2362,7 @@
attributes = {
BuildIndependentTargetsInParallel = YES;
LastSwiftUpdateCheck = 1420;
LastUpgradeCheck = 1620;
LastUpgradeCheck = 1640;
ORGANIZATIONNAME = "Nico Verbruggen";
TargetAttributes = {
C406A5EF298AD2CE00B5B85A = {
@ -2589,6 +2601,7 @@
C4EB53E528551F9B006F9937 /* HeaderView.swift in Sources */,
C4EA3C472BA4F947007B0BA7 /* CustomButtonStyles.swift in Sources */,
C40FE737282ABA4F00A302C2 /* AppVersion.swift in Sources */,
03BFF5282E312C3D007F96FA /* Startup+Timers.swift in Sources */,
C44A874828905BB000498BC4 /* ProgressVC.swift in Sources */,
C4CCBA6C275C567B008C7055 /* PMWindowController.swift in Sources */,
C456A0C62AA614BD0080144F /* PhpPreference.swift in Sources */,
@ -2641,6 +2654,7 @@
C40C7F3027722E8D00DDDCDC /* Logger.swift in Sources */,
C41CA5ED2774F8EE00A2C80E /* DomainListVC+Actions.swift in Sources */,
C412E5FC25700D5300A1FB67 /* HomebrewDecodable.swift in Sources */,
03BFF52E2E313244007F96FA /* StatusMenu+Driver.swift in Sources */,
03E36FE728D9219000636F7F /* ActiveShell.swift in Sources */,
C4D9ADBF277610E1007277F4 /* PhpSwitcher.swift in Sources */,
C45E76142854A65300B4FE0C /* ServicesManager.swift in Sources */,
@ -2862,6 +2876,7 @@
C471E7FE28F9BACE0021E251 /* HomebrewDecodable.swift in Sources */,
C4415E8F2B0287E90035F520 /* BrewFormulaeObservable.swift in Sources */,
C471E7D828F9BA8F0021E251 /* FileSystemProtocol.swift in Sources */,
03BFF52F2E313244007F96FA /* StatusMenu+Driver.swift in Sources */,
C471E7F328F9BAC70021E251 /* PhpHelper.swift in Sources */,
C46DC7A62C7B5BC900F19D17 /* Favorites.swift in Sources */,
C471E7E728F9BAC20021E251 /* Constants.swift in Sources */,
@ -2892,6 +2907,7 @@
C490E3B929BCA368006D2DE6 /* App+BrewWatch.swift in Sources */,
C471E7FF28F9BAD10021E251 /* Xdebug.swift in Sources */,
C409349F298EE8E900D25014 /* AppUpdater.swift in Sources */,
03BFF5292E312C3D007F96FA /* Startup+Timers.swift in Sources */,
C471E7F228F9BAC70021E251 /* PhpEnvironments.swift in Sources */,
C471E7E628F9BAC20021E251 /* Process.swift in Sources */,
C471E81928F9BAE80021E251 /* NSMenuItemExtension.swift in Sources */,
@ -3078,6 +3094,7 @@
C4611E5A2AEAD2E20010BE24 /* ConfigManagerWindowController.swift in Sources */,
C471E80E28F9BAE80021E251 /* DateExtension.swift in Sources */,
C490E3BA29BCA368006D2DE6 /* App+BrewWatch.swift in Sources */,
03BFF5272E312C3D007F96FA /* Startup+Timers.swift in Sources */,
C471E7D028F9BA630021E251 /* FileSystemProtocol.swift in Sources */,
C471E81228F9BAE80021E251 /* TimeIntervalExtension.swift in Sources */,
C471E7DF28F9BAAB0021E251 /* RealCommand.swift in Sources */,
@ -3089,6 +3106,7 @@
C471E80228F9BAD40021E251 /* PhpInstallation.swift in Sources */,
C471E81028F9BAE80021E251 /* StringExtension.swift in Sources */,
C48DDD1029C75C9E00D032D9 /* BlockingOverlayView.swift in Sources */,
03BFF52C2E313244007F96FA /* StatusMenu+Driver.swift in Sources */,
C471E7F828F9BACB0021E251 /* InternalSwitcher.swift in Sources */,
C471E82328F9BB2E0021E251 /* ComposerJson.swift in Sources */,
C471E82128F9BB2E0021E251 /* ProjectTypeDetection.swift in Sources */,
@ -3237,6 +3255,7 @@
C43603A1275E67610028EFC6 /* AppDelegate+Notifications.swift in Sources */,
C4C3643A28AE4FCE00C0770E /* StatusMenu+Items.swift in Sources */,
C42759682627662800093CAE /* NSMenuExtension.swift in Sources */,
03BFF52D2E313244007F96FA /* StatusMenu+Driver.swift in Sources */,
C4AFC4B429C4F43300BF4E0D /* HomebrewUpgradableTest.swift in Sources */,
C4E2E84828FC1D93003B070C /* TestableConfigurationTest.swift in Sources */,
C4D936CB27E3EE4A00BD69FE /* DomainListCellProtocol.swift in Sources */,
@ -3248,6 +3267,7 @@
C485706D28BF450900539B36 /* NSMenuItemExtension.swift in Sources */,
C481F79726164A78004FBCFF /* PreferencesVC.swift in Sources */,
C495F5B028A42E080087F70A /* EnvironmentCheck.swift in Sources */,
03BFF52A2E312C3D007F96FA /* Startup+Timers.swift in Sources */,
C41E871B2763D42300161EE0 /* DomainListVC+ContextMenu.swift in Sources */,
C40C7F3127722E8D00DDDCDC /* Logger.swift in Sources */,
C4068CAB27B0890D00544CD5 /* MenuBarIcons.swift in Sources */,
@ -3436,7 +3456,6 @@
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 30;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 8M54J5J787;
ENABLE_HARDENED_RUNTIME = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_CFBundleDisplayName = "PHP Monitor Self-Updater";
@ -3471,7 +3490,6 @@
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 30;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 8M54J5J787;
ENABLE_HARDENED_RUNTIME = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_CFBundleDisplayName = "PHP Monitor Self-Updater";
@ -3506,7 +3524,6 @@
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 30;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 8M54J5J787;
ENABLE_HARDENED_RUNTIME = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_CFBundleDisplayName = "PHP Monitor Self-Updater";
@ -3541,7 +3558,6 @@
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 30;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 8M54J5J787;
ENABLE_HARDENED_RUNTIME = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_CFBundleDisplayName = "PHP Monitor Self-Updater";
@ -3601,6 +3617,7 @@
COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = 8M54J5J787;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
@ -3666,6 +3683,7 @@
COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = 8M54J5J787;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
@ -3694,10 +3712,9 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1535;
CURRENT_PROJECT_VERSION = 1565;
DEAD_CODE_STRIPPING = YES;
DEBUG = YES;
DEVELOPMENT_TEAM = 8M54J5J787;
ENABLE_HARDENED_RUNTIME = YES;
INFOPLIST_FILE = phpmon/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "PHP Monitor";
@ -3706,8 +3723,8 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 12.4;
MARKETING_VERSION = 7.2;
MACOSX_DEPLOYMENT_TARGET = 13.5;
MARKETING_VERSION = 25.07;
PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon;
PRODUCT_MODULE_NAME = PHP_Monitor;
PRODUCT_NAME = "$(TARGET_NAME)";
@ -3725,10 +3742,9 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1535;
CURRENT_PROJECT_VERSION = 1565;
DEAD_CODE_STRIPPING = YES;
DEBUG = NO;
DEVELOPMENT_TEAM = 8M54J5J787;
ENABLE_HARDENED_RUNTIME = YES;
INFOPLIST_FILE = phpmon/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "PHP Monitor";
@ -3737,8 +3753,8 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 12.4;
MARKETING_VERSION = 7.2;
MACOSX_DEPLOYMENT_TARGET = 13.5;
MARKETING_VERSION = 25.07;
PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon;
PRODUCT_MODULE_NAME = PHP_Monitor;
PRODUCT_NAME = "$(TARGET_NAME)";
@ -3754,7 +3770,6 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 8M54J5J787;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "";
MACOSX_DEPLOYMENT_TARGET = 12.4;
@ -3773,7 +3788,6 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 8M54J5J787;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "";
MACOSX_DEPLOYMENT_TARGET = 12.4;
@ -3792,7 +3806,6 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 8M54J5J787;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "";
MACOSX_DEPLOYMENT_TARGET = 12.4;
@ -3811,7 +3824,6 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 8M54J5J787;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "";
MACOSX_DEPLOYMENT_TARGET = 12.4;
@ -3830,7 +3842,6 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 8M54J5J787;
GENERATE_INFOPLIST_FILE = YES;
MACOSX_DEPLOYMENT_TARGET = 12.4;
MARKETING_VERSION = 1.0;
@ -3849,7 +3860,6 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 8M54J5J787;
GENERATE_INFOPLIST_FILE = YES;
MACOSX_DEPLOYMENT_TARGET = 12.4;
MARKETING_VERSION = 1.0;
@ -3868,7 +3878,6 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 8M54J5J787;
GENERATE_INFOPLIST_FILE = YES;
MACOSX_DEPLOYMENT_TARGET = 12.4;
MARKETING_VERSION = 1.0;
@ -3887,7 +3896,6 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 8M54J5J787;
GENERATE_INFOPLIST_FILE = YES;
MACOSX_DEPLOYMENT_TARGET = 12.4;
MARKETING_VERSION = 1.0;
@ -3938,6 +3946,7 @@
COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = 8M54J5J787;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
@ -3966,10 +3975,9 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1535;
CURRENT_PROJECT_VERSION = 1565;
DEAD_CODE_STRIPPING = YES;
DEBUG = NO;
DEVELOPMENT_TEAM = 8M54J5J787;
ENABLE_HARDENED_RUNTIME = YES;
INFOPLIST_FILE = phpmon/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "PHP Monitor DEV";
@ -3978,8 +3986,8 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 12.4;
MARKETING_VERSION = 7.2;
MACOSX_DEPLOYMENT_TARGET = 13.5;
MARKETING_VERSION = 25.07;
PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon.dev;
PRODUCT_MODULE_NAME = PHP_Monitor;
PRODUCT_NAME = "$(TARGET_NAME) DEV";
@ -3994,7 +4002,6 @@
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 8M54J5J787;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "";
LD_RUNPATH_SEARCH_PATHS = (
@ -4048,6 +4055,7 @@
COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = 8M54J5J787;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
@ -4083,10 +4091,9 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1535;
CURRENT_PROJECT_VERSION = 1565;
DEAD_CODE_STRIPPING = YES;
DEBUG = YES;
DEVELOPMENT_TEAM = 8M54J5J787;
ENABLE_HARDENED_RUNTIME = YES;
INFOPLIST_FILE = phpmon/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "PHP Monitor DEV";
@ -4095,8 +4102,8 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 12.4;
MARKETING_VERSION = 7.2;
MACOSX_DEPLOYMENT_TARGET = 13.5;
MARKETING_VERSION = 25.07;
PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon.dev;
PRODUCT_MODULE_NAME = PHP_Monitor;
PRODUCT_NAME = "$(TARGET_NAME) DEV";
@ -4111,7 +4118,6 @@
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 8M54J5J787;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "";
LD_RUNPATH_SEARCH_PATHS = (
@ -4165,6 +4171,7 @@
COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = 8M54J5J787;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
@ -4200,10 +4207,9 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1535;
CURRENT_PROJECT_VERSION = 1565;
DEAD_CODE_STRIPPING = YES;
DEBUG = YES;
DEVELOPMENT_TEAM = 8M54J5J787;
ENABLE_HARDENED_RUNTIME = YES;
INFOPLIST_FILE = phpmon/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "PHP Monitor EAP";
@ -4212,8 +4218,8 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 12.4;
MARKETING_VERSION = 7.2;
MACOSX_DEPLOYMENT_TARGET = 13.5;
MARKETING_VERSION = 25.07;
PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon.eap;
PRODUCT_MODULE_NAME = PHP_Monitor;
PRODUCT_NAME = "$(TARGET_NAME) EAP";
@ -4236,7 +4242,6 @@
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 30;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 8M54J5J787;
ENABLE_HARDENED_RUNTIME = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_CFBundleDisplayName = "PHP Monitor Self-Updater";
@ -4263,7 +4268,6 @@
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 8M54J5J787;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "";
LD_RUNPATH_SEARCH_PATHS = (
@ -4285,7 +4289,6 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 8M54J5J787;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "";
MACOSX_DEPLOYMENT_TARGET = 12.4;
@ -4304,7 +4307,6 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 8M54J5J787;
GENERATE_INFOPLIST_FILE = YES;
MACOSX_DEPLOYMENT_TARGET = 12.4;
MARKETING_VERSION = 1.0;
@ -4355,6 +4357,7 @@
COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = 8M54J5J787;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
@ -4383,10 +4386,9 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1535;
CURRENT_PROJECT_VERSION = 1565;
DEAD_CODE_STRIPPING = YES;
DEBUG = NO;
DEVELOPMENT_TEAM = 8M54J5J787;
ENABLE_HARDENED_RUNTIME = YES;
INFOPLIST_FILE = phpmon/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "PHP Monitor EAP";
@ -4395,8 +4397,8 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 12.4;
MARKETING_VERSION = 7.2;
MACOSX_DEPLOYMENT_TARGET = 13.5;
MARKETING_VERSION = 25.07;
PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon.eap;
PRODUCT_MODULE_NAME = PHP_Monitor;
PRODUCT_NAME = "$(TARGET_NAME) EAP";
@ -4419,7 +4421,6 @@
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 30;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 8M54J5J787;
ENABLE_HARDENED_RUNTIME = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_CFBundleDisplayName = "PHP Monitor Self-Updater";
@ -4446,7 +4447,6 @@
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 8M54J5J787;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "";
LD_RUNPATH_SEARCH_PATHS = (
@ -4468,7 +4468,6 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 8M54J5J787;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "";
MACOSX_DEPLOYMENT_TARGET = 12.4;
@ -4487,7 +4486,6 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 8M54J5J787;
GENERATE_INFOPLIST_FILE = YES;
MACOSX_DEPLOYMENT_TARGET = 12.4;
MARKETING_VERSION = 1.0;
@ -4505,7 +4503,6 @@
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 8M54J5J787;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "";
LD_RUNPATH_SEARCH_PATHS = (
@ -4526,7 +4523,6 @@
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 8M54J5J787;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "";
LD_RUNPATH_SEARCH_PATHS = (

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1620"
LastUpgradeVersion = "1640"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1620"
LastUpgradeVersion = "1640"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1620"
LastUpgradeVersion = "1640"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1620"
LastUpgradeVersion = "1640"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1620"
LastUpgradeVersion = "1640"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@ -1,7 +1,7 @@
> **Note**
> If this software has been useful to you, I ask that you **please star the repository**, that way I know that the software is being used. Also, please consider [sponsoring](https://nicoverbruggen.be/sponsor) to support the project, as this is something I make in my free time. **Thank you!** ⭐️
<p align="center"><img src="./docs/logo.png" alt="PHP Monitor Logo" width="500px" /></p>
<p align="center"><img src="./docs/logo.svg" alt="PHP Monitor Logo" width="500px" /></p>
**PHP Monitor** (or *phpmon*) is a lightweight macOS utility app that runs on your Mac and displays the active PHP version in your status bar. It's tightly integrated with [Laravel Valet](https://github.com/laravel/valet), so <u>you need to have it set up if you want to use all of the functionality of the app</u> (consult the FAQ below with info about how to set up your environment).
@ -22,7 +22,7 @@ You can also add new domains as links, isolate sites, manage various services, a
PHP Monitor is a universal application that runs natively on Apple Silicon **and** Intel-based Macs.
* Your user account can administer your computer (required for some functionality, e.g. certificate generation)
* macOS 12.4 or later
* macOS 13.5 or later
* Homebrew is installed in the default location (`/usr/local/homebrew` or `/opt/homebrew`)
* Homebrew `php` formula is installed
* Optional but recommended: Laravel Valet

View File

@ -2,11 +2,13 @@
## Supported versions
Generally speaking, only the latest version of **PHP Monitor** is supported, except during transition periods (for example, when particular system requirements go up):
Generally speaking, only the latest version of **PHP Monitor** is supported, except during transition periods (for example, when particular system requirements go up).
| Version | Apple Silicon | Supported | Supported macOS | Minimum Deployment | Detected PHP Versions | Recommended Valet Version |
| ------- | ------------- | ------------------ | ----- | ----- | ----- | ----
| 7.1 | ✅ Universal binary | ✅ Yes | Monterey (12.4+)<br/>Ventura (13.0+)<br/>Sonoma (14.0+)<br/>Sequoia (15.0+) | macOS 12.4+ | PHP 5.6—PHP 8.2 (w/ Valet 2.x)<br/>PHP 7.0—PHP 8.4 (w/ Valet 3.x)<br/>PHP 7.1-PHP 8.5 (w/ Valet 4.x)| 3.0 or higher recommended<br/> 2.16.2 minimum |
| 25 | ✅ Universal binary | ✅ Yes | Ventura (13.5+)<br/>Sonoma (14.0+)<br/>Sequoia (15.0+)<br/>Tahoe (26.0+)* | macOS 13.5+ | PHP 5.6—PHP 8.2 (w/ Valet 2.x)<br/>PHP 7.0—PHP 8.4 (w/ Valet 3.x)<br/>PHP 7.1-PHP 8.5 (w/ Valet 4.x)| 3.0 or higher recommended<br/> 2.16.2 minimum |
(*) Denotes preliminary supported based on the app being built with the latest version of the SDK prior to the release of the latest release of macOS. Please check out the pinned issue for more information.
## Legacy versions
@ -14,6 +16,7 @@ These versions of PHP Monitor are no longer supported, but if youre using an
| Version | Apple Silicon | Supported | Supported macOS | Minimum Deployment | Detected PHP Versions | Minimum Required Valet Version |
| ------- | ------------- | ------------------ | ----- | ----- | ----- | ----
| 7.1 | ✅ Universal binary | ❌ | Monterey (12.4+)<br/>Ventura (13.0+)<br/>Sonoma (14.0+)<br/>Sequoia (15.0+) | macOS 12.4+ | PHP 5.6—PHP 8.2 (w/ Valet 2.x)<br/>PHP 7.0—PHP 8.4 (w/ Valet 3.x)<br/>PHP 7.1-PHP 8.5 (w/ Valet 4.x)| 3.0 or higher recommended<br/> 2.16.2 minimum |
| 7.0 | ✅ Universal binary | ❌ | Monterey (12.4+)<br/>Ventura (13.0+)<br/>Sonoma (14.0) | macOS 12.4+ | PHP 5.6—PHP 8.2 (w/ Valet 2.x)<br/>PHP 7.0—PHP 8.4 (w/ Valet 3.x)<br/>PHP 7.1-PHP 8.4 (w/ Valet 4.x)| 3.0 or higher recommended<br/> 2.16.2 minimum |
| 6.2 | ✅ Universal binary | ❌ | Monterey (12.4+)<br/>Ventura (13.0+)<br/>Sonoma (14.0) | macOS 12.4+ | PHP 5.6—PHP 8.2 (w/ Valet 2.x)<br/>PHP 7.0—PHP 8.4 (w/ Valet 3.x)<br/>PHP 7.1-PHP 8.4 (w/ Valet 4.x)| 3.0 or higher recommended<br/> 2.16.2 minimum |
| 6.1 | ✅ Universal binary | ❌ | Monterey (12.4+)<br/>Ventura (13.0+)<br/>Sonoma (14.0) | macOS 12.4+ | PHP 5.6—PHP 8.2 (w/ Valet 2.x)<br/>PHP 7.0—PHP 8.4 (w/ Valet 3.x)<br/>PHP 7.1-PHP 8.4 (w/ Valet 4.x)| 3.0 or higher recommended<br/> 2.16.2 minimum |

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

1
assets/icon-2025.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 24 KiB

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 500 500" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(1.25033,-0.175723,0.175723,1.25033,14.4412,107.226)">
<path d="M133.3,83.75L120.4,83.75L120.4,54.437C120.4,52.134 118.465,50.25 116.1,50.25L107.5,50.25C105.135,50.25 103.2,52.134 103.2,54.438L103.2,96.312C103.2,98.616 105.135,100.5 107.5,100.5L133.3,100.5C135.665,100.5 137.6,98.616 137.6,96.312L137.6,87.938C137.6,85.634 135.665,83.75 133.3,83.75ZM335.4,184.25L326.8,184.25L326.8,127.666C326.8,121.019 324.059,114.633 319.221,109.922L265.525,57.63C260.688,52.92 254.13,50.25 247.304,50.25L223.6,50.25L223.6,25.125C223.6,11.254 212.044,0 197.8,0L25.8,0C11.556,0 0,11.254 0,25.125L0,192.625C0,206.496 11.556,217.75 25.8,217.75L34.4,217.75C34.4,245.492 57.513,268 86,268C114.487,268 137.6,245.492 137.6,217.75L206.4,217.75C206.4,245.492 229.512,268 258,268C286.488,268 309.6,245.492 309.6,217.75L335.4,217.75C340.13,217.75 344,213.981 344,209.375L344,192.625C344,188.019 340.13,184.25 335.4,184.25ZM86,242.875C71.756,242.875 60.2,231.621 60.2,217.75C60.2,203.879 71.756,192.625 86,192.625C100.244,192.625 111.8,203.879 111.8,217.75C111.8,231.621 100.244,242.875 86,242.875ZM111.8,150.75C78.529,150.75 51.6,124.526 51.6,92.125C51.6,59.725 78.529,33.5 111.8,33.5C145.071,33.5 172,59.724 172,92.125C172,124.525 145.071,150.75 111.8,150.75ZM258,242.875C243.756,242.875 232.2,231.621 232.2,217.75C232.2,203.879 243.756,192.625 258,192.625C272.244,192.625 283.8,203.879 283.8,217.75C283.8,231.621 272.244,242.875 258,242.875ZM301,134L223.6,134L223.6,75.375L247.304,75.375L301,127.666L301,134Z" style="fill:url(#_Linear1);fill-rule:nonzero;"/>
</g>
<defs>
<linearGradient id="_Linear1" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1.96882e-14,321.533,-321.533,1.96882e-14,172.079,-41.4918)"><stop offset="0" style="stop-color:rgb(81,194,251);stop-opacity:1"/><stop offset="0" style="stop-color:rgb(81,194,251);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(28,145,254);stop-opacity:1"/></linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1,48 @@
{
"fill" : {
"linear-gradient" : [
"srgb:0.27800,0.58000,0.98800,1.00000",
"srgb:0.27800,0.58000,0.98800,1.00000"
]
},
"groups" : [
{
"blend-mode" : "screen",
"blur-material" : null,
"layers" : [
{
"blend-mode" : "normal",
"fill" : {
"solid" : "srgb:1.00000,0.99038,0.96423,1.00000"
},
"glass" : true,
"image-name" : "phpmon.svg",
"name" : "phpmon",
"position" : {
"scale" : 1.85,
"translation-in-points" : [
10.0234375,
8.21875
]
}
}
],
"lighting" : "individual",
"shadow" : {
"kind" : "neutral",
"opacity" : 0.5
},
"specular" : true,
"translucency" : {
"enabled" : true,
"value" : 0.5
}
}
],
"supported-platforms" : {
"circles" : [
"watchOS"
],
"squares" : "shared"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

57
docs/logo.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 811 B

After

Width:  |  Height:  |  Size: 811 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 KiB

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 KiB

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 301 KiB

After

Width:  |  Height:  |  Size: 450 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 558 B

After

Width:  |  Height:  |  Size: 783 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 148 KiB

After

Width:  |  Height:  |  Size: 457 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 632 B

After

Width:  |  Height:  |  Size: 790 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 182 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 182 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 163 KiB

After

Width:  |  Height:  |  Size: 648 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.7 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 644 B

After

Width:  |  Height:  |  Size: 819 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 162 KiB

After

Width:  |  Height:  |  Size: 499 KiB

View File

@ -0,0 +1,24 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "ValetDriverIcon@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 831 B

View File

@ -18,6 +18,16 @@ struct Constants {
*/
static let MinimumRecommendedValetVersion = "2.16.2"
/**
The amount of seconds that is considered the threshold for
PHP Monitor to mark any given launch as a "slow" launch.
If the startup procedure was slow (or hangs), this message should
be displayed. This is based on an appropriate launch time on a
basic M1 Apple chip, with some margin for slower Intel chips.
*/
static let SlowBootThresholdInterval: TimeInterval = 30.0
/**
PHP Monitor supplies a hardcoded list of PHP packages in its own
PHP Version Manager.

View File

@ -9,6 +9,24 @@
import Cocoa
extension NSMenuItem {
convenience init(
title: String,
action: Selector? = nil,
keyEquivalent: String = "",
keyModifier: NSEvent.ModifierFlags = [],
systemImage: String? = nil,
customImage: String? = nil,
) {
self.init(title: title, action: action, keyEquivalent: keyEquivalent)
self.keyEquivalentModifierMask = keyModifier
if systemImage != nil {
self.image = NSImage(systemSymbolName: systemImage!, accessibilityDescription: "")
}
if customImage != nil {
self.image = NSImage(named: customImage!)
}
}
convenience init(
title: String,
action: Selector? = nil,
@ -26,12 +44,20 @@ extension NSMenuItem {
keyEquivalent: String = "",
keyModifier: NSEvent.ModifierFlags = [],
toolTip: String? = nil,
systemImage: String? = nil,
customImage: String? = nil,
submenu: [NSMenuItem],
target: NSObject? = nil
) {
self.init(title: title, action: nil, keyEquivalent: keyEquivalent)
self.keyEquivalentModifierMask = keyModifier
self.toolTip = toolTip
if systemImage != nil {
self.image = NSImage(systemSymbolName: systemImage!, accessibilityDescription: "")
}
if customImage != nil {
self.image = NSImage(named: customImage!)
}
self.submenu = NSMenu(items: submenu, target: target)
}
}

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="23727" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22690"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="23727"/>
<capability name="Image references" minToolsVersion="12.0"/>
<capability name="Named colors" minToolsVersion="9.0"/>
<capability name="Search Toolbar Item" minToolsVersion="12.0" minSystemVersion="11.0"/>
@ -826,13 +826,6 @@ Gw
<rect key="frame" x="0.0" y="0.0" width="626" height="309"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<progressIndicator maxValue="100" displayedWhenStopped="NO" indeterminate="YES" style="spinning" translatesAutoresizingMaskIntoConstraints="NO" id="ZiS-Gq-TLQ">
<rect key="frame" x="298" y="150" width="30" height="30"/>
<constraints>
<constraint firstAttribute="width" constant="30" id="XK3-AR-Oc0"/>
<constraint firstAttribute="height" constant="30" id="lfW-dB-Eu3"/>
</constraints>
</progressIndicator>
<scrollView borderType="none" horizontalLineScroll="54" horizontalPageScroll="10" verticalLineScroll="54" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="p0j-eB-I2i">
<rect key="frame" x="0.0" y="0.0" width="626" height="309"/>
<clipView key="contentView" ambiguous="YES" drawsBackground="NO" id="6IL-DW-37w">
@ -1150,21 +1143,51 @@ Gw
<constraint firstAttribute="height" constant="300" id="Xpi-Rl-xmb"/>
</constraints>
</customView>
<visualEffectView hidden="YES" blendingMode="behindWindow" material="popover" state="followsWindowActiveState" translatesAutoresizingMaskIntoConstraints="NO" id="r8h-6t-ZNm">
<rect key="frame" x="263" y="125" width="100" height="80"/>
<subviews>
<progressIndicator wantsLayer="YES" maxValue="100" displayedWhenStopped="NO" indeterminate="YES" style="spinning" translatesAutoresizingMaskIntoConstraints="NO" id="ZiS-Gq-TLQ">
<rect key="frame" x="35" y="35" width="30" height="30"/>
<constraints>
<constraint firstAttribute="width" constant="30" id="XK3-AR-Oc0"/>
<constraint firstAttribute="height" constant="30" id="lfW-dB-Eu3"/>
</constraints>
</progressIndicator>
<textField wantsLayer="YES" focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="xoy-5Y-WDT">
<rect key="frame" x="15" y="14" width="71" height="13"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="PLEASE WAIT" id="tMX-Ky-caT">
<font key="font" metaFont="system" size="10"/>
<color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
<constraints>
<constraint firstItem="xoy-5Y-WDT" firstAttribute="top" secondItem="ZiS-Gq-TLQ" secondAttribute="bottom" constant="8" symbolic="YES" id="4pN-Xn-po4"/>
<constraint firstAttribute="width" constant="100" id="Fo3-MY-e5e"/>
<constraint firstItem="xoy-5Y-WDT" firstAttribute="centerX" secondItem="r8h-6t-ZNm" secondAttribute="centerX" id="JPe-3T-uYg"/>
<constraint firstAttribute="height" constant="80" id="hcO-TE-dKr"/>
<constraint firstItem="ZiS-Gq-TLQ" firstAttribute="centerX" secondItem="r8h-6t-ZNm" secondAttribute="centerX" id="sbD-l6-6kk"/>
<constraint firstItem="ZiS-Gq-TLQ" firstAttribute="centerY" secondItem="r8h-6t-ZNm" secondAttribute="centerY" constant="-10" id="x7S-hb-YV1"/>
</constraints>
</visualEffectView>
</subviews>
<constraints>
<constraint firstItem="p0j-eB-I2i" firstAttribute="leading" secondItem="rIZ-4U-bhj" secondAttribute="leading" id="2Tx-yb-xrv"/>
<constraint firstItem="wcV-ed-8Bv" firstAttribute="centerX" secondItem="rIZ-4U-bhj" secondAttribute="centerX" id="DPz-kQ-aP0"/>
<constraint firstItem="wcV-ed-8Bv" firstAttribute="centerY" secondItem="rIZ-4U-bhj" secondAttribute="centerY" id="HCW-zJ-gSY"/>
<constraint firstItem="r8h-6t-ZNm" firstAttribute="centerX" secondItem="rIZ-4U-bhj" secondAttribute="centerX" id="JF1-EN-aWm"/>
<constraint firstItem="p0j-eB-I2i" firstAttribute="top" secondItem="rIZ-4U-bhj" secondAttribute="top" id="Pst-5A-dI0"/>
<constraint firstAttribute="bottom" secondItem="p0j-eB-I2i" secondAttribute="bottom" id="QEw-5m-u1s"/>
<constraint firstItem="ZiS-Gq-TLQ" firstAttribute="centerY" secondItem="rIZ-4U-bhj" secondAttribute="centerY" constant="-10" id="XqX-Tf-8ck"/>
<constraint firstItem="ZiS-Gq-TLQ" firstAttribute="centerX" secondItem="rIZ-4U-bhj" secondAttribute="centerX" id="eD8-TV-7dF"/>
<constraint firstItem="r8h-6t-ZNm" firstAttribute="centerY" secondItem="rIZ-4U-bhj" secondAttribute="centerY" constant="-10" id="dkm-LB-eCY"/>
<constraint firstAttribute="trailing" secondItem="p0j-eB-I2i" secondAttribute="trailing" id="zWH-TD-RZv"/>
</constraints>
</view>
<connections>
<outlet property="labelProgressIndicator" destination="xoy-5Y-WDT" id="Wfj-oK-Bni"/>
<outlet property="noResultsView" destination="wcV-ed-8Bv" id="K3s-fb-1aN"/>
<outlet property="progressIndicator" destination="ZiS-Gq-TLQ" id="Ylb-Vk-uub"/>
<outlet property="progressIndicatorContainer" destination="r8h-6t-ZNm" id="x0d-1g-Kzw"/>
<outlet property="tableView" destination="cp3-34-pQj" id="sdw-Ac-27X"/>
</connections>
</viewController>
@ -1399,7 +1422,7 @@ Gw
<visualEffectView blendingMode="behindWindow" material="toolTip" state="followsWindowActiveState" translatesAutoresizingMaskIntoConstraints="NO" id="F37-zt-gM3">
<rect key="frame" x="0.0" y="0.0" width="540" height="177"/>
<subviews>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="FhN-AM-SkI">
<button wantsLayer="YES" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="FhN-AM-SkI">
<rect key="frame" x="13" y="13" width="114" height="32"/>
<buttonCell key="cell" type="push" title="[i18n] Cancel" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="LxP-t4-H2W">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
@ -1418,7 +1441,7 @@ Gw
<stackView distribution="fill" orientation="horizontal" alignment="top" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="pYe-Qu-qnK">
<rect key="frame" x="187" y="20" width="333" height="20"/>
<subviews>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="L5n-Gw-J27">
<button wantsLayer="YES" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="L5n-Gw-J27">
<rect key="frame" x="-7" y="-7" width="172" height="32"/>
<buttonCell key="cell" type="push" title="[i18n] Create a Link" bezelStyle="rounded" image="IconLinked" imagePosition="left" alignment="center" borderStyle="border" imageScaling="proportionallyUpOrDown" inset="2" id="8UP-Sw-TP6">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
@ -1429,7 +1452,7 @@ Gw
<action selector="pressedCreateLink:" target="gOD-Gu-zDG" id="77M-Ip-GMi"/>
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="01Z-IV-hv1">
<button wantsLayer="YES" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="01Z-IV-hv1">
<rect key="frame" x="159" y="-7" width="181" height="32"/>
<buttonCell key="cell" type="push" title="[i18n] Create a Proxy" bezelStyle="rounded" image="IconProxy" imagePosition="left" alignment="center" borderStyle="border" imageScaling="proportionallyUpOrDown" inset="2" id="bJ4-q8-1Ej">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>

View File

@ -0,0 +1,74 @@
//
// Startup+Timers.swift
// PHP Monitor
//
// Created by Nico Verbruggen on 23/07/2025.
// Copyright © 2025 Nico Verbruggen. All rights reserved.
//
import Foundation
import AppKit
import NVAlert
extension Startup {
@MainActor static var startupTimer: Timer?
@MainActor static var launchTime: Date?
/** Returns a human-readable version to indicate how many seconds elapsed since boot. */
@MainActor static var humanReadableSinceBootTime: String {
return String(format: "%.2f", Date().timeIntervalSince(Self.launchTime!))
}
/** Starts the timeout timer that keeps track of how long the app takes to boot. */
@MainActor func startStartupTimer() {
Self.launchTime = Date()
Self.startupTimer = Timer.scheduledTimer(
timeInterval: Constants.SlowBootThresholdInterval, target: self,
selector: #selector(startupTimeout), userInfo: nil, repeats: false
)
}
/**
Invalidates and stops the startup timer.
This is only called if the slow boot threshold is not exceeded.
*/
@MainActor static func invalidateTimeoutTimer() {
if Self.startupTimer == nil {
return
}
Log.info("PHP Monitor was quick; elapsed time: \(Self.humanReadableSinceBootTime) sec.")
Self.startupTimer?.invalidate()
Self.startupTimer = nil
}
/**
Displays an alert for when the application startup process takes too long.
*/
@MainActor @objc func startupTimeout() {
Log.info("PHP Monitor was slow; elapsed time: \(Self.humanReadableSinceBootTime) sec.")
// Invalidate the timer
Self.startupTimer?.invalidate()
Self.startupTimer = nil
// Present an alert that lets the user know about the slow start
NVAlert()
.withInformation(
title: "startup.timeout.title".localized,
subtitle: "startup.timeout.subtitle".localized,
description: "startup.timeout.description".localized
)
.withPrimary(text: "alert.cannot_start.close".localized, action: { vc in
vc.close(with: .alertFirstButtonReturn)
exit(1)
})
.withSecondary(text: "startup.timeout.ignore".localized, action: { vc in
vc.close(with: .alertSecondButtonReturn)
})
.withTertiary(text: "", action: { _ in
NSWorkspace.shared.open(URL(string: "https://github.com/nicoverbruggen/phpmon/issues/294")!)
})
.show()
}
}

View File

@ -10,21 +10,6 @@ import AppKit
import NVAlert
class Startup {
@MainActor static var startupTimer: Timer?
@MainActor func startTimeoutTimer() {
Self.startupTimer = Timer.scheduledTimer(
timeInterval: 30.0, target: self, selector: #selector(startupTimeout),
userInfo: nil, repeats: false
)
}
@MainActor static func invalidateTimeoutTimer() {
Self.startupTimer?.invalidate()
Self.startupTimer = nil
}
/**
Checks the user's environment and checks if PHP Monitor can be used properly.
This checks if PHP is installed, Valet is running, the appropriate permissions are set, and more.
@ -38,7 +23,7 @@ class Startup {
// Set up a "background" timer on the main thread
Task { @MainActor in
startTimeoutTimer()
startStartupTimer()
}
for group in self.groups {
@ -69,29 +54,6 @@ class Startup {
return true
}
/**
Displays an alert for when the application startup process takes too long.
*/
@MainActor @objc func startupTimeout() {
NVAlert()
.withInformation(
title: "startup.timeout.title".localized,
subtitle: "startup.timeout.subtitle".localized,
description: "startup.timeout.description".localized
)
.withPrimary(text: "alert.cannot_start.close".localized, action: { vc in
vc.close(with: .alertFirstButtonReturn)
exit(1)
})
.withSecondary(text: "startup.timeout.ignore".localized, action: { vc in
vc.close(with: .alertSecondButtonReturn)
})
.withTertiary(text: "", action: { _ in
NSWorkspace.shared.open(URL(string: "https://github.com/nicoverbruggen/phpmon/issues/294")!)
})
.show()
}
/**
Displays an alert for a particular check. There are two types of alerts:
- ones that require an app restart, which prompt the user to exit the app

View File

@ -15,7 +15,8 @@ struct ProjectTypeDetection {
public static let CommonDependencyList = [
"laravel/framework": "Laravel",
"symfony/symfony": "Symfony",
"laravel/lumen": "Lumen"
"laravel/lumen": "Lumen",
"tempest/framework": "Tempest"
]
/**

View File

@ -51,7 +51,15 @@ class ValetInteractor {
// Keep track of the command we wish to run
let action = site.secured ? "unsecure" : "secure"
let command = "cd '\(site.absolutePath)' && sudo \(Paths.valet) \(action) && exit;"
// Use modernized version of command using domain name
// This will allow us to secure multiple domains that use the same path
var command = "sudo \(Paths.valet) \(action) '\(site.name)' && exit;"
// For Valet 2, use the old syntax; this has a known issue so Valet 3+ is preferred
if !Valet.enabled(feature: .isolatedSites) {
command = "cd '\(site.absolutePath)' && sudo \(Paths.valet) \(action) && exit;"
}
// Run the command
await Shell.quiet(command)

View File

@ -103,12 +103,6 @@ extension MainMenu {
// Find out which services are active
Log.info("The services manager knows about \(ServicesManager.shared.services.count) services.")
// Post-launch stats and update check, but only if not running tests
await performPostLaunchActions()
// Check if the linked version has changed between launches of phpmon
PhpGuard().compareToLastGlobalVersion()
// We are ready!
PhpEnvironments.shared.isBusy = false
@ -120,6 +114,9 @@ extension MainMenu {
// Check if we upgraded from a previous version
AppUpdater.checkIfUpdateWasPerformed()
// Post-launch stats and update check, but only if not running tests
await performPostLaunchActions()
}
/**
@ -127,18 +124,24 @@ extension MainMenu {
(This code is skipped when running SwiftUI previews.)
*/
private func performPostLaunchActions() async {
if !isRunningSwiftUIPreview {
Stats.incrementSuccessfulLaunchCount()
Stats.evaluateSponsorMessageShouldBeDisplayed()
if isRunningSwiftUIPreview {
return
}
if Stats.successfulLaunchCount == 1 {
Log.info("Should present the first launch screen!")
Task { @MainActor in
OnboardingWindowController.show()
}
} else {
await AppUpdater().checkForUpdates(userInitiated: false)
Stats.incrementSuccessfulLaunchCount()
Stats.evaluateSponsorMessageShouldBeDisplayed()
if Stats.successfulLaunchCount == 1 {
Log.info("Should present the first launch screen!")
Task { @MainActor in
OnboardingWindowController.show()
}
} else {
// Check for updates
await AppUpdater().checkForUpdates(userInitiated: false)
// Check if the linked version has changed between launches of phpmon
await PhpGuard().compareToLastGlobalVersion()
}
}

View File

@ -0,0 +1,28 @@
//
// StatusMenu+Driver.swift
// PHP Monitor
//
// Created by Nico Verbruggen on 23/07/2025.
// Copyright © 2025 Nico Verbruggen. All rights reserved.
//
import Cocoa
extension StatusMenu {
@MainActor func addLiteModeMenuItem() {
addItems([
NSMenuItem.separator(),
NSMenuItem(title: "mi_lite_mode".localized, action: #selector(MainMenu.openLiteModeInfo))
])
}
@MainActor func addValetVersionItem() {
if let version = Valet.shared.version {
addItems([
NSMenuItem.separator(),
NSMenuItem(title: "mi_driver".localized("Valet \(version.text)"),
action: nil, customImage: "ValetDriverIcon")
])
}
}
}

View File

@ -78,11 +78,12 @@ extension StatusMenu {
let action = #selector(MainMenu.switchToPhpVersion(sender:))
let brew = (shortVersion == PhpEnvironments.brewPhpAlias) ? "php" : "php@\(shortVersion)"
let isActive = (shortVersion == PhpEnvironments.phpInstall?.version.short)
let menuItem = PhpMenuItem(
title: "\("mi_php_switch".localized) \(versionString) (\(brew))",
action: (shortVersion == PhpEnvironments.phpInstall?.version.short)
? nil
: action, keyEquivalent: "\(shortcutKey)"
action: isActive ? nil : action, keyEquivalent: "\(shortcutKey)",
systemImage: isActive ? "checkmark.square.fill" : "square.dotted"
)
menuItem.version = shortVersion
@ -102,20 +103,19 @@ extension StatusMenu {
}
}
@MainActor func addLiteModeMenuItem() {
addItems([
NSMenuItem.separator(),
NSMenuItem(title: "mi_lite_mode".localized, action: #selector(MainMenu.openLiteModeInfo))
])
}
@MainActor func addPreferencesMenuItems() {
addItems([
NSMenuItem.separator(),
NSMenuItem(title: "mi_preferences".localized,
action: #selector(MainMenu.openPrefs), keyEquivalent: ","),
action: #selector(MainMenu.openPrefs),
keyEquivalent: ",",
systemImage: "gear"
),
NSMenuItem(title: "mi_check_for_updates".localized,
action: #selector(MainMenu.checkForUpdates))
action: #selector(MainMenu.checkForUpdates),
systemImage: "arrow.clockwise.circle"
)
])
}
@ -136,10 +136,12 @@ extension StatusMenu {
HeaderView.asMenuItem(text: "mi_valet".localized),
NSMenuItem(title: "mi_valet_config".localized,
action: #selector(MainMenu.openValetConfigFolder),
keyEquivalent: "v"),
keyEquivalent: "v",
systemImage: "folder.badge.gearshape"),
NSMenuItem(title: "mi_domain_list".localized,
action: #selector(MainMenu.openDomainList),
keyEquivalent: "l"),
keyEquivalent: "l",
systemImage: "globe"),
NSMenuItem.separator()
])
}
@ -151,19 +153,24 @@ extension StatusMenu {
HeaderView.asMenuItem(text: "mi_configuration".localized),
NSMenuItem(title: "mi_php_version_manager".localized,
action: #selector(MainMenu.openPhpVersionManager),
keyEquivalent: "m"),
keyEquivalent: "m",
systemImage: "cpu.fill"),
NSMenuItem(title: "mi_php_ext_manager".localized,
action: #selector(MainMenu.openPhpExtensionManager),
keyEquivalent: "e"),
keyEquivalent: "e",
systemImage: "puzzlepiece.extension"),
NSMenuItem(title: "mi_php_config".localized,
action: #selector(MainMenu.openActiveConfigFolder),
keyEquivalent: "c"),
keyEquivalent: "c",
systemImage: "folder.badge.gearshape"),
NSMenuItem(title: "mi_phpmon_config".localized,
action: #selector(MainMenu.openPhpMonitorConfigurationFile),
keyEquivalent: "y"),
keyEquivalent: "y",
systemImage: "folder.badge.person.crop"),
NSMenuItem(title: "mi_phpinfo".localized,
action: #selector(MainMenu.openPhpInfo),
keyEquivalent: "i")
keyEquivalent: "i",
systemImage: "info.circle.fill")
])
}
@ -175,7 +182,8 @@ extension StatusMenu {
NSMenuItem(
title: "mi_global_composer".localized,
action: #selector(MainMenu.openGlobalComposerFolder),
keyEquivalent: "g"
keyEquivalent: "g",
systemImage: "plus.rectangle.on.folder"
),
NSMenuItem(
title: "mi_update_global_composer".localized,
@ -183,7 +191,8 @@ extension StatusMenu {
? nil
: #selector(MainMenu.updateGlobalComposerDependencies),
keyEquivalent: "g",
keyModifier: [.shift]
keyModifier: [.shift],
systemImage: "arrow.down.to.line.square"
)
])
}
@ -243,7 +252,7 @@ extension StatusMenu {
}
@MainActor private func addEmptyPresetHelp() {
addItem(NSMenuItem(title: "mi_presets_title".localized, submenu: [
addItem(NSMenuItem(title: "mi_presets_title".localized, systemImage: "puzzlepiece.fill", submenu: [
NSMenuItem(title: "mi_no_presets".localized),
NSMenuItem.separator(),
NSMenuItem(title: "mi_set_up_presets".localized,
@ -252,7 +261,7 @@ extension StatusMenu {
}
@MainActor private func addLoadedPresets() {
addItem(NSMenuItem(title: "mi_presets_title".localized, submenu: [
addItem(NSMenuItem(title: "mi_presets_title".localized, systemImage: "puzzlepiece.fill", submenu: [
NSMenuItem.separator(),
HeaderView.asMenuItem(text: "mi_apply_presets_title".localized)
] + PresetMenuItem.getAll() + [
@ -303,7 +312,7 @@ extension StatusMenu {
// MARK: - First Aid & Services
@MainActor func addFirstAidAndServicesMenuItems() {
let services = NSMenuItem(title: "mi_other".localized)
let services = NSMenuItem(title: "mi_other".localized, systemImage: "cross.case")
var items: [NSMenuItem] = [
// FIRST AID
@ -315,13 +324,14 @@ extension StatusMenu {
if Valet.installed {
items.append(contentsOf: [
NSMenuItem.separator(),
HeaderView.asMenuItem(text: "Laravel Valet"),
NSMenuItem(title: "mi_fix_my_valet".localized(PhpEnvironments.brewPhpAlias),
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(),
NSMenuItem.separator(),
// SERVICES
HeaderView.asMenuItem(text: "mi_services".localized),

View File

@ -66,7 +66,11 @@ class StatusMenu: NSMenu {
addPreferencesMenuItems()
if !Valet.installed {
if Valet.installed {
// Add the menu item displaying the driver information
addValetVersionItem()
} else {
// No driver, using Standalone Mode (internally: lite mode)
addLiteModeMenuItem()
}

View File

@ -23,7 +23,7 @@ class PhpGuard {
Log.info("The currently linked version of PHP is: \(linked.version.short).")
}
public func compareToLastGlobalVersion() {
public func compareToLastGlobalVersion() async {
guard let currentVersion else {
return
}
@ -34,6 +34,7 @@ class PhpGuard {
Stats.persistCurrentGlobalPhpVersion(version: currentVersion)
return Log.warn("PHP Guard is saving the currently linked PHP version (first time only).")
}
Log.info("Previously, the globally linked PHP version was: \(previousVersion).")
if previousVersion == currentVersion {

View File

@ -74,21 +74,24 @@ extension DomainListVC {
private func addSystemApps(to menu: NSMenu) {
menu.addItem(HeaderView.asMenuItem(text: "domain_list.system_apps".localized))
menu.addItem(
withTitle: "domain_list.open_in_finder".localized,
menu.addItem(NSMenuItem(
title: "domain_list.open_in_finder".localized,
action: #selector(self.openInFinder),
keyEquivalent: "F"
)
menu.addItem(
withTitle: "domain_list.open_in_terminal".localized,
keyEquivalent: "F",
systemImage: "folder"
))
menu.addItem(NSMenuItem(
title: "domain_list.open_in_terminal".localized,
action: #selector(self.openInTerminal),
keyEquivalent: "T"
)
menu.addItem(
withTitle: "domain_list.open_in_browser".localized,
keyEquivalent: "T",
systemImage: "apple.terminal.fill"
))
menu.addItem(NSMenuItem(
title: "domain_list.open_in_browser".localized,
action: #selector(self.openInBrowser),
keyEquivalent: "B"
)
keyEquivalent: "B",
systemImage: "globe"
))
}
private func addDetectedApps(to menu: NSMenu) {
@ -100,7 +103,8 @@ extension DomainListVC {
let editorMenuItem = EditorMenuItem(
title: "domain_list.open_in".localized(editor.name),
action: #selector(self.openWithEditor(sender:)),
keyEquivalent: ""
keyEquivalent: "",
systemImage: "arrow.up.right"
)
editorMenuItem.editor = editor
menu.addItem(editorMenuItem)
@ -110,11 +114,12 @@ extension DomainListVC {
private func addUnlink(to menu: NSMenu, with site: ValetSite) {
if site.aliasPath != nil {
menu.addItem(
withTitle: "domain_list.unlink".localized,
menu.addItem(NSMenuItem(
title: "domain_list.unlink".localized,
action: #selector(self.unlinkSite),
keyEquivalent: ""
)
keyEquivalent: "",
systemImage: "trash"
))
menu.addItem(NSMenuItem.separator())
}
}
@ -164,23 +169,25 @@ extension DomainListVC {
}
private func addToggleSecure(to menu: NSMenu, secured: Bool) {
menu.addItem(
withTitle: secured
menu.addItem(NSMenuItem(
title: secured
? "domain_list.unsecure".localized
: "domain_list.secure".localized,
action: #selector(toggleSecure),
keyEquivalent: ""
)
keyEquivalent: "",
systemImage: secured ? "lock.slash" : "lock"
))
}
private func addToggleFavorite(to menu: NSMenu, favorited: Bool) {
menu.addItem(
withTitle: favorited
menu.addItem(NSMenuItem(
title: favorited
? "domain_list.unfavorite".localized
: "domain_list.favorite".localized,
action: #selector(toggleFavorite),
keyEquivalent: ""
)
keyEquivalent: "",
systemImage: favorited ? "star.slash.fill" : "star.fill"
))
}
private func addMenuItemsForExtensions(to menu: NSMenu, for extensions: [PhpExtension], version: String) {

View File

@ -17,6 +17,8 @@ class DomainListVC: NSViewController, NSTableViewDelegate, NSTableViewDataSource
@IBOutlet weak var tableView: PMTableView!
@IBOutlet weak var noResultsView: NSView!
@IBOutlet weak var progressIndicator: NSProgressIndicator!
@IBOutlet weak var progressIndicatorContainer: NSVisualEffectView!
@IBOutlet weak var labelProgressIndicator: NSTextField!
// MARK: - Variables
@ -149,6 +151,9 @@ class DomainListVC: NSViewController, NSTableViewDelegate, NSTableViewDataSource
timer = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: false, block: { _ in
Task {
@MainActor in self.progressIndicator.startAnimation(true)
self.labelProgressIndicator.stringValue = "phpman.steps.wait".localized
self.progressIndicatorContainer.layer?.cornerRadius = 10
self.progressIndicatorContainer.isHidden = false
}
})
@ -163,6 +168,7 @@ class DomainListVC: NSViewController, NSTableViewDelegate, NSTableViewDataSource
*/
@MainActor public func setUINotBusy() {
timer?.invalidate()
progressIndicatorContainer.isHidden = true
progressIndicator.stopAnimation(nil)
tableView.alphaValue = 1.0
tableView.isEnabled = true

View File

@ -68,6 +68,7 @@
"mi_donate" = "Donate...";
"mi_check_for_updates" = "Check for Updates...";
"mi_lite_mode" = "About Standalone Mode...";
"mi_driver" = "App Driver: %@";
"mi_quit" = "Quit PHP Monitor";
"mi_about" = "About PHP Monitor";