macos: hook up paste protection delegate, cancel button

This commit is contained in:
Mitchell Hashimoto
2023-11-04 20:47:16 -07:00
parent 5f5f5a44ec
commit 04acaf8b20
4 changed files with 85 additions and 14 deletions

View File

@ -6,10 +6,24 @@ import GhosttyKit
class PasteProtectionController: NSWindowController {
override var windowNibName: NSNib.Name? { "PasteProtection" }
weak private var delegate: PasteProtectionViewDelegate? = nil
init(delegate: PasteProtectionViewDelegate) {
self.delegate = delegate
super.init(window: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) is not supported for this view")
}
//MARK: - NSWindowController
override func windowDidLoad() {
guard let window = window else { return }
window.contentView = NSHostingView(rootView: PasteProtectionView())
window.contentView = NSHostingView(rootView: PasteProtectionView(
contents: "Hello",
delegate: delegate
))
}
}

View File

@ -1,18 +1,57 @@
import SwiftUI
protocol PasteProtectionViewDelegate: AnyObject {
func pasteProtectionComplete(_ action: PasteProtectionView.Action)
}
struct PasteProtectionView: View {
enum Action : String {
case cancel
case paste
}
let contents: String
weak var delegate: PasteProtectionViewDelegate? = nil
var body: some View {
HStack {
Image("AppIconImage")
.resizable()
.scaledToFit()
.frame(width: 128, height: 128)
VStack(alignment: .leading) {
Text("Oh, no. 😭").font(.title)
Text("Something went fatally wrong.\nCheck the logs and restart Ghostty.")
VStack {
HStack {
Image(systemName: "exclamationmark.triangle.fill")
.foregroundColor(.yellow)
.font(.system(size: 42))
.padding()
.frame(alignment: .center)
Text("Pasting this text to the terminal may be dangerous as it looks like " +
"some commands may be executed.")
.frame(maxWidth: .infinity, alignment: .leading)
.padding()
}
TextEditor(text: .constant(contents))
.disabled(true)
.textSelection(.enabled)
.font(.system(.body, design: .monospaced))
.padding(.all, 4)
HStack {
Spacer()
Button("Cancel") { onCancel() }
.keyboardShortcut(.cancelAction)
Button("Paste") { onPaste() }
.keyboardShortcut(.defaultAction)
Spacer()
}
.padding(.bottom)
}
.padding()
}
private func onCancel() {
AppDelegate.logger.warning("PASTE onCancel")
delegate?.pasteProtectionComplete(.cancel)
}
private func onPaste() {
delegate?.pasteProtectionComplete(.paste)
}
}

View File

@ -4,7 +4,10 @@ import SwiftUI
import GhosttyKit
/// The terminal controller is an NSWindowController that maps 1:1 to a terminal window.
class TerminalController: NSWindowController, NSWindowDelegate, TerminalViewDelegate, TerminalViewModel {
class TerminalController: NSWindowController, NSWindowDelegate,
TerminalViewDelegate, TerminalViewModel,
PasteProtectionViewDelegate
{
override var windowNibName: NSNib.Name? { "Terminal" }
/// The app instance that this terminal view will represent.
@ -28,6 +31,9 @@ class TerminalController: NSWindowController, NSWindowDelegate, TerminalViewDele
/// True when an alert is active so we don't overlap multiple.
private var alert: NSAlert? = nil
/// The paste protection window, if shown.
private var pasteProtection: NSWindow? = nil
init(_ ghostty: Ghostty.AppState, withBaseConfig base: Ghostty.SurfaceConfiguration? = nil) {
self.ghostty = ghostty
super.init(window: nil)
@ -117,7 +123,8 @@ class TerminalController: NSWindowController, NSWindowDelegate, TerminalViewDele
))
// TODO: remove this, just for dev
let pp = PasteProtectionController()
let pp = PasteProtectionController(delegate: self)
self.pasteProtection = pp.window
window.beginSheet(pp.window!)
}
@ -313,6 +320,17 @@ class TerminalController: NSWindowController, NSWindowDelegate, TerminalViewDele
self.window?.close()
}
//MARK: - PasteProtectionViewDelegate
func pasteProtectionComplete(_ action: PasteProtectionView.Action) {
if let pasteWindow = self.pasteProtection {
window?.endSheet(pasteWindow)
self.pasteProtection = nil
}
AppDelegate.logger.warning("PASTE action=\(action.rawValue)")
}
//MARK: - Notifications
@objc private func onGotoTab(notification: SwiftUI.Notification) {

View File

@ -4,7 +4,7 @@ import GhosttyKit
/// This delegate is notified of actions and property changes regarding the terminal view. This
/// delegate is optional and can be used by a TerminalView caller to react to changes such as
/// titles being set, cell sizes being changed, etc.
protocol TerminalViewDelegate: AnyObject, ObservableObject {
protocol TerminalViewDelegate: AnyObject {
/// Called when the currently focused surface changed. This can be nil.
func focusedSurfaceDidChange(to: Ghostty.SurfaceView?)