macOS: Tunnels list: Suppress alert buttons when removing tunnels is in progress
Also refactor the deletion alert into a separate helper class
This commit is contained in:
parent
8bbf4e084a
commit
f361b8a674
|
@ -50,6 +50,7 @@
|
||||||
6BD5C97E220D1AE200784E08 /* key.c in Sources */ = {isa = PBXBuildFile; fileRef = 6BD5C979220D1AE100784E08 /* key.c */; };
|
6BD5C97E220D1AE200784E08 /* key.c in Sources */ = {isa = PBXBuildFile; fileRef = 6BD5C979220D1AE100784E08 /* key.c */; };
|
||||||
6F0F44C9222D55BB00B0FF04 /* TextCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F0F44C8222D55BB00B0FF04 /* TextCell.swift */; };
|
6F0F44C9222D55BB00B0FF04 /* TextCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F0F44C8222D55BB00B0FF04 /* TextCell.swift */; };
|
||||||
6F0F44CB222D55FD00B0FF04 /* EditableTextCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F0F44CA222D55FD00B0FF04 /* EditableTextCell.swift */; };
|
6F0F44CB222D55FD00B0FF04 /* EditableTextCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F0F44CA222D55FD00B0FF04 /* EditableTextCell.swift */; };
|
||||||
|
6F1075642258AE9800D78929 /* DeleteTunnelsConfirmationAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F1075632258AE9800D78929 /* DeleteTunnelsConfirmationAlert.swift */; };
|
||||||
6F19D30422402B8700A126F2 /* ConfirmationAlertPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F19D30322402B8700A126F2 /* ConfirmationAlertPresenter.swift */; };
|
6F19D30422402B8700A126F2 /* ConfirmationAlertPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F19D30322402B8700A126F2 /* ConfirmationAlertPresenter.swift */; };
|
||||||
6F4DD16B21DA558800690EAE /* TunnelListRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F4DD16A21DA558800690EAE /* TunnelListRow.swift */; };
|
6F4DD16B21DA558800690EAE /* TunnelListRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F4DD16A21DA558800690EAE /* TunnelListRow.swift */; };
|
||||||
6F4DD16C21DA558F00690EAE /* NSTableView+Reuse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F4DD16721DA552B00690EAE /* NSTableView+Reuse.swift */; };
|
6F4DD16C21DA558F00690EAE /* NSTableView+Reuse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F4DD16721DA552B00690EAE /* NSTableView+Reuse.swift */; };
|
||||||
|
@ -295,6 +296,7 @@
|
||||||
6BD5C97A220D1AE200784E08 /* key.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = key.h; sourceTree = "<group>"; };
|
6BD5C97A220D1AE200784E08 /* key.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = key.h; sourceTree = "<group>"; };
|
||||||
6F0F44C8222D55BB00B0FF04 /* TextCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextCell.swift; sourceTree = "<group>"; };
|
6F0F44C8222D55BB00B0FF04 /* TextCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextCell.swift; sourceTree = "<group>"; };
|
||||||
6F0F44CA222D55FD00B0FF04 /* EditableTextCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditableTextCell.swift; sourceTree = "<group>"; };
|
6F0F44CA222D55FD00B0FF04 /* EditableTextCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditableTextCell.swift; sourceTree = "<group>"; };
|
||||||
|
6F1075632258AE9800D78929 /* DeleteTunnelsConfirmationAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeleteTunnelsConfirmationAlert.swift; sourceTree = "<group>"; };
|
||||||
6F19D30322402B8700A126F2 /* ConfirmationAlertPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfirmationAlertPresenter.swift; sourceTree = "<group>"; };
|
6F19D30322402B8700A126F2 /* ConfirmationAlertPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfirmationAlertPresenter.swift; sourceTree = "<group>"; };
|
||||||
6F4DD16721DA552B00690EAE /* NSTableView+Reuse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSTableView+Reuse.swift"; sourceTree = "<group>"; };
|
6F4DD16721DA552B00690EAE /* NSTableView+Reuse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSTableView+Reuse.swift"; sourceTree = "<group>"; };
|
||||||
6F4DD16A21DA558800690EAE /* TunnelListRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelListRow.swift; sourceTree = "<group>"; };
|
6F4DD16A21DA558800690EAE /* TunnelListRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelListRow.swift; sourceTree = "<group>"; };
|
||||||
|
@ -483,6 +485,7 @@
|
||||||
6F5EA59A223E58A8002B380A /* ButtonRow.swift */,
|
6F5EA59A223E58A8002B380A /* ButtonRow.swift */,
|
||||||
6FB17945222FD5960018AE71 /* OnDemandWiFiControls.swift */,
|
6FB17945222FD5960018AE71 /* OnDemandWiFiControls.swift */,
|
||||||
6FDB6D14224CB2CE00EE4BC3 /* LogViewCell.swift */,
|
6FDB6D14224CB2CE00EE4BC3 /* LogViewCell.swift */,
|
||||||
|
6F1075632258AE9800D78929 /* DeleteTunnelsConfirmationAlert.swift */,
|
||||||
);
|
);
|
||||||
path = View;
|
path = View;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -1287,6 +1290,7 @@
|
||||||
6FADE96C2254B8C300B838A4 /* UnusableTunnelDetailViewController.swift in Sources */,
|
6FADE96C2254B8C300B838A4 /* UnusableTunnelDetailViewController.swift in Sources */,
|
||||||
6FFACD2021E4D8D500E9A2A5 /* ParseError+WireGuardAppError.swift in Sources */,
|
6FFACD2021E4D8D500E9A2A5 /* ParseError+WireGuardAppError.swift in Sources */,
|
||||||
6FB1BDC021D50F0200A991BF /* NETunnelProviderProtocol+Extension.swift in Sources */,
|
6FB1BDC021D50F0200A991BF /* NETunnelProviderProtocol+Extension.swift in Sources */,
|
||||||
|
6F1075642258AE9800D78929 /* DeleteTunnelsConfirmationAlert.swift in Sources */,
|
||||||
6FBA101821D656000051C35F /* StatusMenu.swift in Sources */,
|
6FBA101821D656000051C35F /* StatusMenu.swift in Sources */,
|
||||||
6F613D9B21DE33B8004B217A /* KeyValueRow.swift in Sources */,
|
6F613D9B21DE33B8004B217A /* KeyValueRow.swift in Sources */,
|
||||||
6FB1BDC121D50F0200A991BF /* String+ArrayConversion.swift in Sources */,
|
6FB1BDC121D50F0200A991BF /* String+ArrayConversion.swift in Sources */,
|
||||||
|
|
|
@ -314,6 +314,7 @@
|
||||||
"macDeleteTunnelConfirmationAlertInfo" = "You cannot undo this action.";
|
"macDeleteTunnelConfirmationAlertInfo" = "You cannot undo this action.";
|
||||||
"macDeleteTunnelConfirmationAlertButtonTitleDelete" = "Delete";
|
"macDeleteTunnelConfirmationAlertButtonTitleDelete" = "Delete";
|
||||||
"macDeleteTunnelConfirmationAlertButtonTitleCancel" = "Cancel";
|
"macDeleteTunnelConfirmationAlertButtonTitleCancel" = "Cancel";
|
||||||
|
"macDeleteTunnelConfirmationAlertButtonTitleDeleting" = "Deleting…";
|
||||||
|
|
||||||
"macButtonImportTunnels" = "Import tunnel(s) from file";
|
"macButtonImportTunnels" = "Import tunnel(s) from file";
|
||||||
"macSheetButtonImport" = "Import";
|
"macSheetButtonImport" = "Import";
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
import Cocoa
|
||||||
|
|
||||||
|
class DeleteTunnelsConfirmationAlert: NSAlert {
|
||||||
|
var alertDeleteButton: NSButton?
|
||||||
|
var alertCancelButton: NSButton?
|
||||||
|
|
||||||
|
var onDeleteClicked: ((_ completionHandler: @escaping () -> Void) -> Void)?
|
||||||
|
|
||||||
|
override init() {
|
||||||
|
super.init()
|
||||||
|
let alertDeleteButton = addButton(withTitle: tr("macDeleteTunnelConfirmationAlertButtonTitleDelete"))
|
||||||
|
alertDeleteButton.target = self
|
||||||
|
alertDeleteButton.action = #selector(removeTunnelAlertDeleteClicked)
|
||||||
|
self.alertDeleteButton = alertDeleteButton
|
||||||
|
self.alertCancelButton = addButton(withTitle: tr("macDeleteTunnelConfirmationAlertButtonTitleCancel"))
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func removeTunnelAlertDeleteClicked() {
|
||||||
|
alertDeleteButton?.title = tr("macDeleteTunnelConfirmationAlertButtonTitleDeleting")
|
||||||
|
alertDeleteButton?.isEnabled = false
|
||||||
|
alertCancelButton?.isEnabled = false
|
||||||
|
if let onDeleteClicked = onDeleteClicked {
|
||||||
|
onDeleteClicked { [weak self] in
|
||||||
|
guard let self = self else { return }
|
||||||
|
self.window.sheetParent?.endSheet(self.window)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func beginSheetModal(for sheetWindow: NSWindow) {
|
||||||
|
beginSheetModal(for: sheetWindow) { _ in }
|
||||||
|
}
|
||||||
|
}
|
|
@ -163,9 +163,15 @@ class TunnelsListTableViewController: NSViewController {
|
||||||
|
|
||||||
@objc func handleRemoveTunnelAction() {
|
@objc func handleRemoveTunnelAction() {
|
||||||
guard let window = view.window else { return }
|
guard let window = view.window else { return }
|
||||||
|
|
||||||
let selectedTunnelIndices = tableView.selectedRowIndexes.sorted().filter { $0 >= 0 && $0 < tunnelsManager.numberOfTunnels() }
|
let selectedTunnelIndices = tableView.selectedRowIndexes.sorted().filter { $0 >= 0 && $0 < tunnelsManager.numberOfTunnels() }
|
||||||
guard !selectedTunnelIndices.isEmpty else { return }
|
guard !selectedTunnelIndices.isEmpty else { return }
|
||||||
let alert = NSAlert()
|
var nextSelection = selectedTunnelIndices.last! + 1
|
||||||
|
if nextSelection >= tunnelsManager.numberOfTunnels() {
|
||||||
|
nextSelection = max(selectedTunnelIndices.first! - 1, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
let alert = DeleteTunnelsConfirmationAlert()
|
||||||
if selectedTunnelIndices.count == 1 {
|
if selectedTunnelIndices.count == 1 {
|
||||||
let firstSelectedTunnel = tunnelsManager.tunnel(at: selectedTunnelIndices.first!)
|
let firstSelectedTunnel = tunnelsManager.tunnel(at: selectedTunnelIndices.first!)
|
||||||
alert.messageText = tr(format: "macDeleteTunnelConfirmationAlertMessage (%@)", firstSelectedTunnel.name)
|
alert.messageText = tr(format: "macDeleteTunnelConfirmationAlertMessage (%@)", firstSelectedTunnel.name)
|
||||||
|
@ -173,41 +179,20 @@ class TunnelsListTableViewController: NSViewController {
|
||||||
alert.messageText = tr(format: "macDeleteMultipleTunnelsConfirmationAlertMessage (%d)", selectedTunnelIndices.count)
|
alert.messageText = tr(format: "macDeleteMultipleTunnelsConfirmationAlertMessage (%d)", selectedTunnelIndices.count)
|
||||||
}
|
}
|
||||||
alert.informativeText = tr("macDeleteTunnelConfirmationAlertInfo")
|
alert.informativeText = tr("macDeleteTunnelConfirmationAlertInfo")
|
||||||
let alertDeleteButton = alert.addButton(withTitle: tr("macDeleteTunnelConfirmationAlertButtonTitleDelete"))
|
alert.onDeleteClicked = { [weak self] completion in
|
||||||
alertDeleteButton.target = self
|
|
||||||
alertDeleteButton.action = #selector(removeTunnelAlertDeleteClicked)
|
|
||||||
let alertCancelButton = alert.addButton(withTitle: tr("macDeleteTunnelConfirmationAlertButtonTitleCancel"))
|
|
||||||
alertCancelButton.target = self
|
|
||||||
alertCancelButton.action = #selector(removeTunnelAlertCancelClicked)
|
|
||||||
alert.beginSheetModal(for: window) { _ in }
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc func removeTunnelAlertDeleteClicked(_ sender: AnyObject) {
|
|
||||||
guard let alertWindow = (sender as? NSView)?.window, alertWindow.isSheet else { return }
|
|
||||||
let selectedTunnelIndices = tableView.selectedRowIndexes.sorted().filter { $0 >= 0 && $0 < tunnelsManager.numberOfTunnels() }
|
|
||||||
precondition(!selectedTunnelIndices.isEmpty)
|
|
||||||
var nextSelection = selectedTunnelIndices.last! + 1
|
|
||||||
if nextSelection >= tunnelsManager.numberOfTunnels() {
|
|
||||||
nextSelection = max(selectedTunnelIndices.first! - 1, 0)
|
|
||||||
}
|
|
||||||
let selectedTunnels = selectedTunnelIndices.map { tunnelsManager.tunnel(at: $0) }
|
|
||||||
alertWindow.ignoresMouseEvents = true
|
|
||||||
self.selectTunnel(at: nextSelection)
|
|
||||||
isRemovingTunnels = true
|
|
||||||
tunnelsManager.removeMultiple(tunnels: selectedTunnels) { [weak self] error in
|
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
self.view.window?.endSheet(alertWindow)
|
self.selectTunnel(at: nextSelection)
|
||||||
self.isRemovingTunnels = false
|
let selectedTunnels = selectedTunnelIndices.map { self.tunnelsManager.tunnel(at: $0) }
|
||||||
if let error = error {
|
self.tunnelsManager.removeMultiple(tunnels: selectedTunnels) { [weak self] error in
|
||||||
ErrorPresenter.showErrorAlert(error: error, from: self)
|
guard let self = self else { return }
|
||||||
return
|
defer { completion() }
|
||||||
}
|
if let error = error {
|
||||||
|
ErrorPresenter.showErrorAlert(error: error, from: self)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
alert.beginSheetModal(for: window)
|
||||||
|
|
||||||
@objc func removeTunnelAlertCancelClicked(_ sender: AnyObject) {
|
|
||||||
guard let alertWindow = (sender as? NSView)?.window, alertWindow.isSheet else { return }
|
|
||||||
view.window?.endSheet(alertWindow)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func handleViewLogAction() {
|
@objc func handleViewLogAction() {
|
||||||
|
|
Loading…
Reference in New Issue