NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Jira next-gen - Dedupe notifications // @namespace https://blog.vicshih.com/2022/04/jira-next-gen-dedupe-notifications.html // @version 0.2 // @description Jira next-gen - Hide duplicate notifications for issues. // @author Victor Shih // @match https://*.atlassian.net/* // @icon https://www.google.com/s2/favicons?sz=64&domain=atlassian.net // @grant none // @license GPL-3.0-or-later // ==/UserScript== /* jshint esversion: 6 */ (function () { 'use strict'; const articleSelector = '[data-testid="notification-item-container"]'; function triggerGroup(event) { if (localStorage.dedupe != 'true' || event.detail.dispatched) { return } const theButton = event.currentTarget; const theHref = theButton.closest(articleSelector).querySelector('a').getAttribute('href'); // Trigger all other (hidden) buttons with the same href. const feed = document.querySelector('[role="feed"]'); for (let article of feed.querySelectorAll(articleSelector)) { const button = article.querySelector('[data-testid="read-state-indicator"]'), href = article.querySelector('a').getAttribute('href').split('?')[0]; if (button != theButton && href == theHref) { button.dispatchEvent(new CustomEvent( 'click', {bubbles: true, detail: {dispatched: true}} )); } } } function handleCheckDedupe(event, checked) { if (event) { checked = event.currentTarget.checked; localStorage.dedupe = checked; } const feed = document.querySelector('[role="feed"]'); /* TODO debounce if (feed.getAttribute('deduped')) { return } feed.setAttribute('deduped', true); */ const articles = feed.querySelectorAll(articleSelector); if (checked) { let hrefs = new Set(); for (let article of articles) { const button = article.querySelector('[data-testid="read-state-indicator"]'), href = article.querySelector('a').getAttribute('href').split('?')[0]; if (hrefs.has(href)) { // Hide the (parent) node. article.parentNode.style.display = 'none'; } else { hrefs.add(href); } if (!button.getAttribute('dedupe-handler')) { button.setAttribute('dedupe-handler', true); button.addEventListener('click', triggerGroup, {passive: true}); } } } else { for (let article of articles) { // Just show every article's direct-parent. article.parentNode.style.display = ''; } } } function poll() { let h1 = document.querySelector('#notification-list-header-label'); if (!h1) { // Notifications not open. return; } const checked = localStorage.dedupe == 'true'; if (h1.nextElementSibling.getAttribute('for') != 'dedupe') { // Inject dedupe checkbox. let label = document.createElement('label'); label.setAttribute('for', 'dedupe'); label.innerHTML = `Dedupe <input id="dedupe" type="checkbox" ${checked ? 'checked' : ''}>`; label.style.marginRight = '15px'; h1.after(label); // Register handler. const dedupe = document.querySelector('#dedupe'); dedupe.addEventListener('change', handleCheckDedupe, {passive: true}); } handleCheckDedupe(null, checked); } setInterval(poll, 250); })();