X.com Verified Accounts Customizer

Customize the appearance of verified accounts on X.com with adjustable settings

  1. // ==UserScript==
  2. // @name X.com Verified Accounts Customizer
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.0
  5. // @description Customize the appearance of verified accounts on X.com with adjustable settings
  6. // @author dursunator
  7. // @match *://*.x.com/*
  8. // @icon https://www.google.com/s2/favicons?sz=64&domain=x.com
  9. // @grant GM_getValue
  10. // @grant GM_setValue
  11. // @grant GM_registerMenuCommand
  12. // ==/UserScript==
  13.  
  14. (function() {
  15. 'use strict';
  16.  
  17. const defaultSettings = {
  18. opacity: 0.5,
  19. zoom: 0.75,
  20. enabled: true
  21. };
  22.  
  23. let settings = GM_getValue('verifiedAccountSettings', defaultSettings);
  24.  
  25. applySettings();
  26.  
  27. GM_registerMenuCommand('Edit Settings', showSettingsPanel);
  28.  
  29. function applySettings() {
  30. const oldStyle = document.getElementById('x-verified-customizer');
  31. if (oldStyle) {
  32. oldStyle.remove();
  33. }
  34.  
  35. if (!settings.enabled) return;
  36.  
  37. const styleElement = document.createElement('style');
  38. styleElement.id = 'x-verified-customizer';
  39. styleElement.innerHTML = `
  40. article[data-testid="tweet"]:has([data-testid="icon-verified"]) {
  41. opacity: ${settings.opacity};
  42. zoom: ${settings.zoom};
  43. }
  44. `;
  45. document.querySelector("head").appendChild(styleElement);
  46. }
  47.  
  48. function showSettingsPanel() {
  49. if (document.getElementById('x-settings-panel')) return;
  50.  
  51. const panel = document.createElement('div');
  52. panel.id = 'x-settings-panel';
  53. panel.style.cssText = `
  54. position: fixed;
  55. top: 50%;
  56. left: 50%;
  57. transform: translate(-50%, -50%);
  58. background-color: #15202B;
  59. color: #E7E9EA;
  60. border-radius: 12px;
  61. padding: 24px;
  62. z-index: 10000;
  63. box-shadow: 0 0 20px rgba(0,0,0,0.7);
  64. min-width: 320px;
  65. font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  66. `;
  67.  
  68. const heading = document.createElement('h2');
  69. heading.textContent = 'Verified Account Settings';
  70. heading.style.cssText = `
  71. margin-top: 0;
  72. color: #1D9BF0;
  73. border-bottom: 1px solid #38444D;
  74. padding-bottom: 12px;
  75. font-size: 20px;
  76. `;
  77. panel.appendChild(heading);
  78.  
  79. const enabledDiv = document.createElement('div');
  80. enabledDiv.style.margin = '16px 0';
  81. enabledDiv.style.display = 'flex';
  82. enabledDiv.style.alignItems = 'center';
  83. enabledDiv.style.justifyContent = 'space-between';
  84.  
  85. const enabledLabel = document.createElement('label');
  86. enabledLabel.textContent = 'Enable Feature: ';
  87. enabledLabel.style.fontWeight = '500';
  88.  
  89. const enabledCheckbox = document.createElement('input');
  90. enabledCheckbox.type = 'checkbox';
  91. enabledCheckbox.checked = settings.enabled;
  92. enabledCheckbox.id = 'x-enabled';
  93. enabledCheckbox.style.transform = 'scale(1.2)';
  94. enabledCheckbox.style.accentColor = '#1D9BF0';
  95.  
  96. enabledDiv.appendChild(enabledLabel);
  97. enabledDiv.appendChild(enabledCheckbox);
  98. panel.appendChild(enabledDiv);
  99.  
  100. const opacityDiv = document.createElement('div');
  101. opacityDiv.style.margin = '16px 0';
  102.  
  103. const opacityLabel = document.createElement('label');
  104. opacityLabel.textContent = 'Opacity (0.1 - 1.0): ';
  105. opacityLabel.style.display = 'block';
  106. opacityLabel.style.marginBottom = '8px';
  107. opacityLabel.style.fontWeight = '500';
  108.  
  109. const opacitySliderContainer = document.createElement('div');
  110. opacitySliderContainer.style.display = 'flex';
  111. opacitySliderContainer.style.alignItems = 'center';
  112.  
  113. const opacityInput = document.createElement('input');
  114. opacityInput.type = 'range';
  115. opacityInput.min = '0.1';
  116. opacityInput.max = '1.0';
  117. opacityInput.step = '0.1';
  118. opacityInput.value = settings.opacity;
  119. opacityInput.id = 'x-opacity';
  120. opacityInput.style.flex = '1';
  121. opacityInput.style.accentColor = '#1D9BF0';
  122.  
  123. const opacityValue = document.createElement('span');
  124. opacityValue.textContent = settings.opacity;
  125. opacityValue.style.marginLeft = '10px';
  126. opacityValue.style.backgroundColor = '#253341';
  127. opacityValue.style.padding = '4px 8px';
  128. opacityValue.style.borderRadius = '4px';
  129. opacityValue.style.minWidth = '36px';
  130. opacityValue.style.textAlign = 'center';
  131.  
  132. opacityInput.addEventListener('input', () => {
  133. opacityValue.textContent = opacityInput.value;
  134. });
  135.  
  136. opacitySliderContainer.appendChild(opacityInput);
  137. opacitySliderContainer.appendChild(opacityValue);
  138.  
  139. opacityDiv.appendChild(opacityLabel);
  140. opacityDiv.appendChild(opacitySliderContainer);
  141. panel.appendChild(opacityDiv);
  142.  
  143. const zoomDiv = document.createElement('div');
  144. zoomDiv.style.margin = '16px 0';
  145.  
  146. const zoomLabel = document.createElement('label');
  147. zoomLabel.textContent = 'Size Ratio (0.5 - 1.0): ';
  148. zoomLabel.style.display = 'block';
  149. zoomLabel.style.marginBottom = '8px';
  150. zoomLabel.style.fontWeight = '500';
  151.  
  152. const zoomSliderContainer = document.createElement('div');
  153. zoomSliderContainer.style.display = 'flex';
  154. zoomSliderContainer.style.alignItems = 'center';
  155.  
  156. const zoomInput = document.createElement('input');
  157. zoomInput.type = 'range';
  158. zoomInput.min = '0.5';
  159. zoomInput.max = '1.0';
  160. zoomInput.step = '0.05';
  161. zoomInput.value = settings.zoom;
  162. zoomInput.id = 'x-zoom';
  163. zoomInput.style.flex = '1';
  164. zoomInput.style.accentColor = '#1D9BF0';
  165.  
  166. const zoomValue = document.createElement('span');
  167. zoomValue.textContent = settings.zoom;
  168. zoomValue.style.marginLeft = '10px';
  169. zoomValue.style.backgroundColor = '#253341';
  170. zoomValue.style.padding = '4px 8px';
  171. zoomValue.style.borderRadius = '4px';
  172. zoomValue.style.minWidth = '36px';
  173. zoomValue.style.textAlign = 'center';
  174.  
  175. zoomInput.addEventListener('input', () => {
  176. zoomValue.textContent = zoomInput.value;
  177. });
  178.  
  179. zoomSliderContainer.appendChild(zoomInput);
  180. zoomSliderContainer.appendChild(zoomValue);
  181.  
  182. zoomDiv.appendChild(zoomLabel);
  183. zoomDiv.appendChild(zoomSliderContainer);
  184. panel.appendChild(zoomDiv);
  185.  
  186. const buttonsDiv = document.createElement('div');
  187. buttonsDiv.style.cssText = `
  188. display: flex;
  189. justify-content: space-between;
  190. margin-top: 24px;
  191. `;
  192.  
  193. const saveButton = document.createElement('button');
  194. saveButton.textContent = 'Save';
  195. saveButton.style.cssText = `
  196. background-color: #1D9BF0;
  197. color: white;
  198. border: none;
  199. padding: 10px 18px;
  200. border-radius: 20px;
  201. cursor: pointer;
  202. font-weight: bold;
  203. transition: background-color 0.2s;
  204. `;
  205. saveButton.addEventListener('mouseover', () => {
  206. saveButton.style.backgroundColor = '#1A8CD8';
  207. });
  208. saveButton.addEventListener('mouseout', () => {
  209. saveButton.style.backgroundColor = '#1D9BF0';
  210. });
  211.  
  212. const cancelButton = document.createElement('button');
  213. cancelButton.textContent = 'Cancel';
  214. cancelButton.style.cssText = `
  215. background-color: #273340;
  216. color: #E7E9EA;
  217. border: none;
  218. padding: 10px 18px;
  219. border-radius: 20px;
  220. cursor: pointer;
  221. font-weight: bold;
  222. transition: background-color 0.2s;
  223. `;
  224. cancelButton.addEventListener('mouseover', () => {
  225. cancelButton.style.backgroundColor = '#323F4D';
  226. });
  227. cancelButton.addEventListener('mouseout', () => {
  228. cancelButton.style.backgroundColor = '#273340';
  229. });
  230.  
  231. const resetButton = document.createElement('button');
  232. resetButton.textContent = 'Reset';
  233. resetButton.style.cssText = `
  234. background-color: #F4212E;
  235. color: white;
  236. border: none;
  237. padding: 10px 18px;
  238. border-radius: 20px;
  239. cursor: pointer;
  240. font-weight: bold;
  241. transition: background-color 0.2s;
  242. `;
  243. resetButton.addEventListener('mouseover', () => {
  244. resetButton.style.backgroundColor = '#E0202B';
  245. });
  246. resetButton.addEventListener('mouseout', () => {
  247. resetButton.style.backgroundColor = '#F4212E';
  248. });
  249.  
  250. buttonsDiv.appendChild(resetButton);
  251. buttonsDiv.appendChild(cancelButton);
  252. buttonsDiv.appendChild(saveButton);
  253. panel.appendChild(buttonsDiv);
  254.  
  255. const overlay = document.createElement('div');
  256. overlay.style.cssText = `
  257. position: fixed;
  258. top: 0;
  259. left: 0;
  260. right: 0;
  261. bottom: 0;
  262. background-color: rgba(0,0,0,0.7);
  263. z-index: 9999;
  264. `;
  265.  
  266. saveButton.addEventListener('click', () => {
  267. settings = {
  268. opacity: parseFloat(opacityInput.value),
  269. zoom: parseFloat(zoomInput.value),
  270. enabled: enabledCheckbox.checked
  271. };
  272.  
  273. GM_setValue('verifiedAccountSettings', settings);
  274. applySettings();
  275.  
  276. overlay.remove();
  277. panel.remove();
  278. });
  279.  
  280. cancelButton.addEventListener('click', () => {
  281. overlay.remove();
  282. panel.remove();
  283. });
  284.  
  285. resetButton.addEventListener('click', () => {
  286. opacityInput.value = defaultSettings.opacity;
  287. opacityValue.textContent = defaultSettings.opacity;
  288.  
  289. zoomInput.value = defaultSettings.zoom;
  290. zoomValue.textContent = defaultSettings.zoom;
  291.  
  292. enabledCheckbox.checked = defaultSettings.enabled;
  293. });
  294.  
  295. document.body.appendChild(overlay);
  296. document.body.appendChild(panel);
  297. }
  298.  
  299. const observer = new MutationObserver(() => {
  300. applySettings();
  301. });
  302.  
  303. observer.observe(document.body, {
  304. childList: true,
  305. subtree: true
  306. });
  307. })();