shumin-youtube

自用整合修改,部分代码和样式来自 https://greasyfork.org/zh-CN/scripts/420140 和 https://userstyles.org/styles/115362 ,版权属于原作者。

// ==UserScript==
// @name               shumin-youtube
// @namespace          http://tampermonkey.net/
// @version            1.2.0
// @description        自用整合修改,部分代码和样式来自 https://greasyfork.org/zh-CN/scripts/420140 和 https://userstyles.org/styles/115362 ,版权属于原作者。
// @author             qianjunlang
// @match              *://*.youtube.com/*
// @icon               https://www.google.com/s2/favicons?sz=64&domain=youtube.com
// @require            https://cdn.staticfile.org/jquery/3.3.1/jquery.min.js
// @grant              GM_setValue
// @grant              GM_getValue
// @run-at             document-start
// @noframes
// @license            MIT License
// ==/UserScript==
'use strict';

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-


var css = [
	".ytp-play-progress {",
	"	background: linear-gradient(left,#FF0000,#FF7F00,#FFFF00,#00FF00,#0000FF,#4B0082,#8F00FF);",
	"	background: -moz-linear-gradient(left,#FF0000,#FF7F00,#FFFF00,#00FF00,#0000FF,#4B0082,#8F00FF);",
	"	background: -o-linear-gradient(left,#FF0000,#FF7F00,#FFFF00,#00FF00,#0000FF,#4B0082,#8F00FF);",
	"	background: -webkit-linear-gradient(left,#FF0000,#FF7F00,#FFFF00,#00FF00,#0000FF,#4B0082,#8F00FF);",
	"}",
	".ytp-hover-progress-light {",
	" 	background: linear-gradient(left,#FF8080,#FFBF80,#FFFF80,#80FF80,#8080FF,#A580C0,#C780FF);",
	"	background: -moz-linear-gradient(left,#FF8080,#FFBF80,#FFFF80,#80FF80,#8080FF,#A580C0,#C780FF);",
	"	background: -o-linear-gradient(left,#FF8080,#FFBF80,#FFFF80,#80FF80,#8080FF,#A580C0,#C780FF);",
	"	background: -webkit-linear-gradient(left,#FF8080,#FFBF80,#FFFF80,#80FF80,#8080FF,#A580C0,#C780FF);",
	"}",
	".ytp-unloaded-progress {",
	"	background: linear-gradient(left ,#191919, #4d4d4d, #4C0000, #4c3200, #4c4c00, #002600, #00004c, #260026, #36264c, #4d4d4d, #191919);",
	"  	background: -moz-linear-gradient(left ,#191919, #4d4d4d, #4C0000, #4c3200, #4c4c00, #002600, #00004c, #260026, #36264c, #4d4d4d, #191919);",
	"  	background: -o-linear-gradient(left ,#191919, #4d4d4d, #4C0000, #4c3200, #4c4c00, #002600, #00004c, #260026, #36264c, #4d4d4d, #191919);",
	"  	background: -webkit-linear-gradient(left ,#191919, #4d4d4d, #4C0000, #4c3200, #4c4c00, #002600, #00004c, #260026, #36264c, #4d4d4d, #191919);",
	"}",
	".ytp-load-progress {",
	"  background: rgba(90, 90, 90, .5);",
	"}"
].join("\n");
if (typeof GM_addStyle != "undefined") {
	GM_addStyle(css);
} else if (typeof PRO_addStyle != "undefined") {
	PRO_addStyle(css);
} else if (typeof addStyle != "undefined") {
	addStyle(css);
} else {
	var node = document.createElement("style");
	node.type = "text/css";
	node.appendChild(document.createTextNode(css));
	var heads = document.getElementsByTagName("head");
	if (heads.length > 0) {
		heads[0].appendChild(node);
	} else {
		// no head yet, stick it whereever
		document.documentElement.appendChild(node);
	}
}


//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-


