DownloadButton.tsx
⎇
Raw
1import "./DownloadButton.css";
2import type { MediaFile, Directory } from "music-server-shared/types";
3import { deleteFile, download, getDownloadStatus } from "../offline";
4import { createMemo, type Accessor, type ResourceActions } from "solid-js";
5import type { AppOptions } from "../types";
6import { formatBytes, joinPath } from "../utils";
7import { DeleteSVG, RefreshSVG, SyncSVG } from "./SVG";
8import { LoadingSpinner } from "./LoadingScreen";
9import type { FlatFileListing } from "../App";
10
11interface DownloadButtonProps {
12 fileName: string;
13 item: MediaFile | Directory;
14 fetchFiles: ResourceActions<FlatFileListing>;
15 isOffline: Accessor<boolean>;
16 currentDir: Accessor<string>;
17 options: AppOptions;
18}
19
20export function DownloadButton(props: DownloadButtonProps) {
21 const fullPath = joinPath(props.currentDir(), props.fileName);
22
23 return (
24 <div
25 class="download-item"
26 onClick={(event) => {
27 event.stopPropagation();
28 if (!props.isOffline())
29 download(props.fileName, props.item, props.currentDir(), props.options, props.fetchFiles);
30 else deleteFile(props.fileName, props.item, props.currentDir(), props.fetchFiles);
31 }}
32 >
33 {(() => {
34 //memo needed so progress amount doesn't cause rerenders
35 type ButtonType = "Spinner" | "Delete" | "Sync" | "Refresh" | { bytes: number };
36 const progressMemo = createMemo<ButtonType>(() => {
37 const progress = getDownloadStatus(fullPath)[0]();
38 if (typeof progress === "object" && "amount" in progress) return "Spinner";
39 if (props.isOffline()) return "Delete";
40 if (progress === undefined) return "Sync";
41 if (progress === "Synced") return "Refresh";
42 if ("bytes" in progress) return { bytes: progress.bytes };
43 throw new Error(`Unexpected: ${progress}`);
44 });
45 const progress = progressMemo();
46 if (progress === "Spinner") return <LoadingSpinner center={true} />;
47 if (progress === "Delete") {
48 return (
49 <button title="Purge this file/these files from local sync storage">
50 <DeleteSVG />
51 </button>
52 );
53 }
54 if (progress === "Sync") {
55 return (
56 <button title="Sync this file/directory to your browser for offline use">
57 <SyncSVG />
58 </button>
59 );
60 }
61 if (progress === "Refresh") {
62 return (
63 <button title="Re-sync this file">
64 <RefreshSVG />
65 </button>
66 );
67 }
68 if ("bytes" in progress) return <span>{progress.bytes === 0 ? "Queued..." : formatBytes(progress.bytes)}</span>;
69 console.error("Unexpected", progress);
70 })()}
71 </div>
72 );
73}
74