Reddit Image Gallery Arrow Navigation

Navigate Reddit image galleries using arrow keys, made with the help of ChatGPT, Thanks ChatGPT!

// ==UserScript==
// @name         Reddit Image Gallery Arrow Navigation
// @namespace    https://reddit.com
// @version      1.9.2
// @description  Navigate Reddit image galleries using arrow keys, made with the help of ChatGPT, Thanks ChatGPT!
// @author       TheFantasticLoki
// @match        https://*.reddit.com/*
// @grant        none
// @license      MIT
// @homepage     https://github.com/TheFantasticLoki/Tampermonkey-Scripts
// @homepageURL  https://github.com/TheFantasticLoki/Tampermonkey-Scripts
// @supportURL   https://github.com/TheFantasticLoki/Tampermonkey-Scripts/issues
// ==/UserScript==

(function () {
    'use strict';

    // Set the debug variable to control logging
    const debug = false;

    let activeGallery = null;

    const simulateClick = (button) => {
        if (button) {
            try {
                const event = new MouseEvent('click', {
                    bubbles: true,
                    cancelable: true,
                    view: window,
                });
                button.dispatchEvent(event);
                if (debug) console.log('Dispatched click event successfully');
            } catch (err) {
                if (debug) console.error('Error dispatching click event:', err);
            }
        } else {
            if (debug) console.log('Button not interactable or not found.');
        }
    };

    const handleKeyDown = (e) => {
        if (document.activeElement.tagName === 'INPUT' || document.activeElement.tagName === 'TEXTAREA') {
            return;
        }

        if (!activeGallery) {
            if (debug) console.log('No active gallery to navigate.');
            return;
        }

        if (e.key === 'ArrowLeft') {
            if (debug) console.log('Left arrow pressed');
            const prevButton = activeGallery.querySelector('button[aria-label="Previous page"]');
            if (debug) console.log('Previous Button:', prevButton);
            simulateClick(prevButton);
        }

        if (e.key === 'ArrowRight') {
            if (debug) console.log('Right arrow pressed');
            const nextButton = activeGallery.querySelector('button[aria-label="Next page"]');
            if (debug) console.log('Next Button:', nextButton);
            simulateClick(nextButton);
        }
    };

    const handleMouseEnter = (e) => {
        const galleryCarousel = e.currentTarget;
        if (galleryCarousel && galleryCarousel.shadowRoot) {
            activeGallery = galleryCarousel.shadowRoot;
            if (debug) console.log('Mouse entered gallery-carousel. Active gallery set:', activeGallery);
        }
    };

    const handleMouseLeave = () => {
        activeGallery = null;
        if (debug) console.log('Mouse left gallery-carousel. Active gallery cleared.');
    };

    const detectPopup = () => {
        const lightbox = document.querySelector('#shreddit-media-lightbox');
        if (lightbox) {
            const gallery = lightbox.querySelector('gallery-carousel');
            if (gallery && gallery.shadowRoot) {
                activeGallery = gallery.shadowRoot;
                if (debug) console.log('Gallery popup detected. Active gallery set:', activeGallery);
            }
        }
    };

    const observeDOMChanges = () => {
        const observer = new MutationObserver((mutations) => {
            mutations.forEach((mutation) => {
                if (mutation.addedNodes) {
                    mutation.addedNodes.forEach((node) => {
                        if (node.id === 'shreddit-media-lightbox') {
                            if (debug) console.log('Lightbox detected:', node);
                            detectPopup();
                        }
                    });
                }
            });
        });

        observer.observe(document.body, { childList: true, subtree: true });
    };

    const attachHoverListeners = () => {
        document.querySelectorAll('gallery-carousel').forEach((carousel) => {
            carousel.addEventListener('mouseenter', handleMouseEnter);
            carousel.addEventListener('mouseleave', handleMouseLeave);
        });
    };

    const observeFeed = () => {
        const feedObserver = new MutationObserver(() => {
            attachHoverListeners(); // Reattach listeners as new galleries load
        });

        feedObserver.observe(document.body, { childList: true, subtree: true });
    };

    // Initial setup
    document.addEventListener('keydown', handleKeyDown);
    observeDOMChanges();
    observeFeed();

    // Attach listeners for initial galleries
    attachHoverListeners();

    if (debug) console.log('Script initialized.');
})();