Old Seek UI

Return the old YouTube video player seek UI, replacing the mobile-style ones they added circa 2021.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey, το Greasemonkey ή το Violentmonkey για να εγκαταστήσετε αυτόν τον κώδικα.

You will need to install an extension such as Tampermonkey to install this script.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey ή το Violentmonkey για να εγκαταστήσετε αυτόν τον κώδικα.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey ή το Userscripts για να εγκαταστήσετε αυτόν τον κώδικα.

You will need to install an extension such as Tampermonkey to install this script.

Θα χρειαστεί να εγκαταστήσετε μια επέκταση διαχείρισης κώδικα χρήστη για να εγκαταστήσετε αυτόν τον κώδικα.

(Έχω ήδη έναν διαχειριστή κώδικα χρήστη, επιτρέψτε μου να τον εγκαταστήσω!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Έχω ήδη έναν διαχειριστή στυλ χρήστη, επιτρέψτε μου να τον εγκαταστήσω!)

// ==UserScript==
// @name         Old Seek UI
// @version      0.2
// @description  Return the old YouTube video player seek UI, replacing the mobile-style ones they added circa 2021.
// @author       Taniko Yamamoto
// @author       https://github.com/YukisCoffee/yt-player-classicifier
// @match        https://www.youtube.com/*
// @icon         https://www.youtube.com/favicon.ico
// @grant        none
// @run-at       document-start
// @namespace https://greatest.deepsurf.us/users/1132181
// ==/UserScript==