if (
    window.location.href.indexOf( "watch?v=" ) >= 0 ||
    window.location.href.indexOf( "/v/" ) >= 0 ||
    false
){

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

    let cycle_id = setInterval(() => {
        if(
            $(".ytp-endscreen-previous").is(":visible") ||
            $(".ytp-endscreen-next").is(":visible") ||
            $(".ytp-endscreen-content").is(":visible") ||
            false
        ) {
            document.webkitCancelFullScreen();
            document.exitFullscreen();
            document.cancelFullScreen();
        }
    }, 1000);

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

    document.addEventListener('keydown',(e)=>{
        if( 81==e.keyCode ){
            $(".YtSegmentedLikeDislikeButtonViewModelSegmentedButtonsWrapper button").first().click()
        }
    });

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

    console.log("youtube Cover is loading");
    (async () => // onStart
    {
        let tryTimes = 0;
        while(true)
        {
            console.log("try load");
            if(document.querySelector("#start")!=null)
            {
                load();
                return;
            }
            if(++tryTimes>10) return;
            await delay(300);
        }
    })();


    function delay(ms = 0){return new Promise((r)=>{setTimeout(r, ms)})}

    function getXY(element)
    {
        let x = 0, y = 0;
        while (element)
        {
            x += element.offsetLeft - element.scrollLeft + element.clientLeft;
            y += element.offsetTop - element.scrollLeft + element.clientTop;
            element = element.offsetParent;
        }
        return {X: x, Y: y}
    }

    function checkImg(imgUrl)
    {
      return new Promise(function(resolve)
      {
          let img = new Image();
          img.src = imgUrl;
          img.onload = () => {resolve(img);}
      })
    }


    function load()
    {
        var div = document.createElement("div");
        div.style.marginLeft = "3em";
        div.innerHTML =`

        <!-- css -->
        <style>
            #ytCover {
                text-decoration: none;
                font-size: 1.1em;
                font-weight: bold;
                font-family: Roboto, Arial, sans-serif;
                color: var(--yt-spec-text-primary);
            }

            div.list {
                background-color: var(--yt-spec-brand-background-primary);
                border: 1px solid var(--yt-spec-10-percent-layer);
                padding: 0.5em 0;
                position: fixed;
                z-index: 114514;
                max-height: 40em;
                font-size: 10px
            }

            .linkBtn {
                text-decoration: none;
            }

            .list-item {
                text-align: center;
                font-size: 1.5em;
                color: var(--yt-spec-text-primary);
                background-color: var(--yt-spec-brand-background-primary);
                height: 2.5em;
                line-height: 2.5em;
            }
            .list-item:hover {
                background: #AAA;
                box-shadow: 0 4px 5px rgba(0, 0, 0, 0.2);
            }

            .slide {
                cursor: default
            }

            img#preview {
                position: fixed;
                top: 50%;
                left: 50%;
                transform: translate(-50%, -50%);
                z-index: 2000;
                max-width: 100vw;
                max-height: 65vh;
                min-width: 40vw;
                border: 3px solid #FFF;
            }

            .list > button {
                border: none;
                padding: unset;
                width: inherit;
                cursor: pointer;
            }

        </style>

        <!-- html -->
        <div>
            <div class="slide" id="ytCover"></div>

            <div class="list" id="ytListHead" style="border-top: none; top: 4.8em; left: 19em;" hidden>

                <div class="list-item slide">1280x720+
                    <div class="list" style="border-left: none; width: 11.5em" hidden>
                        <a class="linkBtn" imgTag="maxresdefault"><div class="list-item">maxresdefault</div></a>
                        <a class="linkBtn" imgTag="maxres1"><div class="list-item">maxres1</div></a>
                        <a class="linkBtn" imgTag="maxres2"><div class="list-item">maxres2</div></a>
                        <a class="linkBtn" imgTag="maxres3"><div class="list-item">maxres3</div></a>
                    </div>
                </div>

                <div class="list-item slide">640x480
                    <div class="list" style="border-left: none; width: 8.5em" hidden>
                        <a class="linkBtn" imgTag="sddefault"><div class="list-item">sddefault</div></a>
                        <a class="linkBtn" imgTag="sd1"><div class="list-item">sd1</div></a>
                        <a class="linkBtn" imgTag="sd2"><div class="list-item">sd2</div></a>
                        <a class="linkBtn" imgTag="sd3"><div class="list-item">sd3</div></a>
                    </div>
                </div>

                <div class="list-item slide">480x360
                    <div class="list" style="border-left: none; width: 8.5em" hidden>
                        <a class="linkBtn" imgTag="hqdefault"><div class="list-item">hqdefault</div></a>
                        <a class="linkBtn" imgTag="hq1"><div class="list-item">hq1</div></a>
                        <a class="linkBtn" imgTag="hq2"><div class="list-item">hq2</div></a>
                        <a class="linkBtn" imgTag="hq3"><div class="list-item">hq3</div></a>
                    </div>
                </div>

                <div class="list-item slide">320x180
                    <div class="list" style="border-left: none; width: 8.5em" hidden>
                        <a class="linkBtn" imgTag="mqdefault"><div class="list-item">mqdefault</div></a>
                        <a class="linkBtn" imgTag="mq1"><div class="list-item">mq1</div></a>
                        <a class="linkBtn" imgTag="mq2"><div class="list-item">mq2</div></a>
                        <a class="linkBtn" imgTag="mq3"><div class="list-item">mq3</div></a>
                    </div>
                </div>

                <div class="list-item slide">120x90
                    <div class="list" style="border-left: none; width: 6.5em" hidden>
                        <a class="linkBtn" imgTag="default"><div class="list-item">default</div></a>
                        <a class="linkBtn" imgTag="1"><div class="list-item">1</div></a>
                        <a class="linkBtn" imgTag="2"><div class="list-item">2</div></a>
                        <a class="linkBtn" imgTag="3"><div class="list-item">3</div></a>
                    </div>
                </div>

                <button class="list-item">: <span id="previewSpan" style="font-weight: bold;">On</span></button>
            </div>
        </div>`

        document.querySelector("#start").append(div);
        var preview = document.createElement("img");
        preview.id = "preview";
        preview.hidden = true;
        document.body.append(preview);

        var ytC = document.querySelector("#ytCover");
        var ytLH = document.querySelector("#ytListHead");
        var Btns = document.querySelectorAll(".linkBtn");
        var previewBtn = document.querySelector(".list > button");
        var Lang = { cover: {en:"Cover", tc:"封面", sc:"封面"},
                   preview: {en:"Preview", tc:"圖片預覽", sc:"图片预览"},
                        on: {en:"On", tc:"開", sc:"开"},
                       off: {en:"Off", tc:"關", sc:"关"}};
        var usedLang;

        if (document.querySelector("html").lang.indexOf("zh")!=-1)
            {usedLang = document.querySelector("html").lang.indexOf("CN")!=-1?"sc":"tc";}
        else
            {usedLang = "en";}

        ytC.innerText = Lang.cover[usedLang];
        previewBtn.innerHTML = Lang.preview[usedLang] + previewBtn.innerHTML;
        ytLH.style.width = usedLang=="en"?"10em":"10.4em";

        window.onresize = () =>
        {
            ytLH.style.left = (getXY(ytC).X/10-1)+"em";
            if(window.innerWidth<1350)
            {
                if(window.innerWidth>850)div.style.marginLeft = 3*((window.innerWidth-500)/850) + "em";
                else div.style.marginLeft = "1em";
            }
            else
            {div.style.marginLeft = "3em";}
        }

        document.querySelectorAll(".list > .slide").forEach((e)=>
        {
            let list = e.querySelector(".list");
            e.onmouseenter = () =>
            {
                list.style.top = (getXY(e).Y/10-0.5)+"em";
                list.style.left = parseFloat(ytLH.style.left) + parseFloat(ytLH.style.width) + "em";
                list.hidden = false;
            };
            e.onmouseleave = () => {list.hidden = true;}
        });
        Btns.forEach((e)=>
        {
            e.onmouseenter = () =>
            {
                if(!GM_getValue("previewOn")) return;
                preview.hidden = false;
                preview.src = e.href;
            };
            e.onmouseleave = () => {preview.hidden = true;}
            e.target="_blank";
        });
        var previewSpan = document.querySelector("#previewSpan");

        var previewBtnChange = () =>
        {
            if (GM_getValue("previewOn"))
            {
                previewSpan.style.color = "green";
                previewSpan.innerText = Lang.on[usedLang];
            }
            else
            {
                previewSpan.style.color = "red";
                previewSpan.innerText = Lang.off[usedLang];
            }
        };
        previewBtnChange();
        previewBtn.onclick = () =>
        {
            GM_setValue("previewOn", !GM_getValue("previewOn"));
            previewBtnChange();
        };


        var hide;
        ytC.onmouseenter = () =>
        {
            hide = false;
            ytLH.hidden = false;
        };
        ytC.onmouseleave = async () =>
        {
            hide = true;
            await delay(500);
            ytLH.hidden = hide;
        };
        ytLH.onmouseenter = () =>
        {
            hide = false;
        };
        ytLH.onmouseleave = async () =>
        {
            hide = true;
            await delay(200);
            ytLH.hidden = hide;
        };


        var oldHref = null;
        new MutationObserver(() => // onUrlChange
        {
            if (oldHref != document.location.href)
            {
                oldHref = document.location.href

                let video_id = null;
                window.location.search.replace("?","").split('&').forEach((s)=>{if(s.startsWith("v=")){video_id=s.replace("v=","")};});
                ytC.hidden = (video_id == null);
                if (video_id == null) return;

                document.querySelectorAll(".list-item > .list").forEach((e)=>
                {
                    if (e.style.width=="6.5em") return;
                    let tempBtns = e.querySelectorAll(".linkBtn");
                    e.parentNode.hidden = true;
                    tempBtns.forEach((forEachBtn)=>
                    {
                        checkImg("https://i.ytimg.com/vi/" + video_id + "/" + forEachBtn.getAttribute("imgTag") + ".jpg").then((img)=>
                        {
                            let notHide = (img.width>120 && img.height>90);
                            forEachBtn.hidden = !notHide;
                            if(notHide) e.parentNode.hidden = false;
                        });
                    });
                });

                checkImg("https://i.ytimg.com/vi/" + video_id + "/mq1.jpg").then((img)=>
                {
                    document.querySelector("#ytListHead > div:nth-child(5)").querySelectorAll(".linkBtn").forEach((e)=>
                    {if(e.getAttribute("imgTag").indexOf("default")==-1) e.hidden=(img.width<=120 && img.height<=90);});
                });

                Btns.forEach((e)=>{e.href = "https://i.ytimg.com/vi/" + video_id + "/" + e.getAttribute("imgTag") + ".jpg";});
            }
        }).observe(document.body, {childList: true, subtree: true});

        console.log("done");
    }


//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

}