From f2732b36f236c9d343f23146720d7677e1be8420 Mon Sep 17 00:00:00 2001 From: Gregor Klevze Date: Fri, 2 Jan 2026 20:31:15 +0100 Subject: [PATCH] update --- android/app/src/main/assets/styles.css | 23 ++++++++++ src/main.js | 58 ++++++++++++++++++++++---- src/styles.css | 16 +++++++ 3 files changed, 88 insertions(+), 9 deletions(-) diff --git a/android/app/src/main/assets/styles.css b/android/app/src/main/assets/styles.css index 37e8c62..c01becc 100644 --- a/android/app/src/main/assets/styles.css +++ b/android/app/src/main/assets/styles.css @@ -18,6 +18,13 @@ cursor: default; } +/* Show pointer cursor for interactive / clickable elements (override global default) */ +a, a[href], button, input[type="button"], input[type="submit"], +[role="button"], [onclick], .clickable, .icon-btn, .control-btn, label[for], +.station-item, [tabindex]:not([tabindex="-1"]) { + cursor: pointer !important; +} + /* Hide Scrollbars */ ::-webkit-scrollbar { display: none; @@ -258,6 +265,22 @@ header { pointer-events: none; } +/* Make artwork/logo clickable: show pointer cursor */ +.artwork-placeholder, +.artwork-placeholder:hover, +.station-logo-img, +.station-logo-text { + cursor: pointer !important; + pointer-events: auto; +} + +/* Subtle hover affordance to make clickability clearer */ +.artwork-placeholder:hover .station-logo-img, +.artwork-placeholder:hover .station-logo-text { + transform: scale(1.03); + transition: transform 160ms ease; +} + .blob { position: absolute; border-radius: 50%; diff --git a/src/main.js b/src/main.js index a37a4e7..f15ea03 100644 --- a/src/main.js +++ b/src/main.js @@ -63,6 +63,7 @@ async function init() { restoreSavedVolume(); await loadStations(); setupEventListeners(); + ensureArtworkPointerFallback(); updateUI(); } catch (e) { console.error('Error during init', e); @@ -413,9 +414,10 @@ function updateNowPlayingUI() { if (!station) return; if (nowPlayingEl && nowArtistEl && nowTitleEl) { - if (station.currentSongInfo && station.currentSongInfo.artist && station.currentSongInfo.title) { - nowArtistEl.textContent = station.currentSongInfo.artist; - nowTitleEl.textContent = station.currentSongInfo.title; + // Show now-playing if we have either an artist or a title (some stations only provide title) + if (station.currentSongInfo && (station.currentSongInfo.artist || station.currentSongInfo.title)) { + nowArtistEl.textContent = station.currentSongInfo.artist || ''; + nowTitleEl.textContent = station.currentSongInfo.title || ''; nowPlayingEl.classList.remove('hidden'); } else { nowArtistEl.textContent = ''; @@ -611,6 +613,45 @@ function setupEventListeners() { // Hotkeys? } +// If CSS doesn't produce a pointer, this helper forces a pointer when the +// mouse is inside the artwork placeholder's bounding rect. This handles +// cases where an invisible overlay or ancestor blocks pointer styling. +function ensureArtworkPointerFallback() { + try { + const ap = artworkPlaceholder; + if (!ap) return; + + // Quick inline style fallback (helps when CSS is overridden) + try { ap.style.cursor = 'pointer'; } catch (e) {} + try { if (logoImgEl) logoImgEl.style.cursor = 'pointer'; } catch (e) {} + try { if (logoTextEl) logoTextEl.style.cursor = 'pointer'; } catch (e) {} + + let active = false; + const onMove = (ev) => { + try { + const r = ap.getBoundingClientRect(); + const x = ev.clientX, y = ev.clientY; + const inside = x >= r.left && x <= r.right && y >= r.top && y <= r.bottom; + if (inside && !active) { + document.body.style.cursor = 'pointer'; + active = true; + } else if (!inside && active) { + document.body.style.cursor = ''; + active = false; + } + } catch (e) {} + }; + + window.addEventListener('mousemove', onMove); + // remove on unload + window.addEventListener('beforeunload', () => { + try { window.removeEventListener('mousemove', onMove); } catch (e) {} + }); + } catch (e) { + console.debug('ensureArtworkPointerFallback failed', e); + } +} + function loadStation(index) { if (index < 0 || index >= stations.length) return; const station = stations[index]; @@ -639,14 +680,13 @@ function loadStation(index) { } }); } else { - // Fallback to single-letter/logo text + // Fallback: show the full station name when no logo is provided logoImgEl.src = ''; logoImgEl.classList.add('hidden'); - const numberMatch = station.name.match(/\d+/); - if (numberMatch) { - logoTextEl.textContent = numberMatch[0]; - } else { - logoTextEl.textContent = station.name.charAt(0).toUpperCase(); + try { + logoTextEl.textContent = (station.name || '').trim(); + } catch (e) { + logoTextEl.textContent = ''; } logoTextEl.classList.remove('hidden'); } diff --git a/src/styles.css b/src/styles.css index 88f6731..719257b 100644 --- a/src/styles.css +++ b/src/styles.css @@ -394,6 +394,22 @@ body { z-index: 0; } +/* Make artwork/logo clickable: show pointer cursor */ +.artwork-placeholder, +.artwork-placeholder:hover, +.station-logo-img, +.station-logo-text { + cursor: pointer !important; + pointer-events: auto; +} + +/* Subtle hover affordance to make clickability clearer */ +.artwork-placeholder:hover .station-logo-img, +.artwork-placeholder:hover .station-logo-text { + transform: scale(1.03); + transition: transform 160ms ease; +} + /* Track Info */ .track-info { text-align: center;