fix(ui): prevent multiple track menus open
cx
This commit is contained in:
1 parent
db1957bedd
commit
170158da3f
2 files changed
+58
-4
No files matched your search
@@ -18,6 +18,13 @@
|
||||
Radio
|
||||
} from 'lucide-svelte';
|
||||
import { shouldHidePlaylistFeatures } from '$lib/utils/offlineHelpers';
|
||||
import {
|
||||
getActiveTrackMenuId,
|
||||
setActiveTrackMenuId,
|
||||
subscribeActiveTrackMenuId
|
||||
} from '$lib/stores/activeTrackMenu';
|
||||
|
||||
let trackMenuIdCounter = 1;
|
||||
|
||||
interface Props {
|
||||
onPlayNow?: () => void;
|
||||
@@ -59,6 +66,8 @@
|
||||
onRemoveDownload
|
||||
}: Props = $props();
|
||||
|
||||
const menuId = trackMenuIdCounter++;
|
||||
|
||||
let isOpen = $state(false);
|
||||
let shareOpen = $state(false);
|
||||
let downloadOpen = $state(false);
|
||||
@@ -92,10 +101,21 @@
|
||||
const hasNav = $derived(!!(onGoToAlbum || onGoToArtist));
|
||||
const hasMenu = $derived(hasPlayback || hasLibrary || hasShare || hasDownload || hasNav);
|
||||
|
||||
function closeMenu() {
|
||||
function closeMenu(options?: { clearActive?: boolean }) {
|
||||
isOpen = false;
|
||||
shareOpen = false;
|
||||
downloadOpen = false;
|
||||
if (options?.clearActive !== false && getActiveTrackMenuId() === menuId) {
|
||||
setActiveTrackMenuId(null);
|
||||
}
|
||||
}
|
||||
|
||||
async function openMenu() {
|
||||
setActiveTrackMenuId(menuId);
|
||||
isOpen = true;
|
||||
shareOpen = false;
|
||||
downloadOpen = false;
|
||||
await setMenuPosition();
|
||||
}
|
||||
|
||||
function handleClickOutside(event: MouseEvent) {
|
||||
@@ -198,6 +218,15 @@
|
||||
closeMenu();
|
||||
}
|
||||
|
||||
$effect(() => {
|
||||
const unsubscribe = subscribeActiveTrackMenuId((activeId) => {
|
||||
if (activeId !== menuId && isOpen) {
|
||||
closeMenu({ clearActive: false });
|
||||
}
|
||||
});
|
||||
return unsubscribe;
|
||||
});
|
||||
|
||||
$effect(() => {
|
||||
if (isOpen) {
|
||||
document.addEventListener('mousedown', handleClickOutside);
|
||||
@@ -231,9 +260,11 @@
|
||||
bind:this={triggerRef}
|
||||
onclick={(e) => {
|
||||
e.stopPropagation();
|
||||
isOpen = !isOpen;
|
||||
shareOpen = false;
|
||||
if (isOpen) setMenuPosition();
|
||||
if (isOpen) {
|
||||
closeMenu();
|
||||
} else {
|
||||
openMenu();
|
||||
}
|
||||
}}
|
||||
aria-label="Track actions"
|
||||
>
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
type Listener = (menuId: number | null) => void;
|
||||
|
||||
let activeMenuId: number | null = null;
|
||||
const listeners = new Set<Listener>();
|
||||
|
||||
export function getActiveTrackMenuId(): number | null {
|
||||
return activeMenuId;
|
||||
}
|
||||
|
||||
export function setActiveTrackMenuId(menuId: number | null): void {
|
||||
if (activeMenuId === menuId) return;
|
||||
activeMenuId = menuId;
|
||||
for (const listener of listeners) listener(activeMenuId);
|
||||
}
|
||||
|
||||
export function subscribeActiveTrackMenuId(listener: Listener): () => void {
|
||||
listeners.add(listener);
|
||||
listener(activeMenuId);
|
||||
return () => {
|
||||
listeners.delete(listener);
|
||||
};
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user