From 507d283d00363b599b4fe61245c045b9c81f456f Mon Sep 17 00:00:00 2001 From: Send_Nukez Date: Wed, 6 Oct 2021 07:39:12 +0200 Subject: [PATCH] Updated config Interface --- dribbblish-dynamic.js | 42 ++++--- dribbblish.js | 286 +++++++++++++++++++++++++++--------------- user.css | 71 ++++++++++- 3 files changed, 279 insertions(+), 120 deletions(-) diff --git a/dribbblish-dynamic.js b/dribbblish-dynamic.js index 64a10c1..06bc43e 100644 --- a/dribbblish-dynamic.js +++ b/dribbblish-dynamic.js @@ -176,17 +176,25 @@ function toggleDark(setDark) { /* Init with current system light/dark mode */ let systemDark = parseInt(getComputedStyle(document.documentElement).getPropertyValue("--system_is_dark")) == 1; -DribbblishShared.config.registerSelect("Theme", "theme", ["System", "Dark", "Light"], 0, (val) => { - switch (val) { - case 0: - toggleDark(systemDark); - break; - case 1: - toggleDark(true); - break; - case 2: - toggleDark(false); - break; +DribbblishShared.config.register({ + type: "select", + options: ["System", "Dark", "Light"], + key: "theme", + name: "Theme", + description: "Select Dark / Bright mode", + defaultValue: 0, + onChange: (val) => { + switch (val) { + case 0: + toggleDark(systemDark); + break; + case 1: + toggleDark(true); + break; + case 2: + toggleDark(false); + break; + } } }); @@ -321,11 +329,15 @@ hookCoverChange(false); document.querySelector(".main-userWidget-box").append(upd) upd.append(`Theme UPD v${data.tag_name} avail.`) upd.setAttribute("title", `Changes: ${data.name}`) - DribbblishShared.configButton.addItem( - new Spicetify.Menu.Item("Update", false, (self) => { + DribbblishShared.config.register({ + insertOnTop: true, + type: "button", + name: "Update", + description: "Open the GitHub Page with Installation instructions / Commands.", + onChange: () => { window.open("https://github.com/JulienMaille/dribbblish-dynamic-theme#install", "_blank"); - }) - ); + } + }); } }).catch(err => { // Do something for an error here diff --git a/dribbblish.js b/dribbblish.js index 411f0de..dfa24f4 100644 --- a/dribbblish.js +++ b/dribbblish.js @@ -1,133 +1,213 @@ // Hide popover message // document.getElementById("popover-container").style.height = 0; -const DribbblishShared = { - configButton: new Spicetify.Menu.SubMenu("Dribbblish", []), - config: { - register: (name, key, defaultValue, update) => { - const menuItem = new Spicetify.Menu.Item(name, defaultValue, (self) => { - self.setState(!self.isEnabled); - DribbblishShared.config.toggle(key); - }); - DribbblishShared.configButton.addItem(menuItem); +class ConfigMenu { + constructor() { + this.config = {}; + this.configButton = new Spicetify.Menu.Item("Dribbblish config", false, () => DribbblishShared.config.open()); + this.configButton.register(); - if (localStorage.getItem(`dribbblish:config:${key}`) == null) localStorage.setItem(`dribbblish:config:${key}`, defaultValue); + const container = document.createElement("div"); + container.id = "dribbblish-config"; + container.innerHTML = /* html */ ` +
+ +

Dribbblish Settings

+
+
+ `; - DribbblishShared.configData[key] = { - menuItem, - update - }; + document.body.appendChild(container); + document.querySelector(".dribbblish-config-close").addEventListener("click", () => DribbblishShared.config.close()); + document.querySelector(".dribbblish-config-backdrop").addEventListener("click", () => DribbblishShared.config.close()); + } - DribbblishShared.config.update(key); - }, - registerSelect: (name, key, choices, defaultChoice, update) => { - const menuItem = new Spicetify.Menu.SubMenu(name, []); - const menuItems = choices.map((choice, i) => { - const subItem = new Spicetify.Menu.Item(choice, i == defaultChoice, (self) => { - self.setState(!self.isEnabled); - DribbblishShared.config.set(key, i); - }); - menuItem.addItem(subItem); - return subItem; - }); - DribbblishShared.configButton.addItem(menuItem); - menuItem.register(); + open() { + document.getElementById("dribbblish-config").setAttribute("active", ""); + } - if (localStorage.getItem(`dribbblish:config:${key}`) == null) localStorage.setItem(`dribbblish:config:${key}`, defaultChoice); + close() { + document.getElementById("dribbblish-config").removeAttribute("active"); + } - DribbblishShared.configData[key] = { - subItems: menuItems, - menuItem, - update - }; - - DribbblishShared.config.update(key); - }, - get: (key) => { - const val = localStorage.getItem(`dribbblish:config:${key}`); - if (val == "true" || val == "false") return val == "true"; - if (!isNaN(val) && !isNaN(parseInt(val))) return parseInt(val); - }, - set: (key, val) => { - if (DribbblishShared.configData[key].hasOwnProperty("subItems")) { - DribbblishShared.configData[key].subItems.forEach((item, i) => { - item.setState(val == i); - }); - } else { - DribbblishShared.configData[key].menuItem.setState(val); - } - localStorage.setItem(`dribbblish:config:${key}`, val); - DribbblishShared.config.update(key); - }, - toggle: (key) => { - DribbblishShared.config.set(key, !DribbblishShared.config.get(key)); - - if (DribbblishShared.configData[key].hasOwnProperty("subItems")) { - // Can't toggle lists - } else { - DribbblishShared.configData[key].menuItem.setState(DribbblishShared.config.get(key)); - } - }, - update: (key) => { - const val = DribbblishShared.config.get(key); - if (DribbblishShared.configData[key].hasOwnProperty("subItems")) { - DribbblishShared.configData[key].subItems.forEach((item, i) => { - item.setState(val == i); - }); - } else { - DribbblishShared.configData[key].menuItem.setState(val); - } - DribbblishShared.configData[key].update(val); + /** @private */ + addInputHTML({ type, key, name, description, input, insertOnTop }) { + const elem = document.createElement("div"); + elem.classList.add("dribbblish-config-item"); + elem.setAttribute("key", `dribbblish:config:${key}`); + elem.setAttribute("type", type); + elem.innerHTML = /* html */ ` +

${name}

+ + + `; + if (insertOnTop && document.querySelector(".dribbblish-config-item")) { + console.log("before"); + document.querySelector(".dribbblish-config-container").insertBefore(elem, document.querySelector(".dribbblish-config-item:first-of-type")); + } else { + document.querySelector(".dribbblish-config-container").appendChild(elem); } - }, - configData: {} -}; -DribbblishShared.configButton.register(); + } -// Initialize Config -DribbblishShared.config.register("Right expanded cover", "rightBigCover", true, (value) => { - if (value) { - document.documentElement.classList.add("right-expanded-cover"); - } else { - document.documentElement.classList.remove("right-expanded-cover"); + register({ type, options, key, name, description, defaultValue, insertOnTop, onChange }) { + if (!key) key = cyrb53Hash(name); + var fireChange = true; + + if (type == "checkbox") { + const input = /* html */ ` + + + + + `; + this.addInputHTML({ type, key, name, description, input, insertOnTop }); + + document.getElementById(`dribbblish-config-input-${key}`).addEventListener("change", (e) => { + this.set(key, e.target.checked); + onChange(this.get(key)); + }); + } else if (type == "select") { + const input = /* html */ ` + + + + `; + this.addInputHTML({ type, key, name, description, input, insertOnTop }); + + document.getElementById(`dribbblish-config-input-${key}`).addEventListener("change", (e) => { + this.set(key, e.target.value); + onChange(this.get(key)); + }); + } else if (type == "button") { + const input = /* html */ ` + + + + `; + this.addInputHTML({ type, key, name, description, input, insertOnTop }); + + document.getElementById(`dribbblish-config-input-${key}`).addEventListener("click", (e) => { + onChange(true); + }); + fireChange = false; + } else { + throw new Error(`Config Type "${type}" invalid`); + } + + if (fireChange) onChange(this.get(key, defaultValue)); + } + + get(key, defaultValue) { + const val = localStorage.getItem(`dribbblish:config:${key}`); + if (val == null) return defaultValue; + + if (val == "true" || val == "false") return val == "true"; // Boolean + if (!isNaN(val) && !isNaN(parseInt(val))) return parseInt(val); // Number + return val; // String + } + + set(key, val) { + localStorage.setItem(`dribbblish:config:${key}`, val); + } +} + +class _DribbblishShared { + constructor() { + this.config = new ConfigMenu(); + } +} +const DribbblishShared = new _DribbblishShared(); + +DribbblishShared.config.register({ + type: "checkbox", + key: "rightBigCover", + name: "Right expanded cover", + description: "Have the expanded cover Image on the right instead of onn the left.", + defaultValue: true, + onChange: (val) => { + if (val) { + document.documentElement.classList.add("right-expanded-cover"); + } else { + document.documentElement.classList.remove("right-expanded-cover"); + } } }); -DribbblishShared.config.register("Round Sidebar Icons", "roundSidebarIcons", false, (value) => { - if (value) { - document.documentElement.style.setProperty("--sidebar-icons-border-radius", "50%"); - } else { - document.documentElement.style.setProperty("--sidebar-icons-border-radius", "var(--image-radius)"); +DribbblishShared.config.register({ + type: "checkbox", + key: "roundSidebarIcons", + name: "Round Sidebar Icons", + description: "If the Sidebar Iconns should be round instead of square", + defaultValue: false, + onChange: (val) => { + if (val) { + document.documentElement.style.setProperty("--sidebar-icons-border-radius", "50%"); + } else { + document.documentElement.style.setProperty("--sidebar-icons-border-radius", "var(--image-radius)"); + } } }); +DribbblishShared.config.open(); + waitForElement(["#main"], () => { - DribbblishShared.config.registerSelect("Windows Top Bar", "winTopBar", ["None", "None (With Top Padding)", "Solid", "Transparent"], 0, (value) => { - switch (value) { - case 0: - document.getElementById("main").setAttribute("top-bar", "none"); - break; - case 1: - document.getElementById("main").setAttribute("top-bar", "none-padding"); - break; - case 2: - document.getElementById("main").setAttribute("top-bar", "solid"); - break; - case 3: - document.getElementById("main").setAttribute("top-bar", "transparent"); - break; + DribbblishShared.config.register({ + type: "select", + options: ["None", "None (With Top Padding)", "Solid", "Transparent"], + key: "winTopBar", + name: "Windows Top Bar", + description: "Have differennt top Bars (Ore none at all)", + defaultValue: 0, + onChange: (val) => { + switch (val) { + case 0: + document.getElementById("main").setAttribute("top-bar", "none"); + break; + case 1: + document.getElementById("main").setAttribute("top-bar", "none-padding"); + break; + case 2: + document.getElementById("main").setAttribute("top-bar", "solid"); + break; + case 3: + document.getElementById("main").setAttribute("top-bar", "transparent"); + break; + } } }); }); function waitForElement(els, func, timeout = 100) { - const queries = els.map(el => document.querySelector(el)); - if (queries.every(a => a)) { + const queries = els.map((el) => document.querySelector(el)); + if (queries.every((a) => a)) { func(queries); } else if (timeout > 0) { setTimeout(waitForElement, 300, els, func, --timeout); } } +function cyrb53Hash(str, seed = 0) { + let h1 = 0xdeadbeef ^ seed, + h2 = 0x41c6ce57 ^ seed; + for (let i = 0, ch; i < str.length; i++) { + ch = str.charCodeAt(i); + h1 = Math.imul(h1 ^ ch, 2654435761); + h2 = Math.imul(h2 ^ ch, 1597334677); + } + h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909); + h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909); + return 4294967296 * (2097151 & h2) + (h1 >>> 0); +} + waitForElement([ `.main-rootlist-rootlistPlaylistsScrollNode ul[tabindex="0"]`, `.main-rootlist-rootlistPlaylistsScrollNode ul[tabindex="0"] li` diff --git a/user.css b/user.css index 188704d..368c0ce 100644 --- a/user.css +++ b/user.css @@ -274,14 +274,14 @@ span.artist-artistVerifiedBadge-badge svg > path:last-of-type { } .cover-art, +.main-userWidget-box, .view-homeShortcutsGrid-shortcut, :not(.view-homeShortcutsGrid-imageWrapper) > .main-image-image:not(.main-avatar-image) { border-radius: var(--image-radius) !important; } -.main-userWidget-box, -.main-avatar-userIcon, .main-avatar-image, +.main-avatar-userIcon, .view-homeShortcutsGrid-shortcutLink { border-radius: var(--sidebar-icons-border-radius) !important; } @@ -699,6 +699,73 @@ li.GlueDropTarget { pointer-events: none; } +#dribbblish-config { + display: none; + z-index: 99999; + position: absolute; + inset: 0px; + align-items: center; + justify-content: center; + color: var(--spice-text); +} + +#dribbblish-config[active] { + display: flex; +} + +#dribbblish-config .dribbblish-config-container { + z-index: 1; + position: relative; + max-width: 80%; + background-color: rgba(var(--spice-rgb-main), 0.85); + backdrop-filter: blur(3px); + padding: 20px 15px; + border-radius: var(--main-corner-radius); + display: flex; + gap: 5px; + flex-direction: column; + align-items: center; + justify-content: center; +} + +#dribbblish-config .dribbblish-config-item { + position: relative; + width: 100%; + padding: 0px 50px; + display: grid; + grid-template-columns: 1fr auto; + grid-template-rows: 1fr 1fr; + gap: 0px 10px; + grid-template-areas: + "header input" + "description input"; +} + +#dribbblish-config .dribbblish-config-item > .x-settings-title { + grid-area: header; +} + +#dribbblish-config .dribbblish-config-item > .main-type-mesto { + grid-area: description; +} + +#dribbblish-config .dribbblish-config-item > .x-settings-secondColumn { + grid-area: input; +} + +#dribbblish-config .dribbblish-config-close { + position: absolute; + top: 15px; + right: 15px; +} + +#dribbblish-config .dribbblish-config-backdrop { + position: absolute; + content: ""; + inset: 0px; + backdrop-filter: blur(3px) brightness(60%); +} + /** Rearrange player bar */ .main-nowPlayingBar-left { order: 1;