MeshMessenger with file transfers.
Ylian Saint-Hilaire committed
Dec 17, 2018 at 15:08 UTC
85acf14a259753578374520d685552e46caa5d22
2 files changed
+45
-17
package.json
+1
-1
@@ -1,6 +1,6 @@
1
{
2
"name": "meshcentral",
3
- "version": "0.2.4-s",
3
+ "version": "0.2.4-t",
4
"keywords": [
5
"Remote Management",
6
"Intel AMT",
public/messenger.htm
+44
-16
@@ -8,6 +8,7 @@
8
<link type="text/css" href="styles/style.css" media="screen" rel="stylesheet" title="CSS" />
9
<link type="text/css" href="styles/messenger.css" media="screen" rel="stylesheet" title="CSS" />
10
<script type="text/javascript" src="scripts/common-0.0.1.js"></script>
11
+ <script type="text/javascript" src="scripts/filesaver.1.1.20151003.js"></script>
12
</head>
13
<body style="font-family:Arial,Helvetica,sans-serif">
14
<div id="xtop" style="position:absolute;left:0;right:0;top:0;height:38px;background-color:#036;color:#c8c8c8;box-shadow:3px 3px 10px gray">
@@ -36,7 +37,7 @@
37
<div style="position:absolute;right:0;left:0;top:2.5px;text-align:center">Local</div>
38
<video id="localVideoCanvas" autoplay muted style="position:absolute;top:20px;left:0;width:100%;height:calc(100% - 30px);background-color:black"></video>
39
</div>
39
- <input id="uploadFileInput" type="file" style="display:none">
40
+ <input id="uploadFileInput" type="file" multiple style="display:none">
41
<script type="text/javascript">
42
var userInputFocus = 0;
43
var args = parseUriArgs();
@@ -86,7 +87,7 @@
87
}
88
89
function onUserInputFocus(x) { userInputFocus = x; }
89
- function displayClear() { QH('xmsg', ''); }
90
+ function displayClear() { QH('xmsg', ''); cancelAllFileTransfers(); fileUploads = [], fileDownloads = {}; }
91
92
// Display a control message
93
function displayControl(msg) {
@@ -301,32 +302,47 @@
302
chooser.click();
303
}
304
305
+ // User selected one or more files to upload to remote user.
306
function fileSelect() {
307
if (state != 2) return;
308
var x = Q('uploadFileInput');
307
- if (x.files.length != 1) return;
308
- var reader = new FileReader();
309
- reader.onload = function (e) { this.xfile.data = e.target.result; startFileUpload(this.xfile); };
310
- reader.xfile = x.files[0];
311
- reader.readAsBinaryString(x.files[0]);
309
+ if (x.files.length > 10) {
310
+ displayControl('Limit of 10 file uploads at the same time.');
311
+ } else {
312
+ for (var i = 0; i < x.files.length; i++) {
313
+ if (x.files[i].size > 0) {
314
+ var reader = new FileReader();
315
+ reader.onload = function (e) { this.xfile.data = e.target.result; startFileUpload(this.xfile); };
316
+ reader.xfile = x.files[i];
317
+ reader.readAsBinaryString(x.files[i]);
318
+ }
319
+ }
320
+ }
321
}
322
323
+ // User drag & droped one or more files to upload to remote user.
324
function fileDrop(e) {
325
haltEvent(e);
316
- if (state != 2) return;
317
- if (e.dataTransfer == null || e.dataTransfer.files.length != 1) return;
318
- var reader = new FileReader();
319
- reader.onload = function (e) { this.xfile.data = e.target.result; startFileUpload(this.xfile); };
320
- reader.xfile = e.dataTransfer.files[0];
321
- reader.readAsBinaryString(e.dataTransfer.files[0]);
326
+ if ((state != 2) || (e.dataTransfer == null)) return;
327
+ if (e.dataTransfer.files.length > 10) {
328
+ displayControl('Limit of 10 file uploads at the same time.');
329
+ } else {
330
+ for (var i = 0; i < e.dataTransfer.files.length; i++) {
331
+ if (e.dataTransfer.files[i].size > 0) {
332
+ var reader = new FileReader();
333
+ reader.onload = function (e) { this.xfile.data = e.target.result; startFileUpload(this.xfile); };
334
+ reader.xfile = e.dataTransfer.files[i];
335
+ reader.readAsBinaryString(e.dataTransfer.files[i]);
336
+ }
337
+ }
338
+ }
339
}
340
341
function startFileUpload(file) {
342
if (state != 2) return;
343
file.id = Math.random();
344
fileUploads.push(file);
328
- //console.log('XXX', file);
329
- QA('xmsg', '<div style="clear:both"></div><div id="FILEUP-' + file.id + '" class="localBubble" style="width:240px;cursor:pointer" onclick="cancelFileTransfer(\'' + file.id + '\')"><div id="FILEUP-ICON-' + file.id + '" class="fileicon" style="float:left;width:32px;height:32px"></div><div><div id="FILEUP-NAME-' + file.id + '" style="height:16px;overflow:hidden">' + file.name + '</div><div style="width:200px;background-color:lightgray;margin-left:32px;border-radius:3px;margin-top:3px;height:11px"><div id="FILEUP-PROGRESS-' + file.id + '" style="width:0px;background-color:green;border-radius:3px;height:11px"> </div></div></div></div>');
345
+ QA('xmsg', '<div style="clear:both"></div><div id="FILEUP-' + file.id + '" class="localBubble" style="width:240px;cursor:pointer" onclick="cancelFileTransfer(\'' + file.id + '\')"><div id="FILEUP-ICON-' + file.id + '" class="fileicon" style="float:left;width:32px;height:32px"></div><div><div id="FILEUP-NAME-' + file.id + '" style="height:16px;overflow:hidden;white-space:nowrap;" title="' + file.name + '">' + file.name + '</div><div style="width:200px;background-color:lightgray;margin-left:32px;border-radius:3px;margin-top:3px;height:11px"><div id="FILEUP-PROGRESS-' + file.id + '" style="width:0px;background-color:green;border-radius:3px;height:11px"> </div></div></div></div>');
346
Q('xmsg').scrollTop = Q('xmsg').scrollHeight;
347
send({ action: 'file', size: file.size, id: file.id, type: file.type, name: file.name });
348
if (currentFileUpload == null) continueFileUpload();
@@ -335,7 +351,7 @@
351
function startFileDownload(file) {
352
if (state != 2) return;
353
fileDownloads[file.id] = file;
338
- QA('xmsg', '<div style="clear:both"></div><div id="FILEUP-' + file.id + '" class="remoteBubble" style="width:240px;cursor:pointer"><div id="FILEUP-ICON-' + file.id + '" class="fileicon" style="float:left;width:32px;height:32px"></div><div><div id="FILEUP-NAME-' + file.id + '" style="height:16px;overflow:hidden">' + file.name + '</div><div style="width:200px;background-color:lightgray;margin-left:32px;border-radius:3px;margin-top:3px;height:11px"><div id="FILEUP-PROGRESS-' + file.id + '" style="width:0px;background-color:green;border-radius:3px;height:11px"> </div></div></div></div>');
354
+ QA('xmsg', '<div style="clear:both"></div><div id="FILEUP-' + file.id + '" class="remoteBubble" style="width:240px;cursor:pointer" onclick="saveFileTransfer(\'' + file.id + '\')"><div id="FILEUP-ICON-' + file.id + '" class="fileicon" style="float:left;width:32px;height:32px"></div><div><div id="FILEUP-NAME-' + file.id + '" style="height:16px;overflow:hidden;white-space:nowrap;" title="' + file.name + '">' + file.name + '</div><div style="width:200px;background-color:lightgray;margin-left:32px;border-radius:3px;margin-top:3px;height:11px"><div id="FILEUP-PROGRESS-' + file.id + '" style="width:0px;background-color:green;border-radius:3px;height:11px"> </div></div></div></div>');
355
Q('xmsg').scrollTop = Q('xmsg').scrollHeight;
356
}
357
@@ -352,6 +368,18 @@
368
if (progressColor) { QS('FILEUP-PROGRESS-' + id)['background-color'] = progressColor; }
369
}
370
371
+ // Convert a string into a blob
372
+ data2blob = function (data) {
373
+ var bytes = new Array(data.length);
374
+ for (var i = 0; i < data.length; i++) bytes[i] = data.charCodeAt(i);
375
+ return new Blob([new Uint8Array(bytes)]);
376
+ };
377
+
378
+ function saveFileTransfer(id) {
379
+ var f = fileDownloads[id];
380
+ if (f && f.done == 1) { saveAs(data2blob(f.data), f.name); }
381
+ }
382
+
383
function cancelFileTransfer(id) {
384
if ((currentFileUpload != null) && (currentFileUpload.id == id)) { currentFileUpload = null; }
385
if ((currentFileDownload != null) && (currentFileDownload.id == id)) { currentFileDownload = null; }