DownloadButton.tsx
⎇
Raw
1import "./DownloadButton.css";
2import type { MediaFile, Directory, FileListing } from "music-server-shared/types";
3import { deleteFile, download, downloadStatusMap, type DownloadStatus } from "../offline";
4import type { Accessor, ResourceActions } from "solid-js";
5import type { AppOptions } from "../types";
6import { joinPath } from "../utils";
7import { DeleteSVG, RefreshSVG, SyncSVG } from "./SVG";
8import { LoadingSpinner } from "./LoadingScreen";
9
10interface DownloadButtonProps {
11 fileName: string;
12 item: MediaFile | Directory;
13 fetchFiles: ResourceActions<FileListing>;
14 isOffline: Accessor<boolean>;
15 currentDir: Accessor<string>;
16 options: Accessor<AppOptions>;
17}
18
19function formatProgress(bytes: number): string {
20 if (bytes === 0) return "Queued...";
21
22 const k = 1024;
23 const sizes = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
24 const i = Math.floor(Math.log(bytes) / Math.log(k));
25 const value = bytes / k ** i;
26
27 return `${value.toFixed(2)} ${sizes[i]}`;
28}
29
30export function DownloadButton(props: DownloadButtonProps) {
31 const fullPath = joinPath(props.currentDir(), props.fileName);
32
33 return (
34 <div
35 class="download-item"
36 onClick={(event) => {
37 event.stopPropagation();
38 if (!props.isOffline())
39 download(props.fileName, props.item, props.currentDir(), props.currentDir, props.options(), props.fetchFiles);
40 else deleteFile(props.fileName, props.item, props.currentDir(), props.fetchFiles);
41 }}
42 >
43 {(() => {
44 const progress = downloadStatusMap[fullPath];
45 if (progress === undefined) {
46 if (props.isOffline()) {
47 //only happens if this is a directory
48 return (
49 <button title="Purge the sync storage from all files recursively in this directory">
50 <DeleteSVG />
51 </button>
52 );
53 }
54 return (
55 <button title="Sync this file/directory to your browser for offline use">
56 <SyncSVG />
57 </button>
58 );
59 }
60 if (progress === "DirectoryProgress") return <LoadingSpinner center={true} />;
61 if (progress === "SyncedFile") {
62 if (props.isOffline()) {
63 return (
64 <button title="Purge this file from local sync storage">
65 <DeleteSVG />
66 </button>
67 );
68 }
69 return (
70 <button title="Re-sync this file">
71 <RefreshSVG />
72 </button>
73 );
74 }
75
76 if ("bytes" in progress) return <span>{formatProgress(progress.bytes)}</span>;
77 console.log(progress);
78 console.error("Unexpected", progress);
79 })()}
80 </div>
81 );
82}
83