Better Twitter Monkey Edition

Low effort port of the Better Twitter Chrome Extension.

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Better Twitter Monkey Edition
// @namespace    http://tampermonkey.net/
// @version      0.2
// @description  Low effort port of the Better Twitter Chrome Extension.
// @author       me, oslego
// @match        https://twitter.com/*
// @grant        none
// @run-at document-start
// ==/UserScript==

/*
NOT MY WORK.
Code ported over from here with minimal effort lol.
https://github.com/oslego/better-twitter
*/

const userPrefs = {
    //CONFIGURE START - Flip the values from true/false depending if you want to enable the feature.
  "bt--nofame": {
    value: false,
    label: "No fame: Hide number of followers and following count",
  },
  "bt--nopopularity": {
    value: true,
    label: "No vanity: Hide number of tweet likes, retweets and replies",
  },
  "bt--nopromoted": {
    value: true,
    label: "Hide promoted tweets",
  },
  "bt--noretweets": {
    value: false,
    label: "Hide retweets"
  },
  "bt--nolikedtweets": {
    value: true,
    label: "Hide tweets liked by others"
  },
  "bt--notrends": {
    value: true,
    label: "Hide “Trends for you”",
  },
  "bt--nowtf": {
    value: true,
    label: "Hide “Who to follow”",
  },
  "bt--nofooter": {
    value: true,
    label: "Hide website footer",
  },
    //CONFIGURE END
}

const contentCSS = `
/* Hide promoted tweets */
.bt--nopromoted [aria-label^="timeline" i][aria-label$="timeline" i] div[bt-promoted],
.bt--nopromoted [aria-label^="timeline" i][aria-label$="tweets" i] div[bt-promoted] {
	display: none;
}

/* Hide someone else's liked tweets showing in timelines */
.bt--nolikedtweets [aria-label^="timeline" i][aria-label$="timeline" i] div[bt-likedtweet],
.bt--nolikedtweets [aria-label^="timeline" i][aria-label$="tweets" i] div[bt-likedtweet] {
	display: none;
}

/* Hide retweets */
.bt--noretweets [aria-label^="timeline" i][aria-label$="timeline" i] div[bt-retweet],
.bt--noretweets [aria-label^="timeline" i][aria-label$="tweets" i] div[bt-retweet] {
	display: none;
}

/* Hide "Who to Follow" from users' timelines aside from search result timelines
	 https://github.com/oslego/better-twitter/issues/12
*/
.bt--nowtf [aria-label^="timeline" i][aria-label$="timeline" i]:not([aria-label~="search" i]) div[bt-wtf],
.bt--nowtf [aria-label^="timeline" i][aria-label$="tweets" i] div[bt-wtf] {
	display: none;
}

/* Find "promoted" icons, then mark their ancestor <div> as a promoted tweet */
.bt--nopromoted path[d^="M20.75"] {
	animation: bt-marker-promoted 0s 1;
}
@keyframes bt-marker-promoted { to { outline-color: inherit } }

/* Find "retweeted" icons, then mark their ancestor <div> as a retweet */
.bt--noretweets path[d^="M23.615 15.477c-"] {
	animation: bt-marker-retweet 0s 1;
}
@keyframes bt-marker-retweet { to { outline-color: inherit } }

/* Find "liked tweet" icons next to "Someone liked" annotations, then mark their ancestor <div> as a retweet
	 The  path for "filled heart" is identical to the one used when you yourself like a tweet.
	 When the icon is used in context of the "Someone liked" annotation,
	 the host <svg> is an only child of its parent so we can differentiate on that. This is fragile.
	 FIXME: Find a way to match the tweet annotation container for "Someone liked" or "Someone retweeted".
*/
.bt--nolikedtweets svg:only-child path[d="M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12z"] {
	animation: bt-marker-likedtweet 0s 1;
}
@keyframes bt-marker-likedtweet { to { outline-color: inherit } }

/* Find "Follow" buttons, then mark their ancestor <div> as a who-to-follow prompt */
.bt--nowtf [data-testid$="-follow"] {
	animation: bt-marker-wtf 0s 1;
}
@keyframes bt-marker-wtf { to { outline-color: inherit } }

/* Find the "Who to follow" container from the sidebar */
.bt--nowtf [aria-label*="who to follow" i]{
	animation: bt-marker-wtf-sidebar 0s 1;
}
@keyframes bt-marker-wtf-sidebar { to { outline-color: inherit } }

.bt--nowtf .bt-marker-wtf-sidebar {
	display: none !important;
}

/* Hide "Trends for you" box */
.bt--notrends [aria-label*="trending" i] {
	display: none !important;
}

/* Hide "Footer" box */
.bt--nofooter [aria-label="footer" i] {
	display: none !important;
}

/* Hide tweet reply count */
.bt--nopopularity [data-testid="reply"] span {
	display: none !important;
}

/* Hide tweet retweet count */
.bt--nopopularity [href$="/retweets"] span,
.bt--nopopularity [data-testid="retweet"] span,
.bt--nopopularity [data-testid="unretweet"] span {
  display: none !important;
}

/* Hide tweet like count */
.bt--nopopularity [data-testid="like"] span,
.bt--nopopularity [data-testid="unlike"] span,
/* Hide the likes count on a single tweet page, but not the Likes tab on the user profile page */
.bt--nopopularity [href$="/likes"]:not([role="tab"]) span {
	display: none !important;
}

/* Hide all profile stats from user cards */
.bt--nofame [href$="/following"],
.bt--nofame [href$="/followers"] {
	display: none !important;
}
`;




function applyPrefs() {
  Object.entries(userPrefs).forEach(([id, pref]) => {
    document.documentElement.classList.toggle(id, pref.value);
  })
}

const addGlobalStyle = (css) => {
    var head, style;
    head = document.getElementsByTagName('head')[0];
    if (!head) { return; }
    style = document.createElement('style');
    style.type = 'text/css';
    style.innerHTML = css;
    head.appendChild(style);
}


(function() {
    'use strict';

    addGlobalStyle(contentCSS);
    applyPrefs();
    document.addEventListener('animationstart', (e) => {
        switch (e.animationName) {
            case "bt-marker-likedtweet":
                e.target.closest('div:not([class])').setAttribute('bt-likedtweet', true)
                break;
            case "bt-marker-promoted":
                e.target.closest('div:not([class])').setAttribute('bt-promoted', true)
                break;
            case "bt-marker-retweet":
                e.target.closest('div:not([class])').setAttribute('bt-retweet', true)
                break;
            case "bt-marker-wtf-sidebar":
                // Mark the container's parent for the "Who To Follow" in the sidebar.
                e.target.parentNode.classList.add(e.animationName)
                break;
            case "bt-marker-wtf":
                const container = e.target.closest('div:not([class])');
                container.setAttribute('bt-wtf', true);

                // If found, mark the container for the "Who to Follow" heading
                const prevContainer = container.previousElementSibling;
                if (prevContainer.querySelector('h2')) {
                    prevContainer.setAttribute('bt-wtf', true);
                }

                // If found, mark the container for "show more" link
                const nextContainer = container.nextElementSibling;
                if (nextContainer.querySelector('[href^="/i/connect_people"]')) {
                    nextContainer.setAttribute('bt-wtf', true);
                }
                break;

        }
    });
})();