Scroll to Bottom, Stay Button, and Auto-Reload with Persistence and Icons for reddit-stream.com

Adds a floating button to scroll to the bottom, checkboxes to stay at the bottom, and to reload the page every 10, 15, 20, or 30 seconds on reddit-stream.com, with persistent settings and icons for clarity.

  1. // ==UserScript==
  2. // @name Scroll to Bottom, Stay Button, and Auto-Reload with Persistence and Icons for reddit-stream.com
  3. // @namespace typpi.online
  4. // @version 2.14
  5. // @description Adds a floating button to scroll to the bottom, checkboxes to stay at the bottom, and to reload the page every 10, 15, 20, or 30 seconds on reddit-stream.com, with persistent settings and icons for clarity.
  6. // @author Nick2bad4u
  7. // @match *://*.reddit-stream.com/*
  8. // @connect reddit-stream.com
  9. // @grant GM_xmlhttpRequest
  10. // @license Unlicense
  11. // @resource https://www.google.com/s2/favicons?sz=64&domain=reddit-stream.com
  12. // @icon https://www.google.com/s2/favicons?sz=64&domain=reddit-stream.com
  13. // @icon64 https://www.google.com/s2/favicons?sz=64&domain=reddit-stream.com
  14. // @tag reddit
  15. // ==/UserScript==
  16.  
  17. (function () {
  18. 'use strict';
  19.  
  20. console.log(
  21. 'Script initialized: Adding floating button, checkboxes, and persistence.',
  22. );
  23.  
  24. // Helper function for hover effect
  25. function handleHover(element) {
  26. element.addEventListener('mouseover', function () {
  27. element.style.opacity = '1';
  28. });
  29. element.addEventListener('mouseout', function () {
  30. element.style.opacity = '0.1';
  31. });
  32. console.log(`Hover effect applied to element: ${element}`);
  33. }
  34.  
  35. // Function to save checkbox state
  36. function saveCheckboxState(key, value) {
  37. localStorage.setItem(key, value);
  38. console.log(`Saved checkbox state for ${key}: ${value}`);
  39. }
  40.  
  41. // Function to load checkbox state
  42. function loadCheckboxState(key) {
  43. const state = localStorage.getItem(key) === 'true';
  44. console.log(`Loaded checkbox state for ${key}: ${state}`);
  45. return state;
  46. }
  47.  
  48. // Styling for the checkboxes with hover title support for icons
  49. function styleCheckboxWrapper(wrapper, iconText, checkboxId, titleText) {
  50. wrapper.style.display = 'flex';
  51. wrapper.style.flexDirection = 'column';
  52. wrapper.style.alignItems = 'center';
  53. wrapper.style.position = 'fixed';
  54. wrapper.style.bottom = '20px';
  55. wrapper.style.zIndex = '1000';
  56. wrapper.style.cursor = 'pointer';
  57. wrapper.style.opacity = '0.1';
  58. wrapper.style.transition = 'opacity 0.3s';
  59.  
  60. const label = document.createElement('label');
  61. label.htmlFor = checkboxId;
  62. label.style.cursor = 'pointer';
  63.  
  64. const icon = document.createElement('div');
  65. icon.innerHTML = iconText;
  66. icon.style.fontSize = '12px';
  67. icon.style.color = 'orange';
  68. icon.style.marginTop = '5px';
  69. icon.title = titleText;
  70.  
  71. label.appendChild(icon);
  72. wrapper.appendChild(label);
  73. handleHover(wrapper);
  74.  
  75. console.log(
  76. `Checkbox wrapper styled with icon: ${iconText} and title: ${titleText}`,
  77. );
  78. }
  79.  
  80. // Scroll-to-bottom button
  81. const button = document.createElement('button');
  82. button.innerHTML = '⬇️';
  83. button.style.position = 'fixed';
  84. button.style.bottom = '20px';
  85. button.style.right = '20px'; // Changed from left to right
  86. button.style.zIndex = '1000';
  87. button.style.padding = '10px';
  88. button.style.borderRadius = '50%';
  89. button.style.border = 'none';
  90. button.style.backgroundColor = 'black';
  91. button.style.color = 'blue';
  92. button.style.fontSize = '20px';
  93. button.style.cursor = 'pointer';
  94. button.style.opacity = '0.5';
  95. button.style.transition = 'opacity 0.3s';
  96. button.title = 'Click to scroll to the bottom';
  97. handleHover(button);
  98.  
  99. button.addEventListener('click', function () {
  100. globalThis.scrollTo({
  101. top: document.body.scrollHeight,
  102. behavior: 'smooth',
  103. });
  104. console.log('Scroll-to-bottom button clicked, scrolling to the bottom.');
  105. });
  106.  
  107. // Stay-at-bottom checkbox with icon
  108. const stayAtBottomWrapper = document.createElement('div');
  109. stayAtBottomWrapper.style.right = '60px'; // Changed from left to right
  110. const stayAtBottomCheckboxId = 'stayAtBottomCheckbox';
  111. styleCheckboxWrapper(
  112. stayAtBottomWrapper,
  113. '🔽',
  114. stayAtBottomCheckboxId,
  115. 'Check to stay at the bottom',
  116. );
  117.  
  118. const stayAtBottomCheckbox = document.createElement('input');
  119. stayAtBottomCheckbox.type = 'checkbox';
  120. stayAtBottomCheckbox.id = stayAtBottomCheckboxId;
  121. stayAtBottomCheckbox.checked = loadCheckboxState('stayAtBottom');
  122. stayAtBottomCheckbox.title = 'Check to stay at the bottom';
  123. stayAtBottomWrapper.insertBefore(
  124. stayAtBottomCheckbox,
  125. stayAtBottomWrapper.firstChild,
  126. );
  127.  
  128. stayAtBottomCheckbox.addEventListener('change', function () {
  129. saveCheckboxState('stayAtBottom', stayAtBottomCheckbox.checked);
  130. });
  131.  
  132. let scrollTimeout;
  133. const debounce = (fn, delay) => {
  134. return function () {
  135. clearTimeout(scrollTimeout);
  136. scrollTimeout = setTimeout(fn, delay);
  137. };
  138. };
  139.  
  140. const keepAtBottom = debounce(function () {
  141. if (stayAtBottomCheckbox.checked) {
  142. globalThis.scrollTo({
  143. top: document.body.scrollHeight,
  144. behavior: 'smooth',
  145. });
  146. console.log('Auto-scrolling to the bottom (Stay at Bottom active).');
  147. } else {
  148. console.log('Auto-scrolling stopped (Stay at Bottom inactive).');
  149. }
  150. }, 200);
  151.  
  152. const observer = new MutationObserver(keepAtBottom);
  153. observer.observe(document.body, {
  154. childList: true,
  155. subtree: true,
  156. });
  157. console.log('MutationObserver started for staying at the bottom.');
  158.  
  159. // Auto-reload every 10 seconds checkbox with icon
  160. const autoReload10Wrapper = document.createElement('div');
  161. autoReload10Wrapper.style.right = '100px'; // Changed from left to right
  162. const autoReload10CheckboxId = 'autoReload10Checkbox';
  163. styleCheckboxWrapper(
  164. autoReload10Wrapper,
  165. '10s',
  166. autoReload10CheckboxId,
  167. 'Check to reload every 10 seconds',
  168. );
  169.  
  170. const autoReload10Checkbox = document.createElement('input');
  171. autoReload10Checkbox.type = 'checkbox';
  172. autoReload10Checkbox.id = autoReload10CheckboxId;
  173. autoReload10Checkbox.checked = loadCheckboxState('autoReload10');
  174. autoReload10Checkbox.title = 'Check to reload every 10 seconds';
  175. autoReload10Wrapper.insertBefore(
  176. autoReload10Checkbox,
  177. autoReload10Wrapper.firstChild,
  178. );
  179.  
  180. let reloadInterval10;
  181.  
  182. function startAutoReload10() {
  183. reloadInterval10 = setInterval(() => {
  184. globalThis.location.reload();
  185. console.log('Page reloading every 10 seconds.');
  186. }, 10000);
  187. }
  188.  
  189. if (autoReload10Checkbox.checked) startAutoReload10();
  190.  
  191. autoReload10Checkbox.addEventListener('change', function () {
  192. saveCheckboxState('autoReload10', autoReload10Checkbox.checked);
  193. if (autoReload10Checkbox.checked) {
  194. startAutoReload10();
  195. } else {
  196. clearInterval(reloadInterval10);
  197. console.log('Stopped reloading every 10 seconds.');
  198. }
  199. });
  200.  
  201. // Auto-reload every 15 seconds checkbox with icon
  202. const autoReload15Wrapper = document.createElement('div');
  203. autoReload15Wrapper.style.right = '140px'; // Changed from left to right
  204. const autoReload15CheckboxId = 'autoReload15Checkbox';
  205. styleCheckboxWrapper(
  206. autoReload15Wrapper,
  207. '15s',
  208. autoReload15CheckboxId,
  209. 'Check to reload every 15 seconds',
  210. );
  211.  
  212. const autoReload15Checkbox = document.createElement('input');
  213. autoReload15Checkbox.type = 'checkbox';
  214. autoReload15Checkbox.id = autoReload15CheckboxId;
  215. autoReload15Checkbox.checked = loadCheckboxState('autoReload15');
  216. autoReload15Checkbox.title = 'Check to reload every 15 seconds';
  217. autoReload15Wrapper.insertBefore(
  218. autoReload15Checkbox,
  219. autoReload15Wrapper.firstChild,
  220. );
  221.  
  222. let reloadInterval15;
  223.  
  224. function startAutoReload15() {
  225. reloadInterval15 = setInterval(() => {
  226. globalThis.location.reload();
  227. console.log('Page reloading every 15 seconds.');
  228. }, 15000);
  229. }
  230.  
  231. if (autoReload15Checkbox.checked) startAutoReload15();
  232.  
  233. autoReload15Checkbox.addEventListener('change', function () {
  234. saveCheckboxState('autoReload15', autoReload15Checkbox.checked);
  235. if (autoReload15Checkbox.checked) {
  236. startAutoReload15();
  237. } else {
  238. clearInterval(reloadInterval15);
  239. console.log('Stopped reloading every 15 seconds.');
  240. }
  241. });
  242.  
  243. // Auto-reload every 20 seconds checkbox with icon
  244. const autoReload20Wrapper = document.createElement('div');
  245. autoReload20Wrapper.style.right = '180px'; // Changed from left to right
  246. const autoReload20CheckboxId = 'autoReload20Checkbox';
  247. styleCheckboxWrapper(
  248. autoReload20Wrapper,
  249. '20s',
  250. autoReload20CheckboxId,
  251. 'Check to reload every 20 seconds',
  252. );
  253.  
  254. const autoReload20Checkbox = document.createElement('input');
  255. autoReload20Checkbox.type = 'checkbox';
  256. autoReload20Checkbox.id = autoReload20CheckboxId;
  257. autoReload20Checkbox.checked = loadCheckboxState('autoReload20');
  258. autoReload20Checkbox.title = 'Check to reload every 20 seconds';
  259. autoReload20Wrapper.insertBefore(
  260. autoReload20Checkbox,
  261. autoReload20Wrapper.firstChild,
  262. );
  263.  
  264. let reloadInterval20;
  265.  
  266. function startAutoReload20() {
  267. reloadInterval20 = setInterval(() => {
  268. globalThis.location.reload();
  269. console.log('Page reloading every 20 seconds.');
  270. }, 20000);
  271. }
  272.  
  273. if (autoReload20Checkbox.checked) startAutoReload20();
  274.  
  275. autoReload20Checkbox.addEventListener('change', function () {
  276. saveCheckboxState('autoReload20', autoReload20Checkbox.checked);
  277. if (autoReload20Checkbox.checked) {
  278. startAutoReload20();
  279. } else {
  280. clearInterval(reloadInterval20);
  281. console.log('Stopped reloading every 20 seconds.');
  282. }
  283. });
  284.  
  285. // Auto-reload every 30 seconds checkbox with icon
  286. const autoReload30Wrapper = document.createElement('div');
  287. autoReload30Wrapper.style.right = '220px'; // Changed from left to right
  288. const autoReload30CheckboxId = 'autoReload30Checkbox';
  289. styleCheckboxWrapper(
  290. autoReload30Wrapper,
  291. '30s',
  292. autoReload30CheckboxId,
  293. 'Check to reload every 30 seconds',
  294. );
  295.  
  296. const autoReload30Checkbox = document.createElement('input');
  297. autoReload30Checkbox.type = 'checkbox';
  298. autoReload30Checkbox.id = autoReload30CheckboxId;
  299. autoReload30Checkbox.checked = loadCheckboxState('autoReload30');
  300. autoReload30Checkbox.title = 'Check to reload every 30 seconds';
  301. autoReload30Wrapper.insertBefore(
  302. autoReload30Checkbox,
  303. autoReload30Wrapper.firstChild,
  304. );
  305.  
  306. let reloadInterval30;
  307.  
  308. function startAutoReload30() {
  309. reloadInterval30 = setInterval(() => {
  310. globalThis.location.reload();
  311. console.log('Page reloading every 30 seconds.');
  312. }, 30000);
  313. }
  314.  
  315. if (autoReload30Checkbox.checked) startAutoReload30();
  316.  
  317. autoReload30Checkbox.addEventListener('change', function () {
  318. saveCheckboxState('autoReload30', autoReload30Checkbox.checked);
  319. if (autoReload30Checkbox.checked) {
  320. startAutoReload30();
  321. } else {
  322. clearInterval(reloadInterval30);
  323. console.log('Stopped reloading every 30 seconds.');
  324. }
  325. });
  326.  
  327. // Append elements to the page
  328. document.body.appendChild(button);
  329. document.body.appendChild(stayAtBottomWrapper);
  330. document.body.appendChild(autoReload10Wrapper);
  331. document.body.appendChild(autoReload15Wrapper);
  332. document.body.appendChild(autoReload20Wrapper);
  333. document.body.appendChild(autoReload30Wrapper);
  334. console.log('All elements appended with styling and icons.');
  335. })();