add websockets to get downloads list
This commit is contained in:
@@ -1,27 +1,62 @@
|
||||
import { useState } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useSearchQuery, type Album } from "./api/useSearchQuery";
|
||||
import { useDebouncedValue } from "./hooks/useDebouncedValue";
|
||||
import { getContrastYIQ } from "./getContrastYIQ";
|
||||
import { useDownloadAlbumMutation } from "./api/useDownloadAlbumMutation";
|
||||
import { useDownloadsQuery } from "./api/useDownloadsQuery";
|
||||
import toast from "react-hot-toast";
|
||||
|
||||
type DownloadItem = {
|
||||
id: number;
|
||||
status: "ADDED" | "IN_PROGRESS" | "COMPLETED";
|
||||
album: Album;
|
||||
installedFiles: number;
|
||||
totalFiles: number;
|
||||
};
|
||||
|
||||
export default function App() {
|
||||
const [search, setSearch] = useState("");
|
||||
const debouncedSearch = useDebouncedValue(search);
|
||||
|
||||
const [downloads, setDownloads] = useState<DownloadItem[]>([]);
|
||||
|
||||
const { data } = useSearchQuery({
|
||||
query: debouncedSearch,
|
||||
});
|
||||
const { data: downloads } = useDownloadsQuery();
|
||||
|
||||
const downloadAlbumMutation = useDownloadAlbumMutation();
|
||||
|
||||
useEffect(() => {
|
||||
const ws = new WebSocket("/ws/downloads");
|
||||
|
||||
ws.onopen = () => {
|
||||
console.log("ws connection opened");
|
||||
};
|
||||
|
||||
ws.onclose = () => {
|
||||
console.log("ws connection closed");
|
||||
};
|
||||
|
||||
ws.onmessage = (e) => {
|
||||
const data = JSON.parse(e.data) as { downloads: DownloadItem[] };
|
||||
const items = [...data.downloads].sort((a, b) => {
|
||||
if (a.status === "COMPLETED" && b.status !== "COMPLETED") {
|
||||
return -1;
|
||||
}
|
||||
if (a.status !== "COMPLETED" && b.status === "COMPLETED") {
|
||||
return 1;
|
||||
}
|
||||
return a.album.title.localeCompare(b.album.title);
|
||||
});
|
||||
setDownloads(items);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const handleDownloadAlbum = (album: Album) => {
|
||||
downloadAlbumMutation.mutate(
|
||||
{ albumId: album.id },
|
||||
{
|
||||
onError(error) {
|
||||
console.log({ error });
|
||||
toast.error(error.message);
|
||||
},
|
||||
},
|
||||
);
|
||||
@@ -42,6 +77,7 @@ export default function App() {
|
||||
/>
|
||||
<div>
|
||||
<p>{item.album.title}</p>
|
||||
<p>Status: {formatDownloadStatus(item.status)}</p>
|
||||
<p>
|
||||
Downloaded {item.installedFiles}/{item.totalFiles}
|
||||
</p>
|
||||
@@ -102,3 +138,14 @@ export default function App() {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const formatDownloadStatus = (status: DownloadItem["status"]): string => {
|
||||
switch (status) {
|
||||
case "ADDED":
|
||||
return "added";
|
||||
case "IN_PROGRESS":
|
||||
return "in progress";
|
||||
case "COMPLETED":
|
||||
return "completed";
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import type { Album } from "./useSearchQuery";
|
||||
|
||||
export type DownloadItem = {
|
||||
id: number;
|
||||
album: Album;
|
||||
installedFiles: number;
|
||||
totalFiles: number;
|
||||
};
|
||||
|
||||
export const useDownloadsQuery = () => {
|
||||
return useQuery({
|
||||
queryKey: ["downloads"],
|
||||
queryFn: async () => {
|
||||
const resp = await fetch("/downloads");
|
||||
return (await resp.json()) as DownloadItem[];
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -3,6 +3,7 @@ import { createRoot } from "react-dom/client";
|
||||
import "./index.css";
|
||||
import App from "./App.tsx";
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
import { Toaster } from "react-hot-toast";
|
||||
|
||||
const queryClient = new QueryClient({
|
||||
defaultOptions: {
|
||||
@@ -15,6 +16,7 @@ const queryClient = new QueryClient({
|
||||
createRoot(document.getElementById("root")!).render(
|
||||
<StrictMode>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<Toaster />
|
||||
<App />
|
||||
</QueryClientProvider>
|
||||
</StrictMode>,
|
||||
|
||||
Reference in New Issue
Block a user