import { useQuery } from "@tanstack/react-query"; import { Box, Text, useInput } from "ink"; import { useAtom, useAtomValue } from "jotai"; import React, { useState } from "react"; import { Cell, Ell } from "./Columns"; import { List } from "./List"; import { addTrackToPlaylist, createPlaylist, getCreds, getPlaylists, } from "./navidrome"; import { queryClient } from "./queryClient"; import { addToPlaylistAtom, authAtom } from "./store"; import { BLUE, TEAL, VIOLET } from "./theme"; export function AddToPlaylistView() { const token = useAtomValue(authAtom); const [pending, setPending] = useAtom(addToPlaylistAtom); const [sel, setSel] = useState(0); const [creating, setCreating] = useState(false); const [name, setName] = useState(""); const [note, setNote] = useState(""); const credsQ = useQuery({ queryKey: ["ndCreds", token], enabled: !!token, queryFn: () => getCreds(token), }); const creds = credsQ.data ?? null; const playlistsQ = useQuery({ queryKey: ["playlists", creds?.handle], enabled: !!creds, queryFn: () => getPlaylists(creds!), }); const playlists = playlistsQ.data ?? []; function close() { setPending(null); } async function addTo(playlistId: string) { if (!token || !pending) return; try { setNote("Adding…"); await addTrackToPlaylist(token, playlistId, pending.trackId); queryClient.invalidateQueries({ queryKey: ["playlists"] }); queryClient.invalidateQueries({ queryKey: ["playlist", playlistId] }); close(); } catch (e: any) { setNote(`Error: ${e.message}`); } } useInput((input, key) => { if (creating) { if (key.escape) { setCreating(false); setName(""); return; } if (key.return) { const n = name.trim(); setCreating(false); setName(""); if (n && token && pending) { setNote(`Creating "${n}"…`); createPlaylist(token, n) .then((id) => (id ? addTo(id) : setNote("Create failed"))) .catch((e) => setNote(`Error: ${e.message}`)); } return; } if (key.backspace || key.delete) return setName((s) => s.slice(0, -1)); if (input && input >= " " && !key.ctrl && !key.meta) setName((s) => s + input); return; } if (key.escape) return close(); if (input === "c") { setCreating(true); setName(""); return; } if (key.upArrow || input === "k") return setSel((s) => Math.max(0, s - 1)); if (key.downArrow || input === "j") return setSel((s) => Math.min(playlists.length - 1, s + 1)); if (key.return) { const pl = playlists[sel]; if (pl) void addTo(pl.id); } }); return ( {"Add to playlist: "} {pending?.title ?? ""} {creating ? ( {"new playlist "} {name} ▏ Enter to create & add · Esc to cancel ) : ( {credsQ.isLoading || playlistsQ.isLoading ? ( Loading playlists… ) : ( ( <> {active ? "›" : " "} {pl.name} {`${pl.songCount} songs`} )} /> )} {note ? {note} : null} Enter add · c new playlist · Esc cancel )} ); }