bilibili优化

增加bilibili播放器的快捷按键,优化个别视图。

当前为 2024-08-07 提交的版本,查看 最新版本

// ==UserScript==
// @name         bilibili优化
// @namespace    binger.cc
// @version      1.3
// @description  增加bilibili播放器的快捷按键,优化个别视图。
// @author       Ervoconite
// @match        https://*.bilibili.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=bilibili.com
// @resource     toastifyCSS https://cdn.jsdelivr.net/npm/toastify-js/src/toastify.min.css
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_addStyle
// @grant        GM_getResourceText
// ==/UserScript==


//==========================================: 设定
const autoWide = true; // 自动宽屏


const DEBUG = false; // debug 标志


//==========================================: 预设数据
const d = document;
const _Log = console.log;
const querySelector = (sel) => { return d.querySelector(sel) }
const getActElm = () => { return document.activeElement.nodeName }

GM_addStyle(`
.toastDots {
    color: black;
    font-family: KaiTi,STKaiti;
    padding: 12px 15px !important;
    box-shadow: -2px 4px 6px 1px #00000073, 0 10px 36px -4px #4d60e84d !important;
    background: linear-gradient(120deg, #E0C3FC 0%, #8EC5FC 100%);
    background: -webkit-linear-gradient(120deg, #E0C3FC 0%, #8EC5FC 100%);
    background: -moz-linear-gradient(120deg, #E0C3FC 0%, #8EC5FC 100%);
    background: -o-linear-gradient(120deg, #E0C3FC 0%, #8EC5FC 100%);
    background: -ms-linear-gradient(120deg, #E0C3FC 0%, #8EC5FC 100%);
}
.toast-close {
    color: black !important;
}
`); // Toast class

function runToast(msg) {
    Toastify({
        text: msg,
        duration: 1500,
        className: "toastDots",
        close: true, gravity: "top", position: "right",
        stopOnFocus: true, oldestFirst: false,
        offset: { x: 10, y: 60 },
        onClick: function () { console.log(this) }
    }).showToast();
}

function tipToast(msg) {
    Toastify({
        text: msg,
        duration: 5000,
        className: "toastDots",
        close: true, gravity: "top", position: "right",
        stopOnFocus: true, oldestFirst: false,
        offset: { x: 10, y: 60 },
        onClick: function () { console.log(this) }
    }).showToast();
}
function pinToast(msg) {
    Toastify({
        text: msg,
        duration: -1,
        className: "toastDots",
        close: true, gravity: "top", position: "right",
        stopOnFocus: true, oldestFirst: false,
        offset: { x: 10, y: 60 },
        onClick: function () { console.log(this) }
    }).showToast();
}



//==========================================: Script主体


/**
 *
 *  @description 个人空间——⭐收藏:视图调整
 *
 */
function do_view_adjusting() {
    GM_addStyle(`
#page-fav .fav-main{width:800px!important}
#page-fav .fav-main .small-item{width:170px!important}
#page-fav .fav-main .small-item:nth-child(5n){margin-right:inherit!important}
#page-fav .fav-main .fav-action-bottom .fav-action-fixtop{width:800px!important;}

#page-fav .fav-sidenav{width:300px!important}
#page-fav .fav-sidenav .text{line-height:33px!important;width:180px!important}
#page-fav .fav-sidenav .fav-list-container{max-height:none!important}

@media (min-width:1420px){
  #page-fav .fav-main{width:980px}
}

/* #page-fav .fav-list>li:nth-child(odd){background:whitesmoke!important;} */
#page-fav .fav-sidenav > div:nth-child(2){background:aliceblue!important;}
#page-fav .modal-wrapper .target-favlist{max-height:80vh!important;}
#page-fav .modal-wrapper .target-favitem{height:unset!important;margin:.5em!important;}
#page-fav .modal-wrapper .fav-meta{display:flex!important;}
#page-fav .modal-wrapper .fav-meta .fav-state{margin-left:20px!important;}

`)
    setTimeout(() => {
        querySelector("#page-fav div.fav-sidenav > " +
            "div:nth-child(2) > div.favlist-title").click();
    }, 1000);
}

/**
 *
 * @description 视频播放器:加快捷键
 *
 */
