server and settings setup
This commit is contained in:
@@ -17,6 +17,7 @@ struct Check: Decodable {
|
||||
let need: String
|
||||
let `for`: String
|
||||
let ok: Bool
|
||||
let command: String
|
||||
let fix: String
|
||||
let blocking: Bool
|
||||
}
|
||||
@@ -39,9 +40,14 @@ struct ChecksView: View {
|
||||
}
|
||||
Text("\(need(check)), for \(check.for)").foregroundStyle(Palette.muted)
|
||||
if !check.ok {
|
||||
Text(check.fix)
|
||||
.textSelection(.enabled)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
if !check.command.isEmpty {
|
||||
CommandBox(command: check.command)
|
||||
}
|
||||
if !check.fix.isEmpty {
|
||||
Text(check.fix)
|
||||
.textSelection(.enabled)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -67,6 +73,66 @@ struct ChecksView: View {
|
||||
}
|
||||
}
|
||||
|
||||
private struct CommandBox: View {
|
||||
let command: String
|
||||
@ViewState private var copied = false
|
||||
@ViewState private var failure: String?
|
||||
|
||||
var body: some View {
|
||||
box
|
||||
if let failure {
|
||||
Text(failure)
|
||||
.foregroundStyle(Palette.danger)
|
||||
.textSelection(.enabled)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
}
|
||||
}
|
||||
|
||||
private var box: some View {
|
||||
HStack(alignment: .firstTextBaseline, spacing: 8) {
|
||||
Text(verbatim: command)
|
||||
.font(Fonts.font(12))
|
||||
.textSelection(.enabled)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
Button(copied ? "Copied" : "Copy", action: copy)
|
||||
.buttonStyle(SmallLinkButtonStyle())
|
||||
.help("Copy the command to the clipboard")
|
||||
Button("Run in Terminal", action: run)
|
||||
.buttonStyle(SmallLinkButtonStyle())
|
||||
.help("Open Terminal and run the command")
|
||||
}
|
||||
.padding(.horizontal, 8)
|
||||
.padding(.vertical, 6)
|
||||
.background(Palette.raised, in: RoundedRectangle(cornerRadius: 6))
|
||||
.overlay(RoundedRectangle(cornerRadius: 6).stroke(Palette.border))
|
||||
.padding(.vertical, 2)
|
||||
}
|
||||
|
||||
private func copy() {
|
||||
NSPasteboard.general.clearContents()
|
||||
NSPasteboard.general.setString(command, forType: .string)
|
||||
copied = true
|
||||
Task {
|
||||
try? await Task.sleep(for: .milliseconds(1500))
|
||||
copied = false
|
||||
}
|
||||
}
|
||||
|
||||
private func run() {
|
||||
let shell = unsafe String(cString: getpwuid(getuid()).pointee.pw_shell)
|
||||
let file = FileManager.default.temporaryDirectory.appending(path: "byre-install-\(UUID().uuidString).command")
|
||||
do {
|
||||
try "#!\(shell) -l\n\(command)\n".write(to: file, atomically: true, encoding: .utf8)
|
||||
try FileManager.default.setAttributes([.posixPermissions: 0o755], ofItemAtPath: file.path)
|
||||
failure = nil
|
||||
} catch {
|
||||
failure = errorText(error)
|
||||
return
|
||||
}
|
||||
NSWorkspace.shared.open([file], withApplicationAt: URL(filePath: "/System/Applications/Utilities/Terminal.app"), configuration: NSWorkspace.OpenConfiguration())
|
||||
}
|
||||
}
|
||||
|
||||
// replayd keys ScreenCaptureKit clients by executable path, so the check runs from its own copy beside client_hands' byre-hands.
|
||||
func checkLocalPermissions() async throws -> [Permission] {
|
||||
let dir = FileManager.default.temporaryDirectory.appending(path: "byre-hands-check-\(UUID().uuidString)")
|
||||
|
||||
Reference in New Issue
Block a user