25 votes

Désactiver les notifications de MacOS Big Sur avec le clavier

J'utilise depuis longtemps un Applescript déclenché à partir d'un raccourci clavier pour désactiver les notifications sous MacOS. Cela fonctionnait en simulant un clic sur le bouton "fermer" de chaque fenêtre ouverte du centre de notifications.

Depuis la mise à jour vers Big Sur (actuellement 11.0.1), les notifications n'ont plus de bouton de fermeture. À la place, lorsque vous les survolez avec la souris, un bouton "X" apparaît. Pour une personne qui a du mal à cliquer avec précision (j'ai un léger tremblement de la main), l'utilisation de la souris/trackpad est difficile.

Quelqu'un a-t-il des suggestions sur la façon de restaurer cette fonctionnalité afin que je puisse garder mes mains sur le clavier ?

Mes paramètres

J'utilise Automator pour tester cela.

Sur Préférences du système > Notifications J'ai sélectionné Automator :

  • Autoriser les notifications est vrai.
  • Style d'alerte Automator : est Alertes .
  • Regroupement des notifications est automatique .

Essais

  • J'ai ouvert Automator et créé un nouveau flux de travail.
  • J'ai ajouté trois instances de la Notification de l'affichage action.
  • Je leur ai donné Titre : valeurs de test 1 , test 2 et test 3 .
  • Et Sous-titre : valeurs de subtitle 1 , subtitle 2 et subtitle 3 .
  • Et Message : valeurs de message 1 , message 2 et message 3 .
  • J'ai exécuté le flux de travail en utilisant +R .
  • Dans le coin supérieur droit de mon écran, je vois une notification de Automator empilés sur deux autres. Seule la notification test 3 est entièrement visible et porte la mention "2 notifications supplémentaires" en bas.

Le script de @AndrewJanianscript.

  • Encore une fois, merci à Andrew d'avoir fourni le script !
  • J'ai ajouté la ligne #!/usr/bin/osascript au début du script et l'a enregistré en tant que andrew.applescript .
  • J'ai rendu le fichier exécutable. ( chmod 755 andrew.applescript ).
  • Je l'ai exécuté dans une fenêtre de terminal ( ./andrew.applescript )
  • Le résultat de la course est :

    • les notifications groupées deviennent non groupées (donc je vois test 3 , test 2 et test 1 empilés de haut en bas dans la zone de notification
    • le terminal affiche l'erreur suivante

      ./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)

Je vais essayer de faire des modifications pour voir si je peux le faire fonctionner avec des modifications.

Note : Si je relance le script, en partant de l'état non groupé :

  • il désactive la notification la plus élevée ( test 3 )
  • et il affiche ce qui suit dans le terminal :

    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

13voto

Torben Points 1481

Mise à jour

J'affiche une version plus robuste qui a évolué à partir de mon message initial. Elle semble faire un travail raisonnable pour fermer toutes les fenêtres, mais elle est parfois lente à exécuter. Comme je l'ai dit dans les commentaires, je ne m'y connais pas beaucoup en AppleScript, donc peut-être que quelqu'un qui sait ce qu'il fait peut nous dire comment améliorer les performances.

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

Original

Oui, merci d'avoir publié le script, @AndrewJanian.

J'ai reçu une erreur similaire à celle de @ColinFraizer en l'utilisant tel quel. Je pense que le problème vient de la répétition interne sur les actions : dans certains cas, elle essaie d'accéder aux actions. après la fenêtre est fermée. Une petite modification corrige ce problème pour moi :

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

6voto

MikeH Points 576

J'ai un AppleScript qui fonctionne. J'ai trouvé les éléments en utilisant UIBrowser . La mise en garde est que la notification doit comporter une action "Fermer". Toutes les notifications que j'ai rencontrées ont cette action.

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

4voto

RussellZ Points 81

J'ai trouvé un automate Action JavaScript qui fonctionne :

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;
}

3voto

Russell Dunphy Points 21

Cela m'ennuyait aussi, mais j'ai réussi à faire fonctionner quelque chose de proche aujourd'hui.

J'ai d'abord installé clic sur un outil en ligne de commande qui vous permet de simuler les mouvements et les clics de la souris. Il est disponible via Homebrew avec brew install cliclick .

J'ai ensuite trouvé les coordonnées de l'heure en haut à droite, qui, lorsqu'on clique dessus, ouvre le centre de notification. Cela a nécessité un peu d'expérimentation.

Puis j'ai trouvé les coordonnées du bouton de fermeture qui apparaît au survol. Là encore, j'ai dû expérimenter un peu.

Puis j'ai écrit un script qui utilise cliclick et ces coordonnées pour ouvrir le centre de notification, déplacer la souris sur l'endroit où le bouton "clear" apparaît, dormir pendant 500 millisecondes pour lui donner le temps d'apparaître, puis cliquer dessus. Et ça marche !

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

J'ai ensuite essayé de le faire fonctionner comme un service Automator. J'ai réussi à le faire fonctionner à partir d'Automator, mais bien que le script ait fonctionné, il a refusé de fonctionner lorsque je l'ai assigné à un raccourci clavier. Je me suis tapé la tête contre un mur de briques en essayant différentes permissions etc jusqu'à abandonner.

J'ai essayé l'application HotKey, mais j'ai eu le même résultat.

Finalement, j'ai pensé à essayer un flux de travail Alfred, de sorte que je puisse ouvrir Alfred avec Cmd+Espace et ensuite taper "Clear notifications" pour les effacer. C'est beaucoup plus verbeux qu'un raccourci clavier mais... ça marche ! Et pas besoin de souris. Ma meilleure hypothèse quant à la raison est que lorsqu'Alfred exécute le script, il s'exécute toujours à partir de sur Alfred, et Alfred dispose déjà des autorisations nécessaires pour déplacer la souris et cliquer sur des objets, mais lorsque j'essaie d'attacher un service Automator à un raccourci clavier, ce service s'exécute avec les autorisations dont dispose l'application en cours.

Cette solution semble terriblement fragile (que se passera-t-il lorsque je n'utiliserai pas mon moniteur externe ??) et il semble absurde qu'il n'y ait pas de moyen intégré de le faire, mais au moins cela fonctionne.

TL;DR une combinaison d'un script utilisant cliclick et un flux de travail Alfred pour l'exécuter.

3voto

zgreen Points 121

J'ai essayé la plupart des solutions proposées ici, mais aucune n'a fonctionné aussi bien que je le voulais. J'ai depuis essayé d'utiliser Keysmith et je suis assez satisfait des résultats.

Keysmith propose un raccourci existant pour cela. Ça ressemble à ça :

Screenshot of a Keysmith shortcut to close notification

Cela vous donne la possibilité d'appuyer sur esc pour fermer les notifications (depuis n'importe quelle application).

Le seul problème que j'ai rencontré est qu'une fois les notifications fermées, la fenêtre active de l'application en cours perd le focus. Heureusement, vous pouvez ajouter une étape supplémentaire dans le raccourci Keysmith pour regagner le focus de la fenêtre active : F4 . Cela ressemble à ça dans Keysmith :

Screenshot of a Keysmith shortcut to close notifications. The shortcut is: in Notification center, "Click Close", and then "Press F4"

LesApples.com

LesApples est une communauté de Apple où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres utilisateurs d'appareils Apple, poser vos propres questions ou résoudre celles des autres.

Powered by:

X