mirror of
https://github.com/nicoverbruggen/phpmon.git
synced 2025-08-07 12:00:09 +02:00
🔀 Merge branch 'main' into dev/5.4
This commit is contained in:
@ -9,6 +9,7 @@
|
||||
/* Begin PBXBuildFile section */
|
||||
5420395926135DC100FB00FA /* PrefsVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5420395826135DC100FB00FA /* PrefsVC.swift */; };
|
||||
5420395F2613607600FB00FA /* Preferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5420395E2613607600FB00FA /* Preferences.swift */; };
|
||||
54A18D40282A566E000A0D81 /* nginx-secure-proxy-custom-tld.test in Resources */ = {isa = PBXBuildFile; fileRef = 54A18D3F282A566E000A0D81 /* nginx-secure-proxy-custom-tld.test */; };
|
||||
54B48B5F275F66AE006D90C5 /* Application.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54B48B5E275F66AE006D90C5 /* Application.swift */; };
|
||||
54B48B60275F66AE006D90C5 /* Application.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54B48B5E275F66AE006D90C5 /* Application.swift */; };
|
||||
54D9E0B227E4F51E003B9AD9 /* HotKeysController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54D9E0AC27E4F51E003B9AD9 /* HotKeysController.swift */; };
|
||||
@ -51,6 +52,9 @@
|
||||
C40C7F2927721FF600DDDCDC /* ActivePhpInstallation+Checks.swift in Sources */ = {isa = PBXBuildFile; fileRef = C40C7F2727721FF600DDDCDC /* ActivePhpInstallation+Checks.swift */; };
|
||||
C40C7F3027722E8D00DDDCDC /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = C40C7F2F27722E8D00DDDCDC /* Logger.swift */; };
|
||||
C40C7F3127722E8D00DDDCDC /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = C40C7F2F27722E8D00DDDCDC /* Logger.swift */; };
|
||||
C40FE737282ABA4F00A302C2 /* AppVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = C40FE736282ABA4F00A302C2 /* AppVersion.swift */; };
|
||||
C40FE738282ABA4F00A302C2 /* AppVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = C40FE736282ABA4F00A302C2 /* AppVersion.swift */; };
|
||||
C40FE73B282ABB2E00A302C2 /* AppVersionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C40FE739282ABB2E00A302C2 /* AppVersionTest.swift */; };
|
||||
C412E5FC25700D5300A1FB67 /* HomebrewPackage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C412E5FB25700D5300A1FB67 /* HomebrewPackage.swift */; };
|
||||
C415937F27A1B54F00D2E1B7 /* PhpFrameworks.swift in Sources */ = {isa = PBXBuildFile; fileRef = C415937E27A1B54F00D2E1B7 /* PhpFrameworks.swift */; };
|
||||
C415938027A1B54F00D2E1B7 /* PhpFrameworks.swift in Sources */ = {isa = PBXBuildFile; fileRef = C415937E27A1B54F00D2E1B7 /* PhpFrameworks.swift */; };
|
||||
@ -117,6 +121,9 @@
|
||||
C464ADAF275A7A69003FCD53 /* DomainListVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C464ADAE275A7A69003FCD53 /* DomainListVC.swift */; };
|
||||
C464ADB0275A7A6A003FCD53 /* DomainListVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C464ADAE275A7A69003FCD53 /* DomainListVC.swift */; };
|
||||
C464ADB2275A87CA003FCD53 /* DomainListCellProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = C464ADB1275A87CA003FCD53 /* DomainListCellProtocol.swift */; };
|
||||
C46E206D28299B3800D909D6 /* AppUpdateChecker.swift in Sources */ = {isa = PBXBuildFile; fileRef = C46E206C28299B3800D909D6 /* AppUpdateChecker.swift */; };
|
||||
C46E206E28299B3800D909D6 /* AppUpdateChecker.swift in Sources */ = {isa = PBXBuildFile; fileRef = C46E206C28299B3800D909D6 /* AppUpdateChecker.swift */; };
|
||||
C46E20702829D27F00D909D6 /* AppUpdaterCheckTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C46E206F2829D27F00D909D6 /* AppUpdaterCheckTest.swift */; };
|
||||
C46FA23F246C358E00944F05 /* StringExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C46FA23E246C358E00944F05 /* StringExtension.swift */; };
|
||||
C46FA9882822EFDC00D78807 /* PhpConfigurationFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = C46FA9872822EFDC00D78807 /* PhpConfigurationFile.swift */; };
|
||||
C46FA9892822EFDC00D78807 /* PhpConfigurationFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = C46FA9872822EFDC00D78807 /* PhpConfigurationFile.swift */; };
|
||||
@ -272,6 +279,7 @@
|
||||
/* Begin PBXFileReference section */
|
||||
5420395826135DC100FB00FA /* PrefsVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrefsVC.swift; sourceTree = "<group>"; };
|
||||
5420395E2613607600FB00FA /* Preferences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Preferences.swift; sourceTree = "<group>"; };
|
||||
54A18D3F282A566E000A0D81 /* nginx-secure-proxy-custom-tld.test */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "nginx-secure-proxy-custom-tld.test"; sourceTree = "<group>"; };
|
||||
54B48B5E275F66AE006D90C5 /* Application.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Application.swift; sourceTree = "<group>"; };
|
||||
54D9E0AC27E4F51E003B9AD9 /* HotKeysController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HotKeysController.swift; sourceTree = "<group>"; };
|
||||
54D9E0AD27E4F51E003B9AD9 /* Key.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Key.swift; sourceTree = "<group>"; };
|
||||
@ -294,6 +302,8 @@
|
||||
C40C7F1D2772136000DDDCDC /* PhpEnv.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhpEnv.swift; sourceTree = "<group>"; };
|
||||
C40C7F2727721FF600DDDCDC /* ActivePhpInstallation+Checks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ActivePhpInstallation+Checks.swift"; sourceTree = "<group>"; };
|
||||
C40C7F2F27722E8D00DDDCDC /* Logger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Logger.swift; sourceTree = "<group>"; };
|
||||
C40FE736282ABA4F00A302C2 /* AppVersion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppVersion.swift; sourceTree = "<group>"; };
|
||||
C40FE739282ABB2E00A302C2 /* AppVersionTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppVersionTest.swift; sourceTree = "<group>"; };
|
||||
C412E5FB25700D5300A1FB67 /* HomebrewPackage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomebrewPackage.swift; sourceTree = "<group>"; };
|
||||
C415937E27A1B54F00D2E1B7 /* PhpFrameworks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhpFrameworks.swift; sourceTree = "<group>"; };
|
||||
C415D3B62770F294005EF286 /* Actions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Actions.swift; sourceTree = "<group>"; };
|
||||
@ -340,6 +350,8 @@
|
||||
C464ADAB275A7A3F003FCD53 /* DomainListWC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DomainListWC.swift; sourceTree = "<group>"; };
|
||||
C464ADAE275A7A69003FCD53 /* DomainListVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DomainListVC.swift; sourceTree = "<group>"; };
|
||||
C464ADB1275A87CA003FCD53 /* DomainListCellProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DomainListCellProtocol.swift; sourceTree = "<group>"; };
|
||||
C46E206C28299B3800D909D6 /* AppUpdateChecker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppUpdateChecker.swift; sourceTree = "<group>"; };
|
||||
C46E206F2829D27F00D909D6 /* AppUpdaterCheckTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppUpdaterCheckTest.swift; sourceTree = "<group>"; };
|
||||
C46FA23E246C358E00944F05 /* StringExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringExtension.swift; sourceTree = "<group>"; };
|
||||
C46FA9872822EFDC00D78807 /* PhpConfigurationFile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhpConfigurationFile.swift; sourceTree = "<group>"; };
|
||||
C46FA98A2822F08F00D78807 /* PhpIniTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhpIniTest.swift; sourceTree = "<group>"; };
|
||||
@ -658,8 +670,9 @@
|
||||
C459B4BE27F6093A00E9B4B4 /* nginx */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C42F26752805FEE200938AC7 /* nginx-secure-proxy.test */,
|
||||
C459B4BC27F6093700E9B4B4 /* nginx-proxy.test */,
|
||||
C42F26752805FEE200938AC7 /* nginx-secure-proxy.test */,
|
||||
54A18D3F282A566E000A0D81 /* nginx-secure-proxy-custom-tld.test */,
|
||||
C42CFB1527DFDE7900862737 /* nginx-site.test */,
|
||||
C42CFB1727DFDFDC00862737 /* nginx-site-isolated.test */,
|
||||
);
|
||||
@ -792,6 +805,8 @@
|
||||
C4B97B7A275CF20A003F3378 /* App+GlobalHotkey.swift */,
|
||||
C4EED88827A48778006D7272 /* InterAppHandler.swift */,
|
||||
C4D8016522B1584700C6DA1B /* Startup.swift */,
|
||||
C46E206C28299B3800D909D6 /* AppUpdateChecker.swift */,
|
||||
C40FE736282ABA4F00A302C2 /* AppVersion.swift */,
|
||||
);
|
||||
path = App;
|
||||
sourceTree = "<group>";
|
||||
@ -874,6 +889,8 @@
|
||||
C48D6C73279CD3E400F26D7E /* PhpVersionNumberTest.swift */,
|
||||
C4B56360276AB0A500F12CCB /* VersionExtractorTest.swift */,
|
||||
C4AF9F7C275454A900D44ED0 /* ValetVersionExtractorTest.swift */,
|
||||
C40FE739282ABB2E00A302C2 /* AppVersionTest.swift */,
|
||||
C46E206F2829D27F00D909D6 /* AppUpdaterCheckTest.swift */,
|
||||
);
|
||||
path = Versions;
|
||||
sourceTree = "<group>";
|
||||
@ -1093,6 +1110,7 @@
|
||||
C44C1992276E44CB0072762D /* ProgressWindow.storyboard in Resources */,
|
||||
C42F26762805FEE200938AC7 /* nginx-secure-proxy.test in Resources */,
|
||||
C4F30B08278E195800755FCE /* brew-services.json in Resources */,
|
||||
54A18D40282A566E000A0D81 /* nginx-secure-proxy-custom-tld.test in Resources */,
|
||||
C42CFB1627DFDE7900862737 /* nginx-site.test in Resources */,
|
||||
C459B4BD27F6093700E9B4B4 /* nginx-proxy.test in Resources */,
|
||||
);
|
||||
@ -1157,6 +1175,7 @@
|
||||
C41C02A927E61A65009F26CB /* ValetSite+Fake.swift in Sources */,
|
||||
C4C0E8DF27F88AEB002D32A9 /* FakeSiteScanner.swift in Sources */,
|
||||
C4F2E4372752F0870020E974 /* HomebrewDiagnostics.swift in Sources */,
|
||||
C40FE737282ABA4F00A302C2 /* AppVersion.swift in Sources */,
|
||||
C4CCBA6C275C567B008C7055 /* PMWindowController.swift in Sources */,
|
||||
C4B585442770FE3900DA4FBE /* Command.swift in Sources */,
|
||||
C44067F527E2582B0045BD4E /* DomainListNameCell.swift in Sources */,
|
||||
@ -1186,6 +1205,7 @@
|
||||
C4811D2A22D70F9A00B5F6B3 /* MainMenu.swift in Sources */,
|
||||
C40C7F3027722E8D00DDDCDC /* Logger.swift in Sources */,
|
||||
C41CA5ED2774F8EE00A2C80E /* DomainListVC+Actions.swift in Sources */,
|
||||
C46E206D28299B3800D909D6 /* AppUpdateChecker.swift in Sources */,
|
||||
C412E5FC25700D5300A1FB67 /* HomebrewPackage.swift in Sources */,
|
||||
C4D9ADBF277610E1007277F4 /* PhpSwitcher.swift in Sources */,
|
||||
C4068CAA27B0890D00544CD5 /* MenuBarIcons.swift in Sources */,
|
||||
@ -1298,6 +1318,7 @@
|
||||
C40C7F3127722E8D00DDDCDC /* Logger.swift in Sources */,
|
||||
C4068CAB27B0890D00544CD5 /* MenuBarIcons.swift in Sources */,
|
||||
C4F30B09278E1A0E00755FCE /* CustomPrefs.swift in Sources */,
|
||||
C40FE738282ABA4F00A302C2 /* AppVersion.swift in Sources */,
|
||||
C415D3E92770F692005EF286 /* AppDelegate+InterApp.swift in Sources */,
|
||||
C484437C2804BB560041A78A /* ValetProxyScanner.swift in Sources */,
|
||||
C4AF9F78275447F100D44ED0 /* ValetConfigurationTest.swift in Sources */,
|
||||
@ -1309,6 +1330,7 @@
|
||||
54D9E0B327E4F51E003B9AD9 /* HotKeysController.swift in Sources */,
|
||||
C4B97B79275CF1B5003F3378 /* App+ActivationPolicy.swift in Sources */,
|
||||
C4CE3BBB27B324230086CA49 /* MainMenu+Switcher.swift in Sources */,
|
||||
C46E20702829D27F00D909D6 /* AppUpdaterCheckTest.swift in Sources */,
|
||||
C4F7809C25D80344000DBC97 /* CommandTest.swift in Sources */,
|
||||
C44CCD4127AFE2FC00CE40E5 /* AlertableError.swift in Sources */,
|
||||
C4D936CA27E3EB6100BD69FE /* PhpHelper.swift in Sources */,
|
||||
@ -1354,8 +1376,10 @@
|
||||
C464ADB0275A7A6A003FCD53 /* DomainListVC.swift in Sources */,
|
||||
C43A8A1A25D9CD1000591B77 /* Utility.swift in Sources */,
|
||||
C418898A275FE8CB001EF227 /* Filesystem.swift in Sources */,
|
||||
C40FE73B282ABB2E00A302C2 /* AppVersionTest.swift in Sources */,
|
||||
C4F780C625D80B75000DBC97 /* XibLoadable.swift in Sources */,
|
||||
C4EE55AA27708B9E001DF387 /* PMHeaderView.swift in Sources */,
|
||||
C46E206E28299B3800D909D6 /* AppUpdateChecker.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -1501,12 +1525,12 @@
|
||||
C41C1B4422B0098000E7CF16 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIconDev;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_ENTITLEMENTS = phpmon/phpmon.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 770;
|
||||
CURRENT_PROJECT_VERSION = 786;
|
||||
DEBUG = YES;
|
||||
DEVELOPMENT_TEAM = 8M54J5J787;
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
@ -1516,7 +1540,7 @@
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 11.0;
|
||||
MARKETING_VERSION = "5.3-dev";
|
||||
MARKETING_VERSION = 5.3;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
@ -1527,12 +1551,12 @@
|
||||
C41C1B4522B0098000E7CF16 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIconDev;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_ENTITLEMENTS = phpmon/phpmon.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 770;
|
||||
CURRENT_PROJECT_VERSION = 786;
|
||||
DEBUG = NO;
|
||||
DEVELOPMENT_TEAM = 8M54J5J787;
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
@ -1542,7 +1566,7 @@
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 11.0;
|
||||
MARKETING_VERSION = "5.3-dev";
|
||||
MARKETING_VERSION = 5.3;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
|
@ -61,6 +61,12 @@
|
||||
ReferencedContainer = "container:PHP Monitor.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<CommandLineArguments>
|
||||
<CommandLineArgument
|
||||
argument = "--v"
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
</CommandLineArguments>
|
||||
<EnvironmentVariables>
|
||||
<EnvironmentVariable
|
||||
key = "PHPMON_MARKETING_MODE"
|
||||
|
17
README.md
17
README.md
@ -149,6 +149,15 @@ This should install `dnsmasq` and set up Valet. Great, almost there!
|
||||
Finally, run PHP Monitor. Since the app is notarized and signed with a developer ID, it should work.
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>How frequently does PHP Monitor check for updates?</strong></summary>
|
||||
|
||||
PHP Monitor will check if an update is available every time you start the app.
|
||||
|
||||
You can disable this behaviour by going to Preferences (via the PHP Monitor icon in the menu bar) and unchecking "Automatically check for updates". You can always check for updates manually.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>I have PHP Monitor installed, and it works. I want to upgrade my PHP installations to the latest version, what's the best way to do this?</strong></summary>
|
||||
|
||||
@ -278,9 +287,13 @@ PHP Monitor is a universal app and supports both architectures, so [find out her
|
||||
<details>
|
||||
<summary><strong>Why is the app doing network requests?</strong></summary>
|
||||
|
||||
It's Homebrew. I can't prevent `brew` from doing things via the network when I invoke it.
|
||||
The app will automatically check for updates, which is the most likely culprit.
|
||||
|
||||
PHP Monitor itself doesn't do any network requests. Feel free to check the source code or intercept the traffic, if you don't believe me.
|
||||
This happens at launch (unless disabled), and the app directly checks the Caskfile hosted on GitHub. This data is not, and will not be used for analytics (and, as far as I can tell, cannot).
|
||||
|
||||
I also can't prevent `brew` from doing things via the network when PHP Monitor uses the binary.
|
||||
|
||||
The app includes an Internet Access Policy file, so if you're using something like Little Snitch there should be a description why these calls occur.
|
||||
|
||||
</details>
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
// phpmon-tests
|
||||
//
|
||||
// Created by Nico Verbruggen on 13/02/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
|
@ -3,7 +3,7 @@
|
||||
// phpmon-tests
|
||||
//
|
||||
// Created by Nico Verbruggen on 14/02/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
|
@ -3,13 +3,15 @@
|
||||
// phpmon-tests
|
||||
//
|
||||
// Created by Nico Verbruggen on 29/11/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
|
||||
class NginxConfigurationTest: XCTestCase {
|
||||
|
||||
// MARK: - Test Files
|
||||
|
||||
static var regularUrl: URL {
|
||||
return Bundle(for: Self.self).url(forResource: "nginx-site", withExtension: "test")!
|
||||
}
|
||||
@ -26,42 +28,54 @@ class NginxConfigurationTest: XCTestCase {
|
||||
return Bundle(for: Self.self).url(forResource: "nginx-secure-proxy", withExtension: "test")!
|
||||
}
|
||||
|
||||
static var customTldProxyUrl: URL {
|
||||
return Bundle(for: Self.self).url(forResource: "nginx-secure-proxy-custom-tld", withExtension: "test")!
|
||||
}
|
||||
|
||||
// MARK: - Tests
|
||||
|
||||
func testCanDetermineSiteNameAndTld() throws {
|
||||
XCTAssertEqual(
|
||||
"nginx-site",
|
||||
NginxConfiguration(filePath: NginxConfigurationTest.regularUrl.path).domain
|
||||
NginxConfiguration.from(filePath: NginxConfigurationTest.regularUrl.path)?.domain
|
||||
)
|
||||
XCTAssertEqual(
|
||||
"test",
|
||||
NginxConfiguration(filePath: NginxConfigurationTest.regularUrl.path).tld
|
||||
NginxConfiguration.from(filePath: NginxConfigurationTest.regularUrl.path)?.tld
|
||||
)
|
||||
}
|
||||
|
||||
func testCanDetermineIsolation() throws {
|
||||
XCTAssertNil(
|
||||
NginxConfiguration(filePath: NginxConfigurationTest.regularUrl.path).isolatedVersion
|
||||
NginxConfiguration.from(filePath: NginxConfigurationTest.regularUrl.path)?.isolatedVersion
|
||||
)
|
||||
|
||||
XCTAssertEqual(
|
||||
"8.1",
|
||||
NginxConfiguration(filePath: NginxConfigurationTest.isolatedUrl.path).isolatedVersion
|
||||
NginxConfiguration.from(filePath: NginxConfigurationTest.isolatedUrl.path)?.isolatedVersion
|
||||
)
|
||||
}
|
||||
|
||||
func testCanDetermineProxy() throws {
|
||||
let proxied = NginxConfiguration(filePath: NginxConfigurationTest.proxyUrl.path)
|
||||
let proxied = NginxConfiguration.from(filePath: NginxConfigurationTest.proxyUrl.path)!
|
||||
XCTAssertTrue(proxied.contents.contains("# valet stub: proxy.valet.conf"))
|
||||
XCTAssertEqual("http://127.0.0.1:90", proxied.proxy)
|
||||
|
||||
let normal = NginxConfiguration(filePath: NginxConfigurationTest.regularUrl.path)
|
||||
let normal = NginxConfiguration.from(filePath: NginxConfigurationTest.regularUrl.path)!
|
||||
XCTAssertFalse(normal.contents.contains("# valet stub: proxy.valet.conf"))
|
||||
XCTAssertEqual(nil, normal.proxy)
|
||||
}
|
||||
|
||||
func testCanDetermineSecuredProxy() throws {
|
||||
let proxied = NginxConfiguration(filePath: NginxConfigurationTest.secureProxyUrl.path)
|
||||
let proxied = NginxConfiguration.from(filePath: NginxConfigurationTest.secureProxyUrl.path)!
|
||||
XCTAssertTrue(proxied.contents.contains("# valet stub: secure.proxy.valet.conf"))
|
||||
XCTAssertEqual("http://127.0.0.1:90", proxied.proxy)
|
||||
}
|
||||
|
||||
func testCanDetermineProxyWithCustomTld() throws {
|
||||
let proxied = NginxConfiguration.from(filePath: NginxConfigurationTest.customTldProxyUrl.path)!
|
||||
XCTAssertTrue(proxied.contents.contains("# valet stub: secure.proxy.valet.conf"))
|
||||
XCTAssertEqual("http://localhost:8080", proxied.proxy)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
// phpmon-tests
|
||||
//
|
||||
// Created by Nico Verbruggen on 13/02/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
|
@ -3,7 +3,7 @@
|
||||
// phpmon-tests
|
||||
//
|
||||
// Created by Nico Verbruggen on 29/11/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
|
@ -0,0 +1,57 @@
|
||||
# valet stub: secure.proxy.valet.conf
|
||||
|
||||
server {
|
||||
listen 127.0.0.1:80;
|
||||
#listen 127.0.0.1:80; # valet loopback
|
||||
server_name live.whatagraph.dev.com www.live.whatagraph.dev.com *.live.whatagraph.dev.com;
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 127.0.0.1:443 ssl http2;
|
||||
#listen 127.0.0.1:443 ssl http2; # valet loopback
|
||||
server_name live.whatagraph.dev.com www.live.whatagraph.dev.com *.live.whatagraph.dev.com;
|
||||
root /;
|
||||
charset utf-8;
|
||||
client_max_body_size 128M;
|
||||
http2_push_preload on;
|
||||
|
||||
location /41c270e4-5535-4daa-b23e-c269744c2f45/ {
|
||||
internal;
|
||||
alias /;
|
||||
try_files $uri $uri/;
|
||||
}
|
||||
|
||||
ssl_certificate "/Users/phpmon/.config/valet/Certificates/live.whatagraph.dev.com.crt";
|
||||
ssl_certificate_key "/Users/phpmon/.config/valet/Certificates/live.whatagraph.dev.com.key";
|
||||
|
||||
access_log off;
|
||||
error_log "/Users/phpmon/.config/valet/Log/live.whatagraph.dev.com-error.log";
|
||||
|
||||
error_page 404 "/Users/phpmon/.composer/vendor/laravel/valet/server.php";
|
||||
|
||||
location / {
|
||||
proxy_pass http://localhost:8080/;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Client-Verify SUCCESS;
|
||||
proxy_set_header X-Client-DN $ssl_client_s_dn;
|
||||
proxy_set_header X-SSL-Subject $ssl_client_s_dn;
|
||||
proxy_set_header X-SSL-Issuer $ssl_client_i_dn;
|
||||
proxy_set_header X-NginX-Proxy true;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_http_version 1.1;
|
||||
proxy_read_timeout 1800;
|
||||
proxy_connect_timeout 1800;
|
||||
chunked_transfer_encoding on;
|
||||
proxy_redirect off;
|
||||
proxy_buffering off;
|
||||
}
|
||||
|
||||
location ~ /\.ht {
|
||||
deny all;
|
||||
}
|
||||
}
|
@ -3,7 +3,7 @@
|
||||
// phpmon-tests
|
||||
//
|
||||
// Created by Nico Verbruggen on 14/02/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
21
phpmon-tests/Versions/AppUpdaterCheckTest.swift
Normal file
21
phpmon-tests/Versions/AppUpdaterCheckTest.swift
Normal file
@ -0,0 +1,21 @@
|
||||
//
|
||||
// AppUpdaterCheckTest.swift
|
||||
// phpmon-tests
|
||||
//
|
||||
// Created by Nico Verbruggen on 10/05/2022.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
|
||||
class AppUpdaterCheckTest: XCTestCase {
|
||||
|
||||
func testCanRetrieveVersionFromCask() {
|
||||
let caskVersion = AppUpdateChecker.retrieveVersionFromCask()
|
||||
|
||||
let version = VersionExtractor.from(caskVersion)
|
||||
|
||||
XCTAssertNotNil(version)
|
||||
}
|
||||
|
||||
}
|
62
phpmon-tests/Versions/AppVersionTest.swift
Normal file
62
phpmon-tests/Versions/AppVersionTest.swift
Normal file
@ -0,0 +1,62 @@
|
||||
//
|
||||
// AppVersionTest.swift
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 10/05/2022.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
|
||||
class AppVersionTest: XCTestCase {
|
||||
|
||||
func testCanRetrieveInternalAppVersion() {
|
||||
XCTAssertNotNil(AppVersion.fromCurrentVersion())
|
||||
}
|
||||
|
||||
func testCanParseNormalVersionString() {
|
||||
let version = AppVersion.from("1.0.0")
|
||||
|
||||
XCTAssertNotNil(version)
|
||||
XCTAssertEqual("1.0.0", version?.version)
|
||||
XCTAssertEqual(nil, version?.build)
|
||||
XCTAssertEqual(nil, version?.suffix)
|
||||
}
|
||||
|
||||
func testCanParseCaskVersionString() {
|
||||
let version = AppVersion.from("1.0.0_600")
|
||||
|
||||
XCTAssertNotNil(version)
|
||||
XCTAssertEqual("1.0.0", version?.version)
|
||||
XCTAssertEqual("600", version?.build)
|
||||
XCTAssertEqual(nil, version?.suffix)
|
||||
}
|
||||
|
||||
func testCanParseDevVersionStringWithoutBuildNumber() {
|
||||
let version = AppVersion.from("1.0.0-dev")
|
||||
|
||||
XCTAssertNotNil(version)
|
||||
XCTAssertEqual("1.0.0", version?.version)
|
||||
XCTAssertEqual(nil, version?.build)
|
||||
XCTAssertEqual("dev", version?.suffix)
|
||||
}
|
||||
|
||||
func testCanParseDevVersionStringWithBuildNumber() {
|
||||
let version = AppVersion.from("1.0.0-dev,870")
|
||||
|
||||
XCTAssertNotNil(version)
|
||||
XCTAssertEqual("1.0.0", version?.version)
|
||||
XCTAssertEqual("870", version?.build)
|
||||
XCTAssertEqual("dev", version?.suffix)
|
||||
}
|
||||
|
||||
func testCanParseUnderscoresAsBuildSeparatorToo() {
|
||||
let version = AppVersion.from("1.0.0-dev_870")
|
||||
|
||||
XCTAssertNotNil(version)
|
||||
XCTAssertEqual("1.0.0", version?.version)
|
||||
XCTAssertEqual("870", version?.build)
|
||||
XCTAssertEqual("dev", version?.suffix)
|
||||
}
|
||||
|
||||
}
|
@ -3,7 +3,7 @@
|
||||
// phpmon-tests
|
||||
//
|
||||
// Created by Nico Verbruggen on 01/04/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
|
@ -3,7 +3,7 @@
|
||||
// phpmon-tests
|
||||
//
|
||||
// Created by Nico Verbruggen on 29/11/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
|
@ -3,7 +3,7 @@
|
||||
// phpmon-tests
|
||||
//
|
||||
// Created by Nico Verbruggen on 16/12/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Services.swift
|
||||
// PHP Monitor
|
||||
//
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Command.swift
|
||||
// PHP Monitor
|
||||
//
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Constants.swift
|
||||
// PHP Monitor
|
||||
//
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
@ -56,13 +56,27 @@ struct Constants {
|
||||
static let DonationPayment = URL(
|
||||
string: "https://nicoverbruggen.be/sponsor#pay-now"
|
||||
)!
|
||||
|
||||
static let DonationPage = URL(
|
||||
string: "https://nicoverbruggen.be/sponsor"
|
||||
)!
|
||||
|
||||
static let FrequentlyAskedQuestions = URL(
|
||||
string: "https://github.com/nicoverbruggen/phpmon#%EF%B8%8F-faq--troubleshooting"
|
||||
)!
|
||||
|
||||
static let GitHubReleases = URL(
|
||||
string: "https://github.com/nicoverbruggen/phpmon/releases"
|
||||
)!
|
||||
|
||||
static let StableBuildCaskFile = URL(
|
||||
string: "https://raw.githubusercontent.com/nicoverbruggen/homebrew-cask/master/Casks/phpmon.rb"
|
||||
)!
|
||||
|
||||
static let DevBuildCaskFile = URL(
|
||||
string: "https://raw.githubusercontent.com/nicoverbruggen/homebrew-cask/master/Casks/phpmon-dev.rb"
|
||||
)!
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 24/12/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
// MARK: Common Shell Commands
|
||||
|
@ -3,7 +3,7 @@
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 21/12/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Paths.swift
|
||||
// PHP Monitor
|
||||
//
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Shell.swift
|
||||
// PHP Monitor
|
||||
//
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
@ -91,7 +91,7 @@ public class Shell {
|
||||
task.launch()
|
||||
task.waitUntilExit()
|
||||
|
||||
return Shell.Output(
|
||||
let output = Shell.Output(
|
||||
standardOutput: String(
|
||||
data: outputPipe.fileHandleForReading.readDataToEndOfFile(),
|
||||
encoding: .utf8
|
||||
@ -102,6 +102,12 @@ public class Shell {
|
||||
)!,
|
||||
task: task
|
||||
)
|
||||
|
||||
if CommandLine.arguments.contains("--v") {
|
||||
log(task: task, output: output)
|
||||
}
|
||||
|
||||
return output
|
||||
}
|
||||
|
||||
/**
|
||||
@ -119,6 +125,23 @@ public class Shell {
|
||||
return task
|
||||
}
|
||||
|
||||
/**
|
||||
Verbose logging for PHP Monitor's synchronous shell output.
|
||||
*/
|
||||
private func log(task: Process, output: Output) {
|
||||
Log.info("")
|
||||
Log.info("==== COMMAND ====")
|
||||
Log.info("")
|
||||
Log.info("\(self.shell) \(task.arguments?.joined(separator: " ") ?? "")")
|
||||
Log.info("")
|
||||
Log.info("==== OUTPUT ====")
|
||||
Log.info("")
|
||||
dump(output)
|
||||
Log.info("")
|
||||
Log.info("==== END OUTPUT ====")
|
||||
Log.info("")
|
||||
}
|
||||
|
||||
public class Output {
|
||||
public let standardOutput: String
|
||||
public let errorOutput: String
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Date.swift
|
||||
// PHP Monitor
|
||||
//
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
|
@ -3,7 +3,7 @@
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 14/04/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
|
@ -2,7 +2,7 @@
|
||||
// StringExtension.swift
|
||||
// PHP Monitor
|
||||
//
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
import Foundation
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 04/02/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Alert.swift
|
||||
// PHP Monitor
|
||||
//
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
|
@ -3,7 +3,7 @@
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 07/12/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
@ -3,7 +3,7 @@
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 07/12/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
|
@ -2,7 +2,7 @@
|
||||
// LocalNotification.swift
|
||||
// PHP Monitor
|
||||
//
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
@ -2,7 +2,7 @@
|
||||
// ImageGenerator.swift
|
||||
// PHP Monitor
|
||||
//
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
|
@ -3,7 +3,7 @@
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 05/12/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
|
@ -3,7 +3,7 @@
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 16/12/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
@ -2,7 +2,7 @@
|
||||
// ActivePhpInstallation.swift
|
||||
// PHP Monitor
|
||||
//
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
@ -2,7 +2,7 @@
|
||||
// HomebrewPackage.swift
|
||||
// PHP Monitor
|
||||
//
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
@ -3,7 +3,7 @@
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 21/12/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
@ -3,7 +3,7 @@
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 31/01/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
@ -3,7 +3,7 @@
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 28/11/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
@ -3,7 +3,7 @@
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 24/12/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
@ -3,7 +3,7 @@
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 24/12/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
@ -3,7 +3,7 @@
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 05/12/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
|
@ -3,7 +3,7 @@
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 05/12/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
|
@ -2,7 +2,7 @@
|
||||
// StateManager.swift
|
||||
// PHP Monitor
|
||||
//
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
@ -21,6 +21,16 @@ class App {
|
||||
return "\(version) (\(build))"
|
||||
}
|
||||
|
||||
/** Just the bundle version (build). */
|
||||
static var bundleVersion: String {
|
||||
return Bundle.main.infoDictionary?["CFBundleVersion"] as! String
|
||||
}
|
||||
|
||||
/** Just the version number. */
|
||||
static var shortVersion: String {
|
||||
return Bundle.main.infoDictionary?["CFBundleShortVersionString"] as! String
|
||||
}
|
||||
|
||||
static var architecture: String {
|
||||
var systeminfo = utsname()
|
||||
uname(&systeminfo)
|
||||
|
@ -3,7 +3,7 @@
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 20/12/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
|
@ -3,7 +3,7 @@
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 05/12/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
@ -3,7 +3,7 @@
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 06/12/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
@ -2,7 +2,7 @@
|
||||
// AppDelegate.swift
|
||||
// PHP Monitor
|
||||
//
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
@ -67,6 +67,10 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
|
||||
#if DEBUG
|
||||
logger.verbosity = .performance
|
||||
#endif
|
||||
if CommandLine.arguments.contains("--v") {
|
||||
logger.verbosity = .performance
|
||||
Log.info("Extra verbose mode has been activated.")
|
||||
}
|
||||
Log.separator(as: .info)
|
||||
Log.info("PHP MONITOR by Nico Verbruggen")
|
||||
Log.info("Version \(App.version)")
|
||||
|
181
phpmon/Domain/App/AppUpdateChecker.swift
Normal file
181
phpmon/Domain/App/AppUpdateChecker.swift
Normal file
@ -0,0 +1,181 @@
|
||||
//
|
||||
// Updater.swift
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 09/05/2022.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import AppKit
|
||||
|
||||
class AppUpdateChecker {
|
||||
|
||||
public static var enabled: Bool = {
|
||||
return Preferences.isEnabled(.automaticBackgroundUpdateCheck)
|
||||
}()
|
||||
|
||||
public static var isDev: Bool = {
|
||||
return App.version.contains("-dev")
|
||||
}()
|
||||
|
||||
public static func retrieveVersionFromCask(
|
||||
_ initiatedFromBackground: Bool = true
|
||||
) -> String {
|
||||
let caskFile = App.version.contains("-dev")
|
||||
? Constants.Urls.DevBuildCaskFile.absoluteString
|
||||
: Constants.Urls.StableBuildCaskFile.absoluteString
|
||||
|
||||
var command = "curl -s"
|
||||
|
||||
if initiatedFromBackground {
|
||||
command = "curl -s --max-time 5"
|
||||
}
|
||||
|
||||
return Shell.pipe(
|
||||
"\(command) '\(caskFile)' | grep version"
|
||||
)
|
||||
}
|
||||
|
||||
public static func checkIfNewerVersionIsAvailable(
|
||||
initiatedFromBackground: Bool = true
|
||||
) {
|
||||
if initiatedFromBackground {
|
||||
if !Preferences.isEnabled(.automaticBackgroundUpdateCheck) {
|
||||
Log.info("Automatic updates are disabled. No check will be performed.")
|
||||
return
|
||||
}
|
||||
|
||||
Log.info("Automatic updates are enabled, a check will be performed.")
|
||||
}
|
||||
|
||||
let versionString = retrieveVersionFromCask(initiatedFromBackground)
|
||||
|
||||
guard let onlineVersion = AppVersion.from(versionString) else {
|
||||
Log.err("We couldn't check for updates!")
|
||||
|
||||
// Only notify about connection issues if the request to check for updates was explicit
|
||||
if !initiatedFromBackground {
|
||||
notifyAboutConnectionIssue()
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
let currentVersion = AppVersion.fromCurrentVersion()
|
||||
|
||||
handleVersionComparison(
|
||||
currentVersion,
|
||||
onlineVersion,
|
||||
initiatedFromBackground
|
||||
)
|
||||
}
|
||||
|
||||
private static func handleVersionComparison(
|
||||
_ currentVersion: AppVersion,
|
||||
_ onlineVersion: AppVersion,
|
||||
_ background: Bool
|
||||
) {
|
||||
switch onlineVersion.version.versionCompare(currentVersion.version) {
|
||||
case .orderedAscending:
|
||||
Log.info("You are running a newer version of PHP Monitor "
|
||||
+ "(\(currentVersion.computerReadable) > \(onlineVersion.computerReadable)).")
|
||||
if !background { notifyVersionDoesNotNeedUpgrade() }
|
||||
case .orderedDescending:
|
||||
Log.info("There is a newer version (\(onlineVersion)) available! "
|
||||
+ "(\(onlineVersion.computerReadable) > \(currentVersion.computerReadable))")
|
||||
notifyAboutNewerVersion(version: onlineVersion)
|
||||
case .orderedSame:
|
||||
if currentVersion.build != nil
|
||||
&& onlineVersion.build != nil
|
||||
&& buildDiffers(currentVersion, onlineVersion, background) {
|
||||
return
|
||||
}
|
||||
|
||||
Log.info("The installed version (\(currentVersion.computerReadable)) matches the latest release "
|
||||
+ "(\(onlineVersion.computerReadable)).")
|
||||
if !background { notifyVersionDoesNotNeedUpgrade() }
|
||||
}
|
||||
}
|
||||
|
||||
private static func buildDiffers(
|
||||
_ currentVersion: AppVersion,
|
||||
_ onlineVersion: AppVersion,
|
||||
_ background: Bool
|
||||
) -> Bool {
|
||||
if Int(onlineVersion.build!)! > Int(currentVersion.build!)! {
|
||||
Log.info("There is a newer build of PHP Monitor available! "
|
||||
+ "(\(onlineVersion.computerReadable) > \(currentVersion.computerReadable))")
|
||||
notifyAboutNewerVersion(version: onlineVersion)
|
||||
return true
|
||||
} else if Int(onlineVersion.build!)! < Int(currentVersion.build!)! {
|
||||
Log.info("You are running a newer build of PHP Monitor "
|
||||
+ "(\(currentVersion.computerReadable) > \(onlineVersion.computerReadable)).")
|
||||
if !background { notifyVersionDoesNotNeedUpgrade() }
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private static func notifyVersionDoesNotNeedUpgrade() {
|
||||
DispatchQueue.main.async {
|
||||
BetterAlert().withInformation(
|
||||
title: "updater.alerts.is_latest_version.title".localized,
|
||||
subtitle: "updater.alerts.is_latest_version.subtitle".localized(App.shortVersion),
|
||||
description: ""
|
||||
)
|
||||
.withPrimary(text: "OK")
|
||||
.show()
|
||||
}
|
||||
}
|
||||
|
||||
private static func notifyAboutNewerVersion(version: AppVersion) {
|
||||
let devSuffix = isDev ? "-dev" : ""
|
||||
let command = isDev ? "brew upgrade phpmon-dev" : "brew upgrade phpmon"
|
||||
|
||||
DispatchQueue.main.async {
|
||||
BetterAlert().withInformation(
|
||||
title: "updater.alerts.newer_version_available.title".localized(version.humanReadable),
|
||||
subtitle: "updater.alerts.newer_version_available.subtitle".localized,
|
||||
description: HomebrewDiagnostics.customCaskInstalled
|
||||
? "updater.installation_source.brew".localized(command)
|
||||
: "updater.installation_source.direct".localized
|
||||
)
|
||||
.withPrimary(
|
||||
text: "updater.alerts.buttons.release_notes".localized,
|
||||
action: { vc in
|
||||
vc.close(with: .OK)
|
||||
NSWorkspace.shared.open(
|
||||
Constants.Urls.GitHubReleases.appendingPathComponent("/tag/v\(version.version)\(devSuffix)")
|
||||
)
|
||||
}
|
||||
)
|
||||
.withTertiary(text: "Dismiss", action: { vc in
|
||||
vc.close(with: .OK)
|
||||
})
|
||||
.show()
|
||||
}
|
||||
}
|
||||
|
||||
private static func notifyAboutConnectionIssue() {
|
||||
DispatchQueue.main.async {
|
||||
BetterAlert().withInformation(
|
||||
title: "updater.errors.cannot_check_for_update.title".localized,
|
||||
subtitle: "updater.errors.cannot_check_for_update.subtitle".localized,
|
||||
description: "updater.errors.cannot_check_for_update.description".localized(
|
||||
App.version
|
||||
)
|
||||
)
|
||||
.withTertiary(
|
||||
text: "updater.errors.buttons.releases_on_github".localized,
|
||||
action: { _ in
|
||||
NSWorkspace.shared.open(Constants.Urls.GitHubReleases)
|
||||
}
|
||||
)
|
||||
.withPrimary(text: "OK")
|
||||
.show()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
77
phpmon/Domain/App/AppVersion.swift
Normal file
77
phpmon/Domain/App/AppVersion.swift
Normal file
@ -0,0 +1,77 @@
|
||||
//
|
||||
// AppVersion.swift
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 10/05/2022.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class AppVersion {
|
||||
var version: String
|
||||
var build: String?
|
||||
var suffix: String?
|
||||
|
||||
init(version: String, build: String?, suffix: String? = nil) {
|
||||
self.version = version
|
||||
self.build = build
|
||||
self.suffix = suffix
|
||||
}
|
||||
|
||||
public static func from(_ string: String) -> AppVersion? {
|
||||
do {
|
||||
let regex = try NSRegularExpression(
|
||||
pattern: #"(?<version>(\d+)[.](\d+)([.](\d+))?)(-(?<suffix>[a-z]+)){0,1}((,|_)(?<build>\d+)){0,1}"#,
|
||||
options: []
|
||||
)
|
||||
|
||||
let match = regex.matches(
|
||||
in: string,
|
||||
options: [],
|
||||
range: NSRange(location: 0, length: string.count)
|
||||
).first
|
||||
|
||||
guard let match = match else {
|
||||
return nil
|
||||
}
|
||||
|
||||
var version: String = ""
|
||||
var build: String?
|
||||
var suffix: String?
|
||||
|
||||
if let versionRange = Range(match.range(withName: "version"), in: string) {
|
||||
version = String(string[versionRange])
|
||||
}
|
||||
|
||||
if let buildRange = Range(match.range(withName: "build"), in: string) {
|
||||
build = String(string[buildRange])
|
||||
}
|
||||
|
||||
if let suffixRange = Range(match.range(withName: "suffix"), in: string) {
|
||||
suffix = String(string[suffixRange])
|
||||
}
|
||||
|
||||
return AppVersion(
|
||||
version: version,
|
||||
build: build,
|
||||
suffix: suffix
|
||||
)
|
||||
} catch {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
public static func fromCurrentVersion() -> AppVersion {
|
||||
return AppVersion.from("\(App.shortVersion)_\(App.bundleVersion)")!
|
||||
}
|
||||
|
||||
var computerReadable: String {
|
||||
return "\(version)_\(build ?? "0")"
|
||||
}
|
||||
|
||||
var humanReadable: String {
|
||||
return "\(version) (\(build ?? "???"))"
|
||||
}
|
||||
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
// Environment.swift
|
||||
// PHP Monitor
|
||||
//
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
@ -63,8 +63,6 @@ class AddProxyVC: NSViewController, NSTextFieldDelegate {
|
||||
}
|
||||
|
||||
@IBAction func pressedCreateProxy(_ sender: Any) {
|
||||
// TODO: Validate the input before allowing proxy creation
|
||||
|
||||
let domain = self.inputDomainName.stringValue
|
||||
let proxyName = self.inputProxySubject.stringValue
|
||||
let secure = self.buttonSecure.state == .on ? " --secure" : ""
|
||||
@ -104,18 +102,24 @@ class AddProxyVC: NSViewController, NSTextFieldDelegate {
|
||||
}
|
||||
|
||||
private func validate(domain: String, proxy: String) -> Bool {
|
||||
if domain.isEmpty {
|
||||
textFieldError.isHidden = false
|
||||
textFieldError.stringValue = "domain_list.add.errors.empty".localized
|
||||
return false
|
||||
}
|
||||
|
||||
if proxy.isEmpty {
|
||||
textFieldError.isHidden = false
|
||||
textFieldError.stringValue = "domain_list.add.errors.empty_proxy".localized
|
||||
return false
|
||||
}
|
||||
|
||||
if proxy.range(of: #"(http:\/\/|https:\/\/)(.+)(:)(\d+)$"#, options: .regularExpression) == nil {
|
||||
textFieldError.isHidden = false
|
||||
textFieldError.stringValue = "domain_list.add.errors.subject_invalid".localized
|
||||
return false
|
||||
}
|
||||
|
||||
if domain.isEmpty {
|
||||
textFieldError.isHidden = false
|
||||
textFieldError.stringValue = "domain_list.add.errors.empty".localized
|
||||
return false
|
||||
}
|
||||
|
||||
if Valet.shared.sites.contains(where: { $0.name == domain }) {
|
||||
textFieldError.isHidden = false
|
||||
textFieldError.stringValue = "domain_list.add.errors.already_exists".localized
|
||||
@ -130,6 +134,9 @@ class AddProxyVC: NSViewController, NSTextFieldDelegate {
|
||||
inputDomainName.stringValue = inputDomainName.stringValue
|
||||
.replacingOccurrences(of: " ", with: "-")
|
||||
|
||||
inputProxySubject.stringValue = inputProxySubject.stringValue
|
||||
.replacingOccurrences(of: " ", with: "-")
|
||||
|
||||
buttonCreateProxy.isEnabled = validate(
|
||||
domain: inputDomainName.stringValue,
|
||||
proxy: inputProxySubject.stringValue
|
||||
|
@ -3,7 +3,7 @@
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 03/12/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
|
@ -3,7 +3,7 @@
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 23/12/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
@ -12,6 +12,37 @@ import Cocoa
|
||||
extension DomainListVC {
|
||||
|
||||
@objc func toggleSecure() {
|
||||
if selected is ValetSite {
|
||||
toggleSecureForSite()
|
||||
} else {
|
||||
toggleSecureForProxy()
|
||||
}
|
||||
}
|
||||
|
||||
func toggleSecureForProxy() {
|
||||
let originalSecureStatus = selectedProxy!.secured
|
||||
let selectedProxy = selectedProxy!
|
||||
|
||||
self.waitAndExecute {
|
||||
// 1. Remove the original proxy
|
||||
Shell.run("\(Paths.valet) unproxy \(selectedProxy.domain)", requiresPath: true)
|
||||
|
||||
// 2. Add a new proxy, which is either secured/unsecured
|
||||
let secure = originalSecureStatus ? "" : " --secure"
|
||||
Shell.run("\(Paths.valet) proxy \(selectedProxy.domain) \(selectedProxy.target)\(secure)",
|
||||
requiresPath: true)
|
||||
|
||||
// 3. Restart nginx
|
||||
Actions.restartNginx()
|
||||
|
||||
// 4. Reload site list
|
||||
DispatchQueue.main.async {
|
||||
App.shared.domainListWindowController?.pressedReload(nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func toggleSecureForSite() {
|
||||
let rowToReload = tableView.selectedRow
|
||||
let originalSecureStatus = selectedSite!.secured
|
||||
let action = selectedSite!.secured ? "unsecure" : "secure"
|
||||
@ -122,8 +153,11 @@ extension DomainListVC {
|
||||
secondButtonTitle: "Cancel",
|
||||
style: .critical,
|
||||
onFirstButtonPressed: {
|
||||
Shell.run("valet unlink '\(site.name)'", requiresPath: true)
|
||||
self.reloadDomains()
|
||||
self.waitAndExecute {
|
||||
Shell.run("valet unlink '\(site.name)'", requiresPath: true)
|
||||
} completion: {
|
||||
self.reloadDomains()
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
@ -141,8 +175,11 @@ extension DomainListVC {
|
||||
secondButtonTitle: "Cancel",
|
||||
style: .critical,
|
||||
onFirstButtonPressed: {
|
||||
Shell.run("valet unproxy '\(proxy.domain)'", requiresPath: true)
|
||||
self.reloadDomains()
|
||||
self.waitAndExecute {
|
||||
Shell.run("valet unproxy '\(proxy.domain)'", requiresPath: true)
|
||||
} completion: {
|
||||
self.reloadDomains()
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 10/12/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
@ -43,7 +43,7 @@ extension DomainListVC {
|
||||
}
|
||||
|
||||
addUnlink(to: menu, with: site)
|
||||
addToggleSecure(to: menu, with: site)
|
||||
addToggleSecure(to: menu, secured: site.secured)
|
||||
|
||||
tableView.menu = menu
|
||||
}
|
||||
@ -130,9 +130,9 @@ extension DomainListVC {
|
||||
}
|
||||
}
|
||||
|
||||
private func addToggleSecure(to menu: NSMenu, with site: ValetSite) {
|
||||
private func addToggleSecure(to menu: NSMenu, secured: Bool) {
|
||||
menu.addItem(
|
||||
withTitle: site.secured
|
||||
withTitle: secured
|
||||
? "domain_list.unsecure".localized
|
||||
: "domain_list.secure".localized,
|
||||
action: #selector(toggleSecure),
|
||||
@ -146,6 +146,7 @@ extension DomainListVC {
|
||||
let menu = NSMenu()
|
||||
addOpenProxyInBrowser(to: menu)
|
||||
addSeparator(to: menu)
|
||||
addToggleSecure(to: menu, secured: proxy.secured)
|
||||
addRemoveProxy(to: menu)
|
||||
tableView.menu = menu
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 30/03/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
|
@ -3,7 +3,7 @@
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 03/12/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
|
@ -3,21 +3,49 @@
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 28/11/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class HomebrewDiagnostics {
|
||||
|
||||
/**
|
||||
Determines the Homebrew taps the user has installed.
|
||||
*/
|
||||
public static var installedTaps: [String] = {
|
||||
return Shell
|
||||
.pipe("\(Paths.brew) tap")
|
||||
.split(separator: "\n")
|
||||
.map { string in
|
||||
return String(string)
|
||||
}
|
||||
}()
|
||||
|
||||
/**
|
||||
Determines whether the PHP Monitor Cask is installed.
|
||||
*/
|
||||
public static var customCaskInstalled: Bool = {
|
||||
return installedTaps.contains("nicoverbruggen/cask")
|
||||
}()
|
||||
|
||||
/**
|
||||
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 break all linking functionality in PHP Monitor, and the user needs to be informed of this.
|
||||
|
||||
|
||||
This check only needs to be performed if the `shivammathur/php` tap is active.
|
||||
*/
|
||||
public static func hasAliasConflict() -> Bool {
|
||||
public static func checkForCaskConflict() {
|
||||
if hasAliasConflict() {
|
||||
presentAlertAboutConflict()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Check if the alias conflict as documented in `checkForCaskConflict` actually occurred.
|
||||
*/
|
||||
private static func hasAliasConflict() -> Bool {
|
||||
let tapAlias = Shell.pipe("\(Paths.brew) info shivammathur/php/php --json")
|
||||
|
||||
if tapAlias.contains("brew tap shivammathur/php") || tapAlias.contains("Error") {
|
||||
@ -55,7 +83,10 @@ class HomebrewDiagnostics {
|
||||
}
|
||||
}
|
||||
|
||||
public static func presentAlertAboutConflict() {
|
||||
/**
|
||||
Show this alert in case the tapped Cask does cause issues because of the conflict.
|
||||
*/
|
||||
private static func presentAlertAboutConflict() {
|
||||
DispatchQueue.main.async {
|
||||
BetterAlert()
|
||||
.withInformation(
|
||||
|
@ -19,19 +19,30 @@ class NginxConfiguration {
|
||||
/** The TLD of the domain, usually derived from the name of the file. */
|
||||
var tld: String
|
||||
|
||||
init(filePath: String) {
|
||||
static func from(filePath: String) -> NginxConfiguration? {
|
||||
let path = filePath.replacingOccurrences(
|
||||
of: "~",
|
||||
with: "/Users/\(Paths.whoami)"
|
||||
)
|
||||
|
||||
self.contents = try! String(contentsOfFile: path)
|
||||
do {
|
||||
let fileContents = try String(contentsOfFile: path)
|
||||
return NginxConfiguration.init(
|
||||
path: path,
|
||||
contents: fileContents
|
||||
)
|
||||
} catch {
|
||||
Log.warn("Could not read the nginx configuration file at: `\(filePath)`")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
init(path: String, contents: String) {
|
||||
let domain = String(path.split(separator: "/").last!)
|
||||
let tld = String(domain.split(separator: ".").last!)
|
||||
|
||||
self.domain = domain
|
||||
.replacingOccurrences(of: ".\(tld)", with: "")
|
||||
self.contents = contents
|
||||
self.domain = domain.replacingOccurrences(of: ".\(tld)", with: "")
|
||||
self.tld = tld
|
||||
}
|
||||
|
||||
@ -40,7 +51,7 @@ class NginxConfiguration {
|
||||
*/
|
||||
lazy var proxy: String? = {
|
||||
let regex = try! NSRegularExpression(
|
||||
pattern: #"proxy_pass (?<proxy>.*:\d*);"#,
|
||||
pattern: #"proxy_pass (?<proxy>.*:\d*)(\/*);"#,
|
||||
options: []
|
||||
)
|
||||
|
||||
|
@ -13,8 +13,8 @@ class ValetProxyScanner: ProxyScanner {
|
||||
return try! FileManager
|
||||
.default
|
||||
.contentsOfDirectory(atPath: directoryPath)
|
||||
.map {
|
||||
return NginxConfiguration.init(filePath: "\(directoryPath)/\($0)")
|
||||
.compactMap {
|
||||
return NginxConfiguration.from(filePath: "\(directoryPath)/\($0)")
|
||||
}
|
||||
.filter {
|
||||
return $0.proxy != nil
|
||||
|
@ -226,8 +226,8 @@ class ValetSite: DomainListable {
|
||||
public static func isolatedVersion(_ filePath: String) -> String? {
|
||||
if Filesystem.fileExists(filePath) {
|
||||
return NginxConfiguration
|
||||
.init(filePath: filePath)
|
||||
.isolatedVersion
|
||||
.from(filePath: filePath)?
|
||||
.isolatedVersion ?? nil
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -3,7 +3,7 @@
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 29/11/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
@ -3,7 +3,7 @@
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 04/02/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
@ -29,6 +29,12 @@ extension MainMenu {
|
||||
When the environment is all clear and the app can run, let's go.
|
||||
*/
|
||||
private func onEnvironmentPass() {
|
||||
// Determine install method
|
||||
Log.info(HomebrewDiagnostics.customCaskInstalled
|
||||
? "The app has probably been installed via Homebrew Cask."
|
||||
: "The app has probably been installed directly."
|
||||
)
|
||||
|
||||
// Attempt to find out more info about Valet
|
||||
if Valet.shared.version != nil {
|
||||
Log.info("PHP Monitor has extracted the version number of Valet: \(Valet.shared.version!)")
|
||||
@ -41,9 +47,7 @@ extension MainMenu {
|
||||
PhpEnv.detectPhpVersions()
|
||||
|
||||
// Check for an alias conflict
|
||||
if HomebrewDiagnostics.hasAliasConflict() {
|
||||
HomebrewDiagnostics.presentAlertAboutConflict()
|
||||
}
|
||||
HomebrewDiagnostics.checkForCaskConflict()
|
||||
|
||||
updatePhpVersionInStatusBar()
|
||||
|
||||
@ -86,8 +90,6 @@ extension MainMenu {
|
||||
|
||||
NotificationCenter.default.post(name: Events.ServicesUpdated, object: nil)
|
||||
|
||||
Log.info("PHP Monitor is ready to serve!")
|
||||
|
||||
// Schedule a request to fetch the PHP version every 60 seconds
|
||||
DispatchQueue.main.async { [self] in
|
||||
App.shared.timer = Timer.scheduledTimer(
|
||||
@ -101,6 +103,12 @@ extension MainMenu {
|
||||
|
||||
Stats.incrementSuccessfulLaunchCount()
|
||||
Stats.evaluateSponsorMessageShouldBeDisplayed()
|
||||
|
||||
DispatchQueue.global(qos: .utility).async {
|
||||
AppUpdateChecker.checkIfNewerVersionIsAvailable()
|
||||
}
|
||||
|
||||
Log.info("PHP Monitor is ready to serve!")
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2,7 +2,7 @@
|
||||
// MainMenu.swift
|
||||
// PHP Monitor
|
||||
//
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
@ -337,6 +337,12 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate, PhpSwitcherDelegate
|
||||
NSApplication.shared.terminate(nil)
|
||||
}
|
||||
|
||||
@objc func checkForUpdates() {
|
||||
DispatchQueue.global(qos: .userInitiated).async {
|
||||
AppUpdateChecker.checkIfNewerVersionIsAvailable(initiatedFromBackground: false)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Menu Delegate
|
||||
|
||||
func menuWillOpen(_ menu: NSMenu) {
|
||||
|
@ -3,7 +3,7 @@
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 04/02/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
@ -3,7 +3,7 @@
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 04/02/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
@ -2,7 +2,7 @@
|
||||
// MainMenuBuilder.swift
|
||||
// PHP Monitor
|
||||
//
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
@ -74,15 +74,16 @@ class StatusMenu: NSMenu {
|
||||
}
|
||||
|
||||
func addCoreMenuItems() {
|
||||
self.addItem(
|
||||
NSMenuItem(title: "mi_preferences".localized, action: #selector(MainMenu.openPrefs), keyEquivalent: ",")
|
||||
)
|
||||
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")
|
||||
)
|
||||
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: Remaining Menu Items
|
||||
|
@ -65,7 +65,7 @@ class BetterAlertVC: NSViewController {
|
||||
}
|
||||
|
||||
@IBAction func tertiaryButtonAction(_ sender: Any) {
|
||||
if self.actionSecondary != nil {
|
||||
if self.actionTertiary != nil {
|
||||
self.actionTertiary!(self)
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 21/12/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
@ -3,7 +3,7 @@
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 15/04/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
@ -3,7 +3,7 @@
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 30/03/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
@ -20,6 +20,7 @@ enum PreferenceName: String {
|
||||
case autoComposerGlobalUpdateAfterSwitch = "auto_composer_global_update_after_switch"
|
||||
case allowProtocolForIntegrations = "allow_protocol_for_integrations"
|
||||
case globalHotkey = "global_hotkey"
|
||||
case automaticBackgroundUpdateCheck = "backgroundUpdateCheck"
|
||||
}
|
||||
|
||||
/**
|
||||
@ -76,6 +77,7 @@ class Preferences {
|
||||
PreferenceName.autoServiceRestartAfterExtensionToggle.rawValue: true,
|
||||
PreferenceName.autoComposerGlobalUpdateAfterSwitch.rawValue: false,
|
||||
PreferenceName.allowProtocolForIntegrations.rawValue: true,
|
||||
PreferenceName.automaticBackgroundUpdateCheck.rawValue: true,
|
||||
/// Stats
|
||||
InternalStats.switchCount.rawValue: 0,
|
||||
InternalStats.launchCount.rawValue: 0,
|
||||
@ -145,6 +147,8 @@ class Preferences {
|
||||
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,
|
||||
|
||||
// Part 2: Always Strings
|
||||
.globalHotkey: UserDefaults.standard.string(
|
||||
|
@ -3,7 +3,7 @@
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 30/03/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
@ -53,7 +53,8 @@ class PrefsVC: NSViewController {
|
||||
getAutoRestartPreferenceView(),
|
||||
getAutomaticComposerUpdatePreferenceView(),
|
||||
getShortcutPreferenceView(),
|
||||
getIntegrationsPreferenceView()
|
||||
getIntegrationsPreferenceView(),
|
||||
getAutomaticUpdateCheckPreferenceView()
|
||||
].forEach({ self.stackView.addArrangedSubview($0) })
|
||||
}
|
||||
|
||||
@ -133,6 +134,16 @@ class PrefsVC: NSViewController {
|
||||
)
|
||||
}
|
||||
|
||||
private func getAutomaticUpdateCheckPreferenceView() -> NSView {
|
||||
return CheckboxPreferenceView.make(
|
||||
sectionText: "prefs.updates".localized,
|
||||
descriptionText: "prefs.automatic_update_check_desc".localized,
|
||||
checkboxText: "prefs.automatic_update_check_title".localized,
|
||||
preference: .automaticBackgroundUpdateCheck,
|
||||
action: {}
|
||||
)
|
||||
}
|
||||
|
||||
// MARK: - Listening for hotkey delegate
|
||||
|
||||
var listeningForHotkeyView: HotkeyPreferenceView?
|
||||
|
@ -3,7 +3,7 @@
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 02/04/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
|
@ -3,7 +3,7 @@
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 17/12/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
@ -3,7 +3,7 @@
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 17/12/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
@ -3,7 +3,7 @@
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 18/12/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
@ -3,7 +3,7 @@
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 15/04/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
@ -3,7 +3,7 @@
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 15/04/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
@ -3,7 +3,7 @@
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 15/04/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
@ -3,7 +3,7 @@
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 15/04/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
@ -3,7 +3,7 @@
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 30/03/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
@ -3,7 +3,7 @@
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 30/03/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
@ -10,6 +10,22 @@
|
||||
<string>https://github.com/nicoverbruggen/phpmon</string>
|
||||
<key>Connections</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>IsIncoming</key>
|
||||
<false/>
|
||||
<key>Host</key>
|
||||
<string>raw.githubusercontent.com</string>
|
||||
<key>NetworkProtocol</key>
|
||||
<string>TCP</string>
|
||||
<key>Port</key>
|
||||
<string>80, 443</string>
|
||||
<key>Relevance</key>
|
||||
<string>Essential</string>
|
||||
<key>Purpose</key>
|
||||
<string>PHP Monitor connects to GitHub to check the Cask file to determine what the latest release of PHP Monitor is.</string>
|
||||
<key>DenyConsequences</key>
|
||||
<string>If you deny this connection, PHP Monitor will not be able to search for updates. If you don't want this check to happen, you can disable automatic updates in the Preferences menu instead.</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>IsIncoming</key>
|
||||
<false/>
|
||||
|
@ -3,7 +3,7 @@
|
||||
PHP Monitor
|
||||
|
||||
Created by Nico Verbruggen on 16/05/2020.
|
||||
Copyright © 2020 Nico Verbruggen. All rights reserved.
|
||||
Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
*/
|
||||
|
||||
// MENU ITEMS (MI)
|
||||
@ -59,6 +59,7 @@
|
||||
|
||||
"mi_preferences" = "Preferences...";
|
||||
"mi_donate" = "Donate...";
|
||||
"mi_check_for_updates" = "Check for Updates...";
|
||||
"mi_quit" = "Quit PHP Monitor";
|
||||
"mi_about" = "About PHP Monitor";
|
||||
|
||||
@ -105,7 +106,7 @@
|
||||
// ADD PROXY TO DOMAINS LIST
|
||||
|
||||
"domain_list.add.set_up_proxy" = "Set up a Proxy";
|
||||
"domain_list.add.proxy_subject" = "Proxy subject (usually: protocol, IP address and port)";
|
||||
"domain_list.add.proxy_subject" = "Proxy subject (must include protocol and port)";
|
||||
"domain_list.add.domain_name" = "Domain name";
|
||||
"domain_list.add.create_proxy" = "Create Proxy";
|
||||
"domain_list.add.proxy_available" = "%@ will be proxied and will be available via: %@://%@.%@";
|
||||
@ -123,6 +124,7 @@
|
||||
"domain_list.add.empty_fields" = "One or more fields are empty. Please fill all required fields.";
|
||||
"domain_list.add.errors.empty" = "You must enter a domain name.";
|
||||
"domain_list.add.errors.empty_proxy" = "You must enter what will be proxied.";
|
||||
"domain_list.add.errors.subject_invalid" = "The subject you've entered is not valid.\nYou must include the protocol and port.";
|
||||
"domain_list.add.errors.already_exists" = "A link with that name already exists.";
|
||||
|
||||
// ADD SITE ERROR: FOLDER MISSING SINCE SELECTION
|
||||
@ -183,6 +185,7 @@
|
||||
"prefs.services" = "Services:";
|
||||
"prefs.switcher" = "Switcher:";
|
||||
"prefs.integrations" = "Integrations:";
|
||||
"prefs.updates" = "Updates:";
|
||||
|
||||
"prefs.icon_options.php" = "Display PHP Icon";
|
||||
"prefs.icon_options.elephant" = "Display Elephant Icon";
|
||||
@ -204,6 +207,9 @@
|
||||
|
||||
"prefs.open_protocol_title" = "Allow third-party integrations";
|
||||
"prefs.open_protocol_desc" = "When checked, this will allow the interaction with third party utilities to work (e.g. Alfred, Raycast). If you disable this, PHP Monitor will still receive the commands, but will not act upon them.";
|
||||
|
||||
"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.shortcut_set" = "Set global shortcut";
|
||||
"prefs.shortcut_listening" = "<listening for keypress>";
|
||||
@ -372,6 +378,23 @@ You can do this by running `composer global update` in your terminal. After that
|
||||
"alert.errors.homebrew_permissions.applescript_returned_nil.title" = "Restore Homebrew Permissions has been cancelled.";
|
||||
"alert.errors.homebrew_permissions.applescript_returned_nil.description" = "The outcome of the script that is executed to adjust the permissions returned nil, which usually means that you did not grant administrative permissions to PHP Monitor.\n\nIf you clicked on Cancel during the authentication prompt, this is normal. If you did actually authenticate and you are still seeing this message, something probably went wrong.";
|
||||
|
||||
// CHECK FOR UPDATES
|
||||
|
||||
"updater.alerts.newer_version_available.title" = "PHP Monitor v%@ is now available!";
|
||||
"updater.alerts.newer_version_available.subtitle" = "Keeping PHP Monitor up-to-date is highly recommended, since newer versions usually fix bugs and include fixes to support the latest versions of Valet and PHP.";
|
||||
"updater.alerts.newer_version_available.description" = "PHP Monitor is supposed to be updated via Homebrew, so there is no built-in updater. This check is only meant to inform you of the existence of a new version, you do not need to upgrade.";
|
||||
"updater.installation_source.brew" = "You appear to have installed PHP Monitor via Homebrew (or have at least tapped the required Caskfile) so it is recommended that you upgrade via the terminal by running `%@`.";
|
||||
"updater.installation_source.direct" = "You do not appear to have installed PHP Monitor via Homebrew, so you will need to visit GitHub to download the latest update.";
|
||||
"updater.alerts.buttons.release_notes" = "View Release Notes";
|
||||
|
||||
"updater.alerts.is_latest_version.title" = "PHP Monitor is up-to-date!";
|
||||
"updater.alerts.is_latest_version.subtitle" = "The currently installed version (v%@) is up-to-date.\nThere is no newer version available.";
|
||||
|
||||
"updater.alerts.cannot_check_for_update.title" = "PHP Monitor could not determine if a newer version is available.";
|
||||
"updater.alerts.cannot_check_for_update.subtitle" = "You might not be connected to the internet, are blocking traffic or GitHub is down and won't allow you to check for updates. If you keep seeing this message, you may want to manually check the releases page.";
|
||||
"updater.alerts.cannot_check_for_update.description" = "The currently installed version is: %@. You can go to the list of the latest releases (on GitHub) by clicking on the button on the left.";
|
||||
"updater.alerts.buttons.releases_on_github" = "View Releases";
|
||||
|
||||
// WARNINGS ABOUT NON-DEFAULT TLD
|
||||
|
||||
"alert.warnings.tld_issue.title" = "You are not using `.test` as the TLD for Valet.";
|
||||
|
Reference in New Issue
Block a user