function do_keybindings() {
    // 阻止空格滚屏:
    d.body.addEventListener('keydown', (e) => {
        if (e.key === ' ') {
            e.preventDefault();
        }
    });

    // 设定选择器:
    const selControl = '#bilibili-player .bpx-player-video-area .bpx-player-control-wrap',
        selRate = `${selControl} .bpx-player-ctrl-playbackrate > ul`,
        selWebv = `${selControl} .bpx-player-ctrl-web`,
        selWide = `${selControl} .bpx-player-ctrl-wide`;
    const selToti = `#bilibili-player > div > div > div.bpx-player-tooltip-area`;

    // obs: 给 宽屏 和 页面全屏 按钮 加提示
    const obs = new MutationObserver((mlist) => {
        if (mlist[3] && mlist[3].type == 'childList' && mlist[3].addedNodes.length) {
            var html;
            const wideTip = mlist[2].addedNodes[0].lastChild;
            const webvTip = mlist[3].addedNodes[0].lastChild;
            (html = wideTip.innerHTML, html == '宽屏模式' || html == '退出宽屏') ?
                wideTip.innerHTML += ' (h)' : _Log('h ERROR');
            (html = webvTip.innerHTML, html == '网页全屏' || html == '退出网页全屏') ?
                webvTip.innerHTML += ' (g)' : _Log('g ERROR');
        }
    })

    // 修改播放器的函数
    function modifyPlayer(obs) {
        if (DEBUG) {
            // 开发行为
            const cls_playBtn = '.bpx-player-ctrl-play', // 播放暂停按钮
                cls_videoEl = ".bpx-player-container", // 这是播放器容器
                cls_pauseSign = "bpx-state-paused" // 这是暂停标志
            if (!querySelector(cls_videoEl).classList
                .contains(cls_pauseSign)) {
                // 没有暂停就让他暂停
                querySelector(cls_playBtn).click()
                _Log("Debug: pause")
            }
        }
        obs.disconnect();
        const btnWebv = querySelector(selWebv),
            btnWide = querySelector(selWide),
            btnRate = querySelector(selRate),
            btnRates = Array.from(btnRate.children);
        const rateK2R = new Map([
            ['1', '1'],
            ['2', '1.25'],
            ['3', '1.5'],
            ['4', '2'],
            ['5', '0.5'],
            ['6', '0.75']
        ]), rateR2K = new Map();
        rateK2R.forEach((r, k) => { rateR2K.set(r, k) });
        const rate = (k) => {
            let btn = btnRates.find(e => {
                return e.dataset.value == rateK2R.get(k)
            })
            if (btn) { btn.click(); runToast(btn.dataset.value + ' 倍速~') }
        }
        window.addEventListener('keyup', (e) => {
            if (['TEXTAREA', 'INPUT'].indexOf(getActElm()) > -1) return; // 输入时不反应。
            var k = e.key;
            if (isNaN(k) || !k.trim().length) switch (k) {
                case 'g': btnWebv.click(); runToast('切换网页全屏模式~'); break;
                case 'h': btnWide.click(); runToast((isWide ? "" : "退出") + '宽屏模式~'); break;
                default:
            } else {
                rate(k)
            }
        });
        // 给倍速备注按键
        btnRate.style.cssText = 'text-align:end;width:100px;padding-right:8px;';// font-family:cursive;
        btnRates.map(e => { e.innerHTML += `(按${rateR2K.get(e.dataset.value)})` })
        if (autoWide) btnWide.click();
    }


    new MutationObserver((mlist, muobs) => {
        if (mlist[0].type == 'childList' && querySelector(selWide)) {
            _Log('%c终于加载好了~', "color:lime");

            // 修改播放器
            modifyPlayer(muobs);
            tipToast("按键设定完毕~");

            // 启动提示监视器
            obs.observe(querySelector(selToti), { childList: true });
        }
    }).observe(d.body, { childList: true });
}


//==========================================: Script执行
(function () {
    'use strict';


    // let exterbalScris = []
    // exterbalScris.forEach(url => {
    //     let escr = d.createElement('script')
    //     escr.type = 'text/javascript'; escr.src = url;
    //     d.body.appendChild(escr)
    // })

    let styleSheets = ['toastifyCSS']
    styleSheets.forEach(url => {
        GM_addStyle(GM_getResourceText(url))
    })

    if (location.href.match(/space.bilibili.com/) &&
        location.pathname.endsWith("favlist")) {
        do_view_adjusting();
    }

    else if (location.href.match(/bilibili.com\/video/)) {
        do_keybindings();
    }
})();