Reddit Default Sort

Automatically sets Reddit's default sorting order for home and subreddits.

当前为 2025-02-11 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Reddit Default Sort
  3. // @version 1.2.0
  4. // @description Automatically sets Reddit's default sorting order for home and subreddits.
  5. // @author yodaluca23
  6. // @license MIT
  7. // @match *://*.reddit.com/*
  8. // @grant GM_getValue
  9. // @grant GM_setValue
  10. // @namespace https://greasyfork.org/users/1315976
  11. // ==/UserScript==
  12.  
  13. (function() {
  14.     'use strict';
  15.  
  16.     // Default values
  17.     const defaultHomePageSort = "new";
  18.     const defaultSubredditSort = "new";
  19. const defaultCommentSort = "new";
  20.  
  21. // This allows you to use the Reddit filters temporariliy, without it redirecting you to the default
  22. // This is a domain it should never actually be so it sorts to the default the first time, but doesn't fail being passed to URL()
  23. let lastUrl = "https://www.example.com";
  24.  
  25.     // Function to get the stored sort option, or the default if none is stored.
  26.     function getSortOption(key, defaultValue) {
  27.         let value = GM_getValue(key);
  28.         return value === undefined ? defaultValue : value;
  29.     }
  30.  
  31.     // Get the stored sort options
  32.     let homePageSort = getSortOption("homePageSort", defaultHomePageSort);
  33.     let subredditSort = getSortOption("subredditSort", defaultSubredditSort);
  34. let commentSort = getSortOption("commentSort", defaultCommentSort);
  35.  
  36.     // Function to redirect if necessary
  37.     function redirectIfNeeded() {
  38.         const currentUrl = window.location.href;
  39.  
  40. // Comment page sorting
  41. const commentPattern = /https:\/\/www\.reddit\.com\/r\/[^/]+\/comments\/[^/]+\/[^/]+\/?/;
  42. if (commentPattern.test(currentUrl) && !currentUrl.includes(`?sort=${commentSort}`)) {
  43. const urlObj = new URL(currentUrl);
  44. const justRoot = urlObj.origin + urlObj.pathname;
  45. const urlObjLast = new URL(lastUrl);
  46. const justRootLast = urlObjLast.origin + urlObjLast.pathname;
  47. if (justRootLast != justRoot) {
  48. const newUrl = `${justRoot}?sort=${commentSort}`;
  49. window.location.replace(newUrl);
  50. }
  51. }
  52.  
  53.         // Check for home page URLs
  54.         const homeUrls = [
  55.             "https://www.reddit.com/",
  56.             "https://www.reddit.com/?feed=home",
  57.             "https://www.reddit.com/best/?feed=home",
  58.             "https://www.reddit.com/hot/?feed=home",
  59.             "https://www.reddit.com/top/?feed=home",
  60.             "https://www.reddit.com/new/?feed=home",
  61.             "https://www.reddit.com/rising/?feed=home"
  62.         ];
  63.  
  64.         const homeTargetUrl = `https://www.reddit.com/${homePageSort}/?feed=home`;
  65.  
  66.         if (homeUrls.includes(currentUrl) && currentUrl !== homeTargetUrl && !homeUrls.includes(lastUrl)) {
  67. window.location.replace(homeTargetUrl);
  68. return;
  69.         }
  70.  
  71.         // Check for subreddit URLs
  72. const subredditPattern = /https:\/\/www\.reddit\.com\/r\/([^/]+)(\/(hot|new|top|best|rising))?(\/)?(\?.*)?$/;
  73.  
  74. if (subredditPattern.test(currentUrl)) {
  75. const match = currentUrl.match(subredditPattern);
  76. const subredditName = match[1];
  77.  
  78. // Check if were still on the same sub indicates the user only changed their sort we should not set it back
  79. if (subredditPattern.test(lastUrl)) {
  80. const matchLast = lastUrl.match(subredditPattern);
  81. if (subredditName == matchLast[1]) {
  82. return;
  83. }
  84. }
  85.  
  86. const targetUrl = `https://www.reddit.com/r/${subredditName}/${subredditSort}`;
  87. const altTargetUrl = `https://www.reddit.com/r/${subredditName}/${subredditSort}/`;
  88.  
  89. if (currentUrl !== targetUrl && currentUrl !== altTargetUrl) {
  90. window.location.replace(targetUrl);
  91. }
  92. }
  93.     }
  94.  
  95.     // Function to create the settings UI
  96. function createSettingsUI() {
  97. // Create the settings container
  98. const settingsContainer = document.createElement('div');
  99. settingsContainer.style.position = 'fixed';
  100. settingsContainer.style.top = '50%';
  101. settingsContainer.style.left = '50%';
  102. settingsContainer.style.transform = 'translate(-50%, -50%)';
  103. settingsContainer.style.padding = '20px';
  104. settingsContainer.style.borderRadius = '12px';
  105. settingsContainer.style.boxShadow = '0px 8px 20px rgba(0, 0, 0, 0.1)';
  106. settingsContainer.style.zIndex = '1000';
  107. settingsContainer.style.minWidth = '280px';
  108. settingsContainer.style.textAlign = 'center';
  109. settingsContainer.style.fontFamily = '"Arial", sans-serif';
  110.  
  111. // Dark/Light Mode detection based on system preference
  112. const isDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
  113. if (isDarkMode) {
  114. settingsContainer.style.backgroundColor = '#111111'; // AMOLED dark mode
  115. settingsContainer.style.color = '#fff';
  116. settingsContainer.style.border = '1px solid #444'; // Softer border for dark mode
  117. } else {
  118. settingsContainer.style.backgroundColor = '#f9f9f9';
  119. settingsContainer.style.color = '#000';
  120. settingsContainer.style.border = '1px solid #ccc'; // Softer border for light mode
  121. }
  122.  
  123. // Title
  124. const title = document.createElement('h2');
  125. title.textContent = 'Settings';
  126. title.style.marginBottom = '20px';
  127. settingsContainer.appendChild(title);
  128.  
  129. // Home page sort select
  130. const homePageLabel = document.createElement('label');
  131. homePageLabel.textContent = 'Home Page Sort:';
  132. homePageLabel.style.display = 'block';
  133. homePageLabel.style.marginBottom = '10px';
  134.  
  135. const homePageSelect = document.createElement('select');
  136. homePageSelect.id = 'homePageSortSelect';
  137. homePageSelect.style.width = '100%';
  138. homePageSelect.style.padding = '8px';
  139. homePageSelect.style.borderRadius = '5px';
  140. homePageSelect.style.backgroundColor = isDarkMode ? '#333' : '#fff'; // Darker dropdown in dark mode
  141. homePageSelect.style.color = isDarkMode ? '#fff' : '#000'; // Ensure text contrast is high
  142. homePageSelect.style.border = isDarkMode ? '1px solid #444' : '1px solid #ccc'; // Softer borders
  143.  
  144. ['best', 'hot', 'new', 'top', 'rising'].forEach(option => {
  145. const opt = document.createElement('option');
  146. opt.value = option;
  147. opt.textContent = option.charAt(0).toUpperCase() + option.slice(1);
  148. homePageSelect.appendChild(opt);
  149. });
  150. homePageSelect.value = homePageSort;
  151.  
  152. settingsContainer.appendChild(homePageLabel);
  153. settingsContainer.appendChild(homePageSelect);
  154.  
  155. // Subreddit sort select
  156. const subredditLabel = document.createElement('label');
  157. subredditLabel.textContent = 'Subreddit Sort:';
  158. subredditLabel.style.display = 'block';
  159. subredditLabel.style.marginBottom = '10px';
  160.  
  161. const subredditSelect = document.createElement('select');
  162. subredditSelect.id = 'subredditSortSelect';
  163. subredditSelect.style.width = '100%';
  164. subredditSelect.style.padding = '8px';
  165. subredditSelect.style.borderRadius = '5px';
  166. subredditSelect.style.backgroundColor = isDarkMode ? '#333' : '#fff'; // Darker dropdown in dark mode
  167. subredditSelect.style.color = isDarkMode ? '#fff' : '#000'; // Ensure text contrast is high
  168. subredditSelect.style.border = isDarkMode ? '1px solid #444' : '1px solid #ccc'; // Softer borders
  169.  
  170. ['best', 'hot', 'new', 'top', 'rising'].forEach(option => {
  171. const opt = document.createElement('option');
  172. opt.value = option;
  173. opt.textContent = option.charAt(0).toUpperCase() + option.slice(1);
  174. subredditSelect.appendChild(opt);
  175. });
  176. subredditSelect.value = subredditSort;
  177.  
  178. settingsContainer.appendChild(subredditLabel);
  179. settingsContainer.appendChild(subredditSelect);
  180.  
  181. // Comments sort select
  182. const commentsLabel = document.createElement('label');
  183. commentsLabel.textContent = 'Comments Sort:';
  184. commentsLabel.style.display = 'block';
  185. commentsLabel.style.marginBottom = '10px';
  186.  
  187. const commentSelect = document.createElement('select');
  188. commentSelect.id = 'commentSortSelect';
  189. commentSelect.style.width = '100%';
  190. commentSelect.style.padding = '8px';
  191. commentSelect.style.borderRadius = '5px';
  192. commentSelect.style.backgroundColor = isDarkMode ? '#333' : '#fff'; // Darker dropdown in dark mode
  193. commentSelect.style.color = isDarkMode ? '#fff' : '#000'; // Ensure text contrast is high
  194. commentSelect.style.border = isDarkMode ? '1px solid #444' : '1px solid #ccc'; // Softer borders
  195.  
  196. const optionMapping = {
  197. best: 'confidence',
  198. top: 'top',
  199. new: 'new',
  200. controversial: 'controversial',
  201. old: 'old',
  202. 'Q&A': 'qa'
  203. };
  204.  
  205. Object.entries(optionMapping).forEach(([key, value]) => {
  206. const opt = document.createElement('option');
  207. opt.value = value;
  208. opt.textContent = key.charAt(0).toUpperCase() + key.slice(1);
  209. commentSelect.appendChild(opt);
  210. });
  211.  
  212. commentSelect.value = commentSort;
  213.  
  214. settingsContainer.appendChild(commentsLabel);
  215. settingsContainer.appendChild(commentSelect);
  216.  
  217. // Buttons container
  218. const buttonsContainer = document.createElement('div');
  219. buttonsContainer.style.marginTop = '20px';
  220. buttonsContainer.style.display = 'flex';
  221. buttonsContainer.style.justifyContent = 'space-between';
  222.  
  223. // Save button
  224. const saveButton = document.createElement('button');
  225. saveButton.textContent = 'Save Settings';
  226. saveButton.style.padding = '10px 20px';
  227. saveButton.style.borderRadius = '5px';
  228. saveButton.style.backgroundColor = '#4CAF50';
  229. saveButton.style.color = 'white';
  230. saveButton.style.border = 'none';
  231. saveButton.style.cursor = 'pointer';
  232. saveButton.style.transition = 'background-color 0.3s ease';
  233. saveButton.style.textAlign = 'center'; // Center text
  234. saveButton.style.display = 'flex';
  235. saveButton.style.alignItems = 'center';
  236. saveButton.style.justifyContent = 'center'; // Ensure text is centered
  237. saveButton.addEventListener('click', () => {
  238. homePageSort = document.getElementById('homePageSortSelect').value;
  239. subredditSort = document.getElementById('subredditSortSelect').value;
  240. commentSort = document.getElementById('commentSortSelect').value;
  241.  
  242. GM_setValue("homePageSort", homePageSort);
  243. GM_setValue("subredditSort", subredditSort);
  244. GM_setValue("commentSort", commentSort);
  245.  
  246. if (confirm('Settings Saved!\nWant to refresh now?')) {
  247. // User clicked "Yes" / "Ok"
  248. location.reload();
  249. }
  250.  
  251. settingsContainer.remove(); // Remove the settings UI after saving
  252. });
  253. saveButton.addEventListener('mouseover', () => {
  254. saveButton.style.backgroundColor = '#45a049'; // Darker green on hover
  255. });
  256. saveButton.addEventListener('mouseout', () => {
  257. saveButton.style.backgroundColor = '#4CAF50'; // Reset to original green
  258. });
  259.  
  260. // Close button
  261. const closeButton = document.createElement('button');
  262. closeButton.textContent = 'Close';
  263. closeButton.style.padding = '10px 20px';
  264. closeButton.style.borderRadius = '5px';
  265. closeButton.style.backgroundColor = '#f44336';
  266. closeButton.style.color = 'white';
  267. closeButton.style.border = 'none';
  268. closeButton.style.cursor = 'pointer';
  269. closeButton.style.transition = 'background-color 0.3s ease';
  270. closeButton.style.textAlign = 'center'; // Center text
  271. closeButton.style.display = 'flex';
  272. closeButton.style.alignItems = 'center';
  273. closeButton.style.justifyContent = 'center'; // Ensure text is centered
  274. closeButton.addEventListener('click', () => {
  275. settingsContainer.remove();
  276. });
  277. closeButton.addEventListener('mouseover', () => {
  278. closeButton.style.backgroundColor = '#e53935'; // Darker red on hover
  279. });
  280. closeButton.addEventListener('mouseout', () => {
  281. closeButton.style.backgroundColor = '#f44336'; // Reset to original red
  282. });
  283.  
  284. // Append buttons
  285. buttonsContainer.appendChild(saveButton);
  286. buttonsContainer.appendChild(closeButton);
  287. settingsContainer.appendChild(buttonsContainer);
  288.  
  289. // Append the settings container to the body
  290. document.body.appendChild(settingsContainer);
  291. }
  292.  
  293.     // Add a button to the page to open the settings
  294. function addSettingsButton() {
  295. const container = document.querySelector('.pl-lg.gap-xs.flex.items-center.justify-end');
  296.  
  297. if (!container) {
  298. console.warn("Sort Settings button: Target container not found.");
  299. return; // Exit if container is missing
  300. }
  301.  
  302. // Styling
  303. const settingsButton = document.createElement('button');
  304. settingsButton.textContent = 'Sort Settings';
  305. settingsButton.style.marginLeft = '5px';
  306. settingsButton.style.paddingLeft = '10px';
  307. settingsButton.style.paddingRight = '10px';
  308. settingsButton.style.backgroundColor = 'transparent';
  309. settingsButton.style.border = '1px solid white';
  310. settingsButton.className = 'btn btn-primary';
  311. settingsButton.addEventListener('click', createSettingsUI);
  312.  
  313. container.appendChild(settingsButton);
  314. }
  315.  
  316.  
  317.  
  318.     // Initialize
  319.     addSettingsButton();
  320.     redirectIfNeeded();
  321.  
  322. // Function to monitor URL changes in single-page app
  323. function observeUrlChanges(callback) {
  324. lastUrl = location.href;
  325.  
  326. new MutationObserver(() => {
  327. if (location.href !== lastUrl) {
  328. lastUrl = location.href;
  329. callback();
  330. }
  331. }).observe(document, { subtree: true, childList: true });
  332.  
  333. // Also intercept history changes
  334. const pushState = history.pushState;
  335. const replaceState = history.replaceState;
  336.  
  337. history.pushState = function() {
  338. pushState.apply(this, arguments);
  339. callback();
  340. };
  341. history.replaceState = function() {
  342. replaceState.apply(this, arguments);
  343. callback();
  344. };
  345. }
  346.  
  347. // Run `redirectIfNeeded` whenever Reddit changes the page
  348. observeUrlChanges(redirectIfNeeded);
  349.  
  350. })();