Get Twitter Icons Back

Brings back the blue bird icon on Twitter. No more 𝕏.

当前为 2023-08-01 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Get Twitter Icons Back
  3. // @namespace Pionxzh
  4. // @version 1.6.1
  5. // @author Pionxzh
  6. // @description Brings back the blue bird icon on Twitter. No more 𝕏.
  7. // @license MIT
  8. // @icon https://abs.twimg.com/favicons/twitter.2.ico
  9. // @match https://twitter.com/*
  10. // @match https://x.com/*
  11. // @match https://tweetdeck.twitter.com/*
  12. // @run-at document-start
  13. // ==/UserScript==
  14.  
  15. (function () {
  16. 'use strict';
  17.  
  18. const xIconPath = "M14.258 10.152L23.176 0h-2.113l-7.747 8.813L7.133 0H0l9.352 13.328L0 23.973h2.113l8.176-9.309 6.531 9.309h7.133zm-2.895 3.293l-.949-1.328L2.875 1.56h3.246l6.086 8.523.945 1.328 7.91 11.078h-3.246zm0 0";
  19. const xIconInNotificationPath = "M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z";
  20. const twitterIconPath = "M23.643 4.937c-.835.37-1.732.62-2.675.733.962-.576 1.7-1.49 2.048-2.578-.9.534-1.897.922-2.958 1.13-.85-.904-2.06-1.47-3.4-1.47-2.572 0-4.658 2.086-4.658 4.66 0 .364.042.718.12 1.06-3.873-.195-7.304-2.05-9.602-4.868-.4.69-.63 1.49-.63 2.342 0 1.616.823 3.043 2.072 3.878-.764-.025-1.482-.234-2.11-.583v.06c0 2.257 1.605 4.14 3.737 4.568-.392.106-.803.162-1.227.162-.3 0-.593-.028-.877-.082.593 1.85 2.313 3.198 4.352 3.234-1.595 1.25-3.604 1.995-5.786 1.995-.376 0-.747-.022-1.112-.065 2.062 1.323 4.51 2.093 7.14 2.093 8.57 0 13.255-7.098 13.255-13.254 0-.2-.005-.402-.014-.602.91-.658 1.7-1.477 2.323-2.41z";
  21. const twitterBlue = "rgb(29,155,240)";
  22. const twitterGray = "rgb(231,233,234)";
  23. const linkMap = {
  24. "mask-icon": "https://abs.twimg.com/responsive-web/client-web/icon-svg.168b89da.svg",
  25. // 'shortcut icon': '//abs.twimg.com/favicons/twitter.2.ico',
  26. "apple-touch-icon": "https://abs.twimg.com/responsive-web/client-web/icon-ios.b1fc727a.png"
  27. };
  28. const metaMap = {
  29. "apple-mobile-web-app-title": "Twitter"
  30. };
  31. const twitterFavicon = "//abs.twimg.com/favicons/twitter.2.ico";
  32. const twitterFaviconWithDot = "//abs.twimg.com/favicons/twitter-pip.2.ico";
  33. function main() {
  34. waitForElement("body").then(() => {
  35. doSyncColorScheme();
  36. });
  37. waitForElement("head").then(() => {
  38. injectStyle();
  39. monitorHead();
  40. monitorTitle();
  41. });
  42. }
  43. function syncColorScheme() {
  44. const bgColor = document.body.style.backgroundColor;
  45. if (bgColor === "#FFFFFF" || bgColor === "rgb(255, 255, 255)") {
  46. document.documentElement.setAttribute("data-color-scheme", "light");
  47. } else if (bgColor === "#000000" || bgColor === "rgb(0, 0, 0)") {
  48. document.documentElement.setAttribute("data-color-scheme", "dark");
  49. } else if (bgColor === "#15202B" || bgColor === "rgb(21, 32, 43)") {
  50. document.documentElement.setAttribute("data-color-scheme", "dark");
  51. } else {
  52. const system = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
  53. document.documentElement.setAttribute("data-color-scheme", system);
  54. }
  55. }
  56. async function doSyncColorScheme() {
  57. syncColorScheme();
  58. const bodyStyleObserver = new MutationObserver(syncColorScheme);
  59. bodyStyleObserver.observe(document.body, { attributes: true });
  60. }
  61. function injectStyle() {
  62. const style = document.createElement("style");
  63. style.textContent = `
  64. svg > g > path[d='${xIconPath}'],
  65. svg > g > path[d='${xIconInNotificationPath}'] {
  66. d: path('${twitterIconPath}');
  67. }
  68.  
  69. #placeholder > svg,
  70. h1 a[href='/home'] svg,
  71. svg[data-testid="icon-verified"],
  72. [data-testid="TopNavBar"] div:not([role="button"]) > div > svg,
  73. [data-testid="cellInnerDiv"] svg > g > path[d='${xIconInNotificationPath}'] {
  74. color: ${twitterBlue};
  75. }
  76.  
  77. [data-color-scheme="dark"] h1 a[href='/home'] svg {
  78. color: ${twitterGray};
  79. }`;
  80. document.head.appendChild(style);
  81. }
  82. const mutationObserverOptions = { subtree: true, characterData: true, childList: true, attributes: true };
  83. async function waitForElement(selector) {
  84. const el = document.querySelector(selector);
  85. if (el)
  86. return el;
  87. return new Promise((resolve) => {
  88. const fn = () => {
  89. const el2 = document.querySelector(selector);
  90. if (el2) {
  91. return resolve(el2);
  92. }
  93. requestAnimationFrame(fn);
  94. };
  95. requestAnimationFrame(fn);
  96. });
  97. }
  98. function monitorHead() {
  99. const sync = () => {
  100. Object.entries(linkMap).forEach(([rel, targetValue]) => {
  101. const link = document.querySelector(`link[rel="${rel}"]`);
  102. if (link && link.getAttribute("href") !== targetValue) {
  103. link.setAttribute("href", targetValue);
  104. }
  105. });
  106. Object.entries(metaMap).forEach(([name, targetValue]) => {
  107. const meta = document.querySelector(`meta[name="${name}"]`);
  108. if (meta && meta.getAttribute("content") !== targetValue) {
  109. meta.setAttribute("content", targetValue);
  110. }
  111. });
  112. const shortcut = document.querySelector('link[rel="shortcut icon"]');
  113. if (shortcut) {
  114. const hasNotification = document.querySelector('a[data-testid="AppTabBar_Notifications_Link"] svg ~ div[aria-live="polite"]');
  115. const targetValue = hasNotification ? twitterFaviconWithDot : twitterFavicon;
  116. if (shortcut.getAttribute("href") !== targetValue) {
  117. shortcut.setAttribute("href", targetValue);
  118. }
  119. }
  120. };
  121. sync();
  122. window.addEventListener("visibilitychange", sync);
  123. new MutationObserver(sync).observe(document.head, mutationObserverOptions);
  124. }
  125. async function monitorTitle() {
  126. const titleEl = await waitForElement("head > title");
  127. const sync = () => {
  128. if (document.title.endsWith(" / X")) {
  129. document.title = `${document.title.slice(0, -1)}Twitter`;
  130. }
  131. };
  132. sync();
  133. window.addEventListener("visibilitychange", sync);
  134. new MutationObserver(sync).observe(titleEl, mutationObserverOptions);
  135. }
  136. main();
  137.  
  138. })();