From 8faa22a312b550b5adee10022664ae7706924f11 Mon Sep 17 00:00:00 2001 From: Damjan Antevski Date: Sat, 8 Aug 2026 09:16:11 +0200 Subject: [PATCH] feat(theme): add color customization for player and progress bars --- README.md | 6 +++- theme.js | 104 +++++++++++++++++++++++++++++++++++++++++++++++++----- user.css | 20 ++++++----- 3 files changed, 111 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 4f56d94..5a38153 100644 --- a/README.md +++ b/README.md @@ -76,8 +76,12 @@ Type `help` in the SpoTUI command bar to see a list of available commands. | `tui -wp [-o ]` | Set wallpaper (opacity 0-1) | | `tui -t pull ` | Apply a theme by its ID (you can find the id on our website) | | `tui -wp off` | Remove wallpaper | -| `tui -ly -cp ` | Set lyrics colors (hex) | +| `tui -ly -cp -active <#hex> -inactive <#hex> -near <#hex>` | Set lyrics colors | | `tui -ly -cp off` | Reset lyrics colors | +| `tui -bar -bg <#hex> -border <#hex> -text <#hex>` | Set player bar colors | +| `tui -bar off` | Reset player bar colors | +| `tui -progress -bg <#hex> -fg <#hex>` | Set progress bar colors | +| `tui -progress off` | Reset progress bar colors | | `playlist` / `list` | Open playlist viewer | | `play` / `pause` / `p` | Toggle playback | | `skip` | Next track | diff --git a/theme.js b/theme.js index 5a946db..09e2ee8 100644 --- a/theme.js +++ b/theme.js @@ -1029,6 +1029,42 @@ function applyLyricColors() { } } +function applyPlayerBarColors() { + try { + const bg = localStorage.getItem(PLAYER_BAR_BG); + const border = localStorage.getItem(PLAYER_BAR_BORDER); + const text = localStorage.getItem(PLAYER_BAR_TEXT); + + const root = document.documentElement; + if (bg) root.style.setProperty("--player-bar-background", bg); + else root.style.removeProperty("--player-bar-background"); + + if (border) root.style.setProperty("--player-bar-border-color", border); + else root.style.removeProperty("--player-bar-border-color"); + + if (text) root.style.setProperty("--player-bar-text-color", text); + else root.style.removeProperty("--player-bar-text-color"); + } catch (e) { + console.error("SpoTUI: Failed to apply player bar colors", e); + } +} + +function applyProgressBarColors() { + try { + const bg = localStorage.getItem(PROGRESS_BAR_BG); + const fg = localStorage.getItem(PROGRESS_BAR_FG); + + const root = document.documentElement; + if (bg) root.style.setProperty("--progress-bar-background", bg); + else root.style.removeProperty("--progress-bar-background"); + + if (fg) root.style.setProperty("--progress-bar-foreground", fg); + else root.style.removeProperty("--progress-bar-foreground"); + } catch (e) { + console.error("SpoTUI: Failed to apply progress bar colors", e); + } +} + function setTuiMode(mode) { tuiMode = mode === "cli" ? "cli" : "command"; document.body.classList.toggle("spotui-cli-mode", tuiMode === "cli"); @@ -1263,23 +1299,53 @@ async function execute(cmd) { return; } if (args.includes("-ly") && args.includes("-cp")) { - const cpIndex = args.indexOf("-cp"); - if (args[cpIndex + 1] === "off") { + if (args.includes("off")) { localStorage.removeItem(LYRICS_COLOR_ACTIVE); localStorage.removeItem(LYRICS_COLOR_INACTIVE); localStorage.removeItem(LYRICS_COLOR_LIGHT_INACTIVE); } else { - const colorActive = args[cpIndex + 1]; - const colorInactive = args[cpIndex + 2]; - const colorLightInactive = args[cpIndex + 3]; + const activeIndex = args.indexOf("-active"); + const inactiveIndex = args.indexOf("-inactive"); + const nearIndex = args.indexOf("-near"); - if (colorActive) localStorage.setItem(LYRICS_COLOR_ACTIVE, colorActive); - if (colorInactive) localStorage.setItem(LYRICS_COLOR_INACTIVE, colorInactive); - if (colorLightInactive) localStorage.setItem(LYRICS_COLOR_LIGHT_INACTIVE, colorLightInactive); + if (activeIndex !== -1) localStorage.setItem(LYRICS_COLOR_ACTIVE, args[activeIndex + 1]); + if (inactiveIndex !== -1) localStorage.setItem(LYRICS_COLOR_INACTIVE, args[inactiveIndex + 1]); + if (nearIndex !== -1) localStorage.setItem(LYRICS_COLOR_LIGHT_INACTIVE, args[nearIndex + 1]); } applyLyricColors(); return; } + if (args.includes("-bar")) { + if (args.includes("off")) { + localStorage.removeItem(PLAYER_BAR_BG); + localStorage.removeItem(PLAYER_BAR_BORDER); + localStorage.removeItem(PLAYER_BAR_TEXT); + } else { + const bgIndex = args.indexOf("-bg"); + const borderIndex = args.indexOf("-border"); + const textIndex = args.indexOf("-text"); + + if (bgIndex !== -1) localStorage.setItem(PLAYER_BAR_BG, args[bgIndex + 1]); + if (borderIndex !== -1) localStorage.setItem(PLAYER_BAR_BORDER, args[borderIndex + 1]); + if (textIndex !== -1) localStorage.setItem(PLAYER_BAR_TEXT, args[textIndex + 1]); + } + applyPlayerBarColors(); + return; + } + if (args.includes("-progress")) { + if (args.includes("off")) { + localStorage.removeItem(PROGRESS_BAR_BG); + localStorage.removeItem(PROGRESS_BAR_FG); + } else { + const bgIndex = args.indexOf("-bg"); + const fgIndex = args.indexOf("-fg"); + + if (bgIndex !== -1) localStorage.setItem(PROGRESS_BAR_BG, args[bgIndex + 1]); + if (fgIndex !== -1) localStorage.setItem(PROGRESS_BAR_FG, args[fgIndex + 1]); + } + applyProgressBarColors(); + return; + } if (args.includes("-l") || args.includes("-a")) { const state = args[args.length - 1]; if (state === "off") { @@ -1373,8 +1439,12 @@ const COMMAND_LIST = [ { cmd: "tui -wp <url> [-o <opacity>]", desc: "Set wallpaper (opacity 0-1)" }, { cmd: "tui -wp off", desc: "Remove wallpaper" }, { cmd: "tui -t pull <theme_id>", desc: "Apply a theme by its ID (you can find the id on our website)" }, - { cmd: "tui -ly -cp <active> <inactive> <light_inactive>", desc: "Set lyrics colors (hex)" }, + { cmd: "tui -ly -cp -active <#hex> -inactive <#hex> -near <#hex>", desc: "Set lyrics colors" }, { cmd: "tui -ly -cp off", desc: "Reset lyrics colors" }, + { cmd: "tui -bar -bg <#hex> -border <#hex> -text <#hex>", desc: "Set player bar colors" }, + { cmd: "tui -bar off", desc: "Reset player bar colors" }, + { cmd: "tui -progress -bg <#hex> -fg <#hex>", desc: "Set progress bar colors" }, + { cmd: "tui -progress off", desc: "Reset progress bar colors" }, { cmd: "playlist / list", desc: "Open playlist viewer" }, { cmd: "play / pause / p", desc: "Toggle playback" }, { cmd: "skip", desc: "Next track" }, @@ -1778,6 +1848,11 @@ const WP_OPACITY_KEY = "spotui:wp-opacity"; const LYRICS_COLOR_ACTIVE = "spotui:lyrics-color-active"; const LYRICS_COLOR_INACTIVE = "spotui:lyrics-color-inactive"; const LYRICS_COLOR_LIGHT_INACTIVE = "spotui:lyrics-color-light-inactive"; +const PLAYER_BAR_BG = "spotui:player-bar-bg"; +const PLAYER_BAR_BORDER = "spotui:player-bar-border"; +const PLAYER_BAR_TEXT = "spotui:player-bar-text"; +const PROGRESS_BAR_BG = "spotui:progress-bar-bg"; +const PROGRESS_BAR_FG = "spotui:progress-bar-fg"; let lyricsPanelOpen = false; let lyricsLoadToken = 0; @@ -2088,6 +2163,15 @@ function resetAllSettings() { localStorage.removeItem(LYRICS_COLOR_INACTIVE); localStorage.removeItem(LYRICS_COLOR_LIGHT_INACTIVE); applyLyricColors(); + + localStorage.removeItem(PLAYER_BAR_BG); + localStorage.removeItem(PLAYER_BAR_BORDER); + localStorage.removeItem(PLAYER_BAR_TEXT); + applyPlayerBarColors(); + + localStorage.removeItem(PROGRESS_BAR_BG); + localStorage.removeItem(PROGRESS_BAR_FG); + applyProgressBarColors(); } injectStyle(); @@ -2104,6 +2188,8 @@ try { setTimeout(() => setWallpaper(localStorage.getItem(WP_URL_KEY), localStorage.getItem(WP_OPACITY_KEY) || "1", false), 1500); } applyLyricColors(); + applyPlayerBarColors(); + applyProgressBarColors(); } catch { } })(); diff --git a/user.css b/user.css index 0a870e6..ac25e6a 100644 --- a/user.css +++ b/user.css @@ -147,10 +147,10 @@ body.spotui-spotify-enabled .Root__globalNav .main-globalNav-searchInputTextWrap display: flex !important; align-items: center !important; justify-content: space-between !important; - background: #000 !important; - border-top: 1px solid #ff8c42; + background: var(--player-bar-background, #000) !important; + border-top: 1px solid var(--player-bar-border-color, #ff8c42); box-shadow: inset 0 1px 0 rgba(255, 140, 66, 0.18); - color: #ddd !important; + color: var(--player-bar-text-color, #ddd) !important; font-family: "JetBrains Mono", "Fira Code", monospace !important; } @@ -180,14 +180,15 @@ body.spotui-spotify-enabled .Root__globalNav .main-globalNav-searchInputTextWrap } .Root__now-playing-bar .main-trackInfo-name { - color: #ff8c42 !important; + color: var(--player-bar-text-color, #ff8c42) !important; font-family: inherit !important; letter-spacing: 0.02em; } .Root__now-playing-bar .main-trackInfo-artists a, .Root__now-playing-bar .main-trackInfo-artists { - color: #b8b8b8 !important; + color: var(--player-bar-text-color, #b8b8b8) !important; + opacity: 0.7; font-family: inherit !important; } @@ -195,24 +196,25 @@ body.spotui-spotify-enabled .Root__globalNav .main-globalNav-searchInputTextWrap .Root__now-playing-bar .main-nowPlayingBar-container [role="button"], .Root__now-playing-bar .volume-bar__icon-button { border-radius: 0 !important; - color: #ff8c42 !important; + color: var(--player-bar-text-color, #ff8c42) !important; } .Root__now-playing-bar .main-nowPlayingBar-container button:hover, .Root__now-playing-bar .main-nowPlayingBar-container [role="button"]:hover, .Root__now-playing-bar .volume-bar__icon-button:hover { - color: #ffb26f !important; + color: var(--player-bar-text-color, #ffb26f) !important; + opacity: 0.8; } .Root__now-playing-bar .x-progressBar-progressBarBg, .Root__now-playing-bar .x-progressBar-progressBar { - background: #202020 !important; + background: var(--progress-bar-background, #202020) !important; } .Root__now-playing-bar .x-progressBar-progressFillColor, .Root__now-playing-bar .x-progressBar-fillColor, .Root__now-playing-bar .x-progressBar-handle { - background: #ff8c42 !important; + background: var(--progress-bar-foreground, #ff8c42) !important; } .Root__now-playing-bar .volume-bar {