mirror of
https://github.com/nuttylmao/nutty.gg.git
synced 2026-09-19 04:00:59 -04:00
Fixed accent colors
This commit is contained in:
@@ -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,
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user