fix(ui): prevent multiple track menus open

cx
This commit is contained in:
vicrodh committed 2026-01-22 11:25:48 -06:00
1 parent db1957bedd
commit 170158da3f
2 files changed
+58 -4

No files matched your search

+35 -4
View File
@@ -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"
>
+23
View File
@@ -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);
};
}