mirror of
https://github.com/mickael-kerjean/filestash
synced 2025-12-15 12:55:41 +01:00
fix (upload): canary file uploader
This commit is contained in:
parent
a72925c5d8
commit
c343338983
2 changed files with 36 additions and 26 deletions
|
|
@ -66,6 +66,9 @@
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
font-size: 0.85em;
|
font-size: 0.85em;
|
||||||
}
|
}
|
||||||
|
.component_upload .stats_content:empty {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
.component_upload .stats_content .error_color {
|
.component_upload .stats_content .error_color {
|
||||||
color: var(--error);
|
color: var(--error);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ function componentFilezone(render, { workers$ }) {
|
||||||
if (!isNativeFileUpload(e)) return;
|
if (!isNativeFileUpload(e)) return;
|
||||||
$target.classList.remove("dropzone");
|
$target.classList.remove("dropzone");
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const loadID = setTimeout(() => render(createElement("<div>LOADING</div>")), 2000);
|
workers$.next({ loading: true });
|
||||||
if (e.dataTransfer.items instanceof window.DataTransferItemList) {
|
if (e.dataTransfer.items instanceof window.DataTransferItemList) {
|
||||||
workers$.next(await processItems(e.dataTransfer.items));
|
workers$.next(await processItems(e.dataTransfer.items));
|
||||||
} else if (e.dataTransfer.files instanceof window.FileList) {
|
} else if (e.dataTransfer.files instanceof window.FileList) {
|
||||||
|
|
@ -82,8 +82,6 @@ function componentFilezone(render, { workers$ }) {
|
||||||
} else {
|
} else {
|
||||||
assert.fail("NOT_IMPLEMENTED - unknown entry type in ctrl_upload.js");
|
assert.fail("NOT_IMPLEMENTED - unknown entry type in ctrl_upload.js");
|
||||||
}
|
}
|
||||||
clearTimeout(loadID);
|
|
||||||
render(createFragment(""));
|
|
||||||
};
|
};
|
||||||
$target.ondragleave = (e) => {
|
$target.ondragleave = (e) => {
|
||||||
if (!isNativeFileUpload(e)) return;
|
if (!isNativeFileUpload(e)) return;
|
||||||
|
|
@ -145,7 +143,12 @@ function componentUploadQueue(render, { workers$ }) {
|
||||||
})).subscribe();
|
})).subscribe();
|
||||||
|
|
||||||
// feature2: setup the task queue in the dom
|
// feature2: setup the task queue in the dom
|
||||||
workers$.subscribe(({ tasks }) => {
|
workers$.subscribe(({ tasks, loading = false, size }) => {
|
||||||
|
if (loading) {
|
||||||
|
$page.classList.remove("hidden");
|
||||||
|
updateDOMGlobalTitle($page, t("Loading")+ "...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (tasks.length === 0) return;
|
if (tasks.length === 0) return;
|
||||||
updateTotal.addToTotal(tasks.length);
|
updateTotal.addToTotal(tasks.length);
|
||||||
const $fragment = document.createDocumentFragment();
|
const $fragment = document.createDocumentFragment();
|
||||||
|
|
@ -158,8 +161,8 @@ function componentUploadQueue(render, { workers$ }) {
|
||||||
$task.firstElementChild.nextElementSibling.classList.add("file_state_todo"); // qs($todo, ".file_state")
|
$task.firstElementChild.nextElementSibling.classList.add("file_state_todo"); // qs($todo, ".file_state")
|
||||||
$task.firstElementChild.nextElementSibling.textContent = t("Waiting");
|
$task.firstElementChild.nextElementSibling.textContent = t("Waiting");
|
||||||
}
|
}
|
||||||
$page.classList.remove("hidden");
|
|
||||||
$content.appendChild($fragment);
|
$content.appendChild($fragment);
|
||||||
|
$content.classList.remove("hidden");
|
||||||
});
|
});
|
||||||
|
|
||||||
// feature3: process tasks
|
// feature3: process tasks
|
||||||
|
|
@ -286,7 +289,8 @@ function componentUploadQueue(render, { workers$ }) {
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
const noFailureAllowed = (fn) => fn().catch(() => noFailureAllowed(fn));
|
const noFailureAllowed = (fn) => fn().catch(() => noFailureAllowed(fn));
|
||||||
workers$.subscribe(async({ tasks: newTasks }) => {
|
workers$.subscribe(async({ tasks: newTasks, loading = false }) => {
|
||||||
|
if (loading) return;
|
||||||
tasks = tasks.concat(newTasks); // add new tasks to the pool
|
tasks = tasks.concat(newTasks); // add new tasks to the pool
|
||||||
while (true) {
|
while (true) {
|
||||||
const nworker = reservations.indexOf(false);
|
const nworker = reservations.indexOf(false);
|
||||||
|
|
@ -323,13 +327,12 @@ function workerImplFile({ progress, speed }) {
|
||||||
*/
|
*/
|
||||||
async run({ file, path, virtual }) {
|
async run({ file, path, virtual }) {
|
||||||
const _file = await file();
|
const _file = await file();
|
||||||
const executeJob = (firstRun) => this.prepareJob({ file: _file, path, virtual, firstRun });
|
const executeJob = () => this.prepareJob({ file: _file, path, virtual });
|
||||||
this.retry = () => executeJob(false);
|
this.retry = () => executeJob();
|
||||||
return executeJob(true);
|
return executeJob();
|
||||||
}
|
}
|
||||||
|
|
||||||
async prepareJob({ file, path, virtual, firstRun }) {
|
async prepareJob({ file, path, virtual }) {
|
||||||
if (firstRun === false) virtual.before();
|
|
||||||
const chunkSize = (window.CONFIG["upload_chunk_size"] || 0) *1024*1024;
|
const chunkSize = (window.CONFIG["upload_chunk_size"] || 0) *1024*1024;
|
||||||
const numberOfChunks = Math.ceil(file.size / chunkSize);
|
const numberOfChunks = Math.ceil(file.size / chunkSize);
|
||||||
|
|
||||||
|
|
@ -409,13 +412,12 @@ function workerImplDirectory({ progress }) {
|
||||||
* @override
|
* @override
|
||||||
*/
|
*/
|
||||||
async run({ virtual, path }) {
|
async run({ virtual, path }) {
|
||||||
const executeJob = (firstRun) => this.prepareJob({ virtual, path, firstRun });
|
const executeJob = () => this.prepareJob({ virtual, path });
|
||||||
this.retry = () => executeJob(false);
|
this.retry = () => executeJob();
|
||||||
return executeJob(true);
|
return executeJob();
|
||||||
}
|
}
|
||||||
|
|
||||||
async prepareJob({ virtual, path, firstRun }) {
|
async prepareJob({ virtual, path }) {
|
||||||
if (firstRun === false) virtual.before();
|
|
||||||
let percent = 0;
|
let percent = 0;
|
||||||
const id = setInterval(() => {
|
const id = setInterval(() => {
|
||||||
percent += 10;
|
percent += 10;
|
||||||
|
|
@ -508,7 +510,7 @@ function executeHttp(url, { method, headers, body, progress, speed }) {
|
||||||
|
|
||||||
async function processFiles(filelist) {
|
async function processFiles(filelist) {
|
||||||
const tasks = [];
|
const tasks = [];
|
||||||
// let size = 0; // TODO
|
let size = 0;
|
||||||
const detectFiletype = (file) => {
|
const detectFiletype = (file) => {
|
||||||
// the 4096 is an heuristic observed and taken from:
|
// the 4096 is an heuristic observed and taken from:
|
||||||
// https://stackoverflow.com/questions/25016442
|
// https://stackoverflow.com/questions/25016442
|
||||||
|
|
@ -534,7 +536,6 @@ async function processFiles(filelist) {
|
||||||
let task = null;
|
let task = null;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "file":
|
case "file":
|
||||||
// size += currentFile.size;
|
|
||||||
task = {
|
task = {
|
||||||
type: "file",
|
type: "file",
|
||||||
file: () => new Promise((resolve) => resolve(currentFile)),
|
file: () => new Promise((resolve) => resolve(currentFile)),
|
||||||
|
|
@ -545,8 +546,8 @@ async function processFiles(filelist) {
|
||||||
done: false,
|
done: false,
|
||||||
ready: () => true,
|
ready: () => true,
|
||||||
entry: currentFile,
|
entry: currentFile,
|
||||||
|
|
||||||
};
|
};
|
||||||
|
size += currentFile.size;
|
||||||
break;
|
break;
|
||||||
case "directory":
|
case "directory":
|
||||||
path += "/";
|
path += "/";
|
||||||
|
|
@ -559,15 +560,15 @@ async function processFiles(filelist) {
|
||||||
done: false,
|
done: false,
|
||||||
ready: () => true,
|
ready: () => true,
|
||||||
};
|
};
|
||||||
|
size += 4096;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert.fail(`NOT_SUPPORTED type="${type}"`);
|
assert.fail(`NOT_SUPPORTED type="${type}"`);
|
||||||
}
|
}
|
||||||
task = assert.truthy(task);
|
task = assert.truthy(task);
|
||||||
task.virtual.before();
|
|
||||||
tasks.push(task);
|
tasks.push(task);
|
||||||
}
|
}
|
||||||
return { tasks, size: 0 };
|
return { tasks, size };
|
||||||
}
|
}
|
||||||
|
|
||||||
async function processItems(itemList) {
|
async function processItems(itemList) {
|
||||||
|
|
@ -609,9 +610,12 @@ async function processItems(itemList) {
|
||||||
done: false,
|
done: false,
|
||||||
ready: () => false,
|
ready: () => false,
|
||||||
};
|
};
|
||||||
queue = queue.concat(await new Promise((resolve) => {
|
const reader = entry.createReader();
|
||||||
entry.createReader().readEntries(resolve);
|
let q = [];
|
||||||
}));
|
do {
|
||||||
|
q = await new Promise((resolve) => reader.readEntries(resolve));
|
||||||
|
queue = queue.concat(q);
|
||||||
|
} while (q.length > 0);
|
||||||
} else {
|
} else {
|
||||||
assert.fail("NOT_IMPLEMENTED - unknown entry type in ctrl_upload.js");
|
assert.fail("NOT_IMPLEMENTED - unknown entry type in ctrl_upload.js");
|
||||||
}
|
}
|
||||||
|
|
@ -642,7 +646,7 @@ function formatPercent(number) {
|
||||||
return `${number}%`;
|
return `${number}%`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatSpeed(bytes, si = true) {
|
function formatSize(bytes, si = true) {
|
||||||
const thresh = si ? 1000 : 1024;
|
const thresh = si ? 1000 : 1024;
|
||||||
if (Math.abs(bytes) < thresh) {
|
if (Math.abs(bytes) < thresh) {
|
||||||
return bytes.toFixed(1) + "B/s";
|
return bytes.toFixed(1) + "B/s";
|
||||||
|
|
@ -655,5 +659,8 @@ function formatSpeed(bytes, si = true) {
|
||||||
bytes /= thresh;
|
bytes /= thresh;
|
||||||
++u;
|
++u;
|
||||||
} while (Math.abs(bytes) >= thresh && u < units.length - 1);
|
} while (Math.abs(bytes) >= thresh && u < units.length - 1);
|
||||||
return bytes.toFixed(1) + units[u] + "/s";
|
return bytes.toFixed(1) + units[u];
|
||||||
|
}
|
||||||
|
function formatSpeed(bytes, si = true) {
|
||||||
|
return formatSize(bytes, si)+ "/s";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue