Fixed accent colors

This commit is contained in:
nutty
2026-06-28 04:29:26 +10:00
parent 9e175e2ac7
commit 79edc15f0b
3 changed files with 12 additions and 30 deletions
+1 -1
View File
@@ -83,7 +83,7 @@
}, },
{ {
"id": "showAlbumArt", "id": "showAlbumArt",
"label": "Show AlbumArt", "label": "Show Album Art",
"description": "", "description": "",
"type": "checkbox", "type": "checkbox",
"defaultValue": true, "defaultValue": true,
+2 -22
View File
@@ -33,23 +33,6 @@ CORS(app)
# --- GLOBAL MEMORY CACHE --- # --- GLOBAL MEMORY CACHE ---
ARTWORK_CACHE = {} ARTWORK_CACHE = {}
def get_smart_accent(img):
"""Sorts pixels by saturation to find the most vibrant color."""
thumb = img.copy()
thumb.thumbnail((20, 20)) # Higher sample rate than 1x1
pixels = list(thumb.getdata())
# Sort by saturation: (max_channel - min_channel)
pixels.sort(key=lambda p: max(p) - min(p), reverse=True)
best_rgb = pixels[0]
# Safety boost: ensure it's readable and vibrant
min_val = 80
rgb = [max(c, min_val) for c in best_rgb]
rgb = [min(int(c * 1.2), 255) for c in rgb]
return '#{:02x}{:02x}{:02x}'.format(*rgb)
async def get_all_media_info(): async def get_all_media_info():
global ARTWORK_CACHE global ARTWORK_CACHE
import winsdk._winrt import winsdk._winrt
@@ -90,11 +73,10 @@ async def get_all_media_info():
artist = raw_media.artist if raw_media else "Unknown" artist = raw_media.artist if raw_media else "Unknown"
track_key = f"{title} - {artist}" track_key = f"{title} - {artist}"
media_data = {"Title": title, "Artist": artist, "Base64Image": None, "AccentColor": "#ffffff"} media_data = {"Title": title, "Artist": artist, "Base64Image": None}
if app_id in ARTWORK_CACHE and ARTWORK_CACHE[app_id]["track_key"] == track_key: if app_id in ARTWORK_CACHE and ARTWORK_CACHE[app_id]["track_key"] == track_key:
media_data["Base64Image"] = ARTWORK_CACHE[app_id]["base64"] media_data["Base64Image"] = ARTWORK_CACHE[app_id]["base64"]
media_data["AccentColor"] = ARTWORK_CACHE[app_id]["accent"]
elif raw_media and raw_media.thumbnail: elif raw_media and raw_media.thumbnail:
try: try:
@@ -106,12 +88,10 @@ async def get_all_media_info():
reader.read_bytes(buffer) reader.read_bytes(buffer)
img = Image.open(io.BytesIO(buffer)) img = Image.open(io.BytesIO(buffer))
hex_color = get_smart_accent(img)
base64_art = f"data:image/png;base64,{base64.b64encode(buffer).decode('utf-8')}" base64_art = f"data:image/png;base64,{base64.b64encode(buffer).decode('utf-8')}"
ARTWORK_CACHE[app_id] = {"track_key": track_key, "base64": base64_art, "accent": hex_color} ARTWORK_CACHE[app_id] = {"track_key": track_key, "base64": base64_art}
media_data["Base64Image"] = base64_art media_data["Base64Image"] = base64_art
media_data["AccentColor"] = hex_color
except Exception: except Exception:
pass pass
+9 -7
View File
@@ -51,7 +51,7 @@ if (!showProgressBar)
//////////////////// ////////////////////
// Each theme must implement the following // Each theme must implement the following
function UpdatePlayerState(data) { async function UpdatePlayerState(data) {
// Check if the user has provided a target application in the settings // Check if the user has provided a target application in the settings
const isFiltering = targetApplication && targetApplication.trim() !== ""; const isFiltering = targetApplication && targetApplication.trim() !== "";
@@ -73,6 +73,9 @@ function UpdatePlayerState(data) {
const mediaProps = targetSession.media_properties; const mediaProps = targetSession.media_properties;
const timelineProps = targetSession.timeline_properties; const timelineProps = targetSession.timeline_properties;
// Calcualte an accent color
const accentColorPalette = await GetAccentPalette(mediaProps.Base64Image);
// 1. Check if playback status has changed and update visibility accordingly // 1. Check if playback status has changed and update visibility accordingly
if (playbackInfo.PlaybackStatus !== CurrentPlaybackStatus) { if (playbackInfo.PlaybackStatus !== CurrentPlaybackStatus) {
if (playbackInfo.PlaybackStatus === PlaybackStatus.PLAYING) if (playbackInfo.PlaybackStatus === PlaybackStatus.PLAYING)
@@ -85,7 +88,7 @@ function UpdatePlayerState(data) {
// 2. Check if the track name/artist have changed - this is our indicator that the next track has loaded // 2. Check if the track name/artist have changed - this is our indicator that the next track has loaded
const newTrackKey = `${mediaProps.Title}|${mediaProps.Artist}`; const newTrackKey = `${mediaProps.Title}|${mediaProps.Artist}`;
if (newTrackKey !== CurrentSong) { if (newTrackKey !== CurrentSong) {
ChangeTrack(mediaProps); // Now trigger your cross-fade logic here! ChangeTrack(mediaProps, accentColorPalette.LightVibrant); // Now trigger your cross-fade logic here!
CurrentSong = newTrackKey; // Update the tracker with the string key CurrentSong = newTrackKey; // Update the tracker with the string key
} }
@@ -116,7 +119,7 @@ function UpdatePlayerState(data) {
let progressPercent = durationMs > 0 ? (currentPositionMs / durationMs) * 100 : 0; let progressPercent = durationMs > 0 ? (currentPositionMs / durationMs) * 100 : 0;
progressPercent = Math.min(100, Math.max(0, progressPercent)); progressPercent = Math.min(100, Math.max(0, progressPercent));
progressBarFill.style.width = `${progressPercent}%`; progressBarFill.style.width = `${progressPercent}%`;
progressBarFill.style.setProperty('--accent-color', mediaProps.AccentColor); progressBarFill.style.setProperty('--accent-color', accentColorPalette.LightVibrant);
} }
} }
else else
@@ -152,7 +155,7 @@ function SetVisibility(visible) {
} }
} }
async function ChangeTrack(mediaProps) { async function ChangeTrack(mediaProps, tintColor) {
// Fade in the overlay (shows the new text) // Fade in the overlay (shows the new text)
trackLabel.style.opacity = "0"; trackLabel.style.opacity = "0";
artistLabel.style.opacity = "0"; artistLabel.style.opacity = "0";
@@ -166,7 +169,6 @@ async function ChangeTrack(mediaProps) {
// Extract the image source string (use fallback if Windows has no art) // Extract the image source string (use fallback if Windows has no art)
const newArtUrl = mediaProps.Base64Image; const newArtUrl = mediaProps.Base64Image;
const accent = mediaProps.AccentColor || "#ffffff";
// Set the image // Set the image
backgroundLayer.style.backgroundImage = `url('${newArtUrl}')`; backgroundLayer.style.backgroundImage = `url('${newArtUrl}')`;
@@ -174,7 +176,7 @@ async function ChangeTrack(mediaProps) {
// Apply a tint: Use 30% opacity of the accent color + a dark overlay for contrast // Apply a tint: Use 30% opacity of the accent color + a dark overlay for contrast
// 'rgba(0,0,0,0.6)' ensures the text stays readable // 'rgba(0,0,0,0.6)' ensures the text stays readable
backgroundLayer.style.backgroundColor = accent + "80"; // 80 is 50% opacity in hex backgroundLayer.style.backgroundColor = tintColor + "80"; // 80 is 50% opacity in hex
trackLabel.style.opacity = ""; trackLabel.style.opacity = "";
artistLabel.style.opacity = ""; artistLabel.style.opacity = "";
@@ -188,7 +190,7 @@ async function ChangeTrack(mediaProps) {
// Apply a tint: Use 30% opacity of the accent color + a dark overlay for contrast // Apply a tint: Use 30% opacity of the accent color + a dark overlay for contrast
// 'rgba(0,0,0,0.6)' ensures the text stays readable // 'rgba(0,0,0,0.6)' ensures the text stays readable
backgroundTransitionLayer.style.backgroundColor = accent + "80"; // 80 is 50% opacity in hex backgroundTransitionLayer.style.backgroundColor = tintColor + "80"; // 80 is 50% opacity in hex
SetVisibility(true); // Show the overlay for a few seconds if autoHide is enabled SetVisibility(true); // Show the overlay for a few seconds if autoHide is enabled
}, 250); }, 250);