import React, { useEffect } from 'react'; import { createPortal } from 'react-dom'; import { Music, X } from 'lucide-react'; import { useTranslation } from 'react-i18next'; import type { SubsonicSong } from '@/lib/api/subsonicTypes'; import type { ServerProfile } from '@/store/authStoreTypes'; import { formatTrackTime } from '@/utils/format/formatDuration'; import type { ShareQueuePreviewState } from '@/features/search/hooks/useShareQueuePreview'; import { sharePayloadTotal, type QueueableShareSearchPayload } from '@/utils/share/shareSearch'; import OverlayScrollArea from '@/ui/OverlayScrollArea'; import { usePlayerStore } from '@/store/playerStore'; import { COVER_DENSE_SEARCH_CSS_PX } from '@/cover/layoutSizes'; import { COVER_SCOPE_ACTIVE, type CoverServerScope } from '@/cover/types'; import { AlbumCoverArtImage } from '@/cover/AlbumCoverArtImage'; type ShareQueuePreviewModalProps = { open: boolean; onClose: () => void; payload: Extract; preview: ShareQueuePreviewState; shareServerLabel?: string | null; coverServer?: ServerProfile | null; onEnqueue: () => void; enqueueBusy: boolean; confirmLabel?: string; confirmBusyLabel?: string; }; function shareCoverServerScope(coverServer?: ServerProfile | null): CoverServerScope { if (coverServer) { return { kind: 'server', serverId: coverServer.id, url: coverServer.url, username: coverServer.username, password: coverServer.password, }; } return COVER_SCOPE_ACTIVE; } function QueuePreviewTrackRow({ song, coverServer, }: { song: SubsonicSong; coverServer?: ServerProfile | null; }) { const coverId = song.coverArt || song.id; return (
  • {song.coverArt ? ( ) : (
    )}
    {song.title}
    {song.artist}{song.album ? ` ยท ${song.album}` : ''}
    {formatTrackTime(song.duration)}
  • ); } function PreviewBody({ preview, coverServer, }: { preview: ShareQueuePreviewState; coverServer?: ServerProfile | null; }) { const { t } = useTranslation(); if (preview.status === 'loading' || preview.status === 'idle') { return
    {t('search.shareQueuePreviewLoading')}
    ; } if (preview.status === 'error') { const msg = preview.result.type === 'not-logged-in' ? t('sharePaste.notLoggedIn') : preview.result.type === 'no-matching-server' ? t('sharePaste.noMatchingServer', { url: preview.result.url }) : preview.result.type === 'all-unavailable' ? t('search.shareQueuePreviewEmpty') : t('sharePaste.genericError'); return
    {msg}
    ; } return ( <> {preview.skipped > 0 && (

    {t('search.shareQueuePreviewSkipped', { skipped: preview.skipped, total: preview.total })}

    )} ); } export default function ShareQueuePreviewModal({ open, onClose, payload, preview, shareServerLabel, coverServer, onEnqueue, enqueueBusy, confirmLabel, confirmBusyLabel, }: ShareQueuePreviewModalProps) { const { t } = useTranslation(); const actionLabel = confirmLabel ?? t('search.shareQueueAction'); const actionBusyLabel = confirmBusyLabel ?? t('search.shareQueueing'); useEffect(() => { if (!open) return; usePlayerStore.getState().closeContextMenu(); const handler = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose(); }; const blockContextMenu = (e: MouseEvent) => { e.preventDefault(); e.stopPropagation(); usePlayerStore.getState().closeContextMenu(); }; document.addEventListener('keydown', handler); document.addEventListener('contextmenu', blockContextMenu, true); return () => { document.removeEventListener('keydown', handler); document.removeEventListener('contextmenu', blockContextMenu, true); }; }, [open, onClose]); if (!open) return null; const count = sharePayloadTotal(payload); const canEnqueue = preview.status === 'ok' && preview.songs.length > 0; return createPortal(
    { e.preventDefault(); e.stopPropagation(); }} onMouseDown={e => { if (e.target === e.currentTarget) onClose(); }} >
    { e.preventDefault(); e.stopPropagation(); }} onMouseDown={e => e.stopPropagation()} >

    {t('search.shareQueueTitle', { count })}

    {shareServerLabel && (

    {t('search.shareFromServer', { server: shareServerLabel })}

    )}
    , document.body, ); }