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
|
Radio
|
||||||
} from 'lucide-svelte';
|
} from 'lucide-svelte';
|
||||||
import { shouldHidePlaylistFeatures } from '$lib/utils/offlineHelpers';
|
import { shouldHidePlaylistFeatures } from '$lib/utils/offlineHelpers';
|
||||||
|
import {
|
||||||
|
getActiveTrackMenuId,
|
||||||
|
setActiveTrackMenuId,
|
||||||
|
subscribeActiveTrackMenuId
|
||||||
|
} from '$lib/stores/activeTrackMenu';
|
||||||
|
|
||||||
|
let trackMenuIdCounter = 1;
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
onPlayNow?: () => void;
|
onPlayNow?: () => void;
|
||||||
@@ -59,6 +66,8 @@
|
|||||||
onRemoveDownload
|
onRemoveDownload
|
||||||
}: Props = $props();
|
}: Props = $props();
|
||||||
|
|
||||||
|
const menuId = trackMenuIdCounter++;
|
||||||
|
|
||||||
let isOpen = $state(false);
|
let isOpen = $state(false);
|
||||||
let shareOpen = $state(false);
|
let shareOpen = $state(false);
|
||||||
let downloadOpen = $state(false);
|
let downloadOpen = $state(false);
|
||||||
@@ -92,10 +101,21 @@
|
|||||||
const hasNav = $derived(!!(onGoToAlbum || onGoToArtist));
|
const hasNav = $derived(!!(onGoToAlbum || onGoToArtist));
|
||||||
const hasMenu = $derived(hasPlayback || hasLibrary || hasShare || hasDownload || hasNav);
|
const hasMenu = $derived(hasPlayback || hasLibrary || hasShare || hasDownload || hasNav);
|
||||||
|
|
||||||
function closeMenu() {
|
function closeMenu(options?: { clearActive?: boolean }) {
|
||||||
isOpen = false;
|
isOpen = false;
|
||||||
shareOpen = false;
|
shareOpen = false;
|
||||||
downloadOpen = 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) {
|
function handleClickOutside(event: MouseEvent) {
|
||||||
@@ -198,6 +218,15 @@
|
|||||||
closeMenu();
|
closeMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$effect(() => {
|
||||||
|
const unsubscribe = subscribeActiveTrackMenuId((activeId) => {
|
||||||
|
if (activeId !== menuId && isOpen) {
|
||||||
|
closeMenu({ clearActive: false });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return unsubscribe;
|
||||||
|
});
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
if (isOpen) {
|
if (isOpen) {
|
||||||
document.addEventListener('mousedown', handleClickOutside);
|
document.addEventListener('mousedown', handleClickOutside);
|
||||||
@@ -231,9 +260,11 @@
|
|||||||
bind:this={triggerRef}
|
bind:this={triggerRef}
|
||||||
onclick={(e) => {
|
onclick={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
isOpen = !isOpen;
|
if (isOpen) {
|
||||||
shareOpen = false;
|
closeMenu();
|
||||||
if (isOpen) setMenuPosition();
|
} else {
|
||||||
|
openMenu();
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
aria-label="Track actions"
|
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