Last active
October 28, 2021 16:24
-
-
Save double-beep/7dce3a02154bda4d81e6d514645307d1 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name StackFocus | |
// @namespace https://github.com/SpectricSO/stack-scripts | |
// @version 1.0.0+21AF26D3—-117B344092BD | |
// @author SpectricSO | |
// @contributor double-beep | |
// @match https://stackoverflow.com/* | |
// @resource Clear https://cdn.sstatic.net/Img/stacks-icons/Clear.svg | |
// @license MIT | |
// @grant GM_getValue | |
// @grant GM_setValue | |
// @grant GM_getResourceText | |
// ==/UserScript== | |
/* globals Stacks */ | |
(function () { | |
'use strict'; | |
const configurationCacheKey = 'preferences'; | |
const getConfiguration = () => GM_getValue(configurationCacheKey); | |
const defaultConfiguration = { // true => show, false => hide | |
findajob: true, | |
teamsadvert: true, | |
oblock: true, | |
linked: true, | |
related: true, | |
hotnetworkq: true | |
}; | |
if (!getConfiguration()) GM_setValue(configurationCacheKey, defaultConfiguration); // first install, set the defaults for the user | |
/*function addRobotoFont(){ | |
const roboto = document.createElement('link'); | |
roboto.rel = 'stylesheet'; | |
roboto.href = 'https://fonts.googleapis.com/css?family=Roboto&display=swap'; | |
document.head.appendChild(roboto); | |
}*/ | |
function calibrate() { | |
const configuration = getConfiguration(); | |
// because the elements sometimes may not exist, checking if they do will add some more lines of code, thus making it harder to read | |
// instead, we change the style of a fake element which always exists | |
const fake = document.createElement('fake'); | |
// Find a job module | |
(document.querySelectorAll('li .fs-fine')[1] || fake).style.display = configuration.findajob ? 'block' : 'none'; | |
[...document.querySelectorAll('#nav-jobs, #nav-companies')].forEach(element => (element || fake).style.display = configuration.findajob ? 'block' : 'none'); | |
(document.querySelectorAll('.nav-links')[2] || fake).style.display = configuration.teamsadvert ? 'block' : 'none'; // SO Teams ad below sidebar | |
(document.querySelector('.s-sidebarwidget[data-tracker="cb=1"]') || fake).style.display = configuration.oblock ? 'block' : 'none'; | |
(document.querySelector('.sidebar-linked') || fake).style.display = configuration.linked ? 'block' : 'none'; // linked questions | |
(document.querySelector('.sidebar-related') || fake).style.display = configuration.related ? 'block' : 'none'; // related questions | |
(document.querySelector('#hot-network-questions') || fake).style.display = configuration.hotnetworkq ? 'block' : 'none'; // hot network questions | |
} | |
function createCheckbox(labelText, configurationProperty) { | |
const shouldCheck = getConfiguration()[configurationProperty]; | |
return ` | |
<div class="grid gs4"> | |
<div class="grid--cell"> | |
<input class="s-checkbox" type="checkbox" name="stack-focus-config-options" id="stack-focus-${configurationProperty}-option" | |
data-property="${configurationProperty}"${shouldCheck ? ' checked' : ''}/> | |
</div> | |
<label class="grid--cell s-label fw-normal" for="stack-focus-${configurationProperty}-option">Show the ${labelText}</label> | |
</div>`; | |
} | |
function getAllCheckboxes() { | |
return [ | |
createCheckbox('find a job module', 'findajob'), | |
createCheckbox('Teams ad below the left sidebar', 'teamsadvert'), | |
createCheckbox('Overflow Blog, Featured on Meta and Hot Meta Posts', 'oblock'), | |
createCheckbox('linked questions', 'linked'), | |
createCheckbox('related questions', 'related'), | |
createCheckbox('hot network questions', 'hotnetworkq') | |
].join('\n'); | |
} | |
function logic() { | |
const configurationModalHtml = ` | |
<aside class="s-modal" id="stack-focus-modal" role="dialog" aria-labelledby="stack-focus-modal-title" aria-describedby="stack-focus-modal-body" | |
role="dialog" aria-hidden="true" data-controller="s-modal" data-target="s-modal.modal"> | |
<div class="s-modal--dialog ps-relative" data-controller="se-draggable" role="document"> | |
<h1 class="s-modal--header fw-bold c-move" id="stack-focus-modal-title" data-target="se-draggable.handle">Stack Focus configuration</h1> | |
<div class="s-modal--body fs-body2" id="stack-focus-modal-body">${getAllCheckboxes()}</div> | |
<div class="grid gs8 gsx s-modal--footer"> | |
<button class="grid--cell s-btn s-btn__primary" type="button" data-action="s-modal#hide">I'm done!</button> | |
</div> | |
<button class="s-modal--close s-btn s-btn__muted" href="#" aria-label="Close" data-action="s-modal#hide">${GM_getResourceText('Clear')}</button> | |
</div> | |
</aside>`; | |
document.body.insertAdjacentHTML('beforeend', configurationModalHtml); | |
// listener to update the configuration on change | |
document.querySelectorAll('input[name="stack-focus-config-options"]').forEach(element => { | |
element.addEventListener('change', event => { | |
const isChecked = event.target.checked; | |
const configurationProperty = event.target.getAttribute('data-property'); | |
const configuration = getConfiguration(); | |
if (!configuration || !configurationProperty) return; // something went wrong apparently | |
configuration[configurationProperty] = isChecked; | |
GM_setValue(configurationCacheKey, configuration); | |
calibrate(); | |
}); | |
}); | |
$(document).on('keyup', event => { | |
// open on Ctrl + Q (81 is Q) | |
if (event.keyCode === 81 && event.ctrlKey) Stacks.showModal(document.querySelector('#stack-focus-modal')); | |
}); | |
} | |
//addRobotoFont(); | |
calibrate(); | |
logic(); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment