Greasy Fork

Greasy Fork is available in English.

Tabview Youtube

Make comments and lists into tabs

当前为 2021-06-30 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Tabview Youtube
// @namespace    http://tampermonkey.net/
// @version      0.3
// @description  Make comments and lists into tabs
// @author       CY Fung
// @match        https://www.youtube.com/watch?v=*
// @resource     contentCSS https://github.com/cyfung1031/Tabview-Youtube/raw/main/css/style_content.css?v20210701a
// @icon         https://github.com/cyfung1031/Tabview-Youtube/raw/main/images/icon128p.png
// @require      https://code.jquery.com/jquery-3.6.0.slim.min.js
// @grant        GM_getResourceText
// @run-at       document-start
// @license      MIT https://github.com/cyfung1031/Tabview-Youtube/blob/main/LICENSE
// ==/UserScript==
function main($){
    // MIT License
    // https://github.com/cyfung1031/Tabview-Youtube/raw/main/js/content.js





/**
 * SVG resources:
 * <div>Icons made by <a href="https://www.flaticon.com/authors/smashicons" title="Smashicons">Smashicons</a> from <a href="https://www.flaticon.com/" title="Flaticon">www.flaticon.com</a></div>
 */
 const svgComments = `
 <path d="M40.068,13.465L5.93,13.535c-3.27,0-5.93,2.66-5.93,5.93v21.141c0,3.27,2.66,5.929,5.93,5.929H12v10
 c0,0.413,0.254,0.784,0.64,0.933c0.117,0.045,0.239,0.067,0.36,0.067c0.276,0,0.547-0.115,0.74-0.327l9.704-10.675l16.626-0.068
 c3.27,0,5.93-2.66,5.93-5.929V19.395C46,16.125,43.34,13.465,40.068,13.465z M10,23.465h13c0.553,0,1,0.448,1,1s-0.447,1-1,1H10
 c-0.553,0-1-0.448-1-1S9.447,23.465,10,23.465z M36,37.465H10c-0.553,0-1-0.448-1-1s0.447-1,1-1h26c0.553,0,1,0.448,1,1
 S36.553,37.465,36,37.465z M36,31.465H10c-0.553,0-1-0.448-1-1s0.447-1,1-1h26c0.553,0,1,0.448,1,1S36.553,31.465,36,31.465z"/>
 <path d="M54.072,2.535L19.93,2.465c-3.27,0-5.93,2.66-5.93,5.93v3.124l26.064-0.054c4.377,0,7.936,3.557,7.936,7.93v21.07v0.071
 v2.087l3.26,3.586c0.193,0.212,0.464,0.327,0.74,0.327c0.121,0,0.243-0.022,0.36-0.067c0.386-0.149,0.64-0.52,0.64-0.933v-10h1.07
 c3.27,0,5.93-2.66,5.93-5.929V8.465C60,5.195,57.34,2.535,54.072,2.535z"/>
 `

const svgVideos = `<path d="M298,33c0-13.255-10.745-24-24-24H24C10.745,9,0,19.745,0,33v232c0,13.255,10.745,24,24,24h250c13.255,0,24-10.745,24-24V33
 z M91,39h43v34H91V39z M61,259H30v-34h31V259z M61,73H30V39h31V73z M134,259H91v-34h43V259z M123,176.708v-55.417
 c0-8.25,5.868-11.302,12.77-6.783l40.237,26.272c6.902,4.519,6.958,11.914,0.056,16.434l-40.321,26.277
 C128.84,188.011,123,184.958,123,176.708z M207,259h-43v-34h43V259z M207,73h-43V39h43V73z M268,259h-31v-34h31V259z M268,73h-31V39
 h31V73z"/>`

const svgInfo = `<path d="M11.812,0C5.289,0,0,5.289,0,11.812s5.289,11.813,11.812,11.813s11.813-5.29,11.813-11.813
 S18.335,0,11.812,0z M14.271,18.307c-0.608,0.24-1.092,0.422-1.455,0.548c-0.362,0.126-0.783,0.189-1.262,0.189
 c-0.736,0-1.309-0.18-1.717-0.539s-0.611-0.814-0.611-1.367c0-0.215,0.015-0.435,0.045-0.659c0.031-0.224,0.08-0.476,0.147-0.759
 l0.761-2.688c0.067-0.258,0.125-0.503,0.171-0.731c0.046-0.23,0.068-0.441,0.068-0.633c0-0.342-0.071-0.582-0.212-0.717
 c-0.143-0.135-0.412-0.201-0.813-0.201c-0.196,0-0.398,0.029-0.605,0.09c-0.205,0.063-0.383,0.12-0.529,0.176l0.201-0.828
 c0.498-0.203,0.975-0.377,1.43-0.521c0.455-0.146,0.885-0.218,1.29-0.218c0.731,0,1.295,0.178,1.692,0.53
 c0.395,0.353,0.594,0.812,0.594,1.376c0,0.117-0.014,0.323-0.041,0.617c-0.027,0.295-0.078,0.564-0.152,0.811l-0.757,2.68
 c-0.062,0.215-0.117,0.461-0.167,0.736c-0.049,0.275-0.073,0.485-0.073,0.626c0,0.356,0.079,0.599,0.239,0.728
 c0.158,0.129,0.435,0.194,0.827,0.194c0.185,0,0.392-0.033,0.626-0.097c0.232-0.064,0.4-0.121,0.506-0.17L14.271,18.307z
  M14.137,7.429c-0.353,0.328-0.778,0.492-1.275,0.492c-0.496,0-0.924-0.164-1.28-0.492c-0.354-0.328-0.533-0.727-0.533-1.193
 c0-0.465,0.18-0.865,0.533-1.196c0.356-0.332,0.784-0.497,1.28-0.497c0.497,0,0.923,0.165,1.275,0.497
 c0.353,0.331,0.53,0.731,0.53,1.196C14.667,6.703,14.49,7.101,14.137,7.429z"/>`

const svgPlayList = `
 <rect x="0" y="64" width="256" height="42.667"/>
 <rect x="0" y="149.333" width="256" height="42.667"/>
 <rect x="0" y="234.667" width="170.667" height="42.667"/>
 <polygon points="341.333,234.667 341.333,149.333 298.667,149.333 298.667,234.667 213.333,234.667 213.333,277.333 
     298.667,277.333 298.667,362.667 341.333,362.667 341.333,277.333 426.667,277.333 426.667,234.667"/>
     `



const svgElm = (w, h, vw, vh, p) => `<svg width="${w}" height="${h}" viewBox="0 0 ${vw} ${vh}" preserveAspectRatio="xMidYMid meet">${p}</svg>`

let settings = {
    toggleSettings: {
        tabs: 1,
        tInfo: 1,
        tComments: 1,
        tVideos: 1,
    },
    defaultTab: "videos"
};

function isVideoPlaying(video) {
    return video.currentTime > 0 && !video.paused && !video.ended && video.readyState > video.HAVE_CURRENT_DATA;
}




const Q={}

function chatFrameElement(cssSelector){
    let iframe = document.querySelector('iframe#chatframe');
    if(!iframe) return null;
    let elm = null;
    try{
        elm = iframe.contentDocument.querySelector(cssSelector)
    }catch(e){
        console.log('iframe error', e)
    }
    return elm;
}



function mtf_ChatExist(){

    //iframe can be not mutation triggering
    //collaseped might help
    
    const elmChat = document.querySelector('ytd-live-chat-frame#chat')
    let elmCont = null;
    if(elmChat){
        elmCont=chatFrameElement('yt-live-chat-renderer #continuations')
    }
    
    const chatBlockR = (elmChat?1:0)+(elmCont?2:0)
    if(Q.mtf_chatBlockQ!==chatBlockR){

        //console.log(897, Q.mtf_chatBlockQ, chatBlockR)
        Q.mtf_chatBlockQ=chatBlockR

        
        const cssElm = document.querySelector('ytd-watch-flexy')
        if(elmChat){

            let s=0;
            if(elmCont){
                //not found if it is collasped.
                s |= elmCont.querySelector('yt-timed-continuation')?1:0;
                s |= elmCont.querySelector('yt-live-chat-replay-continuation, yt-player-seek-continuation')?2:0;
                //s |= elmCont.querySelector('yt-live-chat-restricted-participation-renderer')?4:0;
                if(s==1) cssElm.setAttribute('userscript-chatblock', 'chat-live')
                if(s==2) cssElm.setAttribute('userscript-chatblock', 'chat-playback')
                //if(s==5) cssElm.setAttribute('userscript-chatblock', 'chat-live-paid')


                if(s==1){
                    $("span#tab3-txt-loader").text('')
                }

            }
            //keep unknown as original
            if( !cssElm.hasAttribute) cssElm.setAttribute('userscript-chatblock', '')
           
            

        }else{
            cssElm.removeAttribute('userscript-chatblock')
            cssElm.removeAttribute('userscript-chat-collapsed')

        }
        

    }
}




let lastScrollAt = 0;

function makeBodyScroll() {

    // avoid over triggering scroll event
    if (+new Date - lastScrollAt < 30) return;
    lastScrollAt = +new Date;

    //required for youtube content display

    requestAnimationFrame(()=>{

        window.dispatchEvent(new Event("scroll"));

    })

}


let mtoIgnoreTo = 0
let mtoNav = null;

let mtf_playerListQ = null
var stComments_last = null
let mtf_liveChatBtnQ = null;



function AddTabPanel() {

    if (window.location.href.indexOf("www.youtube.com/watch?v=") < 0) return;


    let ts = settings.toggleSettings;

    if (!ts.tabs) return;

    const sTabBtnVideos = `${svgElm(16,16,298,298,svgVideos)}<span>Videos</span>`
    const sTabBtnInfo = `${svgElm(16,16,23.625,23.625,svgInfo)}<span>Info</span>`
    const sTabBtnPlayList = `${svgElm(16,16,426.667,426.667,svgPlayList)}<span>Playlist</span>`

    const str1 = `
     <paper-ripple class="style-scope yt-icon-button">
         <div id="background" class="style-scope paper-ripple" style="opacity:0;"></div>
         <div id="waves" class="style-scope paper-ripple"></div>
     </paper-ripple>
     `;



    const str_tabs = [
        ts.tInfo ? `<a id="tab-btn1" data-name="info" userscript-tab-content="#tab-info" class="tab-btn">${sTabBtnInfo}${str1}</a>` : '',
        `<a id="tab-btn2" userscript-tab-content="#tab-live" class="tab-btn hide">Chat${str1}</a>`,
        ts.tComments ? `<a id="tab-btn3" userscript-tab-content="#tab-comments" data-name="comments" class="tab-btn">${svgElm(16,16,60,60,svgComments)}<span id="tab3-txt-loader"></span>${str1}</a>` : '',
        ts.tVideos ? `<a id="tab-btn4" userscript-tab-content="#tab-videos" data-name="videos" class="active tab-btn">${sTabBtnVideos}${str1}</a>` : '',
        `<a id="tab-btn5" userscript-tab-content="#tab-list">${sTabBtnPlayList}${str1}</a>`
    ].join('')

    var addHTML = `
     <div id="right-tabs">
         <header>
             <div id="material-tabs">
                 ${str_tabs}
             </div>
         </header>
         <div class="tab-content">
             <div id="tab-info" class="tab-content-cld" userscript-scrollbar-render></div>
             <div id="tab-live" class="tab-content-cld hideOnRight" userscript-scrollbar-render></div>
             <div id="tab-comments" class="tab-content-cld" userscript-scrollbar-render></div>
             <div id="tab-videos" class="tab-content-cld" userscript-scrollbar-render></div>
             <div id="tab-list" class="tab-content-cld" userscript-scrollbar-render></div>
         </div>
     </div>
     `;


    $("ytd-watch-flexy").removeAttr("userscript-chatblock").removeAttr("userscript-chat-collapsed")

    remove_DisablePauseVideo();
/*
    let elm1 = document.querySelector("ytd-watch-metadata ~ #info")
    let elm2 = document.querySelector('ytd-comments#comments')


    if (elm1 && elm2) {

        add_DisablePauseVideo();
        $(elm2).addClass('userscript-hide-comments')
        insertBefore(elm2, elm1)

    }
*/



    mtf_liveChatBtnQ = null

    if (mtoNav) {
        mtoNav.takeRecords();
        mtoNav.disconnect();
        mtoNav = null;
        Q.mtf_checkDescriptionLoaded = null
        Q.mtf_related = null;
        Q.mtf_checkPlayList = null;
        Q.mtf_checkCommentsLoaded = null;
        mtf_playerListQ = null
        stComments_last = null
        mtoIgnoreTo = 0;
        Q.mtf_checkTabStatus_playlist=null;
        Q.mtf_checkTabStatus_comments=null;
        Q.mtf_checkStatus_chatroom=null;
        Q.mtf_chatBlockQ=null;
    }
    var wwx = 0;
    var lastRelocate = 0


    function mtf_commentRelocate() {

        let elm1, elm2;

        if (+new Date - lastRelocate > 350) {

            if ((elm1 = document.querySelector("ytd-watch-metadata ~ #info")) && (elm2 = document.querySelector('ytd-watch-metadata ~ #info ~ ytd-comments#comments'))) {
                lastRelocate = +new Date;
                window.requestAnimationFrame(() => {
                    add_DisablePauseVideo();
                    //$(elm2).addClass('userscript-hide-comments')
                    
                    $(elm2).appendTo('#tab-comments')
                    
                    //insertBefore(elm2, elm1)

                    elm1 = null;
                    elm2 = null;
                })

            }
        }
    }

    let mtf_commentRenderingLast=0;
    function mtf_commentRendering() {

        //var elmHeader = document.querySelector("ytd-comments#comments.userscript-hide-comments ytd-comments-header-renderer");
        var elmHeader = document.querySelector("ytd-comments#comments ytd-comments-header-renderer");
        if (elmHeader) {
            if(new Date - mtf_commentRenderingLast<800) return;
            mtf_commentRenderingLast=+new Date;
            window.requestAnimationFrame(() => {
                const comments = $("ytd-comments#comments")[0];
                const tabComments = $("#tab-comments")[0];
                if(!comments|| !tabComments) return;
                if(!tabComments.contains(comments)) $(comments).appendTo(tabComments);
                checkCommentsLoaded();
                $(comments).removeClass('userscript-hide-comments')
            })
        }
    }


    function mtf_liveChatBtnF() {

        let button = document.querySelector('ytd-live-chat-frame#chat>.ytd-live-chat-frame#show-hide-button:nth-child(n+2)')

        if(button){
            requestAnimationFrame(()=> button.parentNode.insertBefore(button, button.parentNode.firstChild) )
            }


    }

    function mtf_fixInfo() {

        const content = document.querySelector('#meta-contents ytd-expander>#content, #tab-info ytd-expander>#content')
        if (content) {
        const expander = content.parentNode;

        if (expander.hasAttribute('collapsed')) expander.removeAttribute('collapsed');

        let btn1 = expander.querySelector('tp-yt-paper-button#less:not([hidden])');
        let btn2 = expander.querySelector('tp-yt-paper-button#more:not([hidden])');

        if (btn1) btn1.setAttribute('hidden', '');
        if (btn2) btn2.setAttribute('hidden', '');

        }



        const playlist = document.querySelector('#tab-list ytd-playlist-panel-renderer#playlist')

        if(playlist){


            if(playlist.hasAttribute('collapsed')) playlist.removeAttribute('collapsed');

            if(playlist.hasAttribute('collapsible')) playlist.removeAttribute('collapsible');
        }
         


    }

    function mtf_appendPlayList(){
        
        let ple1 = document.querySelector("#secondary>ytd-playlist-panel-renderer#playlist, #secondary-inner>ytd-playlist-panel-renderer#playlist");
        if(ple1){

            let $wrapper = $('#ytd-userscript-playlist');
            if(!$wrapper[0]) $wrapper=$('<div id="ytd-userscript-playlist"></div>')
            $wrapper.append(ple1).appendTo("#tab-list");
        }

    }

    let mtfaa=0;
    function mtf_advancedComments(){



        if(mtfaa)return;
        

        if(!$('ytd-comments#comments #continuations')[0]) return;

        mtfaa=1;

        $('ytd-comments#comments')[0].dispatchEvent(new Event("yt-retrieve-location"))



    }



    let mtoNav_delayedC = 0;


    let mtoNav_delayedF = () => {
        mtoNav_delayedC = 0;

        let addP=Q.addP;
        let removeP=Q.removeP;

        Q.addP=0;Q.removeP=0;

        if(!addP||!removeP) return;


        //console.log(999,++wwx)

        (async()=>{
        mtf_fixInfo();
        })();
        (async()=>{

        mtf_ChatExist();
    })();

        if(addP>0){

            (async()=>{
                mtf_commentRelocate();
            })();
            
            (async()=>{
            mtf_liveChatBtnF();
            })();
            
            (async()=>{
                mtf_commentRendering();
            })();

            (async()=>{
            mtf_appendPlayList();
            })();

            (async()=>{
                mtf_advancedComments();
            })();

            (async()=>{
                if (Q.mtf_checkDescriptionLoaded && Q.mtf_checkDescriptionLoaded() === false) Q.mtf_checkDescriptionLoaded = null
            })();

            (async()=>{
                
            if (Q.mtf_related && Q.mtf_related() === false) Q.mtf_related = null;
            })();
            (async()=>{
                
            if (Q.mtf_checkPlayList && Q.mtf_checkPlayList() === false) Q.mtf_checkPlayList = null;
            })();
            (async()=>{
                
            if (Q.mtf_checkCommentsLoaded && Q.mtf_checkCommentsLoaded() === false) Q.mtf_checkCommentsLoaded = null;
            })();
            (async()=>{
                
            if(Q.mtf_checkTabStatus_comments&&Q.mtf_checkTabStatus_comments()===false)Q.mtf_checkTabStatus_comments=null;
            })();
            (async()=>{
                
            if(Q.mtf_checkTabStatus_playlist&&Q.mtf_checkTabStatus_playlist()===false)Q.mtf_checkTabStatus_playlist=null;
            })();
            
            (async()=>{
                
            if(Q.mtf_checkStatus_chatroom&&Q.mtf_checkStatus_chatroom()===false)Q.mtf_checkStatus_chatroom=null;
            })();
      

            (async()=>{
                if(Q.mtf_forceCheckLiveVideo&&Q.mtf_forceCheckLiveVideo()===false)Q.mtf_forceCheckLiveVideo=null;
            
        })();

        }
       

    }

    Q.addP=0;
    Q.removeP=0;
    let mtoI=0;
    mtoNav = new MutationObserver((mutations, observer) => {

        if (mtoIgnoreTo > +new Date) return;

        let ch = false;
        for (const mutation of mutations) {
            for (const addedNode of mutation.addedNodes)
                if (addedNode.nodeType === 1) {
                    Q.addP++
                    ch = true;
                }
            for (const removedNode of mutation.removedNodes)
                if (removedNode.nodeType === 1) {
                    Q.removeP++;
                    ch = true;
                }
        }
        if (!ch) return;

        if (mtoNav_delayedC) return;
        
        mtoNav_delayedC=setTimeout(mtoNav_delayedF,30+((+new Date)%300)>>1)

    });
    mtoNav.observe(document.querySelector('ytd-watch-flexy'), {
        subtree: true,
        childList: true
    })



    if (document.querySelector("#right-tabs")) {
        runAfterTabAppended();
    } else {
        let watchAt = +new Date;

        Q.mtf_related = () => {
            const related = document.querySelector("#related")
            if (!related) return true;
            $(addHTML).prependTo(related);
            runAfterTabAppended();
            return false;
        }
        if (Q.mtf_related && Q.mtf_related() === false) Q.mtf_related = null;

    }


}

function setDefaultActiveTab() {
    const jElm = document.querySelector(`a[userscript-tab-content="${switchTabActivity_lastTab}"]:not(.hide)`) ||
        document.querySelector(`a[userscript-tab-content="#tab-${settings.defaultTab}"]:not(.hide)`) ||
        document.querySelector("a[userscript-tab-content]:not(.hide)") ||
        null;
    switchTabActivity(jElm)
}

function insertBefore(elm, p) {

    if (elm && p && p.parentNode)
        p.parentNode.insertBefore(elm, p)

}

function hDisablePauseVideo(evt) {

    //evt.preventDefault();
    //evt.stopPropagation();
    //evt.stopImmediatePropagation()
   // this.play();

}


function add_DisablePauseVideo() {

    const video = document.querySelector('.ytd-player video')
    if (video && isVideoPlaying(video)) video.addEventListener('pause', hDisablePauseVideo, {
        once: true,
        capture: true,
        passive: false
    })

}

function remove_DisablePauseVideo() {
    const video = document.querySelector('.ytd-player video')
    if (video) video.removeEventListener('pause', hDisablePauseVideo, {
        once: true,
        capture: true,
        passive: false
    })

}




function addControlElement() {

    $('<userscript-control-element></userscript-control-element>').prependTo('ytd-comments#comments')
}

let loadComments_cid1 = 0;


function runAfterTabAppended() {

    $('#tab-comments').attr('lazy-loading','')

    $('span#tab3-txt-loader').text('')

    setDefaultActiveTab();
    if (settings.toggleSettings.tVideos) {
        let $wrapper = $('#ytd-userscript-watch-next-videos');
        if(!$wrapper[0]) $wrapper=$('<div id="ytd-userscript-watch-next-videos"></div>')
        $wrapper.append($("ytd-watch-next-secondary-results-renderer")).appendTo("#tab-videos");
    }
    if (settings.toggleSettings.tInfo) {
        checkDescriptionLoaded();
    }
    tabsUiScript();
    checkPlayList();
    // chatToggleToTop()


    checkTabStatus();
    checkChatStatus();
    forceCheckLiveVideo();


    $("#right-tabs [userscript-scrollbar-render]").scroll(makeBodyScroll);

}


function forceCheckLiveVideo(){




    function timeCheck(){


        setTimeout(function(){

            const cssElm = document.querySelector('ytd-watch-flexy')
            if(!cssElm) return;

            if($('#ytd-player .ytp-time-display').is('.ytp-live')) cssElm.setAttribute('userscript-chatblock', 'chat-live')

        },170)

        

    }


    Q.mtf_forceCheckLiveVideo = () => {
        const playerLabel = document.querySelector('#ytd-player .ytp-time-display') && document.querySelector('ytd-live-chat-frame#chat')
        if (!playerLabel) return true;
        timeCheck();
        return false;
    }

    if (Q.mtf_forceCheckLiveVideo && Q.mtf_forceCheckLiveVideo() === false) Q.mtf_forceCheckLiveVideo = null

}


function forceCheckLiveVideo__(){

    // this is possible to detect the live video when chat area is collaseped 
    //meta might not update... 

function timeCheck(){

    setTimeout(()=>{

        const spanMeta = document.querySelector('[itemprop="publication"][itemscope][itemtype]')
        if(!spanMeta)return;
        let meta_isLiveBroadcast = spanMeta.querySelector('meta[itemprop="isLiveBroadcast"]')
        meta_isLiveBroadcast=meta_isLiveBroadcast?meta_isLiveBroadcast.getAttribute('content').toLowerCase()=='true':null
        let meta_startDate = spanMeta.querySelector('meta[itemprop="isLiveBroadcast"]')
        meta_startDate=((meta_startDate?meta_startDate.getAttribute('content'):null)||"").length>0
        let meta_endDate = spanMeta.querySelector('meta[itemprop="endDate"]')
        meta_endDate=((meta_endDate?meta_endDate.getAttribute('content'):null)||"").length>0



        const cssElm = document.querySelector('ytd-watch-flexy')
        

        if(meta_isLiveBroadcast&&meta_startDate&&!meta_endDate){

            cssElm.setAttribute('userscript-chatblock', 'chat-live')


        }else if(meta_isLiveBroadcast&&meta_startDate&&meta_endDate){

            cssElm.setAttribute('userscript-chatblock', 'chat-playback')

        }



    },170)
    


}

    Q.mtf_forceCheckLiveVideo = () => {
        const spanMeta = document.querySelector('[itemprop="publication"][itemscope][itemtype]')
        if (!spanMeta) return true;
        timeCheck();
        return false;
    }

    if (Q.mtf_forceCheckLiveVideo && Q.mtf_forceCheckLiveVideo() === false) Q.mtf_forceCheckLiveVideo = null


}



function checkDescriptionLoaded() {
    let watchAt = +new Date;
    //console.log(113);
    Q.mtf_checkDescriptionLoaded = () => {
        const expander = document.querySelector("#meta-contents ytd-expander");
        if (!expander) return true;
        $(expander).appendTo("#tab-info")
        return false;
    }

    if (Q.mtf_checkDescriptionLoaded && Q.mtf_checkDescriptionLoaded() === false) Q.mtf_checkDescriptionLoaded = null
}

function checkCommentsLoaded() {
    let $span = $("span#tab3-txt-loader")
    if (!$span[0]) return;

    Q.mtf_checkCommentsLoaded = () => {
        const commentRenderer = document.querySelector("#count.ytd-comments-header-renderer");
        if (!commentRenderer) return true;
        let r = '0';
        let txt = commentRenderer.textContent
        if (typeof txt == 'string') {
            let m = txt.match(/[\d\,\s]+/)
            if (m) r = m[0].trim()
        }      
        remove_DisablePauseVideo();
        $span[0].innerHTML = `${r}`;
        makeBodyScroll(); // force display content
        $('#tab-comments[lazy-loading]').removeAttr('lazy-loading')
        return false
    }
    if (Q.mtf_checkCommentsLoaded && Q.mtf_checkCommentsLoaded() === false) Q.mtf_checkCommentsLoaded = null;
}

const mtoVs={}

function checkTabStatus() {


    if(mtoVs.mtoVisibility_Playlist) {
        mtoVs.mtoVisibility_Playlist.takeRecords();
        mtoVs.mtoVisibility_Playlist.disconnect();
        mtoVs.mtoVisibility_Playlist=null;
    }


    let mtf_attrPlaylist=(mutations, observer)=>{


        var playlist=document.querySelector('ytd-playlist-panel-renderer#playlist')
        const $tabBtn = $('[userscript-tab-content="#tab-list"]');

        //console.log('attr playlist changed')

        if( $tabBtn.is('.hide') && !playlist.hasAttribute('hidden') ){

            //console.log('attr playlist changed - no hide')
            $tabBtn.removeClass("hide");

        }else if( !$tabBtn.is('.hide') && playlist.hasAttribute('hidden') ){


            //console.log('attr playlist changed - add hide')

            var isActiveBefore = $tabBtn.is('.active')

            $tabBtn.addClass("hide");
            if (isActiveBefore) {
                setDefaultActiveTab();
            }


        }

        
    }

    Q.mtf_checkTabStatus_playlist=()=>{


        var playlist=document.querySelector('ytd-playlist-panel-renderer#playlist')

        if(!playlist) return true;


        mtoVs.mtoVisibility_Playlist=new MutationObserver(mtf_attrPlaylist)
        mtoVs.mtoVisibility_Playlist.observe(playlist, {          
            attributes: true,
            attributeFilter: ['hidden'],
            attributeOldValue: true
        })
        mtf_attrPlaylist()


        return false;


    }

    if(Q.mtf_checkTabStatus_playlist&&Q.mtf_checkTabStatus_playlist()===false)Q.mtf_checkTabStatus_playlist=null;










    if(mtoVs.mtoVisibility_Comments) {
        mtoVs.mtoVisibility_Comments.takeRecords();
        mtoVs.mtoVisibility_Comments.disconnect();
        mtoVs.mtoVisibility_Comments=null;
    }


    let mtf_attrComments=(mutations, observer)=>{


        var comments=document.querySelector('ytd-comments#comments')
        const $tabBtn = $('[userscript-tab-content="#tab-comments"]');

        if(!comments || !$tabBtn[0])return;

        //console.log('attr comments changed')

        if( $tabBtn.is('.hide') && !comments.hasAttribute('hidden') ){

            //console.log('attr comments changed - no hide')
            $tabBtn.removeClass("hide");

        }else if( !$tabBtn.is('.hide') && comments.hasAttribute('hidden') ){


            //console.log('attr comments changed - add hide')

            $('span#tab3-txt-loader').text('');

            var isActiveBefore = $tabBtn.is('.active')

            $tabBtn.addClass("hide");
            if (isActiveBefore) {
                setDefaultActiveTab();
            }

            $('span#tab3-txt-loader').text('');


        }

        
    }

    Q.mtf_checkTabStatus_comments=()=>{


        var comments=document.querySelector('ytd-comments#comments')

        if(!comments) return true;


        mtoVs.mtoVisibility_Comments=new MutationObserver(mtf_attrComments)
        mtoVs.mtoVisibility_Comments.observe(comments, {          
            attributes: true,
            attributeFilter: ['hidden'],
            attributeOldValue: true
        })
        mtf_attrComments()


        return false;


    }

    if(Q.mtf_checkTabStatus_comments&&Q.mtf_checkTabStatus_comments()===false)Q.mtf_checkTabStatus_comments=null;



}


function checkChatStatus(){


    
    if(mtoVs.mtoVisibility_Chatroom) {
        mtoVs.mtoVisibility_Chatroom.takeRecords();
        mtoVs.mtoVisibility_Chatroom.disconnect();
        mtoVs.mtoVisibility_Chatroom=null;
    }


    let cid_chatFrameCheck=0;

    let mtf_attrChatroom=(mutations, observer)=>{

        const chatBlock = document.querySelector('ytd-live-chat-frame#chat')
        const cssElm = document.querySelector('ytd-watch-flexy')

        
        if(!cssElm.hasAttribute('userscript-chatblock')) cssElm.setAttribute('userscript-chatblock', '');
        if (chatBlock.hasAttribute('collapsed')) {
            cssElm.setAttribute('userscript-chat-collapsed', '');
        } else {
            cssElm.removeAttribute('userscript-chat-collapsed');
        }


        if(!cid_chatFrameCheck){
            let dd=+new Date;
            cid_chatFrameCheck=setInterval(()=>{
                if(+new Date - dd>2750) {
                    return (cid_chatFrameCheck=clearInterval(cid_chatFrameCheck));
                }
                var chatFrameChecking=!!chatFrameElement('yt-live-chat-renderer #continuations')
                if(chatFrameChecking) {
                    mtf_ChatExist();
                    return (cid_chatFrameCheck=clearInterval(cid_chatFrameCheck));
                }
            },30)
        }

    }

    Q.mtf_checkStatus_chatroom=()=>{


        var chatroom=document.querySelector('ytd-live-chat-frame#chat')

        if(!chatroom) return true;


        mtoVs.mtoVisibility_Chatroom=new MutationObserver(mtf_attrChatroom)
        mtoVs.mtoVisibility_Chatroom.observe(chatroom, {          
            attributes: true,
            attributeFilter: ['collapsed'],
            attributeOldValue: true
        })
        mtf_attrChatroom()


        return false;


    }

    if(Q.mtf_checkStatus_chatroom&&Q.mtf_checkStatus_chatroom()===false)Q.mtf_checkStatus_chatroom=null;





    if(mtoVs.mtoFlexyAttr) {
        mtoVs.mtoFlexyAttr.takeRecords();
        mtoVs.mtoFlexyAttr.disconnect();
        mtoVs.mtoFlexyAttr=null;
    }


    let checkQ = null;
    let mtf_attrFlexy=(mutations, observer)=>{
        
        
        const cssElm = document.querySelector('ytd-watch-flexy')
        let checkR =  !cssElm.hasAttribute('userscript-chat-collapsed') && cssElm.hasAttribute('userscript-chatblock')
        
        if(checkQ!==checkR){

            checkQ=checkR;
            window.requestAnimationFrame(()=>{

                if (checkQ) {
                    switchTabActivity(null)
                } else {
                    setDefaultActiveTab();
                }      


            })

        }


    }


    Q.mtf_checkFlexy=()=>{


        var flexy=document.querySelector('ytd-watch-flexy')

        if(!flexy) return true;


        mtoVs.mtoFlexyAttr=new MutationObserver(mtf_attrFlexy)
        mtoVs.mtoFlexyAttr.observe(flexy, {          
            attributes: true,
            attributeFilter: ['userscript-chat-collapsed','userscript-chatblock'],
            attributeOldValue: true
        })
        mtf_attrFlexy()


        return false;


    }

    if(Q.mtf_checkFlexy&&Q.mtf_checkFlexy()===false)Q.mtf_checkFlexy=null;



}



function checkPlayList() {

    Q.mtf_checkPlayList = () => {

        const items= document.querySelector('ytd-playlist-panel-renderer>#container>#items');
        if(!items) return true;

        $(items).scroll(makeBodyScroll);

        return false;

    }

    if (Q.mtf_checkPlayList && Q.mtf_checkPlayList() === false) Q.mtf_checkPlayList = null;



}

let switchTabActivity_lastTab = null

function switchTabActivity(activeLink) {


    if (activeLink && activeLink.hasAttribute('hide')) return;
    //console.log(1219,'hello', activeLink?activeLink.getAttribute('userscript-tab-content'):null)

    const links = document.querySelectorAll('#material-tabs a[userscript-tab-content]');

    for (const link of links) {
        let content = document.querySelector(link.getAttribute('userscript-tab-content'));
        if (link && content) {
            if (link !== activeLink) {
                $(link).removeClass("active");
                $(content).addClass("hideOnRight");
            } else {
                $(link).addClass("active");
                $(content).removeClass("hideOnRight");
                window.requestAnimationFrame(() => content.focus())
            }
        }
    }


}

let tabsUiScript_setclick = false;

function tabsUiScript() {

    const materialTab = document.querySelector("#material-tabs")
    if (!materialTab) return;


    let noActiveTab = !!document.querySelector('ytd-watch-flexy[userscript-chatblock]:not([userscript-chat-collapsed])')


    const activeLink = materialTab.querySelector('a[userscript-tab-content].active:not(.hide)')
    if (activeLink) switchTabActivity(noActiveTab ? null : activeLink)

    if (!tabsUiScript_setclick) {
        tabsUiScript_setclick = true;
        $(materialTab).on("click", "a", function(evt) {


            if (!this.hasAttribute('userscript-tab-content')) return;

            switchTabActivity_lastTab = this.getAttribute('userscript-tab-content');

            window.requestAnimationFrame(() => {



                Promise.resolve().then(() => {


                    let button = document.querySelector('ytd-live-chat-frame#chat:not([collapsed])>.ytd-live-chat-frame#show-hide-button')
                    return button

                }).then(button => {

                    mtoIgnoreTo = +new Date + 300;

                    if (button) {
                        button.querySelector('ytd-toggle-button-renderer').click();
                    }


                }).then(() => {

                    setTimeout(() => {
                        switchTabActivity(this)

                        setTimeout(() => {

                            makeBodyScroll();

                        },20);


                    }, 100);

                    

                    mtoIgnoreTo = 0;


                })


            })

            evt.preventDefault();
        });

    }



}


// ---------------------------------------------------------------------------------------------

window.addEventListener("yt-navigate-finish", AddTabPanel)










    // https://github.com/cyfung1031/Tabview-Youtube/raw/main/js/content.js

}


;!(function $$() {
    'use strict';

    if(document.documentElement==null) return window.requestAnimationFrame($$)

var cssTxt = GM_getResourceText("contentCSS");

function addStyle (styleText) {
  const styleNode = document.createElement('style');
  styleNode.type = 'text/css';
  styleNode.textContent = styleText;
  document.documentElement.appendChild(styleNode);
  return styleNode;
}


addStyle (cssTxt);

    main(window.$);


    // Your code here...
})();