YouTube Split

Устанавливает сплит по времени, панель управления под видео, показывает статистику "Выкуплено/Всего", оверлей "СПЛИТ НЕ ОПЛАЧЕН" с настраиваемым таймером и кнопками на оверлее, гифкой и звуком.

当前为 2025-04-18 提交的版本,查看 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         YouTube Split
// @namespace    http://tampermonkey.net/
// @version      2.6
// @author       Gemini
// @match        *://www.youtube.com/watch*
// @grant        none
// @description Устанавливает сплит по времени, панель управления под видео, показывает статистику "Выкуплено/Всего", оверлей "СПЛИТ НЕ ОПЛАЧЕН" с настраиваемым таймером и кнопками на оверлее, гифкой и звуком.
// ==/UserScript==

(function() {
    'use strict';

    // --- Конфигурация ---
    let splitMinutes = null;
    let totalVideoMinutes = null;
    const extendCost = 300;
    const splitSoundUrl = 'https://github.com/lardan099/donat/raw/refs/heads/main/alert_orig.mp3'; // ВСТАВЬТЕ СЮДА ПРЯМУЮ ССЫЛКУ НА ВАШ ЗВУК!
    const overlayGifUrl = 'https://i.imgur.com/SS5Nfff.gif'; // URL гифки для оверлея
    const localStorageVolumeKey = 'ytSplitAlertVolume';
    const localStorageTimerKey = 'ytSplitOverlayTimer'; // Ключ для сохранения таймера в localStorage
    const defaultOverlayTimerDuration = 360; // Длительность таймера по умолчанию в секундах (6 минут)


    // --- Глобальные переменные состояния ---
    let overlayTimerDuration = parseInt(localStorage.getItem(localStorageTimerKey), 10);
     if (isNaN(overlayTimerDuration) || overlayTimerDuration < 0) {
         overlayTimerDuration = defaultOverlayTimerDuration;
     }

    let video = null;
    let overlay = null;
    let splitTriggered = false;
    let audioPlayer = null;
    let splitCheckIntervalId = null;
    let setupIntervalId = null;
    let panelAdded = false;

    let overlayTimerIntervalId = null;
    let overlayCountdownRemaining = overlayTimerDuration;


    const styles = `
        #split-control-panel {
            margin-top: 10px;
            margin-bottom: 15px;
            padding: 10px 15px;
            background: var(--yt-spec-badge-chip-background);
            border: 1px solid var(--yt-spec-border-div);
            border-radius: 8px;
            display: flex;
            flex-wrap: wrap;
            align-items: center;
            gap: 10px 20px;
            color: var(--yt-spec-text-primary);
            font-family: "Roboto", Arial, sans-serif;
            font-size: 14px;
            max-width: var(--ytd-watch-flexy-width);
            width: 100%;
            box-sizing: border-box;
        }

        ytd-watch-flexy:not([use- Sarkis]) #primary #split-control-panel {
            margin-left: auto;
            margin-right: auto;
        }

        #split-control-panel label {
            font-weight: 500;
            color: var(--yt-spec-text-secondary);
            flex-shrink: 0;
            line-height: 1.3;
        }

        #split-control-panel label i {
             font-style: normal;
             font-size: 12px;
             color: var(--yt-spec-text-disabled);
        }

         /* Контейнер для поля ввода сплита и кнопок модификации на панели */
        #split-input-group {
            display: flex;
            align-items: center;
            gap: 5px;
        }

        #split-control-panel input[type="number"] {
            width: 60px;
            padding: 8px 10px;
            background: var(--yt-spec-filled-button-background);
            color: var(--yt-spec-text-primary);
            border: 1px solid var(--yt-spec-action-simulate-border);
            border-radius: 4px;
            text-align: center;
            font-size: 15px;
            -moz-appearance: textfield;
        }

        #split-control-panel input[type="number"]::-webkit-outer-spin-button,
        #split-control-panel input[type="number"]::-webkit-inner-spin-button {
            -webkit-appearance: none;
            margin: 0;
        }

        /* Стили для всех кнопок внутри панели */
        #split-control-panel button {
            padding: 8px 15px;
            font-size: 15px;
            cursor: pointer;
            background: var(--yt-spec-grey-1);
            color: var(--yt-spec-text-primary);
            border: none;
            border-radius: 4px;
            transition: background 0.2s ease-in-out;
            font-weight: 500;
            flex-shrink: 0;
        }

        #split-control-panel button:hover {
             background: var(--yt-spec-grey-2);
        }

         /* Стили для кнопок модификации сплита (+1, +5 и т.д.) */
        #split-input-group button {
            padding: 8px 10px;
            font-size: 14px;
            background: var(--yt-spec-filled-button-background);
            border: 1px solid var(--yt-spec-action-simulate-border);
        }
         #split-input-group button:hover {
            background: var(--yt-spec-grey-2);
         }

        #split-control-panel button#set-split-button {
             background: var(--yt-spec-brand-suggested-action);
             color: var(--yt-spec-text-reverse);
             order: -1;
             margin-right: auto;
        }
         #split-control-panel button#set-split-button:hover {
             background: var(--yt-spec-brand-suggested-action-hover);
        }

        #split-volume-control {
             display: flex;
             align-items: center;
             gap: 5px;
        }
         #split-volume-control label {
             font-weight: 500;
             color: var(--yt-spec-text-secondary);
             flex-shrink: 0;
             line-height: normal;
         }
         #split-volume-control input[type="range"] {
             flex-grow: 1;
             min-width: 80px;
             -webkit-appearance: none;
             appearance: none;
             height: 8px;
             background: var(--yt-spec-grey-1);
             outline: none;
             opacity: 0.7;
             transition: opacity .2s;
             border-radius: 4px;
         }
         #split-volume-control input[type="range"]:hover {
             opacity: 1;
         }

        #split-volume-control input[type="range"]::-webkit-slider-thumb {
             -webkit-appearance: none;
             appearance: none;
             width: 15px;
             height: 15px;
             background: var(--yt-spec-brand-button-background);
             cursor: pointer;
             border-radius: 50%;
        }

        #split-volume-control input[type="range"]::-moz-range-thumb {
             width: 15px;
             height: 15px;
             background: var(--yt-spec-brand-button-background);
             cursor: pointer;
             border-radius: 50%;
        }

        #split-stats {
            font-size: 15px;
            color: var(--yt-spec-text-primary);
            font-weight: 500;
            margin-left: 10px;
        }


        #split-overlay {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.95);
            color: white;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            z-index: 99999;
            font-family: "Roboto", Arial, sans-serif;
            text-align: center;
            padding: 20px;
            box-sizing: border-box;
        }

        #split-overlay #split-warning-message {
            font-size: clamp(24px, 4vw, 36px);
            margin-bottom: 15px;
            color: yellow;
            font-weight: bold;
            text-shadow: 0 0 8px rgba(255, 255, 0, 0.5);
        }

        #split-overlay #split-main-message {
            font-size: clamp(40px, 8vw, 72px);
            font-weight: bold;
            margin-bottom: 20px;
            color: red;
            text-shadow: 0 0 15px rgba(255, 0, 0, 0.7);
        }

        /* Стили для таймера и сообщения "ОСТАЛОСЬ" на оверлее */
        #split-overlay #overlay-timer,
        #split-overlay #overlay-remaining-minutes {
            font-size: clamp(28px, 5vw, 48px);
            font-weight: bold;
            margin-bottom: 20px;
        }
         #split-overlay #overlay-timer {
             color: orange;
         }
         #split-overlay #overlay-remaining-minutes {
             color: cyan;
         }

        /* Контейнер для управления таймером на оверлее */
        #split-overlay #overlay-timer-control {
            margin-bottom: 20px;
            display: flex;
            align-items: center;
            gap: 10px;
            flex-wrap: wrap;
            justify-content: center;
            color: white; /* Используем белый цвет для контраста */
            font-size: 18px;
        }
         #split-overlay #overlay-timer-control label {
             font-weight: 500;
         }

         /* Стили для поля ввода таймера на оверлее */
         #split-overlay #overlay-timer-control input[type="number"] {
            width: 70px;
            padding: 8px 10px;
            background: rgba(255, 255, 255, 0.1);
            color: white;
            border: 1px solid rgba(255, 255, 255, 0.3);
            border-radius: 4px;
            text-align: center;
            font-size: 18px;
            -moz-appearance: textfield;
         }
         #split-overlay #overlay-timer-control input[type="number"]::-webkit-outer-spin-button,
         #split-overlay #overlay-timer-control input[type="number"]::-webkit-inner-spin-button {
             -webkit-appearance: none;
             margin: 0;
         }

         /* Стили для кнопок модификации таймера на оверлее */
         #split-overlay #overlay-timer-control button {
            padding: 8px 12px;
            font-size: 16px;
            cursor: pointer;
            background: rgba(255, 255, 255, 0.1);
            color: white;
            border: 1px solid rgba(255, 255, 255, 0.3);
            border-radius: 4px;
            transition: background 0.2s ease-in-out;
            font-weight: 500;
         }
          #split-overlay #overlay-timer-control button:hover {
             background: rgba(255, 255, 255, 0.2);
          }



        #split-extend-buttons {
            display: flex;
            gap: 15px;
            flex-wrap: wrap;
            justify-content: center;
            margin-bottom: 40px;
        }

        #split-extend-buttons button {
            padding: 12px 25px;
            font-size: clamp(18px, 3vw, 24px);
            cursor: pointer;
            background: var(--yt-spec-red-500);
            border: none;
            color: white;
            border-radius: 4px;
            font-weight: bold;
            transition: background 0.2s ease-in-out;
        }

        #split-extend-buttons button:hover {
            background: var(--yt-spec-red-600);
        }

        #split-overlay img {
            max-width: 115%;
            max-height: 50vh;
            height: auto;
            border-radius: 8px;
            margin-top: 20px;
        }
    `;

    function injectStyles() {
        if (document.getElementById('yt-split-styles')) {
            return;
        }
        const styleElement = document.createElement("style");
        styleElement.id = 'yt-split-styles';
        styleElement.textContent = styles;
        document.head.appendChild(styleElement);
    }

    function updateSplitDisplay() {
        const inputField = document.getElementById("split-input");
        if (inputField) {
            inputField.valueAsNumber = splitMinutes === null ? 0 : splitMinutes;
        }
        updateSplitStatsDisplay();
    }

    function updateSplitStatsDisplay() {
        const statsElement = document.getElementById("split-stats");
        if (statsElement) {
             const boughtMinutes = splitMinutes === null ? 0 : splitMinutes;
             const totalMinutesText = totalVideoMinutes !== null ? `${totalVideoMinutes}` : '?';
             statsElement.textContent = `Выкуплено: ${boughtMinutes} / Всего: ${totalVideoMinutes !== null ? totalVideoMinutes : '?'} минут`;
        }
         if (overlay) {
             updateOverlayRemainingMinutes();
         }
    }

    // Функция для изменения значения в поле ввода сплита (минуты) на ПАНЕЛИ
     function modifySplitInput(minutesToModify) {
         const inputField = document.getElementById("split-input");
         if (!inputField) return;
         let currentVal = inputField.valueAsNumber;
         if (isNaN(currentVal)) currentVal = 0;
         let newVal = currentVal + minutesToModify;
         if (newVal < 0) newVal = 0;
         inputField.valueAsNumber = newVal;
     }

     // Функция для изменения значения в поле ввода таймера (секунды) НА ОВЕРЛЕЕ
    // Функция для изменения значения в поле ввода таймера (секунды) НА ОВЕРЛЕЕ
    function modifyTimerInputOverlay(secondsToModify) {
        const inputField = document.getElementById("overlay-timer-input"); // Ищем по ID на оверлее
        if (!inputField) return;
        let currentVal = inputField.valueAsNumber;
        if (isNaN(currentVal)) currentVal = 0;
        let newVal = currentVal + secondsToModify;
        if (newVal < 0) newVal = 0;
        inputField.valueAsNumber = newVal;

        // Обновляем глобальную переменную и localStorage
        overlayTimerDuration = newVal;
        localStorage.setItem(localStorageTimerKey, overlayTimerDuration.toString());

        // --- НАЧАЛО ИСПРАВЛЕНИЯ ---
        // При изменении длительности таймера кнопками,
        // сбрасываем текущий отсчет и перезапускаем таймер
        overlayCountdownRemaining = overlayTimerDuration;
        if (overlayCountdownRemaining < 0) overlayCountdownRemaining = 0; // Доп. проверка

        if (overlayTimerIntervalId) {
            clearInterval(overlayTimerIntervalId); // Останавливаем старый интервал
            overlayTimerIntervalId = null; // Сбрасываем ID
        }

        updateOverlayTimer(); // Обновляем отображение таймера немедленно

        if (overlayTimerDuration > 0) {
            // Запускаем новый интервал, если длительность > 0
            overlayTimerIntervalId = setInterval(updateOverlayTimer, 1000);
        }
        // --- КОНЕЦ ИСПРАВЛЕНИЯ ---
    }


    function startSplitCheckInterval() {
        if (!splitCheckIntervalId) {
            splitCheckIntervalId = setInterval(checkSplitCondition, 500);
        }
    }

    function stopSplitCheckInterval() {
        if (splitCheckIntervalId) {
            clearInterval(splitCheckIntervalId);
            splitCheckIntervalId = null;
        }
    }

    function addControlPanel(primaryContainer) {
        if (panelAdded) {
            ensurePanelPosition();
            updateSplitDisplay(); // Обновляем поле ввода сплита и статистику
            // Поле ввода таймера теперь только на оверлее
            return;
        }

        if (!primaryContainer) {
             return;
        }

        const panel = document.createElement("div");
        panel.id = "split-control-panel";

        const setButton = document.createElement("button");
        setButton.id = "set-split-button";
        setButton.textContent = "НАЧАТЬ СПЛИТ";
        setButton.addEventListener("click", function() {
            const inputField = document.getElementById("split-input");
            const inputVal = inputField.valueAsNumber;

            if (!isNaN(inputVal) && inputVal >= 0) {
                const oldSplitMinutes = splitMinutes;
                splitMinutes = inputVal;

                 if (splitMinutes > 0) {
                     startSplitCheckInterval();
                     setButton.textContent = "СПЛИТ НАЧАТ";
                     setButton.style.background = 'var(--yt-spec-call-to-action)';

                     if (video) {
                         const thresholdSeconds = splitMinutes * 60;
                         if (video.currentTime >= thresholdSeconds) {
                             video.pause();
                             splitTriggered = true;
                             showOverlay();
                             if(splitSoundUrl && audioPlayer && audioPlayer.src !== 'ВАША_ПРЯМАЯ_ССЫЛКА_НА_ЗВУКОВОЙ_ФАЙЛ_ТУТ'){
                                 audioPlayer.pause();
                                 audioPlayer.currentTime = 0;
                                 audioPlayer.play().catch(e => console.error("YouTube Split: Ошибка при воспроизведении звука:", e));
                             }
                         } else {
                             splitTriggered = false;
                             removeOverlay();
                             if (video.paused && oldSplitMinutes === null) {
                                 video.play();
                             }
                         }
                     }

                 } else { // splitMinutes === 0
                     stopSplitCheckInterval();
                     splitTriggered = false;
                     removeOverlay();
                     setButton.textContent = "НАЧАТЬ СПЛИТ";
                     setButton.style.background = 'var(--yt-spec-brand-suggested-action)';

                     if (video && video.paused && oldSplitMinutes !== null && oldSplitMinutes > 0) {
                         video.play();
                     }
                 }
                 updateSplitDisplay();
                 updateSplitStatsDisplay();
            } else {
                alert("Введите корректное число минут.");
            }
        });

        // --- Группа управления сплитом (минуты) ---
        const splitLabel = document.createElement("label");
        splitLabel.setAttribute("for", "split-input");
        const labelTextMain = document.createTextNode("Сплит (мин):");
        const breakElement = document.createElement("br");
        const italicElement = document.createElement("i");
        const labelTextInstruction = document.createTextNode("(уст. перед \"Начать\")");

        splitLabel.appendChild(labelTextMain);
        splitLabel.appendChild(breakElement);
        italicElement.appendChild(labelTextInstruction);
        splitLabel.appendChild(italicElement);

        const splitInputGroup = document.createElement("div");
        splitInputGroup.id = "split-input-group";
        splitInputGroup.classList.add("split-input-group");

        const splitInputField = document.createElement("input");
        splitInputField.type = "number";
        splitInputField.id = "split-input";
        splitInputField.min = "0";
        splitInputField.valueAsNumber = splitMinutes === null ? 0 : splitMinutes;

         const splitModifyButtons = [
             { text: '+1', minutes: 1 },
             { text: '+5', minutes: 5 },
             { text: '+10', minutes: 10 },
             { text: '+20', minutes: 20 }
         ];

         splitModifyButtons.forEach(btnInfo => {
             const button = document.createElement("button");
             button.textContent = btnInfo.text;
             // Используем modifySplitInput, которая работает с элементами на панели
             button.addEventListener("click", () => modifySplitInput(btnInfo.minutes));
             splitInputGroup.appendChild(button);
         });

        splitInputGroup.insertBefore(splitInputField, splitInputGroup.children[0]);


        // --- Регулятор громкости алерта ---
        const volumeControlGroup = document.createElement("div");
        volumeControlGroup.id = "split-volume-control";

        const volumeLabel = document.createElement("label");
        volumeLabel.setAttribute("for", "split-volume-slider");
        volumeLabel.textContent = "Громкость алерта:";

        const volumeSlider = document.createElement("input");
        volumeSlider.type = "range";
        volumeSlider.id = "split-volume-slider";
        volumeSlider.min = "0";
        volumeSlider.max = "1";
        volumeSlider.step = "0.05";

        let savedVolume = localStorage.getItem(localStorageVolumeKey);
        if (savedVolume === null) {
             savedVolume = '0.5';
        }
        volumeSlider.value = savedVolume;

        volumeSlider.addEventListener("input", function() {
             if (audioPlayer) {
                 audioPlayer.volume = parseFloat(this.value);
             }
             localStorage.setItem(localStorageVolumeKey, this.value);
        });

        volumeControlGroup.appendChild(volumeLabel);
        volumeControlGroup.appendChild(volumeSlider);

        if (audioPlayer) {
             audioPlayer.volume = parseFloat(savedVolume);
        }

        const statsElement = document.createElement("span");
        statsElement.id = "split-stats";


        // --- Собираем панель ---
        panel.appendChild(setButton);
        panel.appendChild(splitLabel);
        panel.appendChild(splitInputGroup);
        panel.appendChild(volumeControlGroup);
        panel.appendChild(statsElement);

        primaryContainer.insertBefore(panel, primaryContainer.firstChild);
        panelAdded = true;
        updateSplitDisplay();
        updateSplitStatsDisplay();
    }

     function ensurePanelPosition() {
         if (!panelAdded) return;

         const panel = document.getElementById("split-control-panel");
         const primaryContainer = document.querySelector("ytd-watch-flexy #primary");

         if (panel && primaryContainer) {
             if (primaryContainer.firstChild !== panel) {
                  primaryContainer.insertBefore(panel, primaryContainer.firstChild);
             }
         }
     }

    function addMinutesToActiveSplit(minutesToAdd) {
        if (splitMinutes === null) return;

        splitMinutes += minutesToAdd;
        updateSplitDisplay();

        if (overlay) {
             updateOverlayRemainingMinutes();
        }

        const thresholdSeconds = splitMinutes * 60;

        if (video && video.currentTime < thresholdSeconds) {
            removeOverlay();
            splitTriggered = false;
            video.play();
        }
    }

    // Обновляет текст таймера на оверлее
    function updateOverlayTimer() {
        const timerElement = document.getElementById('overlay-timer');
        if (timerElement) {
             if (overlayCountdownRemaining > 0) {
                const minutes = Math.floor(overlayCountdownRemaining / 60);
                const seconds = overlayCountdownRemaining % 60;
                const secondsFormatted = seconds < 10 ? '0' + seconds : seconds;
                timerElement.textContent = `ЖДЕМ ${minutes}:${secondsFormatted}, ИНАЧЕ СКИП`;
                overlayCountdownRemaining--;
             } else {
                 timerElement.textContent = `ЖДЕМ 0:00, ИНАЧЕ СКИП`;
                 if (overlayTimerIntervalId) {
                     clearInterval(overlayTimerIntervalId);
                     overlayTimerIntervalId = null;
                 }
                 // Здесь можно добавить логику автоматического скипа или действия по истечении таймера
                 // Например: if (video) video.currentTime = video.duration; // Скип до конца
             }
        } else {
            if (overlayTimerIntervalId) {
                 clearInterval(overlayTimerIntervalId);
                 overlayTimerIntervalId = null;
            }
        }
    }

    // Обновляет сообщение "ОСТАЛОСЬ" на оверлее
    function updateOverlayRemainingMinutes() {
         const remainingElement = document.getElementById('overlay-remaining-minutes');
         if (remainingElement) {
             const remainingMinutes = totalVideoMinutes !== null && splitMinutes !== null
                                       ? Math.max(0, totalVideoMinutes - splitMinutes)
                                       : '?';
             if (totalVideoMinutes === null) {
                  remainingElement.textContent = `ОСТАЛОСЬ ? минут выкупить`;
             } else {
                  remainingElement.textContent = `ОСТАЛОСЬ ${remainingMinutes} минут выкупить`;
             }
         }
    }


    function checkSplitCondition() {
        if (!video) {
            video = document.querySelector("video");
            if (!video) {
                 stopSplitCheckInterval();
                 splitTriggered = false;
                 removeOverlay();
                 return;
            }
             initAudioPlayer();
             const volumeSlider = document.getElementById('split-volume-slider');
             if(audioPlayer && volumeSlider) audioPlayer.volume = parseFloat(volumeSlider.value);
        }

        if (totalVideoMinutes === null && isFinite(video.duration) && video.duration > 0) {
             totalVideoMinutes = Math.ceil(video.duration / 60);
             if (panelAdded) {
                 updateSplitStatsDisplay();
             }
        }


        if (splitMinutes !== null && splitMinutes > 0) {
            const thresholdSeconds = splitMinutes * 60;

            if (video.currentTime >= thresholdSeconds && !splitTriggered) {
                video.pause();
                splitTriggered = true;
                showOverlay();
                if(splitSoundUrl && audioPlayer && audioPlayer.src !== 'ВАША_ПРЯМАЯ_ССЫЛКА_НА_ЗВУКОВОЙ_ФАЙЛ_ТУТ'){
                     audioPlayer.pause();
                     audioPlayer.currentTime = 0;
                     audioPlayer.play().catch(e => console.error("YouTube Split: Ошибка при воспроизведении звука:", e));
                }
            }
            if (splitTriggered && video.currentTime < thresholdSeconds) {
                removeOverlay();
                splitTriggered = false;
                video.play();
            }
        } else {
             stopSplitCheckInterval();
             splitTriggered = false;
             removeOverlay();
             if (video && video.paused) video.play();
        }
    }

    function showOverlay() {
        if (overlay) return;

        overlay = document.createElement("div");
        overlay.id = "split-overlay";

        const warningMessage = document.createElement("div");
        warningMessage.id = "split-warning-message";
        warningMessage.textContent = "⚠️ НУЖНО ДОНАТНОЕ ТОПЛИВО ⚠️";

        const splitMessage = document.createElement("div");
        splitMessage.id = "split-main-message";
        splitMessage.textContent = "СПЛИТ НЕ ОПЛАЧЕН";

        // --- Элемент таймера ---
        const timerElement = document.createElement("div");
        timerElement.id = "overlay-timer";

        // --- Элемент сообщения "ОСТАЛОСЬ" ---
        const remainingMinutesElement = document.createElement("div");
        remainingMinutesElement.id = "overlay-remaining-minutes";

        // --- Контейнер управления таймером на оверлее ---
        const overlayTimerControlGroup = document.createElement("div");
        overlayTimerControlGroup.id = "overlay-timer-control";

        const timerLabel = document.createElement("label");
        timerLabel.setAttribute("for", "overlay-timer-input");
        timerLabel.textContent = "Таймер (сек):";

        const timerInputField = document.createElement("input");
        timerInputField.type = "number";
        timerInputField.id = "overlay-timer-input";
        timerInputField.min = "0";
        timerInputField.valueAsNumber = overlayTimerDuration;

         // Обработчик изменения поля ввода таймера (для сохранения значения) НА ОВЕРЛЕЕ
         timerInputField.addEventListener('input', function() {
             const val = this.valueAsNumber;
             if (!isNaN(val) && val >= 0) {
                 overlayTimerDuration = val;
                 localStorage.setItem(localStorageTimerKey, overlayTimerDuration.toString());
                 // При изменении длительности таймера, сбрасываем текущий отсчет и перезапускаем таймер
                 overlayCountdownRemaining = overlayTimerDuration;
                 if (overlayTimerIntervalId) clearInterval(overlayTimerIntervalId);
                 if (overlayTimerDuration > 0) {
                     overlayTimerIntervalId = setInterval(updateOverlayTimer, 1000);
                 } else {
                     overlayTimerIntervalId = null;
                 }
                 updateOverlayTimer(); // Обновить отображение сразу
             } else {
                 this.valueAsNumber = overlayTimerDuration;
             }
         });


         const timerModifyButtons = [
             { text: '-60', seconds: -60 }, // Уменьшение/увеличение на минуту
             { text: '-10', seconds: -10 },
             { text: '-5', seconds: -5 },
             { text: '+5', seconds: 5 },
             { text: '+10', seconds: 10 },
             { text: '+60', seconds: 60 } // Уменьшение/увеличение на минуту
         ];

         timerModifyButtons.forEach(btnInfo => {
             const button = document.createElement("button");
             button.textContent = btnInfo.text;
             // Вызываем modifyTimerInputOverlay, которая работает с элементами на оверлее
             button.addEventListener("click", () => modifyTimerInputOverlay(btnInfo.seconds));
             overlayTimerControlGroup.appendChild(button);
         });

         // Вставляем поле ввода первым в группу таймера на оверлее
         overlayTimerControlGroup.insertBefore(timerInputField, overlayTimerControlGroup.children[0]);


        // --- Контейнер кнопок продления ---
        const extendButtonsContainer = document.createElement("div");
        extendButtonsContainer.id = "split-extend-buttons";

        const extendButtonConfigs = [
             { minutes: 1, cost: extendCost },
             { minutes: 5, cost: extendCost * 5 },
             { minutes: 10, cost: extendCost * 10 },
             { minutes: 20, cost: extendCost * 20 }
        ];

        extendButtonConfigs.forEach(config => {
            const button = document.createElement("button");
            button.textContent = `+ ${config.minutes} минут${getMinuteEnding(config.minutes)} - ${config.cost} рублей`;
            button.addEventListener("click", function() {
                addMinutesToActiveSplit(config.minutes);
            });
            extendButtonsContainer.appendChild(button);
        });

        // --- Добавление гифки ---
        const gifElement = document.createElement("img");
        gifElement.src = overlayGifUrl;


        overlay.appendChild(warningMessage);
        overlay.appendChild(splitMessage);
        overlay.appendChild(timerElement);
        overlay.appendChild(remainingMinutesElement);
        overlay.appendChild(overlayTimerControlGroup); // Добавляем контейнер управления таймером оверлея
        overlay.appendChild(extendButtonsContainer);
        overlay.appendChild(gifElement);

        document.body.appendChild(overlay);

        // --- Запуск таймера и обновление сообщения "Осталось" при показе оверлея ---
        overlayCountdownRemaining = overlayTimerDuration; // Инициализируем отсчет установленной длительностью
         if (overlayCountdownRemaining < 0) overlayCountdownRemaining = 0;

        updateOverlayTimer();
        updateOverlayRemainingMinutes();
        if (overlayTimerDuration > 0 && !overlayTimerIntervalId) {
            overlayTimerIntervalId = setInterval(updateOverlayTimer, 1000);
        }
    }

    function getMinuteEnding(count) {
        const lastDigit = count % 10;
        const lastTwoDigits = count % 100;

        if (lastTwoDigits >= 11 && lastTwoDigits <= 14) {
            return '';
        }
        if (lastDigit === 1) {
            return 'а';
        }
        if (lastDigit >= 2 && lastDigit <= 4) {
            return 'ы';
        }
        return '';
    }

    function removeOverlay() {
        if (overlay) {
            overlay.remove();
            overlay = null;
            if (overlayTimerIntervalId) {
                 clearInterval(overlayTimerIntervalId);
                 overlayTimerIntervalId = null;
            }
            if (audioPlayer) {
                 audioPlayer.pause();
                 audioPlayer.currentTime = 0;
            }
        }
    }

     function initAudioPlayer() {
         if (splitSoundUrl && splitSoundUrl !== 'ВАША_ПРЯМАЯ_ССЫЛКА_НА_ЗВУКОВОЙ_ФАЙЛ_ТУТ') {
             if (!audioPlayer || audioPlayer.src !== splitSoundUrl) {
                  if (audioPlayer) {
                     audioPlayer.pause();
                     audioPlayer = null;
                  }
                 audioPlayer = new Audio(splitSoundUrl);
                 audioPlayer.preload = 'auto';
                 audioPlayer.onerror = (e) => console.error("YouTube Split: Не удалось загрузить или воспроизвести звук:", e);

                 let savedVolume = localStorage.getItem(localStorageVolumeKey);
                 if (savedVolume !== null) {
                      audioPlayer.volume = parseFloat(savedVolume);
                 } else {
                      audioPlayer.volume = 0.5;
                 }
             }
         } else {
              if (audioPlayer) {
                 audioPlayer.pause();
                 audioPlayer = null;
             }
         }
     }

    function setupElementsAndPanel() {
        injectStyles();
        initAudioPlayer();

        video = document.querySelector("video");
        const primaryContainer = document.querySelector("ytd-watch-flexy #primary");
        const panel = document.getElementById("split-control-panel");

        if (video && primaryContainer) {
             if (!panelAdded) {
                 addControlPanel(primaryContainer);
             } else {
                  ensurePanelPosition();
             }

            if (totalVideoMinutes === null && isFinite(video.duration) && video.duration > 0) {
                totalVideoMinutes = Math.ceil(video.duration / 60);
                 if (panelAdded) {
                     updateSplitStatsDisplay();
                 }
            }

        } else {
            if (panelAdded) {
                 const existingPanel = document.getElementById("split-control-panel");
                 if(existingPanel) existingPanel.remove();
                 panelAdded = false;
            }
             video = null;
             totalVideoMinutes = null;
        }
    }

    if (!setupIntervalId) {
        setupIntervalId = setInterval(setupElementsAndPanel, 500);
    }

    let lastUrl = location.href;
    const urlObserver = new MutationObserver(() => {
        if (location.href !== lastUrl) {
            lastUrl = location.href;

            stopSplitCheckInterval();
            if (overlayTimerIntervalId) {
                 clearInterval(overlayTimerIntervalId);
                 overlayTimerIntervalId = null;
            }
            if (setupIntervalId) {
                 clearInterval(setupIntervalId);
                 setupIntervalId = null;
            }

             if (audioPlayer) {
                 audioPlayer.pause();
             }
             removeOverlay();

            const oldPanel = document.getElementById("split-control-panel");
            if (oldPanel) {
                oldPanel.remove();
            }
            const oldStyles = document.getElementById("yt-split-styles");
             if(oldStyles) oldStyles.remove();

            splitMinutes = null;
            totalVideoMinutes = null;
            video = null;
            splitTriggered = false;
            panelAdded = false;
             // overlayTimerDuration сохраняется в localStorage

            if (!setupIntervalId) {
                 setupIntervalId = setInterval(setupElementsAndPanel, 500);
            }
        }
    });

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


    window.addEventListener('beforeunload', function() {
        stopSplitCheckInterval();
        if (overlayTimerIntervalId) {
            clearInterval(overlayTimerIntervalId);
            overlayTimerIntervalId = null;
        }
        if (setupIntervalId) {
            clearInterval(setupIntervalId);
            setupIntervalId = null;
        }
         if (audioPlayer) {
            audioPlayer.pause();
            audioPlayer = null;
         }
        if (urlObserver) {
             urlObserver.disconnect();
        }
    });


})();