feat: Album Color Theme plugin

Co-authored-by: EdiBOI25 <86252338+EdiBOI25@users.noreply.github.com>
This commit is contained in:
JellyBrick
2023-09-27 18:19:23 +09:00
parent 170e2a696e
commit 6bb33453c7
6 changed files with 483 additions and 16 deletions

View File

@ -0,0 +1,39 @@
import path from 'node:path';
import { getAverageColor } from 'fast-average-color-node';
import { BrowserWindow } from 'electron';
import { injectCSS } from '../utils';
import registerCallback from '../../providers/song-info';
export default (win: BrowserWindow) => {
injectCSS(win.webContents, path.join(__dirname, 'style.css'));
registerCallback((songInfo) => {
const songTitle = songInfo.title;
const songImage = songInfo.imageSrc;
if (songImage && songTitle) {
getAverageColor(songImage)
.then((color) => {
//div.style.backgroundColor = color.rgba;
//console.log('Average color', color);
if (color.hex === '#000000') {
color.rgb = 'rgb(238,238,238)';
color.isDark = false;
color.isLight = true;
} else if (color.hex === '#ffffff') {
color.rgb = 'rgb(0,0,0)';
color.isDark = true;
color.isLight = false;
}
win.webContents.send('album-color-changed', color);
})
.catch((e) => {
console.error(e);
});
}
});
};

View File

@ -0,0 +1,113 @@
import { ipcRenderer } from 'electron';
import type { FastAverageColorResult } from 'fast-average-color';
function hexToHSL(H: string) {
// Convert hex to RGB first
let r = 0;
let g = 0;
let b = 0;
if (H.length == 4) {
r = Number('0x' + H[1] + H[1]);
g = Number('0x' + H[2] + H[2]);
b = Number('0x' + H[3] + H[3]);
} else if (H.length == 7) {
r = Number('0x' + H[1] + H[2]);
g = Number('0x' + H[3] + H[4]);
b = Number('0x' + H[5] + H[6]);
}
// Then to HSL
r /= 255;
g /= 255;
b /= 255;
const cmin = Math.min(r, g, b);
const cmax = Math.max(r, g, b);
const delta = cmax - cmin;
let h: number;
let s: number;
let l: number;
if (delta == 0) {
h = 0;
} else if (cmax == r) {
h = ((g - b) / delta) % 6;
} else if (cmax == g) {
h = ((b - r) / delta) + 2;
} else {
h = ((r - g) / delta) + 4;
}
h = Math.round(h * 60);
if (h < 0) {
h += 360;
}
l = (cmax + cmin) / 2;
s = delta == 0 ? 0 : delta / (1 - Math.abs((2 * l) - 1));
s = +(s * 100).toFixed(1);
l = +(l * 100).toFixed(1);
//return "hsl(" + h + "," + s + "%," + l + "%)";
return [h,s,l];
}
// updated elements
const playerPage = document.querySelector<HTMLElement>('#player-page');
const navBarBackground = document.querySelector<HTMLElement>('#nav-bar-background');
const ytmusicPlayerBar = document.querySelector<HTMLElement>('ytmusic-player-bar');
const playerBarBackground = document.querySelector<HTMLElement>('#player-bar-background');
const sidebarBig = document.querySelector<HTMLElement>('#guide-wrapper');
const sidebarSmall = document.querySelector<HTMLElement>('#mini-guide-background');
const ytmusicAppLayout = document.querySelector<HTMLElement>('#layout');
let hue = 0;
let saturation = 0;
let lightness = 0;
function changeElementColor(element: HTMLElement | null, hue: number, saturation: number, lightness: number){
if (element) {
element.style.backgroundColor = `hsl(${hue}, ${saturation}%, ${lightness}%)`;
}
}
export default () => {
const observer = new MutationObserver((mutationsList) => {
for (const mutation of mutationsList) {
if (mutation.type === 'attributes') {
const isPageOpen = ytmusicAppLayout?.hasAttribute('player-page-open');
if (isPageOpen) {
changeElementColor(sidebarSmall, hue, saturation, 30);
} else {
if (sidebarSmall) {
sidebarSmall.style.backgroundColor = 'black';
}
}
}
}
});
if (playerPage) {
observer.observe(playerPage, { attributes: true });
}
ipcRenderer.on('album-color-changed', (_, albumColor: FastAverageColorResult) => {
if (albumColor) {
[hue, saturation, lightness] = hexToHSL(albumColor.hex);
changeElementColor(playerPage, hue, saturation, 30);
changeElementColor(navBarBackground, hue, saturation, 15);
changeElementColor(ytmusicPlayerBar, hue, saturation, 15);
changeElementColor(playerBarBackground, hue, saturation, 15);
changeElementColor(sidebarBig, hue, saturation, 15);
if (ytmusicAppLayout?.hasAttribute('player-page-open')) {
changeElementColor(sidebarSmall, hue, saturation, 30);
}
const ytRightClickList = document.querySelector<HTMLElement>('tp-yt-paper-listbox');
changeElementColor(ytRightClickList, hue, saturation, 15);
} else {
if (playerPage) {
playerPage.style.backgroundColor = '#000000';
}
}
});
};

View File

@ -0,0 +1,29 @@
yt-page-navigation-progress {
--yt-page-navigation-container-color: #00000046 !important;
--yt-page-navigation-progress-color: white !important;
}
#player-page {
transition: transform 300ms,background-color 300ms cubic-bezier(0.2,0,0.6,1) !important;
}
#nav-bar-background {
transition: opacity 200ms,background-color 300ms cubic-bezier(0.2,0,0.6,1) !important;
}
#mini-guide-background {
transition: opacity 200ms,background-color 300ms cubic-bezier(0.2,0,0.6,1) !important;
border-right: 0px !important;
}
#guide-wrapper {
transition: opacity 200ms,background-color 300ms cubic-bezier(0.2,0,0.6,1) !important;
}
#img, #player, .song-media-controls.style-scope.ytmusic-player {
border-radius: 2% !important;
}
#items {
border-radius: 10px !important;
}

View File

@ -5,6 +5,8 @@ import { Color, Titlebar } from 'custom-electron-titlebar';
import config from '../../config';
import { isEnabled } from '../../config/plugins';
import type { FastAverageColorResult } from 'fast-average-color';
function $(selector: string) {
return document.querySelector(selector);
}
@ -38,6 +40,16 @@ export default () => {
}
});
if (isEnabled('album-color-theme')) {
ipcRenderer.on('album-color-changed', (_, albumColor: FastAverageColorResult) => {
if (albumColor) {
bar.updateBackground(Color.fromHex(albumColor.hexa));
} else {
bar.updateBackground(Color.fromHex('#050505'));
}
});
}
if (isEnabled('picture-in-picture')) {
ipcRenderer.on('pip-toggle', () => {
bar.refreshMenu();