macOS: review windows when closing multiple tabs

This commit is contained in:
Lukas
2026-08-28 19:32:27 +02:00
parent 76e568b475
commit 777929a8fe
3 changed files with 68 additions and 16 deletions

View File

@@ -1346,13 +1346,9 @@ extension AppDelegate {
return .terminateLater
} else {
let alert = NSAlert()
alert.messageText = "You have \(controllersNeedConfirmation.count) windows with running processes. Do you want to review these windows before quitting?"
alert.informativeText = "If you don't review your windows, any running processes will be terminated"
alert.addButton(withTitle: "Review Windows...")
alert.addButton(withTitle: "Terminate Processes")
alert.addButton(withTitle: "Cancel")
alert.alertStyle = .warning
let alert = NSAlert.reviewWindowsAlert(
messageText: "You have \(controllersNeedConfirmation.count) windows with running processes. Do you want to review these windows before quitting?"
)
switch alert.runModal() {
case .alertFirstButtonReturn:

View File

@@ -1386,21 +1386,58 @@ class TerminalController: BaseTerminalController, TabGroupCloseCoordinator.Contr
// if we're closing the window. If we don't have a tabgroup for any
// reason we check ourselves.
let windows: [NSWindow] = window.tabGroup?.windows ?? [window]
guard let confirmController = windows
let confirmControllers = windows
.compactMap({ $0.windowController as? TerminalController })
.first(where: { $0.surfaceTree.contains(where: { $0.needsConfirmQuit }) })
.filter({ $0.surfaceTree.contains(where: { $0.needsConfirmQuit }) })
guard
!confirmControllers.isEmpty
else {
closeWindowImmediately()
return
}
if confirmControllers.count == 1 {
// We call confirmClose on the proper controller so the alert is
// attached to the window that needs confirmation.
confirmControllers[0].confirmClose(
messageText: "Close Window?",
informativeText: "All terminal sessions in this window will be terminated.",
) {
self.closeWindowImmediately()
}
return
}
// We call confirmClose on the proper controller so the alert is
// attached to the window that needs confirmation.
confirmController.confirmClose(
messageText: "Close Window?",
informativeText: "All terminal sessions in this window will be terminated.",
) {
self.closeWindowImmediately()
Task {
let alert = NSAlert.reviewWindowsAlert(
messageText: "You have \(confirmControllers.count) windows with running processes. Do you want to review these windows before closing?",
terminateNowButtonTitle: "Close"
)
switch await alert.beginSheetModal(for: window) {
case .alertFirstButtonReturn:
await reviewWindows(confirmControllers, window: window)
case .alertSecondButtonReturn:
closeWindowImmediately()
default:
break
}
}
}
private func reviewWindows(_ controllers: [TerminalController], window: NSWindow) async {
for controller in controllers {
let response = await controller.confirmCloseAsync(
messageText: "Close Window?",
informativeText: "All terminal sessions in this window will be terminated.",
)
if [.OK, .alertFirstButtonReturn].contains(response) {
// Close this tab
controller.closeTabImmediately()
continue
} else {
// Cancel the review
return
}
}
}

View File

@@ -0,0 +1,19 @@
import AppKit
extension NSAlert {
static func reviewWindowsAlert(
messageText: String,
informativeText: String = "If you don't review your windows, any running processes will be terminated",
terminateNowButtonTitle: String = "Terminate Processes"
) -> NSAlert {
let alert = NSAlert()
alert.messageText = messageText
alert.informativeText = informativeText
alert.addButton(withTitle: "Review Windows...")
alert.addButton(withTitle: terminateNowButtonTitle)
alert.addButton(withTitle: "Cancel")
alert.alertStyle = .warning
return alert
}
}