Skip to content

Instantly share code, notes, and snippets.

@strugee
Last active September 17, 2023 22:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save strugee/8a0cdb3f27b40713b7253b1bc2228e1c to your computer and use it in GitHub Desktop.
Save strugee/8a0cdb3f27b40713b7253b1bc2228e1c to your computer and use it in GitHub Desktop.
Hide GitHub notifications about work on your personal machine
// ==UserScript==
// @name Hide work-related GitHub notifications
// @namespace https://strugee.net/
// @description Hides GitHub notifications about work on your personal machine
// @version 4
// @grant GM.setValue
// @grant GM.getValue
// @include https://github.com/*
// @noframes
// @run-at document-end
// ==/UserScript==
async function init() {
// We have to run on all pages because of pushState(). So bail out if we aren't on the right page.
if (String(window.location) !== 'https://github.com/notifications') return;
/* COMMON SETUP */
var targetRepo = await GM.getValue('targetRepo');
/* SETTINGS TEXTBOX */
var manageNotificationsEl = document.querySelector('.notification-navigation').lastElementChild;
var configBox = document.createElement('input');
configBox.type = 'text';
if (targetRepo) configBox.value = targetRepo;
configBox.className = 'form-control width-full input-contrast';
configBox.setAttribute('placeholder', 'Work repo name');
configBox.ariaLabel = 'Work repo name';
var form = document.createElement('form');
form.prepend(configBox);
form.addEventListener('submit', function(e) {
e.preventDefault();
// TODO handle setValue errors...?
GM.setValue('targetRepo', form.firstChild.value);
location.reload();
})
manageNotificationsEl.parentElement.insertBefore(form, manageNotificationsEl);
/* ACTUAL LOGIC */
// Bail out if we haven't configured a target repo
if (!targetRepo) return;
// TODO security alerts are formatted differently
document.querySelectorAll('.notifications-list-item').forEach(function(node) {
var isWork = Array.from(node.querySelectorAll('p')).map(el => el.firstChild.textContent.trim() === targetRepo).reduce((a, b) => a || b);
if (!isWork) return;
// Kill all event listeners on children to prevent buttons, checkboxes, etc. from affecting anything
// Modified from https://stackoverflow.com/a/39026635/1198896
node.innerHTML = node.innerHTML;
// We hide all notification child nodes with CSS instead of HTML `hidden` because we want the computed layout to be the same
// Otherwise we would have to fake up our own margins and stuff and it would get out of sync easily and etc.
node.querySelectorAll('*').forEach(function(el) {
// Kill <a> tags' href so they don't get the hand cursor
if (el.tagName == 'A') el.removeAttribute('href');
el.style.opacity = 0;
el.ariaHidden = true;
el.addEventListener('hover', e => { e.preventDefault(); e.stopPropagation(); });
el.addEventListener('click', e => { e.preventDefault(); e.stopPropagation(); });
});
var n = document.createElement('em');
n.prepend('Hidden');
node.querySelector('div div').prepend(n);
// Make the parent visible so you can see "Hidden"
n.parentNode.style.opacity = 1;
n.parentNode.ariaHidden = undefined;
// TODO: make this align with the text
/*
var afterIcons = node.querySelector('div a');
afterIcons.parentNode.insertBefore(n, afterIcons);
var parent = n.parentNode;
while (parent != node) {
parent.style.opacity = 1;
parent = parent.parentNode;
}
*/
})
}
document.addEventListener('turbo:load', init);
init();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment