Universal Auto-Scroll

Adds auto-scrolling functionality to any website

Dovrai installare un'estensione come Tampermonkey, Greasemonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Userscripts per installare questo script.

Dovrai installare un'estensione come ad esempio Tampermonkey per installare questo script.

Dovrai installare un gestore di script utente per installare questo script.

(Ho già un gestore di script utente, lasciamelo installare!)

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

(Ho già un gestore di stile utente, lasciamelo installare!)

// ==UserScript==
// @name         Universal Auto-Scroll
// @namespace    http://tampermonkey.net/
// @version      1.1
// @description  Adds auto-scrolling functionality to any website
// @author       You
// @match        *://*/*
// @grant        GM_setValue
// @grant        GM_getValue
// @run-at       document-idle
// ==/UserScript==

(function() {
    'use strict';

    // Wait a bit for page to be fully ready
    setTimeout(initAutoScroll, 1000);

    function initAutoScroll() {
        // Configuration
        const DEFAULT_SETTINGS = {
            isActive: false,
            speed: 3,
            isMinimized: false,
            pixelsPerSecond: 50  // Base scrolling speed - will be modified by speed setting
        };

        // State variables
        let isScrolling = false;
        let scrollIntervalId = null;
        let userScrollDetected = false;
        let userScrollTimeout = null;
        let lastScrollPosition = window.scrollY;

        // Load saved settings or use defaults - Using Tampermonkey's built-in storage
        let scrollSettings;
        try {
            scrollSettings = JSON.parse(GM_getValue('autoScrollSettings', JSON.stringify(DEFAULT_SETTINGS)));
        } catch (e) {
            console.log('Could not load settings, using defaults');
            scrollSettings = DEFAULT_SETTINGS;
        }

        // DOM elements references
        let autoScrollPanel;
        let bubbleView;
        let toggleButton;
        let speedSlider;
        let speedValue;

        // Create and inject the UI
        function createUI() {
            // Create a container for our elements with a unique ID
            const containerId = 'auto-scroll-container-' + Math.random().toString(36).substr(2, 9);
            const container = document.createElement('div');
            container.id = containerId;
            document.body.appendChild(container);

            // Add isolated styles to avoid conflicts with page CSS
            const styleElement = document.createElement('style');
            styleElement.textContent = `
                #${containerId} {
                    all: initial;
                    font-family: Arial, sans-serif;
                    color: white;
                    font-size: 14px;
                }
                #${containerId} * {
                    all: unset;
                    box-sizing: border-box;
                }
                #${containerId} .auto-scroll-panel {
                    position: fixed;
                    bottom: 80px;
                    right: 20px;
                    background-color: rgba(0, 0, 0, 0.8);
                    color: white;
                    padding: 15px;
                    border-radius: 8px;
                    width: 220px;
                    z-index: 9999999;
                    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
                    font-family: Arial, sans-serif;
                    display: ${scrollSettings.isMinimized ? 'none' : 'block'};
                }
                #${containerId} .panel-header {
                    display: flex;
                    justify-content: space-between;
                    align-items: center;
                    margin-bottom: 10px;
                    border-bottom: 1px solid rgba(255, 255, 255, 0.2);
                    padding-bottom: 8px;
                }
                #${containerId} .panel-title {
                    font-weight: bold;
                    font-size: 16px;
                    display: block;
                }
                #${containerId} .minimize-button {
                    background: none;
                    border: none;
                    color: white;
                    cursor: pointer;
                    font-size: 20px;
                    padding: 0;
                    margin: 0;
                    display: block;
                }
                #${containerId} .section {
                    margin-bottom: 12px;
                }
                #${containerId} .section-title {
                    font-size: 14px;
                    color: #ffcc00;
                    margin-bottom: 8px;
                    display: block;
                }
                #${containerId} .toggle-button {
                    background-color: #2196F3;
                    border: none;
                    color: white;
                    padding: 10px 15px;
                    text-align: center;
                    text-decoration: none;
                    font-size: 14px;
                    border-radius: 6px;
                    width: 100%;
                    cursor: pointer;
                    display: flex;
                    justify-content: center;
                    align-items: center;
                    gap: 8px;
                    margin-bottom: 10px;
                }
                #${containerId} .toggle-button.active {
                    background-color: #4CAF50;
                }
                #${containerId} .slider-container {
                    width: 100%;
                    display: flex;
                    flex-direction: column;
                    gap: 8px;
                }
                #${containerId} .slider-top {
                    display: flex;
                    justify-content: space-between;
                    width: 100%;
                }
                #${containerId} .speed-value {
                    font-weight: bold;
                }
                #${containerId} .speed-slider {
                    width: 100%;
                    height: 5px;
                    -webkit-appearance: none;
                    appearance: none;
                    background: #444;
                    outline: none;
                    border-radius: 3px;
                    display: block;
                }
                #${containerId} .speed-slider::-webkit-slider-thumb {
                    -webkit-appearance: none;
                    appearance: none;
                    width: 15px;
                    height: 15px;
                    border-radius: 50%;
                    background: #ffcc00;
                    cursor: pointer;
                }
                #${containerId} .speed-slider::-moz-range-thumb {
                    width: 15px;
                    height: 15px;
                    border-radius: 50%;
                    background: #ffcc00;
                    cursor: pointer;
                }
                #${containerId} .slider-labels {
                    display: flex;
                    justify-content: space-between;
                    width: 100%;
                }
                #${containerId} .auto-scroll-bubble {
                    position: fixed;
                    bottom: 80px;
                    right: 20px;
                    width: 60px;
                    height: 60px;
                    border-radius: 50%;
                    background-color: rgba(0, 0, 0, 0.8);
                    display: ${scrollSettings.isMinimized ? 'flex' : 'none'};
                    flex-direction: column;
                    justify-content: center;
                    align-items: center;
                    cursor: pointer;
                    z-index: 9999999;
                    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
                    font-size: 24px;
                }
            `;
            document.head.appendChild(styleElement);

            // Create the main panel
            autoScrollPanel = document.createElement('div');
            autoScrollPanel.className = 'auto-scroll-panel';
            container.appendChild(autoScrollPanel);

            // Create panel header with title and minimize button
            const panelHeader = document.createElement('div');
            panelHeader.className = 'panel-header';

            const panelTitle = document.createElement('div');
            panelTitle.className = 'panel-title';
            panelTitle.textContent = 'Auto-Scroll Controls';

            const minimizeButton = document.createElement('button');
            minimizeButton.className = 'minimize-button';
            minimizeButton.textContent = '−';
            minimizeButton.addEventListener('click', toggleMinimize);

            panelHeader.appendChild(panelTitle);
            panelHeader.appendChild(minimizeButton);
            autoScrollPanel.appendChild(panelHeader);

            // Create scrolling status section
            const statusSection = document.createElement('div');
            statusSection.className = 'section';

            const statusTitle = document.createElement('div');
            statusTitle.className = 'section-title';
            statusTitle.textContent = 'Scrolling Status';

            toggleButton = document.createElement('button');
            toggleButton.className = 'toggle-button' + (scrollSettings.isActive ? ' active' : '');
            toggleButton.innerHTML = scrollSettings.isActive ?
                '<span>⏸️</span> Pause Scrolling' :
                '<span>▶️</span> Start Scrolling';
            toggleButton.addEventListener('click', toggleScrolling);

            statusSection.appendChild(statusTitle);
            statusSection.appendChild(toggleButton);
            autoScrollPanel.appendChild(statusSection);

            // Create speed control section
            const speedSection = document.createElement('div');
            speedSection.className = 'section';

            const speedTitle = document.createElement('div');
            speedTitle.className = 'section-title';
            speedTitle.textContent = 'Scroll Speed';

            const sliderContainer = document.createElement('div');
            sliderContainer.className = 'slider-container';

            const sliderTop = document.createElement('div');
            sliderTop.className = 'slider-top';

            const speedLabel = document.createElement('span');
            speedLabel.textContent = 'Speed:';

            speedValue = document.createElement('span');
            speedValue.className = 'speed-value';
            updateSpeedDisplay(scrollSettings.speed);

            sliderTop.appendChild(speedLabel);
            sliderTop.appendChild(speedValue);

            speedSlider = document.createElement('input');
            speedSlider.type = 'range';
            speedSlider.className = 'speed-slider';
            speedSlider.min = '1';
            speedSlider.max = '5';
            speedSlider.value = scrollSettings.speed;
            speedSlider.addEventListener('input', handleSpeedChange);

            const sliderLabels = document.createElement('div');
            sliderLabels.className = 'slider-labels';

            const slowLabel = document.createElement('span');
            slowLabel.textContent = 'Slow';

            const fastLabel = document.createElement('span');
            fastLabel.textContent = 'Fast';

            sliderLabels.appendChild(slowLabel);
            sliderLabels.appendChild(fastLabel);

            sliderContainer.appendChild(sliderTop);
            sliderContainer.appendChild(speedSlider);
            sliderContainer.appendChild(sliderLabels);

            speedSection.appendChild(speedTitle);
            speedSection.appendChild(sliderContainer);
            autoScrollPanel.appendChild(speedSection);

            // Create bubble view (minimized version)
            bubbleView = document.createElement('div');
            bubbleView.className = 'auto-scroll-bubble';
            bubbleView.innerHTML = '📜';
            bubbleView.addEventListener('click', toggleMinimize);
            container.appendChild(bubbleView);

            // Start scrolling if it was active before
            if (scrollSettings.isActive) {
                startScrolling();
            }
        }

        // Toggle between expanded panel and minimized bubble
        function toggleMinimize() {
            scrollSettings.isMinimized = !scrollSettings.isMinimized;

            if (scrollSettings.isMinimized) {
                autoScrollPanel.style.display = 'none';
                bubbleView.style.display = 'flex';
            } else {
                autoScrollPanel.style.display = 'block';
                bubbleView.style.display = 'none';
            }

            saveSettings();
        }

        // Toggle scrolling on/off
        function toggleScrolling() {
            scrollSettings.isActive = !scrollSettings.isActive;

            if (scrollSettings.isActive) {
                // Start scrolling
                toggleButton.classList.add('active');
                toggleButton.innerHTML = '<span>⏸️</span> Pause Scrolling';
                startScrolling();
            } else {
                // Pause scrolling
                toggleButton.classList.remove('active');
                toggleButton.innerHTML = '<span>▶️</span> Start Scrolling';
                stopScrolling();
            }

            saveSettings();
        }

        // Handle speed slider changes
        function handleSpeedChange() {
            const value = parseInt(speedSlider.value);
            scrollSettings.speed = value;
            updateSpeedDisplay(value);

            // If currently scrolling, update the scroll speed
            if (isScrolling) {
                stopScrolling();
                startScrolling();
            }

            saveSettings();
        }

        // Update speed display text
        function updateSpeedDisplay(value) {
            let speedText;

            if (value === 1) speedText = "Very Slow";
            else if (value === 2) speedText = "Slow";
            else if (value === 3) speedText = "Medium";
            else if (value === 4) speedText = "Fast";
            else speedText = "Very Fast";

            speedValue.textContent = `${speedText} (${value})`;
        }

        // Start auto-scrolling
        function startScrolling() {
            if (isScrolling) return;

            isScrolling = true;
            lastScrollPosition = window.scrollY;

            // Calculate scroll speed based on setting (1-5)
            // The base speed (pixelsPerSecond) is multiplied by a factor based on the speed setting
            const speedFactors = [0.5, 0.75, 1, 1.5, 2.5]; // Factors for speeds 1-5
            const pixelsPerSecond = DEFAULT_SETTINGS.pixelsPerSecond * speedFactors[scrollSettings.speed - 1];

            // Convert pixels per second to interval delay in milliseconds
            // We'll scroll 1px at a time for smoothness
            const scrollDelay = Math.floor(1000 / pixelsPerSecond);

            // Start scroll interval
            scrollIntervalId = setInterval(function() {
                // Only scroll if user isn't manually scrolling
                if (!userScrollDetected) {
                    window.scrollBy(0, 1);
                }
            }, scrollDelay);
        }

        // Stop auto-scrolling
        function stopScrolling() {
            if (!isScrolling) return;

            isScrolling = false;
            if (scrollIntervalId !== null) {
                clearInterval(scrollIntervalId);
                scrollIntervalId = null;
            }
        }

        // Save settings using Tampermonkey's storage
        function saveSettings() {
            try {
                GM_setValue('autoScrollSettings', JSON.stringify(scrollSettings));
            } catch (e) {
                console.error('Failed to save settings:', e);
            }
        }

        // Handle user manual scrolling
        function handleUserScroll() {
            const currentPosition = window.scrollY;

            // If position changed significantly (more than what our auto-scroll would do)
            // and we're currently auto-scrolling, pause temporarily
            if (isScrolling && Math.abs(currentPosition - lastScrollPosition) > 3) {
                userScrollDetected = true;

                // Clear existing timeout if there is one
                if (userScrollTimeout) {
                    clearTimeout(userScrollTimeout);
                }

                // Set timeout to resume auto-scrolling after user stops scrolling
                userScrollTimeout = setTimeout(function() {
                    userScrollDetected = false;
                    lastScrollPosition = window.scrollY;
                }, 5000); // 5-second delay before resuming
            }

            lastScrollPosition = currentPosition;
        }

        // Only create UI if we're on a page with scrollable content
        if (document.body && document.body.scrollHeight > window.innerHeight) {
            createUI();

            // Add scroll event listener to detect manual user scrolling
            window.addEventListener('scroll', handleUserScroll, { passive: true });

            // Clean up when page is unloaded
            window.addEventListener('beforeunload', function() {
                if (scrollIntervalId !== null) {
                    clearInterval(scrollIntervalId);
                }
            });
        }
    }
})();