X/Twitter 干净的选单和侧边栏(支持多种语言)

干净的 选单、Grok、高级订阅、已认证组织、其他、探索、通知、私信、书签、书签和可自订设定

目前为 2025-02-27 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name X/Twitter Clean menu and sidebar (Supports multiple language)
  3. // @name:ja X/Twitter きれいなメニューとサイドバー(多言語対応)
  4. // @name:zh-TW X/Twitter 乾淨的選單和側邊欄(支持多種語言)
  5. // @name:zh-cn X/Twitter 干净的选单和侧边栏(支持多种语言)
  6. // @version 2.1
  7. // @description hidden Menu,Grok,Premium subscription,Verified Orgs,other,Explore,Notifications,Messages,Communities,Bookmarks and Customizable Settings
  8. // @description:ja 清潔なメニュー、Grok、高度なサブスクリプション、認証済み組織、他の、探索、通知、メッセージ、コミュニティ、ブックマーク、およびカスタム設定
  9. // @description:zh-tw 乾淨的 選單、Grok、高級訂閱、已認證組織、其他、探索、通知、訊息、社群、書籤和可自訂設定
  10. // @description:zh-cn 干净的 选单、Grok、高级订阅、已认证组织、其他、探索、通知、私信、书签、书签和可自订设定
  11. // @license MIT
  12. // @author movwei
  13. // @match https://x.com/*
  14. // @match https://twitter.com/*
  15. // @grant GM_registerMenuCommand
  16. // @grant GM_setValue
  17. // @grant GM_getValue
  18. // @grant GM_addStyle
  19. // @namespace https://greasyfork.org/users/1041101
  20. // ==/UserScript==
  21.  
  22. (function() {
  23. 'use strict';
  24.  
  25. const defaultSettings = {
  26. hideGrok: true,
  27. hidePremiumSignUp: true,
  28. hideSelectors: true,
  29. hideVerifiedOrgs: true,
  30. hideother: true,
  31. hideExplore: false,
  32. hideNotifications: false,
  33. hideBookmarks: false,
  34. hideMessages: false,
  35. hideCommunities: false,
  36. };
  37.  
  38. const settings = {
  39. hideGrok: GM_getValue('hideGrok', defaultSettings.hideGrok),
  40. hidePremiumSignUp: GM_getValue('hidePremiumSignUp', defaultSettings.hidePremiumSignUp),
  41. hideSelectors: GM_getValue('hideSelectors', defaultSettings.hideSelectors),
  42. hideVerifiedOrgs: GM_getValue('hideVerifiedOrgs', defaultSettings.hideVerifiedOrgs),
  43. hideother: GM_getValue('hideother', defaultSettings.hideother),
  44. hideExplore: GM_getValue('hideExplore', defaultSettings.hideExplore),
  45. hideNotifications: GM_getValue('hideNotifications', defaultSettings.hideNotifications),
  46. hideBookmarks: GM_getValue('hideBookmarks', defaultSettings.hideBookmarks),
  47. hideCommunities: GM_getValue('hideCommunities', defaultSettings.hideCommunities),
  48. hideMessages: GM_getValue('hideMessages', defaultSettings.hideMessages),
  49. };
  50.  
  51. // 多語言支持
  52. const language = navigator.language || navigator.userLanguage;
  53. const languages = {
  54. 'en': {
  55. 'hideGrok': 'Hide Grok',
  56. 'hidePremiumSignUp': 'Hide Premium Sign-up',
  57. 'hideSelectors': 'Hide Subscribe Message',
  58. 'hideVerifiedOrgs': 'Hide Verified Orgs',
  59. 'hideExplore': 'Hide Explore',
  60. 'hideNotifications': 'Hide Notifications',
  61. 'hideMessages': 'Hide Messages',
  62. 'hideCommunities': 'Hide Communities',
  63. 'hideother': 'Hide other',
  64. 'settings': 'Settings',
  65. 'saveRefresh': 'Save & refresh',
  66. 'close': 'Close'
  67. },
  68. 'zh-TW': {
  69. 'hideGrok': '隱藏 Grok',
  70. 'hidePremiumSignUp': '隱藏 高級訂閱',
  71. 'hideSelectors': '隱藏 訂閱訊息',
  72. 'hideVerifiedOrgs': '隱藏 已認證組織',
  73. 'hideExplore': '隱藏 探索',
  74. 'hideNotifications': '隱藏 通知',
  75. 'hideMessages': '隱藏 訊息',
  76. 'hideCommunities': '隱藏 社群',
  77. 'hideBookmarks': '隱藏 書籤',
  78. 'hideother': '隱藏 其他',
  79. 'settings': '設定',
  80. 'saveRefresh': '保存並刷新',
  81. 'close': '關閉'
  82. },
  83. 'zh-CN': {
  84. 'hideGrok': '隐藏 Grok',
  85. 'hidePremiumSignUp': '隐藏 高级订阅',
  86. 'hideSelectors': '隐藏 订阅消息',
  87. 'hideVerifiedOrgs': '隐藏 已认证组织',
  88. 'hideExplore': '隐藏 探索',
  89. 'hideNotifications': '隐藏 通知',
  90. 'hideMessages': '隐藏 私信',
  91. 'hideCommunities': '隐藏 社群',
  92. 'hideBookmarks': '隐藏 书签',
  93. 'hideother': '隐藏 其他',
  94. 'settings': '设置',
  95. 'saveRefresh': '保存并刷新',
  96. 'close': '关闭'
  97. },
  98. 'ja': {
  99. 'hideGrok': 'Grokを非表示',
  100. 'hidePremiumSignUp': 'プレミアムサインアップを非表示',
  101. 'hideSelectors': 'サブスクライブメッセージを非表示',
  102. 'hideVerifiedOrgs': '認証済み組織を非表示',
  103. 'hideExplore': '話題を検索を非表示',
  104. 'hideNotifications': '通知を非表示',
  105. 'hideMessages': 'メッセージを非表示',
  106. 'hideCommunities': 'コミュニティを非表示',
  107. 'hideBookmarks': 'ブックマークを非表示',
  108. 'hideother': '他のを非表示',
  109. 'settings': '設定',
  110. 'saveRefresh': '保存してリフレッシュ',
  111. 'close': '閉じる'
  112. },
  113. };
  114.  
  115. const currentLanguage = languages[language] || languages['en'];
  116.  
  117. function createSettingsPanel() {
  118. const panel = document.createElement('div');
  119. panel.id = 'settingsPanel';
  120. panel.innerHTML = `
  121. <div id="settingsPanelContent">
  122. <h2>${currentLanguage['settings']}</h2>
  123. <label><input type="checkbox" id="hideGrokCheckbox" ${settings.hideGrok ? 'checked' : ''}> ${currentLanguage['hideGrok']}</label><br>
  124. <label><input type="checkbox" id="hidePremiumSignUpCheckbox" ${settings.hidePremiumSignUp ? 'checked' : ''}> ${currentLanguage['hidePremiumSignUp']}</label><br>
  125. <label><input type="checkbox" id="hideSelectorsCheckbox" ${settings.hideSelectors ? 'checked' : ''}> ${currentLanguage['hideSelectors']}</label><br>
  126. <label><input type="checkbox" id="hideVerifiedOrgsCheckbox" ${settings.hideVerifiedOrgs ? 'checked' : ''}> ${currentLanguage['hideVerifiedOrgs']}</label><br>
  127. <label><input type="checkbox" id="hideotherCheckbox" ${settings.hideother ? 'checked' : ''}> ${currentLanguage['hideother']}</label><br>
  128. <label><input type="checkbox" id="hideExploreCheckbox" ${settings.hideExplore ? 'checked' : ''}> ${currentLanguage['hideExplore']}</label><br>
  129. <label><input type="checkbox" id="hideNotificationsCheckbox" ${settings.hideNotifications ? 'checked' : ''}> ${currentLanguage['hideNotifications']}</label><br>
  130. <label><input type="checkbox" id="hideMessagesCheckbox" ${settings.hideMessages ? 'checked' : ''}> ${currentLanguage['hideMessages']}</label><br>
  131. <label><input type="checkbox" id="hideCommunitiesCheckbox" ${settings.hideCommunities ? 'checked' : ''}> ${currentLanguage['hideCommunities']}</label><br>
  132. <label><input type="checkbox" id="hideBookmarksCheckbox" ${settings.hideBookmarks ? 'checked' : ''}> ${currentLanguage['hideBookmarks']}</label><br>
  133. <button id="saveSettingsButton">${currentLanguage['saveRefresh']}</button>
  134. <button id="closeSettingsButton">${currentLanguage['close']}</button>
  135. </div>
  136. `;
  137. document.body.appendChild(panel);
  138.  
  139. document.getElementById('saveSettingsButton').addEventListener('click', saveSettings);
  140.  
  141. document.getElementById('closeSettingsButton').addEventListener('click', () => {
  142. document.getElementById('settingsPanel').style.display = 'none';
  143. });
  144. }
  145.  
  146. function saveSettings() {
  147. settings.hideGrok = document.getElementById('hideGrokCheckbox').checked;
  148. settings.hidePremiumSignUp = document.getElementById('hidePremiumSignUpCheckbox').checked;
  149. settings.hideSelectors = document.getElementById('hideSelectorsCheckbox').checked;
  150. settings.hideVerifiedOrgs = document.getElementById('hideVerifiedOrgsCheckbox').checked;
  151. settings.hideExplore = document.getElementById('hideExploreCheckbox').checked;
  152. settings.hideNotifications = document.getElementById('hideNotificationsCheckbox').checked;
  153. settings.hideBookmarks = document.getElementById('hideBookmarksCheckbox').checked;
  154. settings.hideMessages = document.getElementById('hideMessagesCheckbox').checked;
  155. settings.hideCommunities = document.getElementById('hideCommunitiesCheckbox').checked;
  156. settings.hideother = document.getElementById('hideotherCheckbox').checked;
  157.  
  158. GM_setValue('hideGrok', settings.hideGrok);
  159. GM_setValue('hidePremiumSignUp', settings.hidePremiumSignUp);
  160. GM_setValue('hideSelectors', settings.hideSelectors);
  161. GM_setValue('hideVerifiedOrgs', settings.hideVerifiedOrgs);
  162. GM_setValue('hideExplore', settings.hideExplore);
  163. GM_setValue('hideNotifications', settings.hideNotifications);
  164. GM_setValue('hideBookmarks', settings.hideBookmarks);
  165. GM_setValue('hideMessages', settings.hideMessages);
  166. GM_setValue('hideCommunities', settings.hideCommunities);
  167. GM_setValue('hideother', settings.hideother);
  168. location.reload();
  169. }
  170.  
  171. GM_addStyle(`
  172. #settingsPanel {
  173. width: 250px;
  174. position: fixed;
  175. top: 50%;
  176. left: 50%;
  177. transform: translate(-50%, -50%);
  178. background-color: white;
  179. border: 1px solid #ccc;
  180. padding: 20px;
  181. z-index: 10000;
  182. display: none;
  183. box-shadow: 0 4px 8px rgba(0,0,0,0.1);
  184. border-radius: 8px;
  185. }
  186.  
  187. #settingsPanelContent {
  188. display: flex;
  189. flex-direction: column;
  190. align-items: flex-start;
  191. width: 100%;
  192. }
  193.  
  194. #settingsPanel h2 {
  195. margin: 0 0 15px 0;
  196. font-size: 18px;
  197. color: #333;
  198. text-align: center;
  199. width: 100%;
  200. }
  201.  
  202. #settingsPanel label {
  203. margin: 5px 0;
  204. font-size: 14px;
  205. color: #333;
  206. }
  207.  
  208. #settingsPanel button {
  209. margin-top: 10px;
  210. padding: 8px 15px;
  211. font-size: 14px;
  212. color: white;
  213. background-color: #007BFF;
  214. border: none;
  215. border-radius: 4px;
  216. cursor: pointer;
  217. width: 100%;
  218. }
  219.  
  220. #settingsPanel button#closeSettingsButton {
  221. background-color: #6c757d;
  222. }
  223. `);
  224.  
  225. createSettingsPanel();
  226. GM_registerMenuCommand(currentLanguage['settings'], () => {
  227. const panel = document.getElementById('settingsPanel');
  228. panel.style.display = 'block';
  229. });
  230.  
  231. function addGlobalStyle(css) {
  232. var head, style;
  233. head = document.getElementsByTagName('head')[0];
  234. if (!head) { return; }
  235. style = document.createElement('style');
  236. style.type = 'text/css';
  237. style.innerHTML = css;
  238. head.appendChild(style);
  239. }
  240.  
  241. var cssRules = '';
  242.  
  243. if (settings.hideSelectors) {
  244. const observer = new MutationObserver(mutations => {
  245. mutations.forEach(mutation => {
  246. const elements = document.querySelectorAll('.css-175oi2r.r-1habvwh.r-eqz5dr.r-uaa2di.r-1mmae3n.r-3pj75a.r-bnwqim');
  247. elements.forEach(element => {
  248. const parentDiv = element.closest('div');
  249. if (parentDiv) {
  250. parentDiv.remove();
  251. }
  252. });
  253. });
  254. });
  255.  
  256. observer.observe(document.body, { childList: true, subtree: true });
  257. }
  258.  
  259. if (settings.hideGrok) {
  260. const targetPathD = "M2.205 7.423L11.745 21h4.241L6.446 7.423H2.204zm4.237 7.541L2.2 21h4.243l2.12-3.017-2.121-3.02zM16.957 0L9.624 10.435l2.122 3.02L21.2 0h-4.243zm.767 6.456V21H21.2V1.51l-3.476 4.946z";
  261. const targetGrokImageGenPathD = "M12.745 20.54l10.97-8.19c.539-.4 1.307-.244 1.564.38 1.349 3.288.746 7.241-1.938 9.955-2.683 2.714-6.417 3.31-9.83 1.954l-3.728 1.745c5.347 3.697 11.84 2.782 15.898-1.324 3.219-3.255 4.216-7.692 3.284-11.693l.008.009c-1.351-5.878.332-8.227 3.782-13.031L33 0l-4.54 4.59v-.014L12.743 20.544M10.48 22.531c-3.837-3.707-3.175-9.446.1-12.755 2.42-2.449 6.388-3.448 9.852-1.979l3.72-1.737c-.67-.49-1.53-1.017-2.515-1.387-4.455-1.854-9.789-.931-13.41 2.728-3.483 3.523-4.579 8.94-2.697 13.561 1.405 3.454-.899 5.898-3.22 8.364C1.49 30.2.666 31.074 0 32l10.478-9.466";
  262. const observer = new MutationObserver(mutations => {
  263. mutations.forEach(mutation => {
  264. const svgs = document.querySelectorAll('svg[aria-hidden="true"].r-4qtqp9');
  265. svgs.forEach(svg => {
  266. const path = svg.querySelector('path');
  267. if (path && path.getAttribute('d') === targetPathD) {
  268. const container = svg.closest('button') || svg.closest('div');
  269. if (container) {
  270. container.remove();
  271. }
  272. }
  273. });
  274.  
  275. const grokImgGenButtons = document.querySelectorAll('button[data-testid="grokImgGen"]');
  276. grokImgGenButtons.forEach(button => {
  277. button.remove();
  278. });
  279. });
  280. });
  281. observer.observe(document.body, { childList: true, subtree: true });
  282.  
  283. GM_addStyle(`
  284. a[href="/i/grok"] {
  285. display: none !important;
  286. }
  287. .css-175oi2r.r-1867qdf.r-xnswec.r-13awgt0.r-1ce3o0f.r-1udh08x.r-u8s1d.r-13qz1uu.r-173mn98.r-1e5uvyk.r-ii8lfi.r-40lpo0.r-rs99b7.r-12jitg0 {
  288. display: none;
  289. }
  290. `);
  291. }
  292. if (settings.hideCommunities) {
  293. const targetCommunitiesPathD = "M7.501 19.917L7.471 21H.472l.029-1.027c.184-6.618 3.736-8.977 7-8.977.963 0 1.95.212 2.87.672-.444.478-.851 1.03-1.212 1.656-.507-.204-1.054-.329-1.658-.329-2.767 0-4.57 2.223-4.938 6.004H7.56c-.023.302-.05.599-.059.917zm15.998.056L23.528 21H9.472l.029-1.027c.184-6.618 3.736-8.977 7-8.977s6.816 2.358 7 8.977zM21.437 19c-.367-3.781-2.17-6.004-4.938-6.004s-4.57 2.223-4.938 6.004h9.875zm-4.938-9c-.799 0-1.527-.279-2.116-.73-.836-.64-1.384-1.638-1.384-2.77 0-1.93 1.567-3.5 3.5-3.5s3.5 1.57 3.5 3.5c0 1.132-.548 2.13-1.384 2.77-.589.451-1.317.73-2.116.73zm-1.5-3.5c0 .827.673 1.5 1.5 1.5s1.5-.673 1.5-1.5-.673-1.5-1.5-1.5-1.5.673-1.5 1.5zM7.5 3C9.433 3 11 4.57 11 6.5S9.433 10 7.5 10 4 8.43 4 6.5 5.567 3 7.5 3zm0 2C6.673 5 6 5.673 6 6.5S6.673 8 7.5 8 9 7.327 9 6.5 8.327 5 7.5 5z";
  294.  
  295. const observerCommunities = new MutationObserver(mutations => {
  296. mutations.forEach(() => {
  297. const svgs = document.querySelectorAll('svg[aria-hidden="true"].r-4qtqp9');
  298. svgs.forEach(svg => {
  299. const path = svg.querySelector('path');
  300. if (path && path.getAttribute('d') === targetCommunitiesPathD) {
  301. const container = svg.closest('a') || svg.closest('div');
  302. if (container) {
  303. container.remove();
  304. }
  305. }
  306. });
  307. });
  308. });
  309. observerCommunities.observe(document.body, { childList: true, subtree: true });
  310. }
  311. if (settings.hidePremiumSignUp) {
  312. cssRules += 'a[href="/i/premium_sign_up"] { display: none !important; }';
  313. }
  314. if (settings.hideVerifiedOrgs) {
  315. cssRules += 'a[href="/i/verified-orgs-signup"] { display: none !important; }';
  316. }
  317. if (settings.hideother) {
  318. cssRules += 'a[href="/jobs"] { display: none !important; }';
  319. cssRules += '.css-175oi2r.r-l00any.r-109y4c4.r-kuekak { display: none; }';
  320. cssRules += 'a.css-175oi2r.r-5oul0u.r-knv0ih.r-faml9v.r-2dysd3.r-13qz1uu.r-o7ynqc.r-6416eg.r-1ny4l3l.r-1loqt21 { display: none; }';
  321. cssRules += 'a.css-175oi2r.r-5oul0u.r-1wzrnnt.r-1c4vpko.r-1c7gwzm.r-13qz1uu.r-o7ynqc.r-6416eg.r-1ny4l3l.r-1loqt21 { display: none; }';
  322. }
  323. if (settings.hideExplore) {
  324. cssRules += 'a[href="/explore"] { display: none !important; }';
  325. }
  326. if (settings.hideNotifications) {
  327. cssRules += 'a[href="/notifications"] { display: none !important; }';
  328. }
  329. if (settings.hideBookmarks) {
  330. cssRules += 'a[href="/i/bookmarks"] { display: none !important; }';
  331. }
  332. if (settings.hideMessages) {
  333. cssRules += 'a[href="/messages"] { display: none !important; }';
  334. }
  335.  
  336. addGlobalStyle(cssRules);
  337. })();