diff options
| author | Oskar Nyberg <oskar@mullvad.net> | 2023-02-09 10:53:22 +0100 |
|---|---|---|
| committer | Oskar Nyberg <oskar@mullvad.net> | 2023-02-09 10:53:22 +0100 |
| commit | 9f9996b47029bceb9582ffdd5199a1db10287e8f (patch) | |
| tree | a867bca5026dc75a4378437c7ebd017ebb9fbf7e | |
| parent | a452a38ed484da45d483150ca35a38705b007dfc (diff) | |
| parent | 8e4170b381f275f6aae787bffc624294b34be1b6 (diff) | |
| download | mullvadvpn-9f9996b47029bceb9582ffdd5199a1db10287e8f.tar.xz mullvadvpn-9f9996b47029bceb9582ffdd5199a1db10287e8f.zip | |
Merge branch 'improve-notifications'
163 files changed, 500 insertions, 206 deletions
diff --git a/gui/assets/images/menubar-icons/darwin/lock-10_notification.png b/gui/assets/images/menubar-icons/darwin/lock-10_notification.png Binary files differnew file mode 100644 index 0000000000..1f2bcb2f95 --- /dev/null +++ b/gui/assets/images/menubar-icons/darwin/lock-10_notification.png diff --git a/gui/assets/images/menubar-icons/darwin/lock-10_notification@2x.png b/gui/assets/images/menubar-icons/darwin/lock-10_notification@2x.png Binary files differnew file mode 100644 index 0000000000..254531a6a2 --- /dev/null +++ b/gui/assets/images/menubar-icons/darwin/lock-10_notification@2x.png diff --git a/gui/assets/images/menubar-icons/darwin/lock-10_notificationTemplate.png b/gui/assets/images/menubar-icons/darwin/lock-10_notificationTemplate.png Binary files differnew file mode 100644 index 0000000000..5a44eae958 --- /dev/null +++ b/gui/assets/images/menubar-icons/darwin/lock-10_notificationTemplate.png diff --git a/gui/assets/images/menubar-icons/darwin/lock-10_notificationTemplate@2x.png b/gui/assets/images/menubar-icons/darwin/lock-10_notificationTemplate@2x.png Binary files differnew file mode 100644 index 0000000000..083c14c6e4 --- /dev/null +++ b/gui/assets/images/menubar-icons/darwin/lock-10_notificationTemplate@2x.png diff --git a/gui/assets/images/menubar-icons/darwin/lock-1_notification.png b/gui/assets/images/menubar-icons/darwin/lock-1_notification.png Binary files differnew file mode 100644 index 0000000000..7f229841e7 --- /dev/null +++ b/gui/assets/images/menubar-icons/darwin/lock-1_notification.png diff --git a/gui/assets/images/menubar-icons/darwin/lock-1_notification@2x.png b/gui/assets/images/menubar-icons/darwin/lock-1_notification@2x.png Binary files differnew file mode 100644 index 0000000000..41ad2d4d4e --- /dev/null +++ b/gui/assets/images/menubar-icons/darwin/lock-1_notification@2x.png diff --git a/gui/assets/images/menubar-icons/darwin/lock-1_notificationTemplate.png b/gui/assets/images/menubar-icons/darwin/lock-1_notificationTemplate.png Binary files differnew file mode 100644 index 0000000000..b3afb3e70b --- /dev/null +++ b/gui/assets/images/menubar-icons/darwin/lock-1_notificationTemplate.png diff --git a/gui/assets/images/menubar-icons/darwin/lock-1_notificationTemplate@2x.png b/gui/assets/images/menubar-icons/darwin/lock-1_notificationTemplate@2x.png Binary files differnew file mode 100644 index 0000000000..62e5b60ebc --- /dev/null +++ b/gui/assets/images/menubar-icons/darwin/lock-1_notificationTemplate@2x.png diff --git a/gui/assets/images/menubar-icons/darwin/lock-2_notification.png b/gui/assets/images/menubar-icons/darwin/lock-2_notification.png Binary files differnew file mode 100644 index 0000000000..14ce173d28 --- /dev/null +++ b/gui/assets/images/menubar-icons/darwin/lock-2_notification.png diff --git a/gui/assets/images/menubar-icons/darwin/lock-2_notification@2x.png b/gui/assets/images/menubar-icons/darwin/lock-2_notification@2x.png Binary files differnew file mode 100644 index 0000000000..587431daf1 --- /dev/null +++ b/gui/assets/images/menubar-icons/darwin/lock-2_notification@2x.png diff --git a/gui/assets/images/menubar-icons/darwin/lock-2_notificationTemplate.png b/gui/assets/images/menubar-icons/darwin/lock-2_notificationTemplate.png Binary files differnew file mode 100644 index 0000000000..8e0925ebd6 --- /dev/null +++ b/gui/assets/images/menubar-icons/darwin/lock-2_notificationTemplate.png diff --git a/gui/assets/images/menubar-icons/darwin/lock-2_notificationTemplate@2x.png b/gui/assets/images/menubar-icons/darwin/lock-2_notificationTemplate@2x.png Binary files differnew file mode 100644 index 0000000000..3ade746899 --- /dev/null +++ b/gui/assets/images/menubar-icons/darwin/lock-2_notificationTemplate@2x.png diff --git a/gui/assets/images/menubar-icons/darwin/lock-3_notification.png b/gui/assets/images/menubar-icons/darwin/lock-3_notification.png Binary files differnew file mode 100644 index 0000000000..b459ff77b6 --- /dev/null +++ b/gui/assets/images/menubar-icons/darwin/lock-3_notification.png diff --git a/gui/assets/images/menubar-icons/darwin/lock-3_notification@2x.png b/gui/assets/images/menubar-icons/darwin/lock-3_notification@2x.png Binary files differnew file mode 100644 index 0000000000..57c5f115b7 --- /dev/null +++ b/gui/assets/images/menubar-icons/darwin/lock-3_notification@2x.png diff --git a/gui/assets/images/menubar-icons/darwin/lock-3_notificationTemplate.png b/gui/assets/images/menubar-icons/darwin/lock-3_notificationTemplate.png Binary files differnew file mode 100644 index 0000000000..aeaca43d3d --- /dev/null +++ b/gui/assets/images/menubar-icons/darwin/lock-3_notificationTemplate.png diff --git a/gui/assets/images/menubar-icons/darwin/lock-3_notificationTemplate@2x.png b/gui/assets/images/menubar-icons/darwin/lock-3_notificationTemplate@2x.png Binary files differnew file mode 100644 index 0000000000..08ca473c2d --- /dev/null +++ b/gui/assets/images/menubar-icons/darwin/lock-3_notificationTemplate@2x.png diff --git a/gui/assets/images/menubar-icons/darwin/lock-4_notification.png b/gui/assets/images/menubar-icons/darwin/lock-4_notification.png Binary files differnew file mode 100644 index 0000000000..5c6f05ee59 --- /dev/null +++ b/gui/assets/images/menubar-icons/darwin/lock-4_notification.png diff --git a/gui/assets/images/menubar-icons/darwin/lock-4_notification@2x.png b/gui/assets/images/menubar-icons/darwin/lock-4_notification@2x.png Binary files differnew file mode 100644 index 0000000000..c89fe28e9f --- /dev/null +++ b/gui/assets/images/menubar-icons/darwin/lock-4_notification@2x.png diff --git a/gui/assets/images/menubar-icons/darwin/lock-4_notificationTemplate.png b/gui/assets/images/menubar-icons/darwin/lock-4_notificationTemplate.png Binary files differnew file mode 100644 index 0000000000..d9de6ef087 --- /dev/null +++ b/gui/assets/images/menubar-icons/darwin/lock-4_notificationTemplate.png diff --git a/gui/assets/images/menubar-icons/darwin/lock-4_notificationTemplate@2x.png b/gui/assets/images/menubar-icons/darwin/lock-4_notificationTemplate@2x.png Binary files differnew file mode 100644 index 0000000000..ea046f7e54 --- /dev/null +++ b/gui/assets/images/menubar-icons/darwin/lock-4_notificationTemplate@2x.png diff --git a/gui/assets/images/menubar-icons/darwin/lock-5_notification.png b/gui/assets/images/menubar-icons/darwin/lock-5_notification.png Binary files differnew file mode 100644 index 0000000000..f800abb54d --- /dev/null +++ b/gui/assets/images/menubar-icons/darwin/lock-5_notification.png diff --git a/gui/assets/images/menubar-icons/darwin/lock-5_notification@2x.png b/gui/assets/images/menubar-icons/darwin/lock-5_notification@2x.png Binary files differnew file mode 100644 index 0000000000..32ef4bf0a0 --- /dev/null +++ b/gui/assets/images/menubar-icons/darwin/lock-5_notification@2x.png diff --git a/gui/assets/images/menubar-icons/darwin/lock-5_notificationTemplate.png b/gui/assets/images/menubar-icons/darwin/lock-5_notificationTemplate.png Binary files differnew file mode 100644 index 0000000000..ce385022b0 --- /dev/null +++ b/gui/assets/images/menubar-icons/darwin/lock-5_notificationTemplate.png diff --git a/gui/assets/images/menubar-icons/darwin/lock-5_notificationTemplate@2x.png b/gui/assets/images/menubar-icons/darwin/lock-5_notificationTemplate@2x.png Binary files differnew file mode 100644 index 0000000000..563180ee15 --- /dev/null +++ b/gui/assets/images/menubar-icons/darwin/lock-5_notificationTemplate@2x.png diff --git a/gui/assets/images/menubar-icons/darwin/lock-6_notification.png b/gui/assets/images/menubar-icons/darwin/lock-6_notification.png Binary files differnew file mode 100644 index 0000000000..ea9164038c --- /dev/null +++ b/gui/assets/images/menubar-icons/darwin/lock-6_notification.png diff --git a/gui/assets/images/menubar-icons/darwin/lock-6_notification@2x.png b/gui/assets/images/menubar-icons/darwin/lock-6_notification@2x.png Binary files differnew file mode 100644 index 0000000000..4bc59ad1c5 --- /dev/null +++ b/gui/assets/images/menubar-icons/darwin/lock-6_notification@2x.png diff --git a/gui/assets/images/menubar-icons/darwin/lock-6_notificationTemplate.png b/gui/assets/images/menubar-icons/darwin/lock-6_notificationTemplate.png Binary files differnew file mode 100644 index 0000000000..cbb45c518c --- /dev/null +++ b/gui/assets/images/menubar-icons/darwin/lock-6_notificationTemplate.png diff --git a/gui/assets/images/menubar-icons/darwin/lock-6_notificationTemplate@2x.png b/gui/assets/images/menubar-icons/darwin/lock-6_notificationTemplate@2x.png Binary files differnew file mode 100644 index 0000000000..741401e26b --- /dev/null +++ b/gui/assets/images/menubar-icons/darwin/lock-6_notificationTemplate@2x.png diff --git a/gui/assets/images/menubar-icons/darwin/lock-7_notification.png b/gui/assets/images/menubar-icons/darwin/lock-7_notification.png Binary files differnew file mode 100644 index 0000000000..d50cf55f07 --- /dev/null +++ b/gui/assets/images/menubar-icons/darwin/lock-7_notification.png diff --git a/gui/assets/images/menubar-icons/darwin/lock-7_notification@2x.png b/gui/assets/images/menubar-icons/darwin/lock-7_notification@2x.png Binary files differnew file mode 100644 index 0000000000..2bf05e2f90 --- /dev/null +++ b/gui/assets/images/menubar-icons/darwin/lock-7_notification@2x.png diff --git a/gui/assets/images/menubar-icons/darwin/lock-7_notificationTemplate.png b/gui/assets/images/menubar-icons/darwin/lock-7_notificationTemplate.png Binary files differnew file mode 100644 index 0000000000..cc37108816 --- /dev/null +++ b/gui/assets/images/menubar-icons/darwin/lock-7_notificationTemplate.png diff --git a/gui/assets/images/menubar-icons/darwin/lock-7_notificationTemplate@2x.png b/gui/assets/images/menubar-icons/darwin/lock-7_notificationTemplate@2x.png Binary files differnew file mode 100644 index 0000000000..6fba7079cc --- /dev/null +++ b/gui/assets/images/menubar-icons/darwin/lock-7_notificationTemplate@2x.png diff --git a/gui/assets/images/menubar-icons/darwin/lock-8_notification.png b/gui/assets/images/menubar-icons/darwin/lock-8_notification.png Binary files differnew file mode 100644 index 0000000000..df0ed069ee --- /dev/null +++ b/gui/assets/images/menubar-icons/darwin/lock-8_notification.png diff --git a/gui/assets/images/menubar-icons/darwin/lock-8_notification@2x.png b/gui/assets/images/menubar-icons/darwin/lock-8_notification@2x.png Binary files differnew file mode 100644 index 0000000000..6f68f85546 --- /dev/null +++ b/gui/assets/images/menubar-icons/darwin/lock-8_notification@2x.png diff --git a/gui/assets/images/menubar-icons/darwin/lock-8_notificationTemplate.png b/gui/assets/images/menubar-icons/darwin/lock-8_notificationTemplate.png Binary files differnew file mode 100644 index 0000000000..821fe6ec70 --- /dev/null +++ b/gui/assets/images/menubar-icons/darwin/lock-8_notificationTemplate.png diff --git a/gui/assets/images/menubar-icons/darwin/lock-8_notificationTemplate@2x.png b/gui/assets/images/menubar-icons/darwin/lock-8_notificationTemplate@2x.png Binary files differnew file mode 100644 index 0000000000..86e1083908 --- /dev/null +++ b/gui/assets/images/menubar-icons/darwin/lock-8_notificationTemplate@2x.png diff --git a/gui/assets/images/menubar-icons/darwin/lock-9_notification.png b/gui/assets/images/menubar-icons/darwin/lock-9_notification.png Binary files differnew file mode 100644 index 0000000000..84fe22dc4b --- /dev/null +++ b/gui/assets/images/menubar-icons/darwin/lock-9_notification.png diff --git a/gui/assets/images/menubar-icons/darwin/lock-9_notification@2x.png b/gui/assets/images/menubar-icons/darwin/lock-9_notification@2x.png Binary files differnew file mode 100644 index 0000000000..fcc94e2a0d --- /dev/null +++ b/gui/assets/images/menubar-icons/darwin/lock-9_notification@2x.png diff --git a/gui/assets/images/menubar-icons/darwin/lock-9_notificationTemplate.png b/gui/assets/images/menubar-icons/darwin/lock-9_notificationTemplate.png Binary files differnew file mode 100644 index 0000000000..e956a58116 --- /dev/null +++ b/gui/assets/images/menubar-icons/darwin/lock-9_notificationTemplate.png diff --git a/gui/assets/images/menubar-icons/darwin/lock-9_notificationTemplate@2x.png b/gui/assets/images/menubar-icons/darwin/lock-9_notificationTemplate@2x.png Binary files differnew file mode 100644 index 0000000000..4a937ba6be --- /dev/null +++ b/gui/assets/images/menubar-icons/darwin/lock-9_notificationTemplate@2x.png diff --git a/gui/assets/images/menubar-icons/linux/lock-1.png b/gui/assets/images/menubar-icons/linux/lock-1.png Binary files differindex 703b5d7d39..2abdf94db1 100644 --- a/gui/assets/images/menubar-icons/linux/lock-1.png +++ b/gui/assets/images/menubar-icons/linux/lock-1.png diff --git a/gui/assets/images/menubar-icons/linux/lock-10.png b/gui/assets/images/menubar-icons/linux/lock-10.png Binary files differindex 2d5ec51cf6..6d84a36af5 100644 --- a/gui/assets/images/menubar-icons/linux/lock-10.png +++ b/gui/assets/images/menubar-icons/linux/lock-10.png diff --git a/gui/assets/images/menubar-icons/linux/lock-10_notification.png b/gui/assets/images/menubar-icons/linux/lock-10_notification.png Binary files differnew file mode 100644 index 0000000000..a2f9b27811 --- /dev/null +++ b/gui/assets/images/menubar-icons/linux/lock-10_notification.png diff --git a/gui/assets/images/menubar-icons/linux/lock-10_white.png b/gui/assets/images/menubar-icons/linux/lock-10_white.png Binary files differindex c0bc8f22cb..05a3d46400 100644 --- a/gui/assets/images/menubar-icons/linux/lock-10_white.png +++ b/gui/assets/images/menubar-icons/linux/lock-10_white.png diff --git a/gui/assets/images/menubar-icons/linux/lock-10_white_notification.png b/gui/assets/images/menubar-icons/linux/lock-10_white_notification.png Binary files differnew file mode 100644 index 0000000000..d3bdcf701d --- /dev/null +++ b/gui/assets/images/menubar-icons/linux/lock-10_white_notification.png diff --git a/gui/assets/images/menubar-icons/linux/lock-1_notification.png b/gui/assets/images/menubar-icons/linux/lock-1_notification.png Binary files differnew file mode 100644 index 0000000000..6d5d93ff82 --- /dev/null +++ b/gui/assets/images/menubar-icons/linux/lock-1_notification.png diff --git a/gui/assets/images/menubar-icons/linux/lock-1_white.png b/gui/assets/images/menubar-icons/linux/lock-1_white.png Binary files differindex fcb8299156..dab3a73af4 100644 --- a/gui/assets/images/menubar-icons/linux/lock-1_white.png +++ b/gui/assets/images/menubar-icons/linux/lock-1_white.png diff --git a/gui/assets/images/menubar-icons/linux/lock-1_white_notification.png b/gui/assets/images/menubar-icons/linux/lock-1_white_notification.png Binary files differnew file mode 100644 index 0000000000..beeedff7db --- /dev/null +++ b/gui/assets/images/menubar-icons/linux/lock-1_white_notification.png diff --git a/gui/assets/images/menubar-icons/linux/lock-2.png b/gui/assets/images/menubar-icons/linux/lock-2.png Binary files differindex 7957030fa7..8cc2ef4ffb 100644 --- a/gui/assets/images/menubar-icons/linux/lock-2.png +++ b/gui/assets/images/menubar-icons/linux/lock-2.png diff --git a/gui/assets/images/menubar-icons/linux/lock-2_notification.png b/gui/assets/images/menubar-icons/linux/lock-2_notification.png Binary files differnew file mode 100644 index 0000000000..97bd0d0459 --- /dev/null +++ b/gui/assets/images/menubar-icons/linux/lock-2_notification.png diff --git a/gui/assets/images/menubar-icons/linux/lock-2_white.png b/gui/assets/images/menubar-icons/linux/lock-2_white.png Binary files differindex 99f610e738..92a5c8adbd 100644 --- a/gui/assets/images/menubar-icons/linux/lock-2_white.png +++ b/gui/assets/images/menubar-icons/linux/lock-2_white.png diff --git a/gui/assets/images/menubar-icons/linux/lock-2_white_notification.png b/gui/assets/images/menubar-icons/linux/lock-2_white_notification.png Binary files differnew file mode 100644 index 0000000000..c016e13535 --- /dev/null +++ b/gui/assets/images/menubar-icons/linux/lock-2_white_notification.png diff --git a/gui/assets/images/menubar-icons/linux/lock-3.png b/gui/assets/images/menubar-icons/linux/lock-3.png Binary files differindex f2c65c79ed..3cb3b7aaac 100644 --- a/gui/assets/images/menubar-icons/linux/lock-3.png +++ b/gui/assets/images/menubar-icons/linux/lock-3.png diff --git a/gui/assets/images/menubar-icons/linux/lock-3_notification.png b/gui/assets/images/menubar-icons/linux/lock-3_notification.png Binary files differnew file mode 100644 index 0000000000..bb2a5d95f4 --- /dev/null +++ b/gui/assets/images/menubar-icons/linux/lock-3_notification.png diff --git a/gui/assets/images/menubar-icons/linux/lock-3_white.png b/gui/assets/images/menubar-icons/linux/lock-3_white.png Binary files differindex 28c035bba3..661fec0e6b 100644 --- a/gui/assets/images/menubar-icons/linux/lock-3_white.png +++ b/gui/assets/images/menubar-icons/linux/lock-3_white.png diff --git a/gui/assets/images/menubar-icons/linux/lock-3_white_notification.png b/gui/assets/images/menubar-icons/linux/lock-3_white_notification.png Binary files differnew file mode 100644 index 0000000000..b09101008a --- /dev/null +++ b/gui/assets/images/menubar-icons/linux/lock-3_white_notification.png diff --git a/gui/assets/images/menubar-icons/linux/lock-4.png b/gui/assets/images/menubar-icons/linux/lock-4.png Binary files differindex 374e52763e..726d161a63 100644 --- a/gui/assets/images/menubar-icons/linux/lock-4.png +++ b/gui/assets/images/menubar-icons/linux/lock-4.png diff --git a/gui/assets/images/menubar-icons/linux/lock-4_notification.png b/gui/assets/images/menubar-icons/linux/lock-4_notification.png Binary files differnew file mode 100644 index 0000000000..87b00973ad --- /dev/null +++ b/gui/assets/images/menubar-icons/linux/lock-4_notification.png diff --git a/gui/assets/images/menubar-icons/linux/lock-4_white.png b/gui/assets/images/menubar-icons/linux/lock-4_white.png Binary files differindex c11f1d7690..e7f4a32ed8 100644 --- a/gui/assets/images/menubar-icons/linux/lock-4_white.png +++ b/gui/assets/images/menubar-icons/linux/lock-4_white.png diff --git a/gui/assets/images/menubar-icons/linux/lock-4_white_notification.png b/gui/assets/images/menubar-icons/linux/lock-4_white_notification.png Binary files differnew file mode 100644 index 0000000000..718b35257b --- /dev/null +++ b/gui/assets/images/menubar-icons/linux/lock-4_white_notification.png diff --git a/gui/assets/images/menubar-icons/linux/lock-5.png b/gui/assets/images/menubar-icons/linux/lock-5.png Binary files differindex d653339175..33af30e754 100644 --- a/gui/assets/images/menubar-icons/linux/lock-5.png +++ b/gui/assets/images/menubar-icons/linux/lock-5.png diff --git a/gui/assets/images/menubar-icons/linux/lock-5_notification.png b/gui/assets/images/menubar-icons/linux/lock-5_notification.png Binary files differnew file mode 100644 index 0000000000..94ccd720e9 --- /dev/null +++ b/gui/assets/images/menubar-icons/linux/lock-5_notification.png diff --git a/gui/assets/images/menubar-icons/linux/lock-5_white.png b/gui/assets/images/menubar-icons/linux/lock-5_white.png Binary files differindex ce57a0b823..a947018533 100644 --- a/gui/assets/images/menubar-icons/linux/lock-5_white.png +++ b/gui/assets/images/menubar-icons/linux/lock-5_white.png diff --git a/gui/assets/images/menubar-icons/linux/lock-5_white_notification.png b/gui/assets/images/menubar-icons/linux/lock-5_white_notification.png Binary files differnew file mode 100644 index 0000000000..de097f21b1 --- /dev/null +++ b/gui/assets/images/menubar-icons/linux/lock-5_white_notification.png diff --git a/gui/assets/images/menubar-icons/linux/lock-6.png b/gui/assets/images/menubar-icons/linux/lock-6.png Binary files differindex 5ed849f866..b6a67f5802 100644 --- a/gui/assets/images/menubar-icons/linux/lock-6.png +++ b/gui/assets/images/menubar-icons/linux/lock-6.png diff --git a/gui/assets/images/menubar-icons/linux/lock-6_notification.png b/gui/assets/images/menubar-icons/linux/lock-6_notification.png Binary files differnew file mode 100644 index 0000000000..419c0c3506 --- /dev/null +++ b/gui/assets/images/menubar-icons/linux/lock-6_notification.png diff --git a/gui/assets/images/menubar-icons/linux/lock-6_white.png b/gui/assets/images/menubar-icons/linux/lock-6_white.png Binary files differindex 68f170b879..211dcbff00 100644 --- a/gui/assets/images/menubar-icons/linux/lock-6_white.png +++ b/gui/assets/images/menubar-icons/linux/lock-6_white.png diff --git a/gui/assets/images/menubar-icons/linux/lock-6_white_notification.png b/gui/assets/images/menubar-icons/linux/lock-6_white_notification.png Binary files differnew file mode 100644 index 0000000000..74992c124e --- /dev/null +++ b/gui/assets/images/menubar-icons/linux/lock-6_white_notification.png diff --git a/gui/assets/images/menubar-icons/linux/lock-7.png b/gui/assets/images/menubar-icons/linux/lock-7.png Binary files differindex 7ecdcb47f9..156e6a248c 100644 --- a/gui/assets/images/menubar-icons/linux/lock-7.png +++ b/gui/assets/images/menubar-icons/linux/lock-7.png diff --git a/gui/assets/images/menubar-icons/linux/lock-7_notification.png b/gui/assets/images/menubar-icons/linux/lock-7_notification.png Binary files differnew file mode 100644 index 0000000000..c1b42201bc --- /dev/null +++ b/gui/assets/images/menubar-icons/linux/lock-7_notification.png diff --git a/gui/assets/images/menubar-icons/linux/lock-7_white.png b/gui/assets/images/menubar-icons/linux/lock-7_white.png Binary files differindex 7b11106178..4005f35872 100644 --- a/gui/assets/images/menubar-icons/linux/lock-7_white.png +++ b/gui/assets/images/menubar-icons/linux/lock-7_white.png diff --git a/gui/assets/images/menubar-icons/linux/lock-7_white_notification.png b/gui/assets/images/menubar-icons/linux/lock-7_white_notification.png Binary files differnew file mode 100644 index 0000000000..9d6a6c26db --- /dev/null +++ b/gui/assets/images/menubar-icons/linux/lock-7_white_notification.png diff --git a/gui/assets/images/menubar-icons/linux/lock-8.png b/gui/assets/images/menubar-icons/linux/lock-8.png Binary files differindex bd9805d254..73ce51db8f 100644 --- a/gui/assets/images/menubar-icons/linux/lock-8.png +++ b/gui/assets/images/menubar-icons/linux/lock-8.png diff --git a/gui/assets/images/menubar-icons/linux/lock-8_notification.png b/gui/assets/images/menubar-icons/linux/lock-8_notification.png Binary files differnew file mode 100644 index 0000000000..9c1663e8ef --- /dev/null +++ b/gui/assets/images/menubar-icons/linux/lock-8_notification.png diff --git a/gui/assets/images/menubar-icons/linux/lock-8_white.png b/gui/assets/images/menubar-icons/linux/lock-8_white.png Binary files differindex 21351d4500..f4ecc9c739 100644 --- a/gui/assets/images/menubar-icons/linux/lock-8_white.png +++ b/gui/assets/images/menubar-icons/linux/lock-8_white.png diff --git a/gui/assets/images/menubar-icons/linux/lock-8_white_notification.png b/gui/assets/images/menubar-icons/linux/lock-8_white_notification.png Binary files differnew file mode 100644 index 0000000000..c7f3981a15 --- /dev/null +++ b/gui/assets/images/menubar-icons/linux/lock-8_white_notification.png diff --git a/gui/assets/images/menubar-icons/linux/lock-9.png b/gui/assets/images/menubar-icons/linux/lock-9.png Binary files differindex 6d3a822ab6..c6a6314d1f 100644 --- a/gui/assets/images/menubar-icons/linux/lock-9.png +++ b/gui/assets/images/menubar-icons/linux/lock-9.png diff --git a/gui/assets/images/menubar-icons/linux/lock-9_notification.png b/gui/assets/images/menubar-icons/linux/lock-9_notification.png Binary files differnew file mode 100644 index 0000000000..fb01498584 --- /dev/null +++ b/gui/assets/images/menubar-icons/linux/lock-9_notification.png diff --git a/gui/assets/images/menubar-icons/linux/lock-9_white.png b/gui/assets/images/menubar-icons/linux/lock-9_white.png Binary files differindex fe6ab88cd6..aef18b9c44 100644 --- a/gui/assets/images/menubar-icons/linux/lock-9_white.png +++ b/gui/assets/images/menubar-icons/linux/lock-9_white.png diff --git a/gui/assets/images/menubar-icons/linux/lock-9_white_notification.png b/gui/assets/images/menubar-icons/linux/lock-9_white_notification.png Binary files differnew file mode 100644 index 0000000000..bd9a7e4791 --- /dev/null +++ b/gui/assets/images/menubar-icons/linux/lock-9_white_notification.png diff --git a/gui/assets/images/menubar-icons/svg/notification.svg b/gui/assets/images/menubar-icons/svg/notification.svg new file mode 100644 index 0000000000..bde33010e2 --- /dev/null +++ b/gui/assets/images/menubar-icons/svg/notification.svg @@ -0,0 +1,5 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14"> + <g fill-rule="evenodd"> + <circle fill="#FFD524" cx="7" cy="7" r="6"/> + </g> +</svg> diff --git a/gui/assets/images/menubar-icons/win32/lock-1.ico b/gui/assets/images/menubar-icons/win32/lock-1.ico Binary files differindex 30d82bec86..0c3677f6d9 100644 --- a/gui/assets/images/menubar-icons/win32/lock-1.ico +++ b/gui/assets/images/menubar-icons/win32/lock-1.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-10.ico b/gui/assets/images/menubar-icons/win32/lock-10.ico Binary files differindex eaa8434279..3012d5e461 100644 --- a/gui/assets/images/menubar-icons/win32/lock-10.ico +++ b/gui/assets/images/menubar-icons/win32/lock-10.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-10_black.ico b/gui/assets/images/menubar-icons/win32/lock-10_black.ico Binary files differindex b466219e74..c5f295c5eb 100644 --- a/gui/assets/images/menubar-icons/win32/lock-10_black.ico +++ b/gui/assets/images/menubar-icons/win32/lock-10_black.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-10_black_notification.ico b/gui/assets/images/menubar-icons/win32/lock-10_black_notification.ico Binary files differnew file mode 100644 index 0000000000..bf28e3e49a --- /dev/null +++ b/gui/assets/images/menubar-icons/win32/lock-10_black_notification.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-10_notification.ico b/gui/assets/images/menubar-icons/win32/lock-10_notification.ico Binary files differnew file mode 100644 index 0000000000..d6ae112a0a --- /dev/null +++ b/gui/assets/images/menubar-icons/win32/lock-10_notification.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-10_white.ico b/gui/assets/images/menubar-icons/win32/lock-10_white.ico Binary files differindex 6bd7d3fdf8..f7f5d420d2 100644 --- a/gui/assets/images/menubar-icons/win32/lock-10_white.ico +++ b/gui/assets/images/menubar-icons/win32/lock-10_white.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-10_white_notification.ico b/gui/assets/images/menubar-icons/win32/lock-10_white_notification.ico Binary files differnew file mode 100644 index 0000000000..bba0cd4542 --- /dev/null +++ b/gui/assets/images/menubar-icons/win32/lock-10_white_notification.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-1_black.ico b/gui/assets/images/menubar-icons/win32/lock-1_black.ico Binary files differindex 92a336c1ab..e2c708789b 100644 --- a/gui/assets/images/menubar-icons/win32/lock-1_black.ico +++ b/gui/assets/images/menubar-icons/win32/lock-1_black.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-1_black_notification.ico b/gui/assets/images/menubar-icons/win32/lock-1_black_notification.ico Binary files differnew file mode 100644 index 0000000000..fb41a1eef0 --- /dev/null +++ b/gui/assets/images/menubar-icons/win32/lock-1_black_notification.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-1_notification.ico b/gui/assets/images/menubar-icons/win32/lock-1_notification.ico Binary files differnew file mode 100644 index 0000000000..c44bef9934 --- /dev/null +++ b/gui/assets/images/menubar-icons/win32/lock-1_notification.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-1_white.ico b/gui/assets/images/menubar-icons/win32/lock-1_white.ico Binary files differindex 73c8051b18..c2732a3d37 100644 --- a/gui/assets/images/menubar-icons/win32/lock-1_white.ico +++ b/gui/assets/images/menubar-icons/win32/lock-1_white.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-1_white_notification.ico b/gui/assets/images/menubar-icons/win32/lock-1_white_notification.ico Binary files differnew file mode 100644 index 0000000000..b8dfce83fc --- /dev/null +++ b/gui/assets/images/menubar-icons/win32/lock-1_white_notification.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-2.ico b/gui/assets/images/menubar-icons/win32/lock-2.ico Binary files differindex e8f0a281f9..0f947e3a91 100644 --- a/gui/assets/images/menubar-icons/win32/lock-2.ico +++ b/gui/assets/images/menubar-icons/win32/lock-2.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-2_black.ico b/gui/assets/images/menubar-icons/win32/lock-2_black.ico Binary files differindex cffca1039e..27da63bf6a 100644 --- a/gui/assets/images/menubar-icons/win32/lock-2_black.ico +++ b/gui/assets/images/menubar-icons/win32/lock-2_black.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-2_black_notification.ico b/gui/assets/images/menubar-icons/win32/lock-2_black_notification.ico Binary files differnew file mode 100644 index 0000000000..ae2e60fe36 --- /dev/null +++ b/gui/assets/images/menubar-icons/win32/lock-2_black_notification.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-2_notification.ico b/gui/assets/images/menubar-icons/win32/lock-2_notification.ico Binary files differnew file mode 100644 index 0000000000..12d3479faa --- /dev/null +++ b/gui/assets/images/menubar-icons/win32/lock-2_notification.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-2_white.ico b/gui/assets/images/menubar-icons/win32/lock-2_white.ico Binary files differindex 973c17fc9a..357cbcd965 100644 --- a/gui/assets/images/menubar-icons/win32/lock-2_white.ico +++ b/gui/assets/images/menubar-icons/win32/lock-2_white.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-2_white_notification.ico b/gui/assets/images/menubar-icons/win32/lock-2_white_notification.ico Binary files differnew file mode 100644 index 0000000000..3e8465c82e --- /dev/null +++ b/gui/assets/images/menubar-icons/win32/lock-2_white_notification.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-3.ico b/gui/assets/images/menubar-icons/win32/lock-3.ico Binary files differindex 09ff8feb17..322f2d35f8 100644 --- a/gui/assets/images/menubar-icons/win32/lock-3.ico +++ b/gui/assets/images/menubar-icons/win32/lock-3.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-3_black.ico b/gui/assets/images/menubar-icons/win32/lock-3_black.ico Binary files differindex 51ba068c06..c691c9b60c 100644 --- a/gui/assets/images/menubar-icons/win32/lock-3_black.ico +++ b/gui/assets/images/menubar-icons/win32/lock-3_black.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-3_black_notification.ico b/gui/assets/images/menubar-icons/win32/lock-3_black_notification.ico Binary files differnew file mode 100644 index 0000000000..b7149c73b6 --- /dev/null +++ b/gui/assets/images/menubar-icons/win32/lock-3_black_notification.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-3_notification.ico b/gui/assets/images/menubar-icons/win32/lock-3_notification.ico Binary files differnew file mode 100644 index 0000000000..30d5386499 --- /dev/null +++ b/gui/assets/images/menubar-icons/win32/lock-3_notification.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-3_white.ico b/gui/assets/images/menubar-icons/win32/lock-3_white.ico Binary files differindex 186d8a2629..f779edd521 100644 --- a/gui/assets/images/menubar-icons/win32/lock-3_white.ico +++ b/gui/assets/images/menubar-icons/win32/lock-3_white.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-3_white_notification.ico b/gui/assets/images/menubar-icons/win32/lock-3_white_notification.ico Binary files differnew file mode 100644 index 0000000000..91340bff46 --- /dev/null +++ b/gui/assets/images/menubar-icons/win32/lock-3_white_notification.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-4.ico b/gui/assets/images/menubar-icons/win32/lock-4.ico Binary files differindex 4cffe9b9fa..9830776eb7 100644 --- a/gui/assets/images/menubar-icons/win32/lock-4.ico +++ b/gui/assets/images/menubar-icons/win32/lock-4.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-4_black.ico b/gui/assets/images/menubar-icons/win32/lock-4_black.ico Binary files differindex 2dd3437b72..60794aab9b 100644 --- a/gui/assets/images/menubar-icons/win32/lock-4_black.ico +++ b/gui/assets/images/menubar-icons/win32/lock-4_black.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-4_black_notification.ico b/gui/assets/images/menubar-icons/win32/lock-4_black_notification.ico Binary files differnew file mode 100644 index 0000000000..6f0b4e5fa1 --- /dev/null +++ b/gui/assets/images/menubar-icons/win32/lock-4_black_notification.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-4_notification.ico b/gui/assets/images/menubar-icons/win32/lock-4_notification.ico Binary files differnew file mode 100644 index 0000000000..8fdd8530ae --- /dev/null +++ b/gui/assets/images/menubar-icons/win32/lock-4_notification.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-4_white.ico b/gui/assets/images/menubar-icons/win32/lock-4_white.ico Binary files differindex 1c5b361b18..f7501a290c 100644 --- a/gui/assets/images/menubar-icons/win32/lock-4_white.ico +++ b/gui/assets/images/menubar-icons/win32/lock-4_white.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-4_white_notification.ico b/gui/assets/images/menubar-icons/win32/lock-4_white_notification.ico Binary files differnew file mode 100644 index 0000000000..fa6b0a71dd --- /dev/null +++ b/gui/assets/images/menubar-icons/win32/lock-4_white_notification.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-5.ico b/gui/assets/images/menubar-icons/win32/lock-5.ico Binary files differindex 8b232cfba6..c49493290f 100644 --- a/gui/assets/images/menubar-icons/win32/lock-5.ico +++ b/gui/assets/images/menubar-icons/win32/lock-5.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-5_black.ico b/gui/assets/images/menubar-icons/win32/lock-5_black.ico Binary files differindex a711341f6b..57bdfa833e 100644 --- a/gui/assets/images/menubar-icons/win32/lock-5_black.ico +++ b/gui/assets/images/menubar-icons/win32/lock-5_black.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-5_black_notification.ico b/gui/assets/images/menubar-icons/win32/lock-5_black_notification.ico Binary files differnew file mode 100644 index 0000000000..22e104d264 --- /dev/null +++ b/gui/assets/images/menubar-icons/win32/lock-5_black_notification.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-5_notification.ico b/gui/assets/images/menubar-icons/win32/lock-5_notification.ico Binary files differnew file mode 100644 index 0000000000..34010156fe --- /dev/null +++ b/gui/assets/images/menubar-icons/win32/lock-5_notification.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-5_white.ico b/gui/assets/images/menubar-icons/win32/lock-5_white.ico Binary files differindex dac76b2a0a..13d58f0880 100644 --- a/gui/assets/images/menubar-icons/win32/lock-5_white.ico +++ b/gui/assets/images/menubar-icons/win32/lock-5_white.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-5_white_notification.ico b/gui/assets/images/menubar-icons/win32/lock-5_white_notification.ico Binary files differnew file mode 100644 index 0000000000..71f9374048 --- /dev/null +++ b/gui/assets/images/menubar-icons/win32/lock-5_white_notification.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-6.ico b/gui/assets/images/menubar-icons/win32/lock-6.ico Binary files differindex ba4a77679d..fdedcf893a 100644 --- a/gui/assets/images/menubar-icons/win32/lock-6.ico +++ b/gui/assets/images/menubar-icons/win32/lock-6.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-6_black.ico b/gui/assets/images/menubar-icons/win32/lock-6_black.ico Binary files differindex 4904fa215f..4b1558701d 100644 --- a/gui/assets/images/menubar-icons/win32/lock-6_black.ico +++ b/gui/assets/images/menubar-icons/win32/lock-6_black.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-6_black_notification.ico b/gui/assets/images/menubar-icons/win32/lock-6_black_notification.ico Binary files differnew file mode 100644 index 0000000000..1531aafe17 --- /dev/null +++ b/gui/assets/images/menubar-icons/win32/lock-6_black_notification.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-6_notification.ico b/gui/assets/images/menubar-icons/win32/lock-6_notification.ico Binary files differnew file mode 100644 index 0000000000..4f086f7023 --- /dev/null +++ b/gui/assets/images/menubar-icons/win32/lock-6_notification.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-6_white.ico b/gui/assets/images/menubar-icons/win32/lock-6_white.ico Binary files differindex 7cf7890dbc..128d68ff29 100644 --- a/gui/assets/images/menubar-icons/win32/lock-6_white.ico +++ b/gui/assets/images/menubar-icons/win32/lock-6_white.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-6_white_notification.ico b/gui/assets/images/menubar-icons/win32/lock-6_white_notification.ico Binary files differnew file mode 100644 index 0000000000..600fbba1a6 --- /dev/null +++ b/gui/assets/images/menubar-icons/win32/lock-6_white_notification.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-7.ico b/gui/assets/images/menubar-icons/win32/lock-7.ico Binary files differindex d43d178a29..064459b9cc 100644 --- a/gui/assets/images/menubar-icons/win32/lock-7.ico +++ b/gui/assets/images/menubar-icons/win32/lock-7.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-7_black.ico b/gui/assets/images/menubar-icons/win32/lock-7_black.ico Binary files differindex f18bfcad29..8c53c73e49 100644 --- a/gui/assets/images/menubar-icons/win32/lock-7_black.ico +++ b/gui/assets/images/menubar-icons/win32/lock-7_black.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-7_black_notification.ico b/gui/assets/images/menubar-icons/win32/lock-7_black_notification.ico Binary files differnew file mode 100644 index 0000000000..430b7107e2 --- /dev/null +++ b/gui/assets/images/menubar-icons/win32/lock-7_black_notification.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-7_notification.ico b/gui/assets/images/menubar-icons/win32/lock-7_notification.ico Binary files differnew file mode 100644 index 0000000000..80dcb40a06 --- /dev/null +++ b/gui/assets/images/menubar-icons/win32/lock-7_notification.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-7_white.ico b/gui/assets/images/menubar-icons/win32/lock-7_white.ico Binary files differindex 5ccc7842d5..dccade1bfc 100644 --- a/gui/assets/images/menubar-icons/win32/lock-7_white.ico +++ b/gui/assets/images/menubar-icons/win32/lock-7_white.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-7_white_notification.ico b/gui/assets/images/menubar-icons/win32/lock-7_white_notification.ico Binary files differnew file mode 100644 index 0000000000..24436e2bc2 --- /dev/null +++ b/gui/assets/images/menubar-icons/win32/lock-7_white_notification.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-8.ico b/gui/assets/images/menubar-icons/win32/lock-8.ico Binary files differindex 7795aadb4b..9499b029ec 100644 --- a/gui/assets/images/menubar-icons/win32/lock-8.ico +++ b/gui/assets/images/menubar-icons/win32/lock-8.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-8_black.ico b/gui/assets/images/menubar-icons/win32/lock-8_black.ico Binary files differindex b3d9c0974f..0c6ef7abb3 100644 --- a/gui/assets/images/menubar-icons/win32/lock-8_black.ico +++ b/gui/assets/images/menubar-icons/win32/lock-8_black.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-8_black_notification.ico b/gui/assets/images/menubar-icons/win32/lock-8_black_notification.ico Binary files differnew file mode 100644 index 0000000000..3c8342c727 --- /dev/null +++ b/gui/assets/images/menubar-icons/win32/lock-8_black_notification.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-8_notification.ico b/gui/assets/images/menubar-icons/win32/lock-8_notification.ico Binary files differnew file mode 100644 index 0000000000..0f1cd8834c --- /dev/null +++ b/gui/assets/images/menubar-icons/win32/lock-8_notification.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-8_white.ico b/gui/assets/images/menubar-icons/win32/lock-8_white.ico Binary files differindex 6949e03e0b..5bc6c25998 100644 --- a/gui/assets/images/menubar-icons/win32/lock-8_white.ico +++ b/gui/assets/images/menubar-icons/win32/lock-8_white.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-8_white_notification.ico b/gui/assets/images/menubar-icons/win32/lock-8_white_notification.ico Binary files differnew file mode 100644 index 0000000000..b85a341ee9 --- /dev/null +++ b/gui/assets/images/menubar-icons/win32/lock-8_white_notification.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-9.ico b/gui/assets/images/menubar-icons/win32/lock-9.ico Binary files differindex fd244f8172..68aac8644c 100644 --- a/gui/assets/images/menubar-icons/win32/lock-9.ico +++ b/gui/assets/images/menubar-icons/win32/lock-9.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-9_black.ico b/gui/assets/images/menubar-icons/win32/lock-9_black.ico Binary files differindex 121ef5dd14..9a37e19034 100644 --- a/gui/assets/images/menubar-icons/win32/lock-9_black.ico +++ b/gui/assets/images/menubar-icons/win32/lock-9_black.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-9_black_notification.ico b/gui/assets/images/menubar-icons/win32/lock-9_black_notification.ico Binary files differnew file mode 100644 index 0000000000..53fe041f73 --- /dev/null +++ b/gui/assets/images/menubar-icons/win32/lock-9_black_notification.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-9_notification.ico b/gui/assets/images/menubar-icons/win32/lock-9_notification.ico Binary files differnew file mode 100644 index 0000000000..a5df31390a --- /dev/null +++ b/gui/assets/images/menubar-icons/win32/lock-9_notification.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-9_white.ico b/gui/assets/images/menubar-icons/win32/lock-9_white.ico Binary files differindex 6ce6ce2486..ba112f3a4a 100644 --- a/gui/assets/images/menubar-icons/win32/lock-9_white.ico +++ b/gui/assets/images/menubar-icons/win32/lock-9_white.ico diff --git a/gui/assets/images/menubar-icons/win32/lock-9_white_notification.ico b/gui/assets/images/menubar-icons/win32/lock-9_white_notification.ico Binary files differnew file mode 100644 index 0000000000..19cd32573e --- /dev/null +++ b/gui/assets/images/menubar-icons/win32/lock-9_white_notification.ico diff --git a/gui/locales/messages.pot b/gui/locales/messages.pot index d2eef0b96f..3fe9fc4570 100644 --- a/gui/locales/messages.pot +++ b/gui/locales/messages.pot @@ -775,6 +775,10 @@ msgid "Disconnected and unsecure" msgstr "" msgctxt "notifications" +msgid "Lockdown mode active, connection blocked" +msgstr "" + +msgctxt "notifications" msgid "No servers in your selected location match your settings." msgstr "" diff --git a/gui/scripts/generate-menubar-icons.sh b/gui/scripts/generate-menubar-icons.sh index 8ef1be5c36..8bd4310ace 100755 --- a/gui/scripts/generate-menubar-icons.sh +++ b/gui/scripts/generate-menubar-icons.sh @@ -47,31 +47,87 @@ function main() { rmdir "$TMP_DIR" } +# Genares the ico icons for the Windows tray icon. The ico consists of 3 different resolutions with +# 3 different bit depths each. Each icon is also available with and without notification dot. function generate_ico() { local svg_source_path="$1" local ico_target_path="$2" local tmp_file_paths=() + local notification_icon_tmp_file_paths=() for size in 16 32 48; do - local png_tmp_path="$TMP_DIR/$size.png" - local png8_tmp_path="$TMP_DIR/$size-8.png" - local png4_tmp_path="$TMP_DIR/$size-4.png" + local padding=$((size / 16)) + local notification_icon_size=$((size / 2)) + local png_tmp_path="$TMP_DIR/$size" + + generate_square "$svg_source_path" "$png_tmp_path.png" \ + "${png_tmp_path}_notification.png" "$size" "$padding" "$notification_icon_size" - rsvg-convert -o "$png_tmp_path" -w $size -h $size "$svg_source_path" - convert -background transparent "$png_tmp_path" -gravity center -extent ${size}x$size \ - "$png_tmp_path" # 4- and 8-bit versions for RDP - convert -colors 256 +dither "$png_tmp_path" png8:"$png8_tmp_path" - convert -colors 16 +dither "$png8_tmp_path" "$png4_tmp_path" + convert -colors 256 +dither "$png_tmp_path.png" png8:"$png_tmp_path-8.png" + convert -colors 16 +dither "$png_tmp_path-8.png" "$png_tmp_path-4.png" + + convert -colors 256 +dither "${png_tmp_path}_notification.png" \ + png8:"${png_tmp_path}_notification-8.png" + convert -colors 16 +dither "${png_tmp_path}_notification-8.png" \ + "${png_tmp_path}_notification-4.png" - tmp_file_paths+=("$png_tmp_path" "$png8_tmp_path" "$png4_tmp_path") + tmp_file_paths+=("$png_tmp_path.png" "$png_tmp_path-8.png" "$png_tmp_path-4.png") + notification_icon_tmp_file_paths+=( + "${png_tmp_path}_notification.png" + "${png_tmp_path}_notification-8.png" + "${png_tmp_path}_notification-4.png" + ) done - convert "${tmp_file_paths[@]}" "${COMPRESSION_OPTIONS[@]}" "$ico_target_path" + convert "${tmp_file_paths[@]}" "${COMPRESSION_OPTIONS[@]}" "$ico_target_path.ico" + convert "${notification_icon_tmp_file_paths[@]}" "${COMPRESSION_OPTIONS[@]}" \ + "${ico_target_path}_notification.ico" + rm "${tmp_file_paths[@]}" + rm "${notification_icon_tmp_file_paths[@]}" +} + +# Generates pngs both for regular icon and icon with notification symbol next to the icon, ending +# up with a rectangular icon. +function generate_rectangle() { + local svg_source_path="$1" + local png_target_path="$2" + local png_notification_target_path="$3" + local target_size=$4 + local target_padding=$5 + local notification_width=$6 + local target_size_no_padding=$((target_size - target_padding * 2)) + local png_tmp_path="$TMP_DIR/tmp.png" + + generate_lock_png "$svg_source_path" "$png_target_path" "$target_size" "$target_padding" + append_notification_icon "$png_target_path" "$png_notification_target_path" \ + "$notification_width" + + rm "$png_tmp_path" } -function generate_png() { +# Generates pngs both for regular icon and icon with notification symbol, ending up with a square +# icon since the notification dot is overlapping the lock. +function generate_square() { + local svg_source_path="$1" + local png_target_path="$2" + local png_notification_target_path="$3" + local target_size=$4 + local target_padding=$5 + local notification_width=$6 + local target_size_no_padding=$((target_size - target_padding * 2)) + local png_tmp_path="$TMP_DIR/tmp.png" + + generate_lock_png "$svg_source_path" "$png_target_path" "$target_size" "$target_padding" + overlay_notification_icon "$png_target_path" "$png_notification_target_path" \ + "$notification_width" + + rm "$png_tmp_path" +} + +# Generates the lock png +function generate_lock_png() { local svg_source_path="$1" local png_target_path="$2" local target_size=$3 @@ -83,9 +139,42 @@ function generate_png() { "$svg_source_path" convert -background transparent "$png_tmp_path" -gravity center \ -extent "${target_size}x$target_size" "${COMPRESSION_OPTIONS[@]}" "$png_target_path" - rm "$png_tmp_path" } +# Creates a copy of the icon at $source_path and appends the notification symbol to it +function append_notification_icon() { + local source_path="$1" + local target_path="$2" + local width="$3" + local padding="${4:-0}" + local size=$((width + 2)) + local notification_icon_tmp_path="$TMP_DIR/notification.png" + + rsvg-convert -o "$notification_icon_tmp_path" -w $size -h $size \ + --left "$padding" --page-width $((size + padding)) --page-height $size \ + "$SVG_DIR/notification.svg" + convert -strip -background transparent -colorspace sRGB -gravity center \ + +append "$source_path" "$notification_icon_tmp_path" "$target_path" + + rm "$notification_icon_tmp_path" +} + +# Creates a copy of the icon at $source_path and puts the notification symbol on top of it in the +# bottom right corner. +function overlay_notification_icon() { + local source_path="$1" + local target_path="$2" + local size="$3" + local notification_icon_tmp_path="$TMP_DIR/notification.png" + + rsvg-convert -o "$notification_icon_tmp_path" -w "$size" -h "$size" "$SVG_DIR/notification.svg" + convert -strip -background transparent -composite -colorspace sRGB -gravity SouthEast \ + "$source_path" "$notification_icon_tmp_path" "$target_path" + + rm "$notification_icon_tmp_path" +} + +# Generates all icon versions for a specific frame. function generate() { local icon_name="$1" local svg_source_path="$SVG_DIR/$icon_name.svg" @@ -94,29 +183,39 @@ function generate() { local black_svg_source_path="$TMP_DIR/black.svg" local white_svg_source_path="$TMP_DIR/white.svg" + local macos_target_base_path="$MACOS_DIR/$icon_name" + local linux_target_base_path="$LINUX_DIR/$icon_name" + local windows_target_base_path="$WINDOWS_DIR/$icon_name" + sed -E 's/#[0-9a-fA-f]{6}/#000000/g' "$monochrome_svg_source_path" > "$black_svg_source_path" sed -E 's/#[0-9a-fA-f]{6}/#FFFFFF/g' "$monochrome_svg_source_path" > "$white_svg_source_path" # MacOS colored - generate_png "$svg_source_path" "$MACOS_DIR/$icon_name.png" 22 3 - generate_png "$svg_source_path" "$MACOS_DIR/$icon_name@2x.png" 44 6 + generate_rectangle "$svg_source_path" "$macos_target_base_path.png" \ + "${macos_target_base_path}_notification.png" 22 3 4 + generate_rectangle "$svg_source_path" "$macos_target_base_path@2x.png" \ + "${macos_target_base_path}_notification@2x.png" 44 6 8 # MacOS monochrome - generate_png "$black_svg_source_path" "$MACOS_DIR/${icon_name}Template.png" 22 3 - generate_png "$black_svg_source_path" "$MACOS_DIR/${icon_name}Template@2x.png" 44 6 + generate_rectangle "$black_svg_source_path" "${macos_target_base_path}Template.png" \ + "${macos_target_base_path}_notificationTemplate.png" 22 3 4 + generate_rectangle "$black_svg_source_path" "${macos_target_base_path}Template@2x.png" \ + "${macos_target_base_path}_notificationTemplate@2x.png" 44 6 8 # Linux colored - generate_png "$svg_source_path" "$LINUX_DIR/$icon_name.png" 48 8 + generate_square "$svg_source_path" "$linux_target_base_path.png" \ + "${linux_target_base_path}_notification.png" 48 4 24 # Linux white - generate_png "$white_svg_source_path" "$LINUX_DIR/${icon_name}_white.png" 48 8 + generate_square "$white_svg_source_path" "${linux_target_base_path}_white.png" \ + "${linux_target_base_path}_white_notification.png" 48 4 24 # Windows colored - generate_ico "$svg_source_path" "$WINDOWS_DIR/$icon_name.ico" + generate_ico "$svg_source_path" "$windows_target_base_path" # Windows monochrome - generate_ico "$white_svg_source_path" "$WINDOWS_DIR/${icon_name}_white.ico" - generate_ico "$black_svg_source_path" "$WINDOWS_DIR/${icon_name}_black.ico" + generate_ico "$white_svg_source_path" "${windows_target_base_path}_white" + generate_ico "$black_svg_source_path" "${windows_target_base_path}_black" rm "$black_svg_source_path" "$white_svg_source_path" } diff --git a/gui/src/main/account.ts b/gui/src/main/account.ts index 00a3bf0dfd..564880fe61 100644 --- a/gui/src/main/account.ts +++ b/gui/src/main/account.ts @@ -1,3 +1,4 @@ +import { closeToExpiry } from '../shared/account-expiry'; import { AccountToken, DeviceEvent, @@ -11,6 +12,7 @@ import log from '../shared/logging'; import { AccountExpiredNotificationProvider, CloseToAccountExpiryNotificationProvider, + SystemNotificationCategory, } from '../shared/notifications/notification'; import { Scheduler } from '../shared/scheduler'; import AccountDataCache from './account-data-cache'; @@ -210,6 +212,9 @@ export default class Account { const remainingMilliseconds = new Date(this.accountData.expiry).getTime() - Date.now(); const delay = Math.min(twelveHours, remainingMilliseconds); this.accountExpiryNotificationScheduler.schedule(() => this.handleAccountExpiry(), delay); + } else if (!closeToExpiry(this.accountData.expiry)) { + // If no longer close to expiry, all previous notifications should be closed + this.delegate.closeNotificationsInCategory(SystemNotificationCategory.expiry); } } } diff --git a/gui/src/main/index.ts b/gui/src/main/index.ts index 40f9054958..7181f863bf 100644 --- a/gui/src/main/index.ts +++ b/gui/src/main/index.ts @@ -20,7 +20,10 @@ import { ITranslations, MacOsScrollbarVisibility } from '../shared/ipc-schema'; import { IChangelog, IHistoryObject } from '../shared/ipc-types'; import log, { ConsoleOutput, Logger } from '../shared/logging'; import { LogLevel } from '../shared/logging-types'; -import { SystemNotification } from '../shared/notifications/notification'; +import { + SystemNotification, + SystemNotificationCategory, +} from '../shared/notifications/notification'; import Account, { AccountDelegate, LocaleProvider } from './account'; import { getOpenAtLogin } from './autostart'; import { readChangelog } from './changelog'; @@ -211,14 +214,6 @@ class ApplicationMain public isLoggedIn = () => this.account.isLoggedIn(); - public notify = (notification: SystemNotification) => { - this.notificationController.notify( - notification, - this.userInterface?.isWindowVisible() ?? false, - this.settings.gui.enableSystemNotifications, - ); - }; - public disconnectAndQuit = async () => { if (this.daemonRpc.isConnected) { try { @@ -316,6 +311,7 @@ class ApplicationMain log.info('Quit initiated'); this.userInterface?.dispose(); + this.notificationController.dispose(); // Unsubscribe the event handler try { @@ -945,12 +941,22 @@ class ApplicationMain return shell.openExternal(url); } }; + public showNotificationIcon = (value: boolean) => this.userInterface?.showNotificationIcon(value); + + // NotificationSender + public notify = (notification: SystemNotification) => { + this.notificationController.notify( + notification, + this.userInterface?.isWindowVisible() ?? false, + this.settings.gui.enableSystemNotifications, + ); + }; + public closeNotificationsInCategory = (category: SystemNotificationCategory) => + this.notificationController.closeNotificationsInCategory(category); // UserInterfaceDelegate - public cancelPendingNotifications = () => - this.notificationController.cancelPendingNotifications(); - public resetTunnelStateAnnouncements = () => - this.notificationController.resetTunnelStateAnnouncements(); + public dismissActiveNotifications = () => + this.notificationController.dismissActiveNotifications(); public isUnpinnedWindow = () => this.settings.gui.unpinnedWindow; public updateAccountData = () => this.account.updateAccountData(); public getAccountData = () => this.account.accountData; @@ -980,7 +986,7 @@ class ApplicationMain // SettingsDelegate public handleMonochromaticIconChange = (value: boolean) => - this.userInterface?.setUseMonochromaticTrayIcon(value) ?? Promise.resolve(); + this.userInterface?.setMonochromaticIcon(value) ?? Promise.resolve(); public handleUnpinnedWindowChange = () => void this.userInterface?.recreateWindow( this.account.isLoggedIn(), diff --git a/gui/src/main/notification-controller.ts b/gui/src/main/notification-controller.ts index 3ea65fa5a0..6fbe6d4f19 100644 --- a/gui/src/main/notification-controller.ts +++ b/gui/src/main/notification-controller.ts @@ -1,4 +1,4 @@ -import { app, NativeImage, nativeImage, Notification } from 'electron'; +import { app, NativeImage, nativeImage, Notification as ElectronNotification } from 'electron'; import os from 'os'; import path from 'path'; @@ -12,23 +12,45 @@ import { NotificationAction, ReconnectingNotificationProvider, SystemNotification, + SystemNotificationCategory, SystemNotificationProvider, + SystemNotificationSeverityType, } from '../shared/notifications/notification'; +import { Scheduler } from '../shared/scheduler'; + +const THROTTLE_DELAY = 500; + +export interface Notification { + specification: SystemNotification; + notification: ElectronNotification; +} export interface NotificationSender { notify(notification: SystemNotification): void; + closeNotificationsInCategory(category: SystemNotificationCategory): void; } export interface NotificationControllerDelegate { openApp(): void; openLink(url: string, withAuth?: boolean): Promise<void>; + showNotificationIcon(value: boolean): void; +} + +enum NotificationSuppressReason { + development, + windowVisible, + preference, + alreadyPresented, } export default class NotificationController { - private lastTunnelStateAnnouncement?: { body: string; notification: Notification }; private reconnecting = false; + private presentedNotifications: { [key: string]: boolean } = {}; - private pendingNotifications: Notification[] = []; + private activeNotifications: Set<Notification> = new Set(); + private dismissedNotifications: Set<SystemNotification> = new Set(); + private throttledNotifications: Map<SystemNotification, Scheduler> = new Map(); + private notificationTitle = process.platform === 'linux' ? app.name : ''; private notificationIcon?: NativeImage; @@ -50,6 +72,13 @@ export default class NotificationController { } } + public dispose() { + this.throttledNotifications.forEach((scheduler) => scheduler.cancel()); + + this.activeNotifications.forEach((notification) => notification.notification.close()); + this.activeNotifications.clear(); + } + public notifyTunnelState( tunnelState: TunnelState, blockWhenDisconnected: boolean, @@ -73,61 +102,119 @@ export default class NotificationController { const notification = notificationProvider.getSystemNotification(); if (notification) { - this.showTunnelStateNotification( - notification, - isWindowVisible, - areSystemNotificationsEnabled, - ); + this.notify(notification, isWindowVisible, areSystemNotificationsEnabled); } else { log.error( `Notification providers mayDisplay() returned true but getSystemNotification() returned undefined for ${notificationProvider.constructor.name}`, ); } + } else { + this.closeNotificationsInCategory(SystemNotificationCategory.tunnelState); } this.reconnecting = tunnelState.state === 'disconnecting' && tunnelState.details === 'reconnect'; } - public cancelPendingNotifications() { - for (const notification of this.pendingNotifications) { - notification.close(); - } + // Closes still relevant notifications but still lets them affect notification dot in tray icon. + public dismissActiveNotifications() { + this.activeNotifications.forEach((notification) => { + notification.notification.close(); + }); + this.updateNotificationIcon(); } - public resetTunnelStateAnnouncements() { - this.lastTunnelStateAnnouncement = undefined; + public closeNotificationsInCategory( + category: SystemNotificationCategory, + severity?: SystemNotificationSeverityType, + ) { + this.activeNotifications.forEach((notification) => { + if (notification.specification.category === category) { + notification.notification.close(); + } + }); + this.dismissedNotifications.forEach((notification) => { + if ( + notification.category === category && + (severity === undefined || severity >= notification.severity) + ) { + this.dismissedNotifications.delete(notification); + } + }); + this.updateNotificationIcon(); } public notify( systemNotification: SystemNotification, - isWindowVisible: boolean, - areSystemNotificationsEnabled: boolean, + windowVisible: boolean, + infoNotificationsEnabled: boolean, ) { - if ( - this.evaluateNotification(systemNotification, isWindowVisible, areSystemNotificationsEnabled) - ) { - const notification = this.createNotification(systemNotification); - this.addPendingNotification(notification); - notification.show(); - - if (!systemNotification.critical) { - setTimeout(() => notification.close(), 4000); + const notificationSuppressReason = this.evaluateNotification( + systemNotification, + windowVisible, + infoNotificationsEnabled, + ); + if (notificationSuppressReason !== undefined) { + if ( + notificationSuppressReason === NotificationSuppressReason.preference || + notificationSuppressReason === NotificationSuppressReason.windowVisible + ) { + this.dismissedNotifications.add(systemNotification); + this.updateNotificationIcon(); } - return notification; - } else { return; } + + // Cancel throttled notifications within the same category + if (systemNotification.category !== undefined) { + this.throttledNotifications.forEach((scheduler, specification) => { + if (specification.category === systemNotification.category) { + scheduler.cancel(); + this.throttledNotifications.delete(specification); + } + }); + } + + if (systemNotification.throttle) { + const scheduler = new Scheduler(); + scheduler.schedule(() => { + this.throttledNotifications.delete(systemNotification); + this.notifyImpl(systemNotification); + }, THROTTLE_DELAY); + + this.throttledNotifications.set(systemNotification, scheduler); + } else { + this.notifyImpl(systemNotification); + } + } + + private notifyImpl(systemNotification: SystemNotification): Notification { + // Remove notifications in the same category if specified + if (systemNotification.category !== undefined) { + this.closeNotificationsInCategory(systemNotification.category, systemNotification.severity); + } + + const notification = this.createNotification(systemNotification); + this.addActiveNotification(notification); + notification.notification.show(); + + // Close notification of low severity automatically + if (systemNotification.severity === SystemNotificationSeverityType.info) { + setTimeout(() => notification.notification.close(), 4000); + } + + return notification; } - private createNotification(systemNotification: SystemNotification) { - const notification = new Notification({ + private createNotification(systemNotification: SystemNotification): Notification { + const notification = new ElectronNotification({ title: this.notificationTitle, body: systemNotification.message, silent: true, icon: this.notificationIcon, - timeoutType: systemNotification.critical ? 'never' : 'default', + timeoutType: + systemNotification.severity == SystemNotificationSeverityType.high ? 'never' : 'default', }); // Action buttons are only available on macOS. @@ -137,7 +224,12 @@ export default class NotificationController { notification.on('action', () => this.performAction(systemNotification.action)); } notification.on('click', () => this.notificationControllerDelegate.openApp()); - } else if (!(process.platform === 'win32' && systemNotification.critical)) { + } else if ( + !( + process.platform === 'win32' && + systemNotification.severity === SystemNotificationSeverityType.high + ) + ) { if (systemNotification.action) { notification.on('click', () => this.performAction(systemNotification.action)); } else { @@ -145,7 +237,7 @@ export default class NotificationController { } } - return notification; + return { specification: systemNotification, notification }; } private performAction(action?: NotificationAction) { @@ -154,68 +246,53 @@ export default class NotificationController { } } - private showTunnelStateNotification( - systemNotification: SystemNotification, - isWindowVisible: boolean, - areSystemNotificationsEnabled: boolean, - ) { - const message = systemNotification.message; - const lastAnnouncement = this.lastTunnelStateAnnouncement; - const sameAsLastNotification = lastAnnouncement && lastAnnouncement.body === message; - - if (sameAsLastNotification) { - return; - } + private addActiveNotification(notification: Notification) { + notification.notification.on('close', () => { + this.dismissedNotifications.add({ ...notification.specification }); + this.activeNotifications.delete(notification); + this.updateNotificationIcon(); + }); + this.activeNotifications.add(notification); + this.updateNotificationIcon(); + } - if (lastAnnouncement) { - lastAnnouncement.notification.close(); + private updateNotificationIcon() { + for (const notification of this.activeNotifications) { + if (notification.specification.severity >= SystemNotificationSeverityType.medium) { + this.notificationControllerDelegate.showNotificationIcon(true); + return; + } } - const newNotification = this.notify( - systemNotification, - isWindowVisible, - areSystemNotificationsEnabled, - ); - - if (newNotification) { - this.lastTunnelStateAnnouncement = { - body: message, - notification: newNotification, - }; + for (const notification of this.dismissedNotifications) { + if (notification.severity >= SystemNotificationSeverityType.medium) { + this.notificationControllerDelegate.showNotificationIcon(true); + return; + } } - } - - private addPendingNotification(notification: Notification) { - notification.on('close', () => { - this.removePendingNotification(notification); - }); - - this.pendingNotifications.push(notification); - } - private removePendingNotification(notification: Notification) { - const index = this.pendingNotifications.indexOf(notification); - if (index !== -1) { - this.pendingNotifications.splice(index, 1); - } + this.notificationControllerDelegate.showNotificationIcon(false); } private evaluateNotification( notification: SystemNotification, isWindowVisible: boolean, areSystemNotificationsEnabled: boolean, - ) { - const suppressDueToDevelopment = - notification.suppressInDevelopment && process.env.NODE_ENV === 'development'; - const suppressDueToVisibleWindow = isWindowVisible; - const suppressDueToPreference = !areSystemNotificationsEnabled && !notification.critical; + ): NotificationSuppressReason | undefined { + if (notification.suppressInDevelopment && process.env.NODE_ENV === 'development') { + return NotificationSuppressReason.development; + } else if (isWindowVisible) { + return NotificationSuppressReason.windowVisible; + } else if ( + !areSystemNotificationsEnabled && + notification.severity >= SystemNotificationSeverityType.low + ) { + return NotificationSuppressReason.preference; + } else if (this.suppressDueToAlreadyPresented(notification)) { + return NotificationSuppressReason.alreadyPresented; + } - return ( - !suppressDueToDevelopment && - !suppressDueToVisibleWindow && - !suppressDueToPreference && - !this.suppressDueToAlreadyPresented(notification) - ); + return undefined; } private suppressDueToAlreadyPresented(notification: SystemNotification) { diff --git a/gui/src/main/settings.ts b/gui/src/main/settings.ts index 26fd14e0fa..634a9109ee 100644 --- a/gui/src/main/settings.ts +++ b/gui/src/main/settings.ts @@ -9,7 +9,7 @@ import GuiSettings from './gui-settings'; import { IpcMainEventChannel } from './ipc-event-channel'; export interface SettingsDelegate { - handleMonochromaticIconChange(value: boolean): Promise<void>; + handleMonochromaticIconChange(value: boolean): void; handleUnpinnedWindowChange(): void; } @@ -139,9 +139,9 @@ export default class Settings implements Readonly<ISettings> { } private registerGuiSettingsListener() { - this.guiSettings.onChange = async (newState, oldState) => { + this.guiSettings.onChange = (newState, oldState) => { if (oldState.monochromaticIcon !== newState.monochromaticIcon) { - await this.delegate.handleMonochromaticIconChange(newState.monochromaticIcon); + this.delegate.handleMonochromaticIconChange(newState.monochromaticIcon); } if (newState.autoConnect !== oldState.autoConnect) { diff --git a/gui/src/main/tray-icon-controller.ts b/gui/src/main/tray-icon-controller.ts index cee57c0161..df474bdc1b 100644 --- a/gui/src/main/tray-icon-controller.ts +++ b/gui/src/main/tray-icon-controller.ts @@ -10,24 +10,23 @@ const exec = promisify(execAsync); export type TrayIconType = 'unsecured' | 'securing' | 'secured'; -type IconSets = { - regular: NativeImage[]; - template: NativeImage[]; - white: NativeImage[]; - black: NativeImage[]; -}; +type IconParameters = { monochromatic: boolean; notification: boolean }; export default class TrayIconController { private animation?: KeyframeAnimation; - private iconSets: IconSets = { regular: [], template: [], white: [], black: [] }; private iconSet: NativeImage[] = []; + private iconParameters: IconParameters; + + private updateThrottlePromise?: Promise<void>; constructor( private tray: Tray, private iconTypeValue: TrayIconType, - private useMonochromaticIconValue: boolean, + monochromaticIcon: boolean, + notificationIcon: boolean, ) { - this.loadImages(); + this.iconParameters = { monochromatic: monochromaticIcon, notification: notificationIcon }; + void this.updateTheme(); } public dispose() { @@ -41,39 +40,25 @@ export default class TrayIconController { return this.iconTypeValue; } - public async updateTheme() { - if (this.useMonochromaticIconValue) { - switch (process.platform) { - case 'darwin': - this.iconSet = this.iconSets.template; - break; - case 'win32': { - if (await this.getSystemUsesLightTheme()) { - this.iconSet = this.iconSets.black; - } else { - this.iconSet = this.iconSets.white; - } - break; - } - case 'linux': - default: - this.iconSet = this.iconSets.white; - break; - } - } else { - this.iconSet = this.iconSets.regular; - } + public updateTheme(): Promise<void> { + // For some reason the icon doesn't update if the iconSet is changed to quickly. Adding a + // throttle fixes this issue. + this.updateThrottlePromise ??= new Promise((resolve) => { + setTimeout(() => { + this.updateThrottlePromise = undefined; + void this.updateThemeImpl().then(resolve); + }, 200); + }); - if (this.animation === undefined) { - this.initAnimation(); - } else if (!this.animation.isRunning) { - this.animation.play({ end: this.targetFrame() }); - } + return this.updateThrottlePromise; } - public async setUseMonochromaticIcon(useMonochromaticIcon: boolean) { - this.useMonochromaticIconValue = useMonochromaticIcon; - await this.updateTheme(); + public setMonochromaticIcon(monochromaticIcon: boolean) { + void this.updateIconParameters({ monochromatic: monochromaticIcon }); + } + + public showNotificationIcon(notificationIcon: boolean) { + void this.updateIconParameters({ notification: notificationIcon }); } public animateToIcon(type: TrayIconType) { @@ -89,6 +74,30 @@ export default class TrayIconController { animation.play({ end: frame }); } + private async updateThemeImpl() { + const systemUsesLightTheme = await this.getSystemUsesLightTheme(); + this.iconSet = this.loadImages(systemUsesLightTheme); + + if (this.animation === undefined) { + this.initAnimation(); + } else if (!this.animation.isRunning) { + this.animation.play({ end: this.targetFrame() }); + } + } + + // This function uses a promise as a lock to prevent multiple simultaneous updates + private updateIconParameters(parameters: Partial<IconParameters>) { + if ( + (parameters.monochromatic !== undefined && + parameters.monochromatic !== this.iconParameters.monochromatic) || + (parameters.notification !== undefined && + parameters.notification !== this.iconParameters.notification) + ) { + this.iconParameters = { ...this.iconParameters, ...parameters }; + void this.updateTheme(); + } + } + private initAnimation() { const initialFrame = this.targetFrame(); const animation = new KeyframeAnimation(); @@ -108,21 +117,22 @@ export default class TrayIconController { } }; - private loadImages() { - this.iconSets.regular = this.loadImageSet(''); - - switch (process.platform) { - case 'darwin': - this.iconSets.template = this.loadImageSet('Template'); - break; - case 'win32': - this.iconSets.white = this.loadImageSet('_white'); - this.iconSets.black = this.loadImageSet('_black'); - break; - case 'linux': - default: - this.iconSets.white = this.loadImageSet('_white'); - break; + private loadImages(systemUsesLightTheme?: boolean): NativeImage[] { + const notificationIcon = this.iconParameters.notification ? '_notification' : ''; + if (this.iconParameters.monochromatic) { + switch (process.platform) { + case 'darwin': + return this.loadImageSet(`${notificationIcon}Template`); + case 'win32': + return systemUsesLightTheme + ? this.loadImageSet(`_black${notificationIcon}`) + : this.loadImageSet(`_white${notificationIcon}`); + case 'linux': + default: + return this.loadImageSet(`_white${notificationIcon}`); + } + } else { + return this.loadImageSet(notificationIcon); } } @@ -138,6 +148,10 @@ export default class TrayIconController { } private async getSystemUsesLightTheme(): Promise<boolean | undefined> { + if (process.platform !== 'win32') { + return undefined; + } + try { // This registry entry contains information about the tray background color. This is // needed to decide between white and black icons. diff --git a/gui/src/main/user-interface.ts b/gui/src/main/user-interface.ts index 78af002c58..bc239cec2c 100644 --- a/gui/src/main/user-interface.ts +++ b/gui/src/main/user-interface.ts @@ -25,8 +25,7 @@ import WindowController, { WindowControllerDelegate } from './window-controller' const execAsync = promisify(exec); export interface UserInterfaceDelegate { - cancelPendingNotifications(): void; - resetTunnelStateAnnouncements(): void; + dismissActiveNotifications(): void; updateAccountData(): void; connectTunnel(): void; reconnectTunnel(): void; @@ -91,7 +90,7 @@ export default class UserInterface implements WindowControllerDelegate { monochromaticIcon: boolean, ) { const iconType = this.trayIconType(tunnelState, blockWhenDisconnected); - this.trayIconController = new TrayIconController(this.tray, iconType, monochromaticIcon); + this.trayIconController = new TrayIconController(this.tray, iconType, monochromaticIcon, false); } public async initializeWindow(isLoggedIn: boolean, tunnelState: TunnelState) { @@ -185,9 +184,11 @@ export default class UserInterface implements WindowControllerDelegate { public reloadWindow = () => this.windowController.window?.reload(); public isWindowVisible = () => this.windowController.isVisible(); public showWindow = () => this.windowController.show(); - public updateTrayTheme = () => this.trayIconController?.updateTheme(); - public setUseMonochromaticTrayIcon = (value: boolean) => - this.trayIconController?.setUseMonochromaticIcon(value); + public updateTrayTheme = () => this.trayIconController?.updateTheme() ?? Promise.resolve(); + public setMonochromaticIcon = (value: boolean) => + this.trayIconController?.setMonochromaticIcon(value); + public showNotificationIcon = (value: boolean) => + this.trayIconController?.showNotificationIcon(value); public setWindowIcon = (icon: string) => this.windowController.window?.setIcon(icon); public updateTrayIcon(tunnelState: TunnelState, blockWhenDisconnected: boolean) { @@ -319,7 +320,7 @@ export default class UserInterface implements WindowControllerDelegate { this.blurNavigationResetScheduler.cancel(); // cancel notifications when window appears - this.delegate.cancelPendingNotifications(); + this.delegate.dismissActiveNotifications(); const accountData = this.delegate.getAccountData(); if (!accountData || closeToExpiry(accountData.expiry, 4) || hasExpired(accountData.expiry)) { @@ -329,9 +330,6 @@ export default class UserInterface implements WindowControllerDelegate { this.windowController.window?.on('blur', () => { IpcMainEventChannel.window.notifyFocus?.(false); - - // ensure notification guard is reset - this.delegate.resetTunnelStateAnnouncements(); }); // Use hide instead of blur to prevent the navigation reset from happening when bluring an diff --git a/gui/src/main/version.ts b/gui/src/main/version.ts index 5e45203c6c..fbe5b64574 100644 --- a/gui/src/main/version.ts +++ b/gui/src/main/version.ts @@ -5,6 +5,7 @@ import { ICurrentAppVersionInfo } from '../shared/ipc-types'; import log from '../shared/logging'; import { InconsistentVersionNotificationProvider, + SystemNotificationCategory, UnsupportedVersionNotificationProvider, UpdateAvailableNotificationProvider, } from '../shared/notifications/notification'; @@ -65,6 +66,8 @@ export default class Version { }); if (notificationProvider.mayDisplay()) { this.delegate.notify(notificationProvider.getSystemNotification()); + } else { + this.delegate.closeNotificationsInCategory(SystemNotificationCategory.inconsistentVersion); } // notify renderer @@ -105,6 +108,8 @@ export default class Version { ); if (notificationProvider) { this.delegate.notify(notificationProvider.getSystemNotification()); + } else { + this.delegate.closeNotificationsInCategory(SystemNotificationCategory.newVersion); } IpcMainEventChannel.upgradeVersion.notify?.(upgradeVersion); diff --git a/gui/src/shared/notifications/account-expired.ts b/gui/src/shared/notifications/account-expired.ts index cbfc782eeb..a7af4f2c8b 100644 --- a/gui/src/shared/notifications/account-expired.ts +++ b/gui/src/shared/notifications/account-expired.ts @@ -2,7 +2,12 @@ import { links } from '../../config.json'; import { hasExpired } from '../account-expiry'; import { TunnelState } from '../daemon-rpc-types'; import { messages } from '../gettext'; -import { SystemNotification, SystemNotificationProvider } from './notification'; +import { + SystemNotification, + SystemNotificationCategory, + SystemNotificationProvider, + SystemNotificationSeverityType, +} from './notification'; interface AccountExpiredNotificaitonContext { accountExpiry: string; @@ -23,7 +28,8 @@ export class AccountExpiredNotificationProvider implements SystemNotificationPro public getSystemNotification(): SystemNotification { return { message: messages.pgettext('notifications', 'Account is out of time'), - critical: true, + category: SystemNotificationCategory.expiry, + severity: SystemNotificationSeverityType.high, presentOnce: { value: true, name: this.constructor.name }, action: { type: 'open-url', diff --git a/gui/src/shared/notifications/block-when-disconnected.ts b/gui/src/shared/notifications/block-when-disconnected.ts index 91b464a299..c0b2f4e0f1 100644 --- a/gui/src/shared/notifications/block-when-disconnected.ts +++ b/gui/src/shared/notifications/block-when-disconnected.ts @@ -3,7 +3,14 @@ import { sprintf } from 'sprintf-js'; import { strings } from '../../config.json'; import { messages } from '../../shared/gettext'; import { TunnelState } from '../daemon-rpc-types'; -import { InAppNotification, InAppNotificationProvider } from './notification'; +import { + InAppNotification, + InAppNotificationProvider, + SystemNotification, + SystemNotificationCategory, + SystemNotificationProvider, + SystemNotificationSeverityType, +} from './notification'; interface BlockWhenDisconnectedNotificationContext { tunnelState: TunnelState; @@ -11,7 +18,8 @@ interface BlockWhenDisconnectedNotificationContext { hasExcludedApps: boolean; } -export class BlockWhenDisconnectedNotificationProvider implements InAppNotificationProvider { +export class BlockWhenDisconnectedNotificationProvider + implements InAppNotificationProvider, SystemNotificationProvider { public constructor(private context: BlockWhenDisconnectedNotificationContext) {} public mayDisplay() { @@ -22,6 +30,16 @@ export class BlockWhenDisconnectedNotificationProvider implements InAppNotificat ); } + public getSystemNotification(): SystemNotification { + const message = messages.pgettext('notifications', 'Lockdown mode active, connection blocked'); + + return { + message, + severity: SystemNotificationSeverityType.info, + category: SystemNotificationCategory.tunnelState, + }; + } + public getInAppNotification(): InAppNotification { const lockdownModeSettingName = messages.pgettext('vpn-settings-view', 'Lockdown mode'); let subtitle = sprintf( diff --git a/gui/src/shared/notifications/close-to-account-expiry.ts b/gui/src/shared/notifications/close-to-account-expiry.ts index 82daf05562..a3f5e749ad 100644 --- a/gui/src/shared/notifications/close-to-account-expiry.ts +++ b/gui/src/shared/notifications/close-to-account-expiry.ts @@ -8,7 +8,9 @@ import { InAppNotification, InAppNotificationProvider, SystemNotification, + SystemNotificationCategory, SystemNotificationProvider, + SystemNotificationSeverityType, } from './notification'; interface CloseToAccountExpiryNotificationContext { @@ -38,7 +40,8 @@ export class CloseToAccountExpiryNotificationProvider return { message, - critical: true, + category: SystemNotificationCategory.expiry, + severity: SystemNotificationSeverityType.medium, action: { type: 'open-url', url: links.purchase, diff --git a/gui/src/shared/notifications/connected.ts b/gui/src/shared/notifications/connected.ts index 5fc667b78c..c66339fe9e 100644 --- a/gui/src/shared/notifications/connected.ts +++ b/gui/src/shared/notifications/connected.ts @@ -2,14 +2,19 @@ import { sprintf } from 'sprintf-js'; import { messages } from '../../shared/gettext'; import { TunnelState } from '../daemon-rpc-types'; -import { SystemNotificationProvider } from './notification'; +import { + SystemNotification, + SystemNotificationCategory, + SystemNotificationProvider, + SystemNotificationSeverityType, +} from './notification'; export class ConnectedNotificationProvider implements SystemNotificationProvider { public constructor(private context: TunnelState) {} public mayDisplay = () => this.context.state === 'connected'; - public getSystemNotification() { + public getSystemNotification(): SystemNotification | undefined { if (this.context.state === 'connected') { let message = messages.pgettext('notifications', 'Connected'); const location = this.context.details.location?.hostname; @@ -27,7 +32,8 @@ export class ConnectedNotificationProvider implements SystemNotificationProvider return { message, - critical: false, + severity: SystemNotificationSeverityType.info, + category: SystemNotificationCategory.tunnelState, }; } else { return undefined; diff --git a/gui/src/shared/notifications/connecting.ts b/gui/src/shared/notifications/connecting.ts index b35d9ed3b6..214e015e10 100644 --- a/gui/src/shared/notifications/connecting.ts +++ b/gui/src/shared/notifications/connecting.ts @@ -5,7 +5,10 @@ import { TunnelState } from '../daemon-rpc-types'; import { InAppNotification, InAppNotificationProvider, + SystemNotification, + SystemNotificationCategory, SystemNotificationProvider, + SystemNotificationSeverityType, } from './notification'; interface ConnectingNotificationContext { @@ -21,7 +24,7 @@ export class ConnectingNotificationProvider return this.context.tunnelState.state === 'connecting' && !this.context.reconnecting; } - public getSystemNotification() { + public getSystemNotification(): SystemNotification | undefined { if (this.context.tunnelState.state === 'connecting') { let message = messages.pgettext('notifications', 'Connecting'); const location = this.context.tunnelState.details?.location?.hostname; @@ -39,7 +42,9 @@ export class ConnectingNotificationProvider return { message, - critical: false, + severity: SystemNotificationSeverityType.info, + category: SystemNotificationCategory.tunnelState, + throttle: true, }; } else { return undefined; diff --git a/gui/src/shared/notifications/disconnected.ts b/gui/src/shared/notifications/disconnected.ts index 05c53148ec..874cb11b3e 100644 --- a/gui/src/shared/notifications/disconnected.ts +++ b/gui/src/shared/notifications/disconnected.ts @@ -1,6 +1,11 @@ import { messages } from '../../shared/gettext'; import { TunnelState } from '../daemon-rpc-types'; -import { SystemNotificationProvider } from './notification'; +import { + SystemNotification, + SystemNotificationCategory, + SystemNotificationProvider, + SystemNotificationSeverityType, +} from './notification'; interface DisconnectedNotificationContext { tunnelState: TunnelState; @@ -13,10 +18,11 @@ export class DisconnectedNotificationProvider implements SystemNotificationProvi public mayDisplay = () => this.context.tunnelState.state === 'disconnected' && !this.context.blockWhenDisconnected; - public getSystemNotification() { + public getSystemNotification(): SystemNotification | undefined { return { message: messages.pgettext('notifications', 'Disconnected and unsecure'), - critical: false, + severity: SystemNotificationSeverityType.info, + category: SystemNotificationCategory.tunnelState, }; } } diff --git a/gui/src/shared/notifications/error.ts b/gui/src/shared/notifications/error.ts index fa1848a0fb..67267a494e 100644 --- a/gui/src/shared/notifications/error.ts +++ b/gui/src/shared/notifications/error.ts @@ -12,7 +12,10 @@ import { messages } from '../gettext'; import { InAppNotification, InAppNotificationProvider, + SystemNotification, + SystemNotificationCategory, SystemNotificationProvider, + SystemNotificationSeverityType, } from './notification'; interface ErrorNotificationContext { @@ -26,7 +29,7 @@ export class ErrorNotificationProvider public mayDisplay = () => this.context.tunnelState.state === 'error'; - public getSystemNotification() { + public getSystemNotification(): SystemNotification | undefined { if (this.context.tunnelState.state === 'error') { let message = getMessage(this.context.tunnelState.details); if (!this.context.tunnelState.details.blockingError && this.context.hasExcludedApps) { @@ -41,7 +44,11 @@ export class ErrorNotificationProvider return { message, - critical: !!this.context.tunnelState.details.blockingError, + severity: + this.context.tunnelState.details.blockingError === undefined + ? SystemNotificationSeverityType.low + : SystemNotificationSeverityType.high, + category: SystemNotificationCategory.tunnelState, }; } else { return undefined; diff --git a/gui/src/shared/notifications/inconsistent-version.ts b/gui/src/shared/notifications/inconsistent-version.ts index e6118c883e..f4a5616c43 100644 --- a/gui/src/shared/notifications/inconsistent-version.ts +++ b/gui/src/shared/notifications/inconsistent-version.ts @@ -3,7 +3,9 @@ import { InAppNotification, InAppNotificationProvider, SystemNotification, + SystemNotificationCategory, SystemNotificationProvider, + SystemNotificationSeverityType, } from './notification'; interface InconsistentVersionNotificationContext { @@ -19,7 +21,8 @@ export class InconsistentVersionNotificationProvider public getSystemNotification(): SystemNotification { return { message: messages.pgettext('notifications', 'App is out of sync. Please quit and restart.'), - critical: true, + category: SystemNotificationCategory.inconsistentVersion, + severity: SystemNotificationSeverityType.high, presentOnce: { value: true, name: this.constructor.name }, suppressInDevelopment: true, }; diff --git a/gui/src/shared/notifications/notification.ts b/gui/src/shared/notifications/notification.ts index 2152da0e79..10b5b21fc8 100644 --- a/gui/src/shared/notifications/notification.ts +++ b/gui/src/shared/notifications/notification.ts @@ -7,13 +7,29 @@ export type NotificationAction = { export type InAppNotificationIndicatorType = 'success' | 'warning' | 'error'; +export enum SystemNotificationSeverityType { + info = 0, + low, + medium, + high, +} + +export enum SystemNotificationCategory { + tunnelState, + expiry, + newVersion, + inconsistentVersion, +} + interface NotificationProvider { mayDisplay(): boolean; } export interface SystemNotification { message: string; - critical: boolean; + severity: SystemNotificationSeverityType; + category: SystemNotificationCategory; + throttle?: boolean; presentOnce?: { value: boolean; name: string }; suppressInDevelopment?: boolean; action?: NotificationAction; diff --git a/gui/src/shared/notifications/reconnecting.ts b/gui/src/shared/notifications/reconnecting.ts index 9c20cad8c9..43491322f0 100644 --- a/gui/src/shared/notifications/reconnecting.ts +++ b/gui/src/shared/notifications/reconnecting.ts @@ -3,7 +3,10 @@ import { TunnelState } from '../daemon-rpc-types'; import { InAppNotification, InAppNotificationProvider, + SystemNotification, + SystemNotificationCategory, SystemNotificationProvider, + SystemNotificationSeverityType, } from './notification'; export class ReconnectingNotificationProvider @@ -14,10 +17,12 @@ export class ReconnectingNotificationProvider return this.context.state === 'disconnecting' && this.context.details === 'reconnect'; } - public getSystemNotification() { + public getSystemNotification(): SystemNotification | undefined { return { message: messages.pgettext('notifications', 'Reconnecting'), - critical: false, + severity: SystemNotificationSeverityType.info, + category: SystemNotificationCategory.tunnelState, + throttle: true, }; } diff --git a/gui/src/shared/notifications/unsupported-version.ts b/gui/src/shared/notifications/unsupported-version.ts index 3db1db9fc7..8c2f87460b 100644 --- a/gui/src/shared/notifications/unsupported-version.ts +++ b/gui/src/shared/notifications/unsupported-version.ts @@ -4,7 +4,9 @@ import { InAppNotification, InAppNotificationProvider, SystemNotification, + SystemNotificationCategory, SystemNotificationProvider, + SystemNotificationSeverityType, } from './notification'; interface UnsupportedVersionNotificationContext { @@ -25,7 +27,8 @@ export class UnsupportedVersionNotificationProvider public getSystemNotification(): SystemNotification { return { message: this.getMessage(), - critical: true, + category: SystemNotificationCategory.newVersion, + severity: SystemNotificationSeverityType.high, action: { type: 'open-url', url: this.context.suggestedIsBeta ? links.betaDownload : links.download, diff --git a/gui/src/shared/notifications/update-available.ts b/gui/src/shared/notifications/update-available.ts index 61a2452138..0394ef15a5 100644 --- a/gui/src/shared/notifications/update-available.ts +++ b/gui/src/shared/notifications/update-available.ts @@ -6,7 +6,9 @@ import { InAppNotification, InAppNotificationProvider, SystemNotification, + SystemNotificationCategory, SystemNotificationProvider, + SystemNotificationSeverityType, } from './notification'; interface UpdateAvailableNotificationContext { @@ -39,7 +41,8 @@ export class UpdateAvailableNotificationProvider public getSystemNotification(): SystemNotification { return { message: this.systemMessage(), - critical: false, + category: SystemNotificationCategory.newVersion, + severity: SystemNotificationSeverityType.medium, action: { type: 'open-url', url: this.context.suggestedIsBeta ? links.betaDownload : links.download, diff --git a/gui/tasks/distribution.js b/gui/tasks/distribution.js index d3d6ad6dc6..e5dc6fd320 100644 --- a/gui/tasks/distribution.js +++ b/gui/tasks/distribution.js @@ -86,7 +86,7 @@ const config = { icon: distAssets('icon-macos.icns'), extendInfo: { LSUIElement: true, - NSUserNotificationAlertStyle: 'alert', + NSUserNotificationAlertStyle: 'banner', }, extraResources: [ { from: distAssets(path.join('${env.TARGET_TRIPLE}', 'mullvad')), to: '.' }, |
