mirror of
https://github.com/danbulant/dribbblish-dynamic-theme
synced 2026-07-06 11:41:00 +00:00
Merge pull request #50 from SendNukez/main
Refactor config code, add top bar options, color scrollbar handles and add option to round sidebar icons
This commit is contained in:
commit
8b5859897f
3 changed files with 256 additions and 72 deletions
|
|
@ -174,15 +174,21 @@ function toggleDark(setDark) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Init with current system light/dark mode */
|
/* Init with current system light/dark mode */
|
||||||
let systemDark = parseInt(getComputedStyle(document.documentElement).getPropertyValue('--system_is_dark'))==1
|
let systemDark = parseInt(getComputedStyle(document.documentElement).getPropertyValue("--system_is_dark")) == 1;
|
||||||
toggleDark(systemDark)
|
|
||||||
|
|
||||||
DribbblishShared.configMenu.register()
|
DribbblishShared.config.registerSelect("Theme", "theme", ["System", "Dark", "Light"], 0, (val) => {
|
||||||
DribbblishShared.configMenu.addItem(new Spicetify.Menu.Item(
|
switch (val) {
|
||||||
"Dark mode",
|
case 0:
|
||||||
systemDark,
|
toggleDark(systemDark);
|
||||||
(self) => { toggleDark(); self.isEnabled = !self.isEnabled; }
|
break;
|
||||||
))
|
case 1:
|
||||||
|
toggleDark(true);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
toggleDark(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
function updateColors(textColHex, sideColHex) {
|
function updateColors(textColHex, sideColHex) {
|
||||||
let isLightBg = isLight(textColorBg)
|
let isLightBg = isLight(textColorBg)
|
||||||
|
|
|
||||||
142
dribbblish.js
142
dribbblish.js
|
|
@ -2,44 +2,122 @@
|
||||||
// document.getElementById("popover-container").style.height = 0;
|
// document.getElementById("popover-container").style.height = 0;
|
||||||
const DribbblishShared = {
|
const DribbblishShared = {
|
||||||
configMenu: new Spicetify.Menu.SubMenu("Dribbblish", []),
|
configMenu: new Spicetify.Menu.SubMenu("Dribbblish", []),
|
||||||
rightBigCover: localStorage.getItem("dribs-right-big-cover") === "true",
|
config: {
|
||||||
osIconDodge: localStorage.getItem("dribs-os-icon-dodge") === "true",
|
register: (name, key, defaultValue, update) => {
|
||||||
updateConfig: () => {
|
const menuItem = new Spicetify.Menu.Item(name, defaultValue, (self) => {
|
||||||
if (DribbblishShared.rightBigCover) {
|
self.setState(!self.isEnabled);
|
||||||
document.documentElement.classList.add("right-expanded-cover");
|
DribbblishShared.config.toggle(key);
|
||||||
} else {
|
});
|
||||||
document.documentElement.classList.remove("right-expanded-cover");
|
DribbblishShared.configMenu.addItem(menuItem);
|
||||||
}
|
|
||||||
|
|
||||||
if (DribbblishShared.osIconDodge) {
|
if (localStorage.getItem(`dribbblish:config:${key}`) == null) localStorage.setItem(`dribbblish:config:${key}`, defaultValue);
|
||||||
document.documentElement.style.setProperty("--os-windows-icon-dodge", 1);
|
|
||||||
} else {
|
DribbblishShared.configData[key] = {
|
||||||
document.documentElement.style.setProperty("--os-windows-icon-dodge", 0);
|
menuItem,
|
||||||
|
update
|
||||||
|
};
|
||||||
|
|
||||||
|
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.configMenu.addItem(menuItem);
|
||||||
|
menuItem.register();
|
||||||
|
|
||||||
|
if (localStorage.getItem(`dribbblish:config:${key}`) == null) localStorage.setItem(`dribbblish:config:${key}`, defaultChoice);
|
||||||
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
configData: {}
|
||||||
};
|
};
|
||||||
|
|
||||||
DribbblishShared.configMenu.register();
|
DribbblishShared.configMenu.register();
|
||||||
DribbblishShared.configMenu.addItem(
|
|
||||||
new Spicetify.Menu.Item("Right expanded cover", DribbblishShared.rightBigCover, (self) => {
|
|
||||||
self.isEnabled = !self.isEnabled;
|
|
||||||
DribbblishShared.rightBigCover = self.isEnabled;
|
|
||||||
localStorage.setItem("dribs-right-big-cover", self.isEnabled);
|
|
||||||
DribbblishShared.updateConfig();
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
DribbblishShared.configMenu.register();
|
// Initialize Config
|
||||||
DribbblishShared.configMenu.addItem(
|
DribbblishShared.config.register("Right expanded cover", "rightBigCover", true, (value) => {
|
||||||
new Spicetify.Menu.Item("OS Icon Dodge", DribbblishShared.osIconDodge, (self) => {
|
if (value) {
|
||||||
self.isEnabled = !self.isEnabled;
|
document.documentElement.classList.add("right-expanded-cover");
|
||||||
DribbblishShared.osIconDodge = self.isEnabled;
|
} else {
|
||||||
localStorage.setItem("dribs-os-icon-dodge", self.isEnabled);
|
document.documentElement.classList.remove("right-expanded-cover");
|
||||||
DribbblishShared.updateConfig();
|
}
|
||||||
})
|
});
|
||||||
);
|
|
||||||
|
|
||||||
DribbblishShared.updateConfig();
|
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)");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
function waitForElement(els, func, timeout = 100) {
|
function waitForElement(els, func, timeout = 100) {
|
||||||
const queries = els.map(el => document.querySelector(el));
|
const queries = els.map(el => document.querySelector(el));
|
||||||
|
|
|
||||||
164
user.css
164
user.css
|
|
@ -6,7 +6,8 @@
|
||||||
--scrollbar-vertical-size: 8px;
|
--scrollbar-vertical-size: 8px;
|
||||||
--cover-border-radius: 8px;
|
--cover-border-radius: 8px;
|
||||||
--playbar-movement-anim-speed: 0.5s;
|
--playbar-movement-anim-speed: 0.5s;
|
||||||
--os-windows-icon-dodge: 0;
|
--image-radius: 10px;
|
||||||
|
--sidebar-icons-border-radius: 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
|
|
@ -44,6 +45,15 @@ body {
|
||||||
letter-spacing: normal;
|
letter-spacing: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.os-scrollbar-handle {
|
||||||
|
background-color: var(--spice-text) !important;
|
||||||
|
border-radius: calc(var(--scrollbar-vertical-size) / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.os-scrollbar-handle:hover {
|
||||||
|
filter: brightness(80%);
|
||||||
|
}
|
||||||
|
|
||||||
.main-type-mesto,
|
.main-type-mesto,
|
||||||
.main-type-mestoBold,
|
.main-type-mestoBold,
|
||||||
.main-type-ballad,
|
.main-type-ballad,
|
||||||
|
|
@ -155,16 +165,6 @@ span.artist-artistVerifiedBadge-badge svg > path:last-of-type {
|
||||||
line-height: 120px !important;
|
line-height: 120px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Hightlight selected playlist */
|
|
||||||
.main-rootlist-rootlistItemLink.main-rootlist-rootlistItemLinkActive {
|
|
||||||
background: var(--spice-button);
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-navBar-navBarLinkActive {
|
|
||||||
background: var(--spice-button);
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-contextMenu-menu {
|
.main-contextMenu-menu {
|
||||||
background-color: var(--spice-button);
|
background-color: var(--spice-button);
|
||||||
}
|
}
|
||||||
|
|
@ -256,6 +256,23 @@ span.artist-artistVerifiedBadge-badge svg > path:last-of-type {
|
||||||
height: 32px !important;
|
height: 32px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.view-homeShortcutsGrid-shortcut {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cover-art,
|
||||||
|
.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,
|
||||||
|
.view-homeShortcutsGrid-shortcutLink {
|
||||||
|
border-radius: var(--sidebar-icons-border-radius) !important;
|
||||||
|
}
|
||||||
|
|
||||||
.main-avatar-avatar.main-avatar-withBadge:after {
|
.main-avatar-avatar.main-avatar-withBadge:after {
|
||||||
box-shadow: 0 0 0 2px var(--spice-sidebar);
|
box-shadow: 0 0 0 2px var(--spice-sidebar);
|
||||||
background-color: var(--spice-notification);
|
background-color: var(--spice-notification);
|
||||||
|
|
@ -321,7 +338,8 @@ html {
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-navBar-navBarItem {
|
.main-navBar-navBarItem {
|
||||||
padding: 0 8px;
|
position: relative;
|
||||||
|
padding: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#spicetify-show-list >* {
|
#spicetify-show-list >* {
|
||||||
|
|
@ -379,6 +397,28 @@ html.sidebar-hide-text .GlueDropTarget span {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.main-rootlist-rootlist::before,
|
||||||
|
.main-rootlist-rootlist::after {
|
||||||
|
z-index: 10;
|
||||||
|
position: absolute;
|
||||||
|
content: "";
|
||||||
|
left: 0px;
|
||||||
|
right: 0px;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-rootlist-rootlist::before {
|
||||||
|
top: 0px;
|
||||||
|
height: 5%;
|
||||||
|
background: linear-gradient(to bottom, var(--spice-sidebar) 10%, transparent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-rootlist-rootlist::after {
|
||||||
|
bottom: 0px;
|
||||||
|
height: 15%;
|
||||||
|
background: linear-gradient(to top, var(--spice-sidebar) 10%, transparent);
|
||||||
|
}
|
||||||
|
|
||||||
.Root__nav-bar .os-scrollbar-vertical,
|
.Root__nav-bar .os-scrollbar-vertical,
|
||||||
.main-buddyFeed-buddyFeedRoot .os-scrollbar-vertical {
|
.main-buddyFeed-buddyFeedRoot .os-scrollbar-vertical {
|
||||||
display: none;
|
display: none;
|
||||||
|
|
@ -396,6 +436,7 @@ html.sidebar-hide-text .GlueDropTarget span {
|
||||||
fill: var(--spice-button);
|
fill: var(--spice-button);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.playback-bar__progress-time,
|
||||||
.playback-bar__progress-time-elapsed,
|
.playback-bar__progress-time-elapsed,
|
||||||
.main-playbackBarRemainingTime-container {
|
.main-playbackBarRemainingTime-container {
|
||||||
display: none;
|
display: none;
|
||||||
|
|
@ -531,7 +572,7 @@ img.playlist-picture {
|
||||||
flex: 0 0 32px;
|
flex: 0 0 32px;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
border-radius: 50%;
|
border-radius: var(--sidebar-icons-border-radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-rootlist-rootlistItem a span {
|
.main-rootlist-rootlistItem a span {
|
||||||
|
|
@ -569,20 +610,52 @@ li.GlueDropTarget {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** OS-specific window controls dodge */
|
/** OS-specific window controls dodge */
|
||||||
.spotify__os--is-windows .main-navBar-navBar {
|
#main:not([top-bar^="none"]) .main-topBar-background {
|
||||||
padding-top: calc(var(--os-windows-icon-dodge) * 24px);
|
-webkit-app-region: no-drag;
|
||||||
}
|
}
|
||||||
|
|
||||||
.spotify__container--is-desktop:not(.fullscreen).spotify__os--is-windows .main-navBar-entryPoints {
|
#main:not([top-bar="none-padding"]) .main-navBar-navBar,
|
||||||
padding-top: calc(var(--os-windows-icon-dodge) * 12px + 12px);
|
#main:not([top-bar="none-padding"]) .main-buddyFeed-header,
|
||||||
|
#main:not([top-bar="none-padding"]) .main-navBar-entryPoints {
|
||||||
|
padding-top: 8px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.spotify__os--is-windows .main-buddyFeed-header {
|
#main:not([top-bar^="none"]) {
|
||||||
padding-top: calc(var(--os-windows-icon-dodge) * 32px);
|
padding-top: 31px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.spotify__container--is-desktop.spotify__os--is-windows[dir=ltr] .main-topBar-container {
|
#main:not([top-bar^="none"])::before {
|
||||||
padding-right: calc(var(--os-windows-icon-dodge) * 135px + 32px);
|
z-index: 999;
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 0px;
|
||||||
|
left: 0px;
|
||||||
|
right: 135px;
|
||||||
|
height: 31px;
|
||||||
|
background-color: rgba(0, 0, 0, 0.53);
|
||||||
|
-webkit-app-region: drag;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main[top-bar="solid"]::before {
|
||||||
|
right: 0px;
|
||||||
|
background-color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main[top-bar="none-padding"] .spotify__os--is-windows .main-navBar-navBar {
|
||||||
|
padding-top: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main[top-bar="none-padding"] .spotify__container--is-desktop:not(.fullscreen).spotify__os--is-windows .main-navBar-entryPoints {
|
||||||
|
padding-top: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main[top-bar="none-padding"] .spotify__os--is-windows .main-buddyFeed-header {
|
||||||
|
padding-top: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main[top-bar="none-padding"] .spotify__container--is-desktop.spotify__os--is-windows[dir=ltr] .Root__top-bar + .main-buddyFeed-buddyFeedRoot .main-topBar-container {
|
||||||
|
padding-right: 167px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-topBar-container {
|
.main-topBar-container {
|
||||||
|
|
@ -590,18 +663,10 @@ li.GlueDropTarget {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Custom elements */
|
/** Custom elements */
|
||||||
#dribbblish-sidebar-fade-in {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 15%;
|
|
||||||
background: linear-gradient(to top, var(--spice-sidebar) 10%, transparent);
|
|
||||||
z-index: 3;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
.dribs-playlist-list {
|
.dribs-playlist-list {
|
||||||
padding-bottom: 56px;
|
padding-bottom: 86px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#dribbblish-back-shadow {
|
#dribbblish-back-shadow {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
width: var(--main-view-width);
|
width: var(--main-view-width);
|
||||||
|
|
@ -745,6 +810,41 @@ span.main-userWidget-displayName,
|
||||||
.main-navBar-entryPoints {
|
.main-navBar-entryPoints {
|
||||||
--left-sidebar-padding-left: 24px;
|
--left-sidebar-padding-left: 24px;
|
||||||
--left-sidebar-padding-right: 24px;
|
--left-sidebar-padding-right: 24px;
|
||||||
|
|
||||||
|
padding: 0px 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-navBar-navBar,
|
||||||
|
.main-rootlist-wrapper > div:nth-child(2),
|
||||||
|
.main-navBar-entryPoints {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-rootlist-wrapper > div:nth-child(2) > li img,
|
||||||
|
.main-navBar-navBarLink > .icon {
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-navBar-navBarItem:hover::before,
|
||||||
|
.main-rootlist-rootlistItem:hover::before,
|
||||||
|
.main-rootlist-rootlistItemLinkActive::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
inset: 0px;
|
||||||
|
background-color: rgba(var(--spice-rgb-main), 0.4);
|
||||||
|
border-radius: var(--image-radius);
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-navBar-navBarLinkActive {
|
||||||
|
border-radius: var(--image-radius);
|
||||||
|
background-color: rgba(var(--spice-rgb-main), 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-navBar-navBar a:hover, .main-navBar-navBar a:hover span {
|
||||||
|
color: unset !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.GlueDropTarget.personal-library {
|
div.GlueDropTarget.personal-library {
|
||||||
|
|
@ -879,4 +979,4 @@ html.right-expanded-cover.buddyfeed-visible .main-coverSlotExpanded-container {
|
||||||
|
|
||||||
.main-actionBar-ActionBarRow button:not(.main-playButton-primary) {
|
.main-actionBar-ActionBarRow button:not(.main-playButton-primary) {
|
||||||
color: var(--spice-subtext);
|
color: var(--spice-subtext);
|
||||||
}
|
}
|
||||||
Loading…
Reference in a new issue