Show global progress while uploading
This commit is contained in:
@@ -184,7 +184,7 @@ onDestroy(() => {
|
|||||||
<td>{peer.load_1_min}</td>
|
<td>{peer.load_1_min}</td>
|
||||||
<td>{peer.load_5_min}</td>
|
<td>{peer.load_5_min}</td>
|
||||||
<td>{peer.load_15_min}</td>
|
<td>{peer.load_15_min}</td>
|
||||||
<td>{formatDuration(peer.latency)}</td>
|
<td>{formatDuration(peer.latency, 3)}</td>
|
||||||
<td>{formatDataVolume(peer.free_space, 3)}</td>
|
<td>{formatDataVolume(peer.free_space, 3)}</td>
|
||||||
<td>{formatDataVolume(peer.min_free_space, 3)}</td>
|
<td>{formatDataVolume(peer.min_free_space, 3)}</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -251,8 +251,8 @@ onDestroy(() => {
|
|||||||
<tr>
|
<tr>
|
||||||
<td>{q.query_name}</td>
|
<td>{q.query_name}</td>
|
||||||
<td>{q.calls}</td>
|
<td>{q.calls}</td>
|
||||||
<td>{formatDuration(q.average_duration)}</td>
|
<td>{formatDuration(q.average_duration, 3)}</td>
|
||||||
<td>{formatDuration(q.total_duration)}</td>
|
<td>{formatDuration(q.total_duration, 3)}</td>
|
||||||
<td>
|
<td>
|
||||||
{#each q.callers as caller}
|
{#each q.callers as caller}
|
||||||
{caller.count}x {caller.name}<br/>
|
{caller.count}x {caller.name}<br/>
|
||||||
|
@@ -6,6 +6,7 @@ import Facebook from "../icons/Facebook.svelte"
|
|||||||
import Reddit from "../icons/Reddit.svelte"
|
import Reddit from "../icons/Reddit.svelte"
|
||||||
import Twitter from "../icons/Twitter.svelte"
|
import Twitter from "../icons/Twitter.svelte"
|
||||||
import Tumblr from "../icons/Tumblr.svelte"
|
import Tumblr from "../icons/Tumblr.svelte"
|
||||||
|
import { formatDataVolume, formatDuration } from "../util/Formatting.svelte";
|
||||||
|
|
||||||
// === UPLOAD LOGIC ===
|
// === UPLOAD LOGIC ===
|
||||||
|
|
||||||
@@ -55,6 +56,9 @@ const upload_files = async (files) => {
|
|||||||
status: "queued",
|
status: "queued",
|
||||||
component: null,
|
component: null,
|
||||||
id: "",
|
id: "",
|
||||||
|
total_size: files[i].size,
|
||||||
|
loaded_size: 0,
|
||||||
|
transfer_rate: 0,
|
||||||
on_finished: finish_upload,
|
on_finished: finish_upload,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -82,9 +86,20 @@ const start_upload = () => {
|
|||||||
|
|
||||||
if (active_uploads === 0 && finished_count != 0) {
|
if (active_uploads === 0 && finished_count != 0) {
|
||||||
state = "finished"
|
state = "finished"
|
||||||
|
|
||||||
|
if (stats_interval !== null) {
|
||||||
|
clearInterval(stats_interval)
|
||||||
|
stats_interval = null
|
||||||
|
stats_finished()
|
||||||
|
}
|
||||||
|
|
||||||
uploads_finished()
|
uploads_finished()
|
||||||
} else {
|
} else {
|
||||||
state = "uploading"
|
state = "uploading"
|
||||||
|
|
||||||
|
if (stats_interval === null) {
|
||||||
|
stats_interval = setInterval(stats_update, 50)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,6 +108,43 @@ const finish_upload = (file) => {
|
|||||||
start_upload()
|
start_upload()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let stats_interval = null
|
||||||
|
let progress_bar_outer
|
||||||
|
let progress_bar_inner
|
||||||
|
let start_time = 0
|
||||||
|
let total_progress = 0
|
||||||
|
let total_size = 0
|
||||||
|
let total_loaded = 0
|
||||||
|
let total_rate = 0
|
||||||
|
let remaining_time = 0
|
||||||
|
const stats_update = () => {
|
||||||
|
if (start_time === 0) {
|
||||||
|
start_time = new Date().getTime()
|
||||||
|
}
|
||||||
|
|
||||||
|
total_size = 0
|
||||||
|
total_loaded = 0
|
||||||
|
total_rate = 0
|
||||||
|
for (let i = 0; i < upload_queue.length; i++) {
|
||||||
|
total_size += upload_queue[i].total_size
|
||||||
|
total_loaded += upload_queue[i].loaded_size
|
||||||
|
total_rate += upload_queue[i].transfer_rate
|
||||||
|
}
|
||||||
|
|
||||||
|
total_progress = total_loaded / total_size
|
||||||
|
|
||||||
|
let elapsed_time = new Date().getTime() - start_time
|
||||||
|
remaining_time = (elapsed_time/total_progress) - elapsed_time
|
||||||
|
|
||||||
|
progress_bar_inner.style.width = (total_progress * 100) + "%"
|
||||||
|
}
|
||||||
|
|
||||||
|
const stats_finished = () => {
|
||||||
|
start_time = 0
|
||||||
|
total_loaded = total_size
|
||||||
|
total_rate = 0
|
||||||
|
}
|
||||||
|
|
||||||
// === SHARING BUTTONS ===
|
// === SHARING BUTTONS ===
|
||||||
|
|
||||||
let navigator_share = !!(window.navigator && window.navigator.share)
|
let navigator_share = !!(window.navigator && window.navigator.share)
|
||||||
@@ -350,12 +402,22 @@ const keydown = (e) => {
|
|||||||
<a href="/about#content-policy">content policy</a>.
|
<a href="/about#content-policy">content policy</a>.
|
||||||
<p>
|
<p>
|
||||||
|
|
||||||
<div class="instruction">
|
<div class="instruction" style="margin-bottom: 0;">
|
||||||
<div class="limit_width">
|
<div class="limit_width">
|
||||||
<span class="big_number">2</span>
|
<span class="big_number">2</span>
|
||||||
<span class="instruction_text">Wait for the files to finish uploading</span>
|
<span class="instruction_text">Wait for the files to finish uploading</span>
|
||||||
|
<br/>
|
||||||
|
<div class="stats_box">
|
||||||
|
<div>Size: {formatDataVolume(total_size, 3)}</div>
|
||||||
|
<div>Progress: {(total_progress*100).toPrecision(3)}%</div>
|
||||||
|
<div>ETA {formatDuration(remaining_time, 0)}</div>
|
||||||
|
<div>Rate: {formatDataVolume(total_rate, 3)}/s</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div bind:this={progress_bar_outer} class="progress_bar_outer" style="margin-bottom: 1.5em;">
|
||||||
|
<div bind:this={progress_bar_inner} class="progress_bar_inner"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="file_drop_highlight" class="highlight_green" class:hide={!dragging}>
|
<div id="file_drop_highlight" class="highlight_green" class:hide={!dragging}>
|
||||||
Gimme gimme gimme!<br/>
|
Gimme gimme gimme!<br/>
|
||||||
@@ -473,6 +535,27 @@ const keydown = (e) => {
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
.stats_box {
|
||||||
|
display: inline-grid;
|
||||||
|
grid-template-columns: 25% 25% 25% 25%;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
font-family: sans-serif, monospace;
|
||||||
|
}
|
||||||
|
@media (max-width: 1000px) {
|
||||||
|
.stats_box {
|
||||||
|
grid-template-columns: 50% 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.progress_bar_outer {
|
||||||
|
width: 100%;
|
||||||
|
height: 3px;
|
||||||
|
}
|
||||||
|
.progress_bar_inner {
|
||||||
|
background-color: var(--highlight_color);
|
||||||
|
height: 100%;
|
||||||
|
width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.social_buttons {
|
.social_buttons {
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
|
@@ -3,44 +3,49 @@ import { domain_url } from "../util/Util.svelte"
|
|||||||
import { formatDataVolume, formatDuration} from "../util/Formatting.svelte"
|
import { formatDataVolume, formatDuration} from "../util/Formatting.svelte"
|
||||||
|
|
||||||
export let job = {}
|
export let job = {}
|
||||||
let loaded_size
|
|
||||||
let total_size
|
|
||||||
let file_button
|
let file_button
|
||||||
let tries = 0
|
let tries = 0
|
||||||
let start_time = 0
|
let start_time = 0
|
||||||
let remaining_time = 0
|
let remaining_time = 0
|
||||||
|
|
||||||
|
let statsInterval = null
|
||||||
|
let progress = 0
|
||||||
let last_progress_time = 0
|
let last_progress_time = 0
|
||||||
let last_loaded_size = 0
|
let last_loaded_size = 0
|
||||||
let transfer_rate = 0
|
|
||||||
const on_progress = () => {
|
const on_progress = () => {
|
||||||
let now = new Date().getTime()
|
if (job.loaded_size === 0 || job.total_size === 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
let prog = loaded_size / total_size
|
let now = new Date().getTime()
|
||||||
|
progress = job.loaded_size / job.total_size
|
||||||
let elapsed_time = now - start_time
|
let elapsed_time = now - start_time
|
||||||
remaining_time = (elapsed_time/prog) - elapsed_time
|
remaining_time = (elapsed_time/progress) - elapsed_time
|
||||||
|
|
||||||
// Calculate transfer rate
|
// Calculate transfer rate
|
||||||
if (last_progress_time != 0) {
|
if (last_progress_time != 0) {
|
||||||
let new_rate = (1000 / (now - last_progress_time)) * (loaded_size - last_loaded_size)
|
let new_rate = (1000 / (now - last_progress_time)) * (job.loaded_size - last_loaded_size)
|
||||||
|
|
||||||
// Apply smoothing by mixing it with the previous number 10:1
|
// Apply smoothing by mixing it with the previous number 10:1
|
||||||
transfer_rate = (transfer_rate * 0.9) + (new_rate * 0.1)
|
job.transfer_rate = Math.floor((job.transfer_rate * 0.9) + (new_rate * 0.1))
|
||||||
}
|
}
|
||||||
|
|
||||||
last_progress_time = now
|
last_progress_time = now
|
||||||
last_loaded_size = loaded_size
|
last_loaded_size = job.loaded_size
|
||||||
|
|
||||||
file_button.style.background = 'linear-gradient(' +
|
file_button.style.background = 'linear-gradient(' +
|
||||||
'to right, ' +
|
'to right, ' +
|
||||||
'var(--layer_3_color) 0%, ' +
|
'var(--layer_3_color) 0%, ' +
|
||||||
'var(--highlight_color) ' + (prog * 100) + '%, ' +
|
'var(--highlight_color) ' + (progress * 100) + '%, ' +
|
||||||
'var(--layer_3_color) ' + ((prog * 100) + 1) + '%)'
|
'var(--layer_3_color) ' + ((progress * 100) + 1) + '%)'
|
||||||
}
|
}
|
||||||
|
|
||||||
let href = null
|
let href = null
|
||||||
let target = null
|
let target = null
|
||||||
const on_success = (resp) => {
|
const on_success = (resp) => {
|
||||||
|
clearInterval(statsInterval)
|
||||||
|
job.transfer_rate = 0
|
||||||
|
|
||||||
job.id = resp.id
|
job.id = resp.id
|
||||||
job.status = "finished"
|
job.status = "finished"
|
||||||
job.on_finished(job)
|
job.on_finished(job)
|
||||||
@@ -56,6 +61,10 @@ const on_success = (resp) => {
|
|||||||
let error_id = ""
|
let error_id = ""
|
||||||
let error_reason = ""
|
let error_reason = ""
|
||||||
const on_failure = (status, message) => {
|
const on_failure = (status, message) => {
|
||||||
|
clearInterval(statsInterval)
|
||||||
|
job.transfer_rate = 0
|
||||||
|
job.loaded_size = job.total_size
|
||||||
|
|
||||||
error_id = status
|
error_id = status
|
||||||
error_reason = message
|
error_reason = message
|
||||||
job.status = "error"
|
job.status = "error"
|
||||||
@@ -67,6 +76,7 @@ const on_failure = (status, message) => {
|
|||||||
|
|
||||||
export const start = () => {
|
export const start = () => {
|
||||||
start_time = new Date().getTime()
|
start_time = new Date().getTime()
|
||||||
|
statsInterval = setInterval(on_progress, 50) // 20 FPS, plenty for stats
|
||||||
|
|
||||||
let form = new FormData();
|
let form = new FormData();
|
||||||
form.append('file', job.file, job.name);
|
form.append('file', job.file, job.name);
|
||||||
@@ -77,9 +87,8 @@ export const start = () => {
|
|||||||
|
|
||||||
xhr.upload.addEventListener("progress", evt => {
|
xhr.upload.addEventListener("progress", evt => {
|
||||||
if (evt.lengthComputable) {
|
if (evt.lengthComputable) {
|
||||||
loaded_size = evt.loaded
|
job.loaded_size = evt.loaded
|
||||||
total_size = evt.total
|
job.total_size = evt.total
|
||||||
on_progress()
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -171,13 +180,13 @@ const add_upload_history = id => {
|
|||||||
Queued...
|
Queued...
|
||||||
{:else if job.status === "uploading"}
|
{:else if job.status === "uploading"}
|
||||||
<div class="stat">
|
<div class="stat">
|
||||||
{((loaded_size/total_size)*100).toPrecision(3)}%
|
{(progress*100).toPrecision(3)}%
|
||||||
</div>
|
</div>
|
||||||
<div class="stat">
|
<div class="stat">
|
||||||
ETA {formatDuration(remaining_time, 0)}
|
ETA {formatDuration(remaining_time, 0)}
|
||||||
</div>
|
</div>
|
||||||
<div class="stat">
|
<div class="stat">
|
||||||
{formatDataVolume(transfer_rate, 3)}/s
|
{formatDataVolume(job.transfer_rate, 3)}/s
|
||||||
</div>
|
</div>
|
||||||
{:else if job.status === "finished"}
|
{:else if job.status === "finished"}
|
||||||
<span class="file_link">
|
<span class="file_link">
|
||||||
@@ -243,6 +252,7 @@ const add_upload_history = id => {
|
|||||||
}
|
}
|
||||||
.upload_task > .queue_body > .title {
|
.upload_task > .queue_body > .title {
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
.upload_task > .queue_body > .stats {
|
.upload_task > .queue_body > .stats {
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
@@ -251,7 +261,7 @@ const add_upload_history = id => {
|
|||||||
height: 1.4em;
|
height: 1.4em;
|
||||||
border-top: 1px solid var(--layer_3_color_border);
|
border-top: 1px solid var(--layer_3_color_border);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-family: 'monospace', sans-serif;
|
font-family: sans-serif, monospace;
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
}
|
}
|
||||||
.upload_task > .queue_body > .stats > .stat {
|
.upload_task > .queue_body > .stats > .stat {
|
||||||
|
Reference in New Issue
Block a user