Twitter media-only filter toggle.

Toggle non-media tweets on and off, for the power-viewer!

As of 2019-09-19. See the latest version.

// ==UserScript==
// @name         Twitter media-only filter toggle.
// @version      0.6
// @description  Toggle non-media tweets on and off, for the power-viewer!
// @author       Cro
// @match        https://twitter.com/*
// @exclude      https://twitter.com/notifications
// @run-at       document-idle
// @grant        GM_setValue
// @grant        GM_getValue
// @namespace https://greatest.deepsurf.us/users/10865
// ==/UserScript==
/* jshint esversion: 6 */

(function() {
    'use strict';
    let program = function(target)
    {
        let storageKey = "cro-media-toggle";
        // The complexity of determining what is a meaningful image post.
        let containsImage = function(node)
        {
            let res = false;
            node.querySelectorAll("img").forEach(function (sub)
            {
                if (!(sub.src.startsWith("https://abs-0.twimg.com/emoji") ||
                     sub.src.startsWith("https://pbs.twimg.com/profile_images") ||
                     sub.src.startsWith("https://abs.twimg.com/hashflags")))
                {
                    res = true;
                }
            });
            return res;
        };
        let isTarget = node => node.tagName &&
            node.tagName.toLowerCase() == "article" &&
            !(node.querySelector("video") || containsImage(node));
        let hideIfTarget = function(node) { if (isTarget(node)) node.style.display = "none"; };
        let show = function(node) { node.style.display = "block"; };
        let hideAll = function() { document.body.querySelectorAll("article").forEach(hideIfTarget); };
        let showAll = function() { document.body.querySelectorAll("article").forEach(show); };
        let running = GM_getValue(storageKey);

        setInterval(function() { if (running) hideAll(); }, 250);

        // UI
        let button = document.createElement("button");
        let setButtonState = function()
        {
            if (running)
            {
                button.innerText = "Only Media Tweets";
            }
            else
            {
                button.innerText = "All Tweets";
                showAll();
            }
        };

        button.onclick = function(event)
        {
            running = !running;
            GM_setValue(storageKey, running);
            setButtonState();
        };

        target.prepend(button);
        setButtonState();
    };

    // Wait for twitter's react crap finish loading things.
    let scanInterval = setInterval(function()
    {
        let target = document.body.querySelector("h1[role='heading']");
        let mainContents = document.body.querySelector("main article");
        if (target && mainContents)
        {
            clearInterval(scanInterval);
            program(target);
        }
    }, 10);
})();