Merge pull request 'feat: 全部下载' (#91) from awalol/um-react:downloadall-fork-chakra-to-daisy into chakra-to-daisy

Reviewed-on: https://git.unlock-music.dev/um/um-react/pulls/91
Reviewed-by: 鲁树人 <lsr@noreply.unlock-music.dev>
This commit is contained in:
鲁树人 2025-06-16 10:15:13 +00:00
commit cbb6347251
2 changed files with 67 additions and 0 deletions

View File

@ -15,6 +15,7 @@ import { Bounce, ToastContainer } from 'react-toastify';
import { SettingsHome } from '~/features/settings/SettingsHome';
import { FAQ_PAGES } from '~/faq/FAQPages';
import { FaqHome } from '~/faq/FaqHome';
import { DownloadAll } from '~/components/DownloadAll.tsx';
// Private to this file only.
const store = setupStore();
@ -71,6 +72,7 @@ export function AppRoot() {
transition={Bounce}
/>
<DownloadAll />
<Footer />
</Provider>
</BrowserRouter>

View File

@ -0,0 +1,65 @@
import { DecryptedAudioFile, selectFiles } from '~/features/file-listing/fileListingSlice';
import { FaDownload } from 'react-icons/fa';
import { useAppSelector } from '~/hooks';
import { toast } from 'react-toastify';
export function DownloadAll() {
const files = useAppSelector(selectFiles);
const filesLength = Object.keys(files).length;
const onClickDownloadAll = async () => {
let dir: FileSystemDirectoryHandle | undefined;
let success = 0;
try {
dir = await window.showDirectoryPicker();
} catch (e) {
console.error(e);
if (e instanceof Error && e.name === 'AbortError') {
return;
}
}
for (const [_, file] of Object.entries(files)) {
try {
if (dir) {
await DownloadNew(dir, file);
} else {
await DownloadOld(file);
}
success++;
} catch (e) {
console.error(`下载失败: ${file.fileName}`, e);
toast.error(`出现错误: ${e}`);
}
}
if (success === filesLength) {
toast.success(`成功下载: ${success}/${filesLength}`);
} else {
toast.error(`成功下载: ${success}/${filesLength}`);
}
};
return (
<button
style={{ width: '48px', height: '48px', paddingInline: '0px', margin: '10px', marginLeft: 'auto' }}
className="btn btn-primary"
onClick={onClickDownloadAll}
title="下载全部"
>
<FaDownload />
</button>
);
}
async function DownloadNew(dir: FileSystemDirectoryHandle, file: DecryptedAudioFile) {
const fileHandle = await dir.getFileHandle(file.cleanName + '.' + file.ext, { create: true });
const writable = await fileHandle.createWritable();
await fetch(file.decrypted).then((res) => res.body?.pipeTo(writable));
}
async function DownloadOld(file: DecryptedAudioFile) {
const a = document.createElement('a');
a.href = file.decrypted;
a.download = file.cleanName + '.' + file.ext;
document.body.append(a);
a.click();
a.remove();
}