mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
macos: hook up paste protection delegate, cancel button
This commit is contained in:
@ -6,10 +6,24 @@ import GhosttyKit
|
|||||||
class PasteProtectionController: NSWindowController {
|
class PasteProtectionController: NSWindowController {
|
||||||
override var windowNibName: NSNib.Name? { "PasteProtection" }
|
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
|
//MARK: - NSWindowController
|
||||||
|
|
||||||
override func windowDidLoad() {
|
override func windowDidLoad() {
|
||||||
guard let window = window else { return }
|
guard let window = window else { return }
|
||||||
window.contentView = NSHostingView(rootView: PasteProtectionView())
|
window.contentView = NSHostingView(rootView: PasteProtectionView(
|
||||||
|
contents: "Hello",
|
||||||
|
delegate: delegate
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,57 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct PasteProtectionView: View {
|
protocol PasteProtectionViewDelegate: AnyObject {
|
||||||
var body: some View {
|
func pasteProtectionComplete(_ action: PasteProtectionView.Action)
|
||||||
HStack {
|
}
|
||||||
Image("AppIconImage")
|
|
||||||
.resizable()
|
|
||||||
.scaledToFit()
|
|
||||||
.frame(width: 128, height: 128)
|
|
||||||
|
|
||||||
VStack(alignment: .leading) {
|
struct PasteProtectionView: View {
|
||||||
Text("Oh, no. 😭").font(.title)
|
enum Action : String {
|
||||||
Text("Something went fatally wrong.\nCheck the logs and restart Ghostty.")
|
case cancel
|
||||||
|
case paste
|
||||||
|
}
|
||||||
|
|
||||||
|
let contents: String
|
||||||
|
weak var delegate: PasteProtectionViewDelegate? = nil
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,10 @@ import SwiftUI
|
|||||||
import GhosttyKit
|
import GhosttyKit
|
||||||
|
|
||||||
/// The terminal controller is an NSWindowController that maps 1:1 to a terminal window.
|
/// 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" }
|
override var windowNibName: NSNib.Name? { "Terminal" }
|
||||||
|
|
||||||
/// The app instance that this terminal view will represent.
|
/// 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.
|
/// True when an alert is active so we don't overlap multiple.
|
||||||
private var alert: NSAlert? = nil
|
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) {
|
init(_ ghostty: Ghostty.AppState, withBaseConfig base: Ghostty.SurfaceConfiguration? = nil) {
|
||||||
self.ghostty = ghostty
|
self.ghostty = ghostty
|
||||||
super.init(window: nil)
|
super.init(window: nil)
|
||||||
@ -117,7 +123,8 @@ class TerminalController: NSWindowController, NSWindowDelegate, TerminalViewDele
|
|||||||
))
|
))
|
||||||
|
|
||||||
// TODO: remove this, just for dev
|
// TODO: remove this, just for dev
|
||||||
let pp = PasteProtectionController()
|
let pp = PasteProtectionController(delegate: self)
|
||||||
|
self.pasteProtection = pp.window
|
||||||
window.beginSheet(pp.window!)
|
window.beginSheet(pp.window!)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -313,6 +320,17 @@ class TerminalController: NSWindowController, NSWindowDelegate, TerminalViewDele
|
|||||||
self.window?.close()
|
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
|
//MARK: - Notifications
|
||||||
|
|
||||||
@objc private func onGotoTab(notification: SwiftUI.Notification) {
|
@objc private func onGotoTab(notification: SwiftUI.Notification) {
|
||||||
|
@ -4,7 +4,7 @@ import GhosttyKit
|
|||||||
/// This delegate is notified of actions and property changes regarding the terminal view. This
|
/// 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
|
/// 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.
|
/// 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.
|
/// Called when the currently focused surface changed. This can be nil.
|
||||||
func focusedSurfaceDidChange(to: Ghostty.SurfaceView?)
|
func focusedSurfaceDidChange(to: Ghostty.SurfaceView?)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user