shuuji3 / Twitter Block Ads & Moments etc. for Mobile

// ==UserScript==
// @name Twitter Block Ads & Moments etc. for Mobile
// @namespace https://openuserjs.org//users/shuuji3
// @version 0.3.1
// @description For mobile user, you can install this script by using Firefox & Greasemonkey (not work yet in Tampermonkey)
// @author TAKAHASHI Shuuji <shuuji3@gmail.com>
// @copyright 2018, shuuji3 (https://openuserjs.org//users/shuuji3)
// @match https://mobile.twitter.com/*
// @grant none
// @license MIT
// ==/UserScript==

/**
 * Changelog
 * v0.3.1 Fix bug where functions disabled when changing tabs.
 * v0.3.0 Improve the logic to hide promoted tweets by using MutationObserver.
 * v0.2.0 Hide "who to follow" button in search tab.
 * v0.1.0 Hide promoted tweets and trends & moment area shown in search tab.
 */

(function () {
    'use strict';

    function removeAds() {
        // Insert stylesheet
        const style = document.createElement('style');
        style.innerText = '.hidden { display: none; }';
        document.body.appendChild(style);

        // Create MutationObserver
        const timelineRootSelector = 'h1 + div[aria-label]';
        new MutationObserver((mutationRecords, observer) => {
            [...document.querySelectorAll(timelineRootSelector)].forEach(timelineRoot => {
                timelineRoot.querySelectorAll('article').forEach(removeAdsNode);

                new MutationObserver((mutations) => mutations.forEach(mutation => mutation.addedNodes.forEach(removeAdsNode)))
                    .observe(timelineRoot, { childList: true, subtree: true });
            });
        })
            .observe(document.documentElement, {
            childList: true,
            subtree: true
        });
    }

    function removeAdsNode(tweet) {
        const isPromotion = tweet.querySelector('svg + div') !== null;
        if (isPromotion) {
            console.log('remove ads:', tweet.textContent);
            tweet.classList.add('hidden');
        }
    }

    function removeMoments() {
        const style = document.createElement('style');
        // Enable only for english and japanese
        style.innerText = 'div[aria-label="Timeline: Explore"], div[aria-label="タイムライン: 話題を検索"] { display: none; }';
        document.body.appendChild(style);
    }

    function removeWhoToFollowButton() {
        const style = document.createElement('style');
        // Enable only for english and japanese
        style.innerText = 'a[href="/who_to_follow"] { display: none; }';
        document.body.appendChild(style);
    }

    removeAds();
    removeMoments();
    removeWhoToFollowButton();
})();