ニコニコ動画 コメントウィンドウ表示

コメント一覧をポップアップウィンドウで表示します。

// ==UserScript==
// @name         ニコニコ動画 コメントウィンドウ表示
// @namespace    https://yyya-nico.co/
// @version      1.0.9
// @description  コメント一覧をポップアップウィンドウで表示します。
// @author       yyya_nico
// @license      MIT License
// @match        https://www.nicovideo.jp/watch/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=nicovideo.jp
// @grant        none
// ==/UserScript==

(() => {
    'use strict';

    let nicoApiDataElem = document.querySelector('[name="server-response"]');
    const origin = 'https://yyya-nico.co';
    let nicoApiData = JSON.parse(nicoApiDataElem.content).data.response;
    let popup = null;

    const observerWrap = (findTargetSelector, sendTargetSelector, callback) => {
        return new MutationObserver(records => {
            records.forEach(record => {
                record[sendTargetSelector ? 'addedNodes' : 'removedNodes'].forEach(node => {
                    if (node.nodeType == 1/*ELEMENT*/ && node.matches(findTargetSelector)) {
                        callback(
                            sendTargetSelector ? node.querySelector(sendTargetSelector)
                                               : record.target
                        );
                    }
                });
            });
        });
    }

    const createTask = target => {
        target.insertAdjacentHTML('beforeend', '<button dir="ltr" id="comments-list" class="cursor_pointer bdr_full fs_base hover:bg-c_action.baseHover hover:cursor_pointer disabled:fill_action.textOnBase_disabled disabled:pointer-events_none h_x4 fs_s fw_bold px_base white-space_nowrap" tabindex="0" type="button">ウィンドウで表示</button>');
        const openBtn = document.getElementById('comments-list');
        openBtn.addEventListener('click', () => {
            const w = 480;
            const h = screen.height * .8;
            const lef = (screen.width - w) * .9;
            const top = (screen.height - h) * .25;
            popup = window.open(`${origin}/nv-comment-viewer`, 'comment-list', 'width='+ w +',height='+ h +',left='+ lef +',top='+ top);
        });
    }

    const waitCreatePlayerPanelContainerObserver = observerWrap('.grid-area_\\[sidebar\\] > div.d_flex.flex-d_column.gap_x2', '.d_flex.gap_x1_5.p_base.bg-c_layer\\.surfaceHighEm.bd-b_m.bd-c_border\\.highEm', target => {
        if (target) {
            waitCreatePlayerPanelContainerObserver.disconnect();
            createTask(target);
        }
    });

    let lastProgress = null;
    const timeObserver = new MutationObserver(records => {
        records.forEach(record => {
            if (!popup.closed) {
                const progressPercentage = Number(record.target.style.transform.slice(7, -1)); // scaleX(****)
                if (progressPercentage !== lastProgress) {
                    popup.postMessage({
                        eventName: 'playerMetadataChange',
                        data: {
                            progressPercentage: progressPercentage
                        }
                    }, origin);
                    lastProgress = progressPercentage;
                }
            } else {
                timeObserver.disconnect();
            }
        });
    });

    window.addEventListener('message', e => {
        if (e.origin === origin) {
            switch (e.data.eventName) {
                case 'ready':
                    // console.log('ready');
                    if (nicoApiData) {
                        popup.postMessage({
                            eventName: 'sendData',
                            data: nicoApiData
                        }, origin);
                    } else {
                        const cutIndex = location.pathname.lastIndexOf('/') + 1;
                        const videoId = location.pathname.slice(cutIndex);
                        popup.postMessage({
                            eventName: 'sendVideoId',
                            data: {
                                videoId
                            }
                        }, origin);
                    }
                case 'returned':
                    // console.log('returned');
                    const played = document.querySelector('[aria-label="video - currentTime"]');
                    timeObserver.observe(played, {attributes: true});
                    break;

                case 'bye':
                    // console.log('bye');
                    timeObserver.disconnect();
                    break;

                case 'keyDown':
                    // console.log('keyDown');
                    ['ArrowUp', 'ArrowRight', 'ArrowDown', 'ArrowLeft', ' '];
                    switch (e.data.data) {
                        case 'ArrowUp':

                            break;
                        case 'ArrowRight':
                            document.querySelector('[aria-label="10 秒送る"]')?.click();
                            break;
                        case 'ArrowDown':

                            break;
                        case 'ArrowLeft':
                            document.querySelector('[aria-label="10 秒戻る"]')?.click();
                            break;
                        case ' ':
                            document.querySelector('[aria-label="再生する"], [aria-label="一時停止する"]')?.click();
                            break;
                    }
                    break;
            }
        }
    });

    const clearNicoApiData = () => {
        nicoApiData = null;
    };

    (history => {
        const pushState = history.pushState;
        history.pushState = (...args) => {
            clearNicoApiData();
            return pushState.apply(history, args);
        };
    })(window.history);

    window.addEventListener('popstate', clearNicoApiData);

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

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址