Greasy Fork is available in English.

Noise's 2016 Website UI Tweaks

Multiple UI Tweaks to make the website look more accurate to how it was back in 2016!

  1. // ==UserScript==
  2. // @name Noise's 2016 Website UI Tweaks
  3. // @namespace http://tampermonkey.net/
  4. // @version 2.3
  5. // @description Multiple UI Tweaks to make the website look more accurate to how it was back in 2016!
  6. // @author The Noise!
  7. // @match https://*.roblox.com/*
  8. // @icon data:image/png;base64,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
  9. // @license MIT
  10. // ==/UserScript==
  11.  
  12. (function () {
  13. 'use strict';
  14.  
  15. // Define replaceAvatarImages function at the top level
  16. const replaceAvatarImages = () => {
  17. // Only run on specified pages
  18. if (!window.location.href.includes('roblox.com/home') &&
  19. !window.location.href.includes('roblox.com/communities/') &&
  20. !window.location.href.includes('roblox.com/users/') &&
  21. !window.location.href.includes('roblox.com/search/users')) {
  22. return;
  23. }
  24.  
  25. // First, ensure header avatars are always headshots
  26. const headerAvatars = [
  27. '#home-header img.avatar-card-image',
  28. '.container-header img[src*="AvatarHeadshot"]'
  29. ];
  30.  
  31. headerAvatars.forEach(selector => {
  32. const headerAvatar = document.querySelector(selector);
  33. if (headerAvatar && headerAvatar.src.includes('30DAY-Avatar-')) {
  34. headerAvatar.src = headerAvatar.src.replace('30DAY-Avatar-', '30DAY-AvatarHeadshot-');
  35. console.log('Restored header avatar to headshot');
  36. }
  37. });
  38.  
  39. // Handle user search page
  40. if (window.location.href.includes('roblox.com/search/users')) {
  41. const searchResultImages = document.querySelectorAll('.avatar-card-container img[src^="https://tr.rbxcdn.com/30DAY-AvatarHeadshot-"]');
  42. searchResultImages.forEach(image => {
  43. if (image.closest('.container-header')) return; // Skip container-header images
  44. const newSrc = image.src.replace("30DAY-AvatarHeadshot-", "30DAY-Avatar-");
  45. image.src = newSrc;
  46. console.log(`Updated search result image source to: ${newSrc}`);
  47. });
  48. return;
  49. }
  50.  
  51. // Handle friends/followers/following pages
  52. if (window.location.href.includes('roblox.com/users/') && window.location.href.includes('#!/')) {
  53. const userListImages = document.querySelectorAll('.list-item img[src^="https://tr.rbxcdn.com/30DAY-AvatarHeadshot-"]');
  54. userListImages.forEach(image => {
  55. if (image.closest('.container-header')) return; // Skip container-header images
  56. const newSrc = image.src.replace("30DAY-AvatarHeadshot-", "30DAY-Avatar-");
  57. image.src = newSrc;
  58. console.log(`Updated user list image source to: ${newSrc}`);
  59. });
  60. return;
  61. }
  62.  
  63. // Handle avatars in friends carousel on user profile pages
  64. if (window.location.href.includes('roblox.com/users/')) {
  65. const friendsCarouselImages = document.querySelectorAll('.friends-carousel-container img[src^="https://tr.rbxcdn.com/30DAY-AvatarHeadshot-"]');
  66. friendsCarouselImages.forEach(image => {
  67. if (image.closest('.container-header')) return; // Skip container-header images
  68. const newSrc = image.src.replace("30DAY-AvatarHeadshot-", "30DAY-Avatar-");
  69. image.src = newSrc;
  70. console.log(`Updated friends carousel image source to: ${newSrc}`);
  71. });
  72. return;
  73. }
  74.  
  75. // Handle other pages (home and communities)
  76. const avatarImages = document.querySelectorAll('img[src^="https://tr.rbxcdn.com/30DAY-AvatarHeadshot-"]');
  77. avatarImages.forEach(image => {
  78. if (image.closest('#home-header') || image.closest('.container-header')) {
  79. return;
  80. }
  81.  
  82. if (image.id === "home-avatar-thumb") {
  83. console.log('Skipped updating home avatar image.');
  84. return;
  85. }
  86.  
  87. const newSrc = image.src.replace("30DAY-AvatarHeadshot-", "30DAY-Avatar-");
  88. image.src = newSrc;
  89. console.log(`Updated image source to: ${newSrc}`);
  90. });
  91. };
  92.  
  93. const modifyUI = () => {
  94. // Remove "Money" navigation element
  95. const moneyNav = document.querySelector('a#nav-money');
  96. if (moneyNav) {
  97. moneyNav.remove();
  98. console.log('Removed "Money" navigation element.');
  99. }
  100.  
  101. // Remove "Premium" navigation element
  102. const premiumNav = document.querySelector('a#nav-premium');
  103. if (premiumNav) {
  104. premiumNav.remove();
  105. console.log('Removed "Premium" navigation element.');
  106. }
  107.  
  108. // Add Message button to user profile pages
  109. if (window.location.href.includes('roblox.com/users/')) {
  110. const addFriendButton = document.querySelector('.details-actions.desktop-action .btn-friends');
  111. if (addFriendButton && !document.querySelector('.btn-message')) {
  112. const messageButtonLi = document.createElement('li');
  113. messageButtonLi.className = 'btn-message';
  114. messageButtonLi.innerHTML = `
  115. <button class="btn-control-md" ng-disabled="!profileHeaderLayout.canMessage || profileHeaderLayout.userId == 0" ng-click="sendMessage()" disabled="disabled">
  116. Message
  117. </button>
  118. `;
  119. addFriendButton.insertAdjacentElement('afterend', messageButtonLi);
  120. console.log('Added Message button next to Add Friend button');
  121. }
  122. }
  123.  
  124. // Replace "Communities" with "Groups"
  125. document.querySelectorAll('span.font-header-2.dynamic-ellipsis-item[title="Communities"]').forEach(element => {
  126. if (element.textContent.trim() === "Communities") {
  127. element.textContent = "Groups";
  128. console.log('Replaced "Communities" with "Groups".');
  129. }
  130. });
  131.  
  132. // Replace "Communities" in visible text nodes
  133. document.querySelectorAll('*:not(script):not(style)').forEach(node => {
  134. if (node.childNodes.length) {
  135. node.childNodes.forEach(child => {
  136. if (child.nodeType === Node.TEXT_NODE && child.nodeValue.includes("Communities")) {
  137. child.nodeValue = child.nodeValue.replace(/Communities/g, "Groups");
  138. }
  139. });
  140. }
  141. });
  142.  
  143. // Replace group-related text
  144. const elements = {
  145. 'button#group-join-button': 'Join Community|Join Group',
  146. 'button.ng-binding': 'Leave Community|Leave Group',
  147. 'a.ng-binding': 'Configure Community|Configure Group'
  148. };
  149.  
  150. for (const [selector, replacement] of Object.entries(elements)) {
  151. const [oldText, newText] = replacement.split('|');
  152. document.querySelectorAll(selector).forEach(element => {
  153. if (element.textContent.trim() === oldText) {
  154. element.textContent = newText;
  155. console.log(`Replaced "${oldText}" with "${newText}"`);
  156. }
  157. });
  158. }
  159. };
  160.  
  161. // Comments section functionality - only runs on game pages
  162. if (window.location.href.includes('roblox.com/games/')) {
  163. const addCommentsSection = (forceFallback = false) => {
  164. if (document.getElementById('AjaxCommentsContainer')) return true;
  165.  
  166. const commentsHTML = `
  167. <div id="AjaxCommentsContainer" class="comments-container" data-asset-id="32990482" data-total-collection-size="" data-is-user-authenticated="False" data-signin-url="https://www.roblox.com/newlogin?returnUrl=%2Fgames%2F32990482%2FFlood-Escape">
  168. <h3>Comments</h3>
  169. <div class="section-content AddAComment">
  170. <div class="comment-form">
  171. <form class="form-horizontal ng-pristine ng-valid" role="form">
  172. <div class="form-group">
  173. <textarea class="form-control input-field rbx-comment-input blur" placeholder="Write a comment!" rows="1"></textarea>
  174. <div class="rbx-comment-msgs">
  175. <span class="rbx-comment-error text-error" style="display: none;"> </span>
  176. <span class="rbx-comment-count small"></span>
  177. </div>
  178. </div>
  179. <button type="button" class="btn-secondary-md rbx-post-comment">Post Comment</button>
  180. </form>
  181. </div>
  182. <div class="comments vlist">
  183. <div class="empty">No comments found.</div>
  184. </div>
  185. </div>
  186. </div>
  187. `;
  188.  
  189. if (!forceFallback) {
  190. const badgesList = document.querySelector('.stack.badge-container.game-badges-list');
  191. if (badgesList) {
  192. badgesList.insertAdjacentHTML('afterend', commentsHTML);
  193. setupCommentButton();
  194. return true;
  195. }
  196. return false;
  197. }
  198.  
  199. const recommendedSection = document.querySelector('.container-list.games-detail');
  200. if (recommendedSection) {
  201. recommendedSection.insertAdjacentHTML('beforebegin', commentsHTML);
  202. setupCommentButton();
  203. return true;
  204. }
  205.  
  206. return false;
  207. };
  208.  
  209. const setupCommentButton = () => {
  210. const postCommentButton = document.querySelector('.rbx-post-comment');
  211. if (postCommentButton) {
  212. postCommentButton.addEventListener('click', (event) => {
  213. event.preventDefault();
  214. });
  215. }
  216. };
  217.  
  218. const init = () => {
  219. let badgeAttempts = 0;
  220. const maxBadgeAttempts = 15;
  221.  
  222. const badgeInterval = setInterval(() => {
  223. badgeAttempts++;
  224. if (addCommentsSection(false)) {
  225. clearInterval(badgeInterval);
  226. } else if (badgeAttempts >= maxBadgeAttempts) {
  227. clearInterval(badgeInterval);
  228. addCommentsSection(true);
  229. }
  230. }, 1000);
  231.  
  232. addCommentsSection(false);
  233. };
  234.  
  235. init();
  236. }
  237.  
  238. // Run initial modifications
  239. modifyUI();
  240. replaceAvatarImages();
  241.  
  242. // Observe the DOM for dynamic changes with both functions
  243. const observer = new MutationObserver(() => {
  244. modifyUI();
  245. replaceAvatarImages();
  246. });
  247.  
  248. observer.observe(document.body, { childList: true, subtree: true });
  249. })();