import browser from 'webextension-polyfill' import throttle from 'lodash/throttle' import { onEnabledChange, isEnabled } from './perOrigin' function hideBanners(elements) { const revertSteps = [] /* Hide all elements with position:fixed */ const fixedElements = elements .filter(el => ( getComputedStyle(el).position === 'fixed' && el.style.opacity !== '0' // ignore if we already hid this one )) fixedElements.forEach(el => { const originalVisibility = el.style.visibility const originalOpacity = el.style.opacity const originalTransition = el.style.transition el.style.transition = 'opacity 1s' el.style.opacity = '0' const hiderTimeoutId = window.setTimeout(() => { el.style.visibility = 'hidden' }, 1000) revertSteps.push(() => { window.clearTimeout(hiderTimeoutId) const reverterTimeoutId = window.setTimeout(() => { el.style.transition = originalTransition }, 1000) el.style.visibility = originalVisibility el.style.opacity = originalOpacity }) }) /* Stop position:sticky elements from sticking. */ const stickyElements = elements .filter(el => getComputedStyle(el).position === 'sticky') stickyElements.forEach(el => { const originalPosition = el.style.position el.style.position = 'relative' revertSteps.push(() => { el.style.position = originalPosition }) }) return revertSteps } async function main() { let revertSteps = [] // XXX We read the location only once, but it may be changed by page scripts. // Fortunately we only need the origin, which should remain the same. const url = window.location.href function run(elements) { if (enabled && scrolledDown) { // Hide everything that looks annoying. Remember the steps to revert this. if (elements === undefined) { elements = Array.from(document.querySelectorAll('*')) } revertSteps = hideBanners(elements).concat(revertSteps) } else { // Unhide everything we have hidden. if (revertSteps.length > 0) { revertSteps.forEach(step => step()) revertSteps = [] } } } // Run whenever the extension is enabled/disabled for this domain. let enabled = await isEnabled(url) onEnabledChange(url, newValue => { enabled = newValue; run() }) // Run whenever crossing the scroll threshold. let scrolledDown = window.scrollY > 20 window.addEventListener('scroll', () => { // We add a hysteresis of 20px. if (window.scrollY > 20 && !scrolledDown) { scrolledDown = true run() } else if (window.scrollY <= 0 && scrolledDown) { scrolledDown = false run() } }) // Run on suspicious page mutations. const observer = new MutationObserver(mutationList => { let elements = [] mutationList.forEach(mutationRecord => { if (mutationRecord.type === 'attributes') { const modifiedElement = mutationRecord.target elements.push(modifiedElement) if (mutationRecord.attributeName === 'class') { // A change in class is likely to influence style of the element's offspring const children = Array.from(modifiedElement.querySelectorAll('*')) elements = elements.concat(children) } } else if (mutationRecord.type === 'childList') { const newElements = [...mutationRecord.addedNodes] .filter(node => node instanceof Element) elements = elements.concat(newElements) } }) run(elements) }) observer.observe(document, { subtree: true, childList: true, attributes: true, attributeFilter: ['class', 'style'], }) // Run once now. run() } main()