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(
30 props.fileName,
31 props.item,
32 props.currentDir(),
33 props.options,
34 props.fetchFiles,
35 "metadata" in props.item,
36 );
37 else deleteFile(props.fileName, props.item, props.currentDir(), props.fetchFiles);
38 }}
39 >
40 {(() => {
41 //memo needed so progress amount doesn't cause rerenders
42 type ButtonType = "Spinner" | "Delete" | "Sync" | "Refresh" | { status: number };
43 const progressMemo = createMemo<ButtonType>(() => {
44 const progress = getDownloadStatus(fullPath);
45 if (typeof progress === "object" && "amount" in progress) return "Spinner";
46 if (props.isOffline()) return "Delete";
47 if (progress === "Synced") return "Refresh";
48 if (progress === undefined || ("status" in progress && typeof progress.status !== "number")) return "Sync";
49 if (typeof progress.status === "number") return { status: progress.status };
50 throw new Error(`Unexpected: ${progress}`);
51 });
52 const progress = progressMemo();
53 if (progress === "Spinner") return <LoadingSpinner center={true} />;
54 if (progress === "Delete") {
55 return (
56 <button title="Purge this file/these files from local sync storage">
57 <DeleteSVG />
58 </button>
59 );
60 }
61 if (progress === "Sync") {
62 return (
63 <button title="Sync missing files this file/directory to your browser for offline use">
64 <SyncSVG />
65 </button>
66 );
67 }
68 if (progress === "Refresh") {
69 return (
70 <button title="Re-sync this file">
71 <RefreshSVG />
72 </button>
73 );
74 }
75 if ("status" in progress) return <span>{formatBytes(progress.status)}</span>;
76 console.error("Unexpected", progress);
77 })()}
78 </div>
79 );
80}
81