🗜️ New Zip UI + 🐜 fix bug in upload cancellation

This commit is contained in:
Luc Didry 2019-07-31 23:28:37 +02:00
parent ab95400163
commit d9928e61c1
No known key found for this signature in database
GPG Key ID: EA868E12D0257E3C
6 changed files with 495 additions and 227 deletions

View File

@ -42,12 +42,36 @@ sub upload {
$c->app->log->debug('Got message');
if (defined($json->{cancel}) && $json->{cancel}) {
my $f = Lufi::DB::File->new(app => $c->app)->from_short($json->{id});
if ($f && $f->mod_token && $f->mod_token eq $json->{mod_token}) {
$f = $f->delete();
return $ws->send(to_json(
{
action => 'cancel',
success => $f->deleted ? true : false,
msg => $f->deleted ? 'Lufi::DB::File->delete() was successfull' : 'Lufi::DB::File->delete() failed',
i => $json->{i}
}
));
} else {
return $ws->send(to_json(
{
action => 'cancel',
success => false,
msg => 'Lufi::DB::File not found or invalid mod_token',
i => $json->{i}
}
));
}
}
my $stop = 0;
# Check if stop_upload file is present
if ($c->stop_upload) {
$stop = 1;
$c->send(decode('UTF-8', encode_json(
return $ws->send(decode('UTF-8', encode_json(
{
success => false,
msg => $c->l('Sorry, uploading is disabled.'),
@ -60,7 +84,7 @@ sub upload {
elsif (defined $c->config('max_file_size')) {
if ($json->{size} > $c->config('max_file_size')) {
$stop = 1;
$c->send(decode('UTF-8', encode_json(
return $ws->send(decode('UTF-8', encode_json(
{
success => false,
msg => $c->l('Your file is too big: %1 (maximum size allowed: %2)', format_bytes($json->{size}), format_bytes($c->config('max_file_size'))),
@ -73,7 +97,7 @@ sub upload {
# Check that we have enough space (multiplying by 2 since it's encrypted, it takes more place that the original file)
elsif ($json->{part} == 0 && ($json->{size} * 2) >= dfportable($c->config('upload_dir'))->{bavail}) {
$stop = 1;
$c->send(decode('UTF-8', encode_json(
return $ws->send(decode('UTF-8', encode_json(
{
success => false,
msg => $c->l('No enough space available on the server for this file (size: %1).', format_bytes($json->{size})),

View File

@ -131,7 +131,7 @@ sub new {
=over 1
=item B<Usage> : C<$c-E<gt>delet>
=item B<Usage> : C<$c-E<gt>delete>
=item B<Arguments> : none

View File

@ -78,7 +78,7 @@ msgstr ""
msgid "Click here to refresh the page and restart the download."
msgstr ""
#: themes/default/templates/index.html.ep:108
#: themes/default/templates/index.html.ep:119
msgid "Click to open the file browser"
msgstr ""
@ -90,6 +90,10 @@ msgstr ""
msgid "Comma-separated email addresses"
msgstr ""
#: themes/default/templates/index.html.ep:133
msgid "Compressing zip file…"
msgstr ""
#: themes/default/templates/partial/index.js.ep:14
msgid "Copy all links to clipboard"
msgstr ""
@ -98,15 +102,15 @@ msgstr ""
msgid "Copy to clipboard"
msgstr ""
#: lib/Lufi/Controller/Files.pm:461
#: lib/Lufi/Controller/Files.pm:485
msgid "Could not delete the file. You are not authenticated."
msgstr ""
#: lib/Lufi/Controller/Files.pm:443
#: lib/Lufi/Controller/Files.pm:467
msgid "Could not find the file. Are you sure of the URL and the token?"
msgstr ""
#: lib/Lufi/Controller/Files.pm:354
#: lib/Lufi/Controller/Files.pm:378
msgid "Could not find the file. Are you sure of the URL?"
msgstr ""
@ -150,7 +154,7 @@ msgstr ""
msgid "Drag and drop files in the appropriate area or use the traditional way to send files and the files will be chunked, encrypted and sent to the server. You will get two links per file: a download link, that you give to the people you want to share the file with and a deletion link, allowing you to delete the file whenever you want."
msgstr ""
#: themes/default/templates/index.html.ep:104
#: themes/default/templates/index.html.ep:115
msgid "Drop files here"
msgstr ""
@ -170,15 +174,15 @@ msgstr ""
msgid "Encrypting part XX1 of XX2"
msgstr ""
#: lib/Lufi/Controller/Files.pm:243
#: lib/Lufi/Controller/Files.pm:267
msgid "Error: the file existed but was deleted."
msgstr ""
#: lib/Lufi/Controller/Files.pm:323
#: lib/Lufi/Controller/Files.pm:347
msgid "Error: the file has not been sent entirely."
msgstr ""
#: lib/Lufi/Controller/Files.pm:333
#: lib/Lufi/Controller/Files.pm:357
msgid "Error: unable to find the file. Are you sure of your URL?"
msgstr ""
@ -194,7 +198,7 @@ msgstr ""
msgid "Export localStorage data"
msgstr ""
#: lib/Lufi/Controller/Files.pm:425
#: lib/Lufi/Controller/Files.pm:449
msgid "File deleted"
msgstr ""
@ -294,8 +298,12 @@ msgstr ""
msgid "My files"
msgstr ""
#: themes/default/templates/index.html.ep:106
msgid "Name of the zip file"
msgstr ""
#. (format_bytes($json->{size})
#: lib/Lufi/Controller/Files.pm:79
#: lib/Lufi/Controller/Files.pm:103
msgid "No enough space available on the server for this file (size: %1)."
msgstr ""
@ -373,7 +381,7 @@ msgstr ""
msgid "Sorry, the uploading is currently disabled. Please try again later."
msgstr ""
#: lib/Lufi/Controller/Files.pm:53
#: lib/Lufi/Controller/Files.pm:77
msgid "Sorry, uploading is disabled."
msgstr ""
@ -397,7 +405,7 @@ msgstr ""
msgid "The email subject can't be empty."
msgstr ""
#: lib/Lufi/Controller/Files.pm:422
#: lib/Lufi/Controller/Files.pm:446
msgid "The file has already been deleted"
msgstr ""
@ -422,11 +430,11 @@ msgstr ""
msgid "The original (and only for now) author is <a href=\"https://fiat-tux.fr\" class=\"classic\">Luc Didry</a>."
msgstr ""
#: lib/Lufi/Controller/Files.pm:190
#: lib/Lufi/Controller/Files.pm:214
msgid "The server was unable to find the file record to add your file part to. Please, contact the administrator."
msgstr ""
#: lib/Lufi/Controller/Files.pm:249
#: lib/Lufi/Controller/Files.pm:273
msgid "This file has been deactivated by the admins. Contact them to know why."
msgstr ""
@ -439,17 +447,17 @@ msgid "Unable to copy the link(s) to your clipboard"
msgstr ""
#. ($short)
#: lib/Lufi/Controller/Files.pm:393
#: lib/Lufi/Controller/Files.pm:417
msgid "Unable to get counter for %1. The file does not exists. It will be removed from your localStorage."
msgstr ""
#. ($short)
#: lib/Lufi/Controller/Files.pm:383
#: lib/Lufi/Controller/Files.pm:407
msgid "Unable to get counter for %1. The token is invalid."
msgstr ""
#. ($short)
#: lib/Lufi/Controller/Files.pm:403
#: lib/Lufi/Controller/Files.pm:427
msgid "Unable to get counter for %1. You are not authenticated."
msgstr ""
@ -457,11 +465,15 @@ msgstr ""
msgid "Upload files"
msgstr ""
#: themes/default/templates/index.html.ep:110
msgid "Upload generated zip file"
msgstr ""
#: themes/default/templates/files.html.ep:30
msgid "Uploaded at"
msgstr ""
#: themes/default/templates/index.html.ep:114
#: themes/default/templates/index.html.ep:142
msgid "Uploaded files"
msgstr ""
@ -514,18 +526,14 @@ msgid "Your browser has not enough entropy to generate a strong encryption key.
msgstr ""
#. (format_bytes($json->{size})
#: lib/Lufi/Controller/Files.pm:66
#: lib/Lufi/Controller/Files.pm:90
msgid "Your file is too big: %1 (maximum size allowed: %2)"
msgstr ""
#: lib/Lufi/Controller/Files.pm:305
#: lib/Lufi/Controller/Files.pm:329
msgid "Your password is not valid. Please refresh the page to retry."
msgstr ""
#: themes/default/templates/index.html.ep:112
msgid "Zip archive creation…"
msgstr ""
#. (format_bytes($keys[$i])
#: themes/default/templates/delays.html.ep:20
msgid "between %1 and %2, the file will be kept %3 day(s)."
@ -554,6 +562,6 @@ msgstr ""
msgid "no time limit"
msgstr ""
#: themes/default/templates/index.html.ep:106
#: themes/default/templates/index.html.ep:117
msgid "or"
msgstr ""

View File

@ -140,6 +140,69 @@ nav .btn-flat {
nav .btn-flat:focus {
background-color: rgba(0,0,0,0.1) !important;
}
/* pulse animation from Materialize CSS 1.0.0 */
button.pulse {
margin-left: 1em;
}
.pulse {
overflow: initial;
position: relative;
}
.pulse::before {
content: '';
display: block;
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
background-color: inherit;
border-radius: inherit;
-webkit-transition: opacity .3s, -webkit-transform .3s;
transition: opacity .3s, -webkit-transform .3s;
transition: opacity .3s, transform .3s;
transition: opacity .3s, transform .3s, -webkit-transform .3s;
-webkit-animation: pulse-animation 1s cubic-bezier(0.24, 0, 0.38, 1) infinite;
animation: pulse-animation 1s cubic-bezier(0.24, 0, 0.38, 1) infinite;
z-index: -1;
}
@-webkit-keyframes pulse-animation {
0% {
opacity: 1;
-webkit-transform: scale(1);
transform: scale(1);
}
50% {
opacity: 0;
-webkit-transform: scale(1.5);
transform: scale(1.5);
}
100% {
opacity: 0;
-webkit-transform: scale(1.5);
transform: scale(1.5);
}
}
@keyframes pulse-animation {
0% {
opacity: 1;
-webkit-transform: scale(1);
transform: scale(1);
}
50% {
opacity: 0;
-webkit-transform: scale(1.5);
transform: scale(1.5);
}
100% {
opacity: 0;
-webkit-transform: scale(1.5);
transform: scale(1.5);
}
}
.white-background {
background-color: #FFF;
}

View File

@ -1,10 +1,16 @@
// vim:set sw=4 ts=4 sts=4 ft=javascript expandtab:
// total file counter
window.fc = 0;
// Cancelled files indexes
window.cancelled = [];
// Set websocket
window.ws = spawnWebsocket(0, function() {return null;});
// Use slice of 2MB
window.sliceLength = 2000000;
// Global zip objects for currently created zip file
window.zip = null;
window.zipSize = 0;
// Copy a link to clipboard
function copyToClipboard(txt) {
@ -78,7 +84,7 @@ function destroyBlock(el) {
var l = $('#results li');
if (a.length === 0) {
$('#misc').empty();
if (l.length === 0) {
if (l.length === 0 && window.fileList === null) {
$('#results').hide();
}
} else {
@ -86,6 +92,86 @@ function destroyBlock(el) {
}
}
// When clicking on del at first view checkbox
function firstViewClicking() {
if ($('#first-view').attr('data-checked') && $('#first-view').attr('data-checked') === 'data-checked') {
$('#first-view').attr('data-checked', null);
} else {
$('#first-view').attr('data-checked', 'data-checked');
}
}
// When clicking on zip checkbox
function zipClicking () {
if ($('#zip-files').attr('data-checked') && $('#zip-files').attr('data-checked') === 'data-checked') {
window.zipSize = 0;
window.zip = null;
$('#zip-files').attr('data-checked', null);
$('#zipname').val('documents.zip');
$('#zipname-input').addClass('hide');
$('#zipping').addClass('hide');
$('#zip-parts').html('');
$('#delete-day').attr('disabled', null);
$('#first-view').attr('disabled', null);
} else {
$('#zip-files').attr('data-checked', 'data-checked');
$('#zipname-input').removeClass('hide');
$('#zip-size').text(filesize(window.zipSize));
}
}
// Get the zip file name
function getZipname() {
var zipname = $('#zipname').val();
if (zipname === '') {
zipname = 'documents.zip';
}
if (!zipname.endsWith('.zip')) {
if (zipname.endsWith('.')) {
zipname += 'zip';
} else {
zipname += '.zip';
}
}
return zipname;
}
// Update the zip name
function updateZipname() {
$('#zip-name').text(getZipname());
}
// Create blob from zip
function uploadZip(e) {
e.preventDefault();
var delay = $('#delete-day');
var del_at_first_view = $('#first-view');
$('#zip-files').attr('disabled', 'disabled');
$('#zip-compressing').removeClass('hide');
window.zip.generateAsync({type:"blob"})
.then(function(zipFile) {
// if $('#zipping') is hidden, the zipping has been aborted
if (!$('#zipping').hasClass('hide')) {
$('#zipping').addClass('hide');
$('#zipname-input').addClass('hide');
$('#zip-compressing').addClass('hide');
$('#results').show();
var zipname = getZipname();
var file = new File([zipFile], zipname, {type: 'application/zip'});
if (window.fileList === undefined || window.fileList === null) {
window.fileList = [file];
uploadFile(0, delay.val(), del_at_first_view.is(':checked'));
} else {
window.fileList.push(file);
}
}
});
}
// Update the mail link
function updateMailLink() {
var a = $('.link-input');
@ -105,29 +191,33 @@ function handleFiles(f) {
var del_at_first_view = $('#first-view');
delay.attr('disabled', 'disabled');
zip_files.attr('disabled', 'disabled');
del_at_first_view.attr('disabled', 'disabled');
if (zip_files.is(':checked')) {
var zip = new JSZip();
$('#zipping').show();
for (var i = 0; i < f.length; i++) {
var element = f.item(i);
zip.file(element.name, element);
if (window.zip === null) {
window.zip = new JSZip();
}
zip.generateAsync({type:"blob"})
.then(function(zipFile) {
$('#zipping').hide();
$('#results').show();
var file = new File([zipFile], 'documents.zip', {type: 'application/zip'});
$('#zipping').removeClass('hide');
for (var i = 0; i < f.length; i++) {
var element = f.item(i);
var filename = element.name;
var origname = filename;
var counter = 0;
while (typeof(window.zip.files[filename]) !== 'undefined') {
counter += 1;
filename = origname.substring(0, origname.lastIndexOf('.')) + '_(' + counter + ')' + origname.substring(origname.lastIndexOf('.'));
}
if (window.fileList === undefined || window.fileList === null) {
window.fileList = [file];
uploadFile(0, delay.val(), del_at_first_view.is(':checked'));
} else {
window.fileList.push(file);
}
});
window.zip.file(filename, element);
window.zipSize += element.size;
$('#zip-size').text(filesize(window.zipSize));
$('#zip-parts').append([
'<li>',
'— ', filename, ' (', filesize(element.size), ')',
'</li>'
].join(''));
}
} else {
if (window.fileList === undefined || window.fileList === null) {
window.fileList = Array.prototype.slice.call(f);
@ -183,198 +273,256 @@ function uploadFile(i, delay, del_at_first_view) {
r.prepend(w);
$('#destroy-'+window.fc).on('click', function(event) {
event.preventDefault();
destroyBlock(this)
window.cancelled.push(i);
destroyBlock(this);
});
sliceAndUpload(randomkey, i, parts, 0, delay, del_at_first_view, null);
sliceAndUpload(randomkey, i, parts, 0, delay, del_at_first_view, null, null);
}
// Get a slice of file and send it
function sliceAndUpload(randomkey, i, parts, j, delay, del_at_first_view, short) {
var file = window.fileList[i];
var slice = file.slice(j * window.sliceLength, (j + 1) * window.sliceLength, file.type);
var fr = new FileReader();
fr.onloadend = function() {
var sl = $('#parts-'+window.fc);
// Get the binary result, different result in IE browsers (see default.html.ep line 27:48)
if (isIE == true){
var bin = fr.content;
} else {
var bin = fr.result;
}
// Transform it in base64
var b = window.btoa(bin);
// Encrypt it
sl.html(i18n.encrypting.replace(/XX1(.*)XX2/, (j+1)+'$1'+parts));
var encrypted = sjcl.encrypt(randomkey, b);
// Prepare json
var data = {
// number of parts
total: parts,
// part X of total
part: j,
size: file.size,
name: file.name,
type: file.type,
delay: delay,
del_at_first_view: del_at_first_view,
zipped: $('#zip-files').is(':checked'),
function sliceAndUpload(randomkey, i, parts, j, delay, del_at_first_view, short, mod_token) {
if (mod_token !== null && window.cancelled.includes(i)) {
var data = JSON.stringify({
id: short,
// number of the sent file in the queue
mod_token: mod_token,
cancel: true,
i: i
};
if ($('#file_pwd').length === 1) {
var pwd = $('#file_pwd').val();
if (pwd !== undefined && pwd !== null && pwd !== '') {
data['file_pwd'] = $('#file_pwd').val();
}
}
data = JSON.stringify(data);
console.log('sending slice '+(j + 1)+'/'+parts+' of file '+file.name);
sl.html(i18n.sending.replace(/XX1(.*)XX2/, (j+1)+'$1'+parts));
})+'XXMOJOXXuseless';
// Verify that we have a websocket and send json
if (window.ws.readyState === 3) {
window.ws = spawnWebsocket(0, function() {
window.ws.send(data+'XXMOJOXX'+JSON.stringify(encrypted));
window.ws.send(data);
});
} else {
window.ws.onclose = function() {
console.log('Websocket closed, waiting 10sec.');
window.ws = spawnWebsocket(0, function() {
console.log('sending again slice '+(j + 1)+'/'+parts+' of file '+file.name);
window.ws.send(data+'XXMOJOXX'+JSON.stringify(encrypted));
});
window.ws = spawnWebsocket(0, function() {return null;});
};
window.ws.onerror = function() {
console.log('Error on Websocket, waiting 10sec.');
window.ws = spawnWebsocket(0, function() {
console.log('sending again slice '+(j + 1)+'/'+parts+' of file '+file.name);
window.ws.send(data+'XXMOJOXX'+JSON.stringify(encrypted));
});
window.ws = spawnWebsocket(0, function() {return null;});
};
window.ws.send(data+'XXMOJOXX'+JSON.stringify(encrypted));
window.ws.send(data);
}
} else {
var file = window.fileList[i];
var slice = file.slice(j * window.sliceLength, (j + 1) * window.sliceLength, file.type);
var fr = new FileReader();
fr.onloadend = function() {
var sl = $('#parts-'+window.fc);
// Get the binary result, different result in IE browsers (see default.html.ep line 27:48)
if (isIE == true){
var bin = fr.content;
} else {
var bin = fr.result;
}
// Transform it in base64
var b = window.btoa(bin);
// Encrypt it
sl.html(i18n.encrypting.replace(/XX1(.*)XX2/, (j+1)+'$1'+parts));
var encrypted = sjcl.encrypt(randomkey, b);
// Prepare json
var data = {
// number of parts
total: parts,
// part X of total
part: j,
size: file.size,
name: file.name,
type: file.type,
delay: delay,
del_at_first_view: del_at_first_view,
zipped: $('#zip-files').is(':checked'),
id: short,
// number of the sent file in the queue
i: i
};
if ($('#file_pwd').length === 1) {
var pwd = $('#file_pwd').val();
if (pwd !== undefined && pwd !== null && pwd !== '') {
data['file_pwd'] = $('#file_pwd').val();
}
}
data = JSON.stringify(data)+'XXMOJOXX'+JSON.stringify(encrypted);;
console.log('sending slice '+(j + 1)+'/'+parts+' of file '+file.name);
sl.html(i18n.sending.replace(/XX1(.*)XX2/, (j+1)+'$1'+parts));
// Verify that we have a websocket and send json
if (window.ws.readyState === 3) {
window.ws = spawnWebsocket(0, function() {
window.ws.send(data);
});
} else {
window.ws.onclose = function() {
console.log('Websocket closed, waiting 10sec.');
window.ws = spawnWebsocket(0, function() {
console.log('sending again slice '+(j + 1)+'/'+parts+' of file '+file.name);
window.ws.send(data);
});
};
window.ws.onerror = function() {
console.log('Error on Websocket, waiting 10sec.');
window.ws = spawnWebsocket(0, function() {
console.log('sending again slice '+(j + 1)+'/'+parts+' of file '+file.name);
window.ws.send(data);
});
};
window.ws.send(data);
}
}
fr.readAsBinaryString(slice);
}
fr.readAsBinaryString(slice);
}
// Update the progress bar
function updateProgressBar(data) {
var i = data.i;
var sent_delay = data.sent_delay;
var del_at_first_view = data.del_at_first_view;
if (data.success) {
var j = data.j;
var delay = data.delay;
var parts = data.parts;
var short = data.short;
var created_at = data.created_at;
console.log('getting response for slice '+(j + 1)+'/'+parts+' of file '+data.name+' ('+data.duration+' sec)');
var dp = $('#progress-'+window.fc);
var key = dp.attr('data-key');
if (j + 1 === parts) {
//
window.ws.onclose = function() {
console.log('Connection is closed.');
};
window.ws.onerror = function() {
console.log('Error on WebSocket connection but file has been fully send, so we don\'t care.');
}
$('#parts-'+window.fc).remove();
var n = $('#name-'+window.fc);
var s = $('#size-'+window.fc);
var d = $('<div>');
var url = baseURL+'r/'+short+'#'+key;
var del_url = actionURL+'d/'+short+'/'+data.token;
var links = encodeURIComponent('["'+short+'"]');
var limit = (delay === 0) ? i18n.noLimit : i18n.expiration+' '+moment.unix(delay * 86400 + created_at).locale(window.navigator.language).format('LLLL');
n.html(n.html()+' '+s.html()+' <a href="'+actionURL+'m?links='+links+'"><i class="mdi-communication-email"></i></a><br>'+limit);
d.html(['<div class="card-action">',
'<div class="input-field">',
'<span class="prefix big-prefix">',
'<a href="', url, '" target="_blank">',
'<i class="mdi-file-file-download small" title="', i18n.dlText, '"></i>',
'</a>',
'<a href="#" id="copyurl-', window.fc, '" title="', i18n.cpText, '">',
'<i class="mdi-content-content-copy small"></i>',
'</a>',
'</span>',
'<input id="', short, '" class="form-control link-input white-background" value="', url, '" readonly="" type="text">',
'<label class="active" for="', short, '">', i18n.dlText, '</label>',
'</div>',
'<div class="input-field">',
'<a href="', del_url, '" target="_blank" class="prefix big-prefix">',
'<i class="mdi-action-delete small" title="', i18n.delText, '"></i>',
'</a>',
'<input id="delete-', short, '" class="form-control white-background" value="', del_url, '" readonly="" type="text">',
'<label class="active" for="delete-', short, '">', i18n.delText, '</label>',
'</div>',
'</div>'].join(''));
s.remove();
var p2 = dp.parent();
var p1 = p2.parent();
p2.remove();
p1.append(d);
$('#copyurl-'+window.fc).on('click', function(e) {
e.preventDefault();
copyToClipboard(url);
});
$("input[type='text']").on("click", function () {
$(this).select();
});
// Add copy all and mailto buttons
var misc = $('#misc');
if (misc.html() === '') {
misc.html('<a href="#" id="copyall" class="btn btn-info">'+i18n.copyAll+'</a> <a id="mailto" href="'+actionURL+'m?links='+links+'" class="btn btn-info">'+i18n.mailTo+'</a>');
$('#copyall').on('click', copyAllToClipboard);
} else {
updateMailLink();
}
// Add the file to localStorage
addItem(data.name, url, data.size, del_at_first_view, created_at, delay, data.short, data.token);
// Upload next file
window.fc++;
i++;
if (i < window.fileList.length) {
uploadFile(i, sent_delay, del_at_first_view);
} else {
// We have finished
window.fileList = null;
window.onbeforeunload = null;
$('#zip-files').attr('disabled', null);
$('#delete-day').attr('disabled', null);
$('#first-view').attr('disabled', null);
}
if (typeof(data.action) !== 'undefined' && data.action === 'cancel') {
if (data.success) {
console.log('Upload successfully cancelled');
} else {
j++;
// Update progress bar
var percent = Math.round(100 * j/parts);
dp.removeClass();
dp.addClass('determinate');
dp.addClass('width-'+percent);
dp.attr('aria-valuenow', percent);
console.log('Upload cancellation failed: ' + data.msg);
}
// Remove the cancelled index
window.cancelled.splice(window.cancelled.indexOf(window.fc), 1);
// Upload next file
window.fc++;
data.i++;
if (data.i < window.fileList.length) {
uploadFile(data.i, $('#delete-day').val(), $('#first-view').is(':checked'));
} else {
// We have finished
window.cancelled = [];
window.fileList = null;
window.onbeforeunload = null;
$('#delete-day').attr('disabled', null);
$('#first-view').attr('disabled', null);
if ($('#zip-files').is(':checked')) {
$('label[for="zip-files"]').click();
}
// Encrypt and upload next slice
sliceAndUpload(key, i, parts, j, delay, del_at_first_view, short);
}
} else {
addAlertOnFile(data.msg, i, delay, del_at_first_view);
var i = data.i;
var sent_delay = data.sent_delay;
var del_at_first_view = data.del_at_first_view;
if (data.success) {
var j = data.j;
var delay = data.delay;
var parts = data.parts;
var short = data.short;
var created_at = data.created_at;
console.log('getting response for slice '+(j + 1)+'/'+parts+' of file '+data.name+' ('+data.duration+' sec)');
var dp = $('#progress-'+window.fc);
var key = dp.attr('data-key');
if (j + 1 === parts) {
//
window.ws.onclose = function() {
console.log('Connection is closed.');
};
window.ws.onerror = function() {
console.log('Error on WebSocket connection but file has been fully send, so we don\'t care.');
}
$('#parts-'+window.fc).remove();
var n = $('#name-'+window.fc);
var s = $('#size-'+window.fc);
var d = $('<div>');
var url = baseURL+'r/'+short+'#'+key;
var del_url = actionURL+'d/'+short+'/'+data.token;
var links = encodeURIComponent('["'+short+'"]');
var limit = (delay === 0) ? i18n.noLimit : i18n.expiration+' '+moment.unix(delay * 86400 + created_at).locale(window.navigator.language).format('LLLL');
n.html(n.html()+' '+s.html()+' <a href="'+actionURL+'m?links='+links+'"><i class="mdi-communication-email"></i></a><br>'+limit);
d.html(['<div class="card-action">',
'<div class="input-field">',
'<span class="prefix big-prefix">',
'<a href="', url, '" target="_blank">',
'<i class="mdi-file-file-download small" title="', i18n.dlText, '"></i>',
'</a>',
'<a href="#" id="copyurl-', window.fc, '" title="', i18n.cpText, '">',
'<i class="mdi-content-content-copy small"></i>',
'</a>',
'</span>',
'<input id="', short, '" class="form-control link-input white-background" value="', url, '" readonly="" type="text">',
'<label class="active" for="', short, '">', i18n.dlText, '</label>',
'</div>',
'<div class="input-field">',
'<a href="', del_url, '" target="_blank" class="prefix big-prefix">',
'<i class="mdi-action-delete small" title="', i18n.delText, '"></i>',
'</a>',
'<input id="delete-', short, '" class="form-control white-background" value="', del_url, '" readonly="" type="text">',
'<label class="active" for="delete-', short, '">', i18n.delText, '</label>',
'</div>',
'</div>'].join(''));
s.remove();
var p2 = dp.parent();
var p1 = p2.parent();
p2.remove();
p1.append(d);
$('#copyurl-'+window.fc).on('click', function(e) {
e.preventDefault();
copyToClipboard(url);
});
$("input[type='text']").on("click", function () {
$(this).select();
});
// Add copy all and mailto buttons
var misc = $('#misc');
if (misc.html() === '') {
misc.html('<a href="#" id="copyall" class="btn btn-info">'+i18n.copyAll+'</a> <a id="mailto" href="'+actionURL+'m?links='+links+'" class="btn btn-info">'+i18n.mailTo+'</a>');
$('#copyall').on('click', copyAllToClipboard);
} else {
updateMailLink();
}
// Add the file to localStorage
addItem(data.name, url, data.size, del_at_first_view, created_at, delay, data.short, data.token);
// Upload next file
window.fc++;
i++;
if (i < window.fileList.length) {
uploadFile(i, sent_delay, del_at_first_view);
} else {
// We have finished
window.fileList = null;
window.onbeforeunload = null;
$('#delete-day').attr('disabled', null);
$('#first-view').attr('disabled', null);
if ($('#zip-files').is(':checked')) {
$('label[for="zip-files"]').click();
}
}
} else {
j++;
// Update progress bar
var percent = Math.round(100 * j/parts);
dp.removeClass();
dp.addClass('determinate');
dp.addClass('width-'+percent);
dp.attr('aria-valuenow', percent);
// Encrypt and upload next slice
sliceAndUpload(key, i, parts, j, delay, del_at_first_view, short, data.token);
}
} else {
addAlertOnFile(data.msg, i, delay, del_at_first_view);
}
}
}
@ -463,7 +611,10 @@ function bindDropZone() {
}
// When it's ready
$(document).ready(function(){
$(document).ready(function() {
$('#zip-files').prop('checked', false);
$('#first-view').prop('checked', false);
$('#zipname').val('documents.zip');
if (!sjcl.random.isReady(10)) {
var loop = setInterval(function() {
if (!sjcl.random.isReady(10)) {
@ -480,18 +631,12 @@ $(document).ready(function(){
if (maxSize > 0) {
$('#max-file-size').text(i18n.maxSize.replace('XXX', filesize(maxSize)));
}
$('label[for="first-view"]').on('click', function(){
if ($('#first-view').attr('data-checked') && $('#first-view').attr('data-checked') === 'data-checked') {
$('#first-view').attr('data-checked', null);
} else {
$('#first-view').attr('data-checked', 'data-checked');
}
});
$('label[for="zip-files"]').on('click', function(){
if ($('#zip-files').attr('data-checked') && $('#zip-files').attr('data-checked') === 'data-checked') {
$('#zip-files').attr('data-checked', null);
} else {
$('#zip-files').attr('data-checked', 'data-checked');
}
$('label[for="first-view"]').on('click', firstViewClicking);
$('label[for="zip-files"]').on('click', zipClicking);
$('#zipname').on('input', updateZipname);
$('#uploadZip').on('click', uploadZip);
$('#reset-zipping').on('click', function() {
window.zip = null;
$('label[for="zip-files"]').click();
});
});

View File

@ -99,6 +99,17 @@
</div>
</div>
% }
<div class="col s12 m12 hide" id="zipname-input">
<div class="col s12 m6">
<div class="input-field">
<input type="text" id="zipname" placeholder="documents.zip" value="documents.zip" class="validate">
<label for="zipname"><%= l('Name of the zip file') %></label>
</div>
</div>
<div class="col s12 m6 text-left input-field">
<a href="#" id="uploadZip" class="btn waves-effect waves-light"><%= l('Upload generated zip file') %></a>
</div>
</div>
</form>
<div id="files">
<h2><%= l('Drop files here') %></h2>
@ -109,7 +120,24 @@
<input type="file" id="file-browser-button" multiple disabled>
</label>
</div>
<p id="zipping" class="hiddendiv"><%= l('Zip archive creation…') %></p>
<div id="zipping" class="hide">
<div class="card">
<div>
<a href="#" id="reset-zipping">
<i class="right mdi-navigation-close small"></i>
</a>
<div class="card-content">
<span class="card-title" id="zip-name">documents.zip</span> (<span id="zip-size"></span>)
<p id="zip-compressing" class="hide">
<button class="btn-floating pulse"><i class="mdi-content-archive"></i></button>
<%= l('Compressing zip file…') %>
</p>
<ul id="zip-parts">
</ul>
</div>
</div>
</div>
</div>
<div id="results">
<h2><%= l('Uploaded files') %></h2>
<div id="misc"></div>