Durante mucho tiempo he usado un Applescript activado desde un atajo de teclado para descartar notificaciones en MacOS. Funcionó simulando un clic en el botón "cerrar" de cada ventana abierta del Centro de notificaciones.
Desde la actualización a Big Sur (actualmente 11.0.1), las notificaciones ya no tienen un botón de cierre. En su lugar, cuando pasa el mouse sobre ellos, aparecerá un botón "X". Para una persona que tiene dificultad para hacer clic con precisión (tengo un ligero temblor en la mano), usar el mouse/panel táctil es difícil.
¿Alguien tiene sugerencias sobre cómo restaurar esa funcionalidad para poder mantener mis manos en el teclado?
Estoy usando Automator para probar esto.
En Preferencias del Sistema > Notificaciones , seleccioné Automator :
test 1
, test 2
y test 3
.subtitle 1
, subtitle 2
y subtitle 3
.message 1
, message 2
y message 3
.test 3
es completamente visible y tiene la anotación "2 notificaciones más" en la parte inferior.#!/usr/bin/osascript
al inicio del script y la guardé como andrew.applescript
.chmod 755 andrew.applescript
)../andrew.applescript
)test 3
, test 2
y test 1
se apilan de arriba a abajo en el área de notificación./andrew.applescript:370:377: execution error: System Events got an error: Can’t get action "Name:Clear All
Target:0x60000116ff20
Selector:_internal_handleCustomActionWithUiAction:" of group 1 of UI element 1 of scroll area 1 of window "Notification Center" of application process "NotificationCenter". (-1728)
Intentaré jugar con él para ver si puedo hacerlo funcionar con modificaciones.
Nota: si vuelvo a ejecutar el script, comenzando desde el estado desagrupado:
test 3
)action Name:Close
Target:0x60000116ff20
Selector:_internal_handleCustomActionWithUiAction: of group 1 of UI element 1 of scroll area 1 of window Notification Center of application process NotificationCenter
Estoy publicando una versión más robusta que evolucionó desde mi publicación inicial. Esto parece hacer un trabajo razonable al cerrar todas las ventanas, pero a veces es lento de ejecutar. Como dije en los comentarios, no sé mucho sobre AppleScript, por lo que quizás alguien que sepa lo que está haciendo pueda decirnos cómo mejorar el rendimiento.
activate application "NotificationCenter"
tell application "System Events"
tell process "Notification Center"
repeat
try
set theWindow to group 1 of UI element 1 of scroll area 1 of window "Notification Center"
on error
exit repeat
end try
try
set theActions to actions of theWindow
# Try to close the whole group first. If that fails, close individual windows.
repeat with theAction in theActions
if description of theAction is "Clear All" then
set closed to true
tell theWindow
perform theAction
end tell
exit repeat
end if
end repeat
repeat with theAction in theActions
if description of theAction is "Close" then
set closed to true
tell theWindow
perform theAction
end tell
exit repeat
end if
end repeat
end try
end repeat
end tell
end tell
Sí, gracias por publicar el guión, @AndrewJanian.
Recibí un error similar al de @ColinFraizer cuando lo usé tal cual. Creo que el problema es la repetición interna de las acciones: intenta acceder a las acciones en algunos casos después de cerrar la ventana. Un ajuste menor soluciona este problema para mí:
activate application "NotificationCenter"
tell application "System Events"
tell process "Notification Center"
set theWindow to group 1 of UI element 1 of scroll area 1 of window "Notification Center"
# click theWindow
set theActions to actions of theWindow
repeat with theAction in theActions
if description of theAction is "Close" then
tell theWindow
perform theAction
end tell
exit repeat
end if
end repeat
end tell
end tell
set theWindow
línea existente conset theWindow to group 1 of UI element 1 of scroll area 1 of UI element 1 of window "Notification Center"
Tengo un AppleScript que funciona. Encontré los elementos usando UIBrowser . La advertencia es que la notificación debe tener una acción "Cerrar". Todas las notificaciones que he encontrado tienen esa acción.
activate application "NotificationCenter"
tell application "System Events"
tell process "Notification Center"
set theWindow to group 1 of UI element 1 of scroll area 1 of window "Notification Center"
click theWindow
set theActions to actions of theWindow
repeat with theAction in theActions
if description of theAction is "Close" then
tell theWindow
perform theAction
end tell
end if
end repeat
end tell
end tell
Encontré una acción de JavaScript de Automator que funciona:
function run(input, parameters) {
const notNull = (val) => {
return val !== null && val !== undefined;
}
const appName = "";
const verbose = true;
const CLEAR_ALL_ACTION = "Clear All";
const CLOSE_ACTION = "Close";
const hasAppName = notNull(appName) && appName !== "";
const appNameForLog = hasAppName ? (" " + appName) : "";
const log = (message, ...optionalParams) => {
console.log("[close_notifications] " + message, optionalParams);
}
const logVerbose = (message) => {
if (verbose) {
log(message);
}
}
const findCloseAction = (group, closedCount) => {
try {
let clearAllAction;
let closeAction;
for (let action of group.actions()) {
if (action.description() === CLEAR_ALL_ACTION) {
clearAllAction = action;
break;
} else if (action.description() === CLOSE_ACTION) {
closeAction = action;
}
}
if (notNull(clearAllAction)) {
return clearAllAction;
} else if (notNull(closeAction)) {
return closeAction;
}
} catch (err) {
logVerbose(`${closedCount}: Caught error while searching for close action, window is probably closed.`);
logVerbose(err);
return null;
}
log("No close action found for notification");
return null;
}
const notificationGroupMatches = (group) => {
if (!hasAppName) {
return true;
}
logVerbose(`Checking UI elements of group...`);
try {
for (let elem of group.uiElements()) {
if (hasAppName && elem.role() === "AXStaticText" && elem.value().toLowerCase() === appName.toLowerCase()) {
return true;
}
}
} catch (err) {
logVerbose(`Caught error while checking window, window is probably closed.`);
logVerbose(err);
}
return false;
}
const closeNextGroup = (groups, closedCount) => {
for (let group of groups) {
if (notificationGroupMatches(group)) {
logVerbose(`${closedCount}: FIND_CLOSE_ACTION`);
let closeAction = findCloseAction(group, closedCount);
if (notNull(closeAction)) {
logVerbose(`${closedCount}: CLOSING`);
try {
closeAction.perform();
logVerbose(`${closedCount}: CLOSE_PERFORMED`);
return [true, 1];
} catch (err) {
logVerbose(`${closedCount}: Caught error while performing close action, window is probably closed.`);
logVerbose(err);
}
}
return [true, 0];
}
}
return false;
}
const getNotificationCenter = () => {
let systemEvents = Application("System Events");
return systemEvents.processes.byName("NotificationCenter");
}
const getNotificationCenterGroups = () => {
return getNotificationCenter().windows[0].uiElements[0].uiElements[0].uiElements();
}
let notificationCenter = getNotificationCenter();
if (notificationCenter.windows.length <= 0) {
return input;
}
let groupsCount = getNotificationCenterGroups().filter(group => notificationGroupMatches(group)).length;
if (groupsCount > 0) {
logVerbose(`Closing ${groupsCount}${appNameForLog} notification group${(groupsCount > 1 ? "s" : "")}`);
let closedCount = 0;
let maybeMore = true;
while (maybeMore) {
let closeResult = closeNextGroup(getNotificationCenterGroups(), closedCount);
maybeMore = closeResult[0];
if (maybeMore) {
closedCount = closedCount + closeResult[1];
}
}
} else {
throw Error(`No${appNameForLog} notifications found...`);
}
return input;
}
Esto también me ha estado molestando, pero hoy logré que algo parecido funcionara.
Primero instalé clickclick , una herramienta de línea de comandos que te permite simular el movimiento del mouse y los clics. Está disponible a través de Homebrew con brew install cliclick
.
Luego descubrí las coordenadas de la hora en la parte superior derecha, que cuando se hace clic, abre el centro de notificaciones. Esto tomó un poco de experimentación.
Luego descubrí las coordenadas del botón de cerrar que aparece al pasar el mouse. De nuevo, esto requirió un poco de experimentación.
Luego escribí un script que usa cliclick
y estas coordenadas para abrir el Centro de notificaciones, mueva el mouse sobre donde aparece el botón "borrar", duerme durante 500 milisegundos para darle tiempo a que aparezca y luego haga clic en él. ¡Funcionó!
export PATH=/usr/local/bin:$PATH # make sure cliclick binary is on the path
cliclick c:1900,10 # click on the time to open Notification Center
cliclick -w 500 m:1570,45 c:. # move mouse over the close button, wait for it to appear, then click it
Luego traté de hacer que esto funcionara como un servicio de Automator. Lo hice ejecutar desde Automator, pero aunque el script funcionó allí, se negó a funcionar cuando lo asigné a un atajo de teclado. Golpeé mi cabeza contra una pared de ladrillos probando diferentes permisos, etc. hasta que me rendí.
Probé la aplicación HotKey, pero obtuve el mismo resultado.
Eventualmente, pensé en probar un flujo de trabajo de Alfred, para poder abrir Alfred con Cmd+Space y luego escribir "Borrar notificaciones" para borrarlas. Mucho más detallado que un atajo de teclado pero... ¡funcionó! Y no se necesita ratón. Mi mejor suposición de por qué es que cuando Alfred ejecuta el script, siempre se ejecuta desde Alfred , y Alfred ya tiene los permisos necesarios para mover el mouse y hacer clic en cosas, pero cuando intento adjuntar un servicio de Automator a un atajo de teclado , ese servicio se ejecuta con los permisos que tenga la aplicación actualmente enfocada.
Esto se siente como una solución terriblemente frágil (¿qué sucede cuando no estoy usando mi monitor externo?) y parece una tontería que no haya una forma integrada de hacer esto, pero al menos funciona.
TL; DR una combinación de un script usando cliclick
y un flujo de trabajo Alfred para ejecutarlo.
He probado la mayoría de las soluciones que se ofrecen aquí, pero ninguna ha funcionado tan bien como quisiera. Desde entonces, he intentado usar Keysmith y estoy muy contento con los resultados.
Keysmith ofrece un atajo existente para esto. Se parece a esto:
Esto le da la posibilidad de presionar ⌘ escpara cerrar las notificaciones (desde cualquier aplicación).
El único problema que tuve fue que una vez que se cerraron las notificaciones, la ventana activa de la aplicación actual perdió el foco. Afortunadamente, puede agregar un paso adicional en el atajo de Keysmith para recuperar el foco de la ventana activa: ⌃F4. Eso se ve así en Keysmith:
Gracias @lunzwell. Agregué una rutina de error.
on run
try
activate application "NotificationCenter"
tell application "System Events"
tell process "Mitteilungszentrale"
set theWindow to group 1 of UI element 1 of scroll area 1 of window "Notification Center"
# click theWindow
set theActions to actions of theWindow
repeat with theAction in theActions
if description of theAction is "Schließen" then
tell theWindow
perform theAction
end tell
exit repeat
end if
end repeat
end tell
end tell
on error e
display dialog e
activate
end try
end run
Sin embargo, me pregunto si hay una manera de evitar un mensaje de error cuando se ejecuta accidentalmente el script sin notificaciones en la pantalla.
Hice algunas mejoras en este script:
"Clear All"
botón (descubrí que a veces tenía que usar esto en lugar de "Close"
)Mi script completo está en mis archivos de puntos en GitHub aquí y lo tengo expuesto a través de Alfred Workflow aquí .
#!/usr/bin/osascript
# via:
# https://apple.stackexchange.com/questions/408019/dismiss-macos-big-sur-notifications-with-keyboard
# define a function we can call recursively
on dismiss_notification_center(n)
log "dismiss_notification_center: " & n
set performedAction to false
activate application "NotificationCenter"
tell application "System Events"
tell process "Notification Center"
try
# when there are no notifications, this may result in:
# 'System Events got an error: Can’t get window "Notification Center" of process "Notification Center".'
# This is our recursion base case.
set theWindow to group 1 of UI element 1 of scroll area 1 of window "Notification Center"
on error e
# log the error to the console:
log quoted form of e
return
end try
# log theWindow
set theActions to actions of theWindow
repeat with theAction in theActions
# log theAction
# log description of theAction
if description of theAction is in {"Close", "Clear All"} then
tell theWindow
perform theAction
set performedAction to true
end tell
exit repeat
end if
end repeat
end tell
end tell
# log "performedAction: " & performedAction
if performedAction
# for some reason, the loop doesn't close them all when grouped, so
# we need to recurse. But, first we have to sleep to allow notif to re-appear:
do shell script "/bin/sleep 3" # min sleep time that worked for me, and sometimes reminders take even longer
dismiss_notification_center(n + 1)
end if
end dismiss_notification_center
# first call to recursive function:
dismiss_notification_center(0)
También obtuve un script de trabajo a través de clickclick. Aquí está mi versión del script que uso. He unido un montón de bibliotecas de usuario que usé. Lo tengo asignado al control de voz creado a través de Automator en lugar de un atajo de teclado.
Todavía falla cuando la notificación se niega a mostrar el botón de cerrar sin importar cuánto muevas el puntero encima.
activate application "NotificationCenter"
delay 0.1
tell application "System Events" to tell process "Notification Center"
if (count of windows) is 0 then return
set theGroup to first group of UI element 1 of scroll area 1 of window "Notification Center"
tell theGroup
if my isStacked(theGroup) then
click theGroup
delay 1
end if
my dismissNotification(theGroup)
end tell
end tell
on isStacked(nextGroup)
tell application "System Events" to tell process "Notification Center"
get help of nextGroup is "Activate to expand"
end tell
end isStacked
to dismissNotification(theNotification)
script CloseButtonClicker
-- pointer's saveCurrentPosition()
movePointer at theNotification
delay 0.1
tell application "System Events"
try
click button "Close" of theNotification
return true
end try
delay 0.1
end tell
-- pointer's restorePosition()
end script
exec on CloseButtonClicker for 3 by 0.4 -- Retry on failure up to 3x. Optional.
end dismissNotification
to movePointer at theUi
set coord to getCoord at theUi
set formattedCoord to formatCoordinates(item 1 of coord, item 2 of coord)
set clickCommand to "/usr/local/bin/cliclick -e 1 m:" & formattedCoord
do shell script clickCommand
end movePointer
to formatCoordinates(x, y)
if x is less than 0 then set x to "=" & x
if y is less than 0 then set y to "=" & y
return x & "," & y as text
end formatCoordinates
to exec on scriptObj by sleep : 1 for ntimes : 1000
repeat ntimes times
try
set handlerResult to run of scriptObj
if handlerResult is not missing value then return handlerResult
end try
delay sleep
end repeat
return missing value
end exec
¿Alguien había considerado simplemente usar:
pkill NotificationCenter
El proceso reaparece después de hacer esto. Lo uso para borrar todas las notificaciones que recibo con una unidad externa.
Esta respuesta sugiere que en Big Sur en su versión actual no hay una forma satisfactoria de descartar notificaciones con un teclado. En cambio, esta respuesta explica formas alternativas de descartarlos que no se mencionan en ninguna otra parte de este hilo.
Deslizar dos dedos hacia la derecha en el grupo de notificaciones funciona en Big Sur con el panel táctil de la Macbook (no estoy seguro acerca de Yosemite). También funciona con clic izquierdo y arrastrar hacia la derecha. Supongo que esto también funcionaría con un Apple Magic Mouse o Magic Trackpad. Personalmente, creo que deslizar dos dedos y hacer clic con el botón izquierdo y arrastrar es más fácil de hacer que hacer clic en el ícono X y luego hacer clic en Borrar todo. Me resulta muy difícil coordinar el doble clic en un área tan pequeña.
Esto no "borra" todas las notificaciones de forma permanente. Todavía se mostrarán si abre la barra lateral de notificaciones. También mostrarán si llega otro mensaje; en lugar de ver 1 notificación, mostrará N + 1 notificaciones disponibles.
Esta idea se anotó en un comentario en otra respuesta: Descartar las notificaciones de MacOS Big Sur con el teclado .
La razón por la que sugiero que no existe una forma satisfactoria de descartar notificaciones con un teclado es: un script automatizado es notablemente lento para una gran cantidad de notificaciones, la solución Keysmith no funcionó en Big Sur (error), pkill/killall NotificationCenter no funcionó descartar las notificaciones (lo que significa que un atajo de teclado no ayudaría). No probé la solución clickclick, me preocupaba perder demasiado tiempo tratando de hacer que funcionara y que experimentaría los mismos retrasos que un script automatizado.
Este hilo es similar a ¿Cómo borro todas las notificaciones de OS X con 1 clic? .
Aivar Paalberg
colin fraizer
X
para hacer clic; es casi como si quisieran hacerlo tan pequeño como el botón "cerrar" para anuncios móviles. :-)Aivar Paalberg
X
si tiene un panel táctil. Mientras se desplaza sobre cualquier lugar sobre la notificación, deslice dos dedos de izquierda a derecha para descartarla. Desde la perspectiva de la productividad, personalmente no creo que las notificaciones en el escritorio y la interacción inmediata con ellas sea un buen flujo de trabajo.colin fraizer
San Nicolás