(function() {

    const ICONSET = {
        "back10": "M 18,11 V 7 l -5,5 5,5 v -4 c 3.3,0 6,2.7 6,6 0,3.3 -2.7,6 -6,6 -3.3,0 -6,-2.7 -6,-6 h -2 c 0,4.4 3.6,8 8,8 4.4,0 8,-3.6 8,-8 0,-4.4 -3.6,-8 -8,-8 z M 16.9,22 H 16 V 18.7 L 15,19 v -0.7 l 1.8,-0.6 h .1 V 22 z m 4.3,-1.8 c 0,.3 0,.6 -0.1,.8 l -0.3,.6 c 0,0 -0.3,.3 -0.5,.3 -0.2,0 -0.4,.1 -0.6,.1 -0.2,0 -0.4,0 -0.6,-0.1 -0.2,-0.1 -0.3,-0.2 -0.5,-0.3 -0.2,-0.1 -0.2,-0.3 -0.3,-0.6 -0.1,-0.3 -0.1,-0.5 -0.1,-0.8 v -0.7 c 0,-0.3 0,-0.6 .1,-0.8 l .3,-0.6 c 0,0 .3,-0.3 .5,-0.3 .2,0 .4,-0.1 .6,-0.1 .2,0 .4,0 .6,.1 .2,.1 .3,.2 .5,.3 .2,.1 .2,.3 .3,.6 .1,.3 .1,.5 .1,.8 v .7 z m -0.9,-0.8 v -0.5 c 0,0 -0.1,-0.2 -0.1,-0.3 0,-0.1 -0.1,-0.1 -0.2,-0.2 -0.1,-0.1 -0.2,-0.1 -0.3,-0.1 -0.1,0 -0.2,0 -0.3,.1 l -0.2,.2 c 0,0 -0.1,.2 -0.1,.3 v 2 c 0,0 .1,.2 .1,.3 0,.1 .1,.1 .2,.2 .1,.1 .2,.1 .3,.1 .1,0 .2,0 .3,-0.1 l .2,-0.2 c 0,0 .1,-0.2 .1,-0.3 v -1.5 z",
        "forward10": "m 10,19 c 0,4.4 3.6,8 8,8 4.4,0 8,-3.6 8,-8 h -2 c 0,3.3 -2.7,6 -6,6 -3.3,0 -6,-2.7 -6,-6 0,-3.3 2.7,-6 6,-6 v 4 l 5,-5 -5,-5 v 4 c -4.4,0 -8,3.6 -8,8 z m 6.8,3 H 16 V 18.7 L 15,19 v -0.7 l 1.8,-0.6 h .1 V 22 z m 4.3,-1.8 c 0,.3 0,.6 -0.1,.8 l -0.3,.6 c 0,0 -0.3,.3 -0.5,.3 C 20,21.9 19.8,22 19.6,22 19.4,22 19.2,22 19,21.9 18.8,21.8 18.7,21.7 18.5,21.6 18.3,21.5 18.3,21.3 18.2,21 18.1,20.7 18.1,20.5 18.1,20.2 v -0.7 c 0,-0.3 0,-0.6 .1,-0.8 l .3,-0.6 c 0,0 .3,-0.3 .5,-0.3 .2,0 .4,-0.1 .6,-0.1 .2,0 .4,0 .6,.1 .2,.1 .3,.2 .5,.3 .2,.1 .2,.3 .3,.6 .1,.3 .1,.5 .1,.8 v .7 z m -0.8,-0.8 v -0.5 c 0,0 -0.1,-0.2 -0.1,-0.3 0,-0.1 -0.1,-0.1 -0.2,-0.2 -0.1,-0.1 -0.2,-0.1 -0.3,-0.1 -0.1,0 -0.2,0 -0.3,.1 l -0.2,.2 c 0,0 -0.1,.2 -0.1,.3 v 2 c 0,0 .1,.2 .1,.3 0,.1 .1,.1 .2,.2 .1,.1 .2,.1 .3,.1 .1,0 .2,0 .3,-0.1 l .2,-0.2 c 0,0 .1,-0.2 .1,-0.3 v -1.5 z",
        "back5": "M 18,11 V 7 l -5,5 5,5 v -4 c 3.3,0 6,2.7 6,6 0,3.3 -2.7,6 -6,6 -3.3,0 -6,-2.7 -6,-6 h -2 c 0,4.4 3.6,8 8,8 4.4,0 8,-3.6 8,-8 0,-4.4 -3.6,-8 -8,-8 z m -1.3,8.9 .2,-2.2 h 2.4 v .7 h -1.7 l -0.1,.9 c 0,0 .1,0 .1,-0.1 0,-0.1 .1,0 .1,-0.1 0,-0.1 .1,0 .2,0 h .2 c .2,0 .4,0 .5,.1 .1,.1 .3,.2 .4,.3 .1,.1 .2,.3 .3,.5 .1,.2 .1,.4 .1,.6 0,.2 0,.4 -0.1,.5 -0.1,.1 -0.1,.3 -0.3,.5 -0.2,.2 -0.3,.2 -0.4,.3 C 18.5,22 18.2,22 18,22 17.8,22 17.6,22 17.5,21.9 17.4,21.8 17.2,21.8 17,21.7 16.8,21.6 16.8,21.5 16.7,21.3 16.6,21.1 16.6,21 16.6,20.8 h .8 c 0,.2 .1,.3 .2,.4 .1,.1 .2,.1 .4,.1 .1,0 .2,0 .3,-0.1 L 18.5,21 c 0,0 .1,-0.2 .1,-0.3 v -0.6 l -0.1,-0.2 -0.2,-0.2 c 0,0 -0.2,-0.1 -0.3,-0.1 h -0.2 c 0,0 -0.1,0 -0.2,.1 -0.1,.1 -0.1,0 -0.1,.1 0,.1 -0.1,.1 -0.1,.1 h -0.7 z",
        "forward5": "m 10,19 c 0,4.4 3.6,8 8,8 4.4,0 8,-3.6 8,-8 h -2 c 0,3.3 -2.7,6 -6,6 -3.3,0 -6,-2.7 -6,-6 0,-3.3 2.7,-6 6,-6 v 4 l 5,-5 -5,-5 v 4 c -4.4,0 -8,3.6 -8,8 z m 6.7,.9 .2,-2.2 h 2.4 v .7 h -1.7 l -0.1,.9 c 0,0 .1,0 .1,-0.1 0,-0.1 .1,0 .1,-0.1 0,-0.1 .1,0 .2,0 h .2 c .2,0 .4,0 .5,.1 .1,.1 .3,.2 .4,.3 .1,.1 .2,.3 .3,.5 .1,.2 .1,.4 .1,.6 0,.2 0,.4 -0.1,.5 -0.1,.1 -0.1,.3 -0.3,.5 -0.2,.2 -0.3,.2 -0.5,.3 C 18.3,22 18.1,22 17.9,22 17.7,22 17.5,22 17.4,21.9 17.3,21.8 17.1,21.8 16.9,21.7 16.7,21.6 16.7,21.5 16.6,21.3 16.5,21.1 16.5,21 16.5,20.8 h .8 c 0,.2 .1,.3 .2,.4 .1,.1 .2,.1 .4,.1 .1,0 .2,0 .3,-0.1 L 18.4,21 c 0,0 .1,-0.2 .1,-0.3 v -0.6 l -0.1,-0.2 -0.2,-0.2 c 0,0 -0.2,-0.1 -0.3,-0.1 h -0.2 c 0,0 -0.1,0 -0.2,.1 -0.1,.1 -0.1,0 -0.1,.1 0,.1 -0.1,.1 -0.1,.1 h -0.6 z",
        "backchapter": "m 16.436975,17.634454 c -0.573529,0 -1.191177,0.117647 -1.617647,0.441177 v 4.308938 c 0,0.191177 0.214706,0.132123 0.220588,0.132123 0.397059,-0.191176 0.970588,-0.323414 1.397059,-0.323414 0.57353,0 1.191177,0.117646 1.617647,0.441176 0.397059,-0.25 1.117648,-0.441176 1.617647,-0.441176 0.485295,0 0.985294,0.08846 1.397059,0.309053 0.120588,0.06177 0.220589,-0.05623 0.220589,-0.132698 v -4.294002 c -0.438235,-0.329412 -1.067647,-0.441177 -1.617648,-0.441177 -0.573529,0 -1.191176,0.117647 -1.617647,0.441177 -0.42647,-0.32353 -1.044117,-0.441177 -1.617647,-0.441177 z m 3.235294,0.588235 c 0.352942,0 0.705883,0.04411 1.029412,0.147059 v 3.382353 c -0.323529,-0.102941 -0.67647,-0.147059 -1.029412,-0.147059 -0.499999,0 -1.220588,0.191177 -1.617647,0.441177 v -3.382353 c 0.397059,-0.25 1.117648,-0.441177 1.617647,-0.441177 z m -0.674976,1.202322 v 1.303997 l 1.024241,-0.651999 z M 18,7 l -5,5 5,5 v -4 c 3.3,0 6,2.7 6,6 0,3.3 -2.7,6 -6,6 -3.3,0 -6,-2.7 -6,-6 h -2 c 0,4.4 3.6,8 8,8 4.4,0 8,-3.6 8,-8 0,-4.4 -3.6,-8 -8,-8 z",
        "forwardchapter": "m 16.436975,17.634454 c -0.573529,0 -1.191177,0.117647 -1.617647,0.441177 v 4.308938 c 0,0.191177 0.214706,0.132123 0.220588,0.132123 0.397059,-0.191176 0.970588,-0.323414 1.397059,-0.323414 0.57353,0 1.191177,0.117646 1.617647,0.441176 0.397059,-0.25 1.117648,-0.441176 1.617647,-0.441176 0.485295,0 0.985294,0.08846 1.397059,0.309053 0.120588,0.06177 0.220589,-0.05623 0.220589,-0.132698 v -4.294002 c -0.438235,-0.329412 -1.067647,-0.441177 -1.617648,-0.441177 -0.573529,0 -1.191176,0.117647 -1.617647,0.441177 -0.42647,-0.32353 -1.044117,-0.441177 -1.617647,-0.441177 z m 3.235294,0.588235 c 0.352942,0 0.705883,0.04411 1.029412,0.147059 v 3.382353 c -0.323529,-0.102941 -0.67647,-0.147059 -1.029412,-0.147059 -0.499999,0 -1.220588,0.191177 -1.617647,0.441177 v -3.382353 c 0.397059,-0.25 1.117648,-0.441177 1.617647,-0.441177 z m -0.674976,1.202322 v 1.303997 l 1.024241,-0.651999 z M 18,7 v 4 c -4.4,0 -8,3.6 -8,8 0,4.4 3.6,8 8,8 4.4,0 8,-3.6 8,-8 h -2 c 0,3.3 -2.7,6 -6,6 -3.3,0 -6,-2.7 -6,-6 0,-3.3 2.7,-6 6,-6 v 4 l 5,-5 z"
    };
    const DEBUG = false;

    // Player API reference
    var api;
    var bezel;

    var animationStartTimer = 0;
    var animationShouldEndTimer = 0;

    function log(a)
    {
        if (DEBUG) console.log(a);
    }

    function getAnimationDuration(elm)
    {
        var prop = window.getComputedStyle(elm).animationDuration;

        switch (true)
        {
            case "ms" == prop.substr(-2):
                return +prop.replace("ms", "");
            case "s" == prop.substr(-1):
                return +(prop.replace("s", "")) * 1000;
        }
    }

    async function attemptEndAnimateBezel()
    {
        while (animationShouldEndTimer > Date.now())
        {
            await new Promise(r => requestAnimationFrame(r));
        }

        animationStartTimer = 0;
        animationShouldEndTimer = 0;
        bezel.style.display = "none";
    }

    function animateBezel()
    {
        var animationDuration = getAnimationDuration(bezel.querySelector(".ytp-bezel"));

        bezel.style.display = "";

        if (0 == animationShouldEndTimer)
        {
            animationStartTimer = Date.now();
            animationShouldEndTimer = animationStartTimer;
        }

        animationShouldEndTimer += animationDuration;

        attemptEndAnimateBezel();
    }

    function waitToAnimate()
    {
        return new Promise(resolve => {
            setTimeout(() => {
                resolve();
            }, 10);
        });
    }

    function createBezel(direction, duration, text = "", chapter = false)
    {
        return new Promise(resolve => {
            log("Creating bezel");
            var bezelElm = api.querySelector(".ytp-bezel");
            bezel = bezelElm.parentNode;

            bezelElm.removeAttribute("aria-label");

            // Get the icon from the iconset
            var icon;
            if (chapter)
            {
                icon = ICONSET[direction + "chapter"];
            }
            else if (ICONSET[direction + duration])
            {
                icon = ICONSET[direction + duration];
            }
            else
            {
                icon = "";
            }

            var iconElm;
            if (iconElm = bezel.querySelector(".ytp-bezel-icon path"))
            {
                iconElm.setAttribute("d", icon);
            }
            else
            {
                bezel.querySelector(".ytp-bezel-icon").insertAdjacentHTML("beforeend",
                    `<svg height="100%" version="1.1" viewBox="0 0 36 36" width="100%">
                        <path class="ytp-svg-fill" d="${icon}"></path>
                    </svg>`
                );
            }

            if ("" === text)
            {
                bezel.setAttribute("class", "ytp-bezel-text-hide");
            }
            else
            {
                bezel.setAttribute("class", "");
                bezel.querySelector(".ytp-bezel-text").innerText = text;
            }

            bezel.style.display = "none";

            resolve();
        });
    }

    async function waitForElement(query, timeout = 500)
    {
        log("Waiting for element " + query + " with timeout in " + timeout + " ms.");
        var hasTimedOut = false;

        setTimeout(function() {
            log("Wait for element " + query + " has timed out.");
            hasTimedOut = true;
        }, timeout);

        while (null == document.querySelector(query) && !hasTimedOut)
        {
            await new Promise(r => requestAnimationFrame(r));
        }

        var a;
        if (a = document.querySelector(query))
        {
            return a;
        }
        else
        {
            return null;
        }
    }

    function handleSeekGui()
    {
        log("Handing seek GUI");
        var direction = this.dataset.side;
        var duration = this.querySelector(".ytp-doubletap-tooltip-label")
            .innerText.replace(/[\s|[A-Za-z]]*/g, "")
        ;
        var text = "";
        var isChapter = false;

        if (this.classList.contains("ytp-chapter-seek"))
        {
            var textContainer = this.querySelector(".ytp-chapter-seek-text-legacy")
            text = textContainer.innerText;
            duration = 0;
            isChapter = true;
        }

        createBezel(direction, duration, text, isChapter).then(waitToAnimate).then(animateBezel);
    }

    async function attemptHookPlayer()
    {
        log("Attempting to hook player");
        var playerApi = await waitForElement(".html5-video-player", 5000);

        if (playerApi)
        {
            log("Player API detected");
            api = playerApi;

            var doubleTapElm = api.querySelector(".ytp-doubletap-ui-legacy") ?? api.querySelector(".ytp-doubletap-ui") ?? null;

            if (doubleTapElm && !api.__oldSeekUi)
            {
                log("Doubletap detected: installing binding");
                (new MutationObserver(handleSeekGui.bind(doubleTapElm)))
                    .observe(doubleTapElm, {"subtree": true, "childList": true, "characterData": "true"});
                api.__oldSeekUi = true;
            }
        }
    }

    function insertContinuationEvent()
    {
        log("Inserting continuation events");
        if (window.ytspf && window.ytspf.enabled)
        {
            log("Inserted spf continuation events");
            document.addEventListener("spfdone", attemptHookPlayer);
        }
        else if (document.querySelector("ytd-app"))
        {
            log("Inserted kevlar continuation events");
            document.addEventListener("yt-page-data-updated", attemptHookPlayer);
        }
    }

    function installInitialStyles()
    {
        log("Installed initial styles");
        document.head.insertAdjacentHTML("beforeend",
            `<style>
                .ytp-doubletap-ui, .ytp-doubletap-ui-legacy
                {
                    display: none !important;
                }
            </style>`
        );
    }

    function handleDOMContentLoaded()
    {
        log("domcontentloaded event fired");
        installInitialStyles();
        document.removeEventListener("DOMContentLoaded", handleDOMContentLoaded);
    }

    async function main()
    {
        log("Old seek ui script loaded");

        document.addEventListener("DOMContentLoaded", handleDOMContentLoaded);

        // The player needs more time to init
        // So wait until a little while after page load to attempt
        // hooking the player
        window.addEventListener("load", function handleLoad() {
            log("load event fired");
            attemptHookPlayer();
            insertContinuationEvent();
            window.removeEventListener("load", handleLoad);
        });
    }

    main();

})();