macos: confirm on quit

This commit is contained in:
Mitchell Hashimoto
2023-03-27 09:41:00 -07:00
parent 9f128afe31
commit 92870e4e60
3 changed files with 61 additions and 10 deletions

View File

@ -20,6 +20,7 @@
A5CEAFDE29B8058B00646FDA /* SplitView.Divider.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5CEAFDD29B8058B00646FDA /* SplitView.Divider.swift */; }; A5CEAFDE29B8058B00646FDA /* SplitView.Divider.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5CEAFDD29B8058B00646FDA /* SplitView.Divider.swift */; };
A5CEAFFF29C2410700646FDA /* Backport.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5CEAFFE29C2410700646FDA /* Backport.swift */; }; A5CEAFFF29C2410700646FDA /* Backport.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5CEAFFE29C2410700646FDA /* Backport.swift */; };
A5D495A2299BEC7E00DD1313 /* GhosttyKit.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = A5D495A1299BEC7E00DD1313 /* GhosttyKit.xcframework */; }; A5D495A2299BEC7E00DD1313 /* GhosttyKit.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = A5D495A1299BEC7E00DD1313 /* GhosttyKit.xcframework */; };
A5FECBD729D1FC3900022361 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5FECBD629D1FC3900022361 /* ContentView.swift */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
@ -38,6 +39,7 @@
A5CEAFDD29B8058B00646FDA /* SplitView.Divider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplitView.Divider.swift; sourceTree = "<group>"; }; A5CEAFDD29B8058B00646FDA /* SplitView.Divider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplitView.Divider.swift; sourceTree = "<group>"; };
A5CEAFFE29C2410700646FDA /* Backport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Backport.swift; sourceTree = "<group>"; }; A5CEAFFE29C2410700646FDA /* Backport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Backport.swift; sourceTree = "<group>"; };
A5D495A1299BEC7E00DD1313 /* GhosttyKit.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = GhosttyKit.xcframework; sourceTree = "<group>"; }; A5D495A1299BEC7E00DD1313 /* GhosttyKit.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = GhosttyKit.xcframework; sourceTree = "<group>"; };
A5FECBD629D1FC3900022361 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
@ -63,6 +65,7 @@
A55685DF29A03A9F004303CE /* AppError.swift */, A55685DF29A03A9F004303CE /* AppError.swift */,
A59444F629A2ED5200725BBA /* SettingsView.swift */, A59444F629A2ED5200725BBA /* SettingsView.swift */,
A5CEAFFE29C2410700646FDA /* Backport.swift */, A5CEAFFE29C2410700646FDA /* Backport.swift */,
A5FECBD629D1FC3900022361 /* ContentView.swift */,
); );
path = Sources; path = Sources;
sourceTree = "<group>"; sourceTree = "<group>";
@ -192,6 +195,7 @@
files = ( files = (
A55B7BBC29B6FC330055DE60 /* SurfaceView.swift in Sources */, A55B7BBC29B6FC330055DE60 /* SurfaceView.swift in Sources */,
A59444F729A2ED5200725BBA /* SettingsView.swift in Sources */, A59444F729A2ED5200725BBA /* SettingsView.swift in Sources */,
A5FECBD729D1FC3900022361 /* ContentView.swift in Sources */,
A55B7BB829B6F53A0055DE60 /* Package.swift in Sources */, A55B7BB829B6F53A0055DE60 /* Package.swift in Sources */,
A55B7BBE29B701360055DE60 /* Ghostty.SplitView.swift in Sources */, A55B7BBE29B701360055DE60 /* Ghostty.SplitView.swift in Sources */,
A55B7BB629B6F47F0055DE60 /* AppState.swift in Sources */, A55B7BB629B6F47F0055DE60 /* AppState.swift in Sources */,

View File

@ -0,0 +1,48 @@
import SwiftUI
import GhosttyKit
struct ContentView: View {
let ghostty: Ghostty.AppState
@EnvironmentObject private var appDelegate: AppDelegate
var body: some View {
switch ghostty.readiness {
case .loading:
Text("Loading")
.onChange(of: appDelegate.confirmQuit) { value in
guard value else { return }
NSApplication.shared.reply(toApplicationShouldTerminate: true)
}
case .error:
ErrorView()
.onChange(of: appDelegate.confirmQuit) { value in
guard value else { return }
NSApplication.shared.reply(toApplicationShouldTerminate: true)
}
case .ready:
Ghostty.TerminalSplit(onClose: Self.closeWindow)
.ghosttyApp(ghostty.app!)
.confirmationDialog(
"Quit Ghostty?",
isPresented: $appDelegate.confirmQuit) {
Button("Close Ghostty", role: .destructive) {
NSApplication.shared.reply(toApplicationShouldTerminate: true)
}
.keyboardShortcut(.defaultAction)
Button("Cancel", role: .cancel) {
NSApplication.shared.reply(toApplicationShouldTerminate: false)
}
.keyboardShortcut(.cancelAction)
} message: {
Text("All terminal sessions will be terminated.")
}
}
}
static func closeWindow() {
guard let currentWindow = NSApp.keyWindow else { return }
currentWindow.close()
}
}

View File

@ -18,15 +18,7 @@ struct GhosttyApp: App {
var body: some Scene { var body: some Scene {
WindowGroup { WindowGroup {
switch ghostty.readiness { ContentView(ghostty: ghostty)
case .loading:
Text("Loading")
case .error:
ErrorView()
case .ready:
Ghostty.TerminalSplit(onClose: Self.closeWindow)
.ghosttyApp(ghostty.app!)
}
} }
.backport.defaultSize(width: 800, height: 600) .backport.defaultSize(width: 800, height: 600)
.commands { .commands {
@ -110,7 +102,9 @@ struct GhosttyApp: App {
} }
} }
class AppDelegate: NSObject, NSApplicationDelegate { class AppDelegate: NSObject, NSApplicationDelegate, ObservableObject {
@Published var confirmQuit: Bool = false
// See CursedMenuManager for more information. // See CursedMenuManager for more information.
private var menuManager: CursedMenuManager? private var menuManager: CursedMenuManager?
@ -124,6 +118,11 @@ class AppDelegate: NSObject, NSApplicationDelegate {
// we can't create from SwiftUI. // we can't create from SwiftUI.
menuManager = CursedMenuManager() menuManager = CursedMenuManager()
} }
func applicationShouldTerminate(_ sender: NSApplication) -> NSApplication.TerminateReply {
confirmQuit = true
return .terminateLater
}
} }
/// SwiftUI as of macOS 13.x provides no way to manage the default menu items that are created /// SwiftUI as of macOS 13.x provides no way to manage the default menu items that are created