Add ETA
This commit is contained in:
@@ -2,6 +2,7 @@ use futures_util::stream::StreamExt;
|
|||||||
use sha2::{Digest, Sha512};
|
use sha2::{Digest, Sha512};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use std::time::Instant;
|
||||||
use std::{
|
use std::{
|
||||||
fs::{File, create_dir_all},
|
fs::{File, create_dir_all},
|
||||||
io::{BufReader, copy},
|
io::{BufReader, copy},
|
||||||
@@ -135,6 +136,8 @@ async fn download(
|
|||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
let start = Instant::now();
|
||||||
|
|
||||||
while let Ok(Some(chunk_result)) = timeout(Duration::from_secs(5), stream.next()).await {
|
while let Ok(Some(chunk_result)) = timeout(Duration::from_secs(5), stream.next()).await {
|
||||||
let chunk = match chunk_result {
|
let chunk = match chunk_result {
|
||||||
Ok(c) => c,
|
Ok(c) => c,
|
||||||
@@ -155,8 +158,19 @@ async fn download(
|
|||||||
0.0
|
0.0
|
||||||
};
|
};
|
||||||
|
|
||||||
app.emit("download-progress", format!("{}:{:.8}:{}", &name, progress, downloaded))
|
let elapsed_secs = start.elapsed().as_secs_f64();
|
||||||
.unwrap();
|
let speed = downloaded as f64 / elapsed_secs;
|
||||||
|
let eta_secs = if total_size > downloaded {
|
||||||
|
(total_size - downloaded) as f64 / speed
|
||||||
|
} else {
|
||||||
|
0.0
|
||||||
|
};
|
||||||
|
|
||||||
|
app.emit(
|
||||||
|
"download-progress",
|
||||||
|
format!("{}:{:.8}:{}:{:.2}", &name, progress, downloaded, eta_secs),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
if total_size > 0 && downloaded < total_size {
|
if total_size > 0 && downloaded < total_size {
|
||||||
|
|||||||
@@ -115,14 +115,21 @@ export default function RootLayout ({
|
|||||||
let unlistenUninstalled: (() => void) | null = null
|
let unlistenUninstalled: (() => void) | null = null
|
||||||
|
|
||||||
listen<string>('download-progress', event => {
|
listen<string>('download-progress', event => {
|
||||||
const [versionName, progStr, totalSizeStr] = event.payload.split(':')
|
const [versionName, progStr, totalSizeStr, etaSecsStr] =
|
||||||
|
event.payload.split(':')
|
||||||
const prog = Number(progStr)
|
const prog = Number(progStr)
|
||||||
const progBytes = Number(totalSizeStr)
|
const progBytes = Number(totalSizeStr)
|
||||||
|
const etaSecs = Number(etaSecsStr)
|
||||||
setDownloadProgress(prev => {
|
setDownloadProgress(prev => {
|
||||||
const i = prev.findIndex(d => d.version === versionName)
|
const i = prev.findIndex(d => d.version === versionName)
|
||||||
if (i === -1) return prev
|
if (i === -1) return prev
|
||||||
const copy = [...prev]
|
const copy = [...prev]
|
||||||
copy[i] = { ...copy[i], progress: prog, progressBytes: progBytes }
|
copy[i] = {
|
||||||
|
...copy[i],
|
||||||
|
progress: prog,
|
||||||
|
progressBytes: progBytes,
|
||||||
|
etaSecs
|
||||||
|
}
|
||||||
return copy
|
return copy
|
||||||
})
|
})
|
||||||
}).then(f => (unlistenProgress = f))
|
}).then(f => (unlistenProgress = f))
|
||||||
@@ -271,7 +278,8 @@ export default function RootLayout ({
|
|||||||
setSelectedVersionList([])
|
setSelectedVersionList([])
|
||||||
|
|
||||||
const newDownloads = list.map(
|
const newDownloads = list.map(
|
||||||
version => new DownloadProgress(version, 0, 0, false, true, false, false)
|
version =>
|
||||||
|
new DownloadProgress(version, 0, 0, false, true, false, false, 0)
|
||||||
)
|
)
|
||||||
|
|
||||||
setDownloadProgress(newDownloads)
|
setDownloadProgress(newDownloads)
|
||||||
@@ -353,6 +361,20 @@ export default function RootLayout ({
|
|||||||
return { installed, total }
|
return { installed, total }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatEtaSmart (seconds: number) {
|
||||||
|
if (seconds < 60) return `${Math.floor(seconds)}s`
|
||||||
|
if (seconds < 3600)
|
||||||
|
return `${Math.floor(seconds / 60)}m ${Math.floor(seconds % 60)}s`
|
||||||
|
if (seconds < 86400) {
|
||||||
|
const h = Math.floor(seconds / 3600)
|
||||||
|
const m = Math.floor((seconds % 3600) / 60)
|
||||||
|
return `${h}h ${m}m`
|
||||||
|
}
|
||||||
|
const d = Math.floor(seconds / 86400)
|
||||||
|
const h = Math.floor((seconds % 86400) / 3600)
|
||||||
|
return `${d}d ${h}h`
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<html lang='en' className={roboto.className}>
|
<html lang='en' className={roboto.className}>
|
||||||
@@ -674,7 +696,7 @@ export default function RootLayout ({
|
|||||||
maximumFractionDigits: 1
|
maximumFractionDigits: 1
|
||||||
}
|
}
|
||||||
)}{' '}
|
)}{' '}
|
||||||
({Math.floor(v.progress)}%)
|
(ETA: {formatEtaSmart(v.etaSecs)})
|
||||||
</span>
|
</span>
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
progress={v.progress}
|
progress={v.progress}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ export class DownloadProgress {
|
|||||||
public failed: boolean,
|
public failed: boolean,
|
||||||
public queued: boolean,
|
public queued: boolean,
|
||||||
public hash_checking: boolean,
|
public hash_checking: boolean,
|
||||||
public finishing: boolean
|
public finishing: boolean,
|
||||||
|
public etaSecs: number
|
||||||
) { }
|
) { }
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user