├── .gitignore
├── LICENSE.txt
├── README.md
├── media
├── demo-alfred-keyword-trigger.png
├── demo-notification-dismisser-in-action-1.gif
└── demo-notification-dismisser-in-action-2.gif
└── src
└── dismiss-active-notifications.applescript
/.gitignore:
--------------------------------------------------------------------------------
1 | ### macOS ###
2 | # General
3 | .DS_Store
4 | .AppleDouble
5 | .LSOverride
6 |
7 | # Icon must end with two \r
8 | Icon
9 |
10 | # Thumbnails
11 | ._*
12 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 zakyum
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Notification Dismisser
2 | >*Ever opened your Mac, just to have a million notifications pop up in you face and didn't feel like manually closing all of them? Or didn't feel like lifting your fingers from the keyboard (and wasting precious seconds!) just to dismiss a random notification from your boss?*
3 | \
4 | \
5 | *Then you've come to the right place!*
6 |
7 |
8 | ## About
9 | Simple Alfred workflow to dismiss all active (currently visible) notifications.
10 | - **Without using the mouse**, either by pressing a shortcut or typing a keyword into Alfred.
11 | - **No external dependencies**, just a bit of AppleScript.
12 |
13 | ## Demo
14 |
15 |
16 | ### Brief Explanation:
17 | 1. Shortcut is pressed.
18 | 2. Banner notifications are dismissed. In this example, the "Script Editor" notification.
19 | 3. Alert notifications are dismissed one-by-one.
20 | 4. Relax and enjoy your precious saved seconds 😌.
21 |
22 |
23 | ## Installing
24 | 1. Click this [download](https://github.com/zakyum/alfred-notification-dismisser/releases/download/v1.0.0/alfred-notification-dismisser.alfredworkflow) button or navigate to this project's releases page.
25 | 2. Double-click the downloaded workflow and import into Alfred.
26 | 3. Open the workflow and set a keyboard shortcut. [optional]
27 |
28 | ## Usage
29 | Launch the workflow by pressing the keyboard shortcut or by typing "dismiss" into Alfred.
30 | 
31 |
32 | ## Specifics
33 | - All the work is done via the AppleScript, the Alfred workflow only runs the script.
34 | - Dismisses only the active/visible notifications on the screen, doesn't touch the notifications in notification center.
35 | - Dismisses alert notifications only if they have a close button, otherwise displays error.
36 | - Detects stuck notifications and displays error, but if there are currently more than 20 notifications will cause a false positive (reason why documented in code).
37 |
38 | ## FAQ
39 | - **Q:** How are banner notifications dismissed if they don't have any buttons?\
40 | **A:** Banner notifications are cleared on notification center restart, so we "dismiss" them by restarting notification center. As far as I know, there is no way to dismiss banner notifications via GUI (AppleScript).
41 |
42 | - **Q:** Why are alert notifications closed one by one?\
43 | **A:** Alert notifications persist notification center restarts and, as far as I know, there isn't a way to batch close them, so we do it via GUI one by one.
44 |
45 | ## License
46 | [MIT License](./LICENSE.txt)
47 |
--------------------------------------------------------------------------------
/media/demo-alfred-keyword-trigger.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zakyum/alfred-notification-dismisser/e9cb4434c84880a7adda124f1c756f6481ee73c5/media/demo-alfred-keyword-trigger.png
--------------------------------------------------------------------------------
/media/demo-notification-dismisser-in-action-1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zakyum/alfred-notification-dismisser/e9cb4434c84880a7adda124f1c756f6481ee73c5/media/demo-notification-dismisser-in-action-1.gif
--------------------------------------------------------------------------------
/media/demo-notification-dismisser-in-action-2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zakyum/alfred-notification-dismisser/e9cb4434c84880a7adda124f1c756f6481ee73c5/media/demo-notification-dismisser-in-action-2.gif
--------------------------------------------------------------------------------
/src/dismiss-active-notifications.applescript:
--------------------------------------------------------------------------------
1 | my dismissActiveNotifications()
2 |
3 | on dismissActiveNotifications()
4 | set nDismissedNotifications to 0
5 |
6 | repeat # until there are none notifications left
7 | my checkIfNotificationStuck(nDismissedNotifications)
8 |
9 | set notification to my getFirstNotification()
10 | if notification is missing value then
11 | log "No notifications, done"
12 | return
13 | end if
14 |
15 | # notification have to be closed differently based on type
16 | tell application "System Events" ¬
17 | to set notificationType to role description of notification
18 |
19 | if notificationType contains "alert" then
20 | my dismissAlertNotification(notification)
21 | else if notificationType contains "banner" then
22 | my dismissAllBannerNotifications()
23 | else # something weird
24 | display notification "Manual closing required" ¬
25 | with title "Error: non-standard notification"
26 | error "Error: unknown notification type"
27 | end if
28 |
29 | set nDismissedNotifications to (nDismissedNotifications + 1)
30 | end repeat
31 | end dismissActiveNotifications
32 |
33 | on getFirstNotification()
34 | tell application "System Events" ¬
35 | to set notificationWindows to windows of process "Notification Center"
36 |
37 | if ((count notificationWindows) < 1) then
38 | return missing value
39 | end if
40 |
41 | set notification to first item of notificationWindows
42 |
43 | # if notification center is open, then it occupies the first window and
44 | #+ is a false positive, in that case we try to get the 2nd window
45 | set isNotificationCenterOpen to ((name of notification) is "Notification Center")
46 | if isNotificationCenterOpen then
47 | log "Notification center is open"
48 |
49 | # if another window exists then it is a genuine notification
50 | if ((count notificationWindows) > 1) then
51 | set notification to second item of notificationWindows
52 | else
53 | return missing value
54 | end if
55 | end if
56 |
57 | return notification
58 | end getFirstNotification
59 |
60 | on dismissAlertNotification(notification)
61 | tell application "System Events" ¬
62 | to set closeButton to a reference to button "Close" of notification
63 |
64 | if closeButton exists then
65 | log "Dismissing an alert notification"
66 | tell application "System Events" to click closeButton
67 | delay 0.2 # wait (approximately) for it to disappear
68 | else
69 | # some applications make custom alert notifications without a close
70 | #+ button (e.g. System Preferences with its update alert)
71 | display notification "Manual closing required" ¬
72 | with title "Error: notification has no close button"
73 | error "Error: can't close alert notification, no close button"
74 | end if
75 | end dismissAlertNotification
76 |
77 | on dismissAllBannerNotifications()
78 | log "Dismissing all banner notifications"
79 |
80 | # banner notifications don't have any buttons so our
81 | #+ only option is to "restart" the notification center
82 | # restarting it removes all banner notifications
83 | do shell script "killall NotificationCenter"
84 |
85 | # wait for NotificationCenter to "restart" so that we can
86 | #+ normally process any remaining notifications (i.e. alert
87 | #+ notifications as they persist restarts)
88 | delay 1
89 | end dismissAllBannerNotifications
90 |
91 | on checkIfNotificationStuck(nDismissedNotifications)
92 | # if we dismiss (or think we dismissed) more than 20 notifications
93 | #+ abort as then there is a high probabily that a notification got
94 | #+ stuck, then abort
95 | set isNotificationStuck to (nDismissedNotifications > 20)
96 | if isNotificationStuck then
97 | display notification "Manual closing required" ¬
98 | with title "Error: can't close notifications"
99 | error "Error: can't close notifications, possibly a stuck notification"
100 | end if
101 | end checkIfNotificationStuck
--------------------------------------------------------------------------------