mirror of
https://github.com/danbulant/dribbblish-dynamic-theme
synced 2026-06-09 09:42:26 +00:00
add option to select color extraction method
This commit is contained in:
parent
fd01cc02ce
commit
784947e3a5
2 changed files with 66 additions and 41 deletions
|
|
@ -33,3 +33,7 @@ export function copyToClipboard(text) {
|
||||||
export function capitalizeFirstLetter(string) {
|
export function capitalizeFirstLetter(string) {
|
||||||
return string.charAt(0).toUpperCase() + string.slice(1);
|
return string.charAt(0).toUpperCase() + string.slice(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getClosestToNum(arr, num) {
|
||||||
|
return arr.reduce((prev, curr) => (Math.abs(curr - num) < Math.abs(prev - num) ? curr : prev));
|
||||||
|
}
|
||||||
|
|
|
||||||
103
src/js/main.js
103
src/js/main.js
|
|
@ -3,7 +3,7 @@ import chroma from "chroma-js";
|
||||||
import $ from "jquery";
|
import $ from "jquery";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
|
|
||||||
import { waitForElement, copyToClipboard, capitalizeFirstLetter } from "./Util";
|
import { waitForElement, copyToClipboard, capitalizeFirstLetter, getClosestToNum } from "./Util";
|
||||||
import ConfigMenu from "./ConfigMenu";
|
import ConfigMenu from "./ConfigMenu";
|
||||||
import Info from "./Info";
|
import Info from "./Info";
|
||||||
|
|
||||||
|
|
@ -492,10 +492,10 @@ function toggleDark(setDark) {
|
||||||
setRootColor("subtext", setDark ? "#EAEAEA" : "#3D3D3D");
|
setRootColor("subtext", setDark ? "#EAEAEA" : "#3D3D3D");
|
||||||
setRootColor("notification", setDark ? "#303030" : "#DDDDDD");
|
setRootColor("notification", setDark ? "#303030" : "#DDDDDD");
|
||||||
|
|
||||||
updateColors(sidebarColor, false);
|
updateColors(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkDarkLightMode(colors) {
|
function checkDarkLightMode() {
|
||||||
const theme = Dribbblish.config.get("theme");
|
const theme = Dribbblish.config.get("theme");
|
||||||
if (theme == "time") {
|
if (theme == "time") {
|
||||||
const start = 60 * parseInt(Dribbblish.config.get("darkModeOnTime").split(":")[0]) + parseInt(Dribbblish.config.get("darkModeOnTime").split(":")[1]);
|
const start = 60 * parseInt(Dribbblish.config.get("darkModeOnTime").split(":")[0]) + parseInt(Dribbblish.config.get("darkModeOnTime").split(":")[1]);
|
||||||
|
|
@ -508,23 +508,53 @@ function checkDarkLightMode(colors) {
|
||||||
if (end < start) dark = start <= time || time < end;
|
if (end < start) dark = start <= time || time < end;
|
||||||
else dark = start <= time && time < end;
|
else dark = start <= time && time < end;
|
||||||
toggleDark(dark);
|
toggleDark(dark);
|
||||||
} else if (theme == "color") {
|
|
||||||
if (colors && colors.length > 0) toggleDark(isLight(colors[0]));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run every Minute to check time and set dark / light mode
|
// Run every Minute to check time and set dark / light mode
|
||||||
setInterval(checkDarkLightMode, 60000);
|
setInterval(checkDarkLightMode, 60000);
|
||||||
|
|
||||||
Dribbblish.config.register({
|
Dribbblish.config.register({
|
||||||
area: "Theme",
|
area: "Theme",
|
||||||
type: "checkbox",
|
type: "select",
|
||||||
key: "dynamicColors",
|
key: "colorSelectionMode",
|
||||||
name: "Dynamic",
|
name: "Color Selection Mode",
|
||||||
description: "If the Theme's Color should be extracted from Albumart",
|
description: "Method of selecting colors from the albumart",
|
||||||
defaultValue: true,
|
data: { dynamic: "Dynamic", dynamicLuminance: "Dynamic (Luminance)", static: "Static" },
|
||||||
onChange: (val) => updateColors(),
|
defaultValue: "dynamic",
|
||||||
showChildren: (val) => !val,
|
onChange: () => updateColors(),
|
||||||
|
showChildren: (val) => {
|
||||||
|
if (val == "dynamicLuminance") return ["lightModeLuminance", "darkModeLuminance"];
|
||||||
|
if (val == "static") return ["colorOverride"];
|
||||||
|
return false;
|
||||||
|
},
|
||||||
children: [
|
children: [
|
||||||
|
{
|
||||||
|
type: "number",
|
||||||
|
key: "lightModeLuminance",
|
||||||
|
name: "Desired Light Mode Luminance",
|
||||||
|
description: `
|
||||||
|
Set desired luminance in light mode.
|
||||||
|
*the selected color will be the one who's luminance is closest to the desired luminance*{.muted}
|
||||||
|
`,
|
||||||
|
defaultValue: 0.6,
|
||||||
|
data: { min: 0, max: 1, step: 0.05 },
|
||||||
|
fireInitialChange: false,
|
||||||
|
onChange: () => updateColors()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "number",
|
||||||
|
key: "darkModeLuminance",
|
||||||
|
name: "Desired Dark Mode Luminance",
|
||||||
|
description: `
|
||||||
|
Set desired luminance in dark mode.
|
||||||
|
*the selected color will be the one who's luminance is closest to the desired luminance*{.muted}
|
||||||
|
`,
|
||||||
|
defaultValue: 0.2,
|
||||||
|
data: { min: 0, max: 1, step: 0.05 },
|
||||||
|
fireInitialChange: false,
|
||||||
|
onChange: () => updateColors()
|
||||||
|
},
|
||||||
{
|
{
|
||||||
type: "color",
|
type: "color",
|
||||||
key: "colorOverride",
|
key: "colorOverride",
|
||||||
|
|
@ -532,7 +562,7 @@ Dribbblish.config.register({
|
||||||
description: "The Color of the Theme",
|
description: "The Color of the Theme",
|
||||||
defaultValue: "#1ed760",
|
defaultValue: "#1ed760",
|
||||||
fireInitialChange: false,
|
fireInitialChange: false,
|
||||||
onChange: (val) => updateColors()
|
onChange: () => updateColors()
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
@ -540,7 +570,7 @@ Dribbblish.config.register({
|
||||||
Dribbblish.config.register({
|
Dribbblish.config.register({
|
||||||
area: "Theme",
|
area: "Theme",
|
||||||
type: "select",
|
type: "select",
|
||||||
data: { dark: "Dark", light: "Light", time: "Based on Time", color: "Based on Color" },
|
data: { dark: "Dark", light: "Light", time: "Based on Time" },
|
||||||
key: "theme",
|
key: "theme",
|
||||||
name: "Theme",
|
name: "Theme",
|
||||||
description: "Select Dark / Bright mode",
|
description: "Select Dark / Bright mode",
|
||||||
|
|
@ -560,9 +590,6 @@ Dribbblish.config.register({
|
||||||
case "time":
|
case "time":
|
||||||
checkDarkLightMode();
|
checkDarkLightMode();
|
||||||
break;
|
break;
|
||||||
case "color":
|
|
||||||
checkDarkLightMode();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
|
|
@ -587,19 +614,8 @@ Dribbblish.config.register({
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
var currentSideColor;
|
function updateColors(checkDarkMode = true, sideColHex) {
|
||||||
|
if (sideColHex == undefined) return registerCoverListener();
|
||||||
function updateColors(sideColHex, checkDarkMode = true) {
|
|
||||||
if (sideColHex) {
|
|
||||||
currentSideColor = sideColHex;
|
|
||||||
} else {
|
|
||||||
if (!currentSideColor) return; // If `updateColors()` is called early these vars are undefined and would break
|
|
||||||
sideColHex = currentSideColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Dribbblish.config.get("dynamicColors")) {
|
|
||||||
sideColHex = Dribbblish.config.get("colorOverride");
|
|
||||||
}
|
|
||||||
|
|
||||||
let isLightBg = isLight(textColorBg);
|
let isLightBg = isLight(textColorBg);
|
||||||
let textColHex = sideColHex;
|
let textColHex = sideColHex;
|
||||||
|
|
@ -653,7 +669,6 @@ async function songchange() {
|
||||||
let bgImage = Spicetify.Player.data.track.metadata.image_url;
|
let bgImage = Spicetify.Player.data.track.metadata.image_url;
|
||||||
if (bgImage === undefined) {
|
if (bgImage === undefined) {
|
||||||
bgImage = "/images/tracklist-row-song-fallback.svg";
|
bgImage = "/images/tracklist-row-song-fallback.svg";
|
||||||
updateColors("#509bf5");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (album_uri !== undefined && !album_uri.includes("spotify:show")) {
|
if (album_uri !== undefined && !album_uri.includes("spotify:show")) {
|
||||||
|
|
@ -698,19 +713,25 @@ async function pickCoverColor(img) {
|
||||||
|
|
||||||
sidebarColor = "#509bf5";
|
sidebarColor = "#509bf5";
|
||||||
if (img.complete) {
|
if (img.complete) {
|
||||||
const dominant = colorThief.getColor(img);
|
const palette = Object.fromEntries([colorThief.getColor(img), ...colorThief.getPalette(img, 24, 5)].map((c) => chroma(c)).map((c) => [c.luminance(), c]));
|
||||||
let palette = colorThief.getPalette(img);
|
const colorSelectionMode = Dribbblish.config.get("colorSelectionMode");
|
||||||
palette.unshift(dominant);
|
if (colorSelectionMode == "dynamic") {
|
||||||
sidebarColor = chroma(dominant).hex();
|
sidebarColor = Object.values(palette)[0];
|
||||||
for (const col of palette) {
|
for (const col of Object.values(palette)) {
|
||||||
const chrmCol = chroma(col);
|
if (col.luminance() > 0.05 && col.luminance() < 0.9) {
|
||||||
if (chrmCol.luminance() > 0.05 && chrmCol.luminance() < 0.9) {
|
sidebarColor = col.hex();
|
||||||
sidebarColor = chrmCol.hex();
|
break;
|
||||||
break;
|
}
|
||||||
}
|
}
|
||||||
|
} else if (colorSelectionMode == "dynamicLuminance") {
|
||||||
|
const wantedLuminance = $("html").css("--is_light") == "1" ? Dribbblish.config.get("lightModeLuminance") : Dribbblish.config.get("darkModeLuminance");
|
||||||
|
sidebarColor = palette[getClosestToNum(Object.keys(palette), wantedLuminance)].hex();
|
||||||
|
} else if (colorSelectionMode == "static") {
|
||||||
|
sidebarColor = Dribbblish.config.get("colorOverride");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateColors(sidebarColor);
|
|
||||||
|
updateColors(false, sidebarColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
var coverListener;
|
var coverListener;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue