Updated config Interface

This commit is contained in:
Send_Nukez 2021-10-06 07:39:12 +02:00
parent db1ad17ffa
commit 507d283d00
3 changed files with 279 additions and 120 deletions

View file

@ -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

View file

@ -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 */ `
<div class="dribbblish-config-container">
<button aria-label="Close" class="dribbblish-config-close main-trackCreditsModal-closeBtn">
<svg width="18" height="18" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg"><path d="M31.098 29.794L16.955 15.65 31.097 1.51 29.683.093 15.54 14.237 1.4.094-.016 1.508 14.126 15.65-.016 29.795l1.414 1.414L15.54 17.065l14.144 14.143" fill="currentColor" fill-rule="evenodd"></path></svg>
</button>
<h1>Dribbblish Settings</h1>
</div>
<div class="dribbblish-config-backdrop"></div>
`;
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 */ `
<h2 class="x-settings-title main-type-cello" as="h2">${name}</h2>
<label class="main-type-mesto" as="label" for="dribbblish-config-input-${key}" style="color: var(--spice-subtext);">${description}</label>
<label class="x-toggle-wrapper x-settings-secondColumn">
${input}
</label>
`;
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 */ `
<input id="dribbblish-config-input-${key}" class="x-toggle-input" type="checkbox"${this.get(key, defaultValue) ? " checked" : ""}>
<span class="x-toggle-indicatorWrapper">
<span class="x-toggle-indicator"></span>
</span>
`;
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 */ `
<span class="x-settings-secondColumn">
<select class="main-dropDown-dropDown" id="dribbblish-config-input-${key}">
${options.map((option, i) => `<option value="${i}"${this.get(key, defaultValue) == i ? " selected" : ""}>${option}</option>`).join("")}
</select>
</span>
`;
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 */ `
<span class="x-settings-secondColumn">
<button class="main-buttons-button main-button-primary" type="button" id="dribbblish-config-input-${key}">
<div class="x-settings-buttonContainer">
<span>${name}</span>
</div>
</button>
</span>
`;
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`

View file

@ -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;