🗜️ New Zip UI + 🐜 fix bug in upload cancellation
This commit is contained in:
parent
ab95400163
commit
d9928e61c1
|
@ -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})),
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 ""
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue