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.

От 04.12.2024. Виж последната версия.

// ==UserScript==
// @name         Scroll to Bottom, Stay Button, and Auto-Reload with Persistence and Icons for reddit-stream.com
// @namespace    https://github.com/Nick2bad4u/UserStyles
// @version      2.13
// @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.
// @author       Nick2bad4u
// @match        *://*.reddit-stream.com/*
// @connect      reddit-stream.com
// @grant        GM_xmlhttpRequest
// @license      Unlicense
// @resource     https://www.google.com/s2/favicons?sz=64&domain=reddit-stream.com
// @icon         https://www.google.com/s2/favicons?sz=64&domain=reddit-stream.com
// @icon64       https://www.google.com/s2/favicons?sz=64&domain=reddit-stream.com
// @tag          reddit
// ==/UserScript==

(function () {
	'use strict';

	console.log(
		'Script initialized: Adding floating button, checkboxes, and persistence.',
	);

	// Helper function for hover effect
	function handleHover(element) {
		element.addEventListener(
			'mouseover',
			function () {
				element.style.opacity = '1';
			},
		);
		element.addEventListener(
			'mouseout',
			function () {
				element.style.opacity = '0.1';
			},
		);
		console.log(
			`Hover effect applied to element: ${element}`,
		);
	}

	// Function to save checkbox state
	function saveCheckboxState(key, value) {
		localStorage.setItem(key, value);
		console.log(
			`Saved checkbox state for ${key}: ${value}`,
		);
	}

	// Function to load checkbox state
	function loadCheckboxState(key) {
		const state =
			localStorage.getItem(key) === 'true';
		console.log(
			`Loaded checkbox state for ${key}: ${state}`,
		);
		return state;
	}

	// Styling for the checkboxes with hover title support for icons
	function styleCheckboxWrapper(
		wrapper,
		iconText,
		checkboxId,
		titleText,
	) {
		wrapper.style.display = 'flex';
		wrapper.style.flexDirection = 'column';
		wrapper.style.alignItems = 'center';
		wrapper.style.position = 'fixed';
		wrapper.style.bottom = '20px';
		wrapper.style.zIndex = '1000';
		wrapper.style.cursor = 'pointer';
		wrapper.style.opacity = '0.1';
		wrapper.style.transition = 'opacity 0.3s';

		const label = document.createElement('label');
		label.htmlFor = checkboxId;
		label.style.cursor = 'pointer';

		const icon = document.createElement('div');
		icon.innerHTML = iconText;
		icon.style.fontSize = '12px';
		icon.style.color = 'orange';
		icon.style.marginTop = '5px';
		icon.title = titleText;

		label.appendChild(icon);
		wrapper.appendChild(label);
		handleHover(wrapper);

		console.log(
			`Checkbox wrapper styled with icon: ${iconText} and title: ${titleText}`,
		);
	}

	// Scroll-to-bottom button
	const button = document.createElement('button');
	button.innerHTML = '⬇️';
	button.style.position = 'fixed';
	button.style.bottom = '20px';
	button.style.right = '20px'; // Changed from left to right
	button.style.zIndex = '1000';
	button.style.padding = '10px';
	button.style.borderRadius = '50%';
	button.style.border = 'none';
	button.style.backgroundColor = 'black';
	button.style.color = 'blue';
	button.style.fontSize = '20px';
	button.style.cursor = 'pointer';
	button.style.opacity = '0.5';
	button.style.transition = 'opacity 0.3s';
	button.title = 'Click to scroll to the bottom';
	handleHover(button);

	button.addEventListener('click', function () {
		globalThis.scrollTo({
			top: document.body.scrollHeight,
			behavior: 'smooth',
		});
		console.log(
			'Scroll-to-bottom button clicked, scrolling to the bottom.',
		);
	});

	// Stay-at-bottom checkbox with icon
	const stayAtBottomWrapper =
		document.createElement('div');
	stayAtBottomWrapper.style.right = '60px'; // Changed from left to right
	const stayAtBottomCheckboxId =
		'stayAtBottomCheckbox';
	styleCheckboxWrapper(
		stayAtBottomWrapper,
		'🔽',
		stayAtBottomCheckboxId,
		'Check to stay at the bottom',
	);

	const stayAtBottomCheckbox =
		document.createElement('input');
	stayAtBottomCheckbox.type = 'checkbox';
	stayAtBottomCheckbox.id =
		stayAtBottomCheckboxId;
	stayAtBottomCheckbox.checked =
		loadCheckboxState('stayAtBottom');
	stayAtBottomCheckbox.title =
		'Check to stay at the bottom';
	stayAtBottomWrapper.insertBefore(
		stayAtBottomCheckbox,
		stayAtBottomWrapper.firstChild,
	);

	stayAtBottomCheckbox.addEventListener(
		'change',
		function () {
			saveCheckboxState(
				'stayAtBottom',
				stayAtBottomCheckbox.checked,
			);
		},
	);

	let scrollTimeout;
	const debounce = (fn, delay) => {
		return function () {
			clearTimeout(scrollTimeout);
			scrollTimeout = setTimeout(fn, delay);
		};
	};

	const keepAtBottom = debounce(function () {
		if (stayAtBottomCheckbox.checked) {
			globalThis.scrollTo({
				top: document.body.scrollHeight,
				behavior: 'smooth',
			});
			console.log(
				'Auto-scrolling to the bottom (Stay at Bottom active).',
			);
		} else {
			console.log(
				'Auto-scrolling stopped (Stay at Bottom inactive).',
			);
		}
	}, 200);

	const observer = new MutationObserver(
		keepAtBottom,
	);
	observer.observe(document.body, {
		childList: true,
		subtree: true,
	});
	console.log(
		'MutationObserver started for staying at the bottom.',
	);

	// Auto-reload every 10 seconds checkbox with icon
	const autoReload10Wrapper =
		document.createElement('div');
	autoReload10Wrapper.style.right = '100px'; // Changed from left to right
	const autoReload10CheckboxId =
		'autoReload10Checkbox';
	styleCheckboxWrapper(
		autoReload10Wrapper,
		'10s',
		autoReload10CheckboxId,
		'Check to reload every 10 seconds',
	);

	const autoReload10Checkbox =
		document.createElement('input');
	autoReload10Checkbox.type = 'checkbox';
	autoReload10Checkbox.id =
		autoReload10CheckboxId;
	autoReload10Checkbox.checked =
		loadCheckboxState('autoReload10');
	autoReload10Checkbox.title =
		'Check to reload every 10 seconds';
	autoReload10Wrapper.insertBefore(
		autoReload10Checkbox,
		autoReload10Wrapper.firstChild,
	);

	let reloadInterval10;

	function startAutoReload10() {
		reloadInterval10 = setInterval(() => {
			globalThis.location.reload();
			console.log(
				'Page reloading every 10 seconds.',
			);
		}, 10000);
	}

	if (autoReload10Checkbox.checked)
		startAutoReload10();

	autoReload10Checkbox.addEventListener(
		'change',
		function () {
			saveCheckboxState(
				'autoReload10',
				autoReload10Checkbox.checked,
			);
			if (autoReload10Checkbox.checked) {
				startAutoReload10();
			} else {
				clearInterval(reloadInterval10);
				console.log(
					'Stopped reloading every 10 seconds.',
				);
			}
		},
	);

	// Auto-reload every 15 seconds checkbox with icon
	const autoReload15Wrapper =
		document.createElement('div');
	autoReload15Wrapper.style.right = '140px'; // Changed from left to right
	const autoReload15CheckboxId =
		'autoReload15Checkbox';
	styleCheckboxWrapper(
		autoReload15Wrapper,
		'15s',
		autoReload15CheckboxId,
		'Check to reload every 15 seconds',
	);

	const autoReload15Checkbox =
		document.createElement('input');
	autoReload15Checkbox.type = 'checkbox';
	autoReload15Checkbox.id =
		autoReload15CheckboxId;
	autoReload15Checkbox.checked =
		loadCheckboxState('autoReload15');
	autoReload15Checkbox.title =
		'Check to reload every 15 seconds';
	autoReload15Wrapper.insertBefore(
		autoReload15Checkbox,
		autoReload15Wrapper.firstChild,
	);

	let reloadInterval15;

	function startAutoReload15() {
		reloadInterval15 = setInterval(() => {
			globalThis.location.reload();
			console.log(
				'Page reloading every 15 seconds.',
			);
		}, 15000);
	}

	if (autoReload15Checkbox.checked)
		startAutoReload15();

	autoReload15Checkbox.addEventListener(
		'change',
		function () {
			saveCheckboxState(
				'autoReload15',
				autoReload15Checkbox.checked,
			);
			if (autoReload15Checkbox.checked) {
				startAutoReload15();
			} else {
				clearInterval(reloadInterval15);
				console.log(
					'Stopped reloading every 15 seconds.',
				);
			}
		},
	);

	// Auto-reload every 20 seconds checkbox with icon
	const autoReload20Wrapper =
		document.createElement('div');
	autoReload20Wrapper.style.right = '180px'; // Changed from left to right
	const autoReload20CheckboxId =
		'autoReload20Checkbox';
	styleCheckboxWrapper(
		autoReload20Wrapper,
		'20s',
		autoReload20CheckboxId,
		'Check to reload every 20 seconds',
	);

	const autoReload20Checkbox =
		document.createElement('input');
	autoReload20Checkbox.type = 'checkbox';
	autoReload20Checkbox.id =
		autoReload20CheckboxId;
	autoReload20Checkbox.checked =
		loadCheckboxState('autoReload20');
	autoReload20Checkbox.title =
		'Check to reload every 20 seconds';
	autoReload20Wrapper.insertBefore(
		autoReload20Checkbox,
		autoReload20Wrapper.firstChild,
	);

	let reloadInterval20;

	function startAutoReload20() {
		reloadInterval20 = setInterval(() => {
			globalThis.location.reload();
			console.log(
				'Page reloading every 20 seconds.',
			);
		}, 20000);
	}

	if (autoReload20Checkbox.checked)
		startAutoReload20();

	autoReload20Checkbox.addEventListener(
		'change',
		function () {
			saveCheckboxState(
				'autoReload20',
				autoReload20Checkbox.checked,
			);
			if (autoReload20Checkbox.checked) {
				startAutoReload20();
			} else {
				clearInterval(reloadInterval20);
				console.log(
					'Stopped reloading every 20 seconds.',
				);
			}
		},
	);

	// Auto-reload every 30 seconds checkbox with icon
	const autoReload30Wrapper =
		document.createElement('div');
	autoReload30Wrapper.style.right = '220px'; // Changed from left to right
	const autoReload30CheckboxId =
		'autoReload30Checkbox';
	styleCheckboxWrapper(
		autoReload30Wrapper,
		'30s',
		autoReload30CheckboxId,
		'Check to reload every 30 seconds',
	);

	const autoReload30Checkbox =
		document.createElement('input');
	autoReload30Checkbox.type = 'checkbox';
	autoReload30Checkbox.id =
		autoReload30CheckboxId;
	autoReload30Checkbox.checked =
		loadCheckboxState('autoReload30');
	autoReload30Checkbox.title =
		'Check to reload every 30 seconds';
	autoReload30Wrapper.insertBefore(
		autoReload30Checkbox,
		autoReload30Wrapper.firstChild,
	);

	let reloadInterval30;

	function startAutoReload30() {
		reloadInterval30 = setInterval(() => {
			globalThis.location.reload();
			console.log(
				'Page reloading every 30 seconds.',
			);
		}, 30000);
	}

	if (autoReload30Checkbox.checked)
		startAutoReload30();

	autoReload30Checkbox.addEventListener(
		'change',
		function () {
			saveCheckboxState(
				'autoReload30',
				autoReload30Checkbox.checked,
			);
			if (autoReload30Checkbox.checked) {
				startAutoReload30();
			} else {
				clearInterval(reloadInterval30);
				console.log(
					'Stopped reloading every 30 seconds.',
				);
			}
		},
	);

	// Append elements to the page
	document.body.appendChild(button);
	document.body.appendChild(stayAtBottomWrapper);
	document.body.appendChild(autoReload10Wrapper);
	document.body.appendChild(autoReload15Wrapper);
	document.body.appendChild(autoReload20Wrapper);
	document.body.appendChild(autoReload30Wrapper);
	console.log(
		'All elements appended with styling and icons.',
	);
})();