lbry-desktop/ui/component/downloadProgress/view.jsx
2021-10-06 10:32:14 -07:00

202 lines
6 KiB
JavaScript
Executable file

// @flow
import React, { useState, useEffect } from 'react';
import { shell } from 'electron';
import Button from 'component/button';
import * as ICONS from 'constants/icons';
import { buildURI } from 'lbry-redux';
import { formatBytes } from 'util/format-bytes';
import usePersistedState from 'effects/use-persisted-state';
type Props = {
downloadList: any[],
stopDownload: (outpoint: string) => void,
updateDownloadingStatus: (outpoint: string) => void,
};
function DownloadProgress({ downloadList, stopDownload, updateDownloadingStatus }: Props) {
const [isShow, setIsShow] = usePersistedState('download-progress', true);
const [cancelHash] = useState({});
const [checkDownloadingHash] = useState({});
const handleCancel = (hash, value) => {
cancelHash[hash] = value;
};
if (downloadList.length === 0) return null;
downloadList.map((item) => {
if (item && !checkDownloadingHash[item.outpoint]) {
updateDownloadingStatus(item.outpoint);
checkDownloadingHash[item.outpoint] = true;
}
});
if (!isShow) {
return (
<Button
iconSize={40}
icon={ICONS.DOWNLOAD}
className="download-progress__toggle-button"
onClick={() => setIsShow(true)}
/>
);
}
return (
<div className="download-progress__header">
<Button className="download-progress__top-close-button" onClick={() => setIsShow(false)}>
<div />
</Button>
{downloadList.map((item, index) => {
let releaseTime = '';
if (item.metadata && item.metadata.release_time) {
releaseTime = new Date(parseInt(item.metadata.release_time) * 1000).toISOString().split('T')[0];
}
return (
<div key={item.outpoint}>
{index !== 0 && <hr className="download-progress__divider" />}
<DownloadProgressItem
fileName={item.suggested_file_name}
title={item.metadata.title}
releaseTime={releaseTime}
writtenBytes={item.written_bytes}
totalBytes={item.total_bytes}
addedOn={item.added_on}
directory={item.download_directory}
stopDownload={stopDownload}
outpoint={item.outpoint}
isCancel={cancelHash[item.outpoint]}
claimID={item.claim_id}
claimName={item.claim_name}
handleCancel={handleCancel}
/>
</div>
);
})}
</div>
);
}
type DownloadProgressItemProps = {
fileName: string,
writtenBytes: number,
totalBytes: number,
addedOn: number,
title: string,
releaseTime: string,
directory: string,
outpoint: string,
isCancel: boolean,
claimID: string,
claimName: string,
stopDownload: (outpoint: string) => void,
handleCancel: (hash: string, value: boolean) => void,
};
function DownloadProgressItem({
fileName,
writtenBytes,
totalBytes,
addedOn,
title,
releaseTime,
directory,
outpoint,
isCancel,
claimID,
claimName,
stopDownload,
handleCancel,
}: DownloadProgressItemProps) {
const processStopDownload = () => {
handleCancel(outpoint, false);
stopDownload(outpoint);
};
const [percent, setPercent] = useState(0);
const [progressText, setProgressText] = useState('');
useEffect(() => {
const updatePercent = ((writtenBytes / totalBytes) * 100).toFixed(0);
setPercent(updatePercent);
let updateText = '';
const downloadSpeed = Math.ceil(writtenBytes / (Date.now() / 1000 - addedOn));
const remainingSecond = Math.ceil((totalBytes - writtenBytes) / downloadSpeed);
const remainingMinutes = Math.floor(remainingSecond / 60);
if (remainingMinutes > 0) {
updateText += __('%remainingMinutes% minutes %remainSecond% seconds remaining', {
remainingMinutes: remainingMinutes,
remainSecond: remainingSecond - 60 * remainingMinutes,
});
} else {
updateText += __('%remainSecond% seconds remaining', { remainSecond: remainingSecond - 60 * remainingMinutes });
}
updateText += ' -- ';
updateText += __('%written% of %total%', {
written: formatBytes(writtenBytes),
total: formatBytes(totalBytes),
});
updateText += ' ';
updateText += __('(%speed%/sec)', {
speed: formatBytes(downloadSpeed),
});
setProgressText(updateText);
}, [writtenBytes, totalBytes, addedOn]);
const openDownloadFolder = () => {
shell.openPath(directory);
};
return (
<div className="download-progress__state-container">
<div className="download-progress__state-bar">
<Button
label={title}
className="download-progress__state-filename"
navigate={buildURI({ claimName, claimID })}
/>
<div
className="download-progress__close-button"
onClick={() => {
handleCancel(outpoint, true);
}}
>
&times;
</div>
</div>
<div className="download-progress__state-bar">
<a className="download-progress__state-filename-link" onClick={openDownloadFolder}>
{fileName}
</a>
<p className="download-progress__release-time">{releaseTime}</p>
</div>
<div className="download-progress__state-bar">
<div className="download-progress__bar-container">
<div className="download-progress__bar-content" style={{ width: `${percent}%` }} />
</div>
</div>
<p className="download-progress__count-time">{progressText}</p>
{isCancel && (
<div className="download-progress__cancel">
<p>{__('Do you cancel download this file?')}</p>
<div className="download-progress__cancel-confirm">
<Button label={__('Yes')} className="download-progress__cancel-ok" onClick={processStopDownload} />
<Button
label={__('No')}
className="download-progress__cancel-ok"
onClick={() => handleCancel(outpoint, false)}
/>
</div>
</div>
)}
</div>
);
}
export default DownloadProgress;