Add progress bar to download of all files

This commit is contained in:
bohwaz 2022-11-22 03:40:49 +01:00
parent 9511ba7e49
commit f34acf7627

111
index.php
View file

@ -1852,11 +1852,11 @@ RewriteRule ^.*$ /index.php [END]
if ($relative_uri == '.webdav/webdav.js') { if ($relative_uri == '.webdav/webdav.js') {
fseek($fp, 49805, SEEK_SET); fseek($fp, 49805, SEEK_SET);
echo fread($fp, 26310); echo fread($fp, 27579);
} }
else { else {
fseek($fp, 49805 + 26310, SEEK_SET); fseek($fp, 49805 + 27579, SEEK_SET);
echo fread($fp, 6760); echo fread($fp, 6801);
} }
fclose($fp); fclose($fp);
@ -1989,7 +1989,7 @@ const WebDAVNavigator = (url, options) => {
<input class="uploadfile" type="button" value="${_('Upload file')}" />`; <input class="uploadfile" type="button" value="${_('Upload file')}" />`;
const dir_row_tpl = `<tr data-permissions="%permissions%"><td class="thumb"><span class="icon dir"><b>%icon%</b></span></td><th colspan="2"><a href="%uri%">%name%</a></th><td>%modified%</td><td class="buttons"><div></div></td></tr>`; const dir_row_tpl = `<tr data-permissions="%permissions%"><td class="thumb"><span class="icon dir"><b>%icon%</b></span></td><th colspan="2"><a href="%uri%">%name%</a></th><td>%modified%</td><td class="buttons"><div></div></td></tr>`;
const file_row_tpl = `<tr data-permissions="%permissions%" data-mime="%mime%"><td class="thumb"><span class="icon %icon%"><b>%icon%</b></span></td><th><a href="%uri%">%name%</a></th><td class="size">%size%</td><td>%modified%</td><td class="buttons"><div><a href="%uri%" download class="btn">${_('Download')}</a></div></td></tr>`; const file_row_tpl = `<tr data-permissions="%permissions%" data-mime="%mime%" data-size="%size%"><td class="thumb"><span class="icon %icon%"><b>%icon%</b></span></td><th><a href="%uri%">%name%</a></th><td class="size">%size_bytes%</td><td>%modified%</td><td class="buttons"><div><a href="%uri%" download class="btn">${_('Download')}</a></div></td></tr>`;
const propfind_tpl = `<?xml version="1.0" encoding="UTF-8"?> const propfind_tpl = `<?xml version="1.0" encoding="UTF-8"?>
<D:propfind xmlns:D="DAV:" xmlns:oc="http://owncloud.org/ns"> <D:propfind xmlns:D="DAV:" xmlns:oc="http://owncloud.org/ns">
@ -2039,17 +2039,6 @@ const WebDAVNavigator = (url, options) => {
return false; return false;
}; };
const get_url = async (url) => {
if (temp_object_url) {
window.URL.revokeObjectURL(temp_object_url);
}
return req('GET', url).then(r => r.blob()).then(blob => {
temp_object_url = window.URL.createObjectURL(blob);
return temp_object_url;
});
}
const req = (method, url, body, headers) => { const req = (method, url, body, headers) => {
if (!headers) { if (!headers) {
headers = {}; headers = {};
@ -2062,6 +2051,51 @@ const WebDAVNavigator = (url, options) => {
return fetch(url, {method, body, headers}); return fetch(url, {method, body, headers});
}; };
const xhr = (method, url, progress_callback) => {
var xhr = new XMLHttpRequest();
current_xhr = xhr;
xhr.responseType = 'blob';
var p = new Promise((resolve, reject) => {
xhr.open(method, url);
xhr.onload = function () {
if (this.status >= 200 && this.status < 300) {
resolve(xhr.response);
} else {
reject({
status: this.status,
statusText: xhr.statusText
});
}
};
xhr.onerror = function () {
reject({
status: this.status,
statusText: xhr.statusText
});
};
xhr.onprogress = progress_callback;
xhr.send();
});
return p;
};
const get_url = async (url) => {
var progress = (e) => {
var p = $('progress');
if (!p) return;
p.value = e.loaded;
};
if (temp_object_url) {
window.URL.revokeObjectURL(temp_object_url);
}
return await xhr('GET', url, progress).then(blob => {
temp_object_url = window.URL.createObjectURL(blob);
return temp_object_url;
});
};
const wopi_init = async () => { const wopi_init = async () => {
if (!wopi_discovery_url) { if (!wopi_discovery_url) {
return; return;
@ -2163,6 +2197,17 @@ const WebDAVNavigator = (url, options) => {
}; };
const closeDialog = (e) => { const closeDialog = (e) => {
if (!$('body').classList.contains('dialog')) {
return;
}
if (current_xhr) {
current_xhr.abort();
current_xhr = null;
}
window.onbeforeunload = null;
$('body').classList.remove('dialog'); $('body').classList.remove('dialog');
if (!$('dialog')) return; if (!$('dialog')) return;
$('dialog').remove(); $('dialog').remove();
@ -2170,16 +2215,29 @@ const WebDAVNavigator = (url, options) => {
evt = null; evt = null;
}; };
const download = async (name, url) => { const download = async (name, size, url) => {
var url = await get_url(url); window.onbeforeunload = () => {
if (current_xhr) {
current_xhr.abort();
}
return true;
};
openDialog(`<h3>${html(name)}</h3><progress max="${size}"></progress>`, false);
await get_url(url);
const a = document.createElement('a'); const a = document.createElement('a');
a.style.display = 'none'; a.style.display = 'none';
a.href = url; a.href = temp_object_url;
a.download = name; a.download = name;
document.body.appendChild(a); document.body.appendChild(a);
a.click(); a.click();
window.URL.revokeObjectURL(url); window.URL.revokeObjectURL(temp_object_url);
a.remove(); a.remove();
closeDialog();
window.onbeforeunload = null;
}; };
const download_all = async () => { const download_all = async () => {
@ -2189,7 +2247,7 @@ const WebDAVNavigator = (url, options) => {
continue; continue;
} }
await download(item.name, item.uri) await download(item.name, item.size, item.uri)
} }
}; };
@ -2395,7 +2453,7 @@ const WebDAVNavigator = (url, options) => {
} }
var row = item.is_dir ? dir_row_tpl : file_row_tpl; var row = item.is_dir ? dir_row_tpl : file_row_tpl;
item.size = item.size !== null ? formatBytes(item.size).replace(/ /g, '&nbsp;') : null; item.size_bytes = item.size !== null ? formatBytes(item.size).replace(/ /g, '&nbsp;') : null;
item.icon = item.is_dir ? '&#x1F4C1;' : (item.uri.indexOf('.') > 0 ? item.uri.replace(/^.*\.(\w+)$/, '$1').toUpperCase() : ''); item.icon = item.is_dir ? '&#x1F4C1;' : (item.uri.indexOf('.') > 0 ? item.uri.replace(/^.*\.(\w+)$/, '$1').toUpperCase() : '');
item.modified = item.modified !== null ? formatDate(item.modified) : null; item.modified = item.modified !== null ? formatDate(item.modified) : null;
item.name = html(item.name); item.name = html(item.name);
@ -2478,6 +2536,7 @@ const WebDAVNavigator = (url, options) => {
var mime = !dir ? tr.getAttribute('data-mime') : 'dir'; var mime = !dir ? tr.getAttribute('data-mime') : 'dir';
var buttons = $$('td.buttons div'); var buttons = $$('td.buttons div');
var permissions = tr.getAttribute('data-permissions'); var permissions = tr.getAttribute('data-permissions');
var size = tr.getAttribute('data-size');
if (permissions == 'null') { if (permissions == 'null') {
permissions = null; permissions = null;
@ -2501,7 +2560,7 @@ const WebDAVNavigator = (url, options) => {
// This is to get around CORS when not on the same domain // This is to get around CORS when not on the same domain
if (user && password && (a = tr.querySelector('a[download]'))) { if (user && password && (a = tr.querySelector('a[download]'))) {
a.onclick = () => { a.onclick = () => {
download(file_name, url); download(file_name, size, url);
return false; return false;
}; };
} }
@ -2575,7 +2634,7 @@ const WebDAVNavigator = (url, options) => {
$$('a').onclick = () => { wopi_open(file_url, view_url); return false; }; $$('a').onclick = () => { wopi_open(file_url, view_url); return false; };
} }
else if (user && password && !dir) { else if (user && password && !dir) {
$$('a').onclick = () => { download(file_name, file_url); return false; }; $$('a').onclick = () => { download(file_name, size, file_url); return false; };
} }
else { else {
$$('a').download = file_name; $$('a').download = file_name;
@ -2631,6 +2690,7 @@ const WebDAVNavigator = (url, options) => {
}; };
var items = [[], []]; var items = [[], []];
var current_xhr = null;
var current_url = url; var current_url = url;
var base_url = url; var base_url = url;
const user = options.user || null; const user = options.user || null;
@ -3100,6 +3160,11 @@ dialog {
transition: all .3s; transition: all .3s;
} }
progress {
height: 2em;
width: 90%;
}
@keyframes spin { to { transform: rotate(360deg); } } @keyframes spin { to { transform: rotate(360deg); } }
@media screen and (max-width: 800px) { @media screen and (max-width: 800px) {