mirror of
https://github.com/nicoverbruggen/phpmon.git
synced 2025-08-09 04:42:59 +02:00
Compare commits
57 Commits
Author | SHA1 | Date | |
---|---|---|---|
e29ca9e1ad | |||
40e05d9445 | |||
3ebf51b319 | |||
4b8ad911f1 | |||
efd902b4f3 | |||
918e272da7 | |||
272a9182d3 | |||
63f85aff91 | |||
581c2d1974 | |||
4deef64537 | |||
bedabaa3bb | |||
9da3772212 | |||
e62b03d070 | |||
9a11d2efed | |||
b134e62328 | |||
5c69133c42 | |||
f4448e0640 | |||
7fd30d7c54 | |||
2c57dea97f | |||
a77fa5557a | |||
45704fc736 | |||
f28354e634 | |||
8055a32bde | |||
5b3054326e | |||
e7f3c7e59c | |||
a407515534 | |||
b827ffb869 | |||
bdb718598e | |||
ddfc73e033 | |||
cfae520984 | |||
0c176493e5 | |||
71da62f954 | |||
d6781568a3 | |||
c9c7e14416 | |||
0947dc5ecc | |||
286cdd00e9 | |||
42b79d3cb3 | |||
36aa41568c | |||
273c51f702 | |||
186f80c90e | |||
d93af814c9 | |||
f4885f7dbc | |||
805c9f5e6a | |||
183d0bbc30 | |||
4855c14d28 | |||
588398ea76 | |||
d2502cfba2 | |||
8d46fa8a4e | |||
e59b89ea49 | |||
da2934c2e5 | |||
9de4fc6712 | |||
f4b1e0745a | |||
c7bb4c1d37 | |||
a17512bfad | |||
1292e91b33 | |||
8c55fee18d | |||
663082d725 |
23
.github/contributing.md
vendored
Normal file
23
.github/contributing.md
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# Contribution Guidelines
|
||||||
|
|
||||||
|
Thank you for your interest in contributing to PHP Monitor.
|
||||||
|
|
||||||
|
I consider this project a bit of a nice side-project to my daily gig, so it is very much a personal affair where I love to tinker around.
|
||||||
|
|
||||||
|
**While the code of the latest PHP Monitor release is public, many things are constantly in flux that may not be pushed to this repository yet.**
|
||||||
|
|
||||||
|
I don't mean to be rude, but I don't want other people involved with the project beyond simply contributing a few small things here and there, as has been the case in the past.
|
||||||
|
|
||||||
|
The extra mental overhead of having additional contributors to report to, whose code will need to be reviewed... it's a lot and it makes working on PHP Monitor less enjoyable for me.
|
||||||
|
|
||||||
|
Plus, at this point, the majority of PHP Monitor's main functionality is also done.
|
||||||
|
|
||||||
|
As a result, I may refer you to this file at some point. Again, I don't wish to be rude, but this general rule stands:
|
||||||
|
|
||||||
|
**Making any changes in a fork and opening a pull request without opening an issue first will most likely result in your PR being closed without mercy.**
|
||||||
|
|
||||||
|
To repeat, I am **not opposed** to small contributions and fixes, if they are **meaningful or insightful**.
|
||||||
|
|
||||||
|
To learn more, please check out the [pull request template](/.github/pull_request_template.md) which contains more information about my contribution requirements. (This will also show up when you open a new PR.)
|
||||||
|
|
||||||
|
Thank you for respecting this!
|
2
.github/pull_request_template.md
vendored
2
.github/pull_request_template.md
vendored
@@ -16,7 +16,7 @@ In short: It is usually best to *get in touch first* if you are making substanti
|
|||||||
|
|
||||||
## About destination branches
|
## About destination branches
|
||||||
|
|
||||||
Please keep in mind that `main` is reserved for the current code state of the latest release and should *never* be the destination branch unless a new release is happening. **Merge requests that target `main` will be closed without mercy.**
|
Please keep in mind that `main` is reserved for the current code state of the latest release and should *never* be the destination branch unless a new release is happening. **Pull requests that target `main` will be closed without mercy.**
|
||||||
|
|
||||||
Usually, the best target is the stable `dev/x.x` branch that corresponds with the latest major version that is released.
|
Usually, the best target is the stable `dev/x.x` branch that corresponds with the latest major version that is released.
|
||||||
|
|
||||||
|
@@ -33,6 +33,8 @@
|
|||||||
54FCFD2E276C8D67004CE748 /* HotkeyPreferenceView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 54FCFD2C276C8D67004CE748 /* HotkeyPreferenceView.xib */; };
|
54FCFD2E276C8D67004CE748 /* HotkeyPreferenceView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 54FCFD2C276C8D67004CE748 /* HotkeyPreferenceView.xib */; };
|
||||||
54FCFD30276C8DA4004CE748 /* HotkeyPreferenceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54FCFD2F276C8DA4004CE748 /* HotkeyPreferenceView.swift */; };
|
54FCFD30276C8DA4004CE748 /* HotkeyPreferenceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54FCFD2F276C8DA4004CE748 /* HotkeyPreferenceView.swift */; };
|
||||||
54FCFD31276C8DA4004CE748 /* 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 */; };
|
C405A4D024B9B9140062FAFA /* InternetAccessPolicy.strings in Resources */ = {isa = PBXBuildFile; fileRef = C405A4CE24B9B9130062FAFA /* InternetAccessPolicy.strings */; };
|
||||||
C405A4D124B9B9140062FAFA /* InternetAccessPolicy.plist in Resources */ = {isa = PBXBuildFile; fileRef = C405A4CF24B9B9140062FAFA /* InternetAccessPolicy.plist */; };
|
C405A4D124B9B9140062FAFA /* InternetAccessPolicy.plist in Resources */ = {isa = PBXBuildFile; fileRef = C405A4CF24B9B9140062FAFA /* InternetAccessPolicy.plist */; };
|
||||||
C4068CA427B0780A00544CD5 /* CheckboxPreferenceView.xib in Resources */ = {isa = PBXBuildFile; fileRef = C4068CA327B0780A00544CD5 /* CheckboxPreferenceView.xib */; };
|
C4068CA427B0780A00544CD5 /* CheckboxPreferenceView.xib in Resources */ = {isa = PBXBuildFile; fileRef = C4068CA327B0780A00544CD5 /* CheckboxPreferenceView.xib */; };
|
||||||
@@ -91,8 +93,6 @@
|
|||||||
C42337A3281F19F000459A48 /* Xdebug.swift in Sources */ = {isa = PBXBuildFile; fileRef = C42337A2281F19F000459A48 /* Xdebug.swift */; };
|
C42337A3281F19F000459A48 /* Xdebug.swift in Sources */ = {isa = PBXBuildFile; fileRef = C42337A2281F19F000459A48 /* Xdebug.swift */; };
|
||||||
C42759672627662800093CAE /* NSMenuExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C42759662627662800093CAE /* NSMenuExtension.swift */; };
|
C42759672627662800093CAE /* NSMenuExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C42759662627662800093CAE /* NSMenuExtension.swift */; };
|
||||||
C42759682627662800093CAE /* NSMenuExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C42759662627662800093CAE /* NSMenuExtension.swift */; };
|
C42759682627662800093CAE /* NSMenuExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C42759662627662800093CAE /* NSMenuExtension.swift */; };
|
||||||
C42800AA28452AA10099C999 /* StatusMenu+Items.swift in Sources */ = {isa = PBXBuildFile; fileRef = C42800A928452AA10099C999 /* StatusMenu+Items.swift */; };
|
|
||||||
C42800AB28452AA50099C999 /* StatusMenu+Items.swift in Sources */ = {isa = PBXBuildFile; fileRef = C42800A928452AA10099C999 /* StatusMenu+Items.swift */; };
|
|
||||||
C4297F7A28970D59004C4630 /* WarningView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4297F7928970D59004C4630 /* WarningView.swift */; };
|
C4297F7A28970D59004C4630 /* WarningView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4297F7928970D59004C4630 /* WarningView.swift */; };
|
||||||
C42C49DB27C2806F0074ABAC /* MainMenu+FixMyValet.swift in Sources */ = {isa = PBXBuildFile; fileRef = C42C49DA27C2806F0074ABAC /* MainMenu+FixMyValet.swift */; };
|
C42C49DB27C2806F0074ABAC /* MainMenu+FixMyValet.swift in Sources */ = {isa = PBXBuildFile; fileRef = C42C49DA27C2806F0074ABAC /* MainMenu+FixMyValet.swift */; };
|
||||||
C42CFB1627DFDE7900862737 /* nginx-site.test in Resources */ = {isa = PBXBuildFile; fileRef = C42CFB1527DFDE7900862737 /* nginx-site.test */; };
|
C42CFB1627DFDE7900862737 /* nginx-site.test in Resources */ = {isa = PBXBuildFile; fileRef = C42CFB1527DFDE7900862737 /* nginx-site.test */; };
|
||||||
@@ -130,6 +130,8 @@
|
|||||||
C44CCD4927AFF3B700CE40E5 /* MainMenu+Async.swift in Sources */ = {isa = PBXBuildFile; fileRef = C44CCD4827AFF3B700CE40E5 /* MainMenu+Async.swift */; };
|
C44CCD4927AFF3B700CE40E5 /* MainMenu+Async.swift in Sources */ = {isa = PBXBuildFile; fileRef = C44CCD4827AFF3B700CE40E5 /* MainMenu+Async.swift */; };
|
||||||
C44CCD4A27AFF3BC00CE40E5 /* MainMenu+Async.swift in Sources */ = {isa = PBXBuildFile; fileRef = C44CCD4827AFF3B700CE40E5 /* MainMenu+Async.swift */; };
|
C44CCD4A27AFF3BC00CE40E5 /* MainMenu+Async.swift in Sources */ = {isa = PBXBuildFile; fileRef = C44CCD4827AFF3B700CE40E5 /* MainMenu+Async.swift */; };
|
||||||
C44F868E2835BD8D005C353A /* phpmon-config.json in Resources */ = {isa = PBXBuildFile; fileRef = C44F868D2835BD8D005C353A /* phpmon-config.json */; };
|
C44F868E2835BD8D005C353A /* phpmon-config.json in Resources */ = {isa = PBXBuildFile; fileRef = C44F868D2835BD8D005C353A /* phpmon-config.json */; };
|
||||||
|
C450C8C628C919EC002A2B4B /* PreferenceName.swift in Sources */ = {isa = PBXBuildFile; fileRef = C450C8C528C919EC002A2B4B /* PreferenceName.swift */; };
|
||||||
|
C450C8C728C919EC002A2B4B /* PreferenceName.swift in Sources */ = {isa = PBXBuildFile; fileRef = C450C8C528C919EC002A2B4B /* PreferenceName.swift */; };
|
||||||
C459B4BD27F6093700E9B4B4 /* nginx-proxy.test in Resources */ = {isa = PBXBuildFile; fileRef = C459B4BC27F6093700E9B4B4 /* nginx-proxy.test */; };
|
C459B4BD27F6093700E9B4B4 /* nginx-proxy.test in Resources */ = {isa = PBXBuildFile; fileRef = C459B4BC27F6093700E9B4B4 /* nginx-proxy.test */; };
|
||||||
C45E76142854A65300B4FE0C /* ServicesManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C45E76132854A65300B4FE0C /* ServicesManager.swift */; };
|
C45E76142854A65300B4FE0C /* ServicesManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C45E76132854A65300B4FE0C /* ServicesManager.swift */; };
|
||||||
C45E76152854A65300B4FE0C /* ServicesManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C45E76132854A65300B4FE0C /* ServicesManager.swift */; };
|
C45E76152854A65300B4FE0C /* ServicesManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C45E76132854A65300B4FE0C /* ServicesManager.swift */; };
|
||||||
@@ -189,6 +191,8 @@
|
|||||||
C495F5B028A42E080087F70A /* EnvironmentCheck.swift in Sources */ = {isa = PBXBuildFile; fileRef = C495F5AE28A42E080087F70A /* EnvironmentCheck.swift */; };
|
C495F5B028A42E080087F70A /* EnvironmentCheck.swift in Sources */ = {isa = PBXBuildFile; fileRef = C495F5AE28A42E080087F70A /* EnvironmentCheck.swift */; };
|
||||||
C4998F0A2617633900B2526E /* PreferencesWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4998F092617633900B2526E /* PreferencesWindowController.swift */; };
|
C4998F0A2617633900B2526E /* PreferencesWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4998F092617633900B2526E /* PreferencesWindowController.swift */; };
|
||||||
C4998F0B2617633900B2526E /* PreferencesWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4998F092617633900B2526E /* PreferencesWindowController.swift */; };
|
C4998F0B2617633900B2526E /* PreferencesWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4998F092617633900B2526E /* PreferencesWindowController.swift */; };
|
||||||
|
C4A81CA428C67101008DD9D1 /* PMTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4A81CA328C67101008DD9D1 /* PMTableView.swift */; };
|
||||||
|
C4A81CA528C67101008DD9D1 /* PMTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4A81CA328C67101008DD9D1 /* PMTableView.swift */; };
|
||||||
C4AC51FC27E27F47008528CA /* DomainListKindCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4AC51FB27E27F47008528CA /* DomainListKindCell.swift */; };
|
C4AC51FC27E27F47008528CA /* DomainListKindCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4AC51FB27E27F47008528CA /* DomainListKindCell.swift */; };
|
||||||
C4ACA38F25C754C100060C66 /* PhpExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4ACA38E25C754C100060C66 /* PhpExtension.swift */; };
|
C4ACA38F25C754C100060C66 /* PhpExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4ACA38E25C754C100060C66 /* PhpExtension.swift */; };
|
||||||
C4AF9F72275445FF00D44ED0 /* valet-config.json in Resources */ = {isa = PBXBuildFile; fileRef = C4AF9F70275445FF00D44ED0 /* valet-config.json */; };
|
C4AF9F72275445FF00D44ED0 /* valet-config.json in Resources */ = {isa = PBXBuildFile; fileRef = C4AF9F70275445FF00D44ED0 /* valet-config.json */; };
|
||||||
@@ -224,6 +228,8 @@
|
|||||||
C4C0E8EB27F88B80002D32A9 /* ValetProxy+Fake.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C0E8E927F88B80002D32A9 /* ValetProxy+Fake.swift */; };
|
C4C0E8EB27F88B80002D32A9 /* ValetProxy+Fake.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C0E8E927F88B80002D32A9 /* ValetProxy+Fake.swift */; };
|
||||||
C4C1019B27C65C6F001FACC2 /* Process.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C1019A27C65C6F001FACC2 /* Process.swift */; };
|
C4C1019B27C65C6F001FACC2 /* Process.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C1019A27C65C6F001FACC2 /* Process.swift */; };
|
||||||
C4C1019C27C65C6F001FACC2 /* Process.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C1019A27C65C6F001FACC2 /* Process.swift */; };
|
C4C1019C27C65C6F001FACC2 /* Process.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C1019A27C65C6F001FACC2 /* Process.swift */; };
|
||||||
|
C4C3643928AE4FCE00C0770E /* StatusMenu+Items.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C3643828AE4FCE00C0770E /* StatusMenu+Items.swift */; };
|
||||||
|
C4C3643A28AE4FCE00C0770E /* StatusMenu+Items.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C3643828AE4FCE00C0770E /* StatusMenu+Items.swift */; };
|
||||||
C4C3ED412783497000AB15D8 /* MainMenu+Startup.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C3ED402783497000AB15D8 /* MainMenu+Startup.swift */; };
|
C4C3ED412783497000AB15D8 /* MainMenu+Startup.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C3ED402783497000AB15D8 /* MainMenu+Startup.swift */; };
|
||||||
C4C3ED4327834C5200AB15D8 /* CustomPrefs.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C3ED4227834C5200AB15D8 /* CustomPrefs.swift */; };
|
C4C3ED4327834C5200AB15D8 /* CustomPrefs.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C3ED4227834C5200AB15D8 /* CustomPrefs.swift */; };
|
||||||
C4C8E818276F54D8003AC782 /* App+ConfigWatch.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C8E817276F54D8003AC782 /* App+ConfigWatch.swift */; };
|
C4C8E818276F54D8003AC782 /* App+ConfigWatch.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C8E817276F54D8003AC782 /* App+ConfigWatch.swift */; };
|
||||||
@@ -238,6 +244,8 @@
|
|||||||
C4CE3BBA27B31F670086CA49 /* ComposerWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4CE3BB927B31F670086CA49 /* ComposerWindow.swift */; };
|
C4CE3BBA27B31F670086CA49 /* ComposerWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4CE3BB927B31F670086CA49 /* ComposerWindow.swift */; };
|
||||||
C4CE3BBB27B324230086CA49 /* MainMenu+Switcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4CE3BB727B31F2E0086CA49 /* MainMenu+Switcher.swift */; };
|
C4CE3BBB27B324230086CA49 /* MainMenu+Switcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4CE3BB727B31F2E0086CA49 /* MainMenu+Switcher.swift */; };
|
||||||
C4CE3BBC27B324250086CA49 /* ComposerWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4CE3BB927B31F670086CA49 /* ComposerWindow.swift */; };
|
C4CE3BBC27B324250086CA49 /* ComposerWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4CE3BB927B31F670086CA49 /* ComposerWindow.swift */; };
|
||||||
|
C4D27F24292BDF630081B38F /* Homebrew.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D27F23292BDF630081B38F /* Homebrew.swift */; };
|
||||||
|
C4D27F25292BDF630081B38F /* Homebrew.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D27F23292BDF630081B38F /* Homebrew.swift */; };
|
||||||
C4D5CFCA27E0F9CD00035329 /* NginxConfigurationFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D5CFC927E0F9CD00035329 /* NginxConfigurationFile.swift */; };
|
C4D5CFCA27E0F9CD00035329 /* NginxConfigurationFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D5CFC927E0F9CD00035329 /* NginxConfigurationFile.swift */; };
|
||||||
C4D5CFCB27E0F9CD00035329 /* NginxConfigurationFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D5CFC927E0F9CD00035329 /* NginxConfigurationFile.swift */; };
|
C4D5CFCB27E0F9CD00035329 /* NginxConfigurationFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D5CFC927E0F9CD00035329 /* NginxConfigurationFile.swift */; };
|
||||||
C4D8016622B1584700C6DA1B /* Startup.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D8016522B1584700C6DA1B /* Startup.swift */; };
|
C4D8016622B1584700C6DA1B /* Startup.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D8016522B1584700C6DA1B /* Startup.swift */; };
|
||||||
@@ -330,6 +338,8 @@
|
|||||||
54FCFD29276C8AA4004CE748 /* CheckboxPreferenceView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckboxPreferenceView.swift; sourceTree = "<group>"; };
|
54FCFD29276C8AA4004CE748 /* CheckboxPreferenceView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckboxPreferenceView.swift; sourceTree = "<group>"; };
|
||||||
54FCFD2C276C8D67004CE748 /* HotkeyPreferenceView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = HotkeyPreferenceView.xib; sourceTree = "<group>"; };
|
54FCFD2C276C8D67004CE748 /* HotkeyPreferenceView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = HotkeyPreferenceView.xib; sourceTree = "<group>"; };
|
||||||
54FCFD2F276C8DA4004CE748 /* HotkeyPreferenceView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HotkeyPreferenceView.swift; sourceTree = "<group>"; };
|
54FCFD2F276C8DA4004CE748 /* HotkeyPreferenceView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HotkeyPreferenceView.swift; sourceTree = "<group>"; };
|
||||||
|
C40508AE28ADA23D008FAC1F /* NoDomainResultsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoDomainResultsView.swift; sourceTree = "<group>"; };
|
||||||
|
C40508B028ADAB44008FAC1F /* NSMenuItemExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSMenuItemExtension.swift; sourceTree = "<group>"; };
|
||||||
C405A4CE24B9B9130062FAFA /* InternetAccessPolicy.strings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; path = InternetAccessPolicy.strings; sourceTree = "<group>"; };
|
C405A4CE24B9B9130062FAFA /* InternetAccessPolicy.strings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; path = InternetAccessPolicy.strings; sourceTree = "<group>"; };
|
||||||
C405A4CF24B9B9140062FAFA /* InternetAccessPolicy.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = InternetAccessPolicy.plist; sourceTree = "<group>"; };
|
C405A4CF24B9B9140062FAFA /* InternetAccessPolicy.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = InternetAccessPolicy.plist; sourceTree = "<group>"; };
|
||||||
C4068CA327B0780A00544CD5 /* CheckboxPreferenceView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CheckboxPreferenceView.xib; sourceTree = "<group>"; };
|
C4068CA327B0780A00544CD5 /* CheckboxPreferenceView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CheckboxPreferenceView.xib; sourceTree = "<group>"; };
|
||||||
@@ -370,7 +380,6 @@
|
|||||||
C4232EE42612526500158FC6 /* Credits.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = Credits.html; sourceTree = "<group>"; };
|
C4232EE42612526500158FC6 /* Credits.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = Credits.html; sourceTree = "<group>"; };
|
||||||
C42337A2281F19F000459A48 /* Xdebug.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Xdebug.swift; sourceTree = "<group>"; };
|
C42337A2281F19F000459A48 /* Xdebug.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Xdebug.swift; sourceTree = "<group>"; };
|
||||||
C42759662627662800093CAE /* NSMenuExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSMenuExtension.swift; sourceTree = "<group>"; };
|
C42759662627662800093CAE /* NSMenuExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSMenuExtension.swift; sourceTree = "<group>"; };
|
||||||
C42800A928452AA10099C999 /* StatusMenu+Items.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "StatusMenu+Items.swift"; sourceTree = "<group>"; };
|
|
||||||
C4297F7928970D59004C4630 /* WarningView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WarningView.swift; sourceTree = "<group>"; };
|
C4297F7928970D59004C4630 /* WarningView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WarningView.swift; sourceTree = "<group>"; };
|
||||||
C42C49DA27C2806F0074ABAC /* MainMenu+FixMyValet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MainMenu+FixMyValet.swift"; sourceTree = "<group>"; };
|
C42C49DA27C2806F0074ABAC /* MainMenu+FixMyValet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MainMenu+FixMyValet.swift"; sourceTree = "<group>"; };
|
||||||
C42CFB1527DFDE7900862737 /* nginx-site.test */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "nginx-site.test"; sourceTree = "<group>"; };
|
C42CFB1527DFDE7900862737 /* nginx-site.test */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "nginx-site.test"; sourceTree = "<group>"; };
|
||||||
@@ -395,6 +404,7 @@
|
|||||||
C44CCD3F27AFE2FC00CE40E5 /* AlertableError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertableError.swift; sourceTree = "<group>"; };
|
C44CCD3F27AFE2FC00CE40E5 /* AlertableError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertableError.swift; sourceTree = "<group>"; };
|
||||||
C44CCD4827AFF3B700CE40E5 /* MainMenu+Async.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MainMenu+Async.swift"; sourceTree = "<group>"; };
|
C44CCD4827AFF3B700CE40E5 /* MainMenu+Async.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MainMenu+Async.swift"; sourceTree = "<group>"; };
|
||||||
C44F868D2835BD8D005C353A /* phpmon-config.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "phpmon-config.json"; sourceTree = "<group>"; };
|
C44F868D2835BD8D005C353A /* phpmon-config.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "phpmon-config.json"; sourceTree = "<group>"; };
|
||||||
|
C450C8C528C919EC002A2B4B /* PreferenceName.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferenceName.swift; sourceTree = "<group>"; };
|
||||||
C459B4BC27F6093700E9B4B4 /* nginx-proxy.test */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "nginx-proxy.test"; sourceTree = "<group>"; };
|
C459B4BC27F6093700E9B4B4 /* nginx-proxy.test */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "nginx-proxy.test"; sourceTree = "<group>"; };
|
||||||
C45E76132854A65300B4FE0C /* ServicesManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServicesManager.swift; sourceTree = "<group>"; };
|
C45E76132854A65300B4FE0C /* ServicesManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServicesManager.swift; sourceTree = "<group>"; };
|
||||||
C463E37F284930EE00422731 /* PresetHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PresetHelper.swift; sourceTree = "<group>"; };
|
C463E37F284930EE00422731 /* PresetHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PresetHelper.swift; sourceTree = "<group>"; };
|
||||||
@@ -423,6 +433,7 @@
|
|||||||
C4930849279F331F009C240B /* AddSiteVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddSiteVC.swift; sourceTree = "<group>"; };
|
C4930849279F331F009C240B /* AddSiteVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddSiteVC.swift; sourceTree = "<group>"; };
|
||||||
C495F5AE28A42E080087F70A /* EnvironmentCheck.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnvironmentCheck.swift; sourceTree = "<group>"; };
|
C495F5AE28A42E080087F70A /* EnvironmentCheck.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnvironmentCheck.swift; sourceTree = "<group>"; };
|
||||||
C4998F092617633900B2526E /* PreferencesWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesWindowController.swift; sourceTree = "<group>"; };
|
C4998F092617633900B2526E /* PreferencesWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesWindowController.swift; sourceTree = "<group>"; };
|
||||||
|
C4A81CA328C67101008DD9D1 /* PMTableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PMTableView.swift; sourceTree = "<group>"; };
|
||||||
C4AC51FB27E27F47008528CA /* DomainListKindCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DomainListKindCell.swift; sourceTree = "<group>"; };
|
C4AC51FB27E27F47008528CA /* DomainListKindCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DomainListKindCell.swift; sourceTree = "<group>"; };
|
||||||
C4ACA38E25C754C100060C66 /* PhpExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhpExtension.swift; sourceTree = "<group>"; };
|
C4ACA38E25C754C100060C66 /* PhpExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhpExtension.swift; sourceTree = "<group>"; };
|
||||||
C4AF9F70275445FF00D44ED0 /* valet-config.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "valet-config.json"; sourceTree = "<group>"; };
|
C4AF9F70275445FF00D44ED0 /* valet-config.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "valet-config.json"; sourceTree = "<group>"; };
|
||||||
@@ -444,6 +455,7 @@
|
|||||||
C4C0E8E627F88B41002D32A9 /* ProxyScanner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProxyScanner.swift; sourceTree = "<group>"; };
|
C4C0E8E627F88B41002D32A9 /* ProxyScanner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProxyScanner.swift; sourceTree = "<group>"; };
|
||||||
C4C0E8E927F88B80002D32A9 /* ValetProxy+Fake.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ValetProxy+Fake.swift"; sourceTree = "<group>"; };
|
C4C0E8E927F88B80002D32A9 /* ValetProxy+Fake.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ValetProxy+Fake.swift"; sourceTree = "<group>"; };
|
||||||
C4C1019A27C65C6F001FACC2 /* Process.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Process.swift; sourceTree = "<group>"; };
|
C4C1019A27C65C6F001FACC2 /* Process.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Process.swift; sourceTree = "<group>"; };
|
||||||
|
C4C3643828AE4FCE00C0770E /* StatusMenu+Items.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "StatusMenu+Items.swift"; sourceTree = "<group>"; };
|
||||||
C4C3ED402783497000AB15D8 /* MainMenu+Startup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MainMenu+Startup.swift"; sourceTree = "<group>"; };
|
C4C3ED402783497000AB15D8 /* MainMenu+Startup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MainMenu+Startup.swift"; sourceTree = "<group>"; };
|
||||||
C4C3ED4227834C5200AB15D8 /* CustomPrefs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomPrefs.swift; sourceTree = "<group>"; };
|
C4C3ED4227834C5200AB15D8 /* CustomPrefs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomPrefs.swift; sourceTree = "<group>"; };
|
||||||
C4C8E817276F54D8003AC782 /* App+ConfigWatch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "App+ConfigWatch.swift"; sourceTree = "<group>"; };
|
C4C8E817276F54D8003AC782 /* App+ConfigWatch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "App+ConfigWatch.swift"; sourceTree = "<group>"; };
|
||||||
@@ -452,6 +464,7 @@
|
|||||||
C4CDA892288F1A71007CE25F /* Keys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Keys.swift; sourceTree = "<group>"; };
|
C4CDA892288F1A71007CE25F /* Keys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Keys.swift; sourceTree = "<group>"; };
|
||||||
C4CE3BB727B31F2E0086CA49 /* MainMenu+Switcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MainMenu+Switcher.swift"; sourceTree = "<group>"; };
|
C4CE3BB727B31F2E0086CA49 /* MainMenu+Switcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MainMenu+Switcher.swift"; sourceTree = "<group>"; };
|
||||||
C4CE3BB927B31F670086CA49 /* ComposerWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposerWindow.swift; sourceTree = "<group>"; };
|
C4CE3BB927B31F670086CA49 /* ComposerWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposerWindow.swift; sourceTree = "<group>"; };
|
||||||
|
C4D27F23292BDF630081B38F /* Homebrew.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Homebrew.swift; sourceTree = "<group>"; };
|
||||||
C4D5CFC927E0F9CD00035329 /* NginxConfigurationFile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NginxConfigurationFile.swift; sourceTree = "<group>"; };
|
C4D5CFC927E0F9CD00035329 /* NginxConfigurationFile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NginxConfigurationFile.swift; sourceTree = "<group>"; };
|
||||||
C4D8016522B1584700C6DA1B /* Startup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Startup.swift; sourceTree = "<group>"; };
|
C4D8016522B1584700C6DA1B /* Startup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Startup.swift; sourceTree = "<group>"; };
|
||||||
C4D89BC52783C99400A02B68 /* ComposerJson.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposerJson.swift; sourceTree = "<group>"; };
|
C4D89BC52783C99400A02B68 /* ComposerJson.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposerJson.swift; sourceTree = "<group>"; };
|
||||||
@@ -513,6 +526,7 @@
|
|||||||
C4998F092617633900B2526E /* PreferencesWindowController.swift */,
|
C4998F092617633900B2526E /* PreferencesWindowController.swift */,
|
||||||
C4FACE7F288F1C0D00FC478F /* PreferencesWindowController+Hotkey.swift */,
|
C4FACE7F288F1C0D00FC478F /* PreferencesWindowController+Hotkey.swift */,
|
||||||
5420395826135DC100FB00FA /* PrefsVC.swift */,
|
5420395826135DC100FB00FA /* PrefsVC.swift */,
|
||||||
|
C450C8C528C919EC002A2B4B /* PreferenceName.swift */,
|
||||||
5420395E2613607600FB00FA /* Preferences.swift */,
|
5420395E2613607600FB00FA /* Preferences.swift */,
|
||||||
C4C3ED4227834C5200AB15D8 /* CustomPrefs.swift */,
|
C4C3ED4227834C5200AB15D8 /* CustomPrefs.swift */,
|
||||||
C4068CA927B0890D00544CD5 /* MenuBarIcons.swift */,
|
C4068CA927B0890D00544CD5 /* MenuBarIcons.swift */,
|
||||||
@@ -633,6 +647,7 @@
|
|||||||
C4C1019A27C65C6F001FACC2 /* Process.swift */,
|
C4C1019A27C65C6F001FACC2 /* Process.swift */,
|
||||||
C40C7F2F27722E8D00DDDCDC /* Logger.swift */,
|
C40C7F2F27722E8D00DDDCDC /* Logger.swift */,
|
||||||
C417DC73277614690015E6EE /* Helpers.swift */,
|
C417DC73277614690015E6EE /* Helpers.swift */,
|
||||||
|
C4D27F23292BDF630081B38F /* Homebrew.swift */,
|
||||||
);
|
);
|
||||||
path = Core;
|
path = Core;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -830,6 +845,7 @@
|
|||||||
C4FE011028084FC200D1DE6D /* SelectionVC.swift */,
|
C4FE011028084FC200D1DE6D /* SelectionVC.swift */,
|
||||||
C4930849279F331F009C240B /* AddSiteVC.swift */,
|
C4930849279F331F009C240B /* AddSiteVC.swift */,
|
||||||
C4D9F24A280B69E100DCD39A /* AddProxyVC.swift */,
|
C4D9F24A280B69E100DCD39A /* AddProxyVC.swift */,
|
||||||
|
C4A81CA328C67101008DD9D1 /* PMTableView.swift */,
|
||||||
);
|
);
|
||||||
path = DomainList;
|
path = DomainList;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -844,7 +860,7 @@
|
|||||||
C42C49DA27C2806F0074ABAC /* MainMenu+FixMyValet.swift */,
|
C42C49DA27C2806F0074ABAC /* MainMenu+FixMyValet.swift */,
|
||||||
C4F361602836BFD9003598CC /* MainMenu+Actions.swift */,
|
C4F361602836BFD9003598CC /* MainMenu+Actions.swift */,
|
||||||
C47331A1247093B7009A0597 /* StatusMenu.swift */,
|
C47331A1247093B7009A0597 /* StatusMenu.swift */,
|
||||||
C42800A928452AA10099C999 /* StatusMenu+Items.swift */,
|
C4C3643828AE4FCE00C0770E /* StatusMenu+Items.swift */,
|
||||||
);
|
);
|
||||||
path = Menu;
|
path = Menu;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -960,6 +976,7 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
C44264BF2850BD2A007400F1 /* VersionPopoverView.swift */,
|
C44264BF2850BD2A007400F1 /* VersionPopoverView.swift */,
|
||||||
|
C40508AE28ADA23D008FAC1F /* NoDomainResultsView.swift */,
|
||||||
);
|
);
|
||||||
path = Domains;
|
path = Domains;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -1136,6 +1153,7 @@
|
|||||||
C46FA23E246C358E00944F05 /* StringExtension.swift */,
|
C46FA23E246C358E00944F05 /* StringExtension.swift */,
|
||||||
C48D0C9225CC804200CC7490 /* XibLoadable.swift */,
|
C48D0C9225CC804200CC7490 /* XibLoadable.swift */,
|
||||||
C42759662627662800093CAE /* NSMenuExtension.swift */,
|
C42759662627662800093CAE /* NSMenuExtension.swift */,
|
||||||
|
C40508B028ADAB44008FAC1F /* NSMenuItemExtension.swift */,
|
||||||
C4E0F7EC27BEBDA9007475F2 /* NSWindowExtension.swift */,
|
C4E0F7EC27BEBDA9007475F2 /* NSWindowExtension.swift */,
|
||||||
C4EB53E628553117006F9937 /* ArrayExtension.swift */,
|
C4EB53E628553117006F9937 /* ArrayExtension.swift */,
|
||||||
);
|
);
|
||||||
@@ -1192,7 +1210,7 @@
|
|||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
LastSwiftUpdateCheck = 1320;
|
LastSwiftUpdateCheck = 1320;
|
||||||
LastUpgradeCheck = 1320;
|
LastUpgradeCheck = 1400;
|
||||||
ORGANIZATIONNAME = "Nico Verbruggen";
|
ORGANIZATIONNAME = "Nico Verbruggen";
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
C41C1B3222B0097F00E7CF16 = {
|
C41C1B3222B0097F00E7CF16 = {
|
||||||
@@ -1313,6 +1331,7 @@
|
|||||||
C4205A7E27F4D21800191A39 /* ValetProxy.swift in Sources */,
|
C4205A7E27F4D21800191A39 /* ValetProxy.swift in Sources */,
|
||||||
C4C8E818276F54D8003AC782 /* App+ConfigWatch.swift in Sources */,
|
C4C8E818276F54D8003AC782 /* App+ConfigWatch.swift in Sources */,
|
||||||
54FCFD30276C8DA4004CE748 /* HotkeyPreferenceView.swift in Sources */,
|
54FCFD30276C8DA4004CE748 /* HotkeyPreferenceView.swift in Sources */,
|
||||||
|
C450C8C628C919EC002A2B4B /* PreferenceName.swift in Sources */,
|
||||||
C4E4404627C56F4700D225E1 /* ValetSite.swift in Sources */,
|
C4E4404627C56F4700D225E1 /* ValetSite.swift in Sources */,
|
||||||
C4F2E43A2752F7D00020E974 /* PhpInstallation.swift in Sources */,
|
C4F2E43A2752F7D00020E974 /* PhpInstallation.swift in Sources */,
|
||||||
C4D9F24B280B69E100DCD39A /* AddProxyVC.swift in Sources */,
|
C4D9F24B280B69E100DCD39A /* AddProxyVC.swift in Sources */,
|
||||||
@@ -1335,8 +1354,8 @@
|
|||||||
C4B6091A2853AAD300C95265 /* SectionHeaderView.swift in Sources */,
|
C4B6091A2853AAD300C95265 /* SectionHeaderView.swift in Sources */,
|
||||||
C44067F727E258410045BD4E /* DomainListPhpCell.swift in Sources */,
|
C44067F727E258410045BD4E /* DomainListPhpCell.swift in Sources */,
|
||||||
C4FACE80288F1C0D00FC478F /* PreferencesWindowController+Hotkey.swift in Sources */,
|
C4FACE80288F1C0D00FC478F /* PreferencesWindowController+Hotkey.swift in Sources */,
|
||||||
C42800AA28452AA10099C999 /* StatusMenu+Items.swift in Sources */,
|
|
||||||
C415D3B72770F294005EF286 /* Actions.swift in Sources */,
|
C415D3B72770F294005EF286 /* Actions.swift in Sources */,
|
||||||
|
C4C3643928AE4FCE00C0770E /* StatusMenu+Items.swift in Sources */,
|
||||||
C4AC51FC27E27F47008528CA /* DomainListKindCell.swift in Sources */,
|
C4AC51FC27E27F47008528CA /* DomainListKindCell.swift in Sources */,
|
||||||
C4CDA893288F1A71007CE25F /* Keys.swift in Sources */,
|
C4CDA893288F1A71007CE25F /* Keys.swift in Sources */,
|
||||||
C4F361612836BFD9003598CC /* MainMenu+Actions.swift in Sources */,
|
C4F361612836BFD9003598CC /* MainMenu+Actions.swift in Sources */,
|
||||||
@@ -1382,6 +1401,7 @@
|
|||||||
C4C1019B27C65C6F001FACC2 /* Process.swift in Sources */,
|
C4C1019B27C65C6F001FACC2 /* Process.swift in Sources */,
|
||||||
C4EC1E73279DFCF40010F296 /* Events.swift in Sources */,
|
C4EC1E73279DFCF40010F296 /* Events.swift in Sources */,
|
||||||
C44067FB27E25FD70045BD4E /* DomainListTLSCell.swift in Sources */,
|
C44067FB27E25FD70045BD4E /* DomainListTLSCell.swift in Sources */,
|
||||||
|
C4A81CA428C67101008DD9D1 /* PMTableView.swift in Sources */,
|
||||||
C4927F0B27B2DFC200C55AFD /* Errors.swift in Sources */,
|
C4927F0B27B2DFC200C55AFD /* Errors.swift in Sources */,
|
||||||
C4B5853E2770FE3900DA4FBE /* Paths.swift in Sources */,
|
C4B5853E2770FE3900DA4FBE /* Paths.swift in Sources */,
|
||||||
C41C1B4B22B019FF00E7CF16 /* ActivePhpInstallation.swift in Sources */,
|
C41C1B4B22B019FF00E7CF16 /* ActivePhpInstallation.swift in Sources */,
|
||||||
@@ -1390,12 +1410,14 @@
|
|||||||
C44CCD4027AFE2FC00CE40E5 /* AlertableError.swift in Sources */,
|
C44CCD4027AFE2FC00CE40E5 /* AlertableError.swift in Sources */,
|
||||||
C4188989275FE8CB001EF227 /* Filesystem.swift in Sources */,
|
C4188989275FE8CB001EF227 /* Filesystem.swift in Sources */,
|
||||||
C4B6091D2853AB9700C95265 /* ServicesView.swift in Sources */,
|
C4B6091D2853AB9700C95265 /* ServicesView.swift in Sources */,
|
||||||
|
C40508B128ADAB44008FAC1F /* NSMenuItemExtension.swift in Sources */,
|
||||||
C4B97B7B275CF20A003F3378 /* App+GlobalHotkey.swift in Sources */,
|
C4B97B7B275CF20A003F3378 /* App+GlobalHotkey.swift in Sources */,
|
||||||
C4EED88927A48778006D7272 /* InterAppHandler.swift in Sources */,
|
C4EED88927A48778006D7272 /* InterAppHandler.swift in Sources */,
|
||||||
C40C7F1E2772136000DDDCDC /* PhpEnv.swift in Sources */,
|
C40C7F1E2772136000DDDCDC /* PhpEnv.swift in Sources */,
|
||||||
C476FF9822B0DD830098105B /* Alert.swift in Sources */,
|
C476FF9822B0DD830098105B /* Alert.swift in Sources */,
|
||||||
C474B00624C0E98C00066A22 /* LocalNotification.swift in Sources */,
|
C474B00624C0E98C00066A22 /* LocalNotification.swift in Sources */,
|
||||||
C4D5CFCA27E0F9CD00035329 /* NginxConfigurationFile.swift in Sources */,
|
C4D5CFCA27E0F9CD00035329 /* NginxConfigurationFile.swift in Sources */,
|
||||||
|
C4D27F24292BDF630081B38F /* Homebrew.swift in Sources */,
|
||||||
C485707028BF452300539B36 /* WarningsWindowController.swift in Sources */,
|
C485707028BF452300539B36 /* WarningsWindowController.swift in Sources */,
|
||||||
C4CE3BBA27B31F670086CA49 /* ComposerWindow.swift in Sources */,
|
C4CE3BBA27B31F670086CA49 /* ComposerWindow.swift in Sources */,
|
||||||
C4D9ADC8277611A0007277F4 /* InternalSwitcher.swift in Sources */,
|
C4D9ADC8277611A0007277F4 /* InternalSwitcher.swift in Sources */,
|
||||||
@@ -1408,6 +1430,7 @@
|
|||||||
C44067F927E2585E0045BD4E /* DomainListTypeCell.swift in Sources */,
|
C44067F927E2585E0045BD4E /* DomainListTypeCell.swift in Sources */,
|
||||||
54D9E0BA27E4F51E003B9AD9 /* ModifierFlagsExtension.swift in Sources */,
|
54D9E0BA27E4F51E003B9AD9 /* ModifierFlagsExtension.swift in Sources */,
|
||||||
C4C3ED412783497000AB15D8 /* MainMenu+Startup.swift in Sources */,
|
C4C3ED412783497000AB15D8 /* MainMenu+Startup.swift in Sources */,
|
||||||
|
C40508AF28ADA23D008FAC1F /* NoDomainResultsView.swift in Sources */,
|
||||||
C4D89BC62783C99400A02B68 /* ComposerJson.swift in Sources */,
|
C4D89BC62783C99400A02B68 /* ComposerJson.swift in Sources */,
|
||||||
C46FA23F246C358E00944F05 /* StringExtension.swift in Sources */,
|
C46FA23F246C358E00944F05 /* StringExtension.swift in Sources */,
|
||||||
C42E3BF428A9BF5100AFECFC /* Shell+PATH.swift in Sources */,
|
C42E3BF428A9BF5100AFECFC /* Shell+PATH.swift in Sources */,
|
||||||
@@ -1484,10 +1507,12 @@
|
|||||||
C4FC21B128391F8E00D368BB /* MainMenu+Actions.swift in Sources */,
|
C4FC21B128391F8E00D368BB /* MainMenu+Actions.swift in Sources */,
|
||||||
54D9E0B927E4F51E003B9AD9 /* KeyCombo.swift in Sources */,
|
54D9E0B927E4F51E003B9AD9 /* KeyCombo.swift in Sources */,
|
||||||
C4EED88A27A48778006D7272 /* InterAppHandler.swift in Sources */,
|
C4EED88A27A48778006D7272 /* InterAppHandler.swift in Sources */,
|
||||||
|
C450C8C728C919EC002A2B4B /* PreferenceName.swift in Sources */,
|
||||||
C48D6C75279CD3E400F26D7E /* PhpVersionNumberTest.swift in Sources */,
|
C48D6C75279CD3E400F26D7E /* PhpVersionNumberTest.swift in Sources */,
|
||||||
C485707B28BF458900539B36 /* VersionPopoverView.swift in Sources */,
|
C485707B28BF458900539B36 /* VersionPopoverView.swift in Sources */,
|
||||||
C485706E28BF451C00539B36 /* OnboardingWindowController.swift in Sources */,
|
C485706E28BF451C00539B36 /* OnboardingWindowController.swift in Sources */,
|
||||||
C43603A1275E67610028EFC6 /* AppDelegate+Notifications.swift in Sources */,
|
C43603A1275E67610028EFC6 /* AppDelegate+Notifications.swift in Sources */,
|
||||||
|
C4C3643A28AE4FCE00C0770E /* StatusMenu+Items.swift in Sources */,
|
||||||
C42759682627662800093CAE /* NSMenuExtension.swift in Sources */,
|
C42759682627662800093CAE /* NSMenuExtension.swift in Sources */,
|
||||||
C4D936CB27E3EE4A00BD69FE /* DomainListCellProtocol.swift in Sources */,
|
C4D936CB27E3EE4A00BD69FE /* DomainListCellProtocol.swift in Sources */,
|
||||||
C4B97B76275CF08C003F3378 /* AppDelegate+MenuOutlets.swift in Sources */,
|
C4B97B76275CF08C003F3378 /* AppDelegate+MenuOutlets.swift in Sources */,
|
||||||
@@ -1500,7 +1525,6 @@
|
|||||||
C4068CAB27B0890D00544CD5 /* MenuBarIcons.swift in Sources */,
|
C4068CAB27B0890D00544CD5 /* MenuBarIcons.swift in Sources */,
|
||||||
C40C5C9D2846A40600E28255 /* Preset.swift in Sources */,
|
C40C5C9D2846A40600E28255 /* Preset.swift in Sources */,
|
||||||
C4F30B09278E1A0E00755FCE /* CustomPrefs.swift in Sources */,
|
C4F30B09278E1A0E00755FCE /* CustomPrefs.swift in Sources */,
|
||||||
C42800AB28452AA50099C999 /* StatusMenu+Items.swift in Sources */,
|
|
||||||
C40FE738282ABA4F00A302C2 /* AppVersion.swift in Sources */,
|
C40FE738282ABA4F00A302C2 /* AppVersion.swift in Sources */,
|
||||||
C415D3E92770F692005EF286 /* AppDelegate+InterApp.swift in Sources */,
|
C415D3E92770F692005EF286 /* AppDelegate+InterApp.swift in Sources */,
|
||||||
C484437C2804BB560041A78A /* ValetProxyScanner.swift in Sources */,
|
C484437C2804BB560041A78A /* ValetProxyScanner.swift in Sources */,
|
||||||
@@ -1536,6 +1560,7 @@
|
|||||||
C4F30B0B278E203C00755FCE /* MainMenu+Startup.swift in Sources */,
|
C4F30B0B278E203C00755FCE /* MainMenu+Startup.swift in Sources */,
|
||||||
C485707C28BF459500539B36 /* NoWarningsView.swift in Sources */,
|
C485707C28BF459500539B36 /* NoWarningsView.swift in Sources */,
|
||||||
C4F5FBCD28218CB8001065C5 /* Xdebug.swift in Sources */,
|
C4F5FBCD28218CB8001065C5 /* Xdebug.swift in Sources */,
|
||||||
|
C4D27F25292BDF630081B38F /* Homebrew.swift in Sources */,
|
||||||
C40B24F227A310770018C7D2 /* Events.swift in Sources */,
|
C40B24F227A310770018C7D2 /* Events.swift in Sources */,
|
||||||
C4F30B0A278E1A1A00755FCE /* ComposerJson.swift in Sources */,
|
C4F30B0A278E1A1A00755FCE /* ComposerJson.swift in Sources */,
|
||||||
C4C0E8E027F88AEB002D32A9 /* FakeSiteScanner.swift in Sources */,
|
C4C0E8E027F88AEB002D32A9 /* FakeSiteScanner.swift in Sources */,
|
||||||
@@ -1558,6 +1583,7 @@
|
|||||||
C4B5853F2770FE3900DA4FBE /* Paths.swift in Sources */,
|
C4B5853F2770FE3900DA4FBE /* Paths.swift in Sources */,
|
||||||
C481F79A26164A7C004FBCFF /* Preferences.swift in Sources */,
|
C481F79A26164A7C004FBCFF /* Preferences.swift in Sources */,
|
||||||
C4E0F7EE27BEBDA9007475F2 /* NSWindowExtension.swift in Sources */,
|
C4E0F7EE27BEBDA9007475F2 /* NSWindowExtension.swift in Sources */,
|
||||||
|
C4A81CA528C67101008DD9D1 /* PMTableView.swift in Sources */,
|
||||||
C4B585422770FE3900DA4FBE /* Shell.swift in Sources */,
|
C4B585422770FE3900DA4FBE /* Shell.swift in Sources */,
|
||||||
C45E76152854A65300B4FE0C /* ServicesManager.swift in Sources */,
|
C45E76152854A65300B4FE0C /* ServicesManager.swift in Sources */,
|
||||||
C464ADAD275A7A3F003FCD53 /* DomainListWindowController.swift in Sources */,
|
C464ADAD275A7A3F003FCD53 /* DomainListWindowController.swift in Sources */,
|
||||||
@@ -1628,6 +1654,7 @@
|
|||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
CODE_SIGN_IDENTITY = "Mac Developer";
|
CODE_SIGN_IDENTITY = "Mac Developer";
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
|
DEAD_CODE_STRIPPING = YES;
|
||||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
ENABLE_TESTABILITY = YES;
|
ENABLE_TESTABILITY = YES;
|
||||||
@@ -1690,6 +1717,7 @@
|
|||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
CODE_SIGN_IDENTITY = "Mac Developer";
|
CODE_SIGN_IDENTITY = "Mac Developer";
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
|
DEAD_CODE_STRIPPING = YES;
|
||||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
ENABLE_NS_ASSERTIONS = NO;
|
ENABLE_NS_ASSERTIONS = NO;
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
@@ -1719,7 +1747,8 @@
|
|||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 955;
|
CURRENT_PROJECT_VERSION = 991;
|
||||||
|
DEAD_CODE_STRIPPING = YES;
|
||||||
DEBUG = YES;
|
DEBUG = YES;
|
||||||
DEVELOPMENT_TEAM = 8M54J5J787;
|
DEVELOPMENT_TEAM = 8M54J5J787;
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
@@ -1729,7 +1758,7 @@
|
|||||||
"@executable_path/../Frameworks",
|
"@executable_path/../Frameworks",
|
||||||
);
|
);
|
||||||
MACOSX_DEPLOYMENT_TARGET = 11.0;
|
MACOSX_DEPLOYMENT_TARGET = 11.0;
|
||||||
MARKETING_VERSION = 5.5.1;
|
MARKETING_VERSION = 5.6.5;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon;
|
PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
@@ -1746,7 +1775,8 @@
|
|||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 955;
|
CURRENT_PROJECT_VERSION = 991;
|
||||||
|
DEAD_CODE_STRIPPING = YES;
|
||||||
DEBUG = NO;
|
DEBUG = NO;
|
||||||
DEVELOPMENT_TEAM = 8M54J5J787;
|
DEVELOPMENT_TEAM = 8M54J5J787;
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
@@ -1756,7 +1786,7 @@
|
|||||||
"@executable_path/../Frameworks",
|
"@executable_path/../Frameworks",
|
||||||
);
|
);
|
||||||
MACOSX_DEPLOYMENT_TARGET = 11.0;
|
MACOSX_DEPLOYMENT_TARGET = 11.0;
|
||||||
MARKETING_VERSION = 5.5.1;
|
MARKETING_VERSION = 5.6.5;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon;
|
PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
@@ -1769,6 +1799,7 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
|
DEAD_CODE_STRIPPING = YES;
|
||||||
DEVELOPMENT_TEAM = 8M54J5J787;
|
DEVELOPMENT_TEAM = 8M54J5J787;
|
||||||
INFOPLIST_FILE = "phpmon-tests/Info.plist";
|
INFOPLIST_FILE = "phpmon-tests/Info.plist";
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
@@ -1788,6 +1819,7 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
|
DEAD_CODE_STRIPPING = YES;
|
||||||
DEVELOPMENT_TEAM = 8M54J5J787;
|
DEVELOPMENT_TEAM = 8M54J5J787;
|
||||||
INFOPLIST_FILE = "phpmon-tests/Info.plist";
|
INFOPLIST_FILE = "phpmon-tests/Info.plist";
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Scheme
|
<Scheme
|
||||||
LastUpgradeVersion = "1320"
|
LastUpgradeVersion = "1400"
|
||||||
version = "1.3">
|
version = "1.3">
|
||||||
<BuildAction
|
<BuildAction
|
||||||
parallelizeBuildables = "YES"
|
parallelizeBuildables = "YES"
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
> **Note**
|
> **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 leaving [a one-time donation](https://nicoverbruggen.be/sponsor) to support the project, as this is something I make in my free time. **Thank you!** ⭐️
|
> 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.png" alt="PHP Monitor Logo" width="500px" /></p>
|
||||||
|
|
||||||
@@ -88,7 +88,8 @@ If you're still having issues, here's a few common questions & answers, as well
|
|||||||
<li>PHP 7.4</li>
|
<li>PHP 7.4</li>
|
||||||
<li>PHP 8.0</li>
|
<li>PHP 8.0</li>
|
||||||
<li>PHP 8.1</li>
|
<li>PHP 8.1</li>
|
||||||
<li>PHP 8.2 (experimental)</li>
|
<li>PHP 8.2</li>
|
||||||
|
<li>PHP 8.3 (experimental)</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
For more details, consult the [constants file](https://github.com/nicoverbruggen/phpmon/blob/main/phpmon/Common/Core/Constants.swift#L16) file to see which versions are supported.
|
For more details, consult the [constants file](https://github.com/nicoverbruggen/phpmon/blob/main/phpmon/Common/Core/Constants.swift#L16) file to see which versions are supported.
|
||||||
@@ -98,7 +99,9 @@ For more details, consult the [constants file](https://github.com/nicoverbruggen
|
|||||||
<details>
|
<details>
|
||||||
<summary><strong>I want PHP Monitor to start up when I boot my Mac!</strong></summary>
|
<summary><strong>I want PHP Monitor to start up when I boot my Mac!</strong></summary>
|
||||||
|
|
||||||
You can do this by dragging *PHP Monitor.app* into the **Login Items** section in **System Preferences > Users & Groups** for your account.
|
On macOS Ventura, you can accomplish this by going to **System Settings > General > Login Items** and adding PHP Monitor.app to the list **Open at Login**. You can do this with any application, by the way.
|
||||||
|
|
||||||
|
On older versions of macOS, you can do this by dragging *PHP Monitor.app* into the **Login Items** section in **System Preferences > Users & Groups** for your account.
|
||||||
|
|
||||||
Super convenient!
|
Super convenient!
|
||||||
</details>
|
</details>
|
||||||
|
@@ -6,9 +6,7 @@ Generally speaking, only the latest version of **PHP Monitor** is supported, exc
|
|||||||
|
|
||||||
| Version | Apple Silicon | Supported | Supported macOS | Deployment Target | Detected PHP Versions | Recommended Valet Version |
|
| Version | Apple Silicon | Supported | Supported macOS | Deployment Target | Detected PHP Versions | Recommended Valet Version |
|
||||||
| ------- | ------------- | ------------------ | ----- | ----- | ----- | ----
|
| ------- | ------------- | ------------------ | ----- | ----- | ----- | ----
|
||||||
| 5.x | ✅ Universal binary | ✅ Yes | Big Sur (11.0)<br/>Monterey (12.0)<br/>Ventura (13.0)* | macOS 11+ | PHP 5.6—PHP 8.2 (w/ Valet 2.x)<br/>PHP 7.0—PHP 8.2 (w/ Valet 3.x) | 3.0 recommended<br/> 2.16.2 minimum |
|
| 5.x | ✅ Universal binary | ✅ Yes | Big Sur (11.0)<br/>Monterey (12.0)<br/>Ventura (13.0) | macOS 11+ | PHP 5.6—PHP 8.2 (w/ Valet 2.x)<br/>PHP 7.0—PHP 8.2 (w/ Valet 3.x) | 3.0 recommended<br/> 2.16.2 minimum |
|
||||||
|
|
||||||
_(*) macOS Ventura (13.0) is not officially supported until it officially releases._
|
|
||||||
|
|
||||||
## Legacy versions
|
## Legacy versions
|
||||||
|
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 454 KiB After Width: | Height: | Size: 524 KiB |
Binary file not shown.
Before Width: | Height: | Size: 469 KiB After Width: | Height: | Size: 519 KiB |
@@ -18,4 +18,30 @@ class AppUpdaterCheckTest: XCTestCase {
|
|||||||
XCTAssertNotNil(version)
|
XCTAssertNotNil(version)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testTaggedReleaseOmitsZeroPatch() {
|
||||||
|
let version = AppVersion.from("3.5.0_333")!
|
||||||
|
|
||||||
|
XCTAssertEqual(version.tagged, "3.5")
|
||||||
|
XCTAssertEqual(version.version, "3.5.0")
|
||||||
|
}
|
||||||
|
|
||||||
|
func testTaggedReleaseDoesntOmitNonZeroPatch() {
|
||||||
|
let version = AppVersion.from("3.5.1_333")!
|
||||||
|
|
||||||
|
XCTAssertEqual(version.tagged, "3.5.1")
|
||||||
|
XCTAssertEqual(version.version, "3.5.1")
|
||||||
|
}
|
||||||
|
|
||||||
|
func testTagTruncationDoesntAffectMajorVersions() {
|
||||||
|
var version = AppVersion.from("5.0_333")!
|
||||||
|
|
||||||
|
XCTAssertEqual(version.tagged, "5.0")
|
||||||
|
XCTAssertEqual(version.version, "5.0")
|
||||||
|
|
||||||
|
version = AppVersion.from("5.0.0_333")!
|
||||||
|
|
||||||
|
XCTAssertEqual(version.tagged, "5.0")
|
||||||
|
XCTAssertEqual(version.version, "5.0.0")
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
import XCTest
|
import XCTest
|
||||||
|
|
||||||
|
// swiftlint:disable type_body_length
|
||||||
class PhpVersionNumberTest: XCTestCase {
|
class PhpVersionNumberTest: XCTestCase {
|
||||||
|
|
||||||
func testCanDeconstructPhpVersion() throws {
|
func testCanDeconstructPhpVersion() throws {
|
||||||
@@ -287,4 +288,76 @@ class PhpVersionNumberTest: XCTestCase {
|
|||||||
.make(from: ["7.3.1", "7.2.9"]).all
|
.make(from: ["7.3.1", "7.2.9"]).all
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testCanCheckLessThanOrEqualConstraints() throws {
|
||||||
|
XCTAssertEqual(
|
||||||
|
PhpVersionNumberCollection
|
||||||
|
.make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"])
|
||||||
|
.matching(constraint: "<=7.2", strict: true),
|
||||||
|
PhpVersionNumberCollection
|
||||||
|
.make(from: ["7.2", "7.1", "7.0"]).all
|
||||||
|
)
|
||||||
|
|
||||||
|
XCTAssertEqual(
|
||||||
|
PhpVersionNumberCollection
|
||||||
|
.make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"])
|
||||||
|
.matching(constraint: "<=7.2.0", strict: true),
|
||||||
|
PhpVersionNumberCollection
|
||||||
|
.make(from: ["7.2", "7.1", "7.0"]).all
|
||||||
|
)
|
||||||
|
|
||||||
|
// Strict check (>7.2.5 is too new for 7.2 which resolves to 7.2.0)
|
||||||
|
XCTAssertEqual(
|
||||||
|
PhpVersionNumberCollection
|
||||||
|
.make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"])
|
||||||
|
.matching(constraint: "<=7.2.5", strict: true),
|
||||||
|
PhpVersionNumberCollection
|
||||||
|
.make(from: ["7.2", "7.1", "7.0"]).all
|
||||||
|
)
|
||||||
|
|
||||||
|
// Non-strict check (ignoring patch has no effect)
|
||||||
|
XCTAssertEqual(
|
||||||
|
PhpVersionNumberCollection
|
||||||
|
.make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"])
|
||||||
|
.matching(constraint: "<=7.2.5", strict: false),
|
||||||
|
PhpVersionNumberCollection
|
||||||
|
.make(from: ["7.2", "7.1", "7.0"]).all
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testCanCheckLessThanConstraints() throws {
|
||||||
|
XCTAssertEqual(
|
||||||
|
PhpVersionNumberCollection
|
||||||
|
.make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"])
|
||||||
|
.matching(constraint: "<7.2", strict: true),
|
||||||
|
PhpVersionNumberCollection
|
||||||
|
.make(from: ["7.1", "7.0"]).all
|
||||||
|
)
|
||||||
|
|
||||||
|
XCTAssertEqual(
|
||||||
|
PhpVersionNumberCollection
|
||||||
|
.make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"])
|
||||||
|
.matching(constraint: "<7.2.0", strict: true),
|
||||||
|
PhpVersionNumberCollection
|
||||||
|
.make(from: ["7.1", "7.0"]).all
|
||||||
|
)
|
||||||
|
|
||||||
|
// Strict check (>7.2.5 is too new for 7.2 which resolves to 7.2.0)
|
||||||
|
XCTAssertEqual(
|
||||||
|
PhpVersionNumberCollection
|
||||||
|
.make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"])
|
||||||
|
.matching(constraint: "<7.2.5", strict: true),
|
||||||
|
PhpVersionNumberCollection
|
||||||
|
.make(from: ["7.2", "7.1", "7.0"]).all
|
||||||
|
)
|
||||||
|
|
||||||
|
// Non-strict check (patch resolves to 7.2.999, which is bigger than 7.2.5)
|
||||||
|
XCTAssertEqual(
|
||||||
|
PhpVersionNumberCollection
|
||||||
|
.make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"])
|
||||||
|
.matching(constraint: "<7.2.5", strict: false),
|
||||||
|
PhpVersionNumberCollection
|
||||||
|
.make(from: ["7.1", "7.0"]).all
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -13,37 +13,35 @@ class Actions {
|
|||||||
// MARK: - Services
|
// MARK: - Services
|
||||||
|
|
||||||
public static func restartPhpFpm() {
|
public static func restartPhpFpm() {
|
||||||
brew("services restart \(PhpEnv.phpInstall.formula)", sudo: true)
|
brew("services restart \(Homebrew.Formulae.php)", sudo: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func restartNginx() {
|
public static func restartNginx() {
|
||||||
brew("services restart nginx", sudo: true)
|
brew("services restart \(Homebrew.Formulae.nginx)", sudo: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func restartDnsMasq() {
|
public static func restartDnsMasq() {
|
||||||
brew("services restart dnsmasq", sudo: true)
|
brew("services restart \(Homebrew.Formulae.dnsmasq)", sudo: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func stopValetServices() {
|
public static func stopValetServices() {
|
||||||
brew("services stop \(PhpEnv.phpInstall.formula)", sudo: true)
|
brew("services stop \(Homebrew.Formulae.php)", sudo: true)
|
||||||
brew("services stop nginx", sudo: true)
|
brew("services stop \(Homebrew.Formulae.nginx)", sudo: true)
|
||||||
brew("services stop dnsmasq", sudo: true)
|
brew("services stop \(Homebrew.Formulae.dnsmasq)", sudo: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func fixHomebrewPermissions() throws {
|
public static func fixHomebrewPermissions() throws {
|
||||||
var servicesCommands = [
|
var servicesCommands = [
|
||||||
"\(Paths.brew) services stop nginx",
|
"\(Paths.brew) services stop \(Homebrew.Formulae.nginx)",
|
||||||
"\(Paths.brew) services stop dnsmasq"
|
"\(Paths.brew) services stop \(Homebrew.Formulae.dnsmasq)"
|
||||||
]
|
]
|
||||||
var cellarCommands = [
|
var cellarCommands = [
|
||||||
"chown -R \(Paths.whoami):admin \(Paths.cellarPath)/nginx",
|
"chown -R \(Paths.whoami):admin \(Paths.cellarPath)/\(Homebrew.Formulae.nginx)",
|
||||||
"chown -R \(Paths.whoami):admin \(Paths.cellarPath)/dnsmasq"
|
"chown -R \(Paths.whoami):admin \(Paths.cellarPath)/\(Homebrew.Formulae.dnsmasq)"
|
||||||
]
|
]
|
||||||
|
|
||||||
PhpEnv.shared.availablePhpVersions.forEach { version in
|
PhpEnv.shared.availablePhpVersions.forEach { version in
|
||||||
let formula = version == PhpEnv.brewPhpVersion
|
let formula = version == PhpEnv.brewPhpVersion ? "php" : "php@\(version)"
|
||||||
? "php"
|
|
||||||
: "php@\(version)"
|
|
||||||
servicesCommands.append("\(Paths.brew) services stop \(formula)")
|
servicesCommands.append("\(Paths.brew) services stop \(formula)")
|
||||||
cellarCommands.append("chown -R \(Paths.whoami):admin \(Paths.cellarPath)/\(formula)")
|
cellarCommands.append("chown -R \(Paths.whoami):admin \(Paths.cellarPath)/\(formula)")
|
||||||
}
|
}
|
||||||
@@ -145,9 +143,9 @@ class Actions {
|
|||||||
*/
|
*/
|
||||||
public static func fixMyValet(completed: @escaping () -> Void) {
|
public static func fixMyValet(completed: @escaping () -> Void) {
|
||||||
InternalSwitcher().performSwitch(to: PhpEnv.brewPhpVersion, completion: {
|
InternalSwitcher().performSwitch(to: PhpEnv.brewPhpVersion, completion: {
|
||||||
brew("services restart dnsmasq", sudo: true)
|
brew("services restart \(Homebrew.Formulae.dnsmasq)", sudo: true)
|
||||||
brew("services restart php", sudo: true)
|
brew("services restart \(Homebrew.Formulae.php)", sudo: true)
|
||||||
brew("services restart nginx", sudo: true)
|
brew("services restart \(Homebrew.Formulae.nginx)", sudo: true)
|
||||||
completed()
|
completed()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@@ -9,12 +9,6 @@ import Cocoa
|
|||||||
|
|
||||||
struct Constants {
|
struct Constants {
|
||||||
|
|
||||||
/**
|
|
||||||
* The latest PHP version that is considered to be stable at the time of release.
|
|
||||||
* This version number is currently not used (only as a default fallback).
|
|
||||||
*/
|
|
||||||
static let LatestStablePhpVersion = "8.1"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The minimum version of Valet that is recommended.
|
The minimum version of Valet that is recommended.
|
||||||
If the installed version is older, a notification will be shown
|
If the installed version is older, a notification will be shown
|
||||||
@@ -42,29 +36,34 @@ struct Constants {
|
|||||||
"7.4",
|
"7.4",
|
||||||
"8.0",
|
"8.0",
|
||||||
"8.1",
|
"8.1",
|
||||||
|
"8.2",
|
||||||
|
|
||||||
// ====================
|
// ====================
|
||||||
// EXPERIMENTAL SUPPORT
|
// EXPERIMENTAL SUPPORT
|
||||||
// ====================
|
// ====================
|
||||||
// Every release that supports the next release will always support the next
|
// Every release that supports the next release will always support the next
|
||||||
// dev release. In this case, that means that the version below is detected.
|
// dev release. In this case, that means that the version below is detected.
|
||||||
"8.2"
|
"8.3"
|
||||||
]
|
]
|
||||||
|
|
||||||
struct Urls {
|
struct Urls {
|
||||||
|
|
||||||
static let DonationPayment = URL(
|
// phpmon.app URLs (these are aliased to redirect correctly)
|
||||||
string: "https://nicoverbruggen.be/sponsor#pay-now"
|
|
||||||
)!
|
|
||||||
|
|
||||||
static let DonationPage = URL(
|
static let DonationPage = URL(
|
||||||
string: "https://nicoverbruggen.be/sponsor"
|
string: "https://phpmon.app/sponsor"
|
||||||
)!
|
)!
|
||||||
|
|
||||||
static let FrequentlyAskedQuestions = URL(
|
static let FrequentlyAskedQuestions = URL(
|
||||||
string: "https://github.com/nicoverbruggen/phpmon#%EF%B8%8F-faq--troubleshooting"
|
string: "https://phpmon.app/faq"
|
||||||
)!
|
)!
|
||||||
|
|
||||||
|
static let DonationPayment = URL(
|
||||||
|
string: "https://phpmon.app/sponsor/now"
|
||||||
|
)!
|
||||||
|
|
||||||
|
// GitHub URLs (do not alias these)
|
||||||
|
|
||||||
static let GitHubReleases = URL(
|
static let GitHubReleases = URL(
|
||||||
string: "https://github.com/nicoverbruggen/phpmon/releases"
|
string: "https://github.com/nicoverbruggen/phpmon/releases"
|
||||||
)!
|
)!
|
||||||
|
25
phpmon/Common/Core/Homebrew.swift
Normal file
25
phpmon/Common/Core/Homebrew.swift
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
//
|
||||||
|
// Homebrew.swift
|
||||||
|
// PHP Monitor
|
||||||
|
//
|
||||||
|
// Created by Nico Verbruggen on 21/11/2022.
|
||||||
|
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
class Homebrew {
|
||||||
|
struct Formulae {
|
||||||
|
static var php: String {
|
||||||
|
return PhpEnv.phpInstall.formula
|
||||||
|
}
|
||||||
|
|
||||||
|
static var nginx: String {
|
||||||
|
return HomebrewDiagnostics.usesNginxFullFormula ? "nginx-full" : "nginx"
|
||||||
|
}
|
||||||
|
|
||||||
|
static var dnsmasq: String {
|
||||||
|
return "dnsmasq"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -14,12 +14,18 @@ extension Shell {
|
|||||||
let task = Process()
|
let task = Process()
|
||||||
task.launchPath = "/bin/zsh"
|
task.launchPath = "/bin/zsh"
|
||||||
|
|
||||||
// We need an interactive shell so the user's PATH is loaded in correctly
|
let command = Filesystem.fileExists("~/.zshrc")
|
||||||
task.arguments = ["--login", "-ilc", "echo $PATH"]
|
// source the user's .zshrc file if it exists to complete $PATH
|
||||||
|
? ". ~/.zshrc && echo $PATH"
|
||||||
|
// otherwise, non-interactive mode is sufficient
|
||||||
|
: "echo $PATH"
|
||||||
|
|
||||||
|
task.arguments = ["--login", "-lc", command]
|
||||||
|
|
||||||
let pipe = Pipe()
|
let pipe = Pipe()
|
||||||
task.standardOutput = pipe
|
task.standardOutput = pipe
|
||||||
task.launch()
|
task.launch()
|
||||||
|
|
||||||
let data = pipe.fileHandleForReading.readDataToEndOfFile()
|
let data = pipe.fileHandleForReading.readDataToEndOfFile()
|
||||||
|
|
||||||
return String(data: data, encoding: String.Encoding.utf8) ?? ""
|
return String(data: data, encoding: String.Encoding.utf8) ?? ""
|
||||||
|
@@ -9,43 +9,17 @@
|
|||||||
import Cocoa
|
import Cocoa
|
||||||
|
|
||||||
extension NSMenu {
|
extension NSMenu {
|
||||||
|
convenience init(items: [NSMenuItem], target: NSObject? = nil) {
|
||||||
open func addItem(_ newItem: NSMenuItem, withKeyModifier modifier: NSEvent.ModifierFlags) {
|
self.init()
|
||||||
newItem.keyEquivalentModifierMask = modifier
|
self.addItems(items, target: target)
|
||||||
self.addItem(newItem)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
public func addItems(_ items: [NSMenuItem], target: NSObject? = nil) {
|
||||||
|
for item in items {
|
||||||
@IBDesignable class LocalizedMenuItem: NSMenuItem {
|
self.addItem(item)
|
||||||
|
if target != nil {
|
||||||
@IBInspectable
|
item.target = target
|
||||||
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?
|
|
||||||
}
|
}
|
||||||
|
87
phpmon/Common/Extensions/NSMenuItemExtension.swift
Normal file
87
phpmon/Common/Extensions/NSMenuItemExtension.swift
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
//
|
||||||
|
// 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? = nil
|
||||||
|
) {
|
||||||
|
self.init(title: title, action: action, keyEquivalent: keyEquivalent)
|
||||||
|
self.keyEquivalentModifierMask = keyModifier
|
||||||
|
self.toolTip = toolTip
|
||||||
|
}
|
||||||
|
|
||||||
|
convenience init(
|
||||||
|
title: String,
|
||||||
|
keyEquivalent: String = "",
|
||||||
|
keyModifier: NSEvent.ModifierFlags = [],
|
||||||
|
toolTip: String? = nil,
|
||||||
|
submenu: [NSMenuItem],
|
||||||
|
target: NSObject? = nil
|
||||||
|
) {
|
||||||
|
self.init(title: title, action: nil, keyEquivalent: keyEquivalent)
|
||||||
|
self.keyEquivalentModifierMask = keyModifier
|
||||||
|
self.toolTip = toolTip
|
||||||
|
self.submenu = NSMenu(items: submenu, target: target)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - NSMenuItem subclasses
|
||||||
|
|
||||||
|
@IBDesignable class LocalizedMenuItem: NSMenuItem {
|
||||||
|
@IBInspectable var localizationKey: String? {
|
||||||
|
didSet {
|
||||||
|
self.title = localizationKey?.localized ?? self.title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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?
|
||||||
|
|
||||||
|
static func getAll() -> [NSMenuItem] {
|
||||||
|
return Preferences.custom.presets!.map { preset in
|
||||||
|
let presetMenuItem = PresetMenuItem(
|
||||||
|
title: preset.getMenuItemText(),
|
||||||
|
action: #selector(MainMenu.togglePreset(sender:))
|
||||||
|
)
|
||||||
|
|
||||||
|
if let attributedString = try? NSMutableAttributedString(
|
||||||
|
data: preset.getMenuItemText().data(using: .utf8)!,
|
||||||
|
options: [.documentType: NSAttributedString.DocumentType.html],
|
||||||
|
documentAttributes: nil
|
||||||
|
) {
|
||||||
|
presetMenuItem.attributedTitle = attributedString
|
||||||
|
}
|
||||||
|
|
||||||
|
presetMenuItem.preset = preset
|
||||||
|
return presetMenuItem
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -30,7 +30,7 @@ class PMWindowController: NSWindowController, NSWindowDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
Log.perf("Window controller '\(windowName)' was deinitialized")
|
Log.perf("deinit: \(String(describing: self)).\(#function)")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
import Cocoa
|
||||||
|
|
||||||
class Xdebug {
|
class Xdebug {
|
||||||
|
|
||||||
@@ -26,6 +27,26 @@ class Xdebug {
|
|||||||
return value.components(separatedBy: ",").filter { self.modes.contains($0) }
|
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] {
|
public static var modes: [String] {
|
||||||
return [
|
return [
|
||||||
"develop",
|
"develop",
|
||||||
|
@@ -87,6 +87,14 @@ public struct PhpVersionNumberCollection: Equatable {
|
|||||||
return self.versions.filter { $0.isNewerThan(version, strict) }
|
return self.versions.filter { $0.isNewerThan(version, strict) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let version = PhpVersionNumber.make(from: constraint, type: .smallerThanOrEqual) {
|
||||||
|
return self.versions.filter { $0.isSameAs(version, strict) || $0.isOlderThan(version, strict)}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let version = PhpVersionNumber.make(from: constraint, type: .smallerThan) {
|
||||||
|
return self.versions.filter { $0.isOlderThan(version, strict)}
|
||||||
|
}
|
||||||
|
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -116,12 +124,8 @@ public struct PhpVersionNumber: Equatable, Hashable {
|
|||||||
case tildeVersionRange = #"^~(?<major>\d+).(?<minor>\d+).?(?<patch>\d+)?\z"#
|
case tildeVersionRange = #"^~(?<major>\d+).(?<minor>\d+).?(?<patch>\d+)?\z"#
|
||||||
case greaterThanOrEqual = #"^>=(?<major>\d+).(?<minor>\d+).?(?<patch>\d+)?\z"#
|
case greaterThanOrEqual = #"^>=(?<major>\d+).(?<minor>\d+).?(?<patch>\d+)?\z"#
|
||||||
case greaterThan = #"^>(?<major>\d+).(?<minor>\d+).?(?<patch>\d+)?\z"#
|
case greaterThan = #"^>(?<major>\d+).(?<minor>\d+).?(?<patch>\d+)?\z"#
|
||||||
|
|
||||||
// TODO: (6.0) Handle these cases (even though I suspect these are uncommon)
|
|
||||||
/*
|
|
||||||
case smallerThanOrEqual = #"^<=(?<major>\d+).(?<minor>\d+).?(?<patch>\d+)?\z"#
|
case smallerThanOrEqual = #"^<=(?<major>\d+).(?<minor>\d+).?(?<patch>\d+)?\z"#
|
||||||
case smallerThan = #"^<(?<major>\d+).(?<minor>\d+).?(?<patch>\d+)?\z"#
|
case smallerThan = #"^<(?<major>\d+).(?<minor>\d+).?(?<patch>\d+)?\z"#
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func parse(_ text: String) throws -> Self {
|
public static func parse(_ text: String) throws -> Self {
|
||||||
@@ -175,6 +179,15 @@ public struct PhpVersionNumber: Equatable, Hashable {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal func isOlderThan(_ version: PhpVersionNumber, _ strict: Bool) -> Bool {
|
||||||
|
return (
|
||||||
|
self.major < version.major ||
|
||||||
|
self.major == version.major && self.minor < version.minor ||
|
||||||
|
self.major == version.major && self.minor == version.minor
|
||||||
|
&& self.patch(strict) < version.patch(strict)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
internal func hasNewerMinorVersionOrPatch(_ version: PhpVersionNumber, _ strict: Bool) -> Bool {
|
internal func hasNewerMinorVersionOrPatch(_ version: PhpVersionNumber, _ strict: Bool) -> Bool {
|
||||||
return self.major == version.major &&
|
return self.major == version.major &&
|
||||||
(
|
(
|
||||||
|
@@ -63,10 +63,8 @@ class PhpConfigurationFile: CreatedFromFile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func getConfig(for key: String) -> ConfigValue? {
|
public func getConfig(for key: String) -> ConfigValue? {
|
||||||
for (_, section) in self.content {
|
for (_, section) in self.content where section.keys.contains(key) {
|
||||||
if section.keys.contains(key) {
|
return section[key]!
|
||||||
return section[key]!
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@@ -46,7 +46,7 @@ class InternalSwitcher: PhpSwitcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Log.info("Restarting nginx, just to be sure!")
|
Log.info("Restarting nginx, just to be sure!")
|
||||||
brew("services restart nginx", sudo: true)
|
brew("services restart \(Homebrew.Formulae.nginx)", sudo: true)
|
||||||
|
|
||||||
Log.info("The new version(s) have been linked!")
|
Log.info("The new version(s) have been linked!")
|
||||||
completion()
|
completion()
|
||||||
|
@@ -13,9 +13,9 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<br>
|
<br>
|
||||||
<p><b>Do you enjoy using the app?</b> Leave a <a href="https://github.com/nicoverbruggen/phpmon">star on GitHub</a>!</p>
|
<p><b>Do you enjoy using the app?</b> Leave a <a href="https://phpmon.app/github">star on GitHub</a>!</p>
|
||||||
<p><b>Having issues?</b> Consult the <a href="https://github.com/nicoverbruggen/phpmon#%EF%B8%8F-faq--troubleshooting">FAQ</a> section, I did my best to ensure everything is documented.</p>
|
<p><b>Having issues?</b> Consult the <a href="https://phpmon.app/faq">FAQ</a> section, I did my best to ensure everything is documented.</p>
|
||||||
<p><b>Want to support further development of PHP Monitor?</b> You can <a href="https://nicoverbruggen.be/sponsor">financially support</a> the continued development of this app.</p>
|
<p><b>Want to support further development of PHP Monitor?</b> You can <a href="https://phpmon.app/sponsor">financially support</a> the continued development of this app.</p>
|
||||||
<p><b>Get the latest on Twitter</b> Give me a <a href="https://twitter.com/nicoverbruggen">follow on Twitter</a> to learn about the latest and greatest updates of this app.</p>
|
<p><b>Get the latest on Twitter</b> Give me a <a href="https://twitter.com/nicoverbruggen">follow on Twitter</a> to learn about the latest and greatest updates of this app.</p>
|
||||||
<br>
|
<br>
|
||||||
</body>
|
</body>
|
||||||
|
@@ -65,7 +65,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
|
|||||||
override init() {
|
override init() {
|
||||||
logger.verbosity = .info
|
logger.verbosity = .info
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
// logger.verbosity = .performance
|
logger.verbosity = .performance
|
||||||
#endif
|
#endif
|
||||||
if CommandLine.arguments.contains("--v") {
|
if CommandLine.arguments.contains("--v") {
|
||||||
logger.verbosity = .performance
|
logger.verbosity = .performance
|
||||||
|
@@ -146,8 +146,9 @@ class AppUpdateChecker {
|
|||||||
text: "updater.alerts.buttons.release_notes".localized,
|
text: "updater.alerts.buttons.release_notes".localized,
|
||||||
action: { vc in
|
action: { vc in
|
||||||
vc.close(with: .OK)
|
vc.close(with: .OK)
|
||||||
|
|
||||||
NSWorkspace.shared.open(
|
NSWorkspace.shared.open(
|
||||||
Constants.Urls.GitHubReleases.appendingPathComponent("/tag/v\(version.version)\(devSuffix)")
|
Constants.Urls.GitHubReleases.appendingPathComponent("/tag/v\(version.tagged)\(devSuffix)")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@@ -66,6 +66,14 @@ class AppVersion {
|
|||||||
return AppVersion.from("\(App.shortVersion)_\(App.bundleVersion)")!
|
return AppVersion.from("\(App.shortVersion)_\(App.bundleVersion)")!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var tagged: String {
|
||||||
|
if version.suffix(2) == ".0" && version.count > 3 {
|
||||||
|
return String(version.dropLast(2))
|
||||||
|
}
|
||||||
|
|
||||||
|
return version
|
||||||
|
}
|
||||||
|
|
||||||
var computerReadable: String {
|
var computerReadable: String {
|
||||||
return "\(version)_\(build ?? "0")"
|
return "\(version)_\(build ?? "0")"
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="20037" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="20037" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
<deployment identifier="macosx"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="20037"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="20037"/>
|
||||||
<capability name="Image references" minToolsVersion="12.0"/>
|
<capability name="Image references" minToolsVersion="12.0"/>
|
||||||
<capability name="Named colors" minToolsVersion="9.0"/>
|
<capability name="Named colors" minToolsVersion="9.0"/>
|
||||||
@@ -818,9 +819,9 @@ Gw
|
|||||||
<rect key="frame" x="0.0" y="0.0" width="626" height="309"/>
|
<rect key="frame" x="0.0" y="0.0" width="626" height="309"/>
|
||||||
<clipView key="contentView" ambiguous="YES" drawsBackground="NO" id="6IL-DW-37w">
|
<clipView key="contentView" ambiguous="YES" drawsBackground="NO" id="6IL-DW-37w">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="626" height="309"/>
|
<rect key="frame" x="0.0" y="0.0" width="626" height="309"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<tableView verticalHuggingPriority="750" ambiguous="YES" allowsExpansionToolTips="YES" multipleSelection="NO" autosaveName="phpmon-sitelist-columns" rowHeight="54" headerView="xUg-Mq-OSh" viewBased="YES" id="cp3-34-pQj">
|
<tableView verticalHuggingPriority="750" ambiguous="YES" allowsExpansionToolTips="YES" multipleSelection="NO" autosaveName="phpmon-sitelist-columns" rowHeight="54" headerView="xUg-Mq-OSh" viewBased="YES" id="cp3-34-pQj" customClass="PMTableView" customModule="PHP_Monitor" customModuleProvider="target">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="626" height="281"/>
|
<rect key="frame" x="0.0" y="0.0" width="626" height="281"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<size key="intercellSpacing" width="17" height="0.0"/>
|
<size key="intercellSpacing" width="17" height="0.0"/>
|
||||||
|
@@ -18,9 +18,9 @@ class ServicesManager: ObservableObject {
|
|||||||
|
|
||||||
public static func loadHomebrewServices(completed: (() -> Void)? = nil) {
|
public static func loadHomebrewServices(completed: (() -> Void)? = nil) {
|
||||||
let rootServiceNames = [
|
let rootServiceNames = [
|
||||||
PhpEnv.phpInstall.formula,
|
Homebrew.Formulae.php,
|
||||||
"nginx",
|
Homebrew.Formulae.nginx,
|
||||||
"dnsmasq"
|
Homebrew.Formulae.dnsmasq
|
||||||
]
|
]
|
||||||
|
|
||||||
DispatchQueue.global(qos: .background).async {
|
DispatchQueue.global(qos: .background).async {
|
||||||
@@ -39,9 +39,7 @@ class ServicesManager: ObservableObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let userServiceNames = Preferences.custom.services else {
|
let userServiceNames = Preferences.custom.services ?? []
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
DispatchQueue.global(qos: .background).async {
|
DispatchQueue.global(qos: .background).async {
|
||||||
let data = Shell
|
let data = Shell
|
||||||
|
@@ -160,7 +160,7 @@ class Startup {
|
|||||||
// Verify if the Homebrew services are running (as root).
|
// Verify if the Homebrew services are running (as root).
|
||||||
// =================================================================================
|
// =================================================================================
|
||||||
EnvironmentCheck(
|
EnvironmentCheck(
|
||||||
command: { return HomebrewDiagnostics.cannotLoadService() },
|
command: { return HomebrewDiagnostics.cannotLoadService("dnsmasq") },
|
||||||
name: "`sudo \(Paths.brew) services info` JSON loaded",
|
name: "`sudo \(Paths.brew) services info` JSON loaded",
|
||||||
titleText: "startup.errors.services_json_error.title".localized,
|
titleText: "startup.errors.services_json_error.title".localized,
|
||||||
subtitleText: "startup.errors.services_json_error.subtitle".localized,
|
subtitleText: "startup.errors.services_json_error.subtitle".localized,
|
||||||
|
@@ -47,7 +47,7 @@ extension DomainListVC {
|
|||||||
let originalSecureStatus = selectedSite!.secured
|
let originalSecureStatus = selectedSite!.secured
|
||||||
let action = selectedSite!.secured ? "unsecure" : "secure"
|
let action = selectedSite!.secured ? "unsecure" : "secure"
|
||||||
let selectedSite = selectedSite!
|
let selectedSite = selectedSite!
|
||||||
let command = "cd '\(selectedSite.absolutePath)' && sudo \(Paths.valet) \(action) && exit;"
|
let command = "sudo \(Paths.valet) \(action) '\(selectedSite.name)' && exit;"
|
||||||
|
|
||||||
waitAndExecute {
|
waitAndExecute {
|
||||||
Shell.run(command, requiresPath: true)
|
Shell.run(command, requiresPath: true)
|
||||||
|
@@ -42,14 +42,15 @@ extension DomainListVC {
|
|||||||
addDisabledIsolation(to: menu)
|
addDisabledIsolation(to: menu)
|
||||||
}
|
}
|
||||||
|
|
||||||
addUnlink(to: menu, with: site)
|
menu.addItem(HeaderView.asMenuItem(text: "domain_list.actions".localized))
|
||||||
addToggleSecure(to: menu, secured: site.secured)
|
addToggleSecure(to: menu, secured: site.secured)
|
||||||
|
addUnlink(to: menu, with: site)
|
||||||
|
|
||||||
tableView.menu = menu
|
tableView.menu = menu
|
||||||
}
|
}
|
||||||
|
|
||||||
private func addSystemApps(to menu: NSMenu) {
|
private func addSystemApps(to menu: NSMenu) {
|
||||||
menu.addItem(withTitle: "domain_list.system_apps".localized, action: nil, keyEquivalent: "")
|
menu.addItem(HeaderView.asMenuItem(text: "domain_list.system_apps".localized))
|
||||||
menu.addItem(
|
menu.addItem(
|
||||||
withTitle: "domain_list.open_in_finder".localized,
|
withTitle: "domain_list.open_in_finder".localized,
|
||||||
action: #selector(self.openInFinder),
|
action: #selector(self.openInFinder),
|
||||||
@@ -70,7 +71,7 @@ extension DomainListVC {
|
|||||||
private func addDetectedApps(to menu: NSMenu) {
|
private func addDetectedApps(to menu: NSMenu) {
|
||||||
if !applications.isEmpty {
|
if !applications.isEmpty {
|
||||||
menu.addItem(NSMenuItem.separator())
|
menu.addItem(NSMenuItem.separator())
|
||||||
menu.addItem(withTitle: "domain_list.detected_apps".localized, action: nil, keyEquivalent: "")
|
menu.addItem(HeaderView.asMenuItem(text: "domain_list.detected_apps".localized))
|
||||||
|
|
||||||
for editor in applications {
|
for editor in applications {
|
||||||
let editorMenuItem = EditorMenuItem(
|
let editorMenuItem = EditorMenuItem(
|
||||||
@@ -96,38 +97,40 @@ extension DomainListVC {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func addDisabledIsolation(to menu: NSMenu) {
|
private func addDisabledIsolation(to menu: NSMenu) {
|
||||||
|
menu.addItem(HeaderView.asMenuItem(text: "domain_list.site_isolation".localized))
|
||||||
menu.addItem(withTitle: "domain_list.isolation_unavailable".localized, action: nil, keyEquivalent: "")
|
menu.addItem(withTitle: "domain_list.isolation_unavailable".localized, action: nil, keyEquivalent: "")
|
||||||
menu.addItem(NSMenuItem.separator())
|
menu.addItem(NSMenuItem.separator())
|
||||||
}
|
}
|
||||||
|
|
||||||
private func addIsolate(to menu: NSMenu, with site: ValetSite) {
|
private func addIsolate(to menu: NSMenu, with site: ValetSite) {
|
||||||
if site.isolatedPhpVersion == nil {
|
var items: [NSMenuItem] = []
|
||||||
// ISOLATION POSSIBLE
|
|
||||||
let isolationMenuItem = NSMenuItem(title: "domain_list.isolate".localized, action: nil, keyEquivalent: "")
|
|
||||||
let submenu = NSMenu()
|
|
||||||
submenu.addItem(withTitle: "Choose a PHP version", action: nil, keyEquivalent: "")
|
|
||||||
for version in PhpEnv.shared.availablePhpVersions.reversed() {
|
|
||||||
let item = PhpMenuItem(
|
|
||||||
title: "Always use PHP \(version)",
|
|
||||||
action: #selector(self.isolateSite),
|
|
||||||
keyEquivalent: ""
|
|
||||||
)
|
|
||||||
item.version = version
|
|
||||||
submenu.addItem(item)
|
|
||||||
}
|
|
||||||
menu.setSubmenu(submenu, for: isolationMenuItem)
|
|
||||||
|
|
||||||
menu.addItem(isolationMenuItem)
|
for version in PhpEnv.shared.availablePhpVersions.reversed() {
|
||||||
menu.addItem(NSMenuItem.separator())
|
let item = PhpMenuItem(
|
||||||
} else {
|
title: "domain_list.always_use_php".localized(version),
|
||||||
// REMOVE ISOLATION POSSIBLE
|
action: #selector(self.isolateSite),
|
||||||
menu.addItem(
|
|
||||||
withTitle: "domain_list.remove_isolation".localized,
|
|
||||||
action: #selector(self.removeIsolatedSite),
|
|
||||||
keyEquivalent: ""
|
keyEquivalent: ""
|
||||||
)
|
)
|
||||||
menu.addItem(NSMenuItem.separator())
|
if site.servingPhpVersion == version && site.isolatedPhpVersion != nil {
|
||||||
|
item.state = .on
|
||||||
|
item.action = nil
|
||||||
|
}
|
||||||
|
item.version = version
|
||||||
|
items.append(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add the option to remove site isolation
|
||||||
|
if site.isolatedPhpVersion != nil {
|
||||||
|
items.append(NSMenuItem.separator())
|
||||||
|
items.append(NSMenuItem(
|
||||||
|
title: "domain_list.remove_isolation".localized,
|
||||||
|
action: #selector(self.removeIsolatedSite)
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
menu.addItem(HeaderView.asMenuItem(text: "domain_list.site_isolation".localized))
|
||||||
|
menu.addItem(NSMenuItem(title: "domain_list.isolate".localized, submenu: items))
|
||||||
|
menu.addItem(NSMenuItem.separator())
|
||||||
}
|
}
|
||||||
|
|
||||||
private func addToggleSecure(to menu: NSMenu, secured: Bool) {
|
private func addToggleSecure(to menu: NSMenu, secured: Bool) {
|
||||||
|
@@ -13,7 +13,7 @@ class DomainListVC: NSViewController, NSTableViewDelegate, NSTableViewDataSource
|
|||||||
|
|
||||||
// MARK: - Outlets
|
// MARK: - Outlets
|
||||||
|
|
||||||
@IBOutlet weak var tableView: NSTableView!
|
@IBOutlet weak var tableView: PMTableView!
|
||||||
@IBOutlet weak var progressIndicator: NSProgressIndicator!
|
@IBOutlet weak var progressIndicator: NSProgressIndicator!
|
||||||
|
|
||||||
// MARK: - Variables
|
// MARK: - Variables
|
||||||
@@ -292,6 +292,6 @@ class DomainListVC: NSViewController, NSTableViewDelegate, NSTableViewDataSource
|
|||||||
// MARK: - Deinitialization
|
// MARK: - Deinitialization
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
Log.perf("DomainListVC deallocated")
|
Log.perf("deinit: \(String(describing: self)).\(#function)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
27
phpmon/Domain/DomainList/PMTableView.swift
Normal file
27
phpmon/Domain/DomainList/PMTableView.swift
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// PMTableView.swift
|
||||||
|
// PHP Monitor
|
||||||
|
//
|
||||||
|
// Created by Nico Verbruggen on 05/09/2022.
|
||||||
|
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Cocoa
|
||||||
|
|
||||||
|
/**
|
||||||
|
This subclassed version of NSTableView selects a row upon right-clicking,
|
||||||
|
thus making the domain list behave more like you'd expect.
|
||||||
|
*/
|
||||||
|
public class PMTableView: NSTableView {
|
||||||
|
|
||||||
|
override open func menu(for event: NSEvent) -> NSMenu? {
|
||||||
|
let row = self.row(at: self.convert(event.locationInWindow, from: nil))
|
||||||
|
|
||||||
|
if row >= 0 {
|
||||||
|
self.selectRowIndexes(IndexSet(integer: row), byExtendingSelection: false)
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.menu(for: event)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -52,15 +52,15 @@ class ComposerWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
task.listen(
|
task.listen(
|
||||||
didReceiveStandardOutputData: { string in
|
didReceiveStandardOutputData: { [weak self] string in
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.window?.addToConsole(string)
|
self?.window?.addToConsole(string)
|
||||||
}
|
}
|
||||||
// Log.perf("\(string.trimmingCharacters(in: .newlines))")
|
// Log.perf("\(string.trimmingCharacters(in: .newlines))")
|
||||||
},
|
},
|
||||||
didReceiveStandardErrorData: { string in
|
didReceiveStandardErrorData: { [weak self] string in
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.window?.addToConsole(string)
|
self?.window?.addToConsole(string)
|
||||||
}
|
}
|
||||||
// Log.perf("\(string.trimmingCharacters(in: .newlines))")
|
// Log.perf("\(string.trimmingCharacters(in: .newlines))")
|
||||||
}
|
}
|
||||||
@@ -91,6 +91,7 @@ class ComposerWindow {
|
|||||||
}
|
}
|
||||||
window = nil
|
window = nil
|
||||||
removeBusyStatus()
|
removeBusyStatus()
|
||||||
|
menu = nil
|
||||||
completion(true)
|
completion(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -103,6 +104,7 @@ class ComposerWindow {
|
|||||||
window?.progressView?.labelDescription.stringValue = "alert.composer_failure.info".localized
|
window?.progressView?.labelDescription.stringValue = "alert.composer_failure.info".localized
|
||||||
window = nil
|
window = nil
|
||||||
removeBusyStatus()
|
removeBusyStatus()
|
||||||
|
menu = nil
|
||||||
completion(false)
|
completion(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -111,9 +113,7 @@ class ComposerWindow {
|
|||||||
|
|
||||||
private func removeBusyStatus() {
|
private func removeBusyStatus() {
|
||||||
PhpEnv.shared.isBusy = false
|
PhpEnv.shared.isBusy = false
|
||||||
DispatchQueue.main.async { [self] in
|
menu?.updatePhpVersionInStatusBar()
|
||||||
menu?.updatePhpVersionInStatusBar()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Alert
|
// MARK: Alert
|
||||||
@@ -128,4 +128,8 @@ class ComposerWindow {
|
|||||||
.withPrimary(text: "OK")
|
.withPrimary(text: "OK")
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
Log.perf("deinit: \(String(describing: self)).\(#function)")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -29,6 +29,21 @@ class HomebrewDiagnostics {
|
|||||||
return installedTaps.contains("nicoverbruggen/cask")
|
return installedTaps.contains("nicoverbruggen/cask")
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
/**
|
||||||
|
Determines whether to use the regular `nginx` or `nginx-full` formula.
|
||||||
|
*/
|
||||||
|
public static var usesNginxFullFormula: Bool = {
|
||||||
|
guard let destination = try? FileManager.default
|
||||||
|
.destinationOfSymbolicLink(atPath: "\(Paths.binPath)/nginx") else { return false }
|
||||||
|
|
||||||
|
return
|
||||||
|
// Verify that the `nginx` binary is symlinked to a directory that includes `nginx-full`.
|
||||||
|
destination.contains("/nginx-full/")
|
||||||
|
// Verify that the formula exists.
|
||||||
|
&& !Shell.pipe("\(Paths.brew) info nginx-full --json")
|
||||||
|
.contains("Error: No available formula")
|
||||||
|
}()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
It is possible to have the `shivammathur/php` tap installed, and for the core homebrew information to be outdated.
|
It is possible to have the `shivammathur/php` tap installed, and for the core homebrew information to be outdated.
|
||||||
This will then result in two different aliases claiming to point to the same formula (`php`).
|
This will then result in two different aliases claiming to point to the same formula (`php`).
|
||||||
@@ -77,7 +92,7 @@ class HomebrewDiagnostics {
|
|||||||
private static func hasAliasConflict() -> Bool {
|
private static func hasAliasConflict() -> Bool {
|
||||||
let tapAlias = Shell.pipe("\(Paths.brew) info shivammathur/php/php --json")
|
let tapAlias = Shell.pipe("\(Paths.brew) info shivammathur/php/php --json")
|
||||||
|
|
||||||
if tapAlias.contains("brew tap shivammathur/php") || tapAlias.contains("Error") {
|
if tapAlias.contains("brew tap shivammathur/php") || tapAlias.contains("Error") || tapAlias.isEmpty {
|
||||||
Log.info("The user does not appear to have tapped: shivammathur/php")
|
Log.info("The user does not appear to have tapped: shivammathur/php")
|
||||||
return false
|
return false
|
||||||
} else {
|
} else {
|
||||||
@@ -128,10 +143,10 @@ class HomebrewDiagnostics {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
In order to see if we support the --json syntax, we'll query nginx.
|
In order to see if we support the --json syntax, we'll query dnsmasq.
|
||||||
If the JSON response cannot be parsed, Homebrew is probably out of date.
|
If the JSON response cannot be parsed, Homebrew is probably out of date.
|
||||||
*/
|
*/
|
||||||
public static func cannotLoadService(_ name: String = "nginx") -> Bool {
|
public static func cannotLoadService(_ name: String) -> Bool {
|
||||||
let serviceInfo = try? JSONDecoder().decode(
|
let serviceInfo = try? JSONDecoder().decode(
|
||||||
[HomebrewService].self,
|
[HomebrewService].self,
|
||||||
from: Shell.pipe(
|
from: Shell.pipe(
|
||||||
|
@@ -78,13 +78,19 @@ class Valet {
|
|||||||
Notify the user about a non-default TLD being set.
|
Notify the user about a non-default TLD being set.
|
||||||
*/
|
*/
|
||||||
public static func notifyAboutUnsupportedTLD() {
|
public static func notifyAboutUnsupportedTLD() {
|
||||||
if Valet.shared.config.tld != "test" {
|
if Valet.shared.config.tld != "test" && Preferences.isEnabled(.warnAboutNonStandardTLD) {
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
BetterAlert().withInformation(
|
BetterAlert().withInformation(
|
||||||
title: "alert.warnings.tld_issue.title".localized,
|
title: "alert.warnings.tld_issue.title".localized,
|
||||||
subtitle: "alert.warnings.tld_issue.subtitle".localized,
|
subtitle: "alert.warnings.tld_issue.subtitle".localized,
|
||||||
description: "alert.warnings.tld_issue.description".localized
|
description: "alert.warnings.tld_issue.description".localized
|
||||||
).withPrimary(text: "OK").show()
|
)
|
||||||
|
.withPrimary(text: "OK")
|
||||||
|
.withTertiary(text: "alert.do_not_tell_again".localized, action: { alert in
|
||||||
|
Preferences.update(.warnAboutNonStandardTLD, value: false)
|
||||||
|
alert.close(with: .alertThirdButtonReturn)
|
||||||
|
})
|
||||||
|
.show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -77,7 +77,11 @@ extension MainMenu {
|
|||||||
ServicesManager.shared.loadData()
|
ServicesManager.shared.loadData()
|
||||||
}
|
}
|
||||||
|
|
||||||
error == nil ? success() : failure(error!)
|
if error != nil {
|
||||||
|
return failure(error!)
|
||||||
|
}
|
||||||
|
|
||||||
|
success()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -29,12 +29,16 @@ extension MainMenu {
|
|||||||
When the environment is all clear and the app can run, let's go.
|
When the environment is all clear and the app can run, let's go.
|
||||||
*/
|
*/
|
||||||
private func onEnvironmentPass() {
|
private func onEnvironmentPass() {
|
||||||
// Determine install method
|
|
||||||
Log.info(HomebrewDiagnostics.customCaskInstalled
|
Log.info(HomebrewDiagnostics.customCaskInstalled
|
||||||
? "The app has probably been installed via Homebrew Cask."
|
? "The app has probably been installed via Homebrew Cask."
|
||||||
: "The app has probably been installed directly."
|
: "The app has probably been installed directly."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Log.info(HomebrewDiagnostics.usesNginxFullFormula
|
||||||
|
? "The app will be using the `nginx-full` formula."
|
||||||
|
: "The app will be using the `nginx` formula."
|
||||||
|
)
|
||||||
|
|
||||||
// Attempt to find out more info about Valet
|
// Attempt to find out more info about Valet
|
||||||
if Valet.shared.version != nil {
|
if Valet.shared.version != nil {
|
||||||
Log.info("PHP Monitor has extracted the version number of Valet: \(Valet.shared.version!)")
|
Log.info("PHP Monitor has extracted the version number of Valet: \(Valet.shared.version!)")
|
||||||
@@ -155,11 +159,11 @@ extension MainMenu {
|
|||||||
|
|
||||||
App.shared.detectedApplications = Application.detectPresetApplications()
|
App.shared.detectedApplications = Application.detectPresetApplications()
|
||||||
|
|
||||||
let customApps = Preferences.custom.scanApps.map { appName in
|
let customApps = Preferences.custom.scanApps?.map { appName in
|
||||||
return Application(appName, .user_supplied)
|
return Application(appName, .user_supplied)
|
||||||
}.filter { app in
|
}.filter { app in
|
||||||
return app.isInstalled()
|
return app.isInstalled()
|
||||||
}
|
} ?? []
|
||||||
|
|
||||||
App.shared.detectedApplications.append(contentsOf: customApps)
|
App.shared.detectedApplications.append(contentsOf: customApps)
|
||||||
|
|
||||||
|
@@ -51,25 +51,10 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate, PhpSwitcherDelegate
|
|||||||
*/
|
*/
|
||||||
private func rebuildMenu() {
|
private func rebuildMenu() {
|
||||||
let menu = StatusMenu()
|
let menu = StatusMenu()
|
||||||
|
menu.addMenuItems()
|
||||||
menu.addPhpVersionMenuItems()
|
|
||||||
menu.addItem(NSMenuItem.separator())
|
|
||||||
|
|
||||||
menu.addPhpActionMenuItems()
|
|
||||||
menu.addItem(NSMenuItem.separator())
|
|
||||||
|
|
||||||
menu.addValetMenuItems()
|
|
||||||
menu.addItem(NSMenuItem.separator())
|
|
||||||
|
|
||||||
menu.addRemainingMenuItems()
|
|
||||||
menu.addItem(NSMenuItem.separator())
|
|
||||||
|
|
||||||
menu.addCoreMenuItems()
|
|
||||||
|
|
||||||
menu.items.forEach({ (item) in
|
menu.items.forEach({ (item) in
|
||||||
item.target = self
|
item.target = self
|
||||||
})
|
})
|
||||||
|
|
||||||
statusItem.menu = menu
|
statusItem.menu = menu
|
||||||
statusItem.menu?.delegate = self
|
statusItem.menu?.delegate = self
|
||||||
}
|
}
|
||||||
|
@@ -2,72 +2,176 @@
|
|||||||
// StatusMenu+Items.swift
|
// StatusMenu+Items.swift
|
||||||
// PHP Monitor
|
// PHP Monitor
|
||||||
//
|
//
|
||||||
// Created by Nico Verbruggen on 30/05/2022.
|
// Created by Nico Verbruggen on 18/08/2022.
|
||||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
import Cocoa
|
import Cocoa
|
||||||
|
|
||||||
|
// MARK: - PHP Version
|
||||||
|
|
||||||
extension StatusMenu {
|
extension StatusMenu {
|
||||||
|
|
||||||
// MARK: Remaining Menu Items
|
func addPhpVersionMenuItems() {
|
||||||
|
if PhpEnv.phpInstall.version.error {
|
||||||
|
let brokenMenuItems = ["mi_php_broken_1", "mi_php_broken_2", "mi_php_broken_3", "mi_php_broken_4"]
|
||||||
|
return addItems(brokenMenuItems.map { NSMenuItem(title: $0.localized) })
|
||||||
|
}
|
||||||
|
|
||||||
|
addItem(HeaderView.asMenuItem(
|
||||||
|
text: "\("mi_php_version".localized) \(PhpEnv.phpInstall.version.long)",
|
||||||
|
minimumWidth: 280 // this ensures the menu is at least wide enough not to cause clipping
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
func addPhpActionMenuItems() {
|
||||||
|
if PhpEnv.shared.isBusy {
|
||||||
|
addItem(NSMenuItem(title: "mi_busy".localized))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if PhpEnv.shared.availablePhpVersions.isEmpty { return }
|
||||||
|
|
||||||
|
addSwitchToPhpMenuItems()
|
||||||
|
self.addItem(NSMenuItem.separator())
|
||||||
|
}
|
||||||
|
|
||||||
|
func addServicesManagerMenuItem() {
|
||||||
|
if PhpEnv.shared.isBusy {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
addItems([
|
||||||
|
ServicesView.asMenuItem(),
|
||||||
|
NSMenuItem.separator()
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
func addSwitchToPhpMenuItems() {
|
||||||
|
var shortcutKey = 1
|
||||||
|
for index in (0..<PhpEnv.shared.availablePhpVersions.count).reversed() {
|
||||||
|
|
||||||
|
// Get the short and long version
|
||||||
|
let shortVersion = PhpEnv.shared.availablePhpVersions[index]
|
||||||
|
let longVersion = PhpEnv.shared.cachedPhpInstallations[shortVersion]!.versionNumber
|
||||||
|
|
||||||
|
let long = Preferences.preferences[.fullPhpVersionDynamicIcon] as! Bool
|
||||||
|
let versionString = long ? longVersion.toString() : shortVersion
|
||||||
|
|
||||||
|
let action = #selector(MainMenu.switchToPhpVersion(sender:))
|
||||||
|
let brew = (shortVersion == PhpEnv.brewPhpVersion) ? "php" : "php@\(shortVersion)"
|
||||||
|
let menuItem = PhpMenuItem(
|
||||||
|
title: "\("mi_php_switch".localized) \(versionString) (\(brew))",
|
||||||
|
action: (shortVersion == PhpEnv.phpInstall.version.short)
|
||||||
|
? nil
|
||||||
|
: action, keyEquivalent: "\(shortcutKey)"
|
||||||
|
)
|
||||||
|
|
||||||
|
menuItem.version = shortVersion
|
||||||
|
shortcutKey += 1
|
||||||
|
|
||||||
|
addItem(menuItem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func addCoreMenuItems() {
|
||||||
|
addItems([
|
||||||
|
NSMenuItem.separator(),
|
||||||
|
NSMenuItem(title: "mi_preferences".localized,
|
||||||
|
action: #selector(MainMenu.openPrefs), keyEquivalent: ","),
|
||||||
|
NSMenuItem(title: "mi_check_for_updates".localized,
|
||||||
|
action: #selector(MainMenu.checkForUpdates)),
|
||||||
|
NSMenuItem.separator(),
|
||||||
|
NSMenuItem(title: "mi_about".localized,
|
||||||
|
action: #selector(MainMenu.openAbout)),
|
||||||
|
NSMenuItem(title: "mi_quit".localized,
|
||||||
|
action: #selector(MainMenu.terminateApp), keyEquivalent: "q")
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Valet
|
||||||
|
|
||||||
|
func addValetMenuItems() {
|
||||||
|
addItems([
|
||||||
|
HeaderView.asMenuItem(text: "mi_valet".localized),
|
||||||
|
NSMenuItem(title: "mi_valet_config".localized,
|
||||||
|
action: #selector(MainMenu.openValetConfigFolder),
|
||||||
|
keyEquivalent: "v"),
|
||||||
|
NSMenuItem(title: "mi_domain_list".localized,
|
||||||
|
action: #selector(MainMenu.openDomainList),
|
||||||
|
keyEquivalent: "l"),
|
||||||
|
NSMenuItem.separator()
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - PHP Configuration
|
||||||
|
|
||||||
func addConfigurationMenuItems() {
|
func addConfigurationMenuItems() {
|
||||||
self.addItem(HeaderView.asMenuItem(text: "mi_configuration".localized))
|
addItems([
|
||||||
self.addItem(
|
HeaderView.asMenuItem(text: "mi_configuration".localized),
|
||||||
NSMenuItem(title: "mi_php_config".localized,
|
NSMenuItem(title: "mi_php_config".localized,
|
||||||
action: #selector(MainMenu.openActiveConfigFolder), keyEquivalent: "c")
|
action: #selector(MainMenu.openActiveConfigFolder),
|
||||||
)
|
keyEquivalent: "c"),
|
||||||
self.addItem(
|
|
||||||
NSMenuItem(title: "mi_phpmon_config".localized,
|
NSMenuItem(title: "mi_phpmon_config".localized,
|
||||||
action: #selector(MainMenu.openPhpMonitorConfigurationFile), keyEquivalent: "y")
|
action: #selector(MainMenu.openPhpMonitorConfigurationFile),
|
||||||
)
|
keyEquivalent: "y"),
|
||||||
self.addItem(
|
NSMenuItem(title: "mi_phpinfo".localized,
|
||||||
NSMenuItem(title: "mi_phpinfo".localized, action: #selector(MainMenu.openPhpInfo), keyEquivalent: "i")
|
action: #selector(MainMenu.openPhpInfo),
|
||||||
)
|
keyEquivalent: "i")
|
||||||
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - Composer
|
||||||
|
|
||||||
func addComposerMenuItems() {
|
func addComposerMenuItems() {
|
||||||
self.addItem(HeaderView.asMenuItem(text: "mi_composer".localized))
|
addItems([
|
||||||
self.addItem(
|
HeaderView.asMenuItem(text: "mi_composer".localized),
|
||||||
NSMenuItem(title: "mi_global_composer".localized,
|
NSMenuItem(
|
||||||
action: #selector(MainMenu.openGlobalComposerFolder), keyEquivalent: "g")
|
title: "mi_global_composer".localized,
|
||||||
)
|
action: #selector(MainMenu.openGlobalComposerFolder),
|
||||||
|
keyEquivalent: "g"
|
||||||
let composerMenuItem = NSMenuItem(
|
),
|
||||||
title: "mi_update_global_composer".localized,
|
NSMenuItem(
|
||||||
action: PhpEnv.shared.isBusy ? nil : #selector(MainMenu.updateGlobalComposerDependencies),
|
title: "mi_update_global_composer".localized,
|
||||||
keyEquivalent: "g"
|
action: PhpEnv.shared.isBusy
|
||||||
)
|
? nil
|
||||||
composerMenuItem.keyEquivalentModifierMask = .shift
|
: #selector(MainMenu.updateGlobalComposerDependencies),
|
||||||
|
keyEquivalent: "g",
|
||||||
self.addItem(composerMenuItem)
|
keyModifier: [.shift]
|
||||||
|
)
|
||||||
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - Stats
|
||||||
|
|
||||||
func addStatsMenuItem() {
|
func addStatsMenuItem() {
|
||||||
guard let stats = PhpEnv.phpInstall.limits else { return }
|
guard let stats = PhpEnv.phpInstall.limits else { return }
|
||||||
|
|
||||||
self.addItem(StatsView.asMenuItem(
|
addItem(StatsView.asMenuItem(
|
||||||
memory: stats.memory_limit,
|
memory: stats.memory_limit,
|
||||||
post: stats.post_max_size,
|
post: stats.post_max_size,
|
||||||
upload: stats.upload_max_filesize)
|
upload: stats.upload_max_filesize)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - Extensions
|
||||||
|
|
||||||
func addExtensionsMenuItems() {
|
func addExtensionsMenuItems() {
|
||||||
self.addItem(HeaderView.asMenuItem(text: "mi_detected_extensions".localized))
|
addItem(HeaderView.asMenuItem(text: "mi_detected_extensions".localized))
|
||||||
|
|
||||||
if PhpEnv.phpInstall.extensions.isEmpty {
|
if PhpEnv.phpInstall.extensions.isEmpty {
|
||||||
self.addItem(NSMenuItem(title: "mi_no_extensions_detected".localized, action: nil, keyEquivalent: ""))
|
addItem(NSMenuItem(title: "mi_no_extensions_detected".localized, action: nil, keyEquivalent: ""))
|
||||||
}
|
}
|
||||||
|
|
||||||
var shortcutKey = 1
|
var shortcutKey = 1
|
||||||
for phpExtension in PhpEnv.phpInstall.extensions {
|
for phpExtension in PhpEnv.phpInstall.extensions {
|
||||||
self.addExtensionItem(phpExtension, shortcutKey)
|
addExtensionItem(phpExtension, shortcutKey)
|
||||||
shortcutKey += 1
|
shortcutKey += 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - Presets
|
||||||
|
|
||||||
func addPresetsMenuItem() {
|
func addPresetsMenuItem() {
|
||||||
guard let presets = Preferences.custom.presets else {
|
guard let presets = Preferences.custom.presets else {
|
||||||
addEmptyPresetHelp()
|
addEmptyPresetHelp()
|
||||||
@@ -82,178 +186,127 @@ extension StatusMenu {
|
|||||||
addLoadedPresets()
|
addLoadedPresets()
|
||||||
}
|
}
|
||||||
|
|
||||||
func addEmptyPresetHelp() {
|
private func addEmptyPresetHelp() {
|
||||||
let presets = NSMenuItem(title: "mi_presets_title".localized, action: nil, keyEquivalent: "")
|
addItem(NSMenuItem(title: "mi_presets_title".localized, submenu: [
|
||||||
|
NSMenuItem(title: "mi_no_presets".localized),
|
||||||
let presetsMenu = NSMenu()
|
NSMenuItem.separator(),
|
||||||
|
NSMenuItem(title: "mi_set_up_presets".localized,
|
||||||
presetsMenu.addItem(NSMenuItem(title: "mi_no_presets".localized, action: nil, keyEquivalent: ""))
|
action: #selector(MainMenu.showPresetHelp))
|
||||||
presetsMenu.addItem(NSMenuItem.separator())
|
], target: MainMenu.shared))
|
||||||
presetsMenu.addItem(NSMenuItem(
|
|
||||||
title: "mi_set_up_presets".localized,
|
|
||||||
action: #selector(MainMenu.showPresetHelp),
|
|
||||||
keyEquivalent: "")
|
|
||||||
)
|
|
||||||
|
|
||||||
presetsMenu.items.forEach { $0.target = MainMenu.shared }
|
|
||||||
|
|
||||||
self.setSubmenu(presetsMenu, for: presets)
|
|
||||||
self.addItem(presets)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func addLoadedPresets() {
|
private func addLoadedPresets() {
|
||||||
let presets = NSMenuItem(title: "mi_presets_title".localized, action: nil, keyEquivalent: "")
|
addItem(NSMenuItem(title: "mi_presets_title".localized, submenu: [
|
||||||
|
NSMenuItem.separator(),
|
||||||
let presetsMenu = NSMenu()
|
HeaderView.asMenuItem(text: "mi_apply_presets_title".localized)
|
||||||
|
] + PresetMenuItem.getAll() + [
|
||||||
presetsMenu.addItem(NSMenuItem.separator())
|
NSMenuItem.separator(),
|
||||||
presetsMenu.addItem(HeaderView.asMenuItem(text: "mi_apply_presets_title".localized))
|
NSMenuItem(title: "mi_revert_to_prev_config".localized,
|
||||||
|
action: PresetHelper.rollbackPreset != nil ? #selector(MainMenu.rollbackPreset) : nil),
|
||||||
for preset in Preferences.custom.presets! {
|
NSMenuItem.separator(),
|
||||||
let presetMenuItem = PresetMenuItem(
|
NSMenuItem(title: "mi_profiles_loaded".localized(Preferences.custom.presets!.count))
|
||||||
title: preset.getMenuItemText(),
|
], target: MainMenu.shared))
|
||||||
action: #selector(MainMenu.togglePreset(sender:)),
|
|
||||||
keyEquivalent: ""
|
|
||||||
)
|
|
||||||
|
|
||||||
if let attributedString = try? NSMutableAttributedString(
|
|
||||||
data: preset.getMenuItemText().data(using: .utf8)!,
|
|
||||||
options: [.documentType: NSAttributedString.DocumentType.html],
|
|
||||||
documentAttributes: nil
|
|
||||||
) {
|
|
||||||
presetMenuItem.attributedTitle = attributedString
|
|
||||||
}
|
|
||||||
|
|
||||||
presetMenuItem.preset = preset
|
|
||||||
presetsMenu.addItem(presetMenuItem)
|
|
||||||
}
|
|
||||||
|
|
||||||
presetsMenu.addItem(NSMenuItem.separator())
|
|
||||||
presetsMenu.addItem(NSMenuItem(
|
|
||||||
title: "mi_revert_to_prev_config".localized,
|
|
||||||
action: PresetHelper.rollbackPreset != nil
|
|
||||||
? #selector(MainMenu.rollbackPreset)
|
|
||||||
: nil,
|
|
||||||
keyEquivalent: ""
|
|
||||||
))
|
|
||||||
presetsMenu.addItem(NSMenuItem.separator())
|
|
||||||
presetsMenu.addItem(NSMenuItem(
|
|
||||||
title: "mi_profiles_loaded".localized(
|
|
||||||
Preferences.custom.presets!.count
|
|
||||||
),
|
|
||||||
action: nil, keyEquivalent: "")
|
|
||||||
)
|
|
||||||
for item in presetsMenu.items {
|
|
||||||
item.target = MainMenu.shared
|
|
||||||
}
|
|
||||||
self.setSubmenu(presetsMenu, for: presets)
|
|
||||||
self.addItem(presets)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - Xdebug
|
||||||
|
|
||||||
func addXdebugMenuItem() {
|
func addXdebugMenuItem() {
|
||||||
if !Xdebug.enabled {
|
if !Xdebug.enabled {
|
||||||
|
addItem(NSMenuItem.separator())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
self.addItem(NSMenuItem.separator())
|
addItems([
|
||||||
let xdebugSwitch = NSMenuItem(
|
NSMenuItem(title: "mi_xdebug_mode".localized, submenu: [
|
||||||
title: "mi_xdebug_mode".localized,
|
HeaderView.asMenuItem(text: "mi_xdebug_available_modes".localized)
|
||||||
action: nil,
|
] + Xdebug.asMenuItems() + [
|
||||||
keyEquivalent: ""
|
HeaderView.asMenuItem(text: "mi_xdebug_actions".localized),
|
||||||
)
|
NSMenuItem(title: "mi_xdebug_disable_all".localized,
|
||||||
let xdebugModesMenu = NSMenu()
|
action: #selector(MainMenu.disableAllXdebugModes))
|
||||||
let activeModes = Xdebug.activeModes
|
], target: MainMenu.shared),
|
||||||
|
NSMenuItem.separator()
|
||||||
xdebugModesMenu.addItem(HeaderView.asMenuItem(text: "mi_xdebug_available_modes".localized))
|
], target: MainMenu.shared)
|
||||||
|
|
||||||
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: ""
|
|
||||||
)
|
|
||||||
|
|
||||||
for item in xdebugModesMenu.items {
|
|
||||||
item.target = MainMenu.shared
|
|
||||||
}
|
|
||||||
|
|
||||||
self.setSubmenu(xdebugModesMenu, for: xdebugSwitch)
|
|
||||||
self.addItem(xdebugSwitch)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - PHP Doctor
|
||||||
|
|
||||||
|
func addPhpDoctorMenuItem() {
|
||||||
|
if !Preferences.isEnabled(.showPhpDoctorSuggestions) ||
|
||||||
|
!WarningManager.shared.hasWarnings() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
addItems([
|
||||||
|
HeaderView.asMenuItem(text: "mi_php_doctor".localized),
|
||||||
|
NSMenuItem(title: "mi_recommendations_count".localized(WarningManager.shared.warnings.count)),
|
||||||
|
NSMenuItem(title: "mi_view_recommendations".localized, action: #selector(MainMenu.openWarnings)),
|
||||||
|
NSMenuItem.separator()
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - First Aid & Services
|
||||||
|
|
||||||
func addFirstAidAndServicesMenuItems() {
|
func addFirstAidAndServicesMenuItems() {
|
||||||
let services = NSMenuItem(title: "mi_other".localized, action: nil, keyEquivalent: "")
|
let services = NSMenuItem(title: "mi_other".localized)
|
||||||
|
|
||||||
let servicesMenu = NSMenu()
|
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,
|
// MANUAL ACTIONS
|
||||||
action: #selector(MainMenu.showWelcomeTour), keyEquivalent: ""))
|
HeaderView.asMenuItem(text: "mi_manual_actions".localized),
|
||||||
|
|
||||||
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(
|
|
||||||
NSMenuItem(title: "mi_php_refresh".localized,
|
NSMenuItem(title: "mi_php_refresh".localized,
|
||||||
action: #selector(MainMenu.reloadPhpMonitorMenuInForeground), keyEquivalent: "r")
|
action: #selector(MainMenu.reloadPhpMonitorMenuInForeground),
|
||||||
)
|
keyEquivalent: "r")
|
||||||
|
], target: MainMenu.shared)
|
||||||
|
|
||||||
for item in servicesMenu.items {
|
setSubmenu(servicesMenu, for: services)
|
||||||
item.target = MainMenu.shared
|
addItem(services)
|
||||||
}
|
|
||||||
|
|
||||||
self.setSubmenu(servicesMenu, for: services)
|
|
||||||
self.addItem(services)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - Other helper methods to generate menu items
|
||||||
|
|
||||||
|
func addExtensionItem(_ phpExtension: PhpExtension, _ shortcutKey: Int) {
|
||||||
|
let keyEquivalent = shortcutKey < 9 ? "\(shortcutKey)" : ""
|
||||||
|
|
||||||
|
let menuItem = ExtensionMenuItem(
|
||||||
|
title: "\(phpExtension.name) (\(phpExtension.fileNameOnly))",
|
||||||
|
action: #selector(MainMenu.toggleExtension),
|
||||||
|
keyEquivalent: keyEquivalent
|
||||||
|
)
|
||||||
|
|
||||||
|
if menuItem.keyEquivalent != "" {
|
||||||
|
menuItem.keyEquivalentModifierMask = [.option]
|
||||||
|
}
|
||||||
|
|
||||||
|
menuItem.state = phpExtension.enabled ? .on : .off
|
||||||
|
menuItem.phpExtension = phpExtension
|
||||||
|
|
||||||
|
addItem(menuItem)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -8,154 +8,63 @@
|
|||||||
import Cocoa
|
import Cocoa
|
||||||
|
|
||||||
class StatusMenu: NSMenu {
|
class StatusMenu: NSMenu {
|
||||||
|
func addMenuItems() {
|
||||||
|
addPhpVersionMenuItems()
|
||||||
|
addItem(NSMenuItem.separator())
|
||||||
|
|
||||||
func addPhpVersionMenuItems() {
|
if Preferences.isEnabled(.displayGlobalVersionSwitcher) {
|
||||||
if PhpEnv.phpInstall.version.error {
|
addPhpActionMenuItems()
|
||||||
for message in ["mi_php_broken_1", "mi_php_broken_2", "mi_php_broken_3", "mi_php_broken_4"] {
|
addItem(NSMenuItem.separator())
|
||||||
addItem(NSMenuItem(title: message.localized, action: nil, keyEquivalent: ""))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let phpVersionText = "\("mi_php_version".localized) \(PhpEnv.phpInstall.version.long)"
|
if Preferences.isEnabled(.displayServicesManager) {
|
||||||
addItem(HeaderView.asMenuItem(text: phpVersionText))
|
addServicesManagerMenuItem()
|
||||||
}
|
addItem(NSMenuItem.separator())
|
||||||
|
|
||||||
func addPhpActionMenuItems() {
|
|
||||||
if PhpEnv.shared.isBusy {
|
|
||||||
addItem(NSMenuItem(title: "mi_busy".localized, action: nil, keyEquivalent: ""))
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if PhpEnv.shared.availablePhpVersions.isEmpty {
|
if Preferences.isEnabled(.displayValetIntegration) {
|
||||||
return
|
addValetMenuItems()
|
||||||
|
addItem(NSMenuItem.separator())
|
||||||
}
|
}
|
||||||
|
|
||||||
self.addSwitchToPhpMenuItems()
|
if Preferences.isEnabled(.displayPhpConfigFinder) {
|
||||||
self.addItem(NSMenuItem.separator())
|
addConfigurationMenuItems()
|
||||||
|
addItem(NSMenuItem.separator())
|
||||||
|
}
|
||||||
|
|
||||||
self.addItem(ServicesView.asMenuItem())
|
if Preferences.isEnabled(.displayComposerToolkit) {
|
||||||
self.addItem(NSMenuItem.separator())
|
addComposerMenuItems()
|
||||||
}
|
addItem(NSMenuItem.separator())
|
||||||
|
}
|
||||||
func addValetMenuItems() {
|
|
||||||
self.addItem(HeaderView.asMenuItem(text: "mi_valet".localized))
|
|
||||||
self.addItem(NSMenuItem(
|
|
||||||
title: "mi_valet_config".localized, action: #selector(MainMenu.openValetConfigFolder), keyEquivalent: "v"))
|
|
||||||
self.addItem(NSMenuItem(
|
|
||||||
title: "mi_domain_list".localized, action: #selector(MainMenu.openDomainList), keyEquivalent: "l"))
|
|
||||||
self.addItem(NSMenuItem.separator())
|
|
||||||
}
|
|
||||||
|
|
||||||
func addRemainingMenuItems() {
|
|
||||||
self.addConfigurationMenuItems()
|
|
||||||
|
|
||||||
self.addItem(NSMenuItem.separator())
|
|
||||||
|
|
||||||
self.addComposerMenuItems()
|
|
||||||
|
|
||||||
if PhpEnv.shared.isBusy {
|
if PhpEnv.shared.isBusy {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
self.addItem(NSMenuItem.separator())
|
if Preferences.isEnabled(.displayLimitsWidget) {
|
||||||
|
addStatsMenuItem()
|
||||||
self.addStatsMenuItem()
|
addItem(NSMenuItem.separator())
|
||||||
|
|
||||||
self.addItem(NSMenuItem.separator())
|
|
||||||
|
|
||||||
self.addExtensionsMenuItems()
|
|
||||||
|
|
||||||
self.addXdebugMenuItem()
|
|
||||||
|
|
||||||
self.addPhpDoctorMenuItem()
|
|
||||||
|
|
||||||
self.addItem(NSMenuItem.separator())
|
|
||||||
|
|
||||||
self.addPresetsMenuItem()
|
|
||||||
|
|
||||||
self.addFirstAidAndServicesMenuItems()
|
|
||||||
}
|
|
||||||
|
|
||||||
func addPhpDoctorMenuItem() {
|
|
||||||
if !Preferences.isEnabled(.showPhpDoctorSuggestions) ||
|
|
||||||
!WarningManager.shared.hasWarnings() {
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.addItem(NSMenuItem.separator())
|
if Preferences.isEnabled(.displayExtensions) {
|
||||||
self.addItem(HeaderView.asMenuItem(text: "mi_php_doctor".localized))
|
addExtensionsMenuItems()
|
||||||
self.addItem(NSMenuItem(
|
NSMenuItem.separator()
|
||||||
title: "mi_recommendations_count".localized(WarningManager.shared.warnings.count),
|
|
||||||
action: nil,
|
|
||||||
keyEquivalent: ""
|
|
||||||
))
|
|
||||||
self.addItem(NSMenuItem(
|
|
||||||
title: "mi_view_recommendations".localized,
|
|
||||||
action: #selector(MainMenu.openWarnings),
|
|
||||||
keyEquivalent: ""
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
func addCoreMenuItems() {
|
addXdebugMenuItem()
|
||||||
self.addItem(NSMenuItem.separator())
|
|
||||||
|
|
||||||
self.addItem(NSMenuItem(title: "mi_preferences".localized,
|
|
||||||
action: #selector(MainMenu.openPrefs), keyEquivalent: ","))
|
|
||||||
self.addItem(NSMenuItem(title: "mi_check_for_updates".localized,
|
|
||||||
action: #selector(MainMenu.checkForUpdates), keyEquivalent: ""))
|
|
||||||
self.addItem(NSMenuItem.separator())
|
|
||||||
self.addItem(NSMenuItem(title: "mi_about".localized,
|
|
||||||
action: #selector(MainMenu.openAbout), keyEquivalent: ""))
|
|
||||||
self.addItem(NSMenuItem(title: "mi_quit".localized,
|
|
||||||
action: #selector(MainMenu.terminateApp), keyEquivalent: "q"))
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: Private Helpers
|
|
||||||
|
|
||||||
internal func addSwitchToPhpMenuItems() {
|
|
||||||
var shortcutKey = 1
|
|
||||||
for index in (0..<PhpEnv.shared.availablePhpVersions.count).reversed() {
|
|
||||||
|
|
||||||
// Get the short and long version
|
|
||||||
let shortVersion = PhpEnv.shared.availablePhpVersions[index]
|
|
||||||
let longVersion = PhpEnv.shared.cachedPhpInstallations[shortVersion]!.versionNumber
|
|
||||||
|
|
||||||
let long = Preferences.preferences[.fullPhpVersionDynamicIcon] as! Bool
|
|
||||||
let versionString = long ? longVersion.toString() : shortVersion
|
|
||||||
|
|
||||||
let action = #selector(MainMenu.switchToPhpVersion(sender:))
|
|
||||||
let brew = (shortVersion == PhpEnv.brewPhpVersion) ? "php" : "php@\(shortVersion)"
|
|
||||||
let menuItem = PhpMenuItem(
|
|
||||||
title: "\("mi_php_switch".localized) \(versionString) (\(brew))",
|
|
||||||
action: (shortVersion == PhpEnv.phpInstall.version.short)
|
|
||||||
? nil
|
|
||||||
: action, keyEquivalent: "\(shortcutKey)"
|
|
||||||
)
|
|
||||||
|
|
||||||
menuItem.version = shortVersion
|
|
||||||
shortcutKey += 1
|
|
||||||
|
|
||||||
self.addItem(menuItem)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal func addExtensionItem(_ phpExtension: PhpExtension, _ shortcutKey: Int) {
|
|
||||||
let keyEquivalent = shortcutKey < 9 ? "\(shortcutKey)" : ""
|
|
||||||
|
|
||||||
let menuItem = ExtensionMenuItem(
|
|
||||||
title: "\(phpExtension.name) (\(phpExtension.fileNameOnly))",
|
|
||||||
action: #selector(MainMenu.toggleExtension),
|
|
||||||
keyEquivalent: keyEquivalent
|
|
||||||
)
|
|
||||||
|
|
||||||
if menuItem.keyEquivalent != "" {
|
|
||||||
menuItem.keyEquivalentModifierMask = [.option]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
menuItem.state = phpExtension.enabled ? .on : .off
|
addPhpDoctorMenuItem()
|
||||||
menuItem.phpExtension = phpExtension
|
|
||||||
|
|
||||||
self.addItem(menuItem)
|
if Preferences.isEnabled(.displayPresets) {
|
||||||
|
addPresetsMenuItem()
|
||||||
|
}
|
||||||
|
|
||||||
|
if Preferences.isEnabled(.displayMisc) {
|
||||||
|
addFirstAidAndServicesMenuItems()
|
||||||
|
}
|
||||||
|
|
||||||
|
addItem(NSMenuItem.separator())
|
||||||
|
|
||||||
|
addCoreMenuItems()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -47,7 +47,7 @@ class BetterAlertVC: NSViewController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
Log.perf("A BetterAlert has been deinitialized.")
|
Log.perf("deinit: \(String(describing: self)).\(#function)")
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Outlet Actions
|
// MARK: Outlet Actions
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
struct CustomPrefs: Decodable {
|
struct CustomPrefs: Decodable {
|
||||||
let scanApps: [String]
|
let scanApps: [String]?
|
||||||
let presets: [Preset]?
|
let presets: [Preset]?
|
||||||
let services: [String]?
|
let services: [String]?
|
||||||
let environmentVariables: [String: String]?
|
let environmentVariables: [String: String]?
|
||||||
@@ -39,3 +39,57 @@ struct CustomPrefs: Decodable {
|
|||||||
case environmentVariables = "export"
|
case environmentVariables = "export"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension Preferences {
|
||||||
|
func loadCustomPreferences() {
|
||||||
|
// Ensure the configuration directory is created if missing
|
||||||
|
Shell.run("mkdir -p ~/.config/phpmon")
|
||||||
|
|
||||||
|
// Move the legacy file
|
||||||
|
moveOutdatedConfigurationFile()
|
||||||
|
|
||||||
|
// Attempt to load the file if it exists
|
||||||
|
let url = URL(fileURLWithPath: "\(Paths.homePath)/.config/phpmon/config.json")
|
||||||
|
if Filesystem.fileExists(url.path) {
|
||||||
|
|
||||||
|
Log.info("A custom ~/.config/phpmon/config.json file was found. Attempting to parse...")
|
||||||
|
loadCustomPreferencesFile(url)
|
||||||
|
} else {
|
||||||
|
Log.info("There was no /.config/phpmon/config.json file to be loaded.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func moveOutdatedConfigurationFile() {
|
||||||
|
if Filesystem.fileExists("~/.phpmon.conf.json") && !Filesystem.fileExists("~/.config/phpmon/config.json") {
|
||||||
|
Log.info("An outdated configuration file was found. Moving it...")
|
||||||
|
Shell.run("cp ~/.phpmon.conf.json ~/.config/phpmon/config.json")
|
||||||
|
Log.info("The configuration file was copied successfully!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadCustomPreferencesFile(_ url: URL) {
|
||||||
|
do {
|
||||||
|
customPreferences = try JSONDecoder().decode(
|
||||||
|
CustomPrefs.self,
|
||||||
|
from: try! String(contentsOf: url, encoding: .utf8).data(using: .utf8)!
|
||||||
|
)
|
||||||
|
|
||||||
|
Log.info("The ~/.config/phpmon/config.json file was successfully parsed.")
|
||||||
|
|
||||||
|
if customPreferences.hasPresets() {
|
||||||
|
Log.info("There are \(customPreferences.presets!.count) custom presets.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if customPreferences.hasServices() {
|
||||||
|
Log.info("There are custom services: \(customPreferences.services!)")
|
||||||
|
}
|
||||||
|
|
||||||
|
if customPreferences.hasEnvironmentVariables() {
|
||||||
|
Log.info("Configuring the additional exports...")
|
||||||
|
Shell.user.exports = customPreferences.getEnvironmentVariables()
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
Log.warn("The ~/.config/phpmon/config.json file seems to be missing or malformed.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
110
phpmon/Domain/Preferences/PreferenceName.swift
Normal file
110
phpmon/Domain/Preferences/PreferenceName.swift
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
//
|
||||||
|
// PreferenceName.swift
|
||||||
|
// PHP Monitor
|
||||||
|
//
|
||||||
|
// Created by Nico Verbruggen on 07/09/2022.
|
||||||
|
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
/**
|
||||||
|
These are the keys used for every preference in the app.
|
||||||
|
*/
|
||||||
|
enum PreferenceName: String {
|
||||||
|
// FIRST-TIME LAUNCH
|
||||||
|
case wasLaunchedBefore = "launched_before"
|
||||||
|
|
||||||
|
// GENERAL
|
||||||
|
case autoServiceRestartAfterExtensionToggle = "auto_restart_after_extension_toggle"
|
||||||
|
case autoComposerGlobalUpdateAfterSwitch = "auto_composer_global_update_after_switch"
|
||||||
|
case allowProtocolForIntegrations = "allow_protocol_for_integrations"
|
||||||
|
case globalHotkey = "global_hotkey"
|
||||||
|
case automaticBackgroundUpdateCheck = "backgroundUpdateCheck"
|
||||||
|
case showPhpDoctorSuggestions = "show_php_doctor_suggestions"
|
||||||
|
|
||||||
|
// APPEARANCE
|
||||||
|
case shouldDisplayDynamicIcon = "use_dynamic_icon"
|
||||||
|
case iconTypeToDisplay = "icon_type_to_display"
|
||||||
|
case fullPhpVersionDynamicIcon = "full_php_in_menu_bar"
|
||||||
|
|
||||||
|
// WARNINGS
|
||||||
|
case warnAboutNonStandardTLD = "warn_about_non_standard_tld"
|
||||||
|
|
||||||
|
// NOTIFICATIONS
|
||||||
|
case notifyAboutVersionChange = "notify_about_version_change"
|
||||||
|
case notifyAboutPhpFpmRestart = "notify_about_php_fpm_restart"
|
||||||
|
case notifyAboutServices = "notify_about_services_restart"
|
||||||
|
case notifyAboutPresets = "notify_about_presets"
|
||||||
|
case notifyAboutSecureToggle = "notify_about_secure_toggle"
|
||||||
|
case notifyAboutGlobalComposerStatus = "notify_about_composer_status"
|
||||||
|
|
||||||
|
// MENU CUSTOMIZATION
|
||||||
|
case displayGlobalVersionSwitcher = "display_global_version_switcher"
|
||||||
|
case displayServicesManager = "display_services_manager"
|
||||||
|
case displayValetIntegration = "display_valet_integration"
|
||||||
|
case displayPhpConfigFinder = "display_php_config_finder"
|
||||||
|
case displayComposerToolkit = "display_composer_toolkit"
|
||||||
|
case displayLimitsWidget = "display_limits_widget"
|
||||||
|
case displayExtensions = "display_extensions"
|
||||||
|
case displayPresets = "display_presets"
|
||||||
|
case displayMisc = "display_misc"
|
||||||
|
|
||||||
|
/**
|
||||||
|
What type of data each preference contains.
|
||||||
|
*/
|
||||||
|
static var mapping: [PreferenceType: [PreferenceName]] = [
|
||||||
|
.boolean: [
|
||||||
|
// Preferences
|
||||||
|
.shouldDisplayDynamicIcon,
|
||||||
|
.fullPhpVersionDynamicIcon,
|
||||||
|
.autoServiceRestartAfterExtensionToggle,
|
||||||
|
.autoComposerGlobalUpdateAfterSwitch,
|
||||||
|
.allowProtocolForIntegrations,
|
||||||
|
.automaticBackgroundUpdateCheck,
|
||||||
|
.showPhpDoctorSuggestions,
|
||||||
|
|
||||||
|
// Notifications
|
||||||
|
.warnAboutNonStandardTLD,
|
||||||
|
.notifyAboutVersionChange,
|
||||||
|
.notifyAboutPhpFpmRestart,
|
||||||
|
.notifyAboutServices,
|
||||||
|
.notifyAboutPresets,
|
||||||
|
.notifyAboutSecureToggle,
|
||||||
|
.notifyAboutGlobalComposerStatus,
|
||||||
|
|
||||||
|
// UI Preferences
|
||||||
|
.displayGlobalVersionSwitcher,
|
||||||
|
.displayServicesManager,
|
||||||
|
.displayValetIntegration,
|
||||||
|
.displayPhpConfigFinder,
|
||||||
|
.displayComposerToolkit,
|
||||||
|
.displayLimitsWidget,
|
||||||
|
.displayExtensions,
|
||||||
|
.displayPresets,
|
||||||
|
.displayMisc
|
||||||
|
],
|
||||||
|
.string: [
|
||||||
|
.globalHotkey,
|
||||||
|
.iconTypeToDisplay
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
enum PreferenceType {
|
||||||
|
case boolean, string
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
These are retired preferences that, if present, should be migrated.
|
||||||
|
*/
|
||||||
|
enum RetiredPreferenceName: String {
|
||||||
|
case shouldDisplayPhpHintInIcon = "add_php_to_icon"
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
These are internal stats. They NEVER get shared.
|
||||||
|
*/
|
||||||
|
enum InternalStats: String {
|
||||||
|
case launchCount = "times_launched"
|
||||||
|
case switchCount = "times_switched_versions"
|
||||||
|
case didSeeSponsorEncouragement = "did_see_sponsor_encouragement"
|
||||||
|
}
|
@@ -8,51 +8,6 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
/**
|
|
||||||
These are the keys used for every preference in the app.
|
|
||||||
*/
|
|
||||||
enum PreferenceName: String {
|
|
||||||
// FIRST-TIME LAUNCH
|
|
||||||
case wasLaunchedBefore = "launched_before"
|
|
||||||
|
|
||||||
// GENERAL
|
|
||||||
case autoServiceRestartAfterExtensionToggle = "auto_restart_after_extension_toggle"
|
|
||||||
case autoComposerGlobalUpdateAfterSwitch = "auto_composer_global_update_after_switch"
|
|
||||||
case allowProtocolForIntegrations = "allow_protocol_for_integrations"
|
|
||||||
case globalHotkey = "global_hotkey"
|
|
||||||
case automaticBackgroundUpdateCheck = "backgroundUpdateCheck"
|
|
||||||
case showPhpDoctorSuggestions = "show_php_doctor_suggestions"
|
|
||||||
|
|
||||||
// APPEARANCE
|
|
||||||
case shouldDisplayDynamicIcon = "use_dynamic_icon"
|
|
||||||
case iconTypeToDisplay = "icon_type_to_display"
|
|
||||||
case fullPhpVersionDynamicIcon = "full_php_in_menu_bar"
|
|
||||||
|
|
||||||
// NOTIFICATIONS
|
|
||||||
case notifyAboutVersionChange = "notify_about_version_change"
|
|
||||||
case notifyAboutPhpFpmRestart = "notify_about_php_fpm_restart"
|
|
||||||
case notifyAboutServices = "notify_about_services_restart"
|
|
||||||
case notifyAboutPresets = "notify_about_presets"
|
|
||||||
case notifyAboutSecureToggle = "notify_about_secure_toggle"
|
|
||||||
case notifyAboutGlobalComposerStatus = "notify_about_composer_status"
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
These are retired preferences that, if present, should be migrated.
|
|
||||||
*/
|
|
||||||
enum RetiredPreferenceName: String {
|
|
||||||
case shouldDisplayPhpHintInIcon = "add_php_to_icon"
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
These are internal stats. They NEVER get shared.
|
|
||||||
*/
|
|
||||||
enum InternalStats: String {
|
|
||||||
case launchCount = "times_launched"
|
|
||||||
case switchCount = "times_switched_versions"
|
|
||||||
case didSeeSponsorEncouragement = "did_see_sponsor_encouragement"
|
|
||||||
}
|
|
||||||
|
|
||||||
class Preferences {
|
class Preferences {
|
||||||
|
|
||||||
// MARK: - Singleton
|
// MARK: - Singleton
|
||||||
@@ -66,7 +21,12 @@ class Preferences {
|
|||||||
public init() {
|
public init() {
|
||||||
Preferences.handleFirstTimeLaunch()
|
Preferences.handleFirstTimeLaunch()
|
||||||
cachedPreferences = Self.cache()
|
cachedPreferences = Self.cache()
|
||||||
customPreferences = CustomPrefs(scanApps: [], presets: [], services: [], environmentVariables: [:])
|
customPreferences = CustomPrefs(
|
||||||
|
scanApps: [],
|
||||||
|
presets: [],
|
||||||
|
services: [],
|
||||||
|
environmentVariables: [:]
|
||||||
|
)
|
||||||
loadCustomPreferences()
|
loadCustomPreferences()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,6 +57,7 @@ class Preferences {
|
|||||||
PreferenceName.fullPhpVersionDynamicIcon.rawValue: false,
|
PreferenceName.fullPhpVersionDynamicIcon.rawValue: false,
|
||||||
|
|
||||||
/// Preferences: Notifications
|
/// Preferences: Notifications
|
||||||
|
PreferenceName.warnAboutNonStandardTLD.rawValue: true,
|
||||||
PreferenceName.notifyAboutVersionChange.rawValue: true,
|
PreferenceName.notifyAboutVersionChange.rawValue: true,
|
||||||
PreferenceName.notifyAboutPhpFpmRestart.rawValue: true,
|
PreferenceName.notifyAboutPhpFpmRestart.rawValue: true,
|
||||||
PreferenceName.notifyAboutServices.rawValue: true,
|
PreferenceName.notifyAboutServices.rawValue: true,
|
||||||
@@ -104,6 +65,17 @@ class Preferences {
|
|||||||
PreferenceName.notifyAboutSecureToggle.rawValue: true,
|
PreferenceName.notifyAboutSecureToggle.rawValue: true,
|
||||||
PreferenceName.notifyAboutGlobalComposerStatus.rawValue: true,
|
PreferenceName.notifyAboutGlobalComposerStatus.rawValue: true,
|
||||||
|
|
||||||
|
/// Preferences: UI Preferences
|
||||||
|
PreferenceName.displayGlobalVersionSwitcher.rawValue: true,
|
||||||
|
PreferenceName.displayServicesManager.rawValue: true,
|
||||||
|
PreferenceName.displayValetIntegration.rawValue: true,
|
||||||
|
PreferenceName.displayPhpConfigFinder.rawValue: true,
|
||||||
|
PreferenceName.displayComposerToolkit.rawValue: true,
|
||||||
|
PreferenceName.displayLimitsWidget.rawValue: true,
|
||||||
|
PreferenceName.displayExtensions.rawValue: true,
|
||||||
|
PreferenceName.displayPresets.rawValue: true,
|
||||||
|
PreferenceName.displayMisc.rawValue: true,
|
||||||
|
|
||||||
/// Stats
|
/// Stats
|
||||||
InternalStats.switchCount.rawValue: 0,
|
InternalStats.switchCount.rawValue: 0,
|
||||||
InternalStats.launchCount.rawValue: 0,
|
InternalStats.launchCount.rawValue: 0,
|
||||||
@@ -160,44 +132,18 @@ class Preferences {
|
|||||||
|
|
||||||
// MARK: - Internal Functionality
|
// MARK: - Internal Functionality
|
||||||
|
|
||||||
private static func cache() -> [PreferenceName: Any] {
|
private static func cache() -> [PreferenceName: Any?] {
|
||||||
return [
|
return Dictionary(uniqueKeysWithValues: PreferenceName.mapping
|
||||||
// Part 1: Always Booleans
|
.flatMap { (key: PreferenceType, value: [PreferenceName]) in
|
||||||
.shouldDisplayDynamicIcon:
|
value.map { preference -> (PreferenceName, Any?) in
|
||||||
UserDefaults.standard.bool(
|
return (preference, { () -> Any? in
|
||||||
forKey: PreferenceName.shouldDisplayDynamicIcon.rawValue) as Any,
|
switch key {
|
||||||
.fullPhpVersionDynamicIcon: UserDefaults.standard.bool(
|
case .boolean: return UserDefaults.standard.bool(forKey: preference.rawValue)
|
||||||
forKey: PreferenceName.fullPhpVersionDynamicIcon.rawValue) as Any,
|
case .string: return UserDefaults.standard.string(forKey: preference.rawValue)
|
||||||
.autoServiceRestartAfterExtensionToggle: UserDefaults.standard.bool(
|
}
|
||||||
forKey: PreferenceName.autoServiceRestartAfterExtensionToggle.rawValue) as Any,
|
}())
|
||||||
.autoComposerGlobalUpdateAfterSwitch: UserDefaults.standard.bool(
|
}
|
||||||
forKey: PreferenceName.autoComposerGlobalUpdateAfterSwitch.rawValue) as Any,
|
})
|
||||||
.allowProtocolForIntegrations: UserDefaults.standard.bool(
|
|
||||||
forKey: PreferenceName.allowProtocolForIntegrations.rawValue) as Any,
|
|
||||||
.automaticBackgroundUpdateCheck: UserDefaults.standard.bool(
|
|
||||||
forKey: PreferenceName.automaticBackgroundUpdateCheck.rawValue) as Any,
|
|
||||||
.showPhpDoctorSuggestions: UserDefaults.standard.bool(
|
|
||||||
forKey: PreferenceName.showPhpDoctorSuggestions.rawValue) as Any,
|
|
||||||
|
|
||||||
.notifyAboutVersionChange: UserDefaults.standard.bool(
|
|
||||||
forKey: PreferenceName.notifyAboutVersionChange.rawValue) as Any,
|
|
||||||
.notifyAboutPhpFpmRestart: UserDefaults.standard.bool(
|
|
||||||
forKey: PreferenceName.notifyAboutPhpFpmRestart.rawValue) as Any,
|
|
||||||
.notifyAboutServices: UserDefaults.standard.bool(
|
|
||||||
forKey: PreferenceName.notifyAboutServices.rawValue) as Any,
|
|
||||||
.notifyAboutPresets: UserDefaults.standard.bool(
|
|
||||||
forKey: PreferenceName.notifyAboutPresets.rawValue) as Any,
|
|
||||||
.notifyAboutSecureToggle: UserDefaults.standard.bool(
|
|
||||||
forKey: PreferenceName.notifyAboutSecureToggle.rawValue) as Any,
|
|
||||||
.notifyAboutGlobalComposerStatus: UserDefaults.standard.bool(
|
|
||||||
forKey: PreferenceName.notifyAboutGlobalComposerStatus.rawValue) as Any,
|
|
||||||
|
|
||||||
// Part 2: Always Strings
|
|
||||||
.globalHotkey: UserDefaults.standard.string(
|
|
||||||
forKey: PreferenceName.globalHotkey.rawValue) as Any,
|
|
||||||
.iconTypeToDisplay: UserDefaults.standard.string(
|
|
||||||
forKey: PreferenceName.iconTypeToDisplay.rawValue) as Any
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static func update(_ preference: PreferenceName, value: Any?) {
|
static func update(_ preference: PreferenceName, value: Any?) {
|
||||||
@@ -211,59 +157,4 @@ class Preferences {
|
|||||||
// Update the preferences cache in memory!
|
// Update the preferences cache in memory!
|
||||||
Preferences.shared.cachedPreferences = Preferences.cache()
|
Preferences.shared.cachedPreferences = Preferences.cache()
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Custom Preferences
|
|
||||||
|
|
||||||
private func loadCustomPreferences() {
|
|
||||||
// Ensure the configuration directory is created if missing
|
|
||||||
Shell.run("mkdir -p ~/.config/phpmon")
|
|
||||||
|
|
||||||
// Move the legacy file
|
|
||||||
moveOutdatedConfigurationFile()
|
|
||||||
|
|
||||||
// Attempt to load the file if it exists
|
|
||||||
let url = URL(fileURLWithPath: "\(Paths.homePath)/.config/phpmon/config.json")
|
|
||||||
if Filesystem.fileExists(url.path) {
|
|
||||||
|
|
||||||
Log.info("A custom ~/.config/phpmon/config.json file was found. Attempting to parse...")
|
|
||||||
loadCustomPreferencesFile(url)
|
|
||||||
} else {
|
|
||||||
Log.info("There was no /.config/phpmon/config.json file to be loaded.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func moveOutdatedConfigurationFile() {
|
|
||||||
if Filesystem.fileExists("~/.phpmon.conf.json") && !Filesystem.fileExists("~/.config/phpmon/config.json") {
|
|
||||||
Log.info("An outdated configuration file was found. Moving it...")
|
|
||||||
Shell.run("cp ~/.phpmon.conf.json ~/.config/phpmon/config.json")
|
|
||||||
Log.info("The configuration file was copied successfully!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func loadCustomPreferencesFile(_ url: URL) {
|
|
||||||
do {
|
|
||||||
customPreferences = try JSONDecoder().decode(
|
|
||||||
CustomPrefs.self,
|
|
||||||
from: try! String(contentsOf: url, encoding: .utf8).data(using: .utf8)!
|
|
||||||
)
|
|
||||||
|
|
||||||
Log.info("The ~/.config/phpmon/config.json file was successfully parsed.")
|
|
||||||
|
|
||||||
if customPreferences.hasPresets() {
|
|
||||||
Log.info("There are \(customPreferences.presets!.count) custom presets.")
|
|
||||||
}
|
|
||||||
|
|
||||||
if customPreferences.hasServices() {
|
|
||||||
Log.info("There are custom services: \(customPreferences.services!)")
|
|
||||||
}
|
|
||||||
|
|
||||||
if customPreferences.hasEnvironmentVariables() {
|
|
||||||
Log.info("Configuring the additional exports...")
|
|
||||||
Shell.user.exports = customPreferences.getEnvironmentVariables()
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
Log.warn("The ~/.config/phpmon/config.json file seems to be missing or malformed.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -91,6 +91,11 @@ class PreferencesWindowController: PMWindowController {
|
|||||||
label: "Appearance",
|
label: "Appearance",
|
||||||
icon: "paintbrush"
|
icon: "paintbrush"
|
||||||
),
|
),
|
||||||
|
PrefTabView(
|
||||||
|
viewController: MenuStructurePreferencesVC.fromStoryboard(),
|
||||||
|
label: "Visibility",
|
||||||
|
icon: "eye"
|
||||||
|
),
|
||||||
PrefTabView(
|
PrefTabView(
|
||||||
viewController: NotificationPreferencesVC.fromStoryboard(),
|
viewController: NotificationPreferencesVC.fromStoryboard(),
|
||||||
label: "Notifications",
|
label: "Notifications",
|
||||||
|
@@ -25,7 +25,7 @@ class GenericPreferenceVC: NSViewController {
|
|||||||
// MARK: - Deinitialization
|
// MARK: - Deinitialization
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
Log.perf("PrefsVC deallocated")
|
Log.perf("deinit: \(String(describing: self)).\(#function)")
|
||||||
}
|
}
|
||||||
|
|
||||||
func getDynamicIconPV() -> NSView {
|
func getDynamicIconPV() -> NSView {
|
||||||
@@ -188,6 +188,33 @@ class GenericPreferenceVC: NSViewController {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getWarnAboutNonStandardTLD() -> NSView {
|
||||||
|
return CheckboxPreferenceView.make(
|
||||||
|
sectionText: "prefs.warnings".localized,
|
||||||
|
descriptionText: "prefs.warn_about_non_standard_tld_desc".localized,
|
||||||
|
checkboxText: "prefs.warn_about_non_standard_tld".localized,
|
||||||
|
preference: .warnAboutNonStandardTLD,
|
||||||
|
action: {}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getDisplayMenuSectionPV(
|
||||||
|
_ localizationKey: String,
|
||||||
|
_ preference: PreferenceName,
|
||||||
|
_ first: Bool = false
|
||||||
|
) -> NSView {
|
||||||
|
return CheckboxPreferenceView.make(
|
||||||
|
sectionText: first ? "prefs.menu_contents".localized : "",
|
||||||
|
descriptionText: "\(localizationKey)_desc".localized,
|
||||||
|
checkboxText: localizationKey.localized,
|
||||||
|
preference: preference,
|
||||||
|
action: {
|
||||||
|
MainMenu.shared.refreshIcon()
|
||||||
|
MainMenu.shared.rebuild()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - Listening for hotkey delegate
|
// MARK: - Listening for hotkey delegate
|
||||||
|
|
||||||
var listeningForHotkeyView: HotkeyPreferenceView?
|
var listeningForHotkeyView: HotkeyPreferenceView?
|
||||||
@@ -232,7 +259,8 @@ class NotificationPreferencesVC: GenericPreferenceVC {
|
|||||||
vc.getNotifyAboutSecureTogglePV(),
|
vc.getNotifyAboutSecureTogglePV(),
|
||||||
vc.getNotifyAboutGlobalComposerStatusPV(),
|
vc.getNotifyAboutGlobalComposerStatusPV(),
|
||||||
vc.getNotifyAboutServicesPV(),
|
vc.getNotifyAboutServicesPV(),
|
||||||
vc.getNotifyAboutPhpFpmChangePV()
|
vc.getNotifyAboutPhpFpmChangePV(),
|
||||||
|
vc.getWarnAboutNonStandardTLD()
|
||||||
]
|
]
|
||||||
|
|
||||||
return vc
|
return vc
|
||||||
@@ -240,9 +268,30 @@ class NotificationPreferencesVC: GenericPreferenceVC {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class AppearancePreferencesVC: GenericPreferenceVC {
|
class MenuStructurePreferencesVC: GenericPreferenceVC {
|
||||||
|
|
||||||
// MARK: - Lifecycle
|
public static func fromStoryboard() -> GenericPreferenceVC {
|
||||||
|
let vc = NSStoryboard(name: "Main", bundle: nil)
|
||||||
|
.instantiateController(withIdentifier: "preferencesTemplateVC") as! GenericPreferenceVC
|
||||||
|
|
||||||
|
vc.views = [
|
||||||
|
vc.getDisplayMenuSectionPV("prefs.display_global_version_switcher", .displayGlobalVersionSwitcher, true),
|
||||||
|
vc.getDisplayMenuSectionPV("prefs.display_services_manager", .displayServicesManager),
|
||||||
|
vc.getDisplayMenuSectionPV("prefs.display_valet_integration", .displayValetIntegration),
|
||||||
|
vc.getDisplayMenuSectionPV("prefs.display_php_config_finder", .displayPhpConfigFinder),
|
||||||
|
vc.getDisplayMenuSectionPV("prefs.display_composer_toolkit", .displayComposerToolkit),
|
||||||
|
vc.getDisplayMenuSectionPV("prefs.display_limits_widget", .displayLimitsWidget),
|
||||||
|
vc.getDisplayMenuSectionPV("prefs.display_extensions", .displayExtensions),
|
||||||
|
vc.getDisplayMenuSectionPV("prefs.display_presets", .displayPresets),
|
||||||
|
vc.getDisplayMenuSectionPV("prefs.display_misc", .displayMisc)
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
|
return vc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AppearancePreferencesVC: GenericPreferenceVC {
|
||||||
|
|
||||||
public static func fromStoryboard() -> GenericPreferenceVC {
|
public static func fromStoryboard() -> GenericPreferenceVC {
|
||||||
let vc = NSStoryboard(name: "Main", bundle: nil)
|
let vc = NSStoryboard(name: "Main", bundle: nil)
|
||||||
|
@@ -167,14 +167,15 @@ struct Preset: Codable, Equatable {
|
|||||||
|
|
||||||
// MARK: - Menu Items
|
// MARK: - Menu Items
|
||||||
|
|
||||||
|
// swiftlint:disable void_function_in_ternary
|
||||||
public func getMenuItemText() -> String {
|
public func getMenuItemText() -> String {
|
||||||
var info = extensions.count == 1
|
var info = extensions.count == 1
|
||||||
? "preset.extension".localized(extensions.count)
|
? "preset.extension".localized(extensions.count)
|
||||||
: "preset.extensions".localized(extensions.count)
|
: "preset.extensions".localized(extensions.count)
|
||||||
info += ", "
|
info += ", "
|
||||||
info += configuration.count == 1
|
info += configuration.count == 1
|
||||||
? "preset.preference".localized(configuration.count)
|
? "preset.preference".localized(configuration.count)
|
||||||
: "preset.preferences".localized(configuration.count)
|
: "preset.preferences".localized(configuration.count)
|
||||||
|
|
||||||
if self.version == nil {
|
if self.version == nil {
|
||||||
return "<span style=\"font-family: '-apple-system'; font-size: 12px;\">"
|
return "<span style=\"font-family: '-apple-system'; font-size: 12px;\">"
|
||||||
|
@@ -18,7 +18,7 @@ class ProgressViewController: NSViewController {
|
|||||||
@IBOutlet weak var imageViewType: NSImageView!
|
@IBOutlet weak var imageViewType: NSImageView!
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
Log.perf("Deinitializing ProgressViewController")
|
Log.perf("deinit: \(String(describing: self)).\(#function)")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -56,7 +56,7 @@ class TerminalProgressWindowController: NSWindowController, NSWindowDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
Log.perf("Deinitializing ProgressWindowController")
|
Log.perf("deinit: \(String(describing: self)).\(#function)")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -10,8 +10,13 @@ import Foundation
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
var isRunningSwiftUIPreview: Bool {
|
var isRunningSwiftUIPreview: Bool {
|
||||||
return ProcessInfo.processInfo
|
#if DEBUG
|
||||||
.environment["XCODE_RUNNING_FOR_PREVIEWS"] != nil
|
// If running SwiftUI *and* when debugging
|
||||||
|
return ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] != nil
|
||||||
|
#else
|
||||||
|
// Release builds should always return false here
|
||||||
|
return false
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Color {
|
extension Color {
|
||||||
|
37
phpmon/Domain/SwiftUI/Domains/NoDomainResultsView.swift
Normal file
37
phpmon/Domain/SwiftUI/Domains/NoDomainResultsView.swift
Normal file
@@ -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()
|
||||||
|
}
|
||||||
|
}
|
@@ -26,11 +26,17 @@ struct HeaderView: View {
|
|||||||
|
|
||||||
static func asMenuItem(
|
static func asMenuItem(
|
||||||
text: String,
|
text: String,
|
||||||
width: Int? = nil
|
minimumWidth: CGFloat? = nil
|
||||||
) -> NSMenuItem {
|
) -> NSMenuItem {
|
||||||
let view = NSHostingView(rootView: Self(text: text))
|
let view = NSHostingView(rootView: Self(text: text))
|
||||||
view.autoresizingMask = [.width, .height]
|
view.autoresizingMask = [.width, .height]
|
||||||
view.setFrameSize(CGSize(width: view.frame.width, height: 24))
|
|
||||||
|
var finalWidth = view.frame.width
|
||||||
|
if minimumWidth != nil && minimumWidth! > finalWidth {
|
||||||
|
finalWidth = minimumWidth!
|
||||||
|
}
|
||||||
|
|
||||||
|
view.setFrameSize(CGSize(width: finalWidth, height: 24))
|
||||||
|
|
||||||
let item = NSMenuItem()
|
let item = NSMenuItem()
|
||||||
item.view = view
|
item.view = view
|
||||||
|
@@ -17,9 +17,9 @@ struct ServicesView: View {
|
|||||||
static func asMenuItem(perRow: Int = 3) -> NSMenuItem {
|
static func asMenuItem(perRow: Int = 3) -> NSMenuItem {
|
||||||
let item = NSMenuItem()
|
let item = NSMenuItem()
|
||||||
var services = [
|
var services = [
|
||||||
PhpEnv.phpInstall.formula,
|
Homebrew.Formulae.php,
|
||||||
"nginx",
|
Homebrew.Formulae.nginx,
|
||||||
"dnsmasq"
|
Homebrew.Formulae.dnsmasq
|
||||||
]
|
]
|
||||||
|
|
||||||
if Preferences.custom.hasServices() {
|
if Preferences.custom.hasServices() {
|
||||||
|
@@ -19,7 +19,6 @@ struct NoWarningsView: View {
|
|||||||
VStack(alignment: .center) {
|
VStack(alignment: .center) {
|
||||||
Text("warnings.none".localizedForSwiftUI)
|
Text("warnings.none".localizedForSwiftUI)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
.frame(minWidth: 0, maxWidth: .infinity)
|
.frame(minWidth: 0, maxWidth: .infinity)
|
||||||
.padding(25)
|
.padding(25)
|
||||||
|
@@ -74,12 +74,10 @@ class WarningManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func loopOverEvaluations() async {
|
private func loopOverEvaluations() async {
|
||||||
for check in self.evaluations {
|
for check in self.evaluations where await check.applies() {
|
||||||
if await check.applies() {
|
Log.info("[DOCTOR] \(check.name) (!)")
|
||||||
Log.info("[DOCTOR] \(check.name) (!)")
|
self.warnings.append(check)
|
||||||
self.warnings.append(check)
|
continue
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -68,7 +68,7 @@ class PhpConfigWatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
Log.perf("A PhpConfigWatcher has been deinitialized.")
|
Log.perf("deinit: \(String(describing: self)).\(#function)")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -100,6 +100,9 @@
|
|||||||
"domain_list.title" = "Domains";
|
"domain_list.title" = "Domains";
|
||||||
"domain_list.subtitle" = "";
|
"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.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.";
|
"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.";
|
||||||
|
|
||||||
@@ -164,10 +167,13 @@
|
|||||||
|
|
||||||
// SITE LIST ACTIONS
|
// SITE LIST ACTIONS
|
||||||
|
|
||||||
"domain_list.isolate" = "Isolate Domain";
|
"domain_list.isolate" = "Switch PHP Version";
|
||||||
|
"domain_list.site_isolation" = "Site Isolation";
|
||||||
"domain_list.remove_isolation" = "Remove Isolation";
|
"domain_list.remove_isolation" = "Remove Isolation";
|
||||||
|
"domain_list.always_use_php" = "Always use PHP %@";
|
||||||
"domain_list.isolation_unavailable" = "Isolation Not Supported (in Valet 2)";
|
"domain_list.isolation_unavailable" = "Isolation Not Supported (in Valet 2)";
|
||||||
|
|
||||||
|
"domain_list.actions" = "Actions";
|
||||||
"domain_list.unlink" = "Unlink Directory";
|
"domain_list.unlink" = "Unlink Directory";
|
||||||
"domain_list.secure" = "Secure Domain";
|
"domain_list.secure" = "Secure Domain";
|
||||||
"domain_list.unsecure" = "Unsecure Domain";
|
"domain_list.unsecure" = "Unsecure Domain";
|
||||||
@@ -221,6 +227,8 @@
|
|||||||
"prefs.integrations" = "Integrations:";
|
"prefs.integrations" = "Integrations:";
|
||||||
"prefs.updates" = "Updates:";
|
"prefs.updates" = "Updates:";
|
||||||
"prefs.notifications" = "Notifications:";
|
"prefs.notifications" = "Notifications:";
|
||||||
|
"prefs.warnings" = "Warnings:";
|
||||||
|
"prefs.menu_contents" = "Features in Menu:";
|
||||||
|
|
||||||
"prefs.icon_options.php" = "Display PHP Icon";
|
"prefs.icon_options.php" = "Display PHP Icon";
|
||||||
"prefs.icon_options.elephant" = "Display Elephant Icon";
|
"prefs.icon_options.elephant" = "Display Elephant Icon";
|
||||||
@@ -246,7 +254,7 @@
|
|||||||
"prefs.automatic_update_check_title" = "Automatically check for updates";
|
"prefs.automatic_update_check_title" = "Automatically check for updates";
|
||||||
"prefs.automatic_update_check_desc" = "When checked, PHP Monitor will automatically check if there is a newer version available, and notify you if that is the case.";
|
"prefs.automatic_update_check_desc" = "When checked, PHP Monitor will automatically check if there is a newer version available, and notify you if that is the case.";
|
||||||
|
|
||||||
"prefs.php_doctor_suggestions_title" = "Show suggestions (if applicable)";
|
"prefs.php_doctor_suggestions_title" = "Always show suggestions";
|
||||||
"prefs.php_doctor_suggestions_desc" = "If you uncheck this item, no PHP Doctor suggestions will appear in PHP Monitor's menu. Keep in mind that PHP Doctor will not appear if there are no recommendations.";
|
"prefs.php_doctor_suggestions_desc" = "If you uncheck this item, no PHP Doctor suggestions will appear in PHP Monitor's menu. Keep in mind that PHP Doctor will not appear if there are no recommendations.";
|
||||||
|
|
||||||
"prefs.shortcut_set" = "Set global shortcut";
|
"prefs.shortcut_set" = "Set global shortcut";
|
||||||
@@ -272,6 +280,36 @@
|
|||||||
"prefs.notify_about_composer_success_desc" = "Displays a notification when the global Composer configuration was successfully updated.";
|
"prefs.notify_about_composer_success_desc" = "Displays a notification when the global Composer configuration was successfully updated.";
|
||||||
"prefs.notify_about_composer_success" = "Notify about global composer update";
|
"prefs.notify_about_composer_success" = "Notify about global composer update";
|
||||||
|
|
||||||
|
"prefs.warn_about_non_standard_tld_desc" = "If you use a non-standard TLD, you may not wish to get repeated notifications about this.";
|
||||||
|
"prefs.warn_about_non_standard_tld" = "Warn about non-standard TLD";
|
||||||
|
|
||||||
|
"prefs.display_global_version_switcher_desc" = "If disabled, you will not be able to change the globally linked PHP version via the main menu.";
|
||||||
|
"prefs.display_global_version_switcher" = "PHP Switcher";
|
||||||
|
|
||||||
|
"prefs.display_services_manager_desc" = "If disabled, you will not be able to see, start or stop individual services. (If any services are disabled, you will not be easily able to see that this is the case.)";
|
||||||
|
"prefs.display_services_manager" = "Services Manager";
|
||||||
|
|
||||||
|
"prefs.display_valet_integration_desc" = "If disabled, you will not be able to locate the main Valet folder or open the list of domains.";
|
||||||
|
"prefs.display_valet_integration" = "Valet Integration";
|
||||||
|
|
||||||
|
"prefs.display_php_config_finder_desc" = "If disabled, you will not be able to easily locate your PHP configuration files and/or generate a phpinfo() dump.";
|
||||||
|
"prefs.display_php_config_finder" = "PHP Config Finder";
|
||||||
|
|
||||||
|
"prefs.display_composer_toolkit_desc" = "If disabled, you will not be able to invoke Composer via the main menu. The automatic Composer update after switching preference is unaffected by this change.";
|
||||||
|
"prefs.display_composer_toolkit" = "Composer Toolkit";
|
||||||
|
|
||||||
|
"prefs.display_limits_widget_desc" = "If disabled, you will not be able to see the limits widget (memory, POST, upload) in the main menu.";
|
||||||
|
"prefs.display_limits_widget" = "Limits Widget";
|
||||||
|
|
||||||
|
"prefs.display_extensions_desc" = "If disabled, you will not be able to easily toggle extensions via the main menu.";
|
||||||
|
"prefs.display_extensions" = "Extensions";
|
||||||
|
|
||||||
|
"prefs.display_presets_desc" = "If disabled, you will not be able to apply or revert PHP configuration presets.";
|
||||||
|
"prefs.display_presets" = "Presets";
|
||||||
|
|
||||||
|
"prefs.display_misc_desc" = "If disabled, you will not be able to access the First Aid & Services menu.";
|
||||||
|
"prefs.display_misc" = "First Aid & Services Menu";
|
||||||
|
|
||||||
// NOTIFICATIONS
|
// NOTIFICATIONS
|
||||||
|
|
||||||
"notification.version_changed_title" = "PHP %@ now active";
|
"notification.version_changed_title" = "PHP %@ now active";
|
||||||
@@ -365,7 +403,7 @@ problem manually, using your own Terminal app (this just shows you the output)."
|
|||||||
// PHP FPM Broken
|
// PHP FPM Broken
|
||||||
"alert.php_fpm_broken.title" = "Your PHP-FPM configuration is not pointing at the Valet socket!";
|
"alert.php_fpm_broken.title" = "Your PHP-FPM configuration is not pointing at the Valet socket!";
|
||||||
"alert.php_fpm_broken.info" = "PHP Monitor has determined that there are issues with your PHP-FPM config. This will result in '502 Bad Gateway' responses if you visit websites linked via Valet.";
|
"alert.php_fpm_broken.info" = "PHP Monitor has determined that there are issues with your PHP-FPM config. This will result in '502 Bad Gateway' responses if you visit websites linked via Valet.";
|
||||||
"alert.php_fpm_broken.description" = "If it's been a while, you can usually fix this by running `valet install`, which updates your PHP-FPM configuration.\n\nIf you are seeing this message and you are trying to run a pre-release version of PHP, it is possible that Valet does not support this pre-release version of PHP yet.\n\nIf that is the case, you can try the following workaround: edit the file at `~/.composer/vendor/laravel/valet/cli/Valet/Brew.php` and add e.g. `php@8.2` to the `SUPPORTED_PHP_VERSIONS` array. After editing the file, try running `valet install`. (This will, if all goes well, set up all the required Valet configuration files.)";
|
"alert.php_fpm_broken.description" = "If it's been a while, you can usually fix this by running `valet install`, which updates your PHP-FPM configuration.\n\nIf you are seeing this message and you are trying to run a pre-release version of PHP, it is possible that Valet does not support this pre-release version of PHP yet.\n\nYou may need to upgrade your installation of Laravel Valet to at least v3.1.11, after that you should run `valet install`. More information here: https://phpmon.app/prerelease-php";
|
||||||
|
|
||||||
// PHP Monitor Cannot Start
|
// PHP Monitor Cannot Start
|
||||||
"alert.cannot_start.title" = "PHP Monitor cannot start due to a problem with your system configuration";
|
"alert.cannot_start.title" = "PHP Monitor cannot start due to a problem with your system configuration";
|
||||||
@@ -470,7 +508,7 @@ If you are seeing this message but are confused why this folder has gone missing
|
|||||||
/// Cannot retrieve services
|
/// Cannot retrieve services
|
||||||
"startup.errors.services_json_error.title" = "Cannot determine services status";
|
"startup.errors.services_json_error.title" = "Cannot determine services status";
|
||||||
"startup.errors.services_json_error.subtitle" = "PHP Monitor usually queries `brew` using the following command to test if the services can be retrieved: `sudo brew services info nginx --json`.\n\nPHP Monitor could not interpret this response.";
|
"startup.errors.services_json_error.subtitle" = "PHP Monitor usually queries `brew` using the following command to test if the services can be retrieved: `sudo brew services info nginx --json`.\n\nPHP Monitor could not interpret this response.";
|
||||||
"startup.errors.services_json_error.desc" = "This can happen if your Homebrew installation is out of date, in which case Homebrew won't return JSON yet. You can usually fix this by running `brew update`. You can also try running `sudo brew services info nginx --json` in your terminal of choice.";
|
"startup.errors.services_json_error.desc" = "This can happen if your Homebrew installation is out of date, in which case Homebrew won't return JSON yet. You can usually fix this by running `brew update` or `brew tap homebrew/services`. You can also try running `sudo brew services info nginx --json` in your terminal of choice.";
|
||||||
|
|
||||||
/// Issue with `which` alias
|
/// Issue with `which` alias
|
||||||
"startup.errors.which_alias_issue.title" = "A configuration issue was detected";
|
"startup.errors.which_alias_issue.title" = "A configuration issue was detected";
|
||||||
@@ -514,6 +552,7 @@ If you are seeing this message but are confused why this folder has gone missing
|
|||||||
"alert.warnings.tld_issue.title" = "You are not using `.test` as the TLD for Valet.";
|
"alert.warnings.tld_issue.title" = "You are not using `.test` as the TLD for Valet.";
|
||||||
"alert.warnings.tld_issue.subtitle" = "Using a non-default TLD may not work correctly and is not officially supported.";
|
"alert.warnings.tld_issue.subtitle" = "Using a non-default TLD may not work correctly and is not officially supported.";
|
||||||
"alert.warnings.tld_issue.description" = "PHP Monitor will remain functional, but there might be issues: the app might not correctly show which domains have been secured. For optimal results, go to your Valet configuration file (config.json in the Valet directory) and change the TLD back to `test`.";
|
"alert.warnings.tld_issue.description" = "PHP Monitor will remain functional, but there might be issues: the app might not correctly show which domains have been secured. For optimal results, go to your Valet configuration file (config.json in the Valet directory) and change the TLD back to `test`.";
|
||||||
|
"alert.do_not_tell_again" = "Don't Tell Me Again";
|
||||||
|
|
||||||
// WARNINGS
|
// WARNINGS
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user