diff --git a/phpmon/Domain/App/Startup.swift b/phpmon/Domain/App/Startup.swift index d388cf2..4f486aa 100644 --- a/phpmon/Domain/App/Startup.swift +++ b/phpmon/Domain/App/Startup.swift @@ -11,6 +11,20 @@ import NVAlert class Startup { + @MainActor static var startupTimer: Timer? + + @MainActor func startTimeoutTimer() { + Self.startupTimer = Timer.scheduledTimer( + timeInterval: 30.0, target: self, selector: #selector(startupTimeout), + userInfo: nil, repeats: false + ) + } + + @MainActor static func invalidateTimeoutTimer() { + Self.startupTimer?.invalidate() + Self.startupTimer = nil + } + /** Checks the user's environment and checks if PHP Monitor can be used properly. This checks if PHP is installed, Valet is running, the appropriate permissions are set, and more. @@ -22,6 +36,11 @@ class Startup { // Do the important system setup checks Log.info("The user is running PHP Monitor with the architecture: \(App.architecture)") + // Set up a "background" timer on the main thread + Task { @MainActor in + startTimeoutTimer() + } + for group in self.groups { if group.condition() { Log.info("Now running \(group.checks.count) \(group.name) checks!") @@ -45,10 +64,34 @@ class Startup { // If we get here, nothing has gone wrong. That's what we want! initializeSwitcher() Log.info("PHP Monitor has determined the application has successfully passed all checks.") + Log.separator(as: .info) return true } + /** + Displays an alert for when the application startup process takes too long. + */ + @MainActor @objc func startupTimeout() { + NVAlert() + .withInformation( + title: "startup.timeout.title".localized, + subtitle: "startup.timeout.subtitle".localized, + description: "startup.timeout.description".localized + ) + .withPrimary(text: "alert.cannot_start.close".localized, action: { vc in + vc.close(with: .alertFirstButtonReturn) + exit(1) + }) + .withSecondary(text: "startup.timeout.ignore".localized, action: { vc in + vc.close(with: .alertSecondButtonReturn) + }) + .withTertiary(text: "", action: { _ in + NSWorkspace.shared.open(URL(string: "https://github.com/nicoverbruggen/phpmon/issues/294")!) + }) + .show() + } + /** Displays an alert for a particular check. There are two types of alerts: - ones that require an app restart, which prompt the user to exit the app diff --git a/phpmon/Domain/Menu/MainMenu+Startup.swift b/phpmon/Domain/Menu/MainMenu+Startup.swift index 8e2c2b0..80ed97e 100644 --- a/phpmon/Domain/Menu/MainMenu+Startup.swift +++ b/phpmon/Domain/Menu/MainMenu+Startup.swift @@ -115,6 +115,9 @@ extension MainMenu { // Finally! Log.info("PHP Monitor is ready to serve!") + // Avoid showing the "startup timeout" alert + Startup.invalidateTimeoutTimer() + // Check if we upgraded from a previous version AppUpdater.checkIfUpdateWasPerformed() } diff --git a/phpmon/Modules/PHP Config Editor/UI/ByteLimitView.swift b/phpmon/Modules/PHP Config Editor/UI/ByteLimitView.swift index 7e5cc77..43c905a 100644 --- a/phpmon/Modules/PHP Config Editor/UI/ByteLimitView.swift +++ b/phpmon/Modules/PHP Config Editor/UI/ByteLimitView.swift @@ -112,5 +112,4 @@ struct ByteLimitView: View { #Preview("Config Manager") { ConfigManagerView() .frame(width: 600, height: .infinity) - .previewDisplayName("Config Manager") } diff --git a/phpmon/Vendor/HotKey/ModifierFlagsExtension.swift b/phpmon/Vendor/HotKey/ModifierFlagsExtension.swift index 8ab6613..a0e7b59 100644 --- a/phpmon/Vendor/HotKey/ModifierFlagsExtension.swift +++ b/phpmon/Vendor/HotKey/ModifierFlagsExtension.swift @@ -45,7 +45,7 @@ extension NSEvent.ModifierFlags { } } -extension NSEvent.ModifierFlags: CustomStringConvertible { +extension NSEvent.ModifierFlags: @retroactive CustomStringConvertible { public var description: String { var output = "" diff --git a/phpmon/en.lproj/Localizable.strings b/phpmon/en.lproj/Localizable.strings index 34f5409..b27ce4e 100644 --- a/phpmon/en.lproj/Localizable.strings +++ b/phpmon/en.lproj/Localizable.strings @@ -864,3 +864,14 @@ Please note that some features (greyed out below) are currently unavailable beca "alert.language_changed.title" = "You must restart PHP Monitor!"; "alert.language_changed.subtitle" = "You just changed the display language of PHP Monitor. The menu will immediately use the correct language, but you may need to restart the app for all text throughout the app to reflect your new language choice."; + +// STARTUP TIMEOUT + +"startup.timeout.ignore" = "Ignore"; +"startup.timeout.title" = "PHP Monitor is taking too long to initialize!"; +"startup.timeout.subtitle" = "If PHP Monitor remains busy for longer than 30 seconds, there may be something wrong with your Homebrew setup."; +"startup.timeout.description" = "Sometimes, due to various file permission issues, things may break. You can try using `brew doctor` and `brew cleanup` to fix this. + +It is recommended to restart PHP Monitor afterwards. Learn more about this issue at: https://github.com/nicoverbruggen/phpmon/issues/294. + +If PHP Monitor has finished initializing anyway or you want to wait a bit longer, feel free to click 'Ignore' and use PHP Monitor as usual. Either way, you may want to investigate, because this isn't supposed to take this long.";