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

🏗 WIP: Tweaks to PHP Doctor

This commit is contained in:
2022-08-12 20:50:27 +02:00
parent 0c59d14da5
commit 4e5b178e36
8 changed files with 105 additions and 61 deletions

View File

@ -68,6 +68,11 @@
</CommandLineArgument> </CommandLineArgument>
</CommandLineArguments> </CommandLineArguments>
<EnvironmentVariables> <EnvironmentVariables>
<EnvironmentVariable
key = "EXTREME_DOCTOR_MODE"
value = ""
isEnabled = "YES">
</EnvironmentVariable>
<EnvironmentVariable <EnvironmentVariable
key = "PAINT_PHPMON_SWIFTUI_VIEWS" key = "PAINT_PHPMON_SWIFTUI_VIEWS"
value = "" value = ""

View File

@ -82,7 +82,7 @@ class StatusMenu: NSMenu {
self.addItem(NSMenuItem.separator()) self.addItem(NSMenuItem.separator())
let count = WarningManager.shared.warnings.count let count = WarningManager.shared.warnings.count
self.addItem(NSMenuItem(title: (count == 1 ? "mi_warning" : "mi_warnings").localized(count), self.addItem(NSMenuItem(title: "mi_warnings".localized(count),
action: #selector(MainMenu.openWarnings), keyEquivalent: "")) action: #selector(MainMenu.openWarnings), keyEquivalent: ""))
} }

View File

@ -10,26 +10,50 @@ import SwiftUI
struct WarningListView: View { struct WarningListView: View {
var body: some View { var body: some View {
VStack {
HStack(spacing: 15) {
Image(systemName: "stethoscope.circle.fill")
.resizable()
.frame(width: 40, height: 40)
.foregroundColor(Color.red)
.padding(12)
VStack(alignment: .trailing, spacing: 5) {
Text("warnings.description".localizedForSwiftUI)
.frame(maxWidth: .infinity, alignment: .leading)
Text("warnings.disclaimer".localizedForSwiftUI)
.font(.system(size: 12))
.foregroundColor(.gray)
.frame(maxWidth: .infinity, alignment: .leading)
}
}
.padding(10)
List { List {
VStack(alignment: .leading) { VStack(alignment: .leading, spacing: 0) {
ForEach(WarningManager.shared.warnings) { warning in ForEach(WarningManager.shared.warnings) { warning in
Group {
WarningView( WarningView(
title: warning.titleText, title: warning.title,
description: warning.descriptionText, paragraphs: warning.paragraphs,
documentationUrl: warning.url documentationUrl: warning.url
) )
Divider() .fixedSize(horizontal: false, vertical: true)
}
}
Divider()
}.padding(5)
}
}.frame(minHeight: 0, maxHeight: .infinity).padding(5)
}
.listRowInsets(EdgeInsets())
.listStyle(.plain)
.frame(maxHeight: .infinity, alignment: .top)
} }
.navigationTitle("Warnings")
.listStyle(.automatic)
} }
} }
struct WarningListView_Previews: PreviewProvider { struct WarningListView_Previews: PreviewProvider {
static var previews: some View { static var previews: some View {
WarningListView() WarningListView()
.frame(width: 600, height: 480)
} }
} }

View File

@ -10,27 +10,37 @@ import SwiftUI
struct WarningView: View { struct WarningView: View {
@State var title: String @State var title: String
@State var description: String @State var paragraphs: [String]
@State var documentationUrl: String? @State var documentationUrl: String?
var body: some View { var body: some View {
VStack(alignment: .leading) { VStack(alignment: .leading) {
HStack(spacing: 10) { HStack(alignment: .top, spacing: 10) {
Image(systemName: "exclamationmark.triangle.fill") Image(systemName: "bandage.fill")
.resizable() .resizable()
.frame(width: 18, height: 18) .frame(width: 18, height: 18)
.foregroundColor(Color.orange) .foregroundColor(Color.orange)
.padding() .padding(.trailing, 5)
VStack(alignment: .leading, spacing: 5) { VStack(alignment: .leading, spacing: 15) {
VStack(alignment: .leading, spacing: 10) {
Text(title.localizedForSwiftUI) Text(title.localizedForSwiftUI)
.fontWeight(.bold) .fontWeight(.bold)
Text(description.localizedForSwiftUI) ForEach(paragraphs, id: \.self) { paragraph in
.font(.system(size: 12)) Text(paragraph.localizedForSwiftUI)
.font(.system(size: 13))
} }
}
.fixedSize(horizontal: false, vertical: false)
.frame(
minWidth: 0, maxWidth: .infinity,
minHeight: 0, maxHeight: .infinity,
alignment: .topLeading
)
if documentationUrl != nil { if documentationUrl != nil {
Button("Learn More") { Button("Learn More") {
NSWorkspace.shared.open(URL(string: documentationUrl!)!) NSWorkspace.shared.open(URL(string: documentationUrl!)!)
}.padding() }
}
} }
}.padding(5) }.padding(5)
} }
@ -39,15 +49,6 @@ struct WarningView: View {
struct WarningView_Previews: PreviewProvider { struct WarningView_Previews: PreviewProvider {
static var previews: some View { static var previews: some View {
WarningView( WarningListView().frame(width: 600, height: 480)
title: "warnings.helper_permissions_title",
description: "warnings.helper_permissions.description",
documentationUrl: "https://nicoverbruggen.be"
)
WarningView(
title: "warnings.helper_permissions_title",
description: "warnings.helper_permissions.description"
)
.preferredColorScheme(.dark)
} }
} }

View File

@ -12,21 +12,21 @@ struct Warning: Identifiable {
var id = UUID() var id = UUID()
let command: () async -> Bool let command: () async -> Bool
let name: String let name: String
let titleText: String let title: String
let descriptionText: String let paragraphs: [String]
let url: String? let url: String?
init( init(
command: @escaping () async -> Bool, command: @escaping () async -> Bool,
name: String, name: String,
titleText: String, title: String,
descriptionText: String, paragraphs: [String],
url: String? url: String?
) { ) {
self.command = command self.command = command
self.name = name self.name = name
self.titleText = titleText self.title = title
self.descriptionText = descriptionText self.paragraphs = paragraphs
self.url = url self.url = url
} }

View File

@ -13,25 +13,31 @@ class WarningManager {
static var shared = WarningManager() static var shared = WarningManager()
init() {
if isRunningSwiftUIPreview {
self.warnings = self.evaluations
}
}
public let evaluations: [Warning] = [ public let evaluations: [Warning] = [
Warning(
command: {
!FileManager.default.isWritableFile(atPath: "/usr/local/bin/")
},
name: "`/usr/local/bin` not writable",
titleText: "warnings.helper_permissions.title",
descriptionText: "warnings.helper_permissions.description",
url: nil
),
Warning( Warning(
command: { command: {
return Shell.pipe("sysctl -n sysctl.proc_translated") return Shell.pipe("sysctl -n sysctl.proc_translated")
.trimmingCharacters(in: .whitespacesAndNewlines) == "1" .trimmingCharacters(in: .whitespacesAndNewlines) == "1"
}, },
name: "Running PHP Monitor with Rosetta on M1", name: "Running PHP Monitor with Rosetta on M1",
titleText: "warnings.arm_compatibility.title", title: "warnings.arm_compatibility.title",
descriptionText: "warnings.arm_compatibility.description", paragraphs: ["warnings.arm_compatibility.description"],
url: "https://github.com/nicoverbruggen/phpmon/wiki/PHP-Monitor-and-Apple-Silicon" url: "https://github.com/nicoverbruggen/phpmon/wiki/PHP-Monitor-and-Apple-Silicon"
),
Warning(
command: {
!FileManager.default.isWritableFile(atPath: "/usr/local/bin/")
},
name: "`/usr/local/bin` not writable",
title: "warnings.helper_permissions.title",
paragraphs: ["warnings.helper_permissions.description", "warnings.helper_permissions.unavailable"],
url: "https://github.com/nicoverbruggen/phpmon/wiki/PHP-Monitor-helper-binaries"
) )
] ]
@ -50,6 +56,7 @@ class WarningManager {
*/ */
func checkEnvironment() async { func checkEnvironment() async {
self.warnings = [] self.warnings = []
for check in self.evaluations { for check in self.evaluations {
if await check.applies() { if await check.applies() {
Log.info("[WARNING] \(check.name)") Log.info("[WARNING] \(check.name)")
@ -57,6 +64,11 @@ class WarningManager {
continue continue
} }
} }
// For debugging purposes, we may wish to see all possible evaluations listed
if ProcessInfo.processInfo.environment["EXTREME_DOCTOR_MODE"] != nil {
self.warnings = self.evaluations
}
} }
} }

View File

@ -22,12 +22,12 @@ class WarningsWindowController: PMWindowController {
windowController.window = NSWindow() windowController.window = NSWindow()
guard let window = windowController.window else { return } guard let window = windowController.window else { return }
window.title = "warnings.title".localized window.title = ""
window.styleMask = [.titled, .closable, .miniaturizable] window.styleMask = [.titled, .closable, .miniaturizable]
window.titlebarAppearsTransparent = true window.titlebarAppearsTransparent = true
window.delegate = delegate ?? windowController window.delegate = delegate ?? windowController
window.contentView = NSHostingView(rootView: WarningListView()) window.contentView = NSHostingView(rootView: WarningListView())
window.setContentSize(NSSize(width: 600, height: 300)) window.setContentSize(NSSize(width: 600, height: 480))
App.shared.warningsWindowController = windowController App.shared.warningsWindowController = windowController
} }

View File

@ -55,8 +55,7 @@
"mi_detected_extensions" = "Detected Extensions"; "mi_detected_extensions" = "Detected Extensions";
"mi_no_extensions_detected" = "No additional extensions detected."; "mi_no_extensions_detected" = "No additional extensions detected.";
"mi_warning" = "⚠️ %i Warning"; "mi_warnings" = "(%i) PHP Doctor...";
"mi_warnings" = "⚠️ %i Warnings...";
"mi_valet" = "Laravel Valet"; "mi_valet" = "Laravel Valet";
"mi_domain_list" = "View Domains List..."; "mi_domain_list" = "View Domains List...";
@ -509,12 +508,15 @@ If you are seeing this message but are confused why this folder has gone missing
// WARNINGS // WARNINGS
"warnings.title" = "Warnings"; "warnings.title" = "PHP Doctor";
"warnings.description" = "**PHP Doctor** will suggest improvements to your active system configuration.";
"warnings.disclaimer" = "You may choose to hide all recommendations from the PHP Monitor menu in Preferences, but it is recommended that you deal with all actionable items.";
"warnings.helper_permissions.title" = "Helpers could not be written!"; "warnings.helper_permissions.title" = "PHP Monitors helpers are currently unavailable.";
"warnings.helper_permissions.description" = "The helper files in `/usr/local/bin` could not be written because PHP Monitor does not have permission to write there."; "warnings.helper_permissions.description" = "PHP Monitor comes with various helper binaries. Using these binaries allows you to easily invoke a specific version of PHP without switching the linked PHP version.";
"warnings.helper_permissions.unavailable" = "However, these helpers are currently *unavailable* because PHP Monitor could not create the required symlinks (alternatively, you could add PHP Monitor's helper directory to your `PATH` variable to make this warning go away as well).";
"warnings.arm_compatibility.title" = "You are running PHP Monitor using Rosetta"; "warnings.arm_compatibility.title" = "You are running PHP Monitor using Rosetta on Apple Silicon, which means your PHP environment is also running via Rosetta.";
"warnings.arm_compatibility.description" = "You appear to be running an ARM-compatible version of macOS, but you are currently running PHP Monitor using Rosetta. While this will work correctly, it is recommended that you use the native version of Homebrew."; "warnings.arm_compatibility.description" = "You appear to be running an ARM-compatible version of macOS, but you are currently running PHP Monitor using Rosetta. While this will work correctly, it is recommended that you use the native version of Homebrew.";
// ONBOARDING // ONBOARDING