import { CirclePause, CirclePlay } from "lucide-react" import React, { useRef, useState } from "react" import { useTranslation } from "react-i18next" import { useFavorites, useMusicFiles } from "@/features/app-state" import { useMusicImport } from "@/features/browser/hooks/use-music-import" import { parseDuration, parseFileSize } from "@/features/browser/utils" import { useDraggable } from "@/features/drag-drop" import { MediaFile } from "@/features/media/types/media" import { useResources } from "@/features/resources" import { formatTime } from "@/lib/date" import { cn } from "@/lib/utils" import type { ListAdapter, ListItem, PreviewComponentProps } from "../types/list" import { getDateGroup, getDurationGroup } from "../utils/grouping" // Адаптер типа для MediaFile чтобы соответствовать ListItem type MusicListItem = MediaFile & ListItem /** * Компонент превью для музыкальных файлов */ const MusicPreviewWrapper: React.FC> = ({ item: file, size, viewMode, onClick, isSelected, }) => { const { t } = useTranslation() const [isPlaying, setIsPlaying] = useState(false) const audioRef = useRef(null) const { isMusicAdded } = useResources() const handlePlayPause = (e: React.MouseEvent) => { e.stopPropagation() if (!audioRef.current) { audioRef.current = new Audio(file.path) audioRef.current.onended = () => setIsPlaying(false) } if (isPlaying) { audioRef.current.pause() setIsPlaying(false) } else { void audioRef.current.play() setIsPlaying(true) } } const duration = file.probeData?.format.duration || 0 const artist = String(file.probeData?.format.tags?.artist || "") const title = String(file.probeData?.format.tags?.title || file.name) const isAdded = isMusicAdded(file) // Используем DragDropManager для перетаскивания const dragProps = useDraggable( "music", () => file, () => ({ url: file.thumbnailPath || file.path, width: 120, height: 80, }), ) if (viewMode === "list") { return (
onClick?.(file)} {...dragProps} > {/* Play/Pause Button */} {/* File Info */}
{title}
{artist &&
{artist}
}
{/* Duration */}
{duration > 0 ? formatTime(duration) : ""}
{/* Status indicator */} {isAdded &&
}
) } // Thumbnails mode return (
onClick?.(file)} {...dragProps} > {/* Play/Pause Button */} {/* File Info */}
{title}
{artist &&
{artist}
}
{duration > 0 ? formatTime(duration) : ""}
{/* Status indicator */} {isAdded &&
}
) } /** * Хук для создания адаптера музыкальных файлов */ export function useMusicAdapter(): ListAdapter { const { musicFiles } = useMusicFiles() const { isItemFavorite } = useFavorites() const { importFile, importDirectory, isImporting } = useMusicImport() const allMusicFiles = (musicFiles || []) as MusicListItem[] return { // Хук для получения данных useData: () => ({ items: allMusicFiles, loading: false, // musicFiles не предоставляет loading состояние error: null, }), // Компонент превью PreviewComponent: MusicPreviewWrapper, // Функция для получения значения сортировки getSortValue: (file, sortBy) => { switch (sortBy) { case "name": return file.name.toLowerCase() case "title": return String(file.probeData?.format.tags?.title || file.name).toLowerCase() case "artist": return String(file.probeData?.format.tags?.artist || "").toLowerCase() case "size": return parseFileSize(file.size) case "duration": return parseDuration(file.probeData?.format.duration) default: return file.startTime || 0 } }, // Функция для получения текста для поиска getSearchableText: (file) => { const texts = [ file.name, String(file.probeData?.format.tags?.title || ""), String(file.probeData?.format.tags?.artist || ""), String(file.probeData?.format.tags?.album || ""), String(file.probeData?.format.tags?.genre || ""), ] return texts.filter(Boolean) }, // Функция для получения значения группировки getGroupValue: (file, groupBy) => { switch (groupBy) { case "artist": const artist = String(file.probeData?.format.tags?.artist || "") return artist || "Неизвестный исполнитель" case "genre": const genre = String(file.probeData?.format.tags?.genre || "") return genre || "Без жанра" case "album": const album = String(file.probeData?.format.tags?.album || "") return album || "Без альбома" case "date": return getDateGroup(file.startTime) case "duration": const duration = parseDuration(file.probeData?.format.duration) return getDurationGroup(duration) default: return "" } }, // Функция для фильтрации по типу (расширения) matchesFilter: (file, filterType) => { if (filterType === "all") return true const fileExt = file.name.split(".").pop()?.toLowerCase() || "" return fileExt === filterType.toLowerCase() }, // Обработчики импорта importHandlers: { importFile: async () => { await importFile() }, importFolder: async () => { await importDirectory() }, isImporting, }, // Проверка избранного isFavorite: (file) => isItemFavorite(file, "music"), // Тип для системы избранного favoriteType: "music", } }