Remove Important YouTube Notifications

Removes the "Important" section in the YouTube notification menu, putting the notifications whithin it back to their appropriate position in the notification list.

目前为 2025-04-05 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Remove Important YouTube Notifications
  3. // @namespace greasyfork.org/en/users/1436613
  4. // @match https://www.youtube.com/*
  5. // @version 1.0
  6. // @license MIT
  7. // @author gosha305
  8. // @description Removes the "Important" section in the YouTube notification menu, putting the notifications whithin it back to their appropriate position in the notification list.
  9. // ==/UserScript==
  10.  
  11. let orderOfPrecedence;
  12. let regularNotificationPanel;
  13. let importantNotificationPanel;
  14. let notificationsHandled = false;
  15.  
  16. const hideImportantNotificationsSection = "ytd-popup-container #sections:has(ytd-notification-renderer),ytd-popup-container #sections:has(ytd-notification-renderer) #section-title {display:none;} ytd-popup-container #sections:has(ytd-notification-renderer.unimportantNotification){display:unset !important;}";
  17.  
  18. let menuRemover = document.createElement("style");
  19. menuRemover.textContent = hideImportantNotificationsSection;
  20. document.head.appendChild(menuRemover);
  21.  
  22. let popupContainer = document.querySelector("ytd-popup-container");
  23.  
  24. (new MutationObserver(function(_,observer){
  25. const notificationMenu = document.querySelector("ytd-popup-container")?.lastChild
  26. if (notificationMenu?.nodeName == "TP-YT-IRON-DROPDOWN"){
  27. (new MutationObserver(function(mutationList){replaceNotifications(mutationList);})).observe(notificationMenu, {attributes: true});
  28. observer.disconnect();
  29. }
  30. })).observe(popupContainer, {childList: true, subtree:true})
  31.  
  32. function replaceNotifications(mutationList){
  33. const importantNotifications = document.querySelectorAll("yt-multi-page-menu-section-renderer:nth-of-type(1) #items > ytd-notification-renderer");
  34. if (!importantNotifications || importantNotifications.length == 0) {
  35. return;
  36. }
  37. regularNotificationPanel = document.querySelector("yt-multi-page-menu-section-renderer:nth-of-type(2) #items");
  38. orderOfPrecedence = getOrderOfPrecendence();
  39. importantNotifications.forEach(element => {regularNotificationPanel.insertBefore(element,findAppropriatePosition(element)); element.classList.add("unimportantNotification")});
  40. }
  41.  
  42.  
  43. function getOrderOfPrecendence(){
  44. const seen = new Set();
  45. const nonNumberDateParts = Array.from(regularNotificationPanel.querySelectorAll("ytd-notification-renderer .metadata.style-scope.ytd-notification-renderer > yt-formatted-string:nth-of-type(2)")).map(e => e.textContent.split(" ").filter(part => isNaN(Number(part))).join(''));
  46. return nonNumberDateParts.filter(e => {if (seen.has(e)) return false; seen.add(e); return true;})
  47. }
  48.  
  49.  
  50. function findAppropriatePosition(element){
  51. const elementParts = element.querySelector(".metadata.style-scope.ytd-notification-renderer > yt-formatted-string:nth-of-type(2)").textContent.split(" ");
  52. const nonNumberPartsRank = orderOfPrecedence.indexOf(elementParts.filter(e => isNaN(Number(e))).join(''));
  53. const NumberParts = elementParts.find(e => !isNaN(Number(e)))
  54. const rep = Array.from(regularNotificationPanel.querySelectorAll("ytd-notification-renderer")).find(e => !compareUploadDateText(e.querySelector(".metadata.style-scope.ytd-notification-renderer > yt-formatted-string:nth-of-type(2)").textContent, nonNumberPartsRank, NumberParts));
  55. return rep;
  56. }
  57.  
  58. function compareUploadDateText(date1, nonNumberPartsRank2,date2NumberParts){
  59. const date1Parts = date1.split(" ");
  60. const nonNumberPartsRank1 = orderOfPrecedence.indexOf(date1Parts.filter(e => isNaN(Number(e))).join(''));
  61. if (nonNumberPartsRank1 < nonNumberPartsRank2){
  62. return true;
  63. } else if (nonNumberPartsRank1 > nonNumberPartsRank2){
  64. return false;
  65. } else {
  66. return Number(date1Parts.find(e => !isNaN(Number(e)))) < date2NumberParts
  67. }
  68. }