diff --git a/plugin/contents/ui/dancer.html b/plugin/contents/ui/dancer.html
index 0602200..75b0ab3 100644
--- a/plugin/contents/ui/dancer.html
+++ b/plugin/contents/ui/dancer.html
@@ -237,38 +237,29 @@ html, body {
}
/* ============================================================
- LYRICS DISPLAY — verse karaoke
+ LYRICS DISPLAY
============================================================ */
.lyric-display {
position: absolute;
left: 2%;
top: 4%;
- width: 38%;
- height: 150px; /* 5 visible slots × 30px */
- overflow: hidden;
+ max-width: 36%;
pointer-events: none;
opacity: 0;
transition: opacity 0.5s ease;
- -webkit-mask-image: linear-gradient(to bottom, transparent 0%, black 15%, black 85%, transparent 100%);
- mask-image: linear-gradient(to bottom, transparent 0%, black 15%, black 85%, transparent 100%);
}
-.lyric-ctx {
- position: absolute;
- left: 0;
- width: 100%;
- height: 30px;
- line-height: 30px;
+.lyric-line {
+ color: #ffffff;
font-family: 'Courier New', monospace;
- letter-spacing: 0.02em;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- transition:
- top 0.5s cubic-bezier(0.4, 0, 0.2, 1),
- opacity 0.45s ease,
- font-size 0.35s ease,
- color 0.35s ease,
- text-shadow 0.35s ease;
+ font-size: clamp(16px, 1.3vw, 18px);
+ line-height: 1.5;
+ letter-spacing: 0.03em;
+ text-shadow:
+ 0 0 18px var(--theme-color, rgba(0,200,255,0.85)),
+ 0 0 6px var(--theme-color, rgba(0,200,255,0.5)),
+ 0 2px 10px rgba(0,0,0,0.95),
+ -1px -1px 0 rgba(0,0,0,0.7),
+ 1px 1px 0 rgba(0,0,0,0.7);
}
/* ============================================================
@@ -896,8 +887,10 @@ html, body {
-
-
+
+
@@ -1170,98 +1163,13 @@ function applyTheme(rgb) {
});
}
-const albumArtEl = document.getElementById('albumArt');
-const fogWisps = document.querySelectorAll('.fog-wisp');
+const albumArtEl = document.getElementById('albumArt');
+const fogWisps = document.querySelectorAll('.fog-wisp');
const lyricDisplay = document.getElementById('lyricDisplay');
+const lyricLineEl = document.getElementById('lyricLine');
-let lastArtUrl = '';
-
-/* ── verse display ── */
-const SLOT_H = 30;
-const CENTER_PX = 60; // top of the active slot within the 150px container
-
-const ACTIVE_SHADOW =
- '0 0 18px var(--theme-color,rgba(0,200,255,0.85)),' +
- '0 0 6px var(--theme-color,rgba(0,200,255,0.5)),' +
- '0 2px 10px rgba(0,0,0,0.95)';
-
-const VERSE_STYLES = [
- { opacity:'0.2', fontSize:'clamp(11px,0.85vw,13px)', color:'#777', shadow:'' }, // dist -2
- { opacity:'0.48', fontSize:'clamp(13px,1.0vw,15px)', color:'#bbb', shadow:'' }, // dist -1
- { opacity:'1', fontSize:'clamp(16px,1.3vw,18px)', color:'#fff', shadow: ACTIVE_SHADOW }, // dist 0
- { opacity:'0.48', fontSize:'clamp(13px,1.0vw,15px)', color:'#bbb', shadow:'' }, // dist +1
- { opacity:'0.2', fontSize:'clamp(11px,0.85vw,13px)', color:'#777', shadow:'' }, // dist +2
-];
-
-let verseEls = [];
-let currentVerseKey = '';
-let currentVerseActive = -1;
-
-function applyVerseStyle(el, dist) {
- if (dist < -2 || dist > 2) {
- el.style.opacity = '0'; el.style.fontSize = 'clamp(11px,0.85vw,13px)';
- el.style.color = '#777'; el.style.textShadow = ''; return;
- }
- const p = VERSE_STYLES[dist + 2];
- el.style.opacity = p.opacity;
- el.style.fontSize = p.fontSize;
- el.style.color = p.color;
- el.style.textShadow = p.shadow;
-}
-
-function positionVerseEls(verse_active) {
- verseEls.forEach((el, i) => {
- const dist = i - verse_active;
- el.style.top = (CENTER_PX + dist * SLOT_H) + 'px';
- applyVerseStyle(el, dist);
- });
-}
-
-function buildVerse(verse_lines, verse_active) {
- lyricDisplay.innerHTML = '';
- verseEls = verse_lines.map(text => {
- const el = document.createElement('div');
- el.className = 'lyric-ctx';
- el.textContent = text;
- el.style.transition = 'none';
- lyricDisplay.appendChild(el);
- return el;
- });
- positionVerseEls(verse_active);
- requestAnimationFrame(() => requestAnimationFrame(() => {
- verseEls.forEach(el => { el.style.transition = ''; });
- }));
-}
-
-function updateLyricVerse(verse_lines, verse_active) {
- if (!verse_lines || !verse_lines.length || verse_active < 0 || !isPlaying) {
- lyricDisplay.style.opacity = '0';
- currentVerseKey = '';
- currentVerseActive = -1;
- return;
- }
- const verseKey = verse_lines.join('\x00');
-
- if (verseKey !== currentVerseKey) {
- currentVerseKey = verseKey;
- currentVerseActive = verse_active;
- if (lyricDisplay.style.opacity === '1') {
- lyricDisplay.style.opacity = '0';
- setTimeout(() => {
- buildVerse(verse_lines, verse_active);
- lyricDisplay.style.opacity = '1';
- }, 500);
- } else {
- buildVerse(verse_lines, verse_active);
- lyricDisplay.style.opacity = '1';
- }
- } else if (verse_active !== currentVerseActive) {
- currentVerseActive = verse_active;
- positionVerseEls(verse_active);
- } else {
- lyricDisplay.style.opacity = '1';
- }
-}
+let lastArtUrl = '';
+let lastLyricLine = '';
function fetchCurrent() {
fetch('http://127.0.0.1:8765/current')
@@ -1273,7 +1181,12 @@ function fetchCurrent() {
document.getElementById('albumArtImg').src =
'http://127.0.0.1:8765/art?' + Date.now();
}
- updateLyricVerse(d.verse_lines || [], d.verse_active ?? -1);
+ const line = d.lyric_line || '';
+ if (line !== lastLyricLine) {
+ lastLyricLine = line;
+ lyricLineEl.textContent = line;
+ }
+ lyricDisplay.style.opacity = (isPlaying && line) ? '1' : '0';
})
.catch(() => {});
}
@@ -1333,12 +1246,7 @@ function updateMusic(artist, title) {
document.querySelector('.robot-wrap').style.opacity = playing ? '1' : '0';
document.querySelector('.music-ticker').style.opacity = playing ? '1' : '0';
albumArtEl.style.opacity = playing ? '1' : '0';
- if (!playing) {
- vuBars.forEach(b => { b.style.height = '3px'; b.style.opacity = '0.15'; });
- lyricDisplay.style.opacity = '0';
- currentVerseKey = '';
- currentVerseActive = -1;
- }
+ if (!playing) vuBars.forEach(b => { b.style.height = '3px'; b.style.opacity = '0.15'; });
if (playing) fetchCurrent();
const key = artist + '|' + title;
if (el.dataset.key === key) return;
diff --git a/plugin/contents/ui/get-playing.sh b/plugin/contents/ui/get-playing.sh
deleted file mode 100644
index 47a942e..0000000
--- a/plugin/contents/ui/get-playing.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/bash
-for player in $(playerctl -l 2>/dev/null); do
- if [ "$(playerctl --player "$player" status 2>/dev/null)" = "Playing" ]; then
- playerctl --player "$player" metadata --format "{{status}}||{{artist}}||{{title}}" 2>/dev/null
- exit 0
- fi
-done
-printf "||"
diff --git a/plugin/contents/ui/main.qml b/plugin/contents/ui/main.qml
index 7402871..173dcae 100644
--- a/plugin/contents/ui/main.qml
+++ b/plugin/contents/ui/main.qml
@@ -38,7 +38,7 @@ WallpaperItem {
Plasma5Support.DataSource {
id: musicSource
engine: "executable"
- connectedSources: ["bash " + Qt.resolvedUrl("get-playing.sh").toString().replace("file://", "")]
+ connectedSources: ["playerctl metadata --format '{{status}}||{{artist}}||{{title}}' 2>/dev/null || echo '||'"]
interval: 2000
onNewData: function(sourceName, data) {