diff --git a/assets/public/custom/web/main.js b/assets/public/custom/web/main.js index 1e6147c7..3de80044 100644 --- a/assets/public/custom/web/main.js +++ b/assets/public/custom/web/main.js @@ -4,9 +4,11 @@ const SWITCH_CONTAINER_ID = "switch-container"; const CUSTOM_CSS_ID = "custom-css"; - const CUSTOM_CSS_STORAGE = "custom_css"; const CUSTOM_CSS_INPUT_ID = "custom-css-input"; - + + const CONFIG_KEY = "rscord_config"; + const DEFAULT_CONFIG = { customCss: "", revertStatusIcons: false }; + const CSS_CLASSES = { tabItem: "item-3XjbnG", selected: "selected-g-kMVV", @@ -21,6 +23,14 @@ textInput: "inputDefault-3FGxgL input-2g-os5" }; + const STATUS_COLOR_MAP = { + 'hsl(38, calc(var(--saturation-factor, 1) * 95.7%), 54.1%)': '#FAA61A', // Idle (yellow) + 'hsl(0, calc(var(--saturation-factor, 1) * 100%), 71.4%)': '#F04747', // DND (red) + 'hsl(235, calc(var(--saturation-factor, 1) * 85.6%), 64.7%)': '#7289DA', // Away (blue) + 'hsl(0, calc(var(--saturation-factor, 1) * 0%), 47.5%)': '#747F8D', // Offline (gray) + 'hsl(139, calc(var(--saturation-factor, 1) * 47.3%), 43.9%)': '#43B581', // Online (green) + }; + const IS_MOBILE = window .matchMedia("(pointer: coarse)") .matches; @@ -33,7 +43,27 @@ `; + function loadConfig() { + try { + return { + ...DEFAULT_CONFIG, + ...JSON.parse(localStorage_.getItem(CONFIG_KEY) || "{}") + }; + } catch { + return { ...DEFAULT_CONFIG }; + } + } + + function saveConfig(patch) { + const config = loadConfig(); + const updated = { ...config, ...patch }; + localStorage_.setItem(CONFIG_KEY, JSON.stringify(updated)); + return updated; + } + async function addSwitches(container) { + const config = loadConfig(); + container.appendChild(createSwitch( "Push Notifications", "Sends you notifications even when you close the app", @@ -41,45 +71,71 @@ await isPushRegistered(), async (checked) => { const publicKey = window.GLOBAL_ENV.VAPID_KEY; - if (!publicKey) { - alert("Server has not enabled push notifications") - return false; - } + if (!publicKey) return false; try { checked ? await registerPush(publicKey) : await unregisterPush(); return true; - } catch(err) { - alert(err.message); + } catch { return false; } } )); + + container.appendChild(createSwitch( + "Revert Status Icons", + "Revert the colorblind status icons added in 2019", + "revert-status", + config.revertStatusIcons, + (checked) => saveConfig({ revertStatusIcons: checked }) + )); } - function applySavedCSS() { - let css = localStorage_.getItem(CUSTOM_CSS_STORAGE) || ""; - let style = document.getElementById(CUSTOM_CSS_ID); + function revertStatusIcons() { + const statusRects = document.querySelectorAll('rect[fill^="hsl"]'); + for (const rect of statusRects) { + const fill = rect.getAttribute("fill"); + if (STATUS_COLOR_MAP[fill]) { + rect.setAttribute("fill", STATUS_COLOR_MAP[fill]); + } + const maskRef = rect.getAttribute("mask"); + if (!maskRef) continue; + + const maskId = maskRef.match(/#([^)]+)/)?.[1]; + if (!maskId) continue; + + const mask = document.getElementById(maskId); + if (!mask) continue; + + mask.querySelectorAll('[fill="black"]').forEach(el => el.remove()); + } + } + + function applyCustomCss() { + const { customCss } = loadConfig(); + + let style = document.getElementById(CUSTOM_CSS_ID); if (!style) { style = document.createElement("style"); style.id = CUSTOM_CSS_ID; document.head.appendChild(style); } - style.textContent = css; + style.textContent = customCss; } - function loadCustomCSS(textarea) { + function setupCssInput(textarea) { if (!textarea) return; - textarea.value = localStorage_.getItem(CUSTOM_CSS_STORAGE) || ""; - let style = document.getElementById(CUSTOM_CSS_ID); + const config = loadConfig(); + textarea.value = config.customCss; + + const style = document.getElementById(CUSTOM_CSS_ID); if (!style) return; textarea.addEventListener("input", () => { - const css = textarea.value; - style.textContent = css; - localStorage_.setItem(CUSTOM_CSS_STORAGE, css); + style.textContent = textarea.value; + saveConfig({ customCss: textarea.value }); }); } @@ -95,7 +151,7 @@ settingsBtn.tabIndex = -1; settingsBtn.ariaSelected = "false"; settingsBtn.textContent = "RSCord Settings"; - + settingsBtn.addEventListener("click", () => { const tabs = settingsBtn.parentElement.querySelectorAll('[role="tab"]'); tabs.forEach(tab => tab.classList.remove(CSS_CLASSES.selected)); @@ -115,7 +171,7 @@ document.querySelector(`.${CSS_CLASSES.contentColumn}`).appendChild(customContent); const cssInput = document.getElementById(CUSTOM_CSS_INPUT_ID); - loadCustomCSS(cssInput); + setupCssInput(cssInput); } const contentColumn = document.querySelector(`.${CSS_CLASSES.contentColumn}`); @@ -129,16 +185,13 @@ return true; } - function startObserver() { - const observer = new MutationObserver(() => { - const sidebar = document.querySelector(`.${CSS_CLASSES.settingsSidebar}`); - if (sidebar) addSettingsTab(); - }); - observer.observe(document.body, { childList: true, subtree: true }); - } + const observer = new MutationObserver(() => { + if (document.querySelector(`.${CSS_CLASSES.settingsSidebar}`)) addSettingsTab(); + if (loadConfig().revertStatusIcons) revertStatusIcons(); + }); - startObserver(); - applySavedCSS(); + observer.observe(document.body, { childList: true, subtree: true }); + applyCustomCss(); document.body.addEventListener("click", (e) => { const clickedHamburger = e.target.closest(`.${CSS_CLASSES.hamburger}`)