nascent / Clean TheOldReader

// ==UserScript==
// @name         Clean TheOldReader
// @namespace    https://theoldreader.com/
// @version      0.3
// @description  Removes unused features of TheOldReader to clean up the interface
// @author       nascent
// @match        https://theoldreader.com/*
// @run-at       document-start
// @grant        none
// @updateURL    https://openuserjs.org/meta/nascent/Clean_TheOldReader.meta.js
// @downloadURL  https://openuserjs.org/install/nascent/Clean_TheOldReader.user.js
// @copyright    2021, nascent (https://openuserjs.org/users/nascent)
// @license      GPL-3.0-or-later
// ==/UserScript==

/* ------------------ CONFIG: Add/remove selectors or keys here ------------------ */

// CSS selectors for elements to remove (use comma to separate multiple)
const REMOVE_SELECTORS = [
  // Buttons (both major possible class combos)
  '.btn-star', '.btn-share', '.btn-like', '.dropdown-toggle',
  '.btn.btn-default.btn-sm.btn-like',
  '.btn.btn-default.btn-sm.btn-share',
  '.btn.btn-default.btn-sm.btn-star',
  // Containers
  '.btn-group',           // "Send to" container
  '.dl-horizontal',       // Metadata blocks
  '.col-md-12',          // Homepage banner
];

// Only on the homepage, hide extra stuff (add selector if needed)
const HOMEPAGE_ONLY_SELECTORS = [
  '.col-md-12'
];

// Keyboard shortcuts to block (by key code or key, see comments)
const BLOCKED_KEYS = [
  67, 70, 76, 83 // C, F, L, S
];

/* ------------------ Style injection for instant hiding (minimize flicker) ------------------ */

// Build a CSS rule to hide everything instantly
const allSelectors = REMOVE_SELECTORS.concat(HOMEPAGE_ONLY_SELECTORS).join(', ');
const hideCSS = `${allSelectors} { display: none !important; }`;

// Inject the style at the earliest possible moment
(function injectHideStyle(){
  const style = document.createElement('style');
  style.textContent = hideCSS;
  document.documentElement.appendChild(style);
})();

/* ------------------ Modular Removal Logic ------------------ */

function removeElements(selectors) {
  selectors.forEach(sel => {
    document.querySelectorAll(sel).forEach(el => {
      if (el.parentNode) el.parentNode.removeChild(el);
    });
  });
}

/* ------------------ Keyboard shortcut blocking ------------------ */
document.addEventListener('keydown', function(e) {
  // If the event comes from an input/textarea, don't block it
  if (/^(input|textarea|select)$/i.test(e.target.tagName)) return;

  // Check by keyCode (legacy, for compatibility)
  if (BLOCKED_KEYS.includes(e.keyCode)) {
    e.stopImmediatePropagation();
    e.preventDefault();
    return false;
  }
  // Optionally, check by e.key for more modern browsers:
  // if (['c','f','l','s'].includes(e.key.toLowerCase())) { ... }
});

/* ------------------ Initial and dynamic cleanup ------------------ */

function runRemovals() {
  removeElements(REMOVE_SELECTORS);
  if (location.pathname === "/" || location.href === "https://theoldreader.com/") {
    removeElements(HOMEPAGE_ONLY_SELECTORS);
  }
}

// Initial removal ASAP
document.addEventListener('DOMContentLoaded', runRemovals);
// Extra run for those sites that inject after DOMContentLoaded
window.addEventListener('load', runRemovals);

// MutationObserver for dynamic content
const observer = new MutationObserver(runRemovals);
// Start observing the <body> (wait for it to exist)
function startObserving() {
  if (!document.body) return setTimeout(startObserving, 25);
  observer.observe(document.body, {childList: true, subtree: true});
}
startObserving();

/* ------------------ END OF SCRIPT ------------------ */