Merge branch 'staging' into oo
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
define([
|
||||
'jquery',
|
||||
'/common/cryptpad-common.js',
|
||||
'/common/common-util.js',
|
||||
'/customize/messages.js',
|
||||
'/customize/translations/messages.js',
|
||||
], function ($, Cryptpad, English) {
|
||||
], function ($, Util, Messages, English) {
|
||||
|
||||
var $body = $('body');
|
||||
|
||||
@@ -11,38 +12,40 @@ define([
|
||||
};
|
||||
|
||||
var todo = function (missing) {
|
||||
var str = "";
|
||||
var need = 1;
|
||||
var currentLang = "";
|
||||
var currentState = 1;
|
||||
|
||||
if (missing.length) {
|
||||
$body.append(pre(missing.map(function (msg) {
|
||||
var res = "";
|
||||
var code = msg[0];
|
||||
var key = msg[1];
|
||||
var needed = msg[2];
|
||||
var lang = msg[0];
|
||||
var key = msg[1]; // Array
|
||||
var state = msg[2]; // 0 === toDelete, 1 === missing, 2 === updated, 3 === invalid (wrong type)
|
||||
var value = msg[3] || '""';
|
||||
|
||||
if (str !== code) {
|
||||
if (str !== "")
|
||||
if (currentLang !== lang) {
|
||||
if (currentLang !== "")
|
||||
{
|
||||
res += '\n';
|
||||
}
|
||||
str = code;
|
||||
res += '/*\n *\n * ' + code + '\n *\n */\n\n';
|
||||
currentLang = lang;
|
||||
res += '/*\n *\n * ' + lang + '\n *\n */\n\n';
|
||||
}
|
||||
if (need !== needed) {
|
||||
need = needed;
|
||||
if (need === 0)
|
||||
if (currentState !== state) {
|
||||
currentState = state;
|
||||
if (currentState === 0)
|
||||
{
|
||||
res += '\n// TODO: These keys are not needed anymore and should be removed ('+ code + ')\n\n';
|
||||
res += '\n// TODO: These keys are not needed anymore and should be removed ('+ lang + ')\n\n';
|
||||
}
|
||||
}
|
||||
|
||||
res += (need ? '' : '// ') + 'out.' + key + ' = ' + value + ';';
|
||||
if (need === 1) {
|
||||
res += ' // ' + JSON.stringify(English[key]);
|
||||
} else if (need === 2) {
|
||||
res += ' // TODO: Key updated --> make sure the updated key "'+ value +'" exists and is translated before that one.';
|
||||
res += (currentState ? '' : '// ') + 'out.' + key.join('.') + ' = ' + value + ';';
|
||||
if (currentState === 1) {
|
||||
res += ' // ' + JSON.stringify(Util.find(English, key));
|
||||
} else if (currentState === 2) {
|
||||
res += ' // TODO: Key updated --> make sure the updated key "'+ value +'" exists and is translated before this one.';
|
||||
} else if (currentState === 3) {
|
||||
res += ' // NOTE: this key has an invalid type! Original value: ' + JSON.stringify(Util.find(English, key));
|
||||
}
|
||||
return res;
|
||||
}).join('\n')));
|
||||
@@ -50,5 +53,5 @@ define([
|
||||
$body.text('// All keys are present in all translations');
|
||||
}
|
||||
};
|
||||
Cryptpad.Messages._checkTranslationState(todo);
|
||||
Messages._checkTranslationState(todo);
|
||||
});
|
||||
|
||||
@@ -42,6 +42,11 @@ define(function() {
|
||||
'#800080', // purple
|
||||
];
|
||||
|
||||
// Background color in the apps with centered content:
|
||||
// - file app in view mode
|
||||
// - rich text app when editor's width reduced in settings
|
||||
config.appBackgroundColor = '#666';
|
||||
|
||||
// Set enableTemplates to false to remove the button allowing users to save a pad as a template
|
||||
// and remove the template category in CryptDrive
|
||||
config.enableTemplates = true;
|
||||
|
||||
@@ -37,6 +37,15 @@ define([
|
||||
window.alert("CryptPad needs localStorage to work, try a different browser");
|
||||
};
|
||||
|
||||
window.onerror = function (e) {
|
||||
if (/requirejs\.org/.test(e)) {
|
||||
console.log();
|
||||
console.error("Require.js threw a Script Error. This probably means you're missing a dependency for CryptPad.\nIt is recommended that the admin of this server runs `bower install && bower update` to get the latest code, then modify their cache version.\nBest of luck,\nThe CryptPad Developers");
|
||||
return void console.log();
|
||||
}
|
||||
throw e;
|
||||
};
|
||||
|
||||
try {
|
||||
var test_key = 'localStorage_test';
|
||||
var testval = Math.random().toString();
|
||||
|
||||
@@ -6,7 +6,7 @@ define([
|
||||
], function (Util, Messages, Crypto) {
|
||||
var Nacl = window.nacl;
|
||||
|
||||
var Hash = {};
|
||||
var Hash = window.CryptPad_Hash = {};
|
||||
|
||||
var uint8ArrayToHex = Util.uint8ArrayToHex;
|
||||
var hexToBase64 = Util.hexToBase64;
|
||||
@@ -176,7 +176,7 @@ Version 1
|
||||
secret.keys = Crypto.createEditCryptor();
|
||||
secret.key = Crypto.createEditCryptor().editKeyStr;
|
||||
};
|
||||
if (!secretHash && !/#/.test(window.location.href)) {
|
||||
if (!secretHash && !window.location.hash) { //!/#/.test(window.location.href)) {
|
||||
generate();
|
||||
return secret;
|
||||
} else {
|
||||
@@ -300,6 +300,8 @@ Version 1
|
||||
var rHref = href || getRelativeHref(window.location.href);
|
||||
var parsed = parsePadUrl(rHref);
|
||||
if (!parsed.hash) { return false; }
|
||||
// We can't have a stronger hash if we're already in edit mode
|
||||
if (parsed.hashData && parsed.hashData.mode === 'edit') { return; }
|
||||
var stronger;
|
||||
Object.keys(recents).some(function (id) {
|
||||
var pad = recents[id];
|
||||
|
||||
@@ -111,12 +111,14 @@ define([
|
||||
return input;
|
||||
};
|
||||
|
||||
dialog.okButton = function (content) {
|
||||
return h('button.ok.primary', { tabindex: '2', }, content || Messages.okButton);
|
||||
dialog.okButton = function (content, classString) {
|
||||
var sel = typeof(classString) === 'string'? 'button.ok.' + classString:'button.ok.primary';
|
||||
return h(sel, { tabindex: '2', }, content || Messages.okButton);
|
||||
};
|
||||
|
||||
dialog.cancelButton = function (content) {
|
||||
return h('button.cancel', { tabindex: '1'}, content || Messages.cancelButton);
|
||||
dialog.cancelButton = function (content, classString) {
|
||||
var sel = typeof(classString) === 'string'? 'button.' + classString:'button.cancel';
|
||||
return h(sel, { tabindex: '1'}, content || Messages.cancelButton);
|
||||
};
|
||||
|
||||
dialog.message = function (text) {
|
||||
@@ -315,11 +317,11 @@ define([
|
||||
message = dialog.message(msg);
|
||||
}
|
||||
|
||||
var close = Util.once(function (el) {
|
||||
var close = function (el) {
|
||||
var $el = $(el).fadeOut(150, function () {
|
||||
$el.remove();
|
||||
$el.detach();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
var navs = [];
|
||||
opt.buttons.forEach(function (b) {
|
||||
@@ -327,7 +329,7 @@ define([
|
||||
var button = h('button', { tabindex: '1', 'class': b.className || '' }, b.name);
|
||||
$(button).click(function () {
|
||||
b.onClick();
|
||||
close($(this).parents('.alertify').first());
|
||||
close($(button).parents('.alertify').first());
|
||||
});
|
||||
if (b.keys && b.keys.length) { $(button).attr('data-keys', JSON.stringify(b.keys)); }
|
||||
navs.push(button);
|
||||
@@ -464,8 +466,8 @@ define([
|
||||
message = dialog.message(msg);
|
||||
}
|
||||
|
||||
var ok = dialog.okButton(opt.ok);
|
||||
var cancel = dialog.cancelButton(opt.cancel);
|
||||
var ok = dialog.okButton(opt.ok, opt.okClass);
|
||||
var cancel = dialog.cancelButton(opt.cancel, opt.cancelClass);
|
||||
|
||||
var frame = dialog.frame([
|
||||
message,
|
||||
@@ -551,6 +553,7 @@ define([
|
||||
var $loading, $container;
|
||||
if ($('#' + LOADING).length) {
|
||||
$loading = $('#' + LOADING); //.show();
|
||||
$loading.css('display', '');
|
||||
$loading.removeClass('cp-loading-hidden');
|
||||
if (loadingText) {
|
||||
$('#' + LOADING).find('p').text(loadingText);
|
||||
@@ -598,11 +601,20 @@ define([
|
||||
}, 3750);
|
||||
// jquery.fadeout can get stuck
|
||||
};
|
||||
UI.errorLoadingScreen = function (error, transparent) {
|
||||
if (!$('#' + LOADING).is(':visible')) { UI.addLoadingScreen({hideTips: true}); }
|
||||
UI.errorLoadingScreen = function (error, transparent, exitable) {
|
||||
if (!$('#' + LOADING).is(':visible') || $('#' + LOADING).hasClass('cp-loading-hidden')) {
|
||||
UI.addLoadingScreen({hideTips: true});
|
||||
}
|
||||
$('.cp-loading-spinner-container').hide();
|
||||
$('#cp-loading-tip').remove();
|
||||
if (transparent) { $('#' + LOADING).css('opacity', 0.8); }
|
||||
$('#' + LOADING).find('p').html(error || Messages.error);
|
||||
if (exitable) {
|
||||
$(window).focus();
|
||||
$(window).keydown(function (e) {
|
||||
if (e.which === 27) { $('#' + LOADING).hide(); }
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var $defaultIcon = $('<span>', {"class": "fa fa-file-text-o"});
|
||||
|
||||
@@ -375,8 +375,8 @@ define([
|
||||
}
|
||||
if (val.embed) { $(link).find('#cp-share-embed').attr('checked', true); }
|
||||
if (val.present) { $(link).find('#cp-share-present').attr('checked', true); }
|
||||
UI.openCustomModal(UI.dialog.tabs(tabs));
|
||||
});
|
||||
return tabs;
|
||||
};
|
||||
UIElements.createFileShareModal = function (config) {
|
||||
var origin = config.origin;
|
||||
@@ -451,7 +451,7 @@ define([
|
||||
pathname: pathname
|
||||
});
|
||||
}
|
||||
UI.openCustomModal(UI.dialog.tabs(tabs));
|
||||
return tabs;
|
||||
};
|
||||
|
||||
UIElements.createButton = function (common, type, rightside, data, callback) {
|
||||
@@ -1655,8 +1655,6 @@ define([
|
||||
var metadataMgr = common.getMetadataMgr();
|
||||
var type = metadataMgr.getMetadataLazy().type;
|
||||
|
||||
// XXX check text for pad creation screen + translate it in French
|
||||
|
||||
var $body = $('body');
|
||||
var $creationContainer = $('<div>', { id: 'cp-creation-container' }).appendTo($body);
|
||||
var $creation = $('<div>', { id: 'cp-creation' }).appendTo($creationContainer);
|
||||
@@ -1687,7 +1685,10 @@ define([
|
||||
Messages.creation_ownedTitle,
|
||||
createHelper(Messages.creation_owned1 + '\n' + Messages.creation_owned2)
|
||||
]),
|
||||
setHTML(h('p'), Messages.creation_owned1 + '<br>' + Messages.creation_owned2),
|
||||
h('div.cp-creation-help-container', [
|
||||
setHTML(h('p'), Messages.creation_owned1),
|
||||
setHTML(h('p'), Messages.creation_owned2)
|
||||
]),
|
||||
h('input#cp-creation-owned-true.cp-creation-owned-value', {
|
||||
type: 'radio',
|
||||
name: 'cp-creation-owned',
|
||||
@@ -1715,7 +1716,10 @@ define([
|
||||
Messages.creation_expireTitle,
|
||||
createHelper(Messages.creation_expire1, Messages.creation_expire2)
|
||||
]),
|
||||
setHTML(h('p'), Messages.creation_expire1 + '<br>' + Messages.creation_expire2),
|
||||
h('div.cp-creation-help-container', [
|
||||
setHTML(h('p'), Messages.creation_expire1),
|
||||
setHTML(h('p'), Messages.creation_expire2)
|
||||
]),
|
||||
h('input#cp-creation-expire-false.cp-creation-expire-value', {
|
||||
type: 'radio',
|
||||
name: 'cp-creation-expire',
|
||||
@@ -1816,6 +1820,32 @@ define([
|
||||
$button.click(function () {
|
||||
create();
|
||||
});
|
||||
|
||||
// Settings button
|
||||
var origin = common.getMetadataMgr().getPrivateData().origin;
|
||||
$(h('div.cp-creation-settings', h('a', {
|
||||
href: origin + '/settings/#creation',
|
||||
target: '_blank'
|
||||
}, Messages.creation_settings))).appendTo($creation);
|
||||
};
|
||||
|
||||
UIElements.onServerError = function (common, err, toolbar, cb) {
|
||||
if (["EDELETED", "EEXPIRED"].indexOf(err.type) === -1) { return; }
|
||||
var msg = err.type;
|
||||
if (err.type === 'EEXPIRED') {
|
||||
msg = Messages.expiredError;
|
||||
if (err.loaded) {
|
||||
msg += Messages.expiredErrorCopy;
|
||||
}
|
||||
} else if (err.type === 'EDELETED') {
|
||||
msg = Messages.deletedError;
|
||||
if (err.loaded) {
|
||||
msg += Messages.expiredErrorCopy;
|
||||
}
|
||||
}
|
||||
if (toolbar && typeof toolbar.deleted === "function") { toolbar.deleted(); }
|
||||
UI.errorLoadingScreen(msg, true, true);
|
||||
(cb || function () {})();
|
||||
};
|
||||
|
||||
return UIElements;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
(function (window) {
|
||||
define([], function () {
|
||||
var Util = {};
|
||||
var Util = window.CryptPad_Util = {};
|
||||
|
||||
// If once is true, after the event has been fired, any further handlers which are
|
||||
// registered will fire immediately, and this type of event cannot be fired twice.
|
||||
|
||||
@@ -195,6 +195,16 @@ define([
|
||||
common.clearOwnedChannel = function (channel, cb) {
|
||||
postMessage("CLEAR_OWNED_CHANNEL", channel, cb);
|
||||
};
|
||||
common.removeOwnedChannel = function (channel, cb) {
|
||||
postMessage("REMOVE_OWNED_CHANNEL", channel, cb);
|
||||
};
|
||||
|
||||
common.getDeletedPads = function (cb) {
|
||||
postMessage("GET_DELETED_PADS", null, function (obj) {
|
||||
if (obj && obj.error) { return void cb(obj.error); }
|
||||
cb(null, obj);
|
||||
});
|
||||
};
|
||||
|
||||
common.uploadComplete = function (cb) {
|
||||
postMessage("UPLOAD_COMPLETE", null, function (obj) {
|
||||
@@ -528,6 +538,7 @@ define([
|
||||
pad.onJoinEvent = Util.mkEvent();
|
||||
pad.onLeaveEvent = Util.mkEvent();
|
||||
pad.onDisconnectEvent = Util.mkEvent();
|
||||
pad.onErrorEvent = Util.mkEvent();
|
||||
|
||||
common.getFullHistory = function (data, cb) {
|
||||
postMessage("GET_FULL_HISTORY", data, cb);
|
||||
@@ -550,6 +561,11 @@ define([
|
||||
return void cb(null, hashes);
|
||||
}
|
||||
|
||||
if (hashes.editHash) {
|
||||
// no need to find stronger if we already have edit hash
|
||||
return void cb(null, hashes);
|
||||
}
|
||||
|
||||
postMessage("GET_STRONGER_HASH", {
|
||||
href: window.location.href
|
||||
}, function (hash) {
|
||||
@@ -664,6 +680,9 @@ define([
|
||||
case 'PAD_DISCONNECT': {
|
||||
common.padRpc.onDisconnectEvent.fire(data); break;
|
||||
}
|
||||
case 'PAD_ERROR': {
|
||||
common.padRpc.onErrorEvent.fire(data); break;
|
||||
}
|
||||
// Drive
|
||||
case 'DRIVE_LOG': {
|
||||
common.drive.onLog.fire(data); break;
|
||||
|
||||
@@ -115,6 +115,12 @@ define(['json.sortify'], function (Sortify) {
|
||||
if (!meta.user) { return; }
|
||||
change(true);
|
||||
});
|
||||
sframeChan.on('EV_RT_ERROR', function (err) {
|
||||
if (err.type !== 'EEXPIRED' && err.type !== 'EDELETED') { return; }
|
||||
members = [];
|
||||
if (!meta.user) { return; }
|
||||
change(true);
|
||||
});
|
||||
|
||||
return Object.freeze({
|
||||
updateMetadata: function (m) {
|
||||
|
||||
@@ -94,9 +94,27 @@ define([
|
||||
return list;
|
||||
};
|
||||
|
||||
var getCanonicalChannelList = function () {
|
||||
return Util.deduplicateString(getUserChannelList()).sort();
|
||||
var getExpirableChannelList = function () {
|
||||
var list = [];
|
||||
store.userObject.getFiles([store.userObject.FILES_DATA]).forEach(function (id) {
|
||||
var data = store.userObject.getFileData(id);
|
||||
var edPublic = store.proxy.edPublic;
|
||||
|
||||
// Push channels owned by someone else or channel that should have expired
|
||||
// because of the expiration time
|
||||
if ((data.owners && data.owners.length && data.owners.indexOf(edPublic) === -1) ||
|
||||
(data.expire && data.expire < (+new Date()))) {
|
||||
list.push(Hash.hrefToHexChannelId(data.href));
|
||||
}
|
||||
});
|
||||
return list;
|
||||
};
|
||||
|
||||
var getCanonicalChannelList = function (expirable) {
|
||||
var list = expirable ? getExpirableChannelList() : getUserChannelList();
|
||||
return Util.deduplicateString(list).sort();
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
/////////////////////// RPC //////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////
|
||||
@@ -172,6 +190,34 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
Store.removeOwnedChannel = function (data, cb) {
|
||||
if (!store.rpc) { return void cb({error: 'RPC_NOT_READY'}); }
|
||||
store.rpc.removeOwnedChannel(data, function (err) {
|
||||
cb({error:err});
|
||||
});
|
||||
};
|
||||
|
||||
var arePinsSynced = function (cb) {
|
||||
if (!store.rpc) { return void cb({error: 'RPC_NOT_READY'}); }
|
||||
|
||||
var list = getCanonicalChannelList(false);
|
||||
var local = Hash.hashChannelList(list);
|
||||
store.rpc.getServerHash(function (e, hash) {
|
||||
if (e) { return void cb(e); }
|
||||
cb(null, hash === local);
|
||||
});
|
||||
};
|
||||
|
||||
var resetPins = function (cb) {
|
||||
if (!store.rpc) { return void cb({error: 'RPC_NOT_READY'}); }
|
||||
|
||||
var list = getCanonicalChannelList(false);
|
||||
store.rpc.reset(list, function (e, hash) {
|
||||
if (e) { return void cb(e); }
|
||||
cb(null, hash);
|
||||
});
|
||||
};
|
||||
|
||||
Store.uploadComplete = function (data, cb) {
|
||||
if (!store.rpc) { return void cb({error: 'RPC_NOT_READY'}); }
|
||||
store.rpc.uploadComplete(function (err, res) {
|
||||
@@ -196,27 +242,6 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
var arePinsSynced = function (cb) {
|
||||
if (!store.rpc) { return void cb({error: 'RPC_NOT_READY'}); }
|
||||
|
||||
var list = getCanonicalChannelList();
|
||||
var local = Hash.hashChannelList(list);
|
||||
store.rpc.getServerHash(function (e, hash) {
|
||||
if (e) { return void cb(e); }
|
||||
cb(null, hash === local);
|
||||
});
|
||||
};
|
||||
|
||||
var resetPins = function (cb) {
|
||||
if (!store.rpc) { return void cb({error: 'RPC_NOT_READY'}); }
|
||||
|
||||
var list = getCanonicalChannelList();
|
||||
store.rpc.reset(list, function (e, hash) {
|
||||
if (e) { return void cb(e); }
|
||||
cb(null, hash);
|
||||
});
|
||||
};
|
||||
|
||||
Store.uploadChunk = function (data, cb) {
|
||||
store.rpc.send.unauthenticated('UPLOAD', data.chunk, function (e, msg) {
|
||||
cb({
|
||||
@@ -309,6 +334,23 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
Store.getDeletedPads = function (data, cb) {
|
||||
if (!store.anon_rpc) { return void cb({error: 'ANON_RPC_NOT_READY'}); }
|
||||
var list = getCanonicalChannelList(true);
|
||||
if (!Array.isArray(list)) {
|
||||
return void cb({error: 'INVALID_FILE_LIST'});
|
||||
}
|
||||
|
||||
store.anon_rpc.send('GET_DELETED_PADS', list, function (e, res) {
|
||||
if (e) { return void cb({error: e}); }
|
||||
if (res && res.length && Array.isArray(res[0])) {
|
||||
cb(res[0]);
|
||||
} else {
|
||||
cb({error: 'UNEXPECTED_RESPONSE'});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Store.initAnonRpc = function (data, cb) {
|
||||
require([
|
||||
'/common/rpc.js',
|
||||
@@ -321,8 +363,6 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
/////////////////////// Store ////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////
|
||||
@@ -579,6 +619,8 @@ define([
|
||||
contains = true;
|
||||
pad.atime = +new Date();
|
||||
pad.title = title;
|
||||
pad.owners = owners;
|
||||
pad.expire = expire;
|
||||
|
||||
// If the href is different, it means we have a stronger one
|
||||
if (href !== pad.href) { isStronger = true; }
|
||||
@@ -773,6 +815,9 @@ define([
|
||||
onDisconnect: function () {
|
||||
postMessage("PAD_DISCONNECT");
|
||||
}, // post EV_PAD_DISCONNECT
|
||||
onError: function (err) {
|
||||
postMessage("PAD_ERROR", err);
|
||||
}, // post EV_PAD_ERROR
|
||||
channel: data.channel,
|
||||
validateKey: data.validateKey,
|
||||
owners: data.owners,
|
||||
@@ -852,7 +897,7 @@ define([
|
||||
case 'addFolder':
|
||||
store.userObject.addFolder(data.path, data.name, cb); break;
|
||||
case 'delete':
|
||||
store.userObject.delete(data.paths, cb, data.nocheck); break;
|
||||
store.userObject.delete(data.paths, cb, data.nocheck, data.isOwnPadRemoved); break;
|
||||
case 'emptyTrash':
|
||||
store.userObject.emptyTrash(cb); break;
|
||||
case 'rename':
|
||||
@@ -871,6 +916,8 @@ define([
|
||||
var userObject = store.userObject = UserObject.init(proxy.drive, {
|
||||
pinPads: Store.pinPads,
|
||||
unpinPads: Store.unpinPads,
|
||||
removeOwnedChannel: Store.removeOwnedChannel,
|
||||
edPublic: store.proxy.edPublic,
|
||||
loggedIn: store.loggedIn,
|
||||
log: function (msg) {
|
||||
postMessage("DRIVE_LOG", msg);
|
||||
|
||||
@@ -33,6 +33,7 @@ define([], function () {
|
||||
var onLeave = conf.onLeave;
|
||||
var onReady = conf.onReady;
|
||||
var onDisconnect = conf.onDisconnect;
|
||||
var onError = conf.onError;
|
||||
var owners = conf.owners;
|
||||
var password = conf.password;
|
||||
var expire = conf.expire;
|
||||
@@ -44,6 +45,17 @@ define([], function () {
|
||||
|
||||
var messageFromOuter = function () {};
|
||||
|
||||
var error = function (err, wc) {
|
||||
if (onError) {
|
||||
onError({
|
||||
type: err,
|
||||
loaded: !initializing
|
||||
});
|
||||
if (wc && (err === "EEXPIRED" || err === "EDELETED")) { wc.leave(); }
|
||||
}
|
||||
else { console.error(err); }
|
||||
};
|
||||
|
||||
var onRdy = function (padData) {
|
||||
// Trigger onReady only if not ready yet. This is important because the history keeper sends a direct
|
||||
// message through "network" when it is synced, and it triggers onReady for each channel joined.
|
||||
@@ -57,27 +69,11 @@ define([], function () {
|
||||
// shim between chainpad and netflux
|
||||
var msgIn = function (peerId, msg) {
|
||||
return msg.replace(/^cp\|/, '');
|
||||
|
||||
/*try {
|
||||
var decryptedMsg = Crypto.decrypt(msg, validateKey);
|
||||
return decryptedMsg;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return msg;
|
||||
}*/
|
||||
};
|
||||
|
||||
var msgOut = function (msg) {
|
||||
if (readOnly) { return; }
|
||||
return msg;
|
||||
/*try {
|
||||
var cmsg = Crypto.encrypt(msg);
|
||||
if (msg.indexOf('[4') === 0) { cmsg = 'cp|' + cmsg; }
|
||||
return cmsg;
|
||||
} catch (err) {
|
||||
console.log(msg);
|
||||
throw err;
|
||||
}*/
|
||||
};
|
||||
|
||||
var onMsg = function(peer, msg, wc, network, direct) {
|
||||
@@ -93,7 +89,9 @@ define([], function () {
|
||||
if (parsed.channel === wc.id && !validateKey) {
|
||||
validateKey = parsed.validateKey;
|
||||
}
|
||||
padData = parsed;
|
||||
if (parsed.channel === wc.id) {
|
||||
padData = parsed;
|
||||
}
|
||||
// We have to return even if it is not the current channel:
|
||||
// we don't want to continue with other channels messages here
|
||||
return;
|
||||
@@ -110,11 +108,17 @@ define([], function () {
|
||||
if (peer === hk) {
|
||||
// if the peer is the 'history keeper', extract their message
|
||||
var parsed1 = JSON.parse(msg);
|
||||
// First check if it is an error message (EXPIRED/DELETED)
|
||||
if (parsed1.channel === wc.id && parsed1.error) {
|
||||
return void error(parsed1.error, wc);
|
||||
}
|
||||
|
||||
msg = parsed1[4];
|
||||
// Check that this is a message for our channel
|
||||
if (parsed1[3] !== wc.id) { return; }
|
||||
}
|
||||
|
||||
|
||||
lastKnownHash = msg.slice(0,64);
|
||||
var message = msgIn(peer, msg);
|
||||
|
||||
@@ -191,7 +195,12 @@ define([], function () {
|
||||
};
|
||||
var msg = ['GET_HISTORY', wc.id, cfg];
|
||||
// Add the validateKey if we are the channel creator and we have a validateKey
|
||||
if (hk) { network.sendto(hk, JSON.stringify(msg)); }
|
||||
if (hk) {
|
||||
network.sendto(hk, JSON.stringify(msg)).then(function () {
|
||||
}, function (err) {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
onRdy();
|
||||
}
|
||||
@@ -218,8 +227,8 @@ define([], function () {
|
||||
// join the netflux network, promise to handle opening of the channel
|
||||
network.join(channel || null).then(function(wc) {
|
||||
onOpen(wc, network, firstConnection);
|
||||
}, function(error) {
|
||||
console.error(error);
|
||||
}, function(err) {
|
||||
console.error(err);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -31,6 +31,9 @@ define([
|
||||
case 'CLEAR_OWNED_CHANNEL': {
|
||||
Store.clearOwnedChannel(data, cb); break;
|
||||
}
|
||||
case 'REMOVE_OWNED_CHANNEL': {
|
||||
Store.removeOwnedChannel(data, cb); break;
|
||||
}
|
||||
case 'UPLOAD_CHUNK': {
|
||||
Store.uploadChunk(data, cb); break;
|
||||
}
|
||||
@@ -49,6 +52,9 @@ define([
|
||||
case 'UNPIN_PADS': {
|
||||
Store.unpinPads(data, cb); break;
|
||||
}
|
||||
case 'GET_DELETED_PADS': {
|
||||
Store.getDeletedPads(data, cb); break;
|
||||
}
|
||||
case 'GET_PINNED_USAGE': {
|
||||
Store.getPinnedUsage(data, cb); break;
|
||||
}
|
||||
|
||||
@@ -3,8 +3,9 @@ define([
|
||||
'/common/common-util.js',
|
||||
'/common/common-hash.js',
|
||||
'/common/common-realtime.js',
|
||||
'/common/common-feedback.js',
|
||||
'/customize/messages.js'
|
||||
], function (AppConfig, Util, Hash, Realtime, Messages) {
|
||||
], function (AppConfig, Util, Hash, Realtime, Feedback, Messages) {
|
||||
var module = {};
|
||||
|
||||
var clone = function (o) {
|
||||
@@ -17,8 +18,12 @@ define([
|
||||
console.error("unpinPads was not provided");
|
||||
};
|
||||
var pinPads = config.pinPads;
|
||||
var removeOwnedChannel = config.removeOwnedChannel || function () {
|
||||
console.error("removeOwnedChannel was not provided");
|
||||
};
|
||||
var loggedIn = config.loggedIn;
|
||||
var workgroup = config.workgroup;
|
||||
var edPublic = config.edPublic;
|
||||
|
||||
var ROOT = exp.ROOT;
|
||||
var FILES_DATA = exp.FILES_DATA;
|
||||
@@ -81,8 +86,11 @@ define([
|
||||
delete files[FILES_DATA][id];
|
||||
};
|
||||
|
||||
exp.checkDeletedFiles = function () {
|
||||
// Nothing in OLD_FILES_DATA for workgroups
|
||||
// Find files in FILES_DATA that are not anymore in the drive, and remove them from
|
||||
// FILES_DATA. If there are owned pads, remove them from server too, unless the flag tells
|
||||
// us they're already removed
|
||||
exp.checkDeletedFiles = function (isOwnPadRemoved) {
|
||||
// Nothing in FILES_DATA for workgroups
|
||||
if (workgroup || (!loggedIn && !config.testMode)) { return; }
|
||||
|
||||
var filesList = exp.getFiles([ROOT, 'hrefArray', TRASH]);
|
||||
@@ -90,9 +98,20 @@ define([
|
||||
exp.getFiles([FILES_DATA]).forEach(function (id) {
|
||||
if (filesList.indexOf(id) === -1) {
|
||||
var fd = exp.getFileData(id);
|
||||
if (fd && fd.href) {
|
||||
toClean.push(Hash.hrefToHexChannelId(fd.href));
|
||||
var channelId = fd && fd.href && Hash.hrefToHexChannelId(fd.href);
|
||||
// If trying to remove an owned pad, remove it from server also
|
||||
if (!isOwnPadRemoved &&
|
||||
fd.owners && fd.owners.indexOf(edPublic) !== -1 && channelId) {
|
||||
removeOwnedChannel(channelId, function (obj) {
|
||||
if (obj && obj.error) {
|
||||
console.error(obj.error);
|
||||
// RPC may not be responding
|
||||
// Send a report that can be handled manually
|
||||
Feedback.send('ERROR_DELETING_OWNED_PAD=' + channelId, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (channelId) { toClean.push(channelId); }
|
||||
spliceFileData(id);
|
||||
}
|
||||
});
|
||||
@@ -114,7 +133,7 @@ define([
|
||||
files[TRASH][obj.name].splice(idx, 1);
|
||||
});
|
||||
};
|
||||
exp.deleteMultiplePermanently = function (paths, nocheck) {
|
||||
exp.deleteMultiplePermanently = function (paths, nocheck, isOwnPadRemoved) {
|
||||
var hrefPaths = paths.filter(function(x) { return exp.isPathIn(x, ['hrefArray']); });
|
||||
var rootPaths = paths.filter(function(x) { return exp.isPathIn(x, [ROOT]); });
|
||||
var trashPaths = paths.filter(function(x) { return exp.isPathIn(x, [TRASH]); });
|
||||
@@ -170,7 +189,7 @@ define([
|
||||
|
||||
// In some cases, we want to remove pads from a location without removing them from
|
||||
// OLD_FILES_DATA (replaceHref)
|
||||
if (!nocheck) { exp.checkDeletedFiles(); }
|
||||
if (!nocheck) { exp.checkDeletedFiles(isOwnPadRemoved); }
|
||||
};
|
||||
|
||||
// Move
|
||||
|
||||
@@ -145,7 +145,22 @@ define([
|
||||
if (response && response.length) {
|
||||
cb(void 0, response[0]);
|
||||
} else {
|
||||
cb('INVALID_RESPONSE');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
exp.removeOwnedChannel = function (channel, cb) {
|
||||
if (typeof(channel) !== 'string' || channel.length !== 32) {
|
||||
// can't use this on files because files can't be owned...
|
||||
return void cb('INVALID_ARGUMENTS');
|
||||
}
|
||||
rpc.send('REMOVE_OWNED_CHANNEL', channel, function (e, response) {
|
||||
if (e) { return void cb(e); }
|
||||
if (response && response.length && response[0] === "OK") {
|
||||
cb();
|
||||
} else {
|
||||
cb('INVALID_RESPONSE');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
+10
-1
@@ -102,7 +102,7 @@ types of messages:
|
||||
}
|
||||
|
||||
// HACK to hide messages from the anon rpc
|
||||
if (parsed.length !== 4) {
|
||||
if (parsed.length !== 4 && parsed[1] !== 'ERROR') {
|
||||
console.log(parsed);
|
||||
console.error("received message [%s] for txid[%s] with no callback", msg, txid);
|
||||
}
|
||||
@@ -217,6 +217,15 @@ types of messages:
|
||||
});
|
||||
});
|
||||
|
||||
if (network.onHistoryKeeperChange) {
|
||||
network.onHistoryKeeperChange(function () {
|
||||
send('COOKIE', "", function (e) {
|
||||
if (e) { return void cb(e); }
|
||||
ctx.connected = true;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
send('COOKIE', "", function (e) {
|
||||
if (e) { return void cb(e); }
|
||||
// callback to provide 'send' method to whatever needs it
|
||||
|
||||
@@ -7,6 +7,7 @@ define([
|
||||
'/common/sframe-common.js',
|
||||
'/customize/messages.js',
|
||||
'/common/common-util.js',
|
||||
'/common/common-hash.js',
|
||||
'/common/common-interface.js',
|
||||
'/common/common-thumbnail.js',
|
||||
'/common/common-feedback.js',
|
||||
@@ -27,6 +28,7 @@ define([
|
||||
SFCommon,
|
||||
Messages,
|
||||
Util,
|
||||
Hash,
|
||||
UI,
|
||||
Thumb,
|
||||
Feedback,
|
||||
@@ -41,6 +43,7 @@ define([
|
||||
var STATE = Object.freeze({
|
||||
DISCONNECTED: 'DISCONNECTED',
|
||||
FORGOTTEN: 'FORGOTTEN',
|
||||
DELETED: 'DELETED',
|
||||
INFINITE_SPINNER: 'INFINITE_SPINNER',
|
||||
INITIALIZING: 'INITIALIZING',
|
||||
HISTORY_MODE: 'HISTORY_MODE',
|
||||
@@ -84,6 +87,7 @@ define([
|
||||
});
|
||||
});
|
||||
|
||||
var textContentGetter;
|
||||
var titleRecommender = function () { return false; };
|
||||
var contentGetter = function () { return UNINITIALIZED; };
|
||||
var normalize0 = function (x) { return x; };
|
||||
@@ -116,8 +120,9 @@ define([
|
||||
|
||||
var stateChange = function (newState) {
|
||||
var wasEditable = (state === STATE.READY);
|
||||
if (state === STATE.DELETED) { return; }
|
||||
if (state === STATE.INFINITE_SPINNER && newState !== STATE.READY) { return; }
|
||||
if (newState === STATE.INFINITE_SPINNER) {
|
||||
if (newState === STATE.INFINITE_SPINNER || newState === STATE.DELETED) {
|
||||
state = newState;
|
||||
} else if (state === STATE.DISCONNECTED && newState !== STATE.INITIALIZING) {
|
||||
throw new Error("Cannot transition from DISCONNECTED to " + newState);
|
||||
@@ -146,6 +151,10 @@ define([
|
||||
evStart.reg(function () { toolbar.forgotten(); });
|
||||
break;
|
||||
}
|
||||
case STATE.DELETED: {
|
||||
evStart.reg(function () { toolbar.deleted(); });
|
||||
break;
|
||||
}
|
||||
default:
|
||||
}
|
||||
if (wasEditable !== (state === STATE.READY)) {
|
||||
@@ -254,6 +263,7 @@ define([
|
||||
|
||||
var onReady = function () {
|
||||
var newContentStr = cpNfInner.chainpad.getUserDoc();
|
||||
if (state === STATE.DELETED) { return; }
|
||||
|
||||
var newPad = false;
|
||||
if (newContentStr === '') { newPad = true; }
|
||||
@@ -287,11 +297,17 @@ define([
|
||||
UI.removeLoadingScreen(emitResize);
|
||||
|
||||
var privateDat = cpNfInner.metadataMgr.getPrivateData();
|
||||
var hash = privateDat.availableHashes.editHash ||
|
||||
privateDat.availableHashes.viewHash;
|
||||
var href = privateDat.pathname + '#' + hash;
|
||||
if (AppConfig.textAnalyzer && textContentGetter) {
|
||||
var channelId = Hash.hrefToHexChannelId(href);
|
||||
AppConfig.textAnalyzer(textContentGetter, channelId);
|
||||
}
|
||||
|
||||
if (options.thumbnail && privateDat.thumbnails) {
|
||||
var hash = privateDat.availableHashes.editHash ||
|
||||
privateDat.availableHashes.viewHash;
|
||||
if (hash) {
|
||||
options.thumbnail.href = privateDat.pathname + '#' + hash;
|
||||
options.thumbnail.href = href;
|
||||
options.thumbnail.getContent = function () {
|
||||
if (!cpNfInner.chainpad) { return; }
|
||||
return cpNfInner.chainpad.getUserDoc();
|
||||
@@ -307,6 +323,7 @@ define([
|
||||
}
|
||||
};
|
||||
var onConnectionChange = function (info) {
|
||||
if (state === STATE.DELETED) { return; }
|
||||
stateChange(info.state ? STATE.INITIALIZING : STATE.DISCONNECTED);
|
||||
if (info.state) {
|
||||
UI.findOKButton().click();
|
||||
@@ -315,6 +332,12 @@ define([
|
||||
}
|
||||
};
|
||||
|
||||
var onError = function (err) {
|
||||
common.onServerError(err, toolbar, function () {
|
||||
stateChange(STATE.DELETED);
|
||||
});
|
||||
};
|
||||
|
||||
var setFileExporter = function (extension, fe, async) {
|
||||
var $export = common.createButton('export', true, {}, function () {
|
||||
var ext = (typeof(extension) === 'function') ? extension() : extension;
|
||||
@@ -407,7 +430,9 @@ define([
|
||||
var priv = common.getMetadataMgr().getPrivateData();
|
||||
if (priv.isNewFile) {
|
||||
var c = (priv.settings.general && priv.settings.general.creation) || {};
|
||||
if (c.skip && !priv.forceCreationScreen) { return void common.createPad(c, waitFor()); }
|
||||
if (c.skip && !priv.forceCreationScreen) {
|
||||
return void common.createPad(c, waitFor());
|
||||
}
|
||||
common.getPadCreationScreen(c, waitFor());
|
||||
}
|
||||
}).nThen(function (waitFor) {
|
||||
@@ -432,7 +457,8 @@ define([
|
||||
onLocal: onLocal,
|
||||
onInit: function () { stateChange(STATE.INITIALIZING); },
|
||||
onReady: function () { evStart.reg(onReady); },
|
||||
onConnectionChange: onConnectionChange
|
||||
onConnectionChange: onConnectionChange,
|
||||
onError: onError
|
||||
});
|
||||
|
||||
var privReady = Util.once(waitFor());
|
||||
@@ -448,6 +474,7 @@ define([
|
||||
var infiniteSpinnerModal = false;
|
||||
window.setInterval(function () {
|
||||
if (state === STATE.DISCONNECTED) { return; }
|
||||
if (state === STATE.DELETED) { return; }
|
||||
var l;
|
||||
try {
|
||||
l = cpNfInner.chainpad.getLag();
|
||||
@@ -567,6 +594,10 @@ define([
|
||||
// in the pad when requested by the framework.
|
||||
setContentGetter: function (cg) { contentGetter = cg; },
|
||||
|
||||
// Set a text content supplier, this is a function which will give a text
|
||||
// representation of the pad content if a text analyzer is configured
|
||||
setTextContentGetter: function (tcg) { textContentGetter = tcg; },
|
||||
|
||||
// Inform the framework that the content of the pad has been changed locally.
|
||||
localChange: onLocal,
|
||||
|
||||
|
||||
@@ -36,5 +36,14 @@ define([
|
||||
// This test is completed in common-interface.js
|
||||
Test(function (t) { Test.__ASYNC_BLOCKER__ = t; });
|
||||
|
||||
window.onerror = function (e) {
|
||||
if (/requirejs\.org/.test(e)) {
|
||||
console.log();
|
||||
console.error("Require.js threw a Script Error. This probably means you're missing a dependency for CryptPad.\nIt is recommended that the admin of this server runs `bower install && bower update` to get the latest code, then modify their cache version.\nBest of luck,\nThe CryptPad Developers");
|
||||
return void console.log();
|
||||
}
|
||||
throw e;
|
||||
};
|
||||
|
||||
require([document.querySelector('script[data-bootload]').getAttribute('data-bootload')]);
|
||||
});
|
||||
|
||||
@@ -34,6 +34,7 @@ define([
|
||||
var onLocal = config.onLocal || function () { };
|
||||
var setMyID = config.setMyID || function () { };
|
||||
var onReady = config.onReady || function () { };
|
||||
var onError = config.onError || function () { };
|
||||
var userName = config.userName;
|
||||
var initialState = config.initialState;
|
||||
if (config.transformFunction) { throw new Error("transformFunction is nolonger allowed"); }
|
||||
@@ -83,6 +84,11 @@ define([
|
||||
chainpad.abort();
|
||||
onConnectionChange({ state: false });
|
||||
});
|
||||
sframeChan.on('EV_RT_ERROR', function (err) {
|
||||
isReady = false;
|
||||
chainpad.abort();
|
||||
onError(err);
|
||||
});
|
||||
sframeChan.on('EV_RT_CONNECT', function (content) {
|
||||
//content.members.forEach(userList.onJoin);
|
||||
isReady = false;
|
||||
|
||||
@@ -102,6 +102,10 @@ define([], function () {
|
||||
sframeChan.event('EV_RT_DISCONNECT');
|
||||
});
|
||||
|
||||
padRpc.onErrorEvent.reg(function (err) {
|
||||
sframeChan.event('EV_RT_ERROR', err);
|
||||
});
|
||||
|
||||
// join the netflux network, promise to handle opening of the channel
|
||||
padRpc.joinPad({
|
||||
channel: channel || null,
|
||||
|
||||
@@ -44,12 +44,12 @@ define([
|
||||
|
||||
History.readOnly = common.getMetadataMgr().getPrivateData().readOnly;
|
||||
|
||||
var to = window.setTimeout(function () {
|
||||
/*var to = window.setTimeout(function () {
|
||||
cb('[GET_FULL_HISTORY_TIMEOUT]');
|
||||
}, 30000);
|
||||
}, 30000);*/
|
||||
|
||||
common.getFullHistory(realtime, function () {
|
||||
window.clearTimeout(to);
|
||||
//window.clearTimeout(to);
|
||||
cb(null, realtime);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -132,10 +132,12 @@ define([
|
||||
// Check if the pad exists on server
|
||||
if (!window.location.hash) { isNewFile = true; return; }
|
||||
|
||||
Cryptpad.isNewChannel(window.location.href, waitFor(function (e, isNew) {
|
||||
if (e) { return console.error(e); }
|
||||
isNewFile = Boolean(isNew);
|
||||
}));
|
||||
if (realtime) {
|
||||
Cryptpad.isNewChannel(window.location.href, waitFor(function (e, isNew) {
|
||||
if (e) { return console.error(e); }
|
||||
isNewFile = Boolean(isNew);
|
||||
}));
|
||||
}
|
||||
}).nThen(function () {
|
||||
var readOnly = secret.keys && !secret.keys.editKeyStr;
|
||||
var isNewHash = true;
|
||||
@@ -501,6 +503,9 @@ define([
|
||||
sframeChan.on('Q_CONTACTS_CLEAR_OWNED_CHANNEL', function (channel, cb) {
|
||||
Cryptpad.clearOwnedChannel(channel, cb);
|
||||
});
|
||||
sframeChan.on('Q_REMOVE_OWNED_CHANNEL', function (channel, cb) {
|
||||
Cryptpad.removeOwnedChannel(channel, cb);
|
||||
});
|
||||
|
||||
if (cfg.addRpc) {
|
||||
cfg.addRpc(sframeChan, Cryptpad, Utils);
|
||||
|
||||
@@ -92,6 +92,7 @@ define([
|
||||
funcs.createMarkdownToolbar = callWithCommon(UIElements.createMarkdownToolbar);
|
||||
funcs.getPadCreationScreen = callWithCommon(UIElements.getPadCreationScreen);
|
||||
funcs.createNewPadModal = callWithCommon(UIElements.createNewPadModal);
|
||||
funcs.onServerError = callWithCommon(UIElements.onServerError);
|
||||
|
||||
// Thumb
|
||||
funcs.displayThumbnail = callWithCommon(Thumb.displayThumbnail);
|
||||
@@ -392,15 +393,12 @@ define([
|
||||
UI.log(data.logText);
|
||||
});
|
||||
|
||||
ctx.metadataMgr.onChange(function () {
|
||||
try {
|
||||
var feedback = ctx.metadataMgr.getPrivateData().feedbackAllowed;
|
||||
Feedback.init(feedback);
|
||||
} catch (e) { Feedback.init(false); }
|
||||
});
|
||||
|
||||
ctx.metadataMgr.onReady(waitFor());
|
||||
}).nThen(function () {
|
||||
try {
|
||||
var feedback = ctx.metadataMgr.getPrivateData().feedbackAllowed;
|
||||
Feedback.init(feedback);
|
||||
} catch (e) { Feedback.init(false); }
|
||||
ctx.sframeChan.ready();
|
||||
cb(funcs);
|
||||
});
|
||||
|
||||
@@ -31,6 +31,8 @@ define({
|
||||
'EV_RT_CONNECT': true,
|
||||
// Called after the history is finished synchronizing, no arguments.
|
||||
'EV_RT_READY': true,
|
||||
// Called when the server returns an error in a pad (EEXPIRED, EDELETED).
|
||||
'EV_RT_ERROR': true,
|
||||
// Called from both outside and inside, argument is a (string) chainpad message.
|
||||
'Q_RT_MESSAGE': true,
|
||||
|
||||
@@ -201,12 +203,17 @@ define({
|
||||
// Inner drive needs to send command and receive updates from the async store
|
||||
'Q_DRIVE_USEROBJECT': true,
|
||||
'Q_DRIVE_GETOBJECT': true,
|
||||
// Get the pads deleted from the server by other users to remove them from the drive
|
||||
'Q_DRIVE_GETDELETED': true,
|
||||
// Store's userObject need to send log messages to inner to display them in the UI
|
||||
'EV_DRIVE_LOG': true,
|
||||
// Refresh the drive when the drive has changed ('change' or 'remove' events)
|
||||
'EV_DRIVE_CHANGE': true,
|
||||
'EV_DRIVE_REMOVE': true,
|
||||
|
||||
// Remove an owned pad from the server
|
||||
'Q_REMOVE_OWNED_CHANNEL': true,
|
||||
|
||||
// Notifications about connection and disconnection from the network
|
||||
'EV_NETWORK_DISCONNECT': true,
|
||||
'EV_NETWORK_RECONNECT': true,
|
||||
|
||||
+26
-12
@@ -444,13 +444,14 @@ define([
|
||||
'class': 'fa fa-share-alt cp-toolbar-share-button',
|
||||
title: Messages.shareButton
|
||||
});
|
||||
var modal = UIElements.createShareModal({
|
||||
origin: origin,
|
||||
pathname: pathname,
|
||||
hashes: hashes,
|
||||
common: Common
|
||||
});
|
||||
$shareBlock.click(function () {
|
||||
UIElements.createShareModal({
|
||||
origin: origin,
|
||||
pathname: pathname,
|
||||
hashes: hashes,
|
||||
common: Common
|
||||
});
|
||||
UI.openCustomModal(UI.dialog.tabs(modal));
|
||||
});
|
||||
|
||||
toolbar.$leftside.append($shareBlock);
|
||||
@@ -472,13 +473,14 @@ define([
|
||||
'class': 'fa fa-share-alt cp-toolbar-share-button',
|
||||
title: Messages.shareButton
|
||||
});
|
||||
var modal = UIElements.createFileShareModal({
|
||||
origin: origin,
|
||||
pathname: pathname,
|
||||
hashes: hashes,
|
||||
common: Common
|
||||
});
|
||||
$shareBlock.click(function () {
|
||||
UIElements.createFileShareModal({
|
||||
origin: origin,
|
||||
pathname: pathname,
|
||||
hashes: hashes,
|
||||
common: Common
|
||||
});
|
||||
UI.openCustomModal(UI.dialog.tabs(modal));
|
||||
});
|
||||
|
||||
toolbar.$leftside.append($shareBlock);
|
||||
@@ -707,6 +709,7 @@ define([
|
||||
typing = 1;
|
||||
$spin.text(Messages.typing);
|
||||
$spin.interval = window.setInterval(function () {
|
||||
if (toolbar.isErrorState) { return; }
|
||||
var dots = Array(typing+1).join('.');
|
||||
$spin.text(Messages.typing + dots);
|
||||
typing++;
|
||||
@@ -716,6 +719,7 @@ define([
|
||||
var onSynced = function () {
|
||||
if ($spin.timeout) { clearTimeout($spin.timeout); }
|
||||
$spin.timeout = setTimeout(function () {
|
||||
if (toolbar.isErrorState) { return; }
|
||||
window.clearInterval($spin.interval);
|
||||
typing = -1;
|
||||
$spin.text(Messages.saved);
|
||||
@@ -1092,6 +1096,16 @@ define([
|
||||
}
|
||||
};
|
||||
|
||||
// When the pad is deleted from the server
|
||||
toolbar.deleted = function (/*userId*/) {
|
||||
toolbar.isErrorState = true;
|
||||
toolbar.connected = false;
|
||||
updateUserList(toolbar, config);
|
||||
if (toolbar.spinner) {
|
||||
toolbar.spinner.text(Messages.deletedFromServer);
|
||||
}
|
||||
};
|
||||
|
||||
// On log out, remove permanently the realtime elements of the toolbar
|
||||
Common.onLogout(function () {
|
||||
failed();
|
||||
|
||||
@@ -380,6 +380,18 @@ define([
|
||||
var trashpaths = _findFileInTrash([TRASH], file);
|
||||
return rootpaths.concat(templatepaths, trashpaths);
|
||||
};
|
||||
|
||||
// Get drive ids of files from their channel ids
|
||||
exp.findChannels = function (channels) {
|
||||
var allFilesList = files[FILES_DATA];
|
||||
var channels64 = channels.slice().map(Util.hexToBase64);
|
||||
return getFiles([FILES_DATA]).filter(function (k) {
|
||||
var data = allFilesList[k];
|
||||
var parsed = Hash.parsePadUrl(data.href);
|
||||
return parsed.hashData && channels64.indexOf(parsed.hashData.channel) !== -1;
|
||||
});
|
||||
};
|
||||
|
||||
exp.search = function (value) {
|
||||
if (typeof(value) !== "string") { return []; }
|
||||
value = value.trim();
|
||||
@@ -544,17 +556,18 @@ define([
|
||||
// DELETE
|
||||
// Permanently delete multiple files at once using a list of paths
|
||||
// NOTE: We have to be careful when removing elements from arrays (trash root, unsorted or template)
|
||||
exp.delete = function (paths, cb, nocheck) {
|
||||
exp.delete = function (paths, cb, nocheck, isOwnPadRemoved) {
|
||||
if (sframeChan) {
|
||||
return void sframeChan.query("Q_DRIVE_USEROBJECT", {
|
||||
cmd: "delete",
|
||||
data: {
|
||||
paths: paths,
|
||||
nocheck: nocheck
|
||||
nocheck: nocheck,
|
||||
isOwnPadRemoved: isOwnPadRemoved
|
||||
}
|
||||
}, cb);
|
||||
}
|
||||
exp.deleteMultiplePermanently(paths, nocheck);
|
||||
exp.deleteMultiplePermanently(paths, nocheck, isOwnPadRemoved);
|
||||
if (typeof cb === "function") { cb(); }
|
||||
};
|
||||
exp.emptyTrash = function (cb) {
|
||||
|
||||
@@ -512,7 +512,11 @@ span {
|
||||
}
|
||||
input {
|
||||
width: 100%;
|
||||
margin-top: 5px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border-radius: 0;
|
||||
border: 1px solid #ddd;
|
||||
font-size: 14px;
|
||||
}
|
||||
.cp-app-drive-element-state {
|
||||
position: absolute;
|
||||
@@ -568,6 +572,11 @@ span {
|
||||
}
|
||||
li {
|
||||
display: table-row;
|
||||
input {
|
||||
border: 1px solid #ddd;
|
||||
margin: 0;
|
||||
padding: 0 4px;
|
||||
}
|
||||
&> span {
|
||||
padding: 0 5px;
|
||||
display: table-cell;
|
||||
|
||||
+69
-43
@@ -802,6 +802,7 @@ define([
|
||||
hide.push('properties');
|
||||
hide.push('rename');
|
||||
hide.push('openparent');
|
||||
hide.push('hashtag');
|
||||
}
|
||||
if (containsFolder && paths.length > 1) {
|
||||
// Cannot open multiple folders
|
||||
@@ -911,6 +912,7 @@ define([
|
||||
//var actions = [];
|
||||
var toShow = filterContextMenu(menuType, paths);
|
||||
var $actions = $contextMenu.find('a');
|
||||
$contextMenu.data('paths', paths);
|
||||
$actions = $actions.filter(function (i, el) {
|
||||
return toShow.some(function (className) { return $(el).is(className); });
|
||||
});
|
||||
@@ -922,9 +924,6 @@ define([
|
||||
} else {
|
||||
$a.text($(el).text());
|
||||
}
|
||||
$(el).data('paths', paths);
|
||||
//$(el).data('path', path);
|
||||
//:$(el).data('element', $element);
|
||||
$container.append($a);
|
||||
$a.click(function() { $(el).click(); });
|
||||
});
|
||||
@@ -1435,6 +1434,7 @@ define([
|
||||
case FILES_DATA: pName = FILES_DATA_NAME; break;
|
||||
case SEARCH: pName = SEARCH_NAME; break;
|
||||
case RECENT: pName = RECENT_NAME; break;
|
||||
case OWNED: pName = OWNED_NAME; break;
|
||||
default: pName = name;
|
||||
}
|
||||
return pName;
|
||||
@@ -1509,6 +1509,11 @@ define([
|
||||
if (!APP.loggedIn) {
|
||||
msg = Messages.fm_info_anonymous;
|
||||
$box.html(msg);
|
||||
$box.find('a[target!="_blank"]').click(function (e) {
|
||||
e.preventDefault();
|
||||
var href = $(this).attr('href');
|
||||
common.gotoURL(href);
|
||||
});
|
||||
return $box;
|
||||
}
|
||||
if (!msg || APP.store['hide-info-' + path[0]] === '1') {
|
||||
@@ -2227,7 +2232,7 @@ define([
|
||||
|
||||
// Only Trash and Root are available in not-owned files manager
|
||||
if (!path || displayedCategories.indexOf(path[0]) === -1) {
|
||||
log(Messages.categoryError);
|
||||
log(Messages.fm_categoryError);
|
||||
currentPath = [ROOT];
|
||||
_displayDirectory(currentPath);
|
||||
return;
|
||||
@@ -2668,11 +2673,14 @@ define([
|
||||
var data = JSON.parse(JSON.stringify(filesOp.getFileData(el)));
|
||||
if (!data || !data.href) { return void cb('INVALID_FILE'); }
|
||||
data.href = base + data.href;
|
||||
|
||||
var roUrl;
|
||||
if (ro) {
|
||||
data.roHref = data.href;
|
||||
delete data.href;
|
||||
} else {
|
||||
data.roHref = base + getReadOnlyUrl(el);
|
||||
roUrl = getReadOnlyUrl(el);
|
||||
if (roUrl) { data.roHref = base + roUrl; }
|
||||
}
|
||||
|
||||
UIElements.getProperties(common, data, cb);
|
||||
@@ -2682,11 +2690,13 @@ define([
|
||||
$contextMenu.find('.cp-app-drive-context-delete').text(Messages.fc_remove)
|
||||
.attr('data-icon', 'fa-eraser');
|
||||
}
|
||||
var deletePaths = function (paths) {
|
||||
var pathsList = [];
|
||||
paths.forEach(function (p) { pathsList.push(p.path); });
|
||||
var msg = Messages._getKey("fm_removeSeveralPermanentlyDialog", [paths.length]);
|
||||
if (paths.length === 1) {
|
||||
var deletePaths = function (paths, pathsList) {
|
||||
pathsList = pathsList || [];
|
||||
if (paths) {
|
||||
paths.forEach(function (p) { pathsList.push(p.path); });
|
||||
}
|
||||
var msg = Messages._getKey("fm_removeSeveralPermanentlyDialog", [pathsList.length]);
|
||||
if (pathsList.length === 1) {
|
||||
msg = Messages.fm_removePermanentlyDialog;
|
||||
}
|
||||
UI.confirm(msg, function(res) {
|
||||
@@ -2695,6 +2705,37 @@ define([
|
||||
filesOp.delete(pathsList, refresh);
|
||||
});
|
||||
};
|
||||
var deleteOwnedPaths = function (paths, pathsList) {
|
||||
pathsList = pathsList || [];
|
||||
if (paths) {
|
||||
paths.forEach(function (p) { pathsList.push(p.path); });
|
||||
}
|
||||
var msgD = pathsList.length === 1 ? Messages.fm_deleteOwnedPad :
|
||||
Messages.fm_deleteOwnedPads;
|
||||
UI.confirm(msgD, function(res) {
|
||||
$(window).focus();
|
||||
if (!res) { return; }
|
||||
filesOp.delete(pathsList, refresh);
|
||||
/*
|
||||
// Try to delete each selected pad from server, and delete from drive if no error
|
||||
var n = nThen(function () {});
|
||||
pathsList.forEach(function (p) {
|
||||
var el = filesOp.find(p);
|
||||
var data = filesOp.getFileData(el);
|
||||
var parsed = Hash.parsePadUrl(data.href);
|
||||
var channel = Util.base64ToHex(parsed.hashData.channel);
|
||||
n = n.nThen(function (waitFor) {
|
||||
sframeChan.query('Q_REMOVE_OWNED_CHANNEL', channel,
|
||||
waitFor(function (e) {
|
||||
if (e) { return void console.error(e); }
|
||||
filesOp.delete([p], function () {}, false, true);
|
||||
}));
|
||||
});
|
||||
});
|
||||
n.nThen(function () { refresh(); });
|
||||
*/
|
||||
});
|
||||
};
|
||||
$contextMenu.on("click", "a", function(e) {
|
||||
e.stopPropagation();
|
||||
var paths = $contextMenu.data('paths');
|
||||
@@ -2720,27 +2761,7 @@ define([
|
||||
moveElements(pathsList, [TRASH], false, refresh);
|
||||
}
|
||||
else if ($(this).hasClass('cp-app-drive-context-deleteowned')) {
|
||||
var msgD = Messages.fm_deleteOwnedPads;
|
||||
UI.confirm(msgD, function(res) {
|
||||
$(window).focus();
|
||||
if (!res) { return; }
|
||||
// Try to delete each selected pad from server, and delete from drive if no error
|
||||
var n = nThen(function () {});
|
||||
paths.forEach(function (p) {
|
||||
var el = filesOp.find(p.path);
|
||||
var data = filesOp.getFileData(el);
|
||||
var parsed = Hash.parsePadUrl(data.href);
|
||||
var channel = Util.base64ToHex(parsed.hashData.channel);
|
||||
n = n.nThen(function (waitFor) {
|
||||
sframeChan.query('Q_CONTACTS_CLEAR_OWNED_CHANNEL', channel,
|
||||
waitFor(function (e) {
|
||||
if (e) { return void console.error(e); }
|
||||
filesOp.delete([p.path], refresh);
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
return;
|
||||
deleteOwnedPaths(paths);
|
||||
}
|
||||
else if ($(this).hasClass('cp-app-drive-context-open')) {
|
||||
paths.forEach(function (p) {
|
||||
@@ -2878,18 +2899,11 @@ define([
|
||||
if (!$(elmt).data('path')) { return; }
|
||||
paths.push($(elmt).data('path'));
|
||||
});
|
||||
// If we are in the trash or anon pad or if we are holding the "shift" key, delete permanently,
|
||||
if (!paths.length) { return; }
|
||||
// If we are in the trash or anon pad or if we are holding the "shift" key,
|
||||
// delete permanently
|
||||
if (!APP.loggedIn || isTrash || e.shiftKey) {
|
||||
var msg = Messages._getKey("fm_removeSeveralPermanentlyDialog", [paths.length]);
|
||||
if (paths.length === 1) {
|
||||
msg = Messages.fm_removePermanentlyDialog;
|
||||
}
|
||||
|
||||
UI.confirm(msg, function(res) {
|
||||
$(window).focus();
|
||||
if (!res) { return; }
|
||||
filesOp.delete(paths, refresh);
|
||||
});
|
||||
deletePaths(null, paths);
|
||||
return;
|
||||
}
|
||||
// else move to trash
|
||||
@@ -2975,6 +2989,19 @@ define([
|
||||
|
||||
refresh();
|
||||
UI.removeLoadingScreen();
|
||||
|
||||
sframeChan.query('Q_DRIVE_GETDELETED', null, function (err, data) {
|
||||
var ids = filesOp.findChannels(data);
|
||||
var titles = [];
|
||||
ids.forEach(function (id) {
|
||||
var title = filesOp.getTitle(id);
|
||||
titles.push(title);
|
||||
var paths = filesOp.findFile(id);
|
||||
filesOp.delete(paths, refresh);
|
||||
});
|
||||
if (!titles.length) { return; }
|
||||
UI.log(Messages._getKey('fm_deletedPads', [titles.join(', ')]));
|
||||
});
|
||||
};
|
||||
|
||||
var setHistory = function (bool, update) {
|
||||
@@ -3091,7 +3118,6 @@ define([
|
||||
throw new Error("Corrupted drive");
|
||||
}
|
||||
andThen(common, proxy);
|
||||
UI.removeLoadingScreen();
|
||||
|
||||
var onDisconnect = APP.onDisconnect = function (noAlert) {
|
||||
setEditable(false);
|
||||
|
||||
@@ -56,6 +56,12 @@ define([
|
||||
cb(obj);
|
||||
});
|
||||
});
|
||||
sframeChan.on('Q_DRIVE_GETDELETED', function (data, cb) {
|
||||
Cryptpad.getDeletedPads(function (err, obj) {
|
||||
if (err) { return void console.error(err); }
|
||||
cb(obj);
|
||||
});
|
||||
});
|
||||
Cryptpad.onNetworkDisconnect.reg(function () {
|
||||
sframeChan.event('EV_NETWORK_DISCONNECT');
|
||||
});
|
||||
|
||||
@@ -224,6 +224,8 @@ define([
|
||||
if (decrypting) { return; }
|
||||
decrypting = true;
|
||||
displayFile(ev, sizeMb, function (err) {
|
||||
$appContainer.css('background-color',
|
||||
common.getAppConfig().appBackgroundColor);
|
||||
if (err) { UI.alert(err); }
|
||||
});
|
||||
};
|
||||
|
||||
+9
-85
@@ -13,7 +13,6 @@ define([
|
||||
$(function () {
|
||||
var $main = $('#mainBlock');
|
||||
var $checkImport = $('#import-recent');
|
||||
var Messages = Cryptpad.Messages;
|
||||
|
||||
// main block is hidden in case javascript is disabled
|
||||
$main.removeClass('hidden');
|
||||
@@ -61,90 +60,15 @@ define([
|
||||
|
||||
hashing = true;
|
||||
var shouldImport = $checkImport[0].checked;
|
||||
|
||||
// setTimeout 100ms to remove the keyboard on mobile devices before the loading screen pops up
|
||||
window.setTimeout(function () {
|
||||
UI.addLoadingScreen({
|
||||
loadingText: Messages.login_hashing,
|
||||
hideTips: true,
|
||||
});
|
||||
// We need a setTimeout(cb, 0) otherwise the loading screen is only displayed after hashing the password
|
||||
window.setTimeout(function () {
|
||||
loginReady(function () {
|
||||
var uname = $uname.val();
|
||||
var passwd = $passwd.val();
|
||||
Login.loginOrRegister(uname, passwd, false, function (err, result) {
|
||||
if (!err) {
|
||||
var proxy = result.proxy;
|
||||
|
||||
// successful validation and user already exists
|
||||
// set user hash in localStorage and redirect to drive
|
||||
if (!proxy.login_name) {
|
||||
result.proxy.login_name = result.userName;
|
||||
}
|
||||
|
||||
proxy.edPrivate = result.edPrivate;
|
||||
proxy.edPublic = result.edPublic;
|
||||
|
||||
proxy.curvePrivate = result.curvePrivate;
|
||||
proxy.curvePublic = result.curvePublic;
|
||||
|
||||
Feedback.send('LOGIN', true);
|
||||
Realtime.whenRealtimeSyncs(result.realtime, function() {
|
||||
LocalStore.login(result.userHash, result.userName, function () {
|
||||
hashing = false;
|
||||
if (test) {
|
||||
localStorage.clear();
|
||||
test.pass();
|
||||
return;
|
||||
}
|
||||
if (shouldImport) {
|
||||
sessionStorage.migrateAnonDrive = 1;
|
||||
}
|
||||
if (sessionStorage.redirectTo) {
|
||||
var h = sessionStorage.redirectTo;
|
||||
var parser = document.createElement('a');
|
||||
parser.href = h;
|
||||
if (parser.origin === window.location.origin) {
|
||||
delete sessionStorage.redirectTo;
|
||||
window.location.href = h;
|
||||
return;
|
||||
}
|
||||
}
|
||||
window.location.href = '/drive/';
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
switch (err) {
|
||||
case 'NO_SUCH_USER':
|
||||
UI.removeLoadingScreen(function () {
|
||||
UI.alert(Messages.login_noSuchUser, function () {
|
||||
hashing = false;
|
||||
});
|
||||
});
|
||||
break;
|
||||
case 'INVAL_USER':
|
||||
UI.removeLoadingScreen(function () {
|
||||
UI.alert(Messages.login_invalUser, function () {
|
||||
hashing = false;
|
||||
});
|
||||
});
|
||||
break;
|
||||
case 'INVAL_PASS':
|
||||
UI.removeLoadingScreen(function () {
|
||||
UI.alert(Messages.login_invalPass, function () {
|
||||
hashing = false;
|
||||
});
|
||||
});
|
||||
break;
|
||||
default: // UNHANDLED ERROR
|
||||
UI.errorLoadingScreen(Messages.login_unhandledError);
|
||||
}
|
||||
});
|
||||
});
|
||||
}, 0);
|
||||
}, 100);
|
||||
var uname = $uname.val();
|
||||
var passwd = $passwd.val();
|
||||
Login.loginOrRegisterUI(uname, passwd, false, shouldImport, Test.testing, function () {
|
||||
if (test) {
|
||||
localStorage.clear();
|
||||
test.pass();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
});
|
||||
$('#register').on('click', function () {
|
||||
if (sessionStorage) {
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="cp">
|
||||
<!-- If this file is not called customize.dist/src/template.html, it is generated -->
|
||||
<head>
|
||||
<title data-localization="main_title">CryptPad: Zero Knowledge, Collaborative Real Time Editing</title>
|
||||
<meta content="text/html; charset=utf-8" http-equiv="content-type"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||
<script async data-main="main" src="/bower_components/requirejs/require.js"></script>
|
||||
<link rel="icon" type="image/png" href="/customize/main-favicon.png" id="favicon"/>
|
||||
</head>
|
||||
<body class="html">
|
||||
<noscript>
|
||||
<p><strong>OOPS</strong> In order to do encryption in your browser, Javascript is really <strong>really</strong> required.</p>
|
||||
<p><strong>OUPS</strong> Afin de pouvoir réaliser le chiffrement dans votre navigateur, Javascript est <strong>vraiment</strong> nécessaire.</p>
|
||||
</noscript>
|
||||
</html>
|
||||
@@ -0,0 +1,5 @@
|
||||
define(['/bower_components/localforage/dist/localforage.min.js'], function (localForage) {
|
||||
localForage.clear();
|
||||
sessionStorage.clear();
|
||||
localStorage.clear();
|
||||
});
|
||||
+16
-2
@@ -31,6 +31,7 @@ define([
|
||||
'/common/common-hash.js',
|
||||
'/common/common-util.js',
|
||||
'/bower_components/chainpad/chainpad.dist.js',
|
||||
'/customize/application_config.js',
|
||||
|
||||
'/bower_components/diff-dom/diffDOM.js',
|
||||
|
||||
@@ -50,7 +51,8 @@ define([
|
||||
ApiConfig,
|
||||
Hash,
|
||||
Util,
|
||||
ChainPad)
|
||||
ChainPad,
|
||||
AppConfig)
|
||||
{
|
||||
var DiffDom = window.diffDOM;
|
||||
|
||||
@@ -400,6 +402,17 @@ define([
|
||||
}
|
||||
});
|
||||
|
||||
framework.setTextContentGetter(function () {
|
||||
var innerCopy = inner.cloneNode(true);
|
||||
displayMediaTags(framework, innerCopy, mediaTagMap);
|
||||
innerCopy.normalize();
|
||||
$(innerCopy).find('*').each(function (i, el) {
|
||||
$(el).append(' ');
|
||||
});
|
||||
var str = $(innerCopy).text();
|
||||
str = str.replace(/\s\s+/g, ' ');
|
||||
return str;
|
||||
});
|
||||
framework.setContentGetter(function () {
|
||||
displayMediaTags(framework, inner, mediaTagMap);
|
||||
inner.normalize();
|
||||
@@ -592,7 +605,8 @@ define([
|
||||
}
|
||||
// Used in ckeditor-config.js
|
||||
Ckeditor.CRYPTPAD_URLARGS = ApiConfig.requireConf.urlArgs;
|
||||
var newCss = '.cke_body_width { background: #666; height: 100%; }' +
|
||||
var backColor = AppConfig.appBackgroundColor;
|
||||
var newCss = '.cke_body_width { background: '+ backColor +'; height: 100%; }' +
|
||||
'.cke_body_width body {' +
|
||||
'max-width: 50em; padding: 10px 30px; margin: 0 auto; min-height: 100%;'+
|
||||
'box-sizing: border-box;'+
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
@import (once) '../../customize/src/less2/include/tokenfield.less';
|
||||
@import (once) '../../customize/src/less2/include/tools.less';
|
||||
@import (once) '../../customize/src/less2/include/avatar.less';
|
||||
@import (once) '../../customize/src/less2/include/creation.less';
|
||||
|
||||
.toolbar_main(
|
||||
@bg-color: @colortheme_poll-bg,
|
||||
@@ -15,6 +16,7 @@
|
||||
.fileupload_main();
|
||||
.alertify_main();
|
||||
.tokenfield_main();
|
||||
.creation_main();
|
||||
|
||||
@poll-fore: #555;
|
||||
|
||||
|
||||
+31
-3
@@ -1119,17 +1119,31 @@ define([
|
||||
}
|
||||
|
||||
UI.removeLoadingScreen();
|
||||
if (isNew) {
|
||||
var privateDat = metadataMgr.getPrivateData();
|
||||
var skipTemp = Util.find(privateDat,
|
||||
['settings', 'general', 'creation', 'noTemplate']);
|
||||
var skipCreation = Util.find(privateDat, ['settings', 'general', 'creation', 'skip']);
|
||||
if (isNew && (!AppConfig.displayCreationScreen || (!skipTemp && skipCreation))) {
|
||||
common.openTemplatePicker();
|
||||
}
|
||||
};
|
||||
|
||||
var onDisconnect = function () {
|
||||
// Manage disconnections because of network or error
|
||||
var onDisconnect = function (info) {
|
||||
if (APP.unrecoverable) { return; }
|
||||
if (info && info.type) {
|
||||
// Server error
|
||||
return void common.onServerError(info, APP.toolbar, function () {
|
||||
APP.unrecoverable = true;
|
||||
setEditable(false);
|
||||
});
|
||||
}
|
||||
setEditable(false);
|
||||
UI.alert(Messages.common_connectionLost, undefined, true);
|
||||
};
|
||||
|
||||
var onReconnect = function () {
|
||||
if (APP.unrecoverable) { return; }
|
||||
setEditable(true);
|
||||
UI.findOKButton().click();
|
||||
};
|
||||
@@ -1175,6 +1189,7 @@ define([
|
||||
Title.setToolbar(APP.toolbar);
|
||||
|
||||
var $rightside = APP.toolbar.$rightside;
|
||||
var $drawer = APP.toolbar.$drawer;
|
||||
|
||||
metadataMgr.onChange(function () {
|
||||
var md = copyObject(metadataMgr.getMetadata());
|
||||
@@ -1189,6 +1204,9 @@ define([
|
||||
var $forgetPad = common.createButton('forget', true, {}, forgetCb);
|
||||
$rightside.append($forgetPad);
|
||||
|
||||
var $properties = common.createButton('properties', true);
|
||||
$drawer.append($properties);
|
||||
|
||||
/* save as template */
|
||||
if (!metadataMgr.getPrivateData().isTemplate) {
|
||||
var templateObj = {
|
||||
@@ -1201,7 +1219,7 @@ define([
|
||||
|
||||
/* add an export button */
|
||||
var $export = common.createButton('export', true, {}, exportFile);
|
||||
$rightside.append($export);
|
||||
$drawer.append($export);
|
||||
|
||||
var $help = common.createButton('', true).click(function () { showHelp(); })
|
||||
.appendTo($rightside);
|
||||
@@ -1255,6 +1273,16 @@ define([
|
||||
SFCommon.create(waitFor(function (c) { APP.common = common = c; }));
|
||||
}).nThen(function (waitFor) {
|
||||
common.getSframeChannel().onReady(waitFor());
|
||||
}).nThen(function (waitFor) {
|
||||
if (!AppConfig.displayCreationScreen) { return; }
|
||||
var priv = common.getMetadataMgr().getPrivateData();
|
||||
if (priv.isNewFile) {
|
||||
var c = (priv.settings.general && priv.settings.general.creation) || {};
|
||||
if (c.skip && !priv.forceCreationScreen) {
|
||||
return void common.createPad(c, waitFor());
|
||||
}
|
||||
common.getPadCreationScreen(c, waitFor());
|
||||
}
|
||||
}).nThen(function (/* waitFor */) {
|
||||
Test.registerInner(common.getSframeChannel());
|
||||
var metadataMgr = common.getMetadataMgr();
|
||||
|
||||
+3
-1
@@ -36,6 +36,8 @@ define([
|
||||
};
|
||||
window.addEventListener('message', onMsg);
|
||||
}).nThen(function (/*waitFor*/) {
|
||||
SFCommonO.start();
|
||||
SFCommonO.start({
|
||||
useCreationScreen: true
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+7
-115
@@ -55,39 +55,6 @@ define([
|
||||
|
||||
var registering = false;
|
||||
var test;
|
||||
var logMeIn = function (result) {
|
||||
LocalStore.setUserHash(result.userHash);
|
||||
|
||||
var proxy = result.proxy;
|
||||
proxy.edPublic = result.edPublic;
|
||||
proxy.edPrivate = result.edPrivate;
|
||||
proxy.curvePublic = result.curvePublic;
|
||||
proxy.curvePrivate = result.curvePrivate;
|
||||
|
||||
Feedback.send('REGISTRATION', true);
|
||||
|
||||
Realtime.whenRealtimeSyncs(result.realtime, function () {
|
||||
LocalStore.login(result.userHash, result.userName, function () {
|
||||
registering = false;
|
||||
if (test) {
|
||||
localStorage.clear();
|
||||
test.pass();
|
||||
return;
|
||||
}
|
||||
if (sessionStorage.redirectTo) {
|
||||
var h = sessionStorage.redirectTo;
|
||||
var parser = document.createElement('a');
|
||||
parser.href = h;
|
||||
if (parser.origin === window.location.origin) {
|
||||
delete sessionStorage.redirectTo;
|
||||
window.location.href = h;
|
||||
return;
|
||||
}
|
||||
}
|
||||
window.location.href = '/drive/';
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
$register.click(function () {
|
||||
if (registering) {
|
||||
@@ -125,89 +92,14 @@ define([
|
||||
function (yes) {
|
||||
if (!yes) { return; }
|
||||
|
||||
Login.loginOrRegisterUI(uname, passwd, true, shouldImport, Test.testing, function () {
|
||||
if (test) {
|
||||
localStorage.clear();
|
||||
test.pass();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
registering = true;
|
||||
// setTimeout 100ms to remove the keyboard on mobile devices before the loading screen pops up
|
||||
window.setTimeout(function () {
|
||||
UI.addLoadingScreen({
|
||||
loadingText: Messages.login_hashing,
|
||||
hideTips: true,
|
||||
});
|
||||
// We need a setTimeout(cb, 0) otherwise the loading screen is only displayed after hashing the password
|
||||
window.setTimeout(function () {
|
||||
Login.loginOrRegister(uname, passwd, true, function (err, result) {
|
||||
var proxy;
|
||||
if (result) { proxy = result.proxy; }
|
||||
|
||||
if (err) {
|
||||
switch (err) {
|
||||
case 'NO_SUCH_USER':
|
||||
UI.removeLoadingScreen(function () {
|
||||
UI.alert(Messages.login_noSuchUser, function () {
|
||||
registering = false;
|
||||
});
|
||||
});
|
||||
break;
|
||||
case 'INVAL_USER':
|
||||
UI.removeLoadingScreen(function () {
|
||||
UI.alert(Messages.login_invalUser, function () {
|
||||
registering = false;
|
||||
});
|
||||
});
|
||||
break;
|
||||
case 'INVAL_PASS':
|
||||
UI.removeLoadingScreen(function () {
|
||||
UI.alert(Messages.login_invalPass, function () {
|
||||
registering = false;
|
||||
});
|
||||
});
|
||||
break;
|
||||
case 'PASS_TOO_SHORT':
|
||||
UI.removeLoadingScreen(function () {
|
||||
var warning = Messages._getKey('register_passwordTooShort', [
|
||||
Cred.MINIMUM_PASSWORD_LENGTH
|
||||
]);
|
||||
UI.alert(warning, function () {
|
||||
registering = false;
|
||||
});
|
||||
});
|
||||
break;
|
||||
case 'ALREADY_REGISTERED':
|
||||
// logMeIn should reset registering = false
|
||||
UI.removeLoadingScreen(function () {
|
||||
UI.confirm(Messages.register_alreadyRegistered, function (yes) {
|
||||
if (!yes) { return; }
|
||||
proxy.login_name = uname;
|
||||
|
||||
if (!proxy[Constants.displayNameKey]) {
|
||||
proxy[Constants.displayNameKey] = uname;
|
||||
}
|
||||
LocalStore.eraseTempSessionValues();
|
||||
logMeIn(result);
|
||||
});
|
||||
});
|
||||
break;
|
||||
default: // UNHANDLED ERROR
|
||||
registering = false;
|
||||
UI.errorLoadingScreen(Messages.login_unhandledError);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (Test.testing) { return void logMeIn(result); }
|
||||
|
||||
LocalStore.eraseTempSessionValues();
|
||||
if (shouldImport) {
|
||||
sessionStorage.migrateAnonDrive = 1;
|
||||
}
|
||||
|
||||
proxy.login_name = uname;
|
||||
proxy[Constants.displayNameKey] = uname;
|
||||
sessionStorage.createReadme = 1;
|
||||
|
||||
logMeIn(result);
|
||||
});
|
||||
}, 0);
|
||||
}, 200);
|
||||
}, {
|
||||
ok: Messages.register_writtenPassword,
|
||||
cancel: Messages.register_cancel,
|
||||
|
||||
+20
-4
@@ -10,6 +10,7 @@ define([
|
||||
'/customize/messages.js',
|
||||
'/common/hyperscript.js',
|
||||
'/customize/application_config.js',
|
||||
'/api/config',
|
||||
|
||||
'/bower_components/file-saver/FileSaver.min.js',
|
||||
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
|
||||
@@ -26,7 +27,8 @@ define([
|
||||
Hash,
|
||||
Messages,
|
||||
h,
|
||||
AppConfig
|
||||
AppConfig,
|
||||
ApiConfig
|
||||
)
|
||||
{
|
||||
var saveAs = window.saveAs;
|
||||
@@ -64,10 +66,16 @@ define([
|
||||
'code': [
|
||||
'cp-settings-code-indent-unit',
|
||||
'cp-settings-code-indent-type'
|
||||
]
|
||||
],
|
||||
'subscription': {
|
||||
onClick: function () {
|
||||
var urls = common.getMetadataMgr().getPrivateData().accounts;
|
||||
window.open(urls.upgradeURL);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (!AppConfig.dislayCreationScreen) {
|
||||
if (!AppConfig.displayCreationScreen) {
|
||||
delete categories.creation;
|
||||
}
|
||||
if (AppConfig.disableFeedback) {
|
||||
@@ -78,6 +86,9 @@ define([
|
||||
var displaynameIdx = categories.account.indexOf('cp-settings-displayname');
|
||||
categories.account.splice(displaynameIdx, 1);
|
||||
}
|
||||
if (!ApiConfig.allowSubscriptions) {
|
||||
delete categories.subscription;
|
||||
}
|
||||
|
||||
var create = {};
|
||||
|
||||
@@ -778,7 +789,7 @@ define([
|
||||
var $categories = $('<div>', {'class': 'cp-sidebarlayout-categories'})
|
||||
.appendTo(APP.$leftside);
|
||||
APP.$usage = $('<div>', {'class': 'usage'}).appendTo(APP.$leftside);
|
||||
var active = 'account';
|
||||
var active = privateData.category || 'account';
|
||||
Object.keys(categories).forEach(function (key) {
|
||||
var $category = $('<div>', {'class': 'cp-sidebarlayout-category'}).appendTo($categories);
|
||||
if (key === 'account') { $category.append($('<span>', {'class': 'fa fa-user-o'})); }
|
||||
@@ -786,12 +797,17 @@ define([
|
||||
if (key === 'code') { $category.append($('<span>', {'class': 'fa fa-file-code-o' })); }
|
||||
if (key === 'pad') { $category.append($('<span>', {'class': 'fa fa-file-word-o' })); }
|
||||
if (key === 'creation') { $category.append($('<span>', {'class': 'fa fa-plus-circle' })); }
|
||||
if (key === 'subscription') { $category.append($('<span>', {'class': 'fa fa-star-o' })); }
|
||||
|
||||
if (key === active) {
|
||||
$category.addClass('cp-leftside-active');
|
||||
}
|
||||
|
||||
$category.click(function () {
|
||||
if (!Array.isArray(categories[key]) && categories[key].onClick) {
|
||||
categories[key].onClick();
|
||||
return;
|
||||
}
|
||||
active = key;
|
||||
$categories.find('.cp-leftside-active').removeClass('cp-leftside-active');
|
||||
$category.addClass('cp-leftside-active');
|
||||
|
||||
+10
-1
@@ -66,9 +66,18 @@ define([
|
||||
Cryptpad.mergeAnonDrive(cb);
|
||||
});
|
||||
};
|
||||
var category;
|
||||
if (window.location.hash) {
|
||||
category = window.location.hash.slice(1);
|
||||
window.location.hash = '';
|
||||
}
|
||||
var addData = function (obj) {
|
||||
if (category) { obj.category = category; }
|
||||
};
|
||||
SFCommonO.start({
|
||||
noRealtime: true,
|
||||
addRpc: addRpc
|
||||
addRpc: addRpc,
|
||||
addData: addData
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -88,6 +88,13 @@
|
||||
color: #777;
|
||||
}
|
||||
|
||||
.cp-app-todo-task-input {
|
||||
margin: @spacing;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
font-weight: bold;
|
||||
display: none;
|
||||
}
|
||||
.cp-app-todo-task-text {
|
||||
margin: @spacing;
|
||||
flex: 1;
|
||||
|
||||
+43
-4
@@ -9,6 +9,7 @@ define([
|
||||
'/common/common-hash.js',
|
||||
'/todo/todo.js',
|
||||
'/customize/messages.js',
|
||||
'/bower_components/sortablejs/Sortable.min.js',
|
||||
|
||||
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
|
||||
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
|
||||
@@ -23,7 +24,8 @@ define([
|
||||
UI,
|
||||
Hash,
|
||||
Todo,
|
||||
Messages
|
||||
Messages,
|
||||
Sortable
|
||||
)
|
||||
{
|
||||
var APP = window.APP = {};
|
||||
@@ -47,6 +49,17 @@ define([
|
||||
var onReady = function () {
|
||||
var todo = Todo.init(APP.lm.proxy);
|
||||
|
||||
Sortable.create($list[0], {
|
||||
store: {
|
||||
get: function () {
|
||||
return todo.getOrder();
|
||||
},
|
||||
set: function (sortable) {
|
||||
todo.reorder(sortable.toArray());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var deleteTask = function(id) {
|
||||
todo.remove(id);
|
||||
|
||||
@@ -70,6 +83,10 @@ define([
|
||||
|
||||
var makeCheckbox = function (id, cb) {
|
||||
var entry = APP.lm.proxy.data[id];
|
||||
if (!entry || typeof(entry) !== 'object') {
|
||||
return void console.log('entry undefined');
|
||||
}
|
||||
|
||||
var checked = entry.state === 1 ?
|
||||
'cp-app-todo-task-checkbox-checked fa-check-square-o':
|
||||
'cp-app-todo-task-checkbox-unchecked fa-square-o';
|
||||
@@ -92,6 +109,7 @@ define([
|
||||
};
|
||||
|
||||
var addTaskUI = function (el, animate) {
|
||||
if (!el) { return; }
|
||||
var $taskDiv = $('<div>', {
|
||||
'class': 'cp-app-todo-task'
|
||||
});
|
||||
@@ -101,6 +119,7 @@ define([
|
||||
$taskDiv.appendTo($list);
|
||||
}
|
||||
$taskDiv.data('id', el);
|
||||
$taskDiv.attr('data-id', el);
|
||||
|
||||
makeCheckbox(el, function (/*state*/) {
|
||||
APP.display();
|
||||
@@ -108,14 +127,34 @@ define([
|
||||
.appendTo($taskDiv);
|
||||
|
||||
var entry = APP.lm.proxy.data[el];
|
||||
if (!entry || typeof(entry) !== 'object') {
|
||||
return void console.log('entry undefined');
|
||||
}
|
||||
|
||||
if (entry.state) {
|
||||
$taskDiv.addClass('cp-app-todo-task-complete');
|
||||
}
|
||||
|
||||
$('<span>', { 'class': 'cp-app-todo-task-text' })
|
||||
.text(entry.task)
|
||||
.appendTo($taskDiv);
|
||||
var $span = $('<span>', { 'class': 'cp-app-todo-task-text' });
|
||||
|
||||
var $input = $('<input>', {
|
||||
type: 'text',
|
||||
'class': 'cp-app-todo-task-input'
|
||||
}).val(entry.task).keydown(function (e) {
|
||||
if (e.which === 13) {
|
||||
todo.val(el, 'task', $input.val().trim());
|
||||
$input.hide();
|
||||
$span.text($input.val().trim());
|
||||
$span.show();
|
||||
}
|
||||
}).appendTo($taskDiv);
|
||||
|
||||
$span.text(entry.task)
|
||||
.appendTo($taskDiv)
|
||||
.click(function () {
|
||||
$input.show();
|
||||
$span.hide();
|
||||
});
|
||||
/*$('<span>', { 'class': 'cp-app-todo-task-date' })
|
||||
.text(new Date(entry.ctime).toLocaleString())
|
||||
.appendTo($taskDiv);*/
|
||||
|
||||
@@ -39,6 +39,24 @@ define([
|
||||
if (typeof(proxy.data) !== 'object') { proxy.data = {}; }
|
||||
if (!Array.isArray(proxy.order)) { proxy.order = []; }
|
||||
if (typeof(proxy.type) !== 'string') { proxy.type = 'todo'; }
|
||||
|
||||
// if a key exists in order, but there is no data for it...
|
||||
// remove that key
|
||||
var i = proxy.order.length - 1;
|
||||
for (;i >= 0; i--) {
|
||||
if (typeof(proxy.data[proxy.order[i]]) === 'undefined') {
|
||||
console.log('removing todo entry with no data at [%s]', i);
|
||||
proxy.order.splice(i, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// if you have data, but it's not in the order array...
|
||||
// add it to the order array...
|
||||
Object.keys(proxy.data).forEach(function (key) {
|
||||
if (proxy.order.indexOf(key) > -1) { return; }
|
||||
console.log("restoring entry with missing key");
|
||||
proxy.order.unshift(key);
|
||||
});
|
||||
};
|
||||
|
||||
/* add (id, obj) push id to order, add object to data */
|
||||
@@ -59,6 +77,17 @@ define([
|
||||
if (proxy.data[id]) { delete proxy.data[id]; }
|
||||
};
|
||||
|
||||
/* change the order in the proxy (with a check to make sure that nothing is missing */
|
||||
var reorder = function (proxy, order) {
|
||||
var existingOrder = proxy.order.slice().sort();
|
||||
var newOrder = order.slice().sort();
|
||||
if (JSON.stringify(existingOrder) === JSON.stringify(newOrder)) {
|
||||
proxy.order = order.slice();
|
||||
} else {
|
||||
console.error("Can't reorder the tasks. Some tasks are missing or added");
|
||||
}
|
||||
};
|
||||
|
||||
Todo.init = function (proxy) {
|
||||
var api = {};
|
||||
initialize(proxy);
|
||||
@@ -72,6 +101,12 @@ define([
|
||||
api.remove = function (id) {
|
||||
return remove(proxy, id);
|
||||
};
|
||||
api.getOrder = function () {
|
||||
return proxy.order.slice();
|
||||
};
|
||||
api.reorder = function (order) {
|
||||
return reorder(proxy, order);
|
||||
};
|
||||
|
||||
return api;
|
||||
};
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
@import (once) '../../customize/src/less2/include/alertify.less';
|
||||
@import (once) '../../customize/src/less2/include/tools.less';
|
||||
@import (once) '../../customize/src/less2/include/tokenfield.less';
|
||||
@import (once) '../../customize/src/less2/include/creation.less';
|
||||
|
||||
.toolbar_main(
|
||||
@bg-color: @colortheme_whiteboard-bg,
|
||||
@@ -14,6 +15,7 @@
|
||||
.fileupload_main();
|
||||
.alertify_main();
|
||||
.tokenfield_main();
|
||||
.creation_main();
|
||||
|
||||
// body
|
||||
&.cp-app-whiteboard {
|
||||
|
||||
+33
-2
@@ -415,6 +415,7 @@ define([
|
||||
Title.setToolbar(toolbar);
|
||||
|
||||
var $rightside = toolbar.$rightside;
|
||||
var $drawer = toolbar.$drawer;
|
||||
|
||||
/* save as template */
|
||||
if (!metadataMgr.getPrivateData().isTemplate) {
|
||||
@@ -428,7 +429,7 @@ define([
|
||||
|
||||
/* add an export button */
|
||||
var $export = common.createButton('export', true, {}, saveImage);
|
||||
$rightside.append($export);
|
||||
$drawer.append($export);
|
||||
|
||||
if (common.isLoggedIn()) {
|
||||
common.createButton('savetodrive', true, {}, function () {})
|
||||
@@ -449,6 +450,9 @@ define([
|
||||
});
|
||||
$rightside.append($forget);
|
||||
|
||||
var $properties = common.createButton('properties', true);
|
||||
toolbar.$drawer.append($properties);
|
||||
|
||||
if (!readOnly) {
|
||||
makeColorButton($rightside);
|
||||
|
||||
@@ -562,7 +566,12 @@ define([
|
||||
|
||||
|
||||
if (readOnly) { return; }
|
||||
if (isNew) {
|
||||
|
||||
var privateDat = metadataMgr.getPrivateData();
|
||||
var skipTemp = Util.find(privateDat,
|
||||
['settings', 'general', 'creation', 'noTemplate']);
|
||||
var skipCreation = Util.find(privateDat, ['settings', 'general', 'creation', 'skip']);
|
||||
if (isNew && (!AppConfig.displayCreationScreen || (!skipTemp && skipCreation))) {
|
||||
common.openTemplatePicker();
|
||||
}
|
||||
});
|
||||
@@ -589,6 +598,7 @@ define([
|
||||
};
|
||||
|
||||
config.onAbort = function () {
|
||||
if (APP.unrecoverable) { return; }
|
||||
// inform of network disconnect
|
||||
setEditable(false);
|
||||
toolbar.failed();
|
||||
@@ -596,6 +606,7 @@ define([
|
||||
};
|
||||
|
||||
config.onConnectionChange = function (info) {
|
||||
if (APP.unrecoverable) { return; }
|
||||
setEditable(info.state);
|
||||
if (info.state) {
|
||||
initializing = true;
|
||||
@@ -605,10 +616,18 @@ define([
|
||||
}
|
||||
};
|
||||
|
||||
config.onError = function (err) {
|
||||
common.onServerError(err, toolbar, function () {
|
||||
APP.unrecoverable = true;
|
||||
setEditable(false);
|
||||
});
|
||||
};
|
||||
|
||||
cpNfInner = common.startRealtime(config);
|
||||
metadataMgr = cpNfInner.metadataMgr;
|
||||
|
||||
cpNfInner.onInfiniteSpinner(function () {
|
||||
if (APP.unrecoverable) { return; }
|
||||
setEditable(false);
|
||||
UI.confirm(Messages.realtime_unrecoverableError, function (yes) {
|
||||
if (!yes) { return; }
|
||||
@@ -640,6 +659,18 @@ define([
|
||||
$('body').append($div.html());
|
||||
}));
|
||||
SFCommon.create(waitFor(function (c) { APP.common = common = c; }));
|
||||
}).nThen(function (waitFor) {
|
||||
common.getSframeChannel().onReady(waitFor());
|
||||
}).nThen(function (waitFor) {
|
||||
if (!AppConfig.displayCreationScreen) { return; }
|
||||
var priv = common.getMetadataMgr().getPrivateData();
|
||||
if (priv.isNewFile) {
|
||||
var c = (priv.settings.general && priv.settings.general.creation) || {};
|
||||
if (c.skip && !priv.forceCreationScreen) {
|
||||
return void common.createPad(c, waitFor());
|
||||
}
|
||||
common.getPadCreationScreen(c, waitFor());
|
||||
}
|
||||
}).nThen(function (/*waitFor*/) {
|
||||
andThen(common);
|
||||
});
|
||||
|
||||
@@ -36,6 +36,8 @@ define([
|
||||
};
|
||||
window.addEventListener('message', onMsg);
|
||||
}).nThen(function (/*waitFor*/) {
|
||||
SFCommonO.start();
|
||||
SFCommonO.start({
|
||||
useCreationScreen: true
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -32,6 +32,7 @@ define([
|
||||
sFrameChan.onReady(waitFor());
|
||||
}).nThen(function (/*waitFor*/) {
|
||||
var $container = $('#cp-app-worker-container');
|
||||
$('<a>', {href:'http://localhost:3000/worker/', target:'_blank'}).text('other').appendTo($container);
|
||||
var $bar = $('.cp-toolbar-container');
|
||||
|
||||
var displayed = ['useradmin', 'newpad', 'limit', 'pageTitle'];
|
||||
|
||||
@@ -29,16 +29,17 @@ require.config({
|
||||
});
|
||||
|
||||
var i = 0;
|
||||
var id = Math.floor(Math.random()*100000);
|
||||
|
||||
onconnect = function(e) {
|
||||
console.log(e);
|
||||
console.log(i);
|
||||
var port = e.ports[0];
|
||||
console.log('here');
|
||||
require([
|
||||
'/common/outer/async-store.js'
|
||||
], function (Store) {
|
||||
console.log(Store);
|
||||
//require([
|
||||
// '/common/outer/async-store.js'
|
||||
//], function (Store) {
|
||||
//console.log(Store);
|
||||
console.log(self.Proxy);
|
||||
var n = i;
|
||||
port.postMessage({state: 'READY'});
|
||||
@@ -46,8 +47,9 @@ onconnect = function(e) {
|
||||
console.log('worker received');
|
||||
console.log(e.data);
|
||||
port.postMessage('hello CryptPad'+n);
|
||||
port.postMessage('This is '+id);
|
||||
};
|
||||
var data = {
|
||||
/*var data = {
|
||||
query: function (cmd, data, cb) {
|
||||
console.log(cmd, data);
|
||||
},
|
||||
@@ -64,7 +66,7 @@ onconnect = function(e) {
|
||||
});
|
||||
port.postMessage('Store is connected!');
|
||||
port.postMessage('Your username is ' + ret.store.proxy['cryptpad.username']);
|
||||
});
|
||||
});*/
|
||||
i++;
|
||||
});
|
||||
//});
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user