Better Twitter Monkey Edition

Low effort port of the Better Twitter Chrome Extension.

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 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;

        }
    });
})();