feat: wire NSBridge fully + HD artwork + disable watchdog in wrapper mode
player.js - Replace `_native()` function with `const HAS_BRIDGE` (evaluated once at module load so bridge detection is rock-solid) - Add `buildTrackList()` — maps S.queue to NSBridge Track array with 1024px artworkUrl so lock-screen cover is crisp on high-DPR displays - Add `_pushQueueIfBridge()` — called by `fillRadioQueue()` so radio top-ups are pushed to ExoPlayer in real time (fixes autoplay gap after radio refill) - `playQueue`: route through `NSBridge.setQueue` when bridge present; old `S.audio` path retained for browser/PWA fallback - `playCurrent`: `NSBridge.seekToIndex + play` in bridge mode - `nextSong / prevSong / togglePlay / onEnded`: delegate to bridge, skip local S.qIdx manipulation (native sends onTrackChanged callback instead) - `seekTo / _initBarScrub`: use `_lastDurationMs` for ms-accurate seeks - `onTrackChanged`: guard with `p.index !== S.qIdx` to avoid redundant redraws - `updateMediaSession`: artwork sizes 96/300/512 → 256/512/1024 - Player-bar cover: 100 → 256px; NP cover/bg: 400 → 1024px; queue items: 60 → 128px; preload hint sizes: 96/300/512 → 256/512/1024 main.js - Wrap watchdog setInterval in `typeof window.NSBridge === 'undefined'` guard; the foreground service keeps ExoPlayer alive — JS watchdog not needed there views.js - Album detail / playlist detail covers: 300 → 512px - Playlist grid cards: 200 → 512px - Search result song cards: 200 → 256px - Artist top-songs / all-songs thumbnails: 60 → 128px - Partial album art in _renderArtistAlbums: 300 → 512px components.js - makeAlbumCard: 200 → 512px - makeSongItem: 60 → 128px nowplaying.js - NP queue items: 60 → 128px - NP action sheet thumb: 80 → 256px sw.js - Bump CACHE to ns-v41 so stale small-cover entries are evicted on next load Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
0ee2a62adb
commit
76ecfe2268
6 files changed
+144
-113
No files matched your search
+6
-6
@@ -250,7 +250,7 @@ export async function loadArtistDetail(artist) {
|
||||
tsEl.appendChild(h);
|
||||
const list = document.createElement('div'); list.style.marginBottom = '8px';
|
||||
topSongs.forEach((s, i) => {
|
||||
const cv = coverUrl(s.coverArt, 60);
|
||||
const cv = coverUrl(s.coverArt, 128);
|
||||
const row = document.createElement('div'); row.className = 'topsong-item';
|
||||
row.innerHTML = `<div class="topsong-num">${i+1}</div>
|
||||
<div class="topsong-thumb">${cv ? `<img src="${cv}" loading="lazy">` : '<div style="width:100%;height:100%;display:flex;align-items:center;justify-content:center;font-size:18px">🎵</div>'}</div>
|
||||
@@ -360,7 +360,7 @@ function _renderArtistAlbums(el, ndAlbums, iAlbums, artist) {
|
||||
if(partial.length) {
|
||||
const g = addGrid('Unvollständig', partial.length);
|
||||
partial.forEach(({ nd, itunes, have, total }) => {
|
||||
const art = itunes?.artworkUrl100?.replace('100x100','300x300') || coverUrl(nd.coverArt, 300);
|
||||
const art = itunes?.artworkUrl100?.replace('100x100','512x512') || coverUrl(nd.coverArt, 512);
|
||||
const c = makeCard(nd.name, `${have} / ${total} Tracks`, art, '💿');
|
||||
c.querySelector('.card-art').onclick = (e) => { e.stopPropagation(); quickPlayAlbum(nd); };
|
||||
c.querySelector('.card-info').onclick = () => itunes ? navigate('itunes-album-detail', itunes) : navigate('album-detail', { ...nd, _fromArtist: artist });
|
||||
@@ -471,7 +471,7 @@ export async function loadAlbumDetail(album) {
|
||||
return `<span class="song-link" onclick="event.stopPropagation();s_goArtist(event,'${esc(name)}','${esc(aid)}')">${esc(name)}</span>`;
|
||||
}).join('<span style="color:var(--text3)"> • </span>') || '';
|
||||
const cw = document.getElementById('album-cover-wrap');
|
||||
const cv = coverUrl(album.coverArt, 300);
|
||||
const cv = coverUrl(album.coverArt, 512);
|
||||
cw.innerHTML = cv ? `<img src="${cv}" onerror="this.parentNode.innerHTML='<div class=\\'no-art\\'>💿</div>'">` : '<div class="no-art">💿</div>';
|
||||
const sl = document.getElementById('album-songs');
|
||||
sl.innerHTML = '<div class="spinner"></div>';
|
||||
@@ -500,7 +500,7 @@ export async function loadPlaylists() {
|
||||
g.innerHTML = '';
|
||||
if(!lists.length) { g.innerHTML = '<div class="empty-state"><div class="icon">🎶</div><p>Keine Playlists vorhanden</p></div>'; return; }
|
||||
lists.forEach(pl => {
|
||||
const cv = coverUrl(pl.coverArt, 200);
|
||||
const cv = coverUrl(pl.coverArt, 512);
|
||||
const c = makeCard(pl.name, pl.songCount+' Titel', cv, '🎶');
|
||||
c.querySelector('.card-art').onclick = (e) => { e.stopPropagation(); quickPlayPlaylist(pl); };
|
||||
c.querySelector('.card-info').onclick = () => navigate('playlist-detail', pl);
|
||||
@@ -531,7 +531,7 @@ export async function loadPlaylistDetail(pl) {
|
||||
S._currentPlaylist = {...pl};
|
||||
document.getElementById('playlist-detail-name').textContent = pl.name;
|
||||
const cw = document.getElementById('playlist-cover');
|
||||
const cv = coverUrl(pl.coverArt, 300);
|
||||
const cv = coverUrl(pl.coverArt, 512);
|
||||
cw.innerHTML = cv ? `<img src="${cv}" onerror="this.parentNode.innerHTML='<div class=\\'no-art\\'>🎶</div>'">` : '<div class="no-art">🎶</div>';
|
||||
document.getElementById('btn-edit-playlist').onclick = () => openEditPlModal(S._currentPlaylist);
|
||||
const sl = document.getElementById('playlist-songs');
|
||||
@@ -701,7 +701,7 @@ export async function doLocalSearch(q) {
|
||||
const s = mkSection('Titel');
|
||||
const g = document.createElement('div'); g.className = 'scroll-row';
|
||||
songs.forEach((so,i) => {
|
||||
const cv = coverUrl(so.coverArt, 200);
|
||||
const cv = coverUrl(so.coverArt, 256);
|
||||
const c = makeCard(so.title, so.artist||'', cv, '🎵');
|
||||
c.querySelector('.play-btn').onclick = (e) => { e.stopPropagation(); playQueue(songs, i); };
|
||||
c.onclick = () => playQueue(songs, i);
|
||||
|
||||
Reference in new issue
Block a user