UNIT3D chatbox - enhanced ULCX

Chat functionalities: Reply, Message and Gift buttons. BBCode buttons. Toggle menu. Emojis.

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         UNIT3D chatbox - enhanced ULCX
// @version      1.2
// @description  Chat functionalities: Reply, Message and Gift buttons. BBCode buttons. Toggle menu. Emojis. 
// @match        https://upload.cx/
// @grant        none
// @namespace https://greasyfork.org/users/1344404
// ==/UserScript==

(function() {
    'use strict';
    //Please do not alter this, It is for contributors to the project only.
            const USER_COLORS = {
    'ace': '#ef008c',
    'TheoneandonlyPook': '#ef008c',
    'Demonic': '#ffac6b',
    }

    // Function to extract the CSRF token
    function extractToken() {
        const tokenElement = document.querySelector('meta[name="csrf-token"]');
        return tokenElement ? tokenElement.content : 'Token not found';
    }

    // Function to extract the user from the URL
    function extractUser() {
        const userLink = document.querySelector('a.top-nav__username--highresolution');
        if (userLink) {
            const url = new URL(userLink.href);
            return url.pathname.split('/').pop();
        }
        return 'User not found';
    }

    // Function to remove the dialog from the page
    function removeDialog() {
        const existingDialog = document.querySelector('dialog');
        if (existingDialog) {
            existingDialog.remove();
        }
    }

    const chatboxID = '#chatbox__messages-create';
    const chatMessagesClassName = '.chatroom__messages';
    const onlineUserListSelector = '.blocks__online .panel__body ul';
    const additionalUserListSelector = '.chatroom-users__list';
    const bbCodesPanelID = 'bbCodesPanel';
    const settingsButtonID = 'settingsButton';
    const settingsPanelID = 'settingsPanel';
    const BBCODES_PANEL_HTML = `
<div id="${bbCodesPanelID}" style="position: relative; display: flex; flex-wrap: wrap; z-index: 9998;">
    <span id="imgButton" style="cursor: pointer; margin-right: 4px;" data-bbcode="[img][/img]">IMG</span>
    <span id="urlButton" style="cursor: pointer; margin-right: 4px;" data-bbcode="[url][/url]">URL</span>
    <span id="colorButton" style="cursor: pointer; margin-right: 4px;">Color</span>
    <input type="color" id="colorPicker" style="cursor: pointer; margin-left: 10px; display: none;" title="Select Color">
    <span style="cursor: pointer; margin: 4px;" id="emojiButton">😊</span>
    <div id="emojiMenu" style="display: none; position: absolute; left: 10px; top: 30px; background: #000000; border: 1px solid #ccc; z-index: 10000;">
        <span class="emoji" data-emoji="😊">😊</span>
        <span class="emoji" data-emoji="😂">😂</span>
        <span class="emoji" data-emoji="😍">😍</span>
        <span class="emoji" data-emoji="😇">😇</span>
        <span class="emoji" data-emoji="🤨">🤨</span>
        <span class="emoji" data-emoji="🥳">🥳</span>
        <span class="emoji" data-emoji="😏">😏</span>
        <span class="emoji" data-emoji="😞">😞</span>
        <span class="emoji" data-emoji="😤">😤</span>
        <span class="emoji" data-emoji="🤬">🤬</span>
        <span class="emoji" data-emoji="🤯">🤯</span>
        <span class="emoji" data-emoji="🥵">🥵</span>
        <span class="emoji" data-emoji="🥶">🥶</span>
        <span class="emoji" data-emoji="🤫">🤫</span>
        <span class="emoji" data-emoji="🤥">🤥</span>
        <span class="emoji" data-emoji="😴">😴</span>
        <span class="emoji" data-emoji="🤮">🤮</span>
        <span class="emoji" data-emoji="🤡">🤡</span>
        <span class="emoji" data-emoji="💩">💩</span>
        <span class="emoji" data-emoji="👻">👻</span>
        <span class="emoji" data-emoji="💀">💀</span>
        <span class="emoji" data-emoji="👽">👽</span>
        <span class="emoji" data-emoji="🎃">🎃</span>
        <span class="emoji" data-emoji="🤝">🤝</span>
        <span class="emoji" data-emoji="👍">👍</span>
        <span class="emoji" data-emoji="👎">👎</span>
        <span class="emoji" data-emoji="✌️">✌️</span>
        <span class="emoji" data-emoji="🖕">🖕</span>
        <span class="emoji" data-emoji="👮">👮</span>
        <span class="emoji" data-emoji="🕸️">🕸️</span>
        <span class="emoji" data-emoji="🐢">🐢</span>
        <span class="emoji" data-emoji="🐋">🐋</span>
        <span class="emoji" data-emoji="🐐">🐐</span>
        <span class="emoji" data-emoji="🐦‍🔥">🐦‍🔥</span>
        <span class="emoji" data-emoji="🌵">🌵</span>
        <span class="emoji" data-emoji="🎄">🎄</span>
        <span class="emoji" data-emoji="🔥">🔥</span>
        <span class="emoji" data-emoji="🌪️">🌪️</span>
        <span class="emoji" data-emoji="🌈">🌈</span>
        <span class="emoji" data-emoji="☀️">☀️</span>
        <span class="emoji" data-emoji="🌧️">🌧️</span>
        <span class="emoji" data-emoji="❄️">❄️</span>
        <span class="emoji" data-emoji="🍺">🍺</span>
        <span class="emoji" data-emoji="🩷">🩷</span>
        <span class="emoji" data-emoji="💔">💔</span>
        <span class="emoji" data-emoji="🛑">🛑</span>
        <span class="emoji" data-emoji="🏴‍☠️">🏴‍☠️</span>
        <!-- Add more emojis as needed -->
    </div>
    <div style="position: relative;">
        <span style="cursor: pointer;" id="bbCodeDropdown">➪</span>
        <div id="bbCodeDropdownMenu" style="display: none; position: absolute; left: 20px; top: -2px; flex-direction: row; z-index: 10000;">
            <span style="cursor: pointer; margin: 2px;" data-bbcode="[b][/b]">[B]</span>
            <span style="cursor: pointer; margin: 2px;" data-bbcode="[i][/i]">[I]</span>
            <span style="cursor: pointer; margin: 2px;" data-bbcode="[u][/u]">[U]</span>
        </div>
    </div>
</div>`;

    const SETTINGS_PANEL_HTML = `<div id="${settingsPanelID}" style="display: none; position: absolute; top: 20px; right: 0; background: rgba(0,0,0,0.9); border-radius: 8px; padding: 10px; color: white; z-index: 10001;">
            <label><input type="checkbox" id="toggleBBCodes" checked> Show BB Codes</label><br>
            <label><input type="checkbox" id="toggleMessageGift" checked> Show Message/Gift Buttons</label><br>
            <label><input type="checkbox" id="toggleReply" checked> Show Reply Button</label>
        </div>`;
    const TOGGLE_BUTTON_HTML = `<div id="${settingsButtonID}" style="cursor: pointer; color: #fff; display: inline-block; margin-left: 4px; font-size: 16px;">⚙️</div>`;
      // Create and add the style block
    const style = document.createElement('style');
    style.type = 'text/css';
    style.innerHTML = `
        .emoji {
            cursor: pointer;
        }
        .reply-icon, .message-icon, .gift-icon { cursor: pointer; margin-left: 5px; }
        .mention-dropdown { position: absolute; background: #333; border: 1px solid #ccc; max-height: 150px; overflow-y: auto; display: none; z-index: 10000; color: #ccc; }
        .mention-dropdown span { display: block; padding: 5px; cursor: pointer; color: #ccc; }
        .mention-dropdown span:hover { background: #555; }
        .panel__actions { position: relative; }
    `;
    document.head.appendChild(style);
    function saveSetting(key, value) {
        localStorage.setItem(key, value);
    }
    function loadSetting(key) {
        return localStorage.getItem(key);
    }
    function applySettings() {
        const toggleBBCodes = loadSetting('toggleBBCodes') === 'true';
        const toggleMessageGift = loadSetting('toggleMessageGift') === 'true';
        const toggleReply = loadSetting('toggleReply') === 'true';
        document.getElementById('toggleBBCodes').checked = toggleBBCodes;
        document.getElementById(bbCodesPanelID).style.display = toggleBBCodes ? 'flex' : 'none';
        document.getElementById('toggleMessageGift').checked = toggleMessageGift;
        const iconsMessageGift = document.querySelectorAll('.message-icon, .gift-icon');
        iconsMessageGift.forEach(icon => icon.style.display = toggleMessageGift ? 'inline' : 'none');
        document.getElementById('toggleReply').checked = toggleReply;
        const iconsReply = document.querySelectorAll('.reply-icon');
        iconsReply.forEach(icon => icon.style.display = toggleReply ? 'inline' : 'none');
    }
    function setupSettingsListeners() {
        document.getElementById('toggleBBCodes').addEventListener('change', (event) => {
            saveSetting('toggleBBCodes', event.target.checked);
            document.getElementById(bbCodesPanelID).style.display = event.target.checked ? 'flex' : 'none';
        });
        document.getElementById('toggleMessageGift').addEventListener('change', (event) => {
            saveSetting('toggleMessageGift', event.target.checked);
            const icons = document.querySelectorAll('.message-icon, .gift-icon');
            icons.forEach(icon => icon.style.display = event.target.checked ? 'inline' : 'none');
        });
        document.getElementById('toggleReply').addEventListener('change', (event) => {
            saveSetting('toggleReply', event.target.checked);
            const icons = document.querySelectorAll('.reply-icon');
            icons.forEach(icon => icon.style.display = event.target.checked ? 'inline' : 'none');
        });
    }
    function getOnlineUsernames() {
        const userElements = document.querySelectorAll(`${onlineUserListSelector} .user-tag__link`);
        const additionalUserElements = document.querySelectorAll(`${additionalUserListSelector} .user-tag__link`);
        const userSet = new Set([...Array.from(userElements), ...Array.from(additionalUserElements)].map(el => el.textContent.trim()));
        return Array.from(userSet);
    }
    function setupMentionFeature(chatbox) {
        const mentionDropdown = document.createElement('div');
        mentionDropdown.classList.add('mention-dropdown');
        document.body.appendChild(mentionDropdown);
        chatbox.addEventListener('input', function(event) {
            const cursorPosition = chatbox.selectionStart;
            const text = chatbox.value.substring(0, cursorPosition);
            const mentionMatch = text.match(/@(\w*)$/);
            if (mentionMatch) {
                const usernamePrefix = mentionMatch[1].toLowerCase();
                const users = getOnlineUsernames().filter(user => user.toLowerCase().startsWith(usernamePrefix));
                mentionDropdown.innerHTML = '';
                users.forEach(user => {
                    const userElement = document.createElement('span');
                    userElement.textContent = user;
                    userElement.addEventListener('click', () => {
                        chatbox.value = chatbox.value.substring(0, cursorPosition - usernamePrefix.length - 1) + '@' + user + ' ' + chatbox.value.substring(cursorPosition);
                        chatbox.focus();
                        mentionDropdown.style.display = 'none';
                    });
                    mentionDropdown.appendChild(userElement);
                });
                const rect = chatbox.getBoundingClientRect();
                mentionDropdown.style.left = `${rect.left}px`;
                mentionDropdown.style.top = `${rect.bottom}px`;
                mentionDropdown.style.display = 'block';
            } else {
                mentionDropdown.style.display = 'none';
            }
        });
        chatbox.addEventListener('keydown', (e) => {
            if (mentionDropdown.style.display === 'block' && e.key === 'Tab') {
                e.preventDefault();
                const firstUser = mentionDropdown.querySelector('span');
                if (firstUser) firstUser.click();
            }
        });
        document.addEventListener('click', function(event) {
            if (!mentionDropdown.contains(event.target)) mentionDropdown.style.display = 'none';
        });
    }

    // Function to add the dialog element to the page
    function addDialog(token, user, username) {
        // Check if a dialog already exists and remove it
        removeDialog();

        // Create dialog HTML
        const dialogHTML = `
        <dialog class="dialog" x-bind="dialogElement">
            <h3 class="dialog__heading">Gift BON to: ${username}</h3>
            <form class="dialog__form" method="POST" action="https://upload.cx/users/${user}/gifts" x-bind="dialogForm">
                <input type="hidden" name="_token" value="${token}" autocomplete="off">
                <input type="hidden" name="recipient_username" value="${username}">
                <p class="form__group">
                    <input id="bon" class="form__text" name="bon" type="text" pattern="[0-9]*" inputmode="numeric" placeholder=" ">
                    <label class="form__label form__label--floating" for="bon">Amount</label>
                </p>
                <p class="form__group">
                    <textarea id="message" class="form__textarea" name="message" placeholder=" "></textarea>
                    <label class="form__label form__label--floating" for="message">Message</label>
                </p>
                <p class="form__group">
                    <button type="submit" class="form__button form__button--filled">Gift</button>
                    <button type="button" class="form__button form__button--outlined">Cancel</button>
                </p>
            </form>
        </dialog>`;

        // Create a container <div> if one does not exist
        let container = document.querySelector('#dialog-container');
        if (!container) {
            container = document.createElement('div');
            container.id = 'dialog-container';
            document.body.appendChild(container);
        }

        // Add dialog HTML to the container
        container.innerHTML = dialogHTML;

        // Add styling for the backdrop
        const style = document.createElement('style');
        style.innerHTML = `
        dialog::backdrop {
            background-color: rgba(0, 0, 0, 0.8);
        }`;
        document.head.appendChild(style);

        // Get the dialog element and show it
        const dialog = container.querySelector('dialog');
        dialog.showModal();

        // Add event listener to the "Cancel" button to remove the dialog
        const cancelButton = dialog.querySelector('button[type="button"]');
        if (cancelButton) {
            cancelButton.addEventListener('click', removeDialog);
        }
    }

    function setupReplyFeatures(chatMessages) {
        //Please do not alter this, It is for contributors to the project only.
        const USER_COLORS = {
    'ace': '#ef008c',
    'TheoneandonlyPook': '#ef008c',
    'Demonic': '#ffac6b'

    // Add more users and colors as needed
};

        const newMessageTextArea = document.querySelector(chatboxID);

function rgbToHex(rgb) {
    // Convert RGB to HEX format
    const rgbArray = rgb.match(/\d+/g).map(Number);
    if (rgbArray.length === 3) {
        return `#${rgbArray.map(value => {
            const hex = value.toString(16).padStart(2, '0');
            return hex;
        }).join('')}`;
    }
    return rgb; // Return original if not in expected format
}

function quoteMessage(username, message) {
    const chatbox = document.querySelector(chatboxID);
    if (!chatbox) {
        console.error(`Chatbox not found: ${chatboxID}`);
        return;
    }

    // Default color if user is not found in USER_COLORS
    let userColor = '#ecc846'; // Default color

    // Check USER_COLORS first
    if (USER_COLORS.hasOwnProperty(username)) {
        userColor = USER_COLORS[username];
    } else {

        // If not in USER_COLORS, extract the color from the chat messages
        const messages = document.querySelectorAll('.chatbox-message, .message');
        for (const msg of messages) {
            const msgUsername = msg.querySelector(".chatbox-message__address.user-tag span, .message-username span");
            if (msgUsername && msgUsername.textContent.trim() === username) {
                const style = window.getComputedStyle(msgUsername);
                userColor = rgbToHex(style.color);
                break; // Stop searching once the user is found
            }
        }
    }

    // Debugging
    console.log(`Username: ${username}, Color used: ${userColor}`);

    // Create the quoted message
    const quoteText = `[color=${userColor}][b]${username}[/b][/color]: [color=#ffff80][i]"${message}"[/i][/color]`;

    // Append the quoted message to the chat input
    chatbox.value += `${quoteText}\n\n`;
    chatbox.focus();
    chatbox.setSelectionRange(chatbox.value.length, chatbox.value.length);
}

        function addReplyIconToMessage(message) {
            const content = message.querySelector(".chatbox-message__content")?.innerText || message.querySelector(".message-content")?.innerText;
            const username = message.querySelector(".chatbox-message__address.user-tag span")?.innerText || message.querySelector(".message-username span")?.innerText;
            const header = message.querySelector(".chatbox-message__header") || message.querySelector(".message-header");
            if (!content || !username || !header) return;
            const replyIcon = document.createElement("i");
            replyIcon.classList.add("fa", "solid", "fa-reply", "reply-icon");
            replyIcon.style.color = "#d82c20";
            replyIcon.addEventListener("click", () => quoteMessage(username, content));
            const messageIcon = document.createElement("i");
            messageIcon.classList.add("fa", "solid", "fa-envelope", "message-icon");
            messageIcon.style.color = "#118DFF";
            const giftIcon = document.createElement("i");
            giftIcon.classList.add("fa", "solid", "fa-gift", "gift-icon");
            giftIcon.style.color = "#f3c911";
            messageIcon.addEventListener("click", () => {
                newMessageTextArea.value += `/msg ${username} `;
                newMessageTextArea.focus();
            });
            giftIcon.addEventListener("click", () => {
                const token = extractToken();
                const user = extractUser();
                addDialog(token, user, username);
            });
            header.appendChild(replyIcon);
            header.appendChild(messageIcon);
            header.appendChild(giftIcon);
            applySettings();
        }
        document.querySelectorAll(".chatbox-message, .message").forEach(addReplyIconToMessage);
        const observer = new MutationObserver(function(mutationsList, observer) {
            document.querySelectorAll(".reply-icon, .message-icon, .gift-icon").forEach((icon) => icon.remove());
            document.querySelectorAll(".chatbox-message, .message").forEach(addReplyIconToMessage);
        });
        observer.observe(chatMessages, { childList: true });
    }
    function setupChatFeatures(chatbox) {
    const container = document.createElement('div');
    container.style.position = 'relative';
    container.style.display = 'inline-flex';
    chatbox.parentNode.insertBefore(container, chatbox.nextSibling);
    const bbCodesPanel = document.createElement('div');
    bbCodesPanel.innerHTML = BBCODES_PANEL_HTML;
    container.appendChild(bbCodesPanel);
    bbCodesPanel.style.background = 'transparent';
    bbCodesPanel.style.border = 'none';

    // BBCode Dropdown
    const bbCodeDropdown = document.getElementById('bbCodeDropdown');
    const bbCodeDropdownMenu = document.getElementById('bbCodeDropdownMenu');
    bbCodeDropdown.addEventListener('click', function() {
        bbCodeDropdownMenu.style.display = bbCodeDropdownMenu.style.display === 'flex' ? 'none' : 'flex';
    });

    // Emoji Button
    const emojiButton = document.getElementById('emojiButton');
    const emojiMenu = document.getElementById('emojiMenu');
    emojiButton.addEventListener('click', function() {
        emojiMenu.style.display = emojiMenu.style.display === 'block' ? 'none' : 'block';
    });

    // Emoji Menu
    emojiMenu.addEventListener('click', function(event) {
        if (event.target.classList.contains('emoji')) {
            const emoji = event.target.getAttribute('data-emoji');
            insertEmoji(emoji, chatbox);
            emojiMenu.style.display = 'none'; // Hide menu after selection
        }
    });

    // BBCode Buttons
    bbCodesPanel.querySelectorAll('span').forEach(function(span) {
        span.addEventListener('click', function() {
            const bbCode = span.getAttribute('data-bbcode');
            if (bbCode === "[img][/img]") {
                insertImgBBCodeWithClipboard(bbCode, chatbox);
            } else if (bbCode === "[url][/url]") {
                insertBBCodeWithClipboard(bbCode, chatbox);
            } else if (span.id === 'colorButton') {
                document.getElementById('colorPicker').style.display = 'block'; // Show color picker
            } else {
                insertBBCode(chatbox, bbCode);
            }
        });
    });

    // Color Picker
    document.getElementById('colorPicker').addEventListener('input', function(event) {
        const color = event.target.value;
        const colorBBCode = `[color=${color}][/color]`;
        chatbox.value += colorBBCode + " ";
        const pos = chatbox.value.length;
        chatbox.setSelectionRange(pos, pos);
        chatbox.focus();
        document.getElementById('colorPicker').style.display = 'none'; // Hide color picker after selection
    });

    setupMentionFeature(chatbox);
}

function insertEmoji(emoji, chatbox) {
    const pos = chatbox.selectionStart;
    chatbox.value = chatbox.value.substring(0, pos) + emoji + chatbox.value.substring(pos);
    chatbox.setSelectionRange(pos + emoji.length, pos + emoji.length);
    chatbox.focus();
}

    function insertBBCodeWithClipboard(tag, chatbox) {
        navigator.clipboard.readText().then(clipText => {
            const newContent = clipText.trim().length > 0
                ? tag.replace(/(\[.*?\])(.*?)(\[\/.*?\])/, `$1${clipText}$3`)
                : tag.replace(/(\[.*?\])(.*?)(\[\/.*?\])/, `$1$2$3`);
            chatbox.value += newContent + " ";
            const pos = chatbox.value.length;
            chatbox.setSelectionRange(pos, pos);
            chatbox.focus();
        }).catch((err) => {
            console.error('Failed to read clipboard contents:', err);
            chatbox.value += tag.replace(/(\[.*?\])(.*?)(\[\/.*?\])/, `$1$2$3`) + " ";
            const pos = chatbox.value.length;
            chatbox.setSelectionRange(pos, pos);
            chatbox.focus();
        });
    }
    function insertImgBBCodeWithClipboard(tag, chatbox) {
        navigator.clipboard.readText().then(clipText => {
            const newContent = clipText.trim().length > 0
                ? tag.replace(/(\[.*?\])(.*?)(\[\/.*?\])/, `$1${clipText}$3`)
                : tag.replace(/(\[.*?\])(.*?)(\[\/.*?\])/, `$1$2$3`);
            chatbox.value += newContent + "\n";
            const pos = chatbox.value.length;
            chatbox.setSelectionRange(pos, pos);
            chatbox.focus();
        }).catch((err) => {
            console.error('Failed to read clipboard contents:', err);
            chatbox.value += tag.replace(/(\[.*?\])(.*?)(\[\/.*?\])/, `$1$2$3`) + "\n";
            const pos = chatbox.value.length;
            chatbox.setSelectionRange(pos, pos);
            chatbox.focus();
        });
    }
    function insertBBCode(chatbox, bbCode) {
        const textSelected = chatbox.value.substring(chatbox.selectionStart, chatbox.selectionEnd);
        const startTag = bbCode.substring(0, bbCode.indexOf(']') + 1);
        const endTag = bbCode.substring(bbCode.lastIndexOf('['));
        if (textSelected.length > 0) {
            const newText = startTag + textSelected + endTag;
            chatbox.value = chatbox.value.substring(0, chatbox.selectionStart) + newText + " " + chatbox.value.substring(chatbox.selectionEnd);
            const newPos = chatbox.value.lastIndexOf(' ') + 1;
            chatbox.setSelectionRange(newPos, newPos);
        } else {
            const pos = chatbox.selectionStart + startTag.length;
            chatbox.value += startTag + endTag + " ";
            chatbox.setSelectionRange(pos, pos);
        }
        chatbox.focus();
    }
function setupSettingsPanel() {
    const chatboxHeaderActions = document.querySelector('#chatbox_header .panel__actions');
    if (chatboxHeaderActions) {
        chatboxHeaderActions.insertAdjacentHTML('beforeend', TOGGLE_BUTTON_HTML);
        const settingsPanel = document.createElement('div');
        settingsPanel.innerHTML = `
            <div id="${settingsPanelID}" style="display: none; position: absolute; top: 30px; right: 0; background: rgba(0,0,0,0.9); border-radius: 8px; padding: 10px; color: white; z-index: 10001;">
                <label><input type="checkbox" id="toggleBBCodes" checked> Show BB Codes</label><br>
                <label><input type="checkbox" id="toggleMessageGift" checked> Show Message/Gift Buttons</label><br>
                <label><input type="checkbox" id="toggleReply" checked> Show Reply Button</label>
            </div>`;
        chatboxHeaderActions.appendChild(settingsPanel);
        const toggleSettingsButton = document.getElementById(settingsButtonID);
        const settingsPanelElement = document.getElementById(settingsPanelID);
        toggleSettingsButton.addEventListener('click', (event) => {
            event.stopPropagation(); // Prevent event from bubbling up
            const isPanelVisible = settingsPanelElement.style.display === 'block';
            settingsPanelElement.style.display = isPanelVisible ? 'none' : 'block';
        });
        document.addEventListener('click', (event) => {
            if (!settingsPanelElement.contains(event.target) && !toggleSettingsButton.contains(event.target)) {
                settingsPanelElement.style.display = 'none'; // Hide when clicking outside
            }
        });
        applySettings();
        setupSettingsListeners();
    } else {
        console.error("Failed to attach the settings button: '#chatbox_header .panel__actions' not found.");
    }
}
    function checkAndSetup() {
        const chatbox = document.querySelector(chatboxID);
        const chatMessages = document.querySelector(chatMessagesClassName);
        if (chatbox) {
            setupChatFeatures(chatbox);
            setupSettingsPanel();
        } else {
            console.error('Chatbox not found: Ensure the chatbox ID is correct.');
        }
        if (chatMessages) {
            setupReplyFeatures(chatMessages);
        } else {
            console.error('Chat messages not found: Ensure the chatMessages class is correct.');
        }
        if (!chatbox || !chatMessages) {
            setTimeout(checkAndSetup, 1000);
        }

    }

    checkAndSetup();

})();