macOS: Set a main menu for the app
The main menu would be shown only when the manage tunnels window is visible.
This commit is contained in:
parent
0c7a9b7644
commit
dcf94293fd
|
@ -53,6 +53,7 @@
|
|||
6F1075642258AE9800D78929 /* DeleteTunnelsConfirmationAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F1075632258AE9800D78929 /* DeleteTunnelsConfirmationAlert.swift */; };
|
||||
6F19D30422402B8700A126F2 /* ConfirmationAlertPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F19D30322402B8700A126F2 /* ConfirmationAlertPresenter.swift */; };
|
||||
6F2449E8226587B90047B9E9 /* MacAppStoreUpdateDetector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F2449E7226587B80047B9E9 /* MacAppStoreUpdateDetector.swift */; };
|
||||
6F3E02E9228000F6001FE7E3 /* MainMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F3E02E8228000F6001FE7E3 /* MainMenu.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 */; };
|
||||
6F4DD16E21DBEA0700690EAE /* ManageTunnelsRootViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F4DD16D21DBEA0700690EAE /* ManageTunnelsRootViewController.swift */; };
|
||||
|
@ -300,6 +301,7 @@
|
|||
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>"; };
|
||||
6F2449E7226587B80047B9E9 /* MacAppStoreUpdateDetector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MacAppStoreUpdateDetector.swift; sourceTree = "<group>"; };
|
||||
6F3E02E8228000F6001FE7E3 /* MainMenu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainMenu.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>"; };
|
||||
6F4DD16D21DBEA0700690EAE /* ManageTunnelsRootViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManageTunnelsRootViewController.swift; sourceTree = "<group>"; };
|
||||
|
@ -631,6 +633,7 @@
|
|||
6FB1BD5F21D2607A00A991BF /* AppDelegate.swift */,
|
||||
6F89E17921EDEB0E00C97BB9 /* StatusItemController.swift */,
|
||||
6FBA101621D655340051C35F /* StatusMenu.swift */,
|
||||
6F3E02E8228000F6001FE7E3 /* MainMenu.swift */,
|
||||
6F89E17B21F090CC00C97BB9 /* TunnelsTracker.swift */,
|
||||
6FBA104121D6BC210051C35F /* ErrorPresenter.swift */,
|
||||
6FCD99AE21E0EA1700BA4C82 /* ImportPanelPresenter.swift */,
|
||||
|
@ -1289,6 +1292,7 @@
|
|||
6F4DD16B21DA558800690EAE /* TunnelListRow.swift in Sources */,
|
||||
6FDB6D15224CB2CE00EE4BC3 /* LogViewCell.swift in Sources */,
|
||||
6FE3661D21F64F6B00F78C7D /* ConfTextColorTheme.swift in Sources */,
|
||||
6F3E02E9228000F6001FE7E3 /* MainMenu.swift in Sources */,
|
||||
5F52D0BF21E3788900283CEA /* NSColor+Hex.swift in Sources */,
|
||||
6FB1BDBE21D50F0200A991BF /* Logger.swift in Sources */,
|
||||
6FB1BDBF21D50F0200A991BF /* TunnelConfiguration+WgQuickConfig.swift in Sources */,
|
||||
|
|
|
@ -291,7 +291,7 @@
|
|||
"alertSystemErrorMessageTunnelConfigurationReadWriteFailed" = "Reading or writing the configuration failed.";
|
||||
"alertSystemErrorMessageTunnelConfigurationUnknown" = "Unknown system error.";
|
||||
|
||||
// Mac status bar menu / pulldown menu
|
||||
// Mac status bar menu / pulldown menu / main menu
|
||||
|
||||
"macMenuNetworks (%@)" = "Networks: %@";
|
||||
"macMenuNetworksNone" = "Networks: None";
|
||||
|
@ -305,6 +305,31 @@
|
|||
"macMenuAbout" = "About WireGuard";
|
||||
"macMenuQuit" = "Quit";
|
||||
|
||||
"macMenuHideApp" = "Hide WireGuard";
|
||||
"macMenuHideOtherApps" = "Hide Others";
|
||||
"macMenuShowAllApps" = "Show All";
|
||||
|
||||
"macMenuFile" = "File";
|
||||
"macMenuCloseWindow" = "Close Window";
|
||||
|
||||
"macMenuEdit" = "Edit";
|
||||
"macMenuUndo" = "Undo";
|
||||
"macMenuRedo" = "Redo";
|
||||
"macMenuCut" = "Cut";
|
||||
"macMenuCopy" = "Copy";
|
||||
"macMenuPaste" = "Paste";
|
||||
"macMenuSelectAll" = "Select All";
|
||||
|
||||
"macMenuTunnel" = "Tunnel";
|
||||
"macMenuToggleStatus" = "Toggle Status";
|
||||
"macMenuEditTunnel" = "Edit…";
|
||||
"macMenuDeleteSelected" = "Delete Selected";
|
||||
|
||||
"macMenuWindow" = "Window";
|
||||
"macMenuMinimize" = "Minimize";
|
||||
"macMenuZoom" = "Zoom";
|
||||
"macMenuFullScreen" = "Full Screen";
|
||||
|
||||
// Mac manage tunnels window
|
||||
|
||||
"macWindowTitleManageTunnels" = "Manage WireGuard Tunnels";
|
||||
|
|
|
@ -17,6 +17,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
|||
func applicationDidFinishLaunching(_ aNotification: Notification) {
|
||||
Logger.configureGlobal(tagged: "APP", withFilePath: FileManager.logFileURL?.path)
|
||||
registerLoginItem(shouldLaunchAtLogin: true)
|
||||
NSApp.mainMenu = MainMenu()
|
||||
|
||||
TunnelsManager.create { [weak self] result in
|
||||
guard let self = self else { return }
|
||||
|
@ -104,6 +105,24 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
|||
}
|
||||
}
|
||||
|
||||
extension AppDelegate {
|
||||
@objc func aboutClicked() {
|
||||
var appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "Unknown"
|
||||
if let appBuild = Bundle.main.infoDictionary?["CFBundleVersion"] as? String {
|
||||
appVersion += " (\(appBuild))"
|
||||
}
|
||||
let appVersionString = [
|
||||
tr(format: "macAppVersion (%@)", appVersion),
|
||||
tr(format: "macGoBackendVersion (%@)", WIREGUARD_GO_VERSION)
|
||||
].joined(separator: "\n")
|
||||
NSApp.activate(ignoringOtherApps: true)
|
||||
NSApp.orderFrontStandardAboutPanel(options: [
|
||||
.applicationVersion: appVersionString,
|
||||
.version: ""
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
extension AppDelegate: StatusMenuWindowDelegate {
|
||||
func manageTunnelsWindow() -> NSWindow {
|
||||
if manageTunnelsWindowObject == nil {
|
||||
|
|
|
@ -0,0 +1,129 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2018 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import Cocoa
|
||||
|
||||
class MainMenu: NSMenu {
|
||||
init() {
|
||||
super.init(title: "")
|
||||
addSubmenu(createApplicationMenu())
|
||||
addSubmenu(createFileMenu())
|
||||
addSubmenu(createEditMenu())
|
||||
addSubmenu(createTunnelMenu())
|
||||
addSubmenu(createWindowMenu())
|
||||
}
|
||||
|
||||
required init(coder decoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
private func addSubmenu(_ menu: NSMenu) {
|
||||
let menuItem = self.addItem(withTitle: "", action: nil, keyEquivalent: "")
|
||||
self.setSubmenu(menu, for: menuItem)
|
||||
}
|
||||
|
||||
private func createApplicationMenu() -> NSMenu {
|
||||
let menu = NSMenu()
|
||||
|
||||
let aboutMenuItem = menu.addItem(withTitle: tr("macMenuAbout"),
|
||||
action: #selector(AppDelegate.aboutClicked), keyEquivalent: "")
|
||||
aboutMenuItem.target = NSApp.delegate
|
||||
|
||||
menu.addItem(NSMenuItem.separator())
|
||||
|
||||
menu.addItem(withTitle: tr("macMenuViewLog"),
|
||||
action: #selector(TunnelsListTableViewController.handleViewLogAction), keyEquivalent: "")
|
||||
|
||||
menu.addItem(NSMenuItem.separator())
|
||||
|
||||
let hideMenuItem = menu.addItem(withTitle: tr("macMenuHideApp"),
|
||||
action: #selector(NSApplication.hide), keyEquivalent: "h")
|
||||
hideMenuItem.target = NSApp
|
||||
let hideOthersMenuItem = menu.addItem(withTitle: tr("macMenuHideOtherApps"),
|
||||
action: #selector(NSApplication.hideOtherApplications), keyEquivalent: "h")
|
||||
hideOthersMenuItem.keyEquivalentModifierMask = [.command, .option]
|
||||
hideOthersMenuItem.target = NSApp
|
||||
let showAllMenuItem = menu.addItem(withTitle: tr("macMenuShowAllApps"),
|
||||
action: #selector(NSApplication.unhideAllApplications), keyEquivalent: "")
|
||||
showAllMenuItem.target = NSApp
|
||||
|
||||
menu.addItem(NSMenuItem.separator())
|
||||
|
||||
let quitMenuItem = menu.addItem(withTitle: tr("macMenuQuit"),
|
||||
action: #selector(AppDelegate.quit), keyEquivalent: "q")
|
||||
quitMenuItem.target = NSApp.delegate
|
||||
|
||||
return menu
|
||||
}
|
||||
|
||||
private func createFileMenu() -> NSMenu {
|
||||
let menu = NSMenu(title: tr("macMenuFile"))
|
||||
|
||||
menu.addItem(withTitle: tr("macMenuAddEmptyTunnel"),
|
||||
action: #selector(TunnelsListTableViewController.handleAddEmptyTunnelAction), keyEquivalent: "n")
|
||||
menu.addItem(withTitle: tr("macMenuImportTunnels"),
|
||||
action: #selector(TunnelsListTableViewController.handleImportTunnelAction), keyEquivalent: "o")
|
||||
|
||||
menu.addItem(NSMenuItem.separator())
|
||||
|
||||
menu.addItem(withTitle: tr("macMenuExportTunnels"),
|
||||
action: #selector(TunnelsListTableViewController.handleExportTunnelsAction), keyEquivalent: "")
|
||||
|
||||
menu.addItem(NSMenuItem.separator())
|
||||
|
||||
menu.addItem(withTitle: tr("macMenuCloseWindow"), action: #selector(NSWindow.performClose(_:)), keyEquivalent:"w")
|
||||
|
||||
return menu
|
||||
}
|
||||
|
||||
private func createEditMenu() -> NSMenu {
|
||||
let menu = NSMenu(title: tr("macMenuEdit"))
|
||||
|
||||
menu.addItem(withTitle: tr("macMenuUndo"), action: #selector(UndoActionRespondable.undo(_:)), keyEquivalent:"z")
|
||||
menu.addItem(withTitle: tr("macMenuRedo"), action: #selector(UndoActionRespondable.redo(_:)), keyEquivalent:"Z")
|
||||
|
||||
menu.addItem(NSMenuItem.separator())
|
||||
|
||||
menu.addItem(withTitle: tr("macMenuCut"), action: #selector(NSText.cut(_:)), keyEquivalent:"x")
|
||||
menu.addItem(withTitle: tr("macMenuCopy"), action: #selector(NSText.copy(_:)), keyEquivalent:"c")
|
||||
menu.addItem(withTitle: tr("macMenuPaste"), action: #selector(NSText.paste(_:)), keyEquivalent:"v")
|
||||
|
||||
menu.addItem(NSMenuItem.separator())
|
||||
|
||||
menu.addItem(withTitle: tr("macMenuSelectAll"), action: #selector(NSText.selectAll(_:)), keyEquivalent:"a")
|
||||
|
||||
return menu
|
||||
}
|
||||
|
||||
private func createTunnelMenu() -> NSMenu {
|
||||
let menu = NSMenu(title: tr("macMenuTunnel"))
|
||||
|
||||
menu.addItem(withTitle: tr("macMenuToggleStatus"), action: #selector(TunnelDetailTableViewController.handleToggleActiveStatusAction), keyEquivalent:"t")
|
||||
|
||||
menu.addItem(NSMenuItem.separator())
|
||||
|
||||
menu.addItem(withTitle: tr("macMenuEditTunnel"), action: #selector(TunnelDetailTableViewController.handleEditTunnelAction), keyEquivalent:"e")
|
||||
menu.addItem(withTitle: tr("macMenuDeleteSelected"), action: #selector(TunnelsListTableViewController.handleRemoveTunnelAction), keyEquivalent: "")
|
||||
|
||||
return menu
|
||||
}
|
||||
|
||||
private func createWindowMenu() -> NSMenu {
|
||||
let menu = NSMenu(title: tr("macMenuWindow"))
|
||||
|
||||
menu.addItem(withTitle: tr("macMenuMinimize"), action: #selector(NSWindow.performMiniaturize(_:)), keyEquivalent:"m")
|
||||
menu.addItem(withTitle: tr("macMenuZoom"), action: #selector(NSWindow.performZoom(_:)), keyEquivalent:"")
|
||||
|
||||
menu.addItem(NSMenuItem.separator())
|
||||
|
||||
let fullScreenMenuItem = menu.addItem(withTitle: tr("macMenuFullScreen"), action: #selector(NSWindow.toggleFullScreen(_:)), keyEquivalent:"f")
|
||||
fullScreenMenuItem.keyEquivalentModifierMask = [.command, .control]
|
||||
|
||||
return menu
|
||||
}
|
||||
}
|
||||
|
||||
@objc protocol UndoActionRespondable {
|
||||
func undo(_ sender: AnyObject)
|
||||
func redo(_ sender: AnyObject)
|
||||
}
|
|
@ -127,8 +127,8 @@ class StatusMenu: NSMenu {
|
|||
}
|
||||
|
||||
func addApplicationItems() {
|
||||
let aboutItem = NSMenuItem(title: tr("macMenuAbout"), action: #selector(aboutClicked), keyEquivalent: "")
|
||||
aboutItem.target = self
|
||||
let aboutItem = NSMenuItem(title: tr("macMenuAbout"), action: #selector(AppDelegate.aboutClicked), keyEquivalent: "")
|
||||
aboutItem.target = NSApp.delegate
|
||||
addItem(aboutItem)
|
||||
let quitItem = NSMenuItem(title: tr("macMenuQuit"), action: #selector(AppDelegate.quit), keyEquivalent: "")
|
||||
quitItem.target = NSApp.delegate
|
||||
|
@ -164,22 +164,6 @@ class StatusMenu: NSMenu {
|
|||
manageTunnelsWindow.makeKeyAndOrderFront(self)
|
||||
ImportPanelPresenter.presentImportPanel(tunnelsManager: tunnelsManager, sourceVC: manageTunnelsWindow.contentViewController)
|
||||
}
|
||||
|
||||
@objc func aboutClicked() {
|
||||
var appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "Unknown"
|
||||
if let appBuild = Bundle.main.infoDictionary?["CFBundleVersion"] as? String {
|
||||
appVersion += " (\(appBuild))"
|
||||
}
|
||||
let appVersionString = [
|
||||
tr(format: "macAppVersion (%@)", appVersion),
|
||||
tr(format: "macGoBackendVersion (%@)", WIREGUARD_GO_VERSION)
|
||||
].joined(separator: "\n")
|
||||
NSApp.activate(ignoringOtherApps: true)
|
||||
NSApp.orderFrontStandardAboutPanel(options: [
|
||||
.applicationVersion: appVersionString,
|
||||
.version: ""
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
extension StatusMenu {
|
||||
|
|
Loading…
Reference in New Issue