From e29cf19fddc6878f7e24c442f83d6ff0d23fa6b8 Mon Sep 17 00:00:00 2001 From: Roopesh Chander Date: Wed, 16 Jan 2019 01:00:42 +0530 Subject: macOS: Different status bar icon looks for different states - Looks dimmed when no tunnel is active - Looks normal when a tunnel is active - Animates when a tunnel is activating Signed-off-by: Roopesh Chander --- WireGuard/WireGuard.xcodeproj/project.pbxproj | 4 ++ WireGuard/WireGuard/Tunnel/TunnelsManager.swift | 4 ++ WireGuard/WireGuard/UI/macOS/AppDelegate.swift | 23 ++++--- .../StatusBarIcon.imageset/Contents.json | 26 ++++++++ .../StatusBarIcon.imageset/StatusBarIcon@1x.png | Bin 0 -> 978 bytes .../StatusBarIcon.imageset/StatusBarIcon@2x.png | Bin 0 -> 1722 bytes .../StatusBarIcon.imageset/StatusBarIcon@3x.png | Bin 0 -> 1975 bytes .../StatusBarIconDimmed.imageset/Contents.json | 26 ++++++++ .../StatusBarIconDimmed@1x.png | Bin 0 -> 881 bytes .../StatusBarIconDimmed@2x.png | Bin 0 -> 1390 bytes .../StatusBarIconDimmed@3x.png | Bin 0 -> 1581 bytes .../StatusBarIconDot1.imageset/Contents.json | 26 ++++++++ .../StatusBarIconDot1@1x.png | Bin 0 -> 953 bytes .../StatusBarIconDot1@2x.png | Bin 0 -> 1570 bytes .../StatusBarIconDot1@3x.png | Bin 0 -> 1744 bytes .../StatusBarIconDot2.imageset/Contents.json | 26 ++++++++ .../StatusBarIconDot2@1x.png | Bin 0 -> 942 bytes .../StatusBarIconDot2@2x.png | Bin 0 -> 1502 bytes .../StatusBarIconDot2@3x.png | Bin 0 -> 1676 bytes .../StatusBarIconDot3.imageset/Contents.json | 26 ++++++++ .../StatusBarIconDot3@1x.png | Bin 0 -> 958 bytes .../StatusBarIconDot3@2x.png | Bin 0 -> 1521 bytes .../StatusBarIconDot3@3x.png | Bin 0 -> 1677 bytes .../Contents.json | 23 ------- .../WireGuardMacStatusBarIcon@1x.png | Bin 990 -> 0 bytes .../WireGuardMacStatusBarIcon@2x.png | Bin 1714 -> 0 bytes .../WireGuardMacStatusBarIcon@3x.png | Bin 1956 -> 0 bytes .../WireGuard/UI/macOS/StatusItemController.swift | 66 +++++++++++++++++++++ WireGuard/WireGuard/UI/macOS/StatusMenu.swift | 15 ++++- 29 files changed, 229 insertions(+), 36 deletions(-) create mode 100644 WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIcon.imageset/Contents.json create mode 100644 WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIcon.imageset/StatusBarIcon@1x.png create mode 100644 WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIcon.imageset/StatusBarIcon@2x.png create mode 100644 WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIcon.imageset/StatusBarIcon@3x.png create mode 100644 WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDimmed.imageset/Contents.json create mode 100644 WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDimmed.imageset/StatusBarIconDimmed@1x.png create mode 100644 WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDimmed.imageset/StatusBarIconDimmed@2x.png create mode 100644 WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDimmed.imageset/StatusBarIconDimmed@3x.png create mode 100644 WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot1.imageset/Contents.json create mode 100644 WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot1.imageset/StatusBarIconDot1@1x.png create mode 100644 WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot1.imageset/StatusBarIconDot1@2x.png create mode 100644 WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot1.imageset/StatusBarIconDot1@3x.png create mode 100644 WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot2.imageset/Contents.json create mode 100644 WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot2.imageset/StatusBarIconDot2@1x.png create mode 100644 WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot2.imageset/StatusBarIconDot2@2x.png create mode 100644 WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot2.imageset/StatusBarIconDot2@3x.png create mode 100644 WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot3.imageset/Contents.json create mode 100644 WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot3.imageset/StatusBarIconDot3@1x.png create mode 100644 WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot3.imageset/StatusBarIconDot3@2x.png create mode 100644 WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot3.imageset/StatusBarIconDot3@3x.png delete mode 100644 WireGuard/WireGuard/UI/macOS/Assets.xcassets/WireGuardMacStatusBarIcon.imageset/Contents.json delete mode 100644 WireGuard/WireGuard/UI/macOS/Assets.xcassets/WireGuardMacStatusBarIcon.imageset/WireGuardMacStatusBarIcon@1x.png delete mode 100644 WireGuard/WireGuard/UI/macOS/Assets.xcassets/WireGuardMacStatusBarIcon.imageset/WireGuardMacStatusBarIcon@2x.png delete mode 100644 WireGuard/WireGuard/UI/macOS/Assets.xcassets/WireGuardMacStatusBarIcon.imageset/WireGuardMacStatusBarIcon@3x.png create mode 100644 WireGuard/WireGuard/UI/macOS/StatusItemController.swift diff --git a/WireGuard/WireGuard.xcodeproj/project.pbxproj b/WireGuard/WireGuard.xcodeproj/project.pbxproj index a5119b6..b6b1c32 100644 --- a/WireGuard/WireGuard.xcodeproj/project.pbxproj +++ b/WireGuard/WireGuard.xcodeproj/project.pbxproj @@ -54,6 +54,7 @@ 6F7774EF21722D97006A79B3 /* TunnelsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F7774EE21722D97006A79B3 /* TunnelsManager.swift */; }; 6F7774F321774263006A79B3 /* TunnelEditTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F7774F221774263006A79B3 /* TunnelEditTableViewController.swift */; }; 6F7F7E5F21C7D74B00527607 /* TunnelErrors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F7F7E5E21C7D74B00527607 /* TunnelErrors.swift */; }; + 6F89E17A21EDEB0E00C97BB9 /* StatusItemController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F89E17921EDEB0E00C97BB9 /* StatusItemController.swift */; }; 6F919EC3218A2AE90023B400 /* ErrorPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F919EC2218A2AE90023B400 /* ErrorPresenter.swift */; }; 6F919ED9218C65C50023B400 /* wireguard_doc_logo_22x29.png in Resources */ = {isa = PBXBuildFile; fileRef = 6F919ED5218C65C50023B400 /* wireguard_doc_logo_22x29.png */; }; 6F919EDA218C65C50023B400 /* wireguard_doc_logo_44x58.png in Resources */ = {isa = PBXBuildFile; fileRef = 6F919ED6218C65C50023B400 /* wireguard_doc_logo_44x58.png */; }; @@ -263,6 +264,7 @@ 6F7774EE21722D97006A79B3 /* TunnelsManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelsManager.swift; sourceTree = ""; }; 6F7774F221774263006A79B3 /* TunnelEditTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelEditTableViewController.swift; sourceTree = ""; }; 6F7F7E5E21C7D74B00527607 /* TunnelErrors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelErrors.swift; sourceTree = ""; }; + 6F89E17921EDEB0E00C97BB9 /* StatusItemController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusItemController.swift; sourceTree = ""; }; 6F919EC2218A2AE90023B400 /* ErrorPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorPresenter.swift; sourceTree = ""; }; 6F919ED5218C65C50023B400 /* wireguard_doc_logo_22x29.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = wireguard_doc_logo_22x29.png; sourceTree = ""; }; 6F919ED6218C65C50023B400 /* wireguard_doc_logo_44x58.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = wireguard_doc_logo_44x58.png; sourceTree = ""; }; @@ -512,6 +514,7 @@ 6FBA104421D7EA750051C35F /* ViewController */, 6FBA101321D613F30051C35F /* Application.swift */, 6FB1BD5F21D2607A00A991BF /* AppDelegate.swift */, + 6F89E17921EDEB0E00C97BB9 /* StatusItemController.swift */, 6FBA101621D655340051C35F /* StatusMenu.swift */, 6FBA104121D6BC210051C35F /* ErrorPresenter.swift */, 6FCD99AE21E0EA1700BA4C82 /* ImportPanelPresenter.swift */, @@ -1111,6 +1114,7 @@ 6FB1BDBC21D50F0200A991BF /* ringlogger.c in Sources */, 6FB1BDBD21D50F0200A991BF /* ringlogger.h in Sources */, 6FBA103F21D6B6FF0051C35F /* TunnelImporter.swift in Sources */, + 6F89E17A21EDEB0E00C97BB9 /* StatusItemController.swift in Sources */, 6F4DD16B21DA558800690EAE /* TunnelListRow.swift in Sources */, 5F52D0BF21E3788900283CEA /* NSColor+Hex.swift in Sources */, 6FB1BDBE21D50F0200A991BF /* Logger.swift in Sources */, diff --git a/WireGuard/WireGuard/Tunnel/TunnelsManager.swift b/WireGuard/WireGuard/Tunnel/TunnelsManager.swift index 4476c4a..1b3cc50 100644 --- a/WireGuard/WireGuard/Tunnel/TunnelsManager.swift +++ b/WireGuard/WireGuard/Tunnel/TunnelsManager.swift @@ -222,6 +222,10 @@ class TunnelsManager { return tunnels.first { $0.name == tunnelName } } + func waitingTunnel() -> TunnelContainer? { + return tunnels.first { $0.status == .waiting } + } + func startActivation(of tunnel: TunnelContainer) { guard tunnels.contains(tunnel) else { return } // Ensure it's not deleted guard tunnel.status == .inactive else { diff --git a/WireGuard/WireGuard/UI/macOS/AppDelegate.swift b/WireGuard/WireGuard/UI/macOS/AppDelegate.swift index a08f9dc..3f08987 100644 --- a/WireGuard/WireGuard/UI/macOS/AppDelegate.swift +++ b/WireGuard/WireGuard/UI/macOS/AppDelegate.swift @@ -6,7 +6,8 @@ import Cocoa @NSApplicationMain class AppDelegate: NSObject, NSApplicationDelegate { - var statusItem: NSStatusItem? + var statusItemController: StatusItemController? + var currentTunnelStatusObserver: AnyObject? func applicationDidFinishLaunching(_ aNotification: Notification) { Logger.configureGlobal(withFilePath: FileManager.appLogFileURL?.path) @@ -19,21 +20,19 @@ class AppDelegate: NSObject, NSApplicationDelegate { } let tunnelsManager: TunnelsManager = result.value! + let statusItemController = StatusItemController() + let statusMenu = StatusMenu(tunnelsManager: tunnelsManager) - self.statusItem = createStatusBarItem(with: statusMenu) + + statusItemController.statusItem.menu = statusMenu + statusItemController.currentTunnel = statusMenu.currentTunnel + self.currentTunnelStatusObserver = statusMenu.observe(\.currentTunnel) { statusMenu, _ in + statusItemController.currentTunnel = statusMenu.currentTunnel + } + self.statusItemController = statusItemController tunnelsManager.tunnelsListDelegate = statusMenu tunnelsManager.activationDelegate = statusMenu } } } - -func createStatusBarItem(with statusMenu: StatusMenu) -> NSStatusItem { - let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.squareLength) - if let statusBarImage = NSImage(named: "WireGuardMacStatusBarIcon") { - statusBarImage.isTemplate = true - statusItem.button?.image = statusBarImage - } - statusItem.menu = statusMenu - return statusItem -} diff --git a/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIcon.imageset/Contents.json b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIcon.imageset/Contents.json new file mode 100644 index 0000000..c878d79 --- /dev/null +++ b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIcon.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "StatusBarIcon@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "StatusBarIcon@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "StatusBarIcon@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "template-rendering-intent" : "template" + } +} \ No newline at end of file diff --git a/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIcon.imageset/StatusBarIcon@1x.png b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIcon.imageset/StatusBarIcon@1x.png new file mode 100644 index 0000000..c0a43e7 Binary files /dev/null and b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIcon.imageset/StatusBarIcon@1x.png differ diff --git a/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIcon.imageset/StatusBarIcon@2x.png b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIcon.imageset/StatusBarIcon@2x.png new file mode 100644 index 0000000..2057c31 Binary files /dev/null and b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIcon.imageset/StatusBarIcon@2x.png differ diff --git a/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIcon.imageset/StatusBarIcon@3x.png b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIcon.imageset/StatusBarIcon@3x.png new file mode 100644 index 0000000..60cc363 Binary files /dev/null and b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIcon.imageset/StatusBarIcon@3x.png differ diff --git a/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDimmed.imageset/Contents.json b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDimmed.imageset/Contents.json new file mode 100644 index 0000000..aeb8a8e --- /dev/null +++ b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDimmed.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "StatusBarIconDimmed@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "StatusBarIconDimmed@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "StatusBarIconDimmed@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "template-rendering-intent" : "template" + } +} \ No newline at end of file diff --git a/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDimmed.imageset/StatusBarIconDimmed@1x.png b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDimmed.imageset/StatusBarIconDimmed@1x.png new file mode 100644 index 0000000..fb9d8f7 Binary files /dev/null and b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDimmed.imageset/StatusBarIconDimmed@1x.png differ diff --git a/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDimmed.imageset/StatusBarIconDimmed@2x.png b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDimmed.imageset/StatusBarIconDimmed@2x.png new file mode 100644 index 0000000..2f4e613 Binary files /dev/null and b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDimmed.imageset/StatusBarIconDimmed@2x.png differ diff --git a/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDimmed.imageset/StatusBarIconDimmed@3x.png b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDimmed.imageset/StatusBarIconDimmed@3x.png new file mode 100644 index 0000000..cc5ead9 Binary files /dev/null and b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDimmed.imageset/StatusBarIconDimmed@3x.png differ diff --git a/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot1.imageset/Contents.json b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot1.imageset/Contents.json new file mode 100644 index 0000000..0024a60 --- /dev/null +++ b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot1.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "StatusBarIconDot1@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "StatusBarIconDot1@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "StatusBarIconDot1@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "template-rendering-intent" : "template" + } +} \ No newline at end of file diff --git a/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot1.imageset/StatusBarIconDot1@1x.png b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot1.imageset/StatusBarIconDot1@1x.png new file mode 100644 index 0000000..bbbe0c3 Binary files /dev/null and b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot1.imageset/StatusBarIconDot1@1x.png differ diff --git a/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot1.imageset/StatusBarIconDot1@2x.png b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot1.imageset/StatusBarIconDot1@2x.png new file mode 100644 index 0000000..01b5eb3 Binary files /dev/null and b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot1.imageset/StatusBarIconDot1@2x.png differ diff --git a/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot1.imageset/StatusBarIconDot1@3x.png b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot1.imageset/StatusBarIconDot1@3x.png new file mode 100644 index 0000000..76afa15 Binary files /dev/null and b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot1.imageset/StatusBarIconDot1@3x.png differ diff --git a/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot2.imageset/Contents.json b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot2.imageset/Contents.json new file mode 100644 index 0000000..8b61c0e --- /dev/null +++ b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot2.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "StatusBarIconDot2@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "StatusBarIconDot2@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "StatusBarIconDot2@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "template-rendering-intent" : "template" + } +} \ No newline at end of file diff --git a/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot2.imageset/StatusBarIconDot2@1x.png b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot2.imageset/StatusBarIconDot2@1x.png new file mode 100644 index 0000000..a16143f Binary files /dev/null and b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot2.imageset/StatusBarIconDot2@1x.png differ diff --git a/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot2.imageset/StatusBarIconDot2@2x.png b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot2.imageset/StatusBarIconDot2@2x.png new file mode 100644 index 0000000..ce00482 Binary files /dev/null and b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot2.imageset/StatusBarIconDot2@2x.png differ diff --git a/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot2.imageset/StatusBarIconDot2@3x.png b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot2.imageset/StatusBarIconDot2@3x.png new file mode 100644 index 0000000..82640f7 Binary files /dev/null and b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot2.imageset/StatusBarIconDot2@3x.png differ diff --git a/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot3.imageset/Contents.json b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot3.imageset/Contents.json new file mode 100644 index 0000000..96da519 --- /dev/null +++ b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot3.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "StatusBarIconDot3@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "StatusBarIconDot3@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "StatusBarIconDot3@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "template-rendering-intent" : "template" + } +} \ No newline at end of file diff --git a/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot3.imageset/StatusBarIconDot3@1x.png b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot3.imageset/StatusBarIconDot3@1x.png new file mode 100644 index 0000000..80e221b Binary files /dev/null and b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot3.imageset/StatusBarIconDot3@1x.png differ diff --git a/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot3.imageset/StatusBarIconDot3@2x.png b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot3.imageset/StatusBarIconDot3@2x.png new file mode 100644 index 0000000..663f92b Binary files /dev/null and b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot3.imageset/StatusBarIconDot3@2x.png differ diff --git a/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot3.imageset/StatusBarIconDot3@3x.png b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot3.imageset/StatusBarIconDot3@3x.png new file mode 100644 index 0000000..10e43d9 Binary files /dev/null and b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/StatusBarIconDot3.imageset/StatusBarIconDot3@3x.png differ diff --git a/WireGuard/WireGuard/UI/macOS/Assets.xcassets/WireGuardMacStatusBarIcon.imageset/Contents.json b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/WireGuardMacStatusBarIcon.imageset/Contents.json deleted file mode 100644 index 2adee86..0000000 --- a/WireGuard/WireGuard/UI/macOS/Assets.xcassets/WireGuardMacStatusBarIcon.imageset/Contents.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "WireGuardMacStatusBarIcon@1x.png", - "scale" : "1x" - }, - { - "idiom" : "universal", - "filename" : "WireGuardMacStatusBarIcon@2x.png", - "scale" : "2x" - }, - { - "idiom" : "universal", - "filename" : "WireGuardMacStatusBarIcon@3x.png", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/WireGuard/WireGuard/UI/macOS/Assets.xcassets/WireGuardMacStatusBarIcon.imageset/WireGuardMacStatusBarIcon@1x.png b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/WireGuardMacStatusBarIcon.imageset/WireGuardMacStatusBarIcon@1x.png deleted file mode 100644 index 1a7d77c..0000000 Binary files a/WireGuard/WireGuard/UI/macOS/Assets.xcassets/WireGuardMacStatusBarIcon.imageset/WireGuardMacStatusBarIcon@1x.png and /dev/null differ diff --git a/WireGuard/WireGuard/UI/macOS/Assets.xcassets/WireGuardMacStatusBarIcon.imageset/WireGuardMacStatusBarIcon@2x.png b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/WireGuardMacStatusBarIcon.imageset/WireGuardMacStatusBarIcon@2x.png deleted file mode 100644 index 66c49c1..0000000 Binary files a/WireGuard/WireGuard/UI/macOS/Assets.xcassets/WireGuardMacStatusBarIcon.imageset/WireGuardMacStatusBarIcon@2x.png and /dev/null differ diff --git a/WireGuard/WireGuard/UI/macOS/Assets.xcassets/WireGuardMacStatusBarIcon.imageset/WireGuardMacStatusBarIcon@3x.png b/WireGuard/WireGuard/UI/macOS/Assets.xcassets/WireGuardMacStatusBarIcon.imageset/WireGuardMacStatusBarIcon@3x.png deleted file mode 100644 index e1bcc35..0000000 Binary files a/WireGuard/WireGuard/UI/macOS/Assets.xcassets/WireGuardMacStatusBarIcon.imageset/WireGuardMacStatusBarIcon@3x.png and /dev/null differ diff --git a/WireGuard/WireGuard/UI/macOS/StatusItemController.swift b/WireGuard/WireGuard/UI/macOS/StatusItemController.swift new file mode 100644 index 0000000..2568c15 --- /dev/null +++ b/WireGuard/WireGuard/UI/macOS/StatusItemController.swift @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: MIT +// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. + +import Cocoa + +class StatusItemController { + var currentTunnel: TunnelContainer? { + didSet { + updateStatusItemImage() + } + } + + let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.squareLength) + private let statusBarImageWhenActive = NSImage(named: "StatusBarIcon")! + private let statusBarImageWhenInactive = NSImage(named: "StatusBarIconDimmed")! + + private let animationImages = [ + NSImage(named: "StatusBarIconDot1")!, + NSImage(named: "StatusBarIconDot2")!, + NSImage(named: "StatusBarIconDot3")! + ] + private var animationImageIndex: Int = 0 + private var animationTimer: Timer? + + init() { + updateStatusItemImage() + } + + func updateStatusItemImage() { + guard let currentTunnel = currentTunnel else { + stopActivatingAnimation() + statusItem.button?.image = statusBarImageWhenInactive + return + } + switch currentTunnel.status { + case .inactive: + stopActivatingAnimation() + statusItem.button?.image = statusBarImageWhenInactive + case .active: + stopActivatingAnimation() + statusItem.button?.image = statusBarImageWhenActive + case .activating, .waiting, .reasserting, .restarting: + startActivatingAnimation() + case .deactivating: + break + } + } + + func startActivatingAnimation() { + guard animationTimer == nil else { return } + let timer = Timer(timeInterval: 0.3, repeats: true) { [weak self] _ in + guard let self = self else { return } + self.statusItem.button?.image = self.animationImages[self.animationImageIndex] + self.animationImageIndex = (self.animationImageIndex + 1) % self.animationImages.count + } + RunLoop.main.add(timer, forMode: .default) + animationTimer = timer + } + + func stopActivatingAnimation() { + guard let timer = self.animationTimer else { return } + timer.invalidate() + animationTimer = nil + animationImageIndex = 0 + } +} diff --git a/WireGuard/WireGuard/UI/macOS/StatusMenu.swift b/WireGuard/WireGuard/UI/macOS/StatusMenu.swift index 78e71ba..a2f02d8 100644 --- a/WireGuard/WireGuard/UI/macOS/StatusMenu.swift +++ b/WireGuard/WireGuard/UI/macOS/StatusMenu.swift @@ -13,6 +13,8 @@ class StatusMenu: NSMenu { var firstTunnelMenuItemIndex = 0 var numberOfTunnelMenuItems = 0 + @objc dynamic var currentTunnel: TunnelContainer? + var manageTunnelsRootVC: ManageTunnelsRootViewController? lazy var manageTunnelsWindow: NSWindow = { manageTunnelsRootVC = ManageTunnelsRootViewController(tunnelsManager: tunnelsManager) @@ -30,7 +32,11 @@ class StatusMenu: NSMenu { addStatusMenuItems() addItem(NSMenuItem.separator()) for index in 0 ..< tunnelsManager.numberOfTunnels() { - let isUpdated = updateStatusMenuItems(with: tunnelsManager.tunnel(at: index), ignoreInactive: true) + let tunnel = tunnelsManager.tunnel(at: index) + if tunnel.status != .inactive { + currentTunnel = tunnel + } + let isUpdated = updateStatusMenuItems(with: tunnel, ignoreInactive: true) if isUpdated { break } @@ -176,6 +182,13 @@ extension StatusMenu { updateTunnelMenuItem(menuItem) let statusObservationToken = tunnel.observe(\.status) { [weak self] tunnel, _ in updateTunnelMenuItem(menuItem) + if tunnel.status == .deactivating || tunnel.status == .inactive { + if self?.currentTunnel == tunnel { + self?.currentTunnel = self?.tunnelsManager.waitingTunnel() + } + } else { + self?.currentTunnel = tunnel + } self?.updateStatusMenuItems(with: tunnel, ignoreInactive: false) } tunnelStatusObservers.insert(statusObservationToken, at: tunnelIndex) -- cgit v1.2.3-59-g8ed1b