Media Stop Visual Alert Window

미디어가 15초 이상 정지되면 별도 창으로 시각 알림 + 정지 시간 표시

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, Greasemonkey alebo Violentmonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, % alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey alebo Userscripts.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie správcu používateľských skriptov.

(Už mám správcu používateľských skriptov, nechajte ma ho nainštalovať!)

Advertisement:

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

(Už mám správcu používateľských štýlov, nechajte ma ho nainštalovať!)

Advertisement:

// ==UserScript==
// @name         Media Stop Visual Alert Window
// @namespace    media-stop-alert-window
// @version      2.4
// @description  미디어가 15초 이상 정지되면 별도 창으로 시각 알림 + 정지 시간 표시
// @match        *://*/*
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    const STOP_DELAY = 15000;

    let stopTimer = null;
    let wasPlaying = false;
    let alertWindow = null;
    let alertActive = false;
    let stoppedAt = null;

    function formatTime(date) {
        return date.toLocaleTimeString('ko-KR', {
            hour: '2-digit',
            minute: '2-digit',
            second: '2-digit'
        });
    }

    function openAlertWindow() {
        if (alertWindow && !alertWindow.closed) return;

        alertWindow = window.open(
            '',
            'MediaStopAlertWindow',
            'width=460,height=300,left=100,top=100'
        );

        if (!alertWindow) {
            console.warn('팝업이 차단되었습니다.');
            return;
        }

        alertWindow.document.write(`
            <html>
            <head>
                <title>미디어 정지 알림</title>
                <style>
                    body {
                        margin: 0;
                        background: #300;
                        color: white;
                        font-family: sans-serif;
                        display: flex;
                        align-items: center;
                        justify-content: center;
                        height: 100vh;
                        text-align: center;
                    }
                    #box {
                        padding: 20px;
                    }
                    .alert {
                        font-size: 34px;
                        font-weight: bold;
                        color: #ff5555;
                        animation: blink 0.8s infinite;
                    }
                    .time {
                        font-size: 20px;
                        margin-top: 14px;
                        color: #ffdada;
                    }
                    .title {
                        font-size: 15px;
                        margin-top: 12px;
                        opacity: 0.85;
                        word-break: break-all;
                    }
                    @keyframes blink {
                        0%, 100% { opacity: 1; }
                        50% { opacity: 0.25; }
                    }
                </style>
            </head>
            <body>
                <div id="box"></div>
            </body>
            </html>
        `);
    }

    function setAlertWindowStopped() {
        openAlertWindow();

        if (!alertWindow || alertWindow.closed) return;

        alertActive = true;

        const stoppedTimeText = stoppedAt ? formatTime(stoppedAt) : '알 수 없음';

        alertWindow.document.title = '⏸ 미디어 정지됨!';
        alertWindow.document.getElementById('box').innerHTML = `
            <div class="alert">미디어 정지됨!</div>
            <p>15초 이상 재생이 재개되지 않았습니다.</p>
            <div class="time">정지된 시간: ${stoppedTimeText}</div>
            <div class="title">정지된 탭: ${document.title}</div>
        `;

        alertWindow.focus();
    }

    function setAlertWindowNormal() {
        alertActive = false;
        stoppedAt = null;

        if (!alertWindow || alertWindow.closed) return;

        alertWindow.close();
        alertWindow = null;
    }

    function getMediaElements() {
        return [...document.querySelectorAll('video, audio')];
    }

    function isAnyMediaPlaying() {
        return getMediaElements().some(media =>
            !media.paused &&
            !media.ended &&
            media.currentTime > 0 &&
            media.readyState > 2
        );
    }

    function startStopTimer() {
        clearTimeout(stopTimer);

        if (!stoppedAt) {
            stoppedAt = new Date();
        }

        stopTimer = setTimeout(() => {
            stopTimer = null;

            if (!isAnyMediaPlaying()) {
                setAlertWindowStopped();
            }
        }, STOP_DELAY);
    }

    function checkMediaState() {
        const playing = isAnyMediaPlaying();

        if (playing) {
            wasPlaying = true;
            clearTimeout(stopTimer);
            stopTimer = null;

            if (alertActive || stoppedAt) {
                setAlertWindowNormal();
            }

            return;
        }

        if (wasPlaying && !playing && !stopTimer && !alertActive) {
            startStopTimer();
        }
    }

    document.addEventListener('play', () => {
        wasPlaying = true;
        clearTimeout(stopTimer);
        stopTimer = null;
        setAlertWindowNormal();
    }, true);

    document.addEventListener('pause', () => {
        if (wasPlaying && !alertActive) {
            startStopTimer();
        }
    }, true);

    document.addEventListener('ended', () => {
        if (wasPlaying && !alertActive) {
            startStopTimer();
        }
    }, true);

    setInterval(checkMediaState, 1000);

})();