feat(macos): detect installed CLI helper
This commit is contained in:
@@ -5,6 +5,8 @@ struct GeneralSettings: View {
|
||||
@ObservedObject var state: AppState
|
||||
@State private var isInstallingCLI = false
|
||||
@State private var cliStatus: String?
|
||||
@State private var cliInstalled = false
|
||||
@State private var cliInstallLocation: String?
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: 18) {
|
||||
@@ -63,6 +65,7 @@ struct GeneralSettings: View {
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.padding(.horizontal, 22)
|
||||
.onAppear { self.refreshCLIStatus() }
|
||||
}
|
||||
|
||||
private var activeBinding: Binding<Bool> {
|
||||
@@ -80,18 +83,37 @@ struct GeneralSettings: View {
|
||||
if self.isInstallingCLI {
|
||||
ProgressView().controlSize(.small)
|
||||
} else {
|
||||
Text("Install CLI helper")
|
||||
Text(self.cliInstalled ? "Reinstall CLI helper" : "Install CLI helper")
|
||||
}
|
||||
}
|
||||
.disabled(self.isInstallingCLI)
|
||||
|
||||
if let status = cliStatus {
|
||||
Text(status)
|
||||
.font(.caption)
|
||||
if self.isInstallingCLI {
|
||||
Text("Working...")
|
||||
.font(.callout)
|
||||
.foregroundStyle(.secondary)
|
||||
} else if self.cliInstalled {
|
||||
Label("Installed", systemImage: "checkmark.circle.fill")
|
||||
.font(.callout)
|
||||
.foregroundStyle(.secondary)
|
||||
} else {
|
||||
Text("Not installed")
|
||||
.font(.callout)
|
||||
.foregroundStyle(.secondary)
|
||||
.lineLimit(2)
|
||||
}
|
||||
}
|
||||
|
||||
if let status = cliStatus {
|
||||
Text(status)
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
.lineLimit(2)
|
||||
} else if let installLocation = self.cliInstallLocation {
|
||||
Text("Found at \(installLocation)")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
.lineLimit(2)
|
||||
}
|
||||
Text("Symlink \"clawdis-mac\" into /usr/local/bin and /opt/homebrew/bin for scripts.")
|
||||
.font(.callout)
|
||||
.foregroundStyle(.secondary)
|
||||
@@ -104,7 +126,16 @@ struct GeneralSettings: View {
|
||||
self.isInstallingCLI = true
|
||||
defer { isInstallingCLI = false }
|
||||
await CLIInstaller.install { status in
|
||||
await MainActor.run { self.cliStatus = status }
|
||||
await MainActor.run {
|
||||
self.cliStatus = status
|
||||
self.refreshCLIStatus()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func refreshCLIStatus() {
|
||||
let installLocation = CLIInstaller.installedLocation()
|
||||
self.cliInstallLocation = installLocation
|
||||
self.cliInstalled = installLocation != nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,6 +90,29 @@ enum LaunchAgentManager {
|
||||
|
||||
@MainActor
|
||||
enum CLIInstaller {
|
||||
static func installedLocation() -> String? {
|
||||
let fm = FileManager.default
|
||||
|
||||
for basePath in cliHelperSearchPaths {
|
||||
let candidate = URL(fileURLWithPath: basePath).appendingPathComponent("clawdis-mac").path
|
||||
var isDirectory: ObjCBool = false
|
||||
|
||||
guard fm.fileExists(atPath: candidate, isDirectory: &isDirectory), !isDirectory.boolValue else {
|
||||
continue
|
||||
}
|
||||
|
||||
if fm.isExecutableFile(atPath: candidate) {
|
||||
return candidate
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
static func isInstalled() -> Bool {
|
||||
self.installedLocation() != nil
|
||||
}
|
||||
|
||||
static func install(statusHandler: @escaping @Sendable (String) async -> Void) async {
|
||||
let helper = Bundle.main.bundleURL.appendingPathComponent("Contents/MacOS/ClawdisCLI")
|
||||
guard FileManager.default.isExecutableFile(atPath: helper.path) else {
|
||||
|
||||
Reference in New Issue
Block a user