ghostty/macos/Sources/Features/ClipboardConfirmation/ClipboardConfirmationView.swift
Thorsten Ball b7a715ec86 macos: allow submitting clipboard confirmation with return
Before this change I couldn't submit the dialog with return. Or
cmd+return.

From what I understand the problem was that the `TextEditor` always
steals the default focus. I tried a bunch of workarounds I found to set
the default focus on the button, but none of them worked.

Then I thought: do we even need a full-on Text*Editor*? So I switched
`TextEditor` to `Text` with a `ScrollView`: things look the same, text
is selectable and scrollable, but I can hit return to submit the dialog.
2024-01-10 06:58:56 +01:00

78 lines
2.5 KiB
Swift

import SwiftUI
/// This delegate is notified of the completion result of the clipboard confirmation dialog.
protocol ClipboardConfirmationViewDelegate: AnyObject {
func clipboardConfirmationComplete(_ action: ClipboardConfirmationView.Action, _ request: Ghostty.ClipboardRequest)
}
/// The SwiftUI view for showing a clipboard confirmation dialog.
struct ClipboardConfirmationView: View {
enum Action : String {
case cancel
case confirm
static func text(_ action: Action, _ reason: Ghostty.ClipboardRequest) -> String {
switch (action, reason) {
case (.cancel, .paste):
return "Cancel"
case (.cancel, .osc_52_read), (.cancel, .osc_52_write):
return "Deny"
case (.confirm, .paste):
return "Paste"
case (.confirm, .osc_52_read), (.confirm, .osc_52_write):
return "Allow"
}
}
}
/// The contents of the paste.
let contents: String
/// The type of the clipboard request
let request: Ghostty.ClipboardRequest
/// Optional delegate to get results. If this is nil, then this view will never close on its own.
weak var delegate: ClipboardConfirmationViewDelegate? = nil
var body: some View {
VStack {
HStack {
Image(systemName: "exclamationmark.triangle.fill")
.foregroundColor(.yellow)
.font(.system(size: 42))
.padding()
.frame(alignment: .center)
Text(request.text())
.frame(maxWidth: .infinity, alignment: .leading)
.padding()
}
ScrollView {
Text(contents)
.textSelection(.enabled)
.font(.system(.body, design: .monospaced))
.padding(.all, 4)
}
HStack {
Spacer()
Button(Action.text(.cancel, request)) { onCancel() }
.keyboardShortcut(.cancelAction)
Button(Action.text(.confirm, request)) { onPaste() }
.keyboardShortcut(.defaultAction)
Spacer()
}
.padding(.bottom)
}
}
private func onCancel() {
delegate?.clipboardConfirmationComplete(.cancel, request)
}
private func onPaste() {
delegate?.clipboardConfirmationComplete(.confirm, request)
}
}