feat: Added upload progress

This commit is contained in:
florian 2024-06-02 15:43:24 +02:00
parent 3e6df7a246
commit 78610d17a5
2 changed files with 68 additions and 18 deletions

View File

@ -8,13 +8,14 @@ import {
import { ServerList } from '../components/ServerList/ServerList';
import { useServerInfo } from '../utils/useServerInfo';
import { useMemo, useState } from 'react';
import { BlobDescriptor, BlossomClient } from 'blossom-client-sdk';
import { BlobDescriptor, BlossomClient, SignedEvent } from 'blossom-client-sdk';
import { useNDK } from '../utils/ndk';
import { useQueryClient } from '@tanstack/react-query';
import { formatFileSize } from '../utils/utils';
import BlobList from '../components/BlobList/BlobList';
import './Transfer.css';
import { useNavigate, useParams } from 'react-router-dom';
import axios, { AxiosProgressEvent } from 'axios';
import ProgressBar from '../components/ProgressBar/ProgressBar';
type TransferStatus = {
@ -23,6 +24,8 @@ type TransferStatus = {
status: 'pending' | 'done' | 'error';
message?: string;
size: number;
transferred?: number;
rate?: number;
};
};
@ -54,25 +57,71 @@ export const Transfer = () => {
}
return [];
}, [serverInfo, transferSource, transferTarget]);
// https://github.com/sindresorhus/p-limit
//
const uploadBlob = async (
server: string,
file: File,
auth?: SignedEvent,
onUploadProgress?: (progressEvent: AxiosProgressEvent) => void
) => {
const headers = {
Accept: 'application/json',
'Content-Type': file.type,
};
const res = await axios.put<BlobDescriptor>(`${server}/upload`, file, {
headers: auth ? { ...headers, authorization: BlossomClient.encodeAuthorizationHeader(auth) } : headers,
onUploadProgress,
});
return res.data;
};
const performTransfer = async (sourceServer: string, targetServer: string, blobs: BlobDescriptor[]) => {
setTransferLog({});
setStarted(true);
for (const b of blobs) {
try {
// BlossomClient.getGetAuth()
setTransferLog(ts => ({ ...ts, [b.sha256]: { sha256: b.sha256, status: 'pending', size: b.size } }));
setTransferLog(ts => ({
...ts,
[b.sha256]: { sha256: b.sha256, status: 'pending', size: b.size, transferred: 0, rate: 0 },
}));
const data = await BlossomClient.getBlob(serverInfo[sourceServer].url, b.sha256).catch(e => {
if (e.response?.status === 404) {
setTransferLog(ts => ({
...ts,
[b.sha256]: { sha256: b.sha256, status: 'error', message: 'Blob not found (404)', size: b.size },
}));
return null;
}
throw e;
});
if (!data) continue;
const data = await BlossomClient.getBlob(serverInfo[sourceServer].url, b.sha256);
const file = new File([data], b.sha256, { type: b.type, lastModified: b.created });
const uploadAuth = await BlossomClient.getUploadAuth(file, signEventTemplate, 'Upload Blob');
await BlossomClient.uploadBlob(serverInfo[targetServer].url, file, uploadAuth);
setTransferLog(ts => ({ ...ts, [b.sha256]: { sha256: b.sha256, status: 'done', size: b.size } }));
await uploadBlob(serverInfo[targetServer].url, file, uploadAuth, progressEvent => {
setTransferLog(ts => ({
...ts,
[b.sha256]: {
...ts[b.sha256],
transferred: progressEvent.loaded,
rate: progressEvent.rate || 0,
},
}));
});
setTransferLog(ts => ({
...ts,
[b.sha256]: { sha256: b.sha256, status: 'done', size: b.size },
}));
} catch (e) {
setTransferLog(ts => ({
...ts,
[b.sha256]: { sha256: b.sha256, status: 'error', message: (e as Error).message, size: blobs.length },
[b.sha256]: { sha256: b.sha256, status: 'error', message: (e as Error).message, size: b.size },
}));
console.warn(e);
}
@ -101,6 +150,8 @@ export const Transfer = () => {
return { ...stats, fullSize: transferJobs?.reduce((acc, b) => acc + b.size, 0) || 0 };
}, [transferLog, transferJobs]);
const transferErrors = useMemo(() => Object.values(transferLog).filter(b => b.status == 'error'), [transferLog]);
return transferSource ? (
<>
<ServerList
@ -148,11 +199,10 @@ export const Transfer = () => {
}
/>
{<div className="message"></div>}
<div className="error-log">
{Object.values(transferLog)
.filter(b => b.status == 'error')
.map(t => (
<div>
{transferErrors.length > 0 && (
<div className="error-log">
{transferErrors.map(t => (
<div key={t.sha256}>
<span>
<DocumentIcon />
</span>
@ -162,7 +212,8 @@ export const Transfer = () => {
<span>{t.message}</span>
</div>
))}
</div>
</div>
)}
</div>
</div>
{!started && <BlobList blobs={transferJobs}></BlobList>}

View File

@ -3,7 +3,7 @@ import useEvents from '../utils/useEvents';
import groupBy from 'lodash/groupBy';
import { NDKEvent, NDKFilter } from '@nostr-dev-kit/ndk';
import { useNDK } from '../utils/ndk';
import { mapValues, uniq } from 'lodash';
import { mapValues } from 'lodash';
export const KIND_FILE_META = 1063;
export const KIND_BLOSSOM_DRIVE = 30563;
@ -12,7 +12,6 @@ export const KIND_VIDEO_HORIZONTAL = 34235;
export const KIND_VIDEO_VERTICAL = 34236;
export const KIND_AUDIO = 31337;
const blossomUrlRegex = /https?:\/\/(?:www\.)?[^\s/]+\/([a-fA-F0-9]{64})(?:\.[a-zA-Z0-9]+)?/g;
function extractHashesFromContent(text: string) {
@ -58,7 +57,7 @@ const useFileMetaEventsByHash = () => {
const groupedByX = groupBy(allXTags, item => item.x);
return mapValues(groupedByX, v => v.map(e => e.ev));
}, [fileMetaSub]);
console.log(fileMetaEventsByHash);
console.log(fileMetaEventsByHash);
return fileMetaEventsByHash;
};