Themes - Bonk.io

Recolors elements in Bonk.io to customizable colors, and allows toggling your theme with a hotkey

目前为 2021-11-23 提交的版本。查看 最新版本

作者
Excigma
评分
0 0 0
版本
0.1.3
创建于
2021-11-20
更新于
2021-11-23
大小
33.0 KB
许可证
GPL-3.0
适用于

// ==UserScript== // @name Themes - Bonk.io // @description Recolors elements in Bonk.io to customizable colors, and allows toggling your theme with a hotkey // @author Excigma // @namespace https://gf.qytechs.cn/users/416480 // @license GPL-3.0 // @version 0.1.3 // @match https://bonk.io/* // @grant GM_addStyle // @grant GM_registerMenuCommand // @grant unsafeWindow // @run-at document-start // ==/UserScript==

(() => { const configuration_metadata_map = { hotkey: { default: "d", description: "Hotkey used to toggle the theme on and off\n(Ctrl + Alt + )", datatype: "char" }, colored_text: { default: "#40c99e", description: "Text color of custom games with friends online in the room, and 'Added by' in picks", datatype: "color" }, primary_text: { default: "#f8fafd", description: "Primary text color", datatype: "color" }, secondary_text: { default: "#bebebe", description: "Secondary text color\nNote: Some of the texts are lightened by 'brightness_lighter' above\nthis will have no affect on such texts (Eg: Chat usernames)", datatype: "color" }, window_color: { default: "#2b6351", description: "Color of window titles\n(Eg: Custom games, Leave Game, Chat, Level Select, ...)", datatype: "color" }, page_background: { default: "#111111", description: "Used for the main page's background", datatype: "color" }, primary_background: { default: "#222222", description: "Used as the main background color of windows\n(Eg: Chat background, Leave lobby background, Login page)", datatype: "color" }, secondary_background: { default: "#333333", description: "Secondary background color for things inside windows\n(Eg: Auto login, Joining room status text, Map Editor inputs, ...)", datatype: "color" }, behind_lobby_background: { default: "#131313", description: "Color for the Lobby's background\n(Eg: Behind the Lobby and Map Editor)", datatype: "color" }, red_text: { default: "#e14747", description: "Used for player nerf indicator in the lobby", datatype: "color" }, blue_text: { default: "#179be8", description: "Used for [Load] when a map is suggested, and Copy link is clicked", datatype: "color" }, green_text: { default: "#17e88b", description: "Used for player buff and in chat friend requests", datatype: "color" }, purple_text: { default: "#8f68e8", description: "Used for output of /curate", datatype: "color" }, magenta_text: { default: "#d23cfb", description: "Used for when [Load] is clicked, or when you are now the host of the game", datatype: "color" }, button_color: { default: "#4f382f", description: "Button/dropdown color", datatype: "color" }, hover_button_color: { default: "#3a2a24", description: "Button/dropdown hover color", datatype: "color" }, active_button_color: { default: "#362620", description: "Button/dropdown click color", datatype: "color" }, disabled_button_color: { default: "#444444", description: "Button/dropdown disabled color", datatype: "color" }, button_text: { default: "#f8fafd", description: "Button/dropdown text color", datatype: "color" }, xp_bar_fill: { default: "#2b6351", description: "XP bar fill color at the top of your screen whilst in-game", datatype: "color" }, top_bar_opacity: { default: 0.8, description: "Opacity of the 'top bar' that contains your:\nSkin, Username, Level, Volume Settings, ...", datatype: "percentage" }, top_bar_color: { default: "#333333", description: "Color of the 'top bar'\nMake sure this value is dark, the icon colors are white and can't really be easily changed", datatype: "color" }, top_bar_hover_color: { default: "#222222", description: "Color of buttons in the 'top bar' then hovered", datatype: "color" }, top_bar_text: { default: "#bebebe", description: "Color of text in the 'top bar'", datatype: "color" }, football_background: { default: "#161616", description: "Color for the Football gamemode's background\n(Note: Requires restarting the football to apply)\nWarning: Unstable, experimental", datatype: "color" }, mini_menu_color: { default: "#191919", description: "Used for Tooltips and 'Filter by' in Custom Games", datatype: "color" }, mini_menu_text: { default: "#bebebe", description: "Used for Tooltips and 'Filter by' in Custom Games", datatype: "color" }, scrollbar_background: { default: "#191919", description: "Used for the scrollbar's background (Chromium only)", datatype: "color" }, scrollbar_thumb: { default: "#555555", description: "Used for the scrollbar's thumb - which is the thing you drag (Chromium only)", datatype: "color" }, list_headers: { default: "#2b3839", description: "Used for the colors of lists\n(Eg: Friends list and the sections in the Map Editor, ...)", datatype: "color" }, table_color: { default: "#444444", description: "Stripe color for use in tables\n(Eg: Custom games, Friends list, Map Editor, Skin Editor, ...)", datatype: "color" }, table_alt_color: { default: "#333333", description: "Alternative stripe color used in tables", datatype: "color" }, table_hover_color: { default: "#222222", description: "Color used when a row in a table is hovered", datatype: "color" }, table_active_color: { default: "#111111", description: "Color used when a row in a table is selected", datatype: "color" }, brightness_lighter: { default: 2.5, description: "Used to lighten text that have bad contrast with dark colors\nNote: Change to 1 if making a light theme\n(0.5 = 50%, 1.5 = 150% brightness)", datatype: "brightness" }, brightness_darker: { default: 0.5, description: "Used to darken images that that are too bright\nNote: Change to 1 if making a light theme\n(0.5 = 50%, 1.5 = 150% brightness)", datatype: "brightness" }, description_invert: { default: 1, description: "How much to invert description at the bottom of the page by\n(Value from 0 to 1, Don't use 0.5)", datatype: "percentage" }, };

const datatype_metadata_map = {
    "color": {
        value: "value",
        attributes: {
            type: "color"
        }
    },
    "percentage": {
        value: "value",
        attributes: {
            type: "number",
            max: 1,
            min: 0,
            step: 0.01
        }
    },
    "brightness": {
        value: "value",
        attributes: {
            type: "number",
            max: 10,
            min: 0,
            step: 0.05
        }
    },
    "char": {
        value: "value",
        attributes: { 
            type: "text" ,
            maxLength: 1 
        }
    },
};

const default_configuration = {};
for (const [key, value] of Object.entries(configuration_metadata_map)) 
    default_configuration[key] = value.default;

// If running inside maingameframe, inject our injectors
if (unsafeWindow.parent !== unsafeWindow) {
    unsafeWindow.bonk_theme = {
        on: true,
        get_football_background: () => parseInt(getComputedStyle(document.documentElement)
            .getPropertyValue("--bonk_theme_football_background").trim().slice(1), 16)
    };

    // Injector for football mode, if it doesn't work, ...well football will be bright
    if (!unsafeWindow.bonkCodeInjectors) unsafeWindow.bonkCodeInjectors = [];
    unsafeWindow.bonkCodeInjectors.push(bonkCode => {
        try {
            // Default football background color, not used elsewhere (yet?)
            const FOOTBALL_BACKGROUND_COLOR = "0x5a7f64";
            let newBonkCode = bonkCode;
            newBonkCode = newBonkCode
                .replace(
                    FOOTBALL_BACKGROUND_COLOR,
                    `(window.bonk_theme.on ? window.bonk_theme.get_football_background() : ${FOOTBALL_BACKGROUND_COLOR})`
                );
            if (bonkCode === newBonkCode) throw "[Themes] Injection failed!";

            console.log("Themes injector run");
            return newBonkCode;
        } catch (er) {
            // Silently ignore errors, only football's background will be affected
            console.log("[Themes] Failed to inject");
            console.error(er);
            return bonkCode;
        }
    });
}

document.addEventListener("DOMContentLoaded", () => {
    document.body.classList.add("themed-colors");
    // Get the currently applied theme
    const get_stored_theme = () => {
    // Get the stored theme, if it doesn't exist, it will be null
        let stored_theme = localStorage.getItem("bonk_theme");
        try {
            stored_theme = JSON.parse(stored_theme);
        } catch (er) {
        // If the stored theme is somehow corrupted - use blank theme
            console.log("[Themes] Failed to load theme from localstorage");
            console.log(`[Themes] ${stored_theme}`);
            console.error(er);
            alert("Failed to load theme from localstorage");
            stored_theme = {};
        }
        // Merge the stored theme with the default (if null, it will overwrite)
        return {...default_configuration, ...stored_theme};
    };

    // Get the stored theme when the page loads
    const configuration = get_stored_theme();

    // Check if the script is running inside maingameframe or not
    if (unsafeWindow.parent === unsafeWindow) {
        // Outer bonk.io website
        // Hotkey to turn the script on and off
        const maingameframe = document.getElementById("maingameframe");
        document.addEventListener("keydown", evt => {
            if (evt.key?.toLowerCase() === configuration.key && evt.ctrlKey && evt.altKey) {            
                document.body.classList.toggle("themed-colors");
                maingameframe.contentDocument.body.classList.toggle("themed-colors");
                maingameframe.contentWindow.bonk_theme.on = !maingameframe.contentWindow.bonk_theme.on;
            }
        });

        // Flag to check whether the theme container already exists
        let theme_container_created = false;
        // Create the menu only when someone clicks on the thing in the menu
        // Show the theme container when you click the menu command thing
        // eslint-disable-next-line no-undef
        GM_registerMenuCommand("Edit theme", () => {
            // Creating a new theme_container, don't make new ones after this
            if (theme_container_created) return document.getElementById("theme_container").style.display = "block";
            theme_container_created = true;

            // Create the theme menu. This is really ugly but there's like no other way idk.
            const theme_container = document.createElement("div");
            const theme_container_title = document.createElement("p");
            const configuration_container = document.createElement("div");
            const configuration_list = document.createElement("div");
            const configuration_json = document.createElement("textarea");
            const configuration_json_label = document.createElement("label");
            const theme_cancel = document.createElement("div");
            const theme_save = document.createElement("div");
            const theme_reset = document.createElement("div");

            // Add the IDs so we can style them with CSS
            theme_container_title.id = "theme_container_title";
            theme_container.id = "theme_container";
            configuration_list.id = "configuration_list";
            configuration_json.id = "configuration_json";
            theme_cancel.id = "theme_cancel";
            theme_save.id = "theme_save";
            theme_reset.id = "theme_reset";

            // Add the classes
            theme_container_title.classList.add("classicTopBar");
            theme_cancel.classList.add("brownButton", "brownButton_classic", "buttonShadow");
            theme_save.classList.add("brownButton", "brownButton_classic", "buttonShadow");
            theme_reset.classList.add("brownButton", "brownButton_classic", "buttonShadow");

            // Add text to buttons and titles
            theme_container_title.textContent = "Theme Editor";
            theme_cancel.textContent = "CANCEL";
            theme_save.textContent = "SAVE";
            theme_reset.textContent = "RESET";
            configuration_json_label.textContent = "Share, Backup or Import theme data - Copy or paste into the textbox";
            configuration_json_label.for = "configuration_json";
            configuration_json.value = JSON.stringify(configuration);

            theme_container.appendChild(theme_container_title);

            // Populate the themes list with the theme that is currently loaded
            for (const [key, value] of Object.entries(configuration)) {
            // Check if the setting exists
                if (!configuration_metadata_map[key]) continue;
                const datatype_metadata = datatype_metadata_map[configuration_metadata_map[key].datatype];
                const configuration_container = document.createElement("div");
                const configuration_name = document.createElement("p");
                const configuration_value = document.createElement("input");

                configuration_container.classList.add("configuration_container");
                configuration_name.classList.add("configuration_name");
                configuration_value.classList.add("configuration_value");

                configuration_container.dataset["configuration_name"] = key;
                configuration_container.title = configuration_metadata_map[key].description ?? "No description";
                configuration_name.textContent = key.replace(/_/g, " ");

                for (const [key, value] of Object.entries(datatype_metadata.attributes))
                    configuration_value[key] = value;
                configuration_value[datatype_metadata.value] = value;
                // Using "oninput" instead of addEventListener so we can call it somewhere else
                configuration_value.oninput = () => {
                    if (!datatype_metadata.ignore_change) {
                    // Update the CSS variable on both bonk.io and maingameframe
                        document.documentElement.style
                            .setProperty(`--bonk_theme_${key}`, configuration_value.value);
                        maingameframe.contentDocument.documentElement.style
                            .setProperty(`--bonk_theme_${key}`, configuration_value.value);
                        // Store it in the current configuration (so it can be saved later)
                        configuration[key] = configuration_value[datatype_metadata.value];
                    }

                    // Update the data at the bottom
                    configuration_json.value = JSON.stringify(configuration);
                };

                // Add the current config to the list of settings
                configuration_container.appendChild(configuration_name);
                configuration_container.appendChild(configuration_value);
                configuration_list.appendChild(configuration_container);
            }

            // Add the Save and Cancel buttons
            configuration_container.appendChild(theme_cancel);
            configuration_container.appendChild(theme_save);

            configuration_list.appendChild(document.createElement("br"));
            configuration_list.appendChild(configuration_container);
            configuration_list.appendChild(document.createElement("br"));
            configuration_list.appendChild(configuration_json_label);
            configuration_list.appendChild(configuration_json);
            configuration_list.appendChild(document.createElement("br"));
            configuration_list.appendChild(theme_reset);
            theme_container.appendChild(configuration_list);

            // When save is clicked, try save theme to localstorage
            theme_save.addEventListener("click", () => {
                try {
                    localStorage.setItem("bonk_theme", JSON.stringify(configuration));
                    theme_container.style.display = "none";
                } catch (er) {
                    console.log("[Themes] Failed to save theme to localstorage");
                    console.log(`[Themes] ${JSON.stringify(configuration)}`);
                    console.error(er);
                    alert("Failed to save theme to localstorage");
                }
            });

            // Reset the state of configuration from localstorage
            theme_cancel.addEventListener("click", () => {
                configuration_json.value = JSON.stringify(get_stored_theme());
                configuration_json.oninput();
                theme_container.style.display = "none";
            });

            // Get the currently saved theme, and overwrite everything with it
            theme_reset.addEventListener("click", () => {
                configuration_json.value = JSON.stringify(default_configuration);
                configuration_json.oninput();
            });

            configuration_json.oninput = () => {
                try {
                    const new_theme = JSON.parse(configuration_json.value);
                    // Update the configurations
                    const configuration_list_children = Array.from(configuration_list.children);
                    for (const configuration_container of configuration_list_children) {
                        const key = configuration_container.dataset["configuration_name"];
                        const value = new_theme[key];
                        if (!value) continue;

                        const configuration_value = configuration_container.querySelector("input");
                        const datatype_meta = datatype_metadata_map[configuration_metadata_map[key].datatype];

                        configuration_value[datatype_meta.value] = value;
                        configuration_value.oninput();
                    }

                    // If success, remove the border
                    configuration_json.style.setProperty("border", "none");
                } catch (er) {
                    console.log("[Themes] Failed to load theme from <textarea>");
                    console.log(`[Themes] ${configuration_json.value}`);
                    console.error(er);
                    // If there is an error, set a red border
                    configuration_json.style.setProperty("border", "3px solid var(--bonk_theme_red)", "important");
                }
            };

            // Add the theme dialog to body
            document.body.appendChild(theme_container);
        });
    } else {
        // This code is for inside maingameframe
        // Hotkey to turn the script on and off
        document.addEventListener("keydown", evt => {
            if (evt.key?.toLowerCase() === configuration.key && evt.ctrlKey && evt.altKey) {
                unsafeWindow.bonk_theme.on = !unsafeWindow.bonk_theme.on;
                document.body.classList.toggle("themed-colors");
                unsafeWindow.parent.document.body.classList.toggle("themed-colors");
            }
        });
    }

    // List of default CSS variables
    let root_vars = [];
    for (const [key, value] of Object.entries(configuration))
        root_vars.push(`--bonk_theme_${key}: ${value};`);

    // eslint-disable-next-line no-undef
    GM_addStyle(`
/* CSS Variables, so we can edit their values on the fly */
:root {
    ${root_vars.join("\n        ")}
    --kkleeMultiSelectColour: ${configuration.colored_text} !important;
    --kkleeErrorColour: ${configuration.red_text} !important;
    --kkleeCheckboxTfsTrue: ${configuration.green_text} !important;
    --kkleeCheckboxTfsFalse: ${configuration.red_text} !important;
}

/* Page background color */
.themed-colors #pagecontainer,
body.themed-colors { 
    background-color: var(--bonk_theme_page_background) !important;
}

/* Dark scroll bar tracks on Firefox and Chromium-based browsers */
.themed-colors {
    scrollbar-color: var(--bonk_theme_scrollbar_thumb) var(--bonk_theme_scrollbar_background) !important;
}

.themed-colors ::-webkit-scrollbar-track {
    background-color: var(--bonk_theme_scrollbar_background) !important;
}

.themed-colors ::-webkit-scrollbar-thumb { 
    background-color: var(--bonk_theme_scrollbar_thumb) !important;
}

/* Color tooltips */
.themed-colors #friendsToolTip,
.themed-colors #pretty_top_replay_report_tooltip,
.themed-colors #pretty_top_replay_fav_tooltip,
.themed-colors #newbonklobby_tooltip,
.themed-colors #mapeditor_rightbox_shapeaddmenucontainer,
.themed-colors #mapeditor_leftbox_createmenucontainerleft,
.themed-colors #mapeditor_leftbox_createmenucontainerright,
.themed-colors #mapeditor_leftbox_copywindow,
.themed-colors #mapeditor_rightbox_newjointmenu,
.themed-colors .newbonklobby_playerentry_menu,
.themed-colors .newbonklobby_playerentry_menu_submenu {
    background-color: var(--bonk_theme_mini_menu_color) !important;
    color: var(--bonk_theme_mini_menu_text) !important;
}

/* Color the lobby's background */
.themed-colors #bonkiocontainer {
    background-color: var(--bonk_theme_behind_lobby_background) !important;
}

/* Dialogs - I can just do windowShadow, but it might break things if new things are added */
/* It's better to have a new thing visibly light rather than broken */
.themed-colors .bt-primary-background,
.themed-colors #autoLoginContainer,
.themed-colors #guestOrAccountContainer_accountBox,
.themed-colors #guestOrAccountContainer_guestBox,
.themed-colors #guestContainer, 
.themed-colors .accountContainer,
.themed-colors #registerwindow_remember_label,
.themed-colors #loginwindow_remember_label,
.themed-colors #loginwindow,
.themed-colors #registerwindow,
.themed-colors #settingsContainer,
.themed-colors .settingsHeading,
.themed-colors .redefineControls_selectionCell:hover,
.themed-colors #newswindow,
.themed-colors #skinmanager,
.themed-colors .skineditor_shapewindow,
.themed-colors .skineditor_shapewindow_imagecontainer,
.themed-colors #skineditor_propertiesbox,
.themed-colors #skineditor_propertiesbox_table,
.themed-colors #skineditor_previewbox,
.themed-colors #skineditor_layerbox,
.themed-colors #skineditor_layerbox_baselabel,
.themed-colors #quickPlayWindow,
.themed-colors #roomlistcreatewindow,
.themed-colors .roomlistcreatewindowlabel,
.themed-colors #roomlistjoinpasswordwindow,
.themed-colors #sm_connectingWindow,
.themed-colors #newbonklobby_specbox,
.themed-colors #newbonklobby_playerbox,
.themed-colors #newbonklobby_chatbox,
.themed-colors #newbonklobby_settingsbox,
.themed-colors #newbonklobby_votewindow,
.themed-colors #newbonklobby_votewindow_maptitle,
.themed-colors #newbonklobby_votewindow_mapauthor,
.themed-colors #leaveconfirmwindow,
.themed-colors #leaveconfirmwindow_text2,
.themed-colors #hostleaveconfirmwindow,
.themed-colors #hostleaveconfirmwindow_text2,
.themed-colors #maploadwindow,
.themed-colors #maploadwindowgreybar,
.themed-colors #maploadwindowstatustext,
.themed-colors #mapeditor_leftbox,
.themed-colors #mapeditor_midbox,
.themed-colors #mapeditor_rightbox,
.themed-colors #mapeditor_save_window,
.themed-colors #kkleeRoot,
.themed-colors #skineditor_colorpicker,
.themed-colors #mapeditor_colorpicker,
.themed-colors #friendsSendWindow,
.themed-colors #roomlistfilterwindow,
.themed-colors #ingamecountdown,
.themed-colors #mapeditor_save_overwrite_window,
#theme_container {
    background-color: var(--bonk_theme_primary_background) !important;
    color: var(--bonk_theme_primary_text) !important;
}

/* Lighter backgrounds for some menus and stuff */
.themed-colors .bt-secondary-background,
.themed-colors #bonkioheader,
.themed-colors .windowTopBar_classic,
.themed-colors #autoLogin_text,
.themed-colors .guestOrAccountContainerLabelBox,
.themed-colors #guest_nametext,
.themed-colors #loginwindow_username,
.themed-colors #loginwindow_password,
.themed-colors #registerwindow_username,
.themed-colors #registerwindow_password,
.themed-colors #guest_skinbox,
.themed-colors #skineditor_propertiesbox_blocker,
.themed-colors #newswindow_white,
.themed-colors .quickPlayWindowModeDiv,
.themed-colors .quickPlayWindowText1,
.themed-colors .quickPlayWindowText2,
.themed-colors .quickPlayWindowText3,
.themed-colors #roomlist,
.themed-colors #roomlisttableheadercontainer,
.themed-colors .roomlistcreatewindowinput,
.themed-colors .whiteInputField,
.themed-colors #sm_connectingWindow_text,
.themed-colors #friendsContainer,
.themed-colors .friends_table,
.themed-colors .skinmanager_icon,
.themed-colors #maploadwindowsearchinput,
.themed-colors .maploadwindowmapdiv,
.themed-colors #mapeditor_midbox_explain,
.themed-colors #mapeditor_rightbox_namefield,
.configuration_value,
#configuration_json {
    border-color: transparent !important;
    background-color: var(--bonk_theme_secondary_background) !important;
    color: var(--bonk_theme_primary_text) !important;
}

.themed-colors .mapeditor_field,
.themed-colors .skineditor_field,
.themed-colors .mapeditor_rightbox_table_shape_headerfield {
    border-color: transparent;
    background-color: var(--bonk_theme_secondary_background);
    color: var(--bonk_theme_primary_text);
}

.themed-colors .newbonklobby_playerentry_name,
.themed-colors #newbonklobby_modetext,
.themed-colors #newbonklobby_roundslabel,
.themed-colors .maploadwindowtext,
.themed-colors #roomliststatustext, 
.themed-colors #roomlisttable,
.themed-colors .mapeditor_rightbox_table_leftcell,
.themed-colors .mapeditor_rightbox_table_rightcell,
.themed-colors #ingamecountdown_text,
.themed-colors #roomlisthidepasswordedcheckboxlabel,
.themed-colors #bonkiobugemail {
    color: var(--bonk_theme_primary_text) !important;
}

.themed-colors .newbonklobby_mapsuggest_high,
.themed-colors .maploadwindowtext_picks,
.themed-colors .newbonklobby_chat_msg_name,
.themed-colors .newbonklobby_playerentry_balancetext {
    color: var(--bonk_theme_primary_text);
}

.themed-colors .newbonklobby_playerentry_level,
.themed-colors .newbonklobby_playerentry_pingtext, 
.themed-colors #newbonklobby_chat_lowerinstruction,
.themed-colors #newbonklobby_chat_lowerline, 
.themed-colors .newbonklobby_chat_msg_txt,
.themed-colors #newbonklobby_chat_input,
.themed-colors #newbonklobby_maptext,
.themed-colors #newbonklobby_roundsinput,
.themed-colors #newbonklobby_mapauthortext,
.themed-colors #newbonklobby_votewindow_maptitle_by,
.themed-colors #hostleaveconfirmwindow_text1,
.themed-colors #leaveconfirmwindow_text1,
.themed-colors .maploadwindowtextmode_picks,
.themed-colors .maploadwindowtextmode,
.themed-colors .maploadwindowtextauthor,
.themed-colors .maploadwindowtextauthor_picks,
.themed-colors .roomlisttablejoined {
    color: var(--bonk_theme_secondary_text) !important;
}

/* Lobby chat */
.themed-colors .newbonklobby_mapsuggest_low {
    color: var(--bonk_theme_secondary_text);
}

/* Copy link */
.themed-colors #newbonklobby_chat_content span[style="color: rgb(9, 85, 199);"],
.themed-colors .newbonklobby_chat_link {
    color: var(--bonk_theme_blue_text) !important;
}

/* /help, player join */
.themed-colors .newbonklobby_playerentry_balance_nerf,
.themed-colors #newbonklobby_chat_content span[style="color: rgb(204, 68, 68);"],
.themed-colors #newbonklobby_chat_content span[style="color: rgb(204, 51, 51);"],
.themed-colors #newbonklobby_chat_content span[style="color: rgb(255, 0, 0);"] {
    color: var(--bonk_theme_red_text) !important;
}

/* Friend requests */
.themed-colors .newbonklobby_playerentry_balance_buff,
.themed-colors #newbonklobby_chat_content span[style="color: rgb(0, 103, 93);"] {
    color: var(--bonk_theme_green_text) !important;
}

/* /curate */
.themed-colors #newbonklobby_chat_content span[style="color: rgb(96, 51, 204);"] {
    color: var(--bonk_theme_purple_text) !important;
}

/* "You are now host" */
.themed-colors #newbonklobby_chat_content span[style="color: rgb(122, 25, 154);"],
.themed-colors #newbonklobby_chat_content span[style="color: rgb(128, 13, 110);"] {
    color: var(--bonk_theme_magenta_text) !important;
}

.themed-colors .newbonklobby_chat_status:not([style]) {
    filter: brightness(var(--bonk_theme_brightness_lighter)) !important;
}

.themed-colors #descriptioncontainer,
.themed-colors #gamethumbbox,
.themed-colors #bgreplay {
    filter: brightness(var(--bonk_theme_brightness_darker)) !important;
}

/* Style sliders and buttons */
.themed-colors .compactSlider {
    background-color: transparent !important;
    color: var(--bonk_theme_button_text) !important;
}

.themed-colors .brownButton_classic,
.themed-colors .dropdown_classic,
.themed-colors .skineditor_field_button,
.themed-colors .mapeditor_field_button,
#theme_save, #theme_cancel, #theme_reset {
    border-color: transparent !important;
    background-color: var(--bonk_theme_button_color) !important;
    color: var(--bonk_theme_button_text) !important;
}

.themed-colors .brownButtonDisabled,
.themed-colors .brownButton_disabled_classic,
.themed-colors .dropdown-option-disabled {
    background-color: var(--bonk_theme_disabled_button_color) !important;
    color: var(--bonk_theme_button_text) !important;
}

.themed-colors .brownButton_classic:hover,
.themed-colors .dropdown_classic:hover,
#theme_save:hover, #theme_cancel:hover, #theme_reset:hover {
    background-color: var(--bonk_theme_hover_button_color) !important;
    color: var(--bonk_theme_button_text) !important;
}

.themed-colors .brownButton_classic:active,
.themed-colors .dropdown_classic:active,
.themed-colors .newbonklobby_teamlockbutton_warn,
#theme_save:active, #theme_cancel:active, #theme_reset:active {
    background-color: var(--bonk_theme_active_button_color) !important;
    color: var(--bonk_theme_button_text) !important;
}

/* Tables in the game - Skin editor, Map Editor and Custom game list */
.themed-colors #roomlisttable tr:nth-child(odd),
.themed-colors .friends_table>tbody:nth-child(odd),
.themed-colors #skineditor_layerbox_layertable tr:nth-child(odd),
.themed-colors #mapeditor_leftbox_platformtable tr:nth-child(odd),
.themed-colors #mapeditor_leftbox_spawntable tr:nth-child(odd),
.themed-colors #redefineControls_table tr:nth-child(odd),
.themed-colors .roomlistfilterwindow_a,
.themed-colors #redefineControls_table th {
    background-color: var(--bonk_theme_table_color) !important;
    color: var(--bonk_theme_primary_text) !important;
}

.themed-colors #roomlisttable tr:nth-child(even),
.themed-colors .friends_table tr:nth-child(even),
.themed-colors #skineditor_layerbox_layertable tr:nth-child(even),
.themed-colors #mapeditor_leftbox_platformtable tr:nth-child(even),
.themed-colors #mapeditor_leftbox_spawntable tr:nth-child(even),
.themed-colors #redefineControls_table tr:nth-child(even),
.themed-colors #roomlisttableheadercontainer,
.themed-colors .roomlistfilterwindow_b {
    background-color: var(--bonk_theme_table_alt_color) !important;
    color: var(--bonk_theme_primary_text) !important;
}

.themed-colors #roomlisttable tr.FRIENDSPRESENT,
.themed-colors .maploadwindowtextaddedby_picks {
    color: var(--bonk_theme_colored_text) !important;
}

.themed-colors tr.HOVERUNSELECTED:hover td {
    background-color: var(--bonk_theme_table_hover_color) !important;
}

.themed-colors tr.HOVERSELECTED td,
.themed-colors tr.SELECTED td {
    background-color: var(--bonk_theme_table_active_color) !important;
}

/* "popup" color, custom room list top bar */
.themed-colors .bt-titlebar,
.themed-colors .windowTopBar_classic, 
.themed-colors .classicTopBar,
.themed-colors .newbonklobby_boxtop, 
.themed-colors .newbonklobby_boxtop_classic,
.themed-colors .friends_topbar,
.themed-colors #newbonklobby_votewindow_top,
.themed-colors #hostleaveconfirmwindow_top,
.themed-colors #leaveconfirmwindow_top,
.themed-colors #ingamecountdown_top,
#theme_container_title {
    background-color: var(--bonk_theme_window_color) !important;
    color: var(--bonk_theme_primary_text) !important;
}

/* Style the top bar */
.themed-colors #pretty_top_bar {
    background-color: var(--bonk_theme_top_bar_color) !important;
    opacity: var(--bonk_theme_top_bar_opacity) !important;
    color: var(--bonk_theme_top_bar_text) !important;
}

.themed-colors .pretty_top_button,
.themed-colors #pretty_top_name,
.themed-colors #pretty_top_name,
.themed-colors #pretty_top_level,
.themed-colors #pretty_top_playercount {
    background-color: var(--bonk_theme_top_bar_color) !important;
    color: var(--bonk_theme_top_bar_text) !important;
}

.themed-colors .pretty_top_button:hover {
    background-color: var(--bonk_theme_top_bar_hover_color) !important;
}

/* Invert the Bonk.io description at the bottom of the page */
.themed-colors #descriptioninner,
.themed-colors #descriptioninner .descriptionthumbr,
.themed-colors #descriptioninner .descriptionthumbl {
    filter: invert(var(--bonk_theme_description_invert)) !important;
}

/* Remove settings borders */
.themed-colors #redefineControls_table td,
.themed-colors #redefineControls_table th,
.themed-colors #redefineControls_table {
    border: none !important;
}

/* Players in lobby */
.themed-colors .newbonklobby_playerentry {
    border-left: 4px solid var(--bonk_theme_primary_background) !important;
    border-top: 4px solid var(--bonk_theme_primary_background) !important;
    border-right: 4px solid var(--bonk_theme_primary_background) !important;
    background-color: var(--bonk_theme_primary_background) !important;
    color: var(--bonk_theme_primary_text) !important;
}

.themed-colors .newbonklobby_playerentry:hover {
    border-left: 4px solid var(--bonk_theme_secondary_background) !important;
    border-top: 4px solid var(--bonk_theme_secondary_background) !important;
    border-right: 4px solid var(--bonk_theme_secondary_background) !important;
    background-color: var(--bonk_theme_secondary_background) !important;
}

.themed-colors #newbonklobby_chat_lowerline {
    border-top: 1px solid var(--bonk_theme_secondary_background) !important;
}

.themed-colors #newbonklobby_playerbox_middleline {
    border-left: 1px solid var(--bonk_theme_secondary_background) !important;
}

/* Headings in the Map Editor and stuff */
.themed-colors .friends_titles,
.themed-colors .mapeditor_table_heading_div {
    background-color: var(--bonk_theme_list_headers) !important;
}

/* Change the XP bar to use the colors we want */
#xpbarfill {
    background-color: var(--bonk_theme_xp_bar_fill) !important;
}

/* Below is CSS for our theme editor thing */
#theme_container {
    border-radius: 3px 0px 3px 3px;
    z-index: 999;
    font-family: "futurept_b1";
    padding: 0px;
    right: 0px;
    top: 0px;
    position: fixed;
    overflow-y: scroll;
    max-height: 100vh;
    width: 20em;
}

#configuration_list {
    padding: 1.5em;
    display: flex;
    flex-direction: column;
}

#theme_container_title {
    text-align: center;
    margin: 0px;
    font-size: 20px;
    line-height: 32px;
    font-family: "futurept_b1"
}

.configuration_container {
    white-space: pre-line;
    display: flex;
    justify-content: space-between;
    align-items: center;
    height: 2.25em;
}

.configuration_name {
    text-transform: capitalize;
    float: left;
    width: 70%;
}

.configuration_value {
    float: right;
    width: 25%;
}

#theme_cancel {
    float: left;
    width: 45%;
}

#theme_save {
    float: right;
    width: 45%;
}

#configuration_json {
    align-self: center;
    resize: none;
    width: 100%;
    height: 15em;
}
`);
});

})();

QingJ © 2025

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