import { type Accessor, createResource, createSignal, For, type Setter, Show } from "solid-js"; import "./PlaylistManager.css"; import "./Dialog.css"; import "toastify-js/src/toastify.css"; import { deletePlaylist, loadPlaylists, savePlaylist } from "../offline"; import type { AppOptions, Playlist, PlaylistItem } from "../types"; import { formatFilename, formatTime, toast } from "../utils"; import { LoadingScreen } from "./LoadingScreen"; import { Modal } from "./Modal"; import { ClearSVG, DeleteSVG, DownloadSVG, UploadSVG } from "./SVG"; interface PlaylistManagerProps { showPlaylistManager: Accessor; setShowPlaylistManager: Setter; playlist: Accessor; setPlaylist: Setter; playTrack: (track: PlaylistItem) => void; options: AppOptions; } export default function PlaylistManager(props: PlaylistManagerProps) { const [playlists, fetchPlaylists] = createResource( async () => { return await loadPlaylists(); }, { initialValue: [] }, ); const [loadingActions, setLoadingActions] = createSignal(0); function getTotalDuration(playlist: Playlist) { if (playlist.items.length === 0) return 0; //for some reason "duration" is a string at runtime... return playlist.items .map((item) => Number.parseFloat(item.metadata.duration as unknown as string)) .reduce((a, b) => a + b); } function exportPlaylists() { toast("Exporting playlists...", "info"); const blob = new Blob([JSON.stringify(playlists())], { type: "application/json" }); const link = document.createElement("a"); link.href = URL.createObjectURL(blob); link.download = "pico-playlists.json"; link.click(); URL.revokeObjectURL(link.href); } function importPlaylists() { const input = document.createElement("input"); input.type = "file"; input.onchange = async (event) => { const target = event.target as HTMLInputElement; const file = target.files?.[0]; if (file) { try { toast("Importing playlists...", "info"); setLoadingActions((prev) => prev + 1); const imports = JSON.parse(await file.text()) as Playlist[]; for (const imported of imports) { await savePlaylist(imported, true); } setLoadingActions((prev) => prev - 1); fetchPlaylists.refetch(); } catch (e) { toast("Importing playlists failed", "error", e); } } }; input.click(); } function generateIds(items: Omit[]): PlaylistItem[] { return items.map((item) => ({ ...item, id: crypto.randomUUID() })); } return ( fetchPlaylists.refetch()} > {(close) => (
Playlists

0}> {(item) => { const [showSongs, setShowSongs] = createSignal(false); return (
{item.name}
{item.items.length} Items ({formatTime(getTotalDuration(item))})
{(item) => { return ( <> {formatFilename(item, props.options.playlistDisplay)}
); }}
); }}
)} ); }