Reddit controls for player

controls for player in new/sh reddit

// ==UserScript==
// @name            	Reddit controls for player
// @namespace       	https://greasyfork.org/users/821661
// @match           	https://www.reddit.com/*
// @match           	https://new.reddit.com/*
// @match           	https://sh.reddit.com/*
// @grant           	none
// @version         	1.2
// @author          	hdyzen
// @description     	controls for player in new/sh reddit
// @license         	MIT
// ==/UserScript==
'use strict';

const clickEv = new Event('pointerup', {
    bubbles: true,
    cancelable: true,
});
let lastVol;
let defaultVol;

function observeShplayers() {
    const observer = new MutationObserver(mutations => {
        const shPlayers = document.querySelectorAll('shreddit-player:not([wControls])');
        shPlayers.forEach(shPlayer => {
            const video = shPlayer.shadowRoot?.querySelector('video');
            const shadow = shPlayer?.shadowRoot;

            if (video) {
                shPlayer.setAttribute('wControls', '');

                video.addEventListener('keydown', e => keyHandler(e, shadow, video, shPlayer));
            }
        });
    });

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

function toggleFullScreen(element) {
    if (!document.fullscreenElement) {
        element.requestFullscreen();
    } else {
        if (document.exitFullscreen) {
            document.exitFullscreen();
        }
    }
}

function framePause(video, per = 1) {
    if (!video.paused) video.pause();

    video.currentTime += per / 30;
}

function keyHandler(e, shadow, video, shPlayer) {
    if (!/ArrowUp|ArrowDown|ArrowLeft|ArrowRight|Space|KeyS|KeyF|KeyM|Comma|Period/.test(e.code)) return;
    e.preventDefault();

    let captions = shadow.querySelector('vds-caption-button');

    switch (e.code) {
        case 'ArrowUp':
            if (video.volume + 0.1 <= 1) {
                video.volume += 0.1;
            } else {
                const remainingVolume = 1 - video.volume;
                video.volume += remainingVolume;
            }
            lastVol = video.volume;
            break;
        case 'ArrowDown':
            if (video.volume - 0.1 >= 0) {
                video.volume -= 0.1;
            } else {
                const remainingVolume = 0 + video.volume;
                video.volume -= remainingVolume;
            }
            lastVol = video.volume === 0 ? 0.1 : video.volume;
            break;
        case 'ArrowLeft':
            if (e.ctrlKey) {
                video.currentTime -= 30;
            } else if (e.shiftKey) {
                video.currentTime -= 10;
            } else {
                video.currentTime -= 5;
            }
            break;
        case 'ArrowRight':
            if (e.ctrlKey) {
                video.currentTime += 30;
            } else if (e.shiftKey) {
                video.currentTime += 10;
            } else {
                video.currentTime += 5;
            }
            break;
        case 'Space':
            if (video.paused) {
                video.play();
            } else {
                video.pause();
            }
            break;
        case 'KeyS':
            captions?.dispatchEvent(clickEv);
            break;
        case 'KeyF':
            toggleFullScreen(shPlayer);
            break;
        case 'KeyM':
            if (video.volume) {
                video.volume = 0;
            } else {
                video.volume = lastVol;
            }
            break;
        case 'Period':
            framePause(video, 1);
            break;
        case 'Comma':
            framePause(video, -1);
            break;
        default:
            break;
    }
}

document.documentElement.addEventListener('click', e => {
    if (e.target.matches('shreddit-player')) {
        e.target.shadowRoot.querySelector('video').focus();
    }
});