Clean old code
parent
be848c1bec
commit
354c63bd64
@ -1,54 +0,0 @@
|
|||||||
define([
|
|
||||||
'jquery',
|
|
||||||
'/customize/application_config.js',
|
|
||||||
'/common/cryptpad-common.js',
|
|
||||||
'/api/config',
|
|
||||||
], function ($, Config, Cryptpad, ApiConfig) {
|
|
||||||
|
|
||||||
window.APP = {
|
|
||||||
Cryptpad: Cryptpad,
|
|
||||||
};
|
|
||||||
|
|
||||||
var Messages = Cryptpad.Messages;
|
|
||||||
|
|
||||||
$(function () {
|
|
||||||
// Language selector
|
|
||||||
var $sel = $('#language-selector');
|
|
||||||
Cryptpad.createLanguageSelector(undefined, $sel);
|
|
||||||
$sel.find('button').addClass('btn').addClass('btn-secondary');
|
|
||||||
$sel.show();
|
|
||||||
|
|
||||||
var $upgrade = $('#upgrade');
|
|
||||||
|
|
||||||
var showUpgrade = function (text, feedback, url) {
|
|
||||||
if (ApiConfig.removeDonateButton) { return; }
|
|
||||||
if (localStorage.plan) { return; }
|
|
||||||
if (!text) { return; }
|
|
||||||
$upgrade.text(text).show();
|
|
||||||
$upgrade.click(function () {
|
|
||||||
Cryptpad.feedback(feedback);
|
|
||||||
window.open(url,'_blank');
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// User admin menu
|
|
||||||
var $userMenu = $('#user-menu');
|
|
||||||
var userMenuCfg = {
|
|
||||||
$initBlock: $userMenu,
|
|
||||||
'static': true
|
|
||||||
};
|
|
||||||
var $userAdmin = Cryptpad.createUserAdminMenu(userMenuCfg);
|
|
||||||
$userAdmin.find('button').addClass('btn').addClass('btn-secondary');
|
|
||||||
|
|
||||||
$(window).click(function () {
|
|
||||||
$('.cp-dropdown-content').hide();
|
|
||||||
});
|
|
||||||
|
|
||||||
if (Cryptpad.isLoggedIn() && ApiConfig.allowSubscriptions) {
|
|
||||||
showUpgrade(Messages.upgradeAccount, "HOME_UPGRADE_ACCOUNT", Cryptpad.upgradeURL);
|
|
||||||
} else {
|
|
||||||
showUpgrade(Messages.supportCryptpad, "HOME_SUPPORT_CRYPTPAD", Cryptpad.donateURL);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
@ -1,308 +0,0 @@
|
|||||||
define([
|
|
||||||
'jquery',
|
|
||||||
'/common/modes.js',
|
|
||||||
'/common/themes.js',
|
|
||||||
|
|
||||||
'/bower_components/file-saver/FileSaver.min.js'
|
|
||||||
], function ($, Modes, Themes) {
|
|
||||||
var saveAs = window.saveAs;
|
|
||||||
var module = {};
|
|
||||||
|
|
||||||
module.create = function (ifrw, Cryptpad, defaultMode, CMeditor) {
|
|
||||||
var exp = {};
|
|
||||||
var Messages = Cryptpad.Messages;
|
|
||||||
|
|
||||||
var CodeMirror = exp.CodeMirror = CMeditor;
|
|
||||||
CodeMirror.modeURL = "cm/mode/%N/%N";
|
|
||||||
|
|
||||||
var $pad = $('#pad-iframe');
|
|
||||||
var $textarea = exp.$textarea = $('#editor1');
|
|
||||||
if (!$textarea.length) { $textarea = exp.$textarea = $pad.contents().find('#editor1'); }
|
|
||||||
|
|
||||||
var Title;
|
|
||||||
var onLocal = function () {};
|
|
||||||
var $rightside;
|
|
||||||
var $drawer;
|
|
||||||
exp.init = function (local, title, toolbar) {
|
|
||||||
if (typeof local === "function") {
|
|
||||||
onLocal = local;
|
|
||||||
}
|
|
||||||
Title = title;
|
|
||||||
$rightside = toolbar.$rightside;
|
|
||||||
$drawer = toolbar.$drawer;
|
|
||||||
};
|
|
||||||
|
|
||||||
var editor = exp.editor = CMeditor.fromTextArea($textarea[0], {
|
|
||||||
lineNumbers: true,
|
|
||||||
lineWrapping: true,
|
|
||||||
autoCloseBrackets: true,
|
|
||||||
matchBrackets : true,
|
|
||||||
showTrailingSpace : true,
|
|
||||||
styleActiveLine : true,
|
|
||||||
search: true,
|
|
||||||
highlightSelectionMatches: {showToken: /\w+/},
|
|
||||||
extraKeys: {"Shift-Ctrl-R": undefined},
|
|
||||||
foldGutter: true,
|
|
||||||
gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"],
|
|
||||||
mode: defaultMode || "javascript",
|
|
||||||
readOnly: true
|
|
||||||
});
|
|
||||||
editor.setValue(Messages.codeInitialState);
|
|
||||||
|
|
||||||
var setMode = exp.setMode = function (mode, cb) {
|
|
||||||
exp.highlightMode = mode;
|
|
||||||
if (mode !== "text") {
|
|
||||||
CMeditor.autoLoadMode(editor, mode);
|
|
||||||
}
|
|
||||||
editor.setOption('mode', mode);
|
|
||||||
if (exp.$language) {
|
|
||||||
var name = exp.$language.find('a[data-value="' + mode + '"]').text() || undefined;
|
|
||||||
name = name ? Messages.languageButton + ' ('+name+')' : Messages.languageButton;
|
|
||||||
exp.$language.setValue(mode, name);
|
|
||||||
}
|
|
||||||
if(cb) { cb(mode); }
|
|
||||||
};
|
|
||||||
|
|
||||||
var setTheme = exp.setTheme = (function () {
|
|
||||||
var path = '/common/theme/';
|
|
||||||
|
|
||||||
var $head = $(ifrw.document.head);
|
|
||||||
|
|
||||||
var themeLoaded = exp.themeLoaded = function (theme) {
|
|
||||||
return $head.find('link[href*="'+theme+'"]').length;
|
|
||||||
};
|
|
||||||
|
|
||||||
var loadTheme = exp.loadTheme = function (theme) {
|
|
||||||
$head.append($('<link />', {
|
|
||||||
rel: 'stylesheet',
|
|
||||||
href: path + theme + '.css',
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
||||||
return function (theme, $select) {
|
|
||||||
if (!theme) {
|
|
||||||
editor.setOption('theme', 'default');
|
|
||||||
} else {
|
|
||||||
if (!themeLoaded(theme)) {
|
|
||||||
loadTheme(theme);
|
|
||||||
}
|
|
||||||
editor.setOption('theme', theme);
|
|
||||||
}
|
|
||||||
if ($select) {
|
|
||||||
var name = theme || undefined;
|
|
||||||
name = name ? Messages.themeButton + ' ('+theme+')' : Messages.themeButton;
|
|
||||||
$select.setValue(theme, name);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}());
|
|
||||||
|
|
||||||
exp.getHeadingText = function () {
|
|
||||||
var lines = editor.getValue().split(/\n/);
|
|
||||||
|
|
||||||
var text = '';
|
|
||||||
lines.some(function (line) {
|
|
||||||
// lines including a c-style comment are also valuable
|
|
||||||
var clike = /^\s*(\/\*|\/\/)(.*)?(\*\/)*$/;
|
|
||||||
if (clike.test(line)) {
|
|
||||||
line.replace(clike, function (a, one, two) {
|
|
||||||
if (!(two && two.replace)) { return; }
|
|
||||||
text = two.replace(/\*\/\s*$/, '').trim();
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// lisps?
|
|
||||||
var lispy = /^\s*(;|#\|)+(.*?)$/;
|
|
||||||
if (lispy.test(line)) {
|
|
||||||
line.replace(lispy, function (a, one, two) {
|
|
||||||
text = two;
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// lines beginning with a hash are potentially valuable
|
|
||||||
// works for markdown, python, bash, etc.
|
|
||||||
var hash = /^#+(.*?)$/;
|
|
||||||
if (hash.test(line)) {
|
|
||||||
line.replace(hash, function (a, one) {
|
|
||||||
text = one;
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO make one more pass for multiline comments
|
|
||||||
});
|
|
||||||
|
|
||||||
return text.trim();
|
|
||||||
};
|
|
||||||
|
|
||||||
exp.configureLanguage = function (cb, onModeChanged) {
|
|
||||||
var options = [];
|
|
||||||
Modes.list.forEach(function (l) {
|
|
||||||
options.push({
|
|
||||||
tag: 'a',
|
|
||||||
attributes: {
|
|
||||||
'data-value': l.mode,
|
|
||||||
'href': '#',
|
|
||||||
},
|
|
||||||
content: l.language // Pretty name of the language value
|
|
||||||
});
|
|
||||||
});
|
|
||||||
var dropdownConfig = {
|
|
||||||
text: 'Mode', // Button initial text
|
|
||||||
options: options, // Entries displayed in the menu
|
|
||||||
left: true, // Open to the left of the button
|
|
||||||
isSelect: true,
|
|
||||||
feedback: 'CODE_LANGUAGE',
|
|
||||||
};
|
|
||||||
var $block = exp.$language = Cryptpad.createDropdown(dropdownConfig);
|
|
||||||
$block.find('button').attr('title', Messages.languageButtonTitle);
|
|
||||||
$block.find('a').click(function () {
|
|
||||||
setMode($(this).attr('data-value'), onModeChanged);
|
|
||||||
onLocal();
|
|
||||||
});
|
|
||||||
|
|
||||||
if ($drawer) { $drawer.append($block); }
|
|
||||||
if (cb) { cb(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
exp.configureTheme = function (cb) {
|
|
||||||
/* Remember the user's last choice of theme using localStorage */
|
|
||||||
var themeKey = 'CRYPTPAD_CODE_THEME';
|
|
||||||
var lastTheme = localStorage.getItem(themeKey) || 'default';
|
|
||||||
|
|
||||||
var options = [];
|
|
||||||
Themes.forEach(function (l) {
|
|
||||||
options.push({
|
|
||||||
tag: 'a',
|
|
||||||
attributes: {
|
|
||||||
'data-value': l.name,
|
|
||||||
'href': '#',
|
|
||||||
},
|
|
||||||
content: l.name // Pretty name of the language value
|
|
||||||
});
|
|
||||||
});
|
|
||||||
var dropdownConfig = {
|
|
||||||
text: 'Theme', // Button initial text
|
|
||||||
options: options, // Entries displayed in the menu
|
|
||||||
left: true, // Open to the left of the button
|
|
||||||
isSelect: true,
|
|
||||||
initialValue: lastTheme,
|
|
||||||
feedback: 'CODE_THEME',
|
|
||||||
};
|
|
||||||
var $block = exp.$theme = Cryptpad.createDropdown(dropdownConfig);
|
|
||||||
$block.find('button').attr('title', Messages.themeButtonTitle);
|
|
||||||
|
|
||||||
setTheme(lastTheme, $block);
|
|
||||||
|
|
||||||
$block.find('a').click(function () {
|
|
||||||
var theme = $(this).attr('data-value');
|
|
||||||
setTheme(theme, $block);
|
|
||||||
localStorage.setItem(themeKey, theme);
|
|
||||||
});
|
|
||||||
|
|
||||||
if ($drawer) { $drawer.append($block); }
|
|
||||||
if (cb) { cb(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
exp.exportText = function () {
|
|
||||||
var text = editor.getValue();
|
|
||||||
|
|
||||||
var ext = Modes.extensionOf(exp.highlightMode);
|
|
||||||
|
|
||||||
var title = Cryptpad.fixFileName(Title ? Title.suggestTitle('cryptpad') : "?") + (ext || '.txt');
|
|
||||||
|
|
||||||
Cryptpad.prompt(Messages.exportPrompt, title, function (filename) {
|
|
||||||
if (filename === null) { return; }
|
|
||||||
var blob = new Blob([text], {
|
|
||||||
type: 'text/plain;charset=utf-8'
|
|
||||||
});
|
|
||||||
saveAs(blob, filename);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
exp.importText = function (content, file) {
|
|
||||||
var $bar = ifrw.$('#cme_toolbox');
|
|
||||||
var mode;
|
|
||||||
var mime = CodeMirror.findModeByMIME(file.type);
|
|
||||||
|
|
||||||
if (!mime) {
|
|
||||||
var ext = /.+\.([^.]+)$/.exec(file.name);
|
|
||||||
if (ext[1]) {
|
|
||||||
mode = CMeditor.findModeByExtension(ext[1]);
|
|
||||||
mode = mode && mode.mode || null;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mode = mime && mime.mode || null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mode && Modes.list.some(function (o) { return o.mode === mode; })) {
|
|
||||||
setMode(mode);
|
|
||||||
$bar.find('#language-mode').val(mode);
|
|
||||||
} else {
|
|
||||||
console.log("Couldn't find a suitable highlighting mode: %s", mode);
|
|
||||||
setMode('text');
|
|
||||||
$bar.find('#language-mode').val('text');
|
|
||||||
}
|
|
||||||
|
|
||||||
editor.setValue(content);
|
|
||||||
onLocal();
|
|
||||||
};
|
|
||||||
|
|
||||||
var cursorToPos = function(cursor, oldText) {
|
|
||||||
var cLine = cursor.line;
|
|
||||||
var cCh = cursor.ch;
|
|
||||||
var pos = 0;
|
|
||||||
var textLines = oldText.split("\n");
|
|
||||||
for (var line = 0; line <= cLine; line++) {
|
|
||||||
if(line < cLine) {
|
|
||||||
pos += textLines[line].length+1;
|
|
||||||
}
|
|
||||||
else if(line === cLine) {
|
|
||||||
pos += cCh;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return pos;
|
|
||||||
};
|
|
||||||
|
|
||||||
var posToCursor = function(position, newText) {
|
|
||||||
var cursor = {
|
|
||||||
line: 0,
|
|
||||||
ch: 0
|
|
||||||
};
|
|
||||||
var textLines = newText.substr(0, position).split("\n");
|
|
||||||
cursor.line = textLines.length - 1;
|
|
||||||
cursor.ch = textLines[cursor.line].length;
|
|
||||||
return cursor;
|
|
||||||
};
|
|
||||||
|
|
||||||
exp.setValueAndCursor = function (oldDoc, remoteDoc, TextPatcher) {
|
|
||||||
var scroll = editor.getScrollInfo();
|
|
||||||
//get old cursor here
|
|
||||||
var oldCursor = {};
|
|
||||||
oldCursor.selectionStart = cursorToPos(editor.getCursor('from'), oldDoc);
|
|
||||||
oldCursor.selectionEnd = cursorToPos(editor.getCursor('to'), oldDoc);
|
|
||||||
|
|
||||||
editor.setValue(remoteDoc);
|
|
||||||
editor.save();
|
|
||||||
|
|
||||||
var op = TextPatcher.diff(oldDoc, remoteDoc);
|
|
||||||
var selects = ['selectionStart', 'selectionEnd'].map(function (attr) {
|
|
||||||
return TextPatcher.transformCursor(oldCursor[attr], op);
|
|
||||||
});
|
|
||||||
|
|
||||||
if(selects[0] === selects[1]) {
|
|
||||||
editor.setCursor(posToCursor(selects[0], remoteDoc));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
editor.setSelection(posToCursor(selects[0], remoteDoc), posToCursor(selects[1], remoteDoc));
|
|
||||||
}
|
|
||||||
|
|
||||||
editor.scrollTo(scroll.left, scroll.top);
|
|
||||||
};
|
|
||||||
|
|
||||||
return exp;
|
|
||||||
};
|
|
||||||
|
|
||||||
return module;
|
|
||||||
});
|
|
||||||
|
|
@ -1,366 +0,0 @@
|
|||||||
define([
|
|
||||||
'jquery',
|
|
||||||
'/file/file-crypto.js',
|
|
||||||
'/common/common-thumbnail.js',
|
|
||||||
'/bower_components/tweetnacl/nacl-fast.min.js',
|
|
||||||
], function ($, FileCrypto, Thumb) {
|
|
||||||
var Nacl = window.nacl;
|
|
||||||
var module = {};
|
|
||||||
|
|
||||||
var blobToArrayBuffer = module.blobToArrayBuffer = function (blob, cb) {
|
|
||||||
var reader = new FileReader();
|
|
||||||
reader.onloadend = function () {
|
|
||||||
cb(void 0, this.result);
|
|
||||||
};
|
|
||||||
reader.readAsArrayBuffer(blob);
|
|
||||||
};
|
|
||||||
|
|
||||||
var arrayBufferToString = function (AB) {
|
|
||||||
try {
|
|
||||||
return Nacl.util.encodeBase64(new Uint8Array(AB));
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.upload = function (file, noStore, common, updateProgress, onComplete, onError, onPending) {
|
|
||||||
var u8 = file.blob; // This is not a blob but a uint8array
|
|
||||||
var metadata = file.metadata;
|
|
||||||
|
|
||||||
// if it exists, path contains the new pad location in the drive
|
|
||||||
var path = file.path;
|
|
||||||
|
|
||||||
var key = Nacl.randomBytes(32);
|
|
||||||
var next = FileCrypto.encrypt(u8, metadata, key);
|
|
||||||
|
|
||||||
var estimate = FileCrypto.computeEncryptedSize(u8.length, metadata);
|
|
||||||
|
|
||||||
var sendChunk = function (box, cb) {
|
|
||||||
var enc = Nacl.util.encodeBase64(box);
|
|
||||||
common.rpc.send.unauthenticated('UPLOAD', enc, function (e, msg) {
|
|
||||||
cb(e, msg);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var actual = 0;
|
|
||||||
var again = function (err, box) {
|
|
||||||
if (err) { throw new Error(err); }
|
|
||||||
if (box) {
|
|
||||||
actual += box.length;
|
|
||||||
var progressValue = (actual / estimate * 100);
|
|
||||||
updateProgress(progressValue);
|
|
||||||
|
|
||||||
return void sendChunk(box, function (e) {
|
|
||||||
if (e) { return console.error(e); }
|
|
||||||
next(again);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (actual !== estimate) {
|
|
||||||
console.error('Estimated size does not match actual size');
|
|
||||||
}
|
|
||||||
|
|
||||||
// if not box then done
|
|
||||||
common.uploadComplete(function (e, id) {
|
|
||||||
if (e) { return void console.error(e); }
|
|
||||||
var uri = ['', 'blob', id.slice(0,2), id].join('/');
|
|
||||||
console.log("encrypted blob is now available as %s", uri);
|
|
||||||
|
|
||||||
var b64Key = Nacl.util.encodeBase64(key);
|
|
||||||
|
|
||||||
var hash = common.getFileHashFromKeys(id, b64Key);
|
|
||||||
var href = '/file/#' + hash;
|
|
||||||
|
|
||||||
var title = metadata.name;
|
|
||||||
|
|
||||||
if (noStore) { return void onComplete(href); }
|
|
||||||
|
|
||||||
common.initialPath = path;
|
|
||||||
common.renamePad(title || "", href, function (err) {
|
|
||||||
if (err) { return void console.error(err); }
|
|
||||||
onComplete(href);
|
|
||||||
common.setPadAttribute('fileType', metadata.type, null, href);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
common.uploadStatus(estimate, function (e, pending) {
|
|
||||||
if (e) {
|
|
||||||
console.error(e);
|
|
||||||
onError(e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pending) {
|
|
||||||
return void onPending(function () {
|
|
||||||
// if the user wants to cancel the pending upload to execute that one
|
|
||||||
common.uploadCancel(function (e, res) {
|
|
||||||
if (e) {
|
|
||||||
return void console.error(e);
|
|
||||||
}
|
|
||||||
console.log(res);
|
|
||||||
next(again);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
next(again);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
module.create = function (common, config) {
|
|
||||||
var File = {};
|
|
||||||
|
|
||||||
var Messages = common.Messages;
|
|
||||||
|
|
||||||
var queue = File.queue = {
|
|
||||||
queue: [],
|
|
||||||
inProgress: false
|
|
||||||
};
|
|
||||||
|
|
||||||
var uid = function () {
|
|
||||||
return 'file-' + String(Math.random()).substring(2);
|
|
||||||
};
|
|
||||||
|
|
||||||
var $table = File.$table = $('<table>', { id: 'uploadStatus' });
|
|
||||||
var $thead = $('<tr>').appendTo($table);
|
|
||||||
$('<td>').text(Messages.upload_name).appendTo($thead);
|
|
||||||
$('<td>').text(Messages.upload_size).appendTo($thead);
|
|
||||||
$('<td>').text(Messages.upload_progress).appendTo($thead);
|
|
||||||
$('<td>').text(Messages.cancel).appendTo($thead);
|
|
||||||
|
|
||||||
var createTableContainer = function ($body) {
|
|
||||||
File.$container = $('<div>', { id: 'uploadStatusContainer' }).append($table).appendTo($body);
|
|
||||||
return File.$container;
|
|
||||||
};
|
|
||||||
|
|
||||||
var getData = function (file, href) {
|
|
||||||
var data = {};
|
|
||||||
|
|
||||||
data.name = file.metadata.name;
|
|
||||||
data.url = href;
|
|
||||||
if (file.metadata.type.slice(0,6) === 'image/') {
|
|
||||||
data.mediatag = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
|
||||||
};
|
|
||||||
|
|
||||||
var upload = function (file) {
|
|
||||||
var blob = file.blob; // This is not a blob but an array buffer
|
|
||||||
var u8 = new Uint8Array(blob);
|
|
||||||
var metadata = file.metadata;
|
|
||||||
var id = file.id;
|
|
||||||
if (queue.inProgress) { return; }
|
|
||||||
queue.inProgress = true;
|
|
||||||
|
|
||||||
var $row = $table.find('tr[id="'+id+'"]');
|
|
||||||
|
|
||||||
$row.find('.upCancel').html('-');
|
|
||||||
var $pv = $row.find('.progressValue');
|
|
||||||
var $pb = $row.find('.progressContainer');
|
|
||||||
var $pc = $row.find('.upProgress');
|
|
||||||
var $link = $row.find('.upLink');
|
|
||||||
|
|
||||||
var updateProgress = function (progressValue) {
|
|
||||||
$pv.text(Math.round(progressValue*100)/100 + '%');
|
|
||||||
$pb.css({
|
|
||||||
width: (progressValue/100)*$pc.width()+'px'
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var onComplete = function (href) {
|
|
||||||
$link.attr('href', href)
|
|
||||||
.click(function (e) {
|
|
||||||
e.preventDefault();
|
|
||||||
window.open($link.attr('href'), '_blank');
|
|
||||||
});
|
|
||||||
var title = metadata.name;
|
|
||||||
common.log(Messages._getKey('upload_success', [title]));
|
|
||||||
common.prepareFeedback('upload')();
|
|
||||||
|
|
||||||
if (config.onUploaded) {
|
|
||||||
var data = getData(file, href);
|
|
||||||
config.onUploaded(file.dropEvent, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
queue.inProgress = false;
|
|
||||||
queue.next();
|
|
||||||
};
|
|
||||||
|
|
||||||
var onError = function (e) {
|
|
||||||
queue.inProgress = false;
|
|
||||||
queue.next();
|
|
||||||
if (e === 'TOO_LARGE') {
|
|
||||||
// TODO update table to say too big?
|
|
||||||
return void common.alert(Messages.upload_tooLarge);
|
|
||||||
}
|
|
||||||
if (e === 'NOT_ENOUGH_SPACE') {
|
|
||||||
// TODO update table to say not enough space?
|
|
||||||
return void common.alert(Messages.upload_notEnoughSpace);
|
|
||||||
}
|
|
||||||
console.error(e);
|
|
||||||
return void common.alert(Messages.upload_serverError);
|
|
||||||
};
|
|
||||||
|
|
||||||
var onPending = function (cb) {
|
|
||||||
common.confirm(Messages.upload_uploadPending, function (yes) {
|
|
||||||
if (!yes) { return; }
|
|
||||||
cb();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
file.blob = u8;
|
|
||||||
module.upload(file, config.noStore, common, updateProgress, onComplete, onError, onPending);
|
|
||||||
};
|
|
||||||
|
|
||||||
var prettySize = function (bytes) {
|
|
||||||
var kB = common.bytesToKilobytes(bytes);
|
|
||||||
if (kB < 1024) { return kB + Messages.KB; }
|
|
||||||
var mB = common.bytesToMegabytes(bytes);
|
|
||||||
return mB + Messages.MB;
|
|
||||||
};
|
|
||||||
|
|
||||||
queue.next = function () {
|
|
||||||
if (queue.queue.length === 0) {
|
|
||||||
queue.to = window.setTimeout(function () {
|
|
||||||
if (config.keepTable) { return; }
|
|
||||||
File.$container.fadeOut();
|
|
||||||
}, 3000);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (queue.inProgress) { return; }
|
|
||||||
File.$container.show();
|
|
||||||
var file = queue.queue.shift();
|
|
||||||
upload(file);
|
|
||||||
};
|
|
||||||
queue.push = function (obj) {
|
|
||||||
var id = uid();
|
|
||||||
obj.id = id;
|
|
||||||
queue.queue.push(obj);
|
|
||||||
|
|
||||||
$table.show();
|
|
||||||
var estimate = FileCrypto.computeEncryptedSize(obj.blob.byteLength, obj.metadata);
|
|
||||||
|
|
||||||
var $progressBar = $('<div>', {'class':'progressContainer'});
|
|
||||||
var $progressValue = $('<span>', {'class':'progressValue'}).text(Messages.upload_pending);
|
|
||||||
|
|
||||||
var $tr = $('<tr>', {id: id}).appendTo($table);
|
|
||||||
|
|
||||||
var $cancel = $('<span>', {'class': 'cancel fa fa-times'}).click(function () {
|
|
||||||
queue.queue = queue.queue.filter(function (el) { return el.id !== id; });
|
|
||||||
$cancel.remove();
|
|
||||||
$tr.find('.upCancel').text('-');
|
|
||||||
$tr.find('.progressValue').text(Messages.upload_cancelled);
|
|
||||||
});
|
|
||||||
|
|
||||||
var $link = $('<a>', {
|
|
||||||
'class': 'upLink',
|
|
||||||
'rel': 'noopener noreferrer'
|
|
||||||
}).text(obj.metadata.name);
|
|
||||||
|
|
||||||
$('<td>').append($link).appendTo($tr);
|
|
||||||
$('<td>').text(prettySize(estimate)).appendTo($tr);
|
|
||||||
$('<td>', {'class': 'upProgress'}).append($progressBar).append($progressValue).appendTo($tr);
|
|
||||||
$('<td>', {'class': 'upCancel'}).append($cancel).appendTo($tr);
|
|
||||||
|
|
||||||
queue.next();
|
|
||||||
};
|
|
||||||
|
|
||||||
var handleFile = File.handleFile = function (file, e, thumbnail) {
|
|
||||||
var thumb;
|
|
||||||
var file_arraybuffer;
|
|
||||||
var finish = function () {
|
|
||||||
var metadata = {
|
|
||||||
name: file.name,
|
|
||||||
type: file.type,
|
|
||||||
};
|
|
||||||
if (thumb) { metadata.thumbnail = thumb; }
|
|
||||||
queue.push({
|
|
||||||
blob: file_arraybuffer,
|
|
||||||
metadata: metadata,
|
|
||||||
dropEvent: e
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
blobToArrayBuffer(file, function (e, buffer) {
|
|
||||||
if (e) { console.error(e); }
|
|
||||||
file_arraybuffer = buffer;
|
|
||||||
if (thumbnail) { // there is already a thumbnail
|
|
||||||
return blobToArrayBuffer(thumbnail, function (e, buffer) {
|
|
||||||
if (e) { console.error(e); }
|
|
||||||
thumb = arrayBufferToString(buffer);
|
|
||||||
finish();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Thumb.isSupportedType(file.type)) { return finish(); }
|
|
||||||
// make a resized thumbnail from the image..
|
|
||||||
Thumb.fromBlob(file, function (e, thumb64) {
|
|
||||||
if (e) { console.error(e); }
|
|
||||||
if (!thumb64) { return finish(); }
|
|
||||||
thumb = thumb64;
|
|
||||||
finish();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var onFileDrop = File.onFileDrop = function (file, e) {
|
|
||||||
if (!common.isLoggedIn()) {
|
|
||||||
return common.alert(common.Messages.upload_mustLogin);
|
|
||||||
}
|
|
||||||
|
|
||||||
Array.prototype.slice.call(file).forEach(function (d) {
|
|
||||||
handleFile(d, e);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var createAreaHandlers = File.createDropArea = function ($area, $hoverArea) {
|
|
||||||
var counter = 0;
|
|
||||||
if (!$hoverArea) { $hoverArea = $area; }
|
|
||||||
if (!$area) { return; }
|
|
||||||
$hoverArea
|
|
||||||
.on('dragenter', function (e) {
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
counter++;
|
|
||||||
$hoverArea.addClass('hovering');
|
|
||||||
})
|
|
||||||
.on('dragleave', function (e) {
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
counter--;
|
|
||||||
if (counter <= 0) {
|
|
||||||
$hoverArea.removeClass('hovering');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$area
|
|
||||||
.on('drag dragstart dragend dragover drop dragenter dragleave', function (e) {
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
})
|
|
||||||
.on('drop', function (e) {
|
|
||||||
e.stopPropagation();
|
|
||||||
|
|
||||||
var dropped = e.originalEvent.dataTransfer.files;
|
|
||||||
counter = 0;
|
|
||||||
$hoverArea.removeClass('hovering');
|
|
||||||
onFileDrop(dropped, e);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var createUploader = function ($area, $hover, $body) {
|
|
||||||
if (!config.noHandlers) {
|
|
||||||
createAreaHandlers($area, null);
|
|
||||||
}
|
|
||||||
createTableContainer($body);
|
|
||||||
};
|
|
||||||
|
|
||||||
createUploader(config.dropArea, config.hoverArea, config.body);
|
|
||||||
|
|
||||||
return File;
|
|
||||||
};
|
|
||||||
|
|
||||||
return module;
|
|
||||||
});
|
|
@ -1,268 +0,0 @@
|
|||||||
define([
|
|
||||||
'jquery',
|
|
||||||
'/bower_components/chainpad-json-validator/json-ot.js',
|
|
||||||
'/bower_components/chainpad-crypto/crypto.js',
|
|
||||||
'/bower_components/chainpad/chainpad.dist.js',
|
|
||||||
], function ($, JsonOT, Crypto) {
|
|
||||||
var ChainPad = window.ChainPad;
|
|
||||||
var History = {};
|
|
||||||
|
|
||||||
var getStates = function (rt) {
|
|
||||||
var states = [];
|
|
||||||
var b = rt.getAuthBlock();
|
|
||||||
if (b) { states.unshift(b); }
|
|
||||||
while (b.getParent()) {
|
|
||||||
b = b.getParent();
|
|
||||||
states.unshift(b);
|
|
||||||
}
|
|
||||||
return states;
|
|
||||||
};
|
|
||||||
|
|
||||||
var loadHistory = function (config, common, cb) {
|
|
||||||
var network = common.getNetwork();
|
|
||||||
var hkn = network.historyKeeper;
|
|
||||||
|
|
||||||
var wcId = common.hrefToHexChannelId(config.href || window.location.href);
|
|
||||||
|
|
||||||
var createRealtime = function () {
|
|
||||||
return ChainPad.create({
|
|
||||||
userName: 'history',
|
|
||||||
initialState: '',
|
|
||||||
transformFunction: JsonOT.validate,
|
|
||||||
logLevel: 0,
|
|
||||||
noPrune: true
|
|
||||||
});
|
|
||||||
};
|
|
||||||
var realtime = createRealtime();
|
|
||||||
|
|
||||||
var parsed = config.href ? common.parsePadUrl(config.href) : {};
|
|
||||||
var secret = common.getSecrets(parsed.type, parsed.hash);
|
|
||||||
|
|
||||||
History.readOnly = 0;
|
|
||||||
if (!secret.keys) {
|
|
||||||
secret.keys = secret.key;
|
|
||||||
History.readOnly = 0;
|
|
||||||
}
|
|
||||||
else if (!secret.keys.validateKey) {
|
|
||||||
History.readOnly = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
var crypto = Crypto.createEncryptor(secret.keys);
|
|
||||||
|
|
||||||
var to = window.setTimeout(function () {
|
|
||||||
cb('[GET_FULL_HISTORY_TIMEOUT]');
|
|
||||||
}, 30000);
|
|
||||||
|
|
||||||
var parse = function (msg) {
|
|
||||||
try {
|
|
||||||
return JSON.parse(msg);
|
|
||||||
} catch (e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
var onMsg = function (msg) {
|
|
||||||
var parsed = parse(msg);
|
|
||||||
if (parsed[0] === 'FULL_HISTORY_END') {
|
|
||||||
console.log('END');
|
|
||||||
window.clearTimeout(to);
|
|
||||||
cb(null, realtime);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (parsed[0] !== 'FULL_HISTORY') { return; }
|
|
||||||
if (parsed[1] && parsed[1].validateKey) { // First message
|
|
||||||
secret.keys.validateKey = parsed[1].validateKey;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
msg = parsed[1][4];
|
|
||||||
if (msg) {
|
|
||||||
msg = msg.replace(/^cp\|/, '');
|
|
||||||
var decryptedMsg = crypto.decrypt(msg, secret.keys.validateKey);
|
|
||||||
realtime.message(decryptedMsg);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
network.on('message', function (msg) {
|
|
||||||
onMsg(msg);
|
|
||||||
});
|
|
||||||
|
|
||||||
network.sendto(hkn, JSON.stringify(['GET_FULL_HISTORY', wcId, secret.keys.validateKey]));
|
|
||||||
};
|
|
||||||
|
|
||||||
History.create = function (common, config) {
|
|
||||||
if (!config.$toolbar) { return void console.error("config.$toolbar is undefined");}
|
|
||||||
if (History.loading) { return void console.error("History is already being loaded..."); }
|
|
||||||
History.loading = true;
|
|
||||||
var $toolbar = config.$toolbar;
|
|
||||||
|
|
||||||
if (!config.applyVal || !config.setHistory || !config.onLocal || !config.onRemote) {
|
|
||||||
throw new Error("Missing config element: applyVal, onLocal, onRemote, setHistory");
|
|
||||||
}
|
|
||||||
|
|
||||||
// config.setHistory(bool, bool)
|
|
||||||
// - bool1: history value
|
|
||||||
// - bool2: reset old content?
|
|
||||||
var render = function (val) {
|
|
||||||
if (typeof val === "undefined") { return; }
|
|
||||||
try {
|
|
||||||
config.applyVal(val);
|
|
||||||
} catch (e) {
|
|
||||||
// Probably a parse error
|
|
||||||
console.error(e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
var onClose = function () { config.setHistory(false, true); };
|
|
||||||
var onRevert = function () {
|
|
||||||
config.setHistory(false, false);
|
|
||||||
config.onLocal();
|
|
||||||
config.onRemote();
|
|
||||||
};
|
|
||||||
var onReady = function () {
|
|
||||||
config.setHistory(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
var Messages = common.Messages;
|
|
||||||
|
|
||||||
var realtime;
|
|
||||||
|
|
||||||
var states = [];
|
|
||||||
var c = states.length - 1;
|
|
||||||
|
|
||||||
var $hist = $toolbar.find('.cryptpad-toolbar-history');
|
|
||||||
var $left = $toolbar.find('.cryptpad-toolbar-leftside');
|
|
||||||
var $right = $toolbar.find('.cryptpad-toolbar-rightside');
|
|
||||||
var $cke = $toolbar.find('.cke_toolbox_main');
|
|
||||||
|
|
||||||
$hist.html('').show();
|
|
||||||
$left.hide();
|
|
||||||
$right.hide();
|
|
||||||
$cke.hide();
|
|
||||||
|
|
||||||
common.spinner($hist).get().show();
|
|
||||||
|
|
||||||
var onUpdate;
|
|
||||||
|
|
||||||
var update = function () {
|
|
||||||
if (!realtime) { return []; }
|
|
||||||
states = getStates(realtime);
|
|
||||||
if (typeof onUpdate === "function") { onUpdate(); }
|
|
||||||
return states;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get the content of the selected version, and change the version number
|
|
||||||
var get = function (i) {
|
|
||||||
i = parseInt(i);
|
|
||||||
if (isNaN(i)) { return; }
|
|
||||||
if (i < 0) { i = 0; }
|
|
||||||
if (i > states.length - 1) { i = states.length - 1; }
|
|
||||||
var val = states[i].getContent().doc;
|
|
||||||
c = i;
|
|
||||||
if (typeof onUpdate === "function") { onUpdate(); }
|
|
||||||
$hist.find('.next, .previous').css('visibility', '');
|
|
||||||
if (c === states.length - 1) { $hist.find('.next').css('visibility', 'hidden'); }
|
|
||||||
if (c === 0) { $hist.find('.previous').css('visibility', 'hidden'); }
|
|
||||||
return val || '';
|
|
||||||
};
|
|
||||||
|
|
||||||
var getNext = function (step) {
|
|
||||||
return typeof step === "number" ? get(c + step) : get(c + 1);
|
|
||||||
};
|
|
||||||
var getPrevious = function (step) {
|
|
||||||
return typeof step === "number" ? get(c - step) : get(c - 1);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Create the history toolbar
|
|
||||||
var display = function () {
|
|
||||||
$hist.html('');
|
|
||||||
var $prev =$('<button>', {
|
|
||||||
'class': 'previous fa fa-step-backward buttonPrimary',
|
|
||||||
title: Messages.history_prev
|
|
||||||
}).appendTo($hist);
|
|
||||||
var $nav = $('<div>', {'class': 'goto'}).appendTo($hist);
|
|
||||||
var $next = $('<button>', {
|
|
||||||
'class': 'next fa fa-step-forward buttonPrimary',
|
|
||||||
title: Messages.history_next
|
|
||||||
}).appendTo($hist);
|
|
||||||
|
|
||||||
$('<label>').text(Messages.history_version).appendTo($nav);
|
|
||||||
var $cur = $('<input>', {
|
|
||||||
'class' : 'gotoInput',
|
|
||||||
'type' : 'number',
|
|
||||||
'min' : '1',
|
|
||||||
'max' : states.length
|
|
||||||
}).val(c + 1).appendTo($nav).mousedown(function (e) {
|
|
||||||
// stopPropagation because the event would be cancelled by the dropdown menus
|
|
||||||
e.stopPropagation();
|
|
||||||
});
|
|
||||||
var $label2 = $('<label>').text(' / '+ states.length).appendTo($nav);
|
|
||||||
$('<br>').appendTo($nav);
|
|
||||||
var $close = $('<button>', {
|
|
||||||
'class':'closeHistory',
|
|
||||||
title: Messages.history_closeTitle
|
|
||||||
}).text(Messages.history_closeTitle).appendTo($nav);
|
|
||||||
var $rev = $('<button>', {
|
|
||||||
'class':'revertHistory buttonSuccess',
|
|
||||||
title: Messages.history_restoreTitle
|
|
||||||
}).text(Messages.history_restore).appendTo($nav);
|
|
||||||
if (History.readOnly) { $rev.hide(); }
|
|
||||||
|
|
||||||
onUpdate = function () {
|
|
||||||
$cur.attr('max', states.length);
|
|
||||||
$cur.val(c+1);
|
|
||||||
$label2.text(' / ' + states.length);
|
|
||||||
};
|
|
||||||
|
|
||||||
var close = function () {
|
|
||||||
$hist.hide();
|
|
||||||
$left.show();
|
|
||||||
$right.show();
|
|
||||||
$cke.show();
|
|
||||||
};
|
|
||||||
|
|
||||||
// Buttons actions
|
|
||||||
$prev.click(function () { render(getPrevious()); });
|
|
||||||
$next.click(function () { render(getNext()); });
|
|
||||||
$cur.keydown(function (e) {
|
|
||||||
var p = function () { e.preventDefault(); };
|
|
||||||
if (e.which === 13) { p(); return render( get($cur.val() - 1) ); } // Enter
|
|
||||||
if ([37, 40].indexOf(e.which) >= 0) { p(); return render(getPrevious()); } // Left
|
|
||||||
if ([38, 39].indexOf(e.which) >= 0) { p(); return render(getNext()); } // Right
|
|
||||||
if (e.which === 33) { p(); return render(getNext(10)); } // PageUp
|
|
||||||
if (e.which === 34) { p(); return render(getPrevious(10)); } // PageUp
|
|
||||||
if (e.which === 27) { p(); $close.click(); }
|
|
||||||
}).keyup(function (e) { e.stopPropagation(); }).focus();
|
|
||||||
$cur.on('change', function () {
|
|
||||||
render( get($cur.val() - 1) );
|
|
||||||
});
|
|
||||||
$close.click(function () {
|
|
||||||
states = [];
|
|
||||||
close();
|
|
||||||
onClose();
|
|
||||||
});
|
|
||||||
$rev.click(function () {
|
|
||||||
common.confirm(Messages.history_restorePrompt, function (yes) {
|
|
||||||
if (!yes) { return; }
|
|
||||||
close();
|
|
||||||
onRevert();
|
|
||||||
common.log(Messages.history_restoreDone);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Display the latest content
|
|
||||||
render(get(c));
|
|
||||||
};
|
|
||||||
|
|
||||||
// Load all the history messages into a new chainpad object
|
|
||||||
loadHistory(config, common, function (err, newRt) {
|
|
||||||
History.loading = false;
|
|
||||||
if (err) { throw new Error(err); }
|
|
||||||
realtime = newRt;
|
|
||||||
update();
|
|
||||||
c = states.length - 1;
|
|
||||||
display();
|
|
||||||
onReady();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return History;
|
|
||||||
});
|
|
||||||
|
|
@ -1,87 +0,0 @@
|
|||||||
define(['jquery'], function ($) {
|
|
||||||
var module = {};
|
|
||||||
|
|
||||||
module.create = function (cfg, onLocal, Cryptpad) {
|
|
||||||
var exp = {};
|
|
||||||
|
|
||||||
var parsed = exp.parsedHref = Cryptpad.parsePadUrl(window.location.href);
|
|
||||||
exp.defaultTitle = Cryptpad.getDefaultName(parsed);
|
|
||||||
|
|
||||||
exp.title = document.title; // TOOD slides
|
|
||||||
|
|
||||||
cfg = cfg || {};
|
|
||||||
|
|
||||||
var getHeadingText = cfg.getHeadingText || function () { return; };
|
|
||||||
var updateLocalTitle = function (newTitle) {
|
|
||||||
exp.title = newTitle;
|
|
||||||
onLocal();
|
|
||||||
if (typeof cfg.updateLocalTitle === "function") {
|
|
||||||
cfg.updateLocalTitle(newTitle);
|
|
||||||
} else {
|
|
||||||
document.title = newTitle;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var $title;
|
|
||||||
exp.setToolbar = function (toolbar) {
|
|
||||||
$title = toolbar && toolbar.title;
|
|
||||||
};
|
|
||||||
|
|
||||||
exp.getTitle = function () { return exp.title; };
|
|
||||||
var isDefaultTitle = exp.isDefaultTitle = function (){return exp.title === exp.defaultTitle;};
|
|
||||||
|
|
||||||
var suggestTitle = exp.suggestTitle = function (fallback) {
|
|
||||||
if (isDefaultTitle()) {
|
|
||||||
return getHeadingText() || fallback || "";
|
|
||||||
} else {
|
|
||||||
return exp.title || getHeadingText() || exp.defaultTitle;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var renameCb = function (err, newTitle) {
|
|
||||||
if (err) { return; }
|
|
||||||
updateLocalTitle(newTitle);
|
|
||||||
onLocal();
|
|
||||||
};
|
|
||||||
|
|
||||||
// update title: href is optional; if not specified, we use window.location.href
|
|
||||||
exp.updateTitle = function (newTitle, href, cb) {
|
|
||||||
cb = cb || $.noop;
|
|
||||||
if (newTitle === exp.title) { return; }
|
|
||||||
// Change the title now, and set it back to the old value if there is an error
|
|
||||||
var oldTitle = exp.title;
|
|
||||||
Cryptpad.renamePad(newTitle, href, function (err, data) {
|
|
||||||
if (err) {
|
|
||||||
console.log("Couldn't set pad title");
|
|
||||||
console.error(err);
|
|
||||||
updateLocalTitle(oldTitle);
|
|
||||||
return void cb(err);
|
|
||||||
}
|
|
||||||
updateLocalTitle(data);
|
|
||||||
cb(null, data);
|
|
||||||
if (!$title) { return; }
|
|
||||||
$title.find('span.title').text(data);
|
|
||||||
$title.find('input').val(data);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
exp.updateDefaultTitle = function (newDefaultTitle) {
|
|
||||||
exp.defaultTitle = newDefaultTitle;
|
|
||||||
if (!$title) { return; }
|
|
||||||
$title.find('input').attr("placeholder", exp.defaultTitle);
|
|
||||||
};
|
|
||||||
|
|
||||||
exp.getTitleConfig = function () {
|
|
||||||
return {
|
|
||||||
onRename: renameCb,
|
|
||||||
suggestName: suggestTitle,
|
|
||||||
defaultName: exp.defaultTitle
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
return exp;
|
|
||||||
};
|
|
||||||
|
|
||||||
return module;
|
|
||||||
});
|
|
||||||
|
|
@ -1,117 +0,0 @@
|
|||||||
define(['json.sortify'], function (Sortify) {
|
|
||||||
var module = {};
|
|
||||||
|
|
||||||
module.create = function (info, onLocal, Cryptget, Cryptpad) {
|
|
||||||
var exp = {};
|
|
||||||
|
|
||||||
var userData = exp.userData = {};
|
|
||||||
var userList = exp.userList = info.userList;
|
|
||||||
var myData = exp.myData = {};
|
|
||||||
exp.myUserName = info.myID;
|
|
||||||
exp.myNetfluxId = info.myID;
|
|
||||||
|
|
||||||
var network = Cryptpad.getNetwork();
|
|
||||||
|
|
||||||
var parsed = Cryptpad.parsePadUrl(window.location.href);
|
|
||||||
var appType = parsed ? parsed.type : undefined;
|
|
||||||
|
|
||||||
var oldUserData = {};
|
|
||||||
var addToUserData = exp.addToUserData = function(data) {
|
|
||||||
var users = userList.users;
|
|
||||||
for (var attrname in data) { userData[attrname] = data[attrname]; }
|
|
||||||
|
|
||||||
if (users && users.length) {
|
|
||||||
for (var userKey in userData) {
|
|
||||||
if (users.indexOf(userKey) === -1) {
|
|
||||||
delete userData[userKey];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(userList && typeof userList.onChange === "function") {
|
|
||||||
// Make sure we don't update the userlist everytime someone makes a change to the pad
|
|
||||||
if (Sortify(oldUserData) === Sortify(userData)) { return; }
|
|
||||||
oldUserData = JSON.parse(JSON.stringify(userData));
|
|
||||||
|
|
||||||
userList.onChange(userData);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
exp.getToolbarConfig = function () {
|
|
||||||
return {
|
|
||||||
data: userData,
|
|
||||||
list: userList,
|
|
||||||
userNetfluxId: exp.myNetfluxId
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
var setName = exp.setName = function (newName, cb) {
|
|
||||||
if (typeof(newName) !== 'string') { return; }
|
|
||||||
var myUserNameTemp = newName.trim();
|
|
||||||
if(myUserNameTemp.length > 32) {
|
|
||||||
myUserNameTemp = myUserNameTemp.substr(0, 32);
|
|
||||||
}
|
|
||||||
exp.myUserName = myUserNameTemp;
|
|
||||||
myData = {};
|
|
||||||
myData[exp.myNetfluxId] = {
|
|
||||||
name: exp.myUserName,
|
|
||||||
uid: Cryptpad.getUid(),
|
|
||||||
avatar: Cryptpad.getAvatarUrl(),
|
|
||||||
profile: Cryptpad.getProfileUrl(),
|
|
||||||
curvePublic: Cryptpad.getProxy().curvePublic
|
|
||||||
};
|
|
||||||
addToUserData(myData);
|
|
||||||
/*Cryptpad.setAttribute('username', exp.myUserName, function (err) {
|
|
||||||
if (err) {
|
|
||||||
console.log("Couldn't set username");
|
|
||||||
console.error(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (typeof cb === "function") { cb(); }
|
|
||||||
});*/
|
|
||||||
if (typeof cb === "function") { cb(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
exp.getLastName = function ($changeNameButton, isNew) {
|
|
||||||
Cryptpad.getLastName(function (err, lastName) {
|
|
||||||
if (err) {
|
|
||||||
console.log("Could not get previous name");
|
|
||||||
console.error(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Update the toolbar list:
|
|
||||||
// Add the current user in the metadata
|
|
||||||
if (typeof(lastName) === 'string') {
|
|
||||||
setName(lastName, onLocal);
|
|
||||||
} else {
|
|
||||||
myData[exp.myNetfluxId] = {
|
|
||||||
name: "",
|
|
||||||
uid: Cryptpad.getUid(),
|
|
||||||
avatar: Cryptpad.getAvatarUrl(),
|
|
||||||
profile: Cryptpad.getProfileUrl(),
|
|
||||||
curvePublic: Cryptpad.getProxy().curvePublic
|
|
||||||
};
|
|
||||||
addToUserData(myData);
|
|
||||||
onLocal();
|
|
||||||
$changeNameButton.click();
|
|
||||||
}
|
|
||||||
if (isNew && appType) {
|
|
||||||
Cryptpad.selectTemplate(appType, info.realtime, Cryptget);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
Cryptpad.onDisplayNameChanged(function (newName) {
|
|
||||||
setName(newName, onLocal);
|
|
||||||
});
|
|
||||||
|
|
||||||
network.on('reconnect', function (uid) {
|
|
||||||
exp.myNetfluxId = uid;
|
|
||||||
exp.setName(exp.myUserName);
|
|
||||||
});
|
|
||||||
|
|
||||||
return exp;
|
|
||||||
};
|
|
||||||
|
|
||||||
return module;
|
|
||||||
});
|
|
@ -1,112 +0,0 @@
|
|||||||
define(function () {
|
|
||||||
var module = {};
|
|
||||||
|
|
||||||
module.create = function (info, onLocal, Cryptget, Cryptpad) {
|
|
||||||
var exp = {};
|
|
||||||
|
|
||||||
var userData = exp.userData = {};
|
|
||||||
var userList = exp.userList = info.userList;
|
|
||||||
var myData = exp.myData = {};
|
|
||||||
exp.myUserName = info.myID;
|
|
||||||
exp.myNetfluxId = info.myID;
|
|
||||||
|
|
||||||
var network = Cryptpad.getNetwork();
|
|
||||||
|
|
||||||
var parsed = Cryptpad.parsePadUrl(window.location.href);
|
|
||||||
var appType = parsed ? parsed.type : undefined;
|
|
||||||
|
|
||||||
var addToUserData = exp.addToUserData = function(data) {
|
|
||||||
var users = userList.users;
|
|
||||||
for (var attrname in data) { userData[attrname] = data[attrname]; }
|
|
||||||
|
|
||||||
if (users && users.length) {
|
|
||||||
for (var userKey in userData) {
|
|
||||||
if (users.indexOf(userKey) === -1) {
|
|
||||||
delete userData[userKey];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(userList && typeof userList.onChange === "function") {
|
|
||||||
userList.onChange(userData);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
exp.getToolbarConfig = function () {
|
|
||||||
return {
|
|
||||||
data: userData,
|
|
||||||
list: userList,
|
|
||||||
userNetfluxId: exp.myNetfluxId
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
var setName = exp.setName = function (newName, cb) {
|
|
||||||
if (typeof(newName) !== 'string') { return; }
|
|
||||||
var myUserNameTemp = newName.trim();
|
|
||||||
if(myUserNameTemp.length > 32) {
|
|
||||||
myUserNameTemp = myUserNameTemp.substr(0, 32);
|
|
||||||
}
|
|
||||||
exp.myUserName = myUserNameTemp;
|
|
||||||
myData = {};
|
|
||||||
myData[exp.myNetfluxId] = {
|
|
||||||
name: exp.myUserName,
|
|
||||||
uid: Cryptpad.getUid(),
|
|
||||||
avatar: Cryptpad.getAvatarUrl(),
|
|
||||||
profile: Cryptpad.getProfileUrl(),
|
|
||||||
curvePublic: Cryptpad.getProxy().curvePublic
|
|
||||||
};
|
|
||||||
addToUserData(myData);
|
|
||||||
/*Cryptpad.setAttribute('username', exp.myUserName, function (err) {
|
|
||||||
if (err) {
|
|
||||||
console.log("Couldn't set username");
|
|
||||||
console.error(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (typeof cb === "function") { cb(); }
|
|
||||||
});*/
|
|
||||||
if (typeof cb === "function") { cb(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
exp.getLastName = function ($changeNameButton, isNew) {
|
|
||||||
Cryptpad.getLastName(function (err, lastName) {
|
|
||||||
if (err) {
|
|
||||||
console.log("Could not get previous name");
|
|
||||||
console.error(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Update the toolbar list:
|
|
||||||
// Add the current user in the metadata
|
|
||||||
if (typeof(lastName) === 'string') {
|
|
||||||
setName(lastName, onLocal);
|
|
||||||
} else {
|
|
||||||
myData[exp.myNetfluxId] = {
|
|
||||||
name: "",
|
|
||||||
uid: Cryptpad.getUid(),
|
|
||||||
avatar: Cryptpad.getAvatarUrl(),
|
|
||||||
profile: Cryptpad.getProfileUrl(),
|
|
||||||
curvePublic: Cryptpad.getProxy().curvePublic
|
|
||||||
};
|
|
||||||
addToUserData(myData);
|
|
||||||
onLocal();
|
|
||||||
$changeNameButton.click();
|
|
||||||
}
|
|
||||||
if (isNew && appType) {
|
|
||||||
Cryptpad.selectTemplate(appType, info.realtime, Cryptget);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
Cryptpad.onDisplayNameChanged(function (newName) {
|
|
||||||
setName(newName, onLocal);
|
|
||||||
});
|
|
||||||
|
|
||||||
network.on('reconnect', function (uid) {
|
|
||||||
exp.myNetfluxId = uid;
|
|
||||||
exp.setName(exp.myUserName);
|
|
||||||
});
|
|
||||||
|
|
||||||
return exp;
|
|
||||||
};
|
|
||||||
|
|
||||||
return module;
|
|
||||||
});
|
|
@ -0,0 +1,92 @@
|
|||||||
|
define([
|
||||||
|
'/file/file-crypto.js',
|
||||||
|
'/bower_components/tweetnacl/nacl-fast.min.js',
|
||||||
|
], function (FileCrypto) {
|
||||||
|
var Nacl = window.nacl;
|
||||||
|
var module = {};
|
||||||
|
|
||||||
|
module.upload = function (file, noStore, common, updateProgress, onComplete, onError, onPending) {
|
||||||
|
var u8 = file.blob; // This is not a blob but a uint8array
|
||||||
|
var metadata = file.metadata;
|
||||||
|
|
||||||
|
// if it exists, path contains the new pad location in the drive
|
||||||
|
var path = file.path;
|
||||||
|
|
||||||
|
var key = Nacl.randomBytes(32);
|
||||||
|
var next = FileCrypto.encrypt(u8, metadata, key);
|
||||||
|
|
||||||
|
var estimate = FileCrypto.computeEncryptedSize(u8.length, metadata);
|
||||||
|
|
||||||
|
var sendChunk = function (box, cb) {
|
||||||
|
var enc = Nacl.util.encodeBase64(box);
|
||||||
|
common.rpc.send.unauthenticated('UPLOAD', enc, function (e, msg) {
|
||||||
|
cb(e, msg);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var actual = 0;
|
||||||
|
var again = function (err, box) {
|
||||||
|
if (err) { throw new Error(err); }
|
||||||
|
if (box) {
|
||||||
|
actual += box.length;
|
||||||
|
var progressValue = (actual / estimate * 100);
|
||||||
|
updateProgress(progressValue);
|
||||||
|
|
||||||
|
return void sendChunk(box, function (e) {
|
||||||
|
if (e) { return console.error(e); }
|
||||||
|
next(again);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actual !== estimate) {
|
||||||
|
console.error('Estimated size does not match actual size');
|
||||||
|
}
|
||||||
|
|
||||||
|
// if not box then done
|
||||||
|
common.uploadComplete(function (e, id) {
|
||||||
|
if (e) { return void console.error(e); }
|
||||||
|
var uri = ['', 'blob', id.slice(0,2), id].join('/');
|
||||||
|
console.log("encrypted blob is now available as %s", uri);
|
||||||
|
|
||||||
|
var b64Key = Nacl.util.encodeBase64(key);
|
||||||
|
|
||||||
|
var hash = common.getFileHashFromKeys(id, b64Key);
|
||||||
|
var href = '/file/#' + hash;
|
||||||
|
|
||||||
|
var title = metadata.name;
|
||||||
|
|
||||||
|
if (noStore) { return void onComplete(href); }
|
||||||
|
|
||||||
|
common.initialPath = path;
|
||||||
|
common.renamePad(title || "", href, function (err) {
|
||||||
|
if (err) { return void console.error(err); }
|
||||||
|
onComplete(href);
|
||||||
|
common.setPadAttribute('fileType', metadata.type, null, href);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
common.uploadStatus(estimate, function (e, pending) {
|
||||||
|
if (e) {
|
||||||
|
console.error(e);
|
||||||
|
onError(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pending) {
|
||||||
|
return void onPending(function () {
|
||||||
|
// if the user wants to cancel the pending upload to execute that one
|
||||||
|
common.uploadCancel(function (e, res) {
|
||||||
|
if (e) {
|
||||||
|
return void console.error(e);
|
||||||
|
}
|
||||||
|
console.log(res);
|
||||||
|
next(again);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
next(again);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
return module;
|
||||||
|
});
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue