Привет, у меня есть js скрипт для tampermonkey. Он выводит отдельный оверлей чата twitch. В нем нужно исправить баг, который происходит со скролом, при переходе в режим на весь экран чат автоскроллится в самый верх, при выходе из фуллскрина происходит тоже самое
// ==UserScript==
// @name         Twitch Chat Overlay Ultimate
// @namespace    http://tampermonkey.net/
// @version      16.0
// @description  Финальный оверлей чата Twitch с правильным отображением значков пользователей
// @author       You
// @match        https://www.twitch.tv/*
// @grant        none
// @run-at       document-idle
// ==/UserScript==

(function() {
    'use strict';

    // Создаем стили
    const style = document.createElement('style');
    style.textContent = `
        #twitch-chat-overlay {
            position: fixed;
            top: 50px;
            right: 20px;
            width: 320px;
            height: 450px;
            background: rgba(0, 0, 0, 0.7);
            color: white;
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
            z-index: 9999999;
            border-radius: 5px;
            border: 1px solid rgba(128, 128, 128, 0.3);
            overflow: hidden;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
        }

        #twitch-chat-header {
            padding: 8px;
            background: rgba(50, 50, 50, 0.7);
            cursor: move;
            display: flex;
            justify-content: space-between;
            align-items: center;
            border-bottom: 1px solid rgba(128, 128, 128, 0.3);
        }

        #twitch-chat-title {
            font-weight: bold;
        }

        #twitch-chat-close {
            cursor: pointer;
            padding: 0 5px;
        }

        #twitch-chat-messages {
            height: calc(100% - 37px);
            overflow-y: auto;
            padding: 8px;
            scrollbar-width: thin;
            scrollbar-color: rgba(100, 65, 164, 0.6) rgba(30, 30, 30, 0.3);
        }

        /* Стили для скроллбара Webkit (Chrome, Safari, Edge) */
        #twitch-chat-messages::-webkit-scrollbar {
            width: 8px;
            background-color: rgba(30, 30, 30, 0.3);
        }

        #twitch-chat-messages::-webkit-scrollbar-thumb {
            background-color: rgba(100, 65, 164, 0.6);
            border-radius: 4px;
        }

        #twitch-chat-messages::-webkit-scrollbar-thumb:hover {
            background-color: rgba(100, 65, 164, 0.8);
        }

        .twitch-chat-message {
            margin-bottom: 10px;
            line-height: 1.5;
            word-break: break-word;
        }

        .twitch-chat-reply-indicator {
            color: #9147ff;
            font-style: italic;
            margin-right: 5px;
            font-size: 0.9em;
        }

        .twitch-chat-badges {
            display: inline-flex;
            margin-right: 5px;
            vertical-align: middle;
        }

        .twitch-chat-badge {
            display: inline-block;
            margin-right: 2px;
            width: 18px;
            height: 18px;
            vertical-align: middle;
        }

        .twitch-chat-mention {
            color: #b19dd8;
            font-weight: bold;
        }

        .twitch-chat-emote {
            display: inline-block;
            vertical-align: middle;
            margin: 0 2px;
            height: 24px;
        }

        .twitch-chat-emoji {
            display: inline;
            height: 1.25em;
            vertical-align: -0.25em;
        }

        #twitch-chat-resize {
            position: absolute;
            right: 0;
            bottom: 0;
            width: 14px;
            height: 14px;
            background: rgba(100, 65, 164, 0.5);
            cursor: se-resize;
            border-radius: 0 0 5px 0;
        }
    `;
    document.head.appendChild(style);

    // Глобальные переменные для отслеживания состояния
    let currentChannelURL = window.location.pathname;
    let lastProcessedMessageCount = 0;
    let lastMessageHash = '';
    let chatMonitoringInterval = null;

    // Создаем структуру чата
    const overlay = document.createElement('div');
    overlay.id = 'twitch-chat-overlay';

    const header = document.createElement('div');
    header.id = 'twitch-chat-header';
    header.innerHTML = '<div id="twitch-chat-title">Twitch Chat</div><div id="twitch-chat-close">×</div>';

    const messages = document.createElement('div');
    messages.id = 'twitch-chat-messages';

    const resize = document.createElement('div');
    resize.id = 'twitch-chat-resize';

    overlay.appendChild(header);
    overlay.appendChild(messages);
    overlay.appendChild(resize);
    document.body.appendChild(overlay);

    // Закрытие чата
    document.getElementById('twitch-chat-close').addEventListener('click', () => {
        overlay.style.display = 'none';
    });

    // Перемещение чата
    let isDragging = false;
    let dragOffsetX = 0, dragOffsetY = 0;

    header.addEventListener('mousedown', (e) => {
        if (e.target.id !== 'twitch-chat-close') {
            isDragging = true;
            dragOffsetX = e.clientX - overlay.getBoundingClientRect().left;
            dragOffsetY = e.clientY - overlay.getBoundingClientRect().top;
        }
    });

    document.addEventListener('mousemove', (e) => {
        if (isDragging) {
            overlay.style.left = (e.clientX - dragOffsetX) + 'px';
            overlay.style.top = (e.clientY - dragOffsetY) + 'px';
        }
    });

    document.addEventListener('mouseup', () => {
        isDragging = false;
    });

    // Изменение размера
    let isResizing = false;

    resize.addEventListener('mousedown', (e) => {
        isResizing = true;
        e.stopPropagation();
    });

    document.addEventListener('mousemove', (e) => {
        if (isResizing) {
            const width = Math.max(200, e.clientX - overlay.getBoundingClientRect().left);
            const height = Math.max(150, e.clientY - overlay.getBoundingClientRect().top);
            overlay.style.width = width + 'px';
            overlay.style.height = height + 'px';
        }
    });

    document.addEventListener('mouseup', () => {
        isResizing = false;
    });

    // Горячие клавиши (O/Щ)
    document.addEventListener('keydown', (e) => {
        if (e.code === 'KeyO' || e.code === 'BracketLeft' || e.keyCode === 79 || e.keyCode === 219) {
            overlay.style.display = overlay.style.display === 'none' ? 'block' : 'none';
        }
    });

    // Полноэкранный режим
    document.addEventListener('fullscreenchange', () => {
        if (document.fullscreenElement) {
            document.fullscreenElement.appendChild(overlay);
        } else {
            document.body.appendChild(overlay);
        }
    });

    // Функция для очистки всех сообщений в чате
    function clearChat() {
        const messagesContainer = document.getElementById('twitch-chat-messages');
        if (messagesContainer) {
            messagesContainer.innerHTML = '';
            lastProcessedMessageCount = 0;
            lastMessageHash = '';
        }
    }

    // Функция для экранирования HTML-разметки
    function escapeHTML(str) {
        if (typeof str !== 'string') return '';
        return str
            .replace(/&/g, '&amp;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;')
            .replace(/"/g, '&quot;')
            .replace(/'/g, '&#039;');
    }

    // Обработка текста с упоминаниями
    function processTextWithMentions(text) {
        // Проверяем тип данных
        if (typeof text !== 'string') {
            return '';
        }

        // Сначала экранируем HTML
        text = escapeHTML(text);

        // Регулярное выражение для обнаружения упоминаний (@username)
        const mentionRegex = /(@\w+)/g;

        // Заменяем упоминания на HTML с классом
        return text.replace(mentionRegex, '<span class="twitch-chat-mention">$1</span>');
    }

    // Удаление лишнего текста эмодзи и меток
    function cleanEmoteText(text) {
        if (typeof text !== 'string') {
            return '';
        }

        // Удаляем HTML-теги
        text = text.replace(/<[^>]*>/g, '');

        // Удаляем метки типа "Канал:" и "Смайлики канала BetterTTV"
        const cleanedText = text
            .replace(/Канал:\s*\w+/g, '')
            .replace(/Смайлики канала \w+/g, '')
            .replace(/Channel:\s*\w+/g, '')
            .replace(/Emotes:\s*\w+/g, '')
            .replace(/\b\w+TV\b/g, '')  // Удаляем только слова, заканчивающиеся на TV
            .replace(/^\s*:\s*/, '')    // Удаляем начальное двоеточие с пробелами
            .trim();

        return cleanedText;
    }

    // Определение и замена Unicode эмодзи
    function replaceEmojis(text) {
        // Регулярное выражение для поиска эмодзи Unicode
        const emojiRegex = /[\u{1F600}-\u{1F64F}\u{1F300}-\u{1F5FF}\u{1F680}-\u{1F6FF}\u{1F700}-\u{1F77F}\u{1F780}-\u{1F7FF}\u{1F800}-\u{1F8FF}\u{1F900}-\u{1F9FF}\u{1FA00}-\u{1FA6F}\u{1FA70}-\u{1FAFF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}]/gu;

        // Заменяем эмодзи на HTML-элементы с классом
        return text.replace(emojiRegex, match => {
            return `<span class="twitch-chat-emoji">${match}</span>`;
        });
    }

    // Получение бейджей пользователя
    function getUserBadges(message) {
        const badges = [];

        try {
            // Ищем все бейджи в сообщении
            const badgeElements = message.querySelectorAll('.chat-badge');

            badgeElements.forEach(badge => {
                const imgElement = badge.querySelector('img');
                if (imgElement && imgElement.src) {
                    badges.push({
                        url: imgElement.src,
                        title: imgElement.alt || badge.getAttribute('title') || badge.getAttribute('aria-label') || ''
                    });
                }
            });

            // Дополнительно ищем бейджи в других местах
            const allBadges = message.querySelectorAll('[data-a-target="chat-badge"], [data-test-selector="message-badge"]');
            allBadges.forEach(badge => {
                const imgElement = badge.querySelector('img');
                if (imgElement && imgElement.src) {
                    // Проверяем, нет ли уже такого бейджа
                    if (!badges.some(b => b.url === imgElement.src)) {
                        badges.push({
                            url: imgElement.src,
                            title: imgElement.alt || badge.getAttribute('title') || badge.getAttribute('aria-label') || ''
                        });
                    }
                }
            });
        } catch (e) {
            console.error('Ошибка при получении бейджей пользователя:', e);
        }

        return badges;
    }

    // Добавление сообщения в чат
    function addMessage(username, content, color, isReply, emotes = [], badges = []) {
        const messagesContainer = document.getElementById('twitch-chat-messages');
        if (!messagesContainer) return;

        const message = document.createElement('div');
        message.className = 'twitch-chat-message';

        let messageContent = '';

        // Добавляем индикатор ответа, если это ответ
        if (isReply) {
            messageContent += '<span class="twitch-chat-reply-indicator">↩️ В ответ:</span> ';
        }

        // Добавляем бейджи пользователя
        if (badges.length > 0) {
            messageContent += '<span class="twitch-chat-badges">';
            badges.forEach(badge => {
                messageContent += `<img class="twitch-chat-badge" src="${badge.url}" alt="${badge.title}" title="${badge.title}" />`;
            });
            messageContent += '</span>';
        }

        // Добавляем имя пользователя
        messageContent += `<span style="color:${color || '#ffffff'};font-weight:bold;">${escapeHTML(username)}:</span> `;

        // Очищаем и обрабатываем текст сообщения
        let processedContent = cleanEmoteText(content);

        // Обрабатываем Unicode эмодзи
        if (processedContent.match(/[\u{1F600}-\u{1F64F}]/u)) {
            processedContent = replaceEmojis(processedContent);
        }

        // Обрабатываем упоминания
        processedContent = processTextWithMentions(processedContent);

        // Вставляем обработанный текст сообщения
        if (processedContent.trim()) {
            messageContent += processedContent;
        }

        // Вставляем эмодзи после текста
        if (emotes.length > 0) {
            // Добавляем пробел, если уже есть текст
            if (processedContent.trim()) {
                messageContent += ' ';
            }

            // Добавляем каждый эмодзи
            emotes.forEach(emote => {
                if (emote.url) {
                    messageContent += `<img class="twitch-chat-emote" src="${emote.url}" alt="${escapeHTML(emote.name)}" title="${escapeHTML(emote.name)}" height="24" /> `;
                }
            });
        }

        message.innerHTML = messageContent;
        messagesContainer.appendChild(message);
        messagesContainer.scrollTop = messagesContainer.scrollHeight;

        // Ограничение количества сообщений
        while (messagesContainer.children.length > 100) {
            messagesContainer.removeChild(messagesContainer.firstChild);
        }
    }

    // Функция для обнаружения и обработки эмодзи в сообщении
    function findEmotesInMessage(message) {
        const emotes = [];

        try {
            // Ищем эмодзи от Twitch, BTTV, FFZ и 7TV
            const emoteElements = message.querySelectorAll('.chat-line__message--emote, .seventv-emote, .bttv-emote, .ffz-emote');

            emoteElements.forEach(emote => {
                // Получаем URL изображения
                const emoteUrl = emote.src || emote.getAttribute('data-src');

                if (emoteUrl) {
                    // Получаем название эмодзи
                    const emoteName = emote.alt ||
                                     emote.getAttribute('data-name') ||
                                     emote.getAttribute('data-tooltip-text') ||
                                     'emote';

                    // Добавляем эмодзи в список
                    emotes.push({
                        name: emoteName,
                        url: emoteUrl
                    });
                }
            });

            // Специальная проверка изображений, чтобы исключить бейджи
            const imgElements = message.querySelectorAll('img');
            imgElements.forEach(img => {
                // Проверяем, что изображение не является бейджем пользователя
                const notBadge = !(
                    img.parentElement && (
                        img.parentElement.classList.contains('chat-badge') ||
                        img.parentElement.hasAttribute('data-badge') ||
                        img.parentElement.getAttribute('data-a-target')?.includes('badge')
                    )
                );

                // Проверяем, что это изображение похоже на эмодзи
                const isEmote = (
                    img.classList.contains('chat-image') ||
                    img.hasAttribute('data-provider') ||
                    (img.alt && img.alt.length < 20) ||
                    img.src?.includes('emote') ||
                    img.src?.includes('emoticon')
                );

                if (notBadge && isEmote && img.src) {
                    // Получаем название эмодзи
                    const emoteName = img.alt || 'emote';

                    // Добавляем эмодзи в список, исключая дубликаты
                    if (!emotes.some(e => e.url === img.src)) {
                        emotes.push({
                            name: emoteName,
                            url: img.src
                        });
                    }
                }
            });

            // Специальная обработка для 7TV и других контейнеров эмодзи
            const emoteContainers = message.querySelectorAll('[data-7tv-emote], [data-v-7tv-emote], [data-emote-id], [data-test-selector="emote-button"]');
            emoteContainers.forEach(container => {
                const emoteImgs = container.querySelectorAll('img');
                emoteImgs.forEach(img => {
                    if (img.src) {
                        const emoteName = img.alt ||
                                         container.getAttribute('data-name') ||
                                         container.getAttribute('data-tooltip-text') ||
                                         'emote';

                        // Добавляем в список, исключая дубликаты
                        if (!emotes.some(e => e.url === img.src)) {
                            emotes.push({
                                name: emoteName,
                                url: img.src
                            });
                        }
                    }
                });
            });
        } catch (e) {
            console.error('Ошибка при обработке эмодзи:', e);
        }

        return emotes;
    }

    // Функция для извлечения текста сообщения, исключая бейджи
    function extractMessageText(message) {
        try {
            // Находим элементы с текстом
            const textElements = message.querySelectorAll('.text-fragment, [data-a-target="chat-message-text"]');

            let messageText = '';
            if (textElements.length > 0) {
                // Если есть конкретные текстовые элементы, собираем их
                textElements.forEach(el => {
                    if (el.textContent.trim()) {
                        messageText += el.textContent.trim() + ' ';
                    }
                });
                return messageText.trim();
            }

            // Если текстовые элементы не найдены, получаем весь текст
            // Находим имя пользователя
            const usernameElement = message.querySelector('[data-a-target="chat-message-username"]');
            const username = usernameElement ? usernameElement.textContent.trim() : '';

            // Получаем весь текст сообщения
            messageText = message.textContent.trim();

            // Удаляем имя пользователя из текста
            if (username && messageText.includes(username)) {
                messageText = messageText.replace(username, '');

                // Удаляем двоеточие после имени
                messageText = messageText.replace(/^\s*:\s*/, '');
            }

            return messageText.trim();
        } catch (e) {
            console.error('Ошибка при извлечении текста сообщения:', e);
            return message.textContent;
        }
    }

    // Мониторинг чата Twitch
    function startChatMonitoring() {
        // Системное сообщение при запуске
        addMessage('System', 'Инициализация чата...', '#00C2FF', false);

        // Функция поиска контейнера чата
        function findChatContainer() {
            const selectors = [
                '.chat-scrollable-area__message-container',
                '[data-test-selector="chat-scrollable-area__message-container"]',
                '[role="log"][data-a-target="chat-scroller"]'
            ];

            for (const selector of selectors) {
                const element = document.querySelector(selector);
                if (element) return element;
            }

            return null;
        }

        // Функция для проверки, является ли сообщение ответом
        function isReplyMessage(message) {
            // Проверяем наличие элементов, которые могут указывать на ответ
            return !!message.querySelector('.reply-text, [data-test-selector="comment-reply-context"], [data-a-target="chat-reply-line"], .replay-button') ||
                   message.textContent.includes('В ответ @') ||
                   message.textContent.includes('Reply to @');
        }

        // Функция для извлечения содержимого сообщения
        function extractMessageData(message) {
            try {
                // Проверяем, является ли сообщение ответом
                const isReply = isReplyMessage(message);

                // Находим имя пользователя
                const usernameElement = message.querySelector('[data-a-target="chat-message-username"]');
                const username = usernameElement ? usernameElement.textContent.trim() : 'User';

                // Получаем цвет имени пользователя
                const color = usernameElement ?
                    (usernameElement.style.color ||
                     window.getComputedStyle(usernameElement).color) :
                    '#' + Math.floor(Math.random()*16777215).toString(16);

                // Получаем бейджи пользователя
                const badges = getUserBadges(message);

                // Получаем текст сообщения, исключая бейджи
                let messageContent = extractMessageText(message);

                // Удаляем текст ответа, если это ответ
                if (isReply) {
                    messageContent = messageContent.replace(/^В ответ @[^:]+:\s*/, '');
                }

                // Ищем все упоминания в сообщении
                const mentions = message.querySelectorAll('[data-a-target="chat-message-mention"]');
                let mentionTexts = [];
                mentions.forEach(mention => {
                    mentionTexts.push(mention.textContent.trim());
                });

                // Убеждаемся, что упоминания сохранены в тексте
                mentionTexts.forEach(mention => {
                    if (!messageContent.includes(mention)) {
                        messageContent += ' ' + mention;
                    }
                });

                // Ищем эмодзи в сообщении
                const emotes = findEmotesInMessage(message);

                return {
                    username,
                    content: messageContent,
                    color,
                    isReply,
                    emotes,
                    badges
                };
            } catch (e) {
                console.error('Ошибка при обработке сообщения:', e);
                return {
                    username: 'User',
                    content: message.textContent || '[ошибка обработки]',
                    color: '#ffffff',
                    isReply: false,
                    emotes: [],
                    badges: []
                };
            }
        }

        // Функция для обработки сообщений
        function processMessages() {
            const chatContainer = findChatContainer();

            if (!chatContainer) {
                return;
            }

            // Найдем все сообщения чата
            const messageElements = chatContainer.querySelectorAll('.chat-line__message, [data-a-target="chat-line-message"]');

            if (messageElements.length > 0) {
                // Добавляем системное сообщение при первом успешном поиске
                if (lastProcessedMessageCount === 0) {
                    addMessage('System', 'Чат успешно подключен!', '#00C2FF', false);
                }

                // Проверяем, появились ли новые сообщения
                if (messageElements.length > lastProcessedMessageCount) {
                    // Обрабатываем только новые сообщения
                    for (let i = lastProcessedMessageCount; i < messageElements.length; i++) {
                        const message = messageElements[i];

                        // Извлекаем данные сообщения
                        const messageData = extractMessageData(message);

                        // Добавляем сообщение в наш чат
                        addMessage(
                            messageData.username,
                            messageData.content,
                            messageData.color,
                            messageData.isReply,
                            messageData.emotes,
                            messageData.badges
                        );
                    }

                    // Обновляем счетчик обработанных сообщений
                    lastProcessedMessageCount = messageElements.length;
                }

                // Проверка на перезагрузку чата (если количество сообщений уменьшилось)
                if (messageElements.length < lastProcessedMessageCount) {
                    // Создаем хеш текущего состояния чата
                    const currentHash = messageElements[messageElements.length - 1].textContent;

                    // Если хеш изменился, значит это новые сообщения после перезагрузки
                    if (currentHash !== lastMessageHash) {
                        // Добавляем системное сообщение о перезагрузке чата
                        addMessage('System', 'Чат обновлен...', '#00C2FF', false);

                        // Сбрасываем счетчик
                        lastProcessedMessageCount = 0;
                    }
                }

                // Сохраняем хеш последнего сообщения для проверки перезагрузки
                if (messageElements.length > 0) {
                    lastMessageHash = messageElements[messageElements.length - 1].textContent;
                }
            }
        }

        // Запускаем интервал для обработки сообщений
        chatMonitoringInterval = setInterval(processMessages, 500);
    }

    // Функция для проверки изменения URL
    function checkURLChange() {
        if (window.location.pathname !== currentChannelURL) {
            // URL изменился, что означает переход на другой канал
            currentChannelURL = window.location.pathname;

            // Очищаем чат и сбрасываем переменные отслеживания
            clearChat();

            // Добавляем сообщение о смене канала
            addMessage('System', 'Переход на новый канал. Обновление чата...', '#00C2FF', false);

            // Перезапускаем мониторинг чата
            if (chatMonitoringInterval) {
                clearInterval(chatMonitoringInterval);
            }

            // Даем небольшую задержку перед запуском нового мониторинга
            setTimeout(startChatMonitoring, 2000);
        }
    }

    // Запускаем начальный мониторинг чата
    startChatMonitoring();

    // Настраиваем интервал для проверки изменения URL
    setInterval(checkURLChange, 1000);
})();