fix: cover art on auto-advance + native back-button overlay routing
Issue 1 (MusicService): wrap DefaultHttpDataSource in CacheBitmapLoader so Media3 notification artwork is fetched once and served from memory on every subsequent auto-advance. warmArtworkCache() pre-loads current+next 3 tracks on both onMediaItemTransition and onTimelineChanged (queue replace via setQueue). Adds explicit media3-datasource dependency. Issue 2 (back button): replace deprecated onKeyDown with OnBackPressedCallback. WebBridge.setOverlayState(bool) tracks whether JS has an overlay open; consumeBackPress() is called first — if true, MainActivity delegates to window.NSPlayer.handleBack() which closes the topmost layer. Falls back to webView.goBack() then moveTaskToBack(true) so the MusicService binding survives. JS side: _syncOverlayState() + MutationObserver keep the native flag current; handleBack covers NP overlay, queue panel, action sheet, all modals, sidebar. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
76ecfe2268
commit
cf2921c56f
7 files changed
+178
-10
No files matched your search
@@ -710,6 +710,7 @@ export function toggleQueue() {
|
||||
S.queueOpen = !S.queueOpen;
|
||||
document.getElementById('queue-panel').classList.toggle('open', S.queueOpen);
|
||||
if(S.queueOpen) renderQueue();
|
||||
_syncOverlayState();
|
||||
}
|
||||
|
||||
// ─── DOWNLOAD ─────────────────────────────────────────────────────────────
|
||||
@@ -767,6 +768,83 @@ export function updatePreviewProgress() {
|
||||
|
||||
// ─── RESTORE LAST PLAYED ──────────────────────────────────────────────────
|
||||
|
||||
// ─── BACK-BUTTON / OVERLAY STATE SYNC ────────────────────────────────────
|
||||
// Native back button: when JS has an overlay open, Android delegates the event
|
||||
// to window.NSPlayer.handleBack() instead of minimising the app.
|
||||
|
||||
function _hasAnyOverlayOpen() {
|
||||
if (S.npOpen || S.queueOpen) return true;
|
||||
if (document.getElementById('np-sheet')?.classList.contains('open')) return true;
|
||||
if (document.getElementById('ctx-menu')?.style.display === 'block') return true;
|
||||
if (document.getElementById('sidebar')?.classList.contains('mobile-open')) return true;
|
||||
return ['settings-modal','pl-modal','info-modal','dl-modal','edit-pl-modal','confirm-modal','notif-panel']
|
||||
.some(id => document.getElementById(id)?.classList.contains('open'));
|
||||
}
|
||||
|
||||
export function _syncOverlayState() {
|
||||
if (!HAS_BRIDGE) return;
|
||||
try { window.NSBridge.setOverlayState(_hasAnyOverlayOpen()); } catch {}
|
||||
}
|
||||
|
||||
window.NSPlayer.handleBack = function() {
|
||||
// Close overlays from topmost layer downward.
|
||||
if (document.getElementById('np-sheet')?.classList.contains('open')) {
|
||||
window.closeNpMenu?.(); _syncOverlayState(); return;
|
||||
}
|
||||
const ctxMenu = document.getElementById('ctx-menu');
|
||||
if (ctxMenu?.style.display === 'block') {
|
||||
ctxMenu.style.display = 'none'; ctxMenu.innerHTML = '';
|
||||
_syncOverlayState(); return;
|
||||
}
|
||||
if (S.npOpen) {
|
||||
window.closeNowPlaying?.(); _syncOverlayState(); return;
|
||||
}
|
||||
if (S.queueOpen) {
|
||||
toggleQueue(); _syncOverlayState(); return;
|
||||
}
|
||||
// Generic modals
|
||||
const modalMap = {
|
||||
'settings-modal': 'closeSettings',
|
||||
'pl-modal': 'closePlModal',
|
||||
'info-modal': 'closeInfoModal',
|
||||
'dl-modal': 'closeDlModal',
|
||||
'edit-pl-modal': 'closeEditPlModal',
|
||||
'confirm-modal': '_confirmCancel',
|
||||
};
|
||||
for (const [id, fn] of Object.entries(modalMap)) {
|
||||
const el = document.getElementById(id);
|
||||
if (el?.classList.contains('open')) {
|
||||
if (window[fn]) window[fn](); else el.classList.remove('open');
|
||||
_syncOverlayState(); return;
|
||||
}
|
||||
}
|
||||
// Notif panel (generic fallback)
|
||||
const notifPanel = document.getElementById('notif-panel');
|
||||
if (notifPanel?.classList.contains('open')) {
|
||||
notifPanel.classList.remove('open'); _syncOverlayState(); return;
|
||||
}
|
||||
// Sidebar
|
||||
if (document.getElementById('sidebar')?.classList.contains('mobile-open')) {
|
||||
window.closeSidebar?.(); _syncOverlayState(); return;
|
||||
}
|
||||
};
|
||||
|
||||
// MutationObserver keeps hasOpenOverlay in sync whenever the DOM changes class
|
||||
// attributes (e.g. any overlay gains/loses the 'open' class).
|
||||
if (HAS_BRIDGE) {
|
||||
const _startOverlayObserver = () => {
|
||||
if (!document.body) return;
|
||||
new MutationObserver(_syncOverlayState).observe(document.body, {
|
||||
attributes: true, attributeFilter: ['class'], subtree: true,
|
||||
});
|
||||
};
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', _startOverlayObserver);
|
||||
} else {
|
||||
_startOverlayObserver();
|
||||
}
|
||||
}
|
||||
|
||||
export function _restoreLastPlayed() {
|
||||
try {
|
||||
const saved = JSON.parse(localStorage.getItem('ns_last_played') || 'null');
|
||||
|
||||
Reference in new issue
Block a user