Merge branch 'staging' of github.com:xwiki-labs/cryptpad into staging
This commit is contained in:
commit
33e19d5918
@ -12,6 +12,8 @@ define(function() {
|
|||||||
*/
|
*/
|
||||||
config.notificationTimeout = 5000;
|
config.notificationTimeout = 5000;
|
||||||
|
|
||||||
|
config.enablePinning = true;
|
||||||
|
|
||||||
config.whiteboardPalette = [
|
config.whiteboardPalette = [
|
||||||
'#000000', // black
|
'#000000', // black
|
||||||
'#FFFFFF', // white
|
'#FFFFFF', // white
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"lint": "jshint --config .jshintrc --exclude-path .jshintignore .",
|
"lint": "jshint --config .jshintrc --exclude-path .jshintignore .",
|
||||||
"test": "node TestSelenium.js",
|
"test": "node TestSelenium.js",
|
||||||
"style": "lessc ./customize.dist/src/less/cryptpad.less > ./customize.dist/main.css && lessc ./customize.dist/src/less/toolbar.less > ./customize.dist/toolbar.css && lessc ./www/drive/file.less > ./www/drive/file.css && lessc ./www/settings/main.less > ./www/settings/main.css && lessc ./www/slide/slide.less > ./www/slide/slide.css",
|
"style": "lessc ./customize.dist/src/less/cryptpad.less > ./customize.dist/main.css && lessc ./customize.dist/src/less/toolbar.less > ./customize.dist/toolbar.css && lessc ./www/drive/file.less > ./www/drive/file.css && lessc ./www/settings/main.less > ./www/settings/main.css && lessc ./www/slide/slide.less > ./www/slide/slide.css && lessc ./www/whiteboard/whiteboard.less > ./www/whiteboard/whiteboard.css",
|
||||||
"template": "cd customize.dist/src && node build.js"
|
"template": "cd customize.dist/src && node build.js"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
7
rpc.js
7
rpc.js
@ -144,16 +144,11 @@ var getChannelList = function (store, publicKey, cb) {
|
|||||||
pins[pin] = false;
|
pins[pin] = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!parsed[1] || parsed[1].length) {
|
if (parsed[1] && parsed[1].length) {
|
||||||
break;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
parsed[1].forEach(function (channel) {
|
parsed[1].forEach(function (channel) {
|
||||||
pins[channel] = true;
|
pins[channel] = true;
|
||||||
});
|
});
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
console.error('invalid message read from store');
|
console.error('invalid message read from store');
|
||||||
|
|||||||
@ -6,9 +6,11 @@ define([
|
|||||||
'/bower_components/alertifyjs/dist/js/alertify.js',
|
'/bower_components/alertifyjs/dist/js/alertify.js',
|
||||||
'/common/clipboard.js',
|
'/common/clipboard.js',
|
||||||
'/customize/application_config.js',
|
'/customize/application_config.js',
|
||||||
|
'/common/pinpad.js', /* TODO
|
||||||
|
load pinpad dynamically only after you know that it will be needed */
|
||||||
|
|
||||||
'/bower_components/jquery/dist/jquery.min.js',
|
'/bower_components/jquery/dist/jquery.min.js',
|
||||||
], function (Config, Messages, Store, Crypto, Alertify, Clipboard, AppConfig) {
|
], function (Config, Messages, Store, Crypto, Alertify, Clipboard, Pinpad, AppConfig) {
|
||||||
/* This file exposes functionality which is specific to Cryptpad, but not to
|
/* This file exposes functionality which is specific to Cryptpad, but not to
|
||||||
any particular pad type. This includes functions for committing metadata
|
any particular pad type. This includes functions for committing metadata
|
||||||
about pads to your local storage for future use and improved usability.
|
about pads to your local storage for future use and improved usability.
|
||||||
@ -25,6 +27,8 @@ define([
|
|||||||
|
|
||||||
var store;
|
var store;
|
||||||
|
|
||||||
|
var PINNING_ENABLED = AppConfig.enablePinning;
|
||||||
|
var rpc;
|
||||||
|
|
||||||
var find = common.find = function (map, path) {
|
var find = common.find = function (map, path) {
|
||||||
return (map && path.reduce(function (p, n) {
|
return (map && path.reduce(function (p, n) {
|
||||||
@ -36,6 +40,11 @@ define([
|
|||||||
if (store) { return store; }
|
if (store) { return store; }
|
||||||
throw new Error("Store is not ready!");
|
throw new Error("Store is not ready!");
|
||||||
};
|
};
|
||||||
|
var getProxy = common.getProxy = function () {
|
||||||
|
if (store && store.getProxy()) {
|
||||||
|
return store.getProxy().proxy;
|
||||||
|
}
|
||||||
|
};
|
||||||
var getNetwork = common.getNetwork = function () {
|
var getNetwork = common.getNetwork = function () {
|
||||||
if (store) {
|
if (store) {
|
||||||
if (store.getProxy() && store.getProxy().info) {
|
if (store.getProxy() && store.getProxy().info) {
|
||||||
@ -168,7 +177,6 @@ define([
|
|||||||
return typeof getUserHash() === "string";
|
return typeof getUserHash() === "string";
|
||||||
};
|
};
|
||||||
|
|
||||||
// var isArray = function (o) { return Object.prototype.toString.call(o) === '[object Array]'; };
|
|
||||||
var isArray = common.isArray = $.isArray;
|
var isArray = common.isArray = $.isArray;
|
||||||
|
|
||||||
var fixHTML = common.fixHTML = function (str) {
|
var fixHTML = common.fixHTML = function (str) {
|
||||||
@ -206,7 +214,7 @@ define([
|
|||||||
return hexArray.join("");
|
return hexArray.join("");
|
||||||
};
|
};
|
||||||
|
|
||||||
var deduplicate = common.deduplicateString = function (array) {
|
var deduplicateString = common.deduplicateString = function (array) {
|
||||||
var a = array.slice();
|
var a = array.slice();
|
||||||
for(var i=0; i<a.length; i++) {
|
for(var i=0; i<a.length; i++) {
|
||||||
for(var j=i+1; j<a.length; j++) {
|
for(var j=i+1; j<a.length; j++) {
|
||||||
@ -216,7 +224,6 @@ define([
|
|||||||
return a;
|
return a;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
var parseHash = common.parseHash = function (hash) {
|
var parseHash = common.parseHash = function (hash) {
|
||||||
var parsed = {};
|
var parsed = {};
|
||||||
if (hash.slice(0,1) !== '/' && hash.length >= 56) {
|
if (hash.slice(0,1) !== '/' && hash.length >= 56) {
|
||||||
@ -289,14 +296,6 @@ define([
|
|||||||
throw new Error("Unable to parse the key");
|
throw new Error("Unable to parse the key");
|
||||||
}
|
}
|
||||||
var version = hashArray[1];
|
var version = hashArray[1];
|
||||||
/*if (version === "1") {
|
|
||||||
secret.channel = base64ToHex(hashArray[2]);
|
|
||||||
secret.key = hashArray[3].replace(/-/g, '/');
|
|
||||||
if (secret.channel.length !== 32 || secret.key.length !== 24) {
|
|
||||||
common.alert("The channel key and/or the encryption key is invalid");
|
|
||||||
throw new Error("The channel key and/or the encryption key is invalid");
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
if (version === "1") {
|
if (version === "1") {
|
||||||
var mode = hashArray[2];
|
var mode = hashArray[2];
|
||||||
if (mode === 'edit') {
|
if (mode === 'edit') {
|
||||||
@ -492,12 +491,6 @@ define([
|
|||||||
var untitledIndex = 1;
|
var untitledIndex = 1;
|
||||||
var name = (Messages.type)[type] + ' - ' + new Date().toString().split(' ').slice(0,4).join(' ');
|
var name = (Messages.type)[type] + ' - ' + new Date().toString().split(' ').slice(0,4).join(' ');
|
||||||
return name;
|
return name;
|
||||||
/*
|
|
||||||
* Pad titles are shared in the document so it does not make sense anymore to avoid duplicates
|
|
||||||
if (isNameAvailable(name, parsed, recentPads)) { return name; }
|
|
||||||
while (!isNameAvailable(name + ' - ' + untitledIndex, parsed, recentPads)) { untitledIndex++; }
|
|
||||||
return name + ' - ' + untitledIndex;
|
|
||||||
*/
|
|
||||||
};
|
};
|
||||||
var isDefaultName = common.isDefaultName = function (parsed, title) {
|
var isDefaultName = common.isDefaultName = function (parsed, title) {
|
||||||
var name = getDefaultName(parsed, []);
|
var name = getDefaultName(parsed, []);
|
||||||
@ -579,6 +572,7 @@ define([
|
|||||||
|
|
||||||
// STORAGE
|
// STORAGE
|
||||||
/* commit a list of pads to localStorage */
|
/* commit a list of pads to localStorage */
|
||||||
|
// TODO integrate pinning if enabled
|
||||||
var setRecentPads = common.setRecentPads = function (pads, cb) {
|
var setRecentPads = common.setRecentPads = function (pads, cb) {
|
||||||
getStore().setDrive(storageKey, pads, function (err, data) {
|
getStore().setDrive(storageKey, pads, function (err, data) {
|
||||||
cb(err, data);
|
cb(err, data);
|
||||||
@ -605,6 +599,7 @@ define([
|
|||||||
|
|
||||||
|
|
||||||
// STORAGE
|
// STORAGE
|
||||||
|
// TODO integrate pinning if enabled
|
||||||
var forgetPad = common.forgetPad = function (href, cb) {
|
var forgetPad = common.forgetPad = function (href, cb) {
|
||||||
var parsed = parsePadUrl(href);
|
var parsed = parsePadUrl(href);
|
||||||
|
|
||||||
@ -686,6 +681,8 @@ define([
|
|||||||
var isNotStrongestStored = common.isNotStrongestStored = function (href, recents) {
|
var isNotStrongestStored = common.isNotStrongestStored = function (href, recents) {
|
||||||
return findStronger(href, recents);
|
return findStronger(href, recents);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO integrate pinning
|
||||||
var setPadTitle = common.setPadTitle = function (name, cb) {
|
var setPadTitle = common.setPadTitle = function (name, cb) {
|
||||||
var href = window.location.href;
|
var href = window.location.href;
|
||||||
var parsed = parsePadUrl(href);
|
var parsed = parsePadUrl(href);
|
||||||
@ -821,12 +818,14 @@ define([
|
|||||||
|
|
||||||
// local name?
|
// local name?
|
||||||
common.ready = function (f) {
|
common.ready = function (f) {
|
||||||
var state = 0;
|
var block = 0;
|
||||||
|
|
||||||
var env = {};
|
var env = {};
|
||||||
|
|
||||||
var cb = function () {
|
var cb = function () {
|
||||||
f(void 0, env);
|
block--;
|
||||||
|
if (!block) {
|
||||||
|
f(void 0, env);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (sessionStorage[newPadNameKey]) {
|
if (sessionStorage[newPadNameKey]) {
|
||||||
@ -841,6 +840,9 @@ define([
|
|||||||
Store.ready(function (err, storeObj) {
|
Store.ready(function (err, storeObj) {
|
||||||
store = common.store = env.store = storeObj;
|
store = common.store = env.store = storeObj;
|
||||||
|
|
||||||
|
var proxy = getProxy();
|
||||||
|
var network = getNetwork();
|
||||||
|
|
||||||
$(function() {
|
$(function() {
|
||||||
// Race condition : if document.body is undefined when alertify.js is loaded, Alertify
|
// Race condition : if document.body is undefined when alertify.js is loaded, Alertify
|
||||||
// won't work. We have to reset it now to make sure it uses a correct "body"
|
// won't work. We have to reset it now to make sure it uses a correct "body"
|
||||||
@ -864,8 +866,34 @@ define([
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (PINNING_ENABLED && isLoggedIn()) {
|
||||||
|
console.log("logged in. pads will be pinned");
|
||||||
|
block++;
|
||||||
|
|
||||||
|
// TODO setTimeout in case rpc doesn't
|
||||||
|
// activate in reasonable time?
|
||||||
|
Pinpad.create(network, proxy, function (e, call) {
|
||||||
|
if (e) {
|
||||||
|
console.error(e);
|
||||||
|
return cb();
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('RPC handshake complete');
|
||||||
|
rpc = env.rpc = call;
|
||||||
|
|
||||||
|
// TODO check if pin list is up to date
|
||||||
|
// if not, reset
|
||||||
|
cb();
|
||||||
|
});
|
||||||
|
} else if (PINNING_ENABLED) {
|
||||||
|
console.log('not logged in. pads will not be pinned');
|
||||||
|
} else {
|
||||||
|
console.log('pinning disabled');
|
||||||
|
}
|
||||||
|
|
||||||
// Everything's ready, continue...
|
// Everything's ready, continue...
|
||||||
if($('#pad-iframe').length) {
|
if($('#pad-iframe').length) {
|
||||||
|
block++;
|
||||||
var $iframe = $('#pad-iframe');
|
var $iframe = $('#pad-iframe');
|
||||||
var iframe = $iframe[0];
|
var iframe = $iframe[0];
|
||||||
var iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
|
var iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
|
||||||
@ -876,6 +904,8 @@ define([
|
|||||||
$iframe.load(cb);
|
$iframe.load(cb);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
block++;
|
||||||
cb();
|
cb();
|
||||||
});
|
});
|
||||||
}, common);
|
}, common);
|
||||||
@ -966,6 +996,7 @@ define([
|
|||||||
/*
|
/*
|
||||||
* Buttons
|
* Buttons
|
||||||
*/
|
*/
|
||||||
|
// TODO integrate pinning if enabled
|
||||||
var renamePad = common.renamePad = function (title, callback) {
|
var renamePad = common.renamePad = function (title, callback) {
|
||||||
if (title === null) { return; }
|
if (title === null) { return; }
|
||||||
|
|
||||||
@ -982,30 +1013,6 @@ define([
|
|||||||
}
|
}
|
||||||
callback(null, title);
|
callback(null, title);
|
||||||
});
|
});
|
||||||
/* Pad titles are shared in the document. We don't check for duplicates anymore.
|
|
||||||
common.causesNamingConflict(title, function (err, conflicts) {
|
|
||||||
if (err) {
|
|
||||||
console.log("Unable to determine if name caused a conflict");
|
|
||||||
console.error(err);
|
|
||||||
callback(err, title);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (conflicts) {
|
|
||||||
common.alert(Messages.renameConflict);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
common.setPadTitle(title, function (err, data) {
|
|
||||||
if (err) {
|
|
||||||
console.log("unable to set pad title");
|
|
||||||
console.log(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
callback(null, title);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var getUserChannelList = common.getUserChannelList = function () {
|
var getUserChannelList = common.getUserChannelList = function () {
|
||||||
@ -1047,6 +1054,10 @@ define([
|
|||||||
return list;
|
return list;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var getCanonicalChannelList = common.getCanonicalChannelList = function () {
|
||||||
|
return deduplicateString(getUserChannelList()).sort();
|
||||||
|
};
|
||||||
|
|
||||||
var createButton = common.createButton = function (type, rightside, data, callback) {
|
var createButton = common.createButton = function (type, rightside, data, callback) {
|
||||||
var button;
|
var button;
|
||||||
var size = "17px";
|
var size = "17px";
|
||||||
|
|||||||
@ -1,69 +1,12 @@
|
|||||||
define([
|
define([
|
||||||
'/common/cryptpad-common.js',
|
|
||||||
'/common/rpc.js',
|
'/common/rpc.js',
|
||||||
|
|
||||||
'/bower_components/tweetnacl/nacl-fast.min.js'
|
'/bower_components/tweetnacl/nacl-fast.min.js'
|
||||||
], function (Cryptpad, Rpc) {
|
], function (Rpc) {
|
||||||
var Nacl = window.nacl;
|
var Nacl = window.nacl;
|
||||||
|
|
||||||
var uniqueChannelList = function (list) {
|
var create = function (network, proxy, cb) {
|
||||||
list = list || Cryptpad.getUserChannelList();
|
if (!network) { return void cb('INVALID_NETWORK'); }
|
||||||
return Cryptpad.deduplicateString(list).sort();
|
if (!proxy) { return void cb('INVALID_PROXY'); }
|
||||||
};
|
|
||||||
|
|
||||||
var localChannelsHash = function (fileList) {
|
|
||||||
var uniqueList = uniqueChannelList(fileList);
|
|
||||||
var hash = Nacl.util.encodeBase64(Nacl
|
|
||||||
.hash(Nacl.util.decodeUTF8( JSON.stringify(uniqueList) )));
|
|
||||||
return hash;
|
|
||||||
};
|
|
||||||
|
|
||||||
var getServerHash = function (rpc, edPublic, cb) {
|
|
||||||
rpc.send('GET_HASH', edPublic, function (e, hash) {
|
|
||||||
cb(e, hash[0]);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var getFileSize = function (rpc, file, cb) {
|
|
||||||
rpc.send('GET_FILE_SIZE', file, cb);
|
|
||||||
};
|
|
||||||
|
|
||||||
var getFileListSize = function (rpc, cb) {
|
|
||||||
return rpc.send('GET_TOTAL_SIZE', undefined, cb);
|
|
||||||
};
|
|
||||||
|
|
||||||
var pinChannel = function (rpc, channel, cb) {
|
|
||||||
rpc.send('PIN', channel, cb);
|
|
||||||
};
|
|
||||||
|
|
||||||
var unpinChannel = function (rpc, channel, cb) {
|
|
||||||
rpc.send('UNPIN', channel, cb);
|
|
||||||
};
|
|
||||||
|
|
||||||
var reset = function (rpc, cb) {
|
|
||||||
var list = uniqueChannelList();
|
|
||||||
rpc.send('RESET', list, cb);
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
1. every time you want to pin or unpid a pad you send a message to the server
|
|
||||||
2. the server sends back a hash of the sorted list of your pinned pads
|
|
||||||
3. you hash your sorted list of pinned pads that you should have according to your drive
|
|
||||||
4. compare them, if same
|
|
||||||
AWESOME
|
|
||||||
if they are not
|
|
||||||
UNPIN all, send all
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Don't use create until Cryptpad is ready
|
|
||||||
// (use Cryptpad.ready)
|
|
||||||
var create = function (cb) {
|
|
||||||
// you will need to communicate with the server
|
|
||||||
// use an already established
|
|
||||||
var network = Cryptpad.getNetwork();
|
|
||||||
|
|
||||||
// your user proxy contains credentials you will need to make RPC calls
|
|
||||||
var proxy = Cryptpad.getStore().getProxy().proxy;
|
|
||||||
|
|
||||||
var edPrivate = proxy.edPrivate;
|
var edPrivate = proxy.edPrivate;
|
||||||
var edPublic = proxy.edPublic;
|
var edPublic = proxy.edPublic;
|
||||||
@ -74,32 +17,52 @@ define([
|
|||||||
if (e) { return void cb(e); }
|
if (e) { return void cb(e); }
|
||||||
|
|
||||||
var exp = {};
|
var exp = {};
|
||||||
|
|
||||||
|
// expose the supplied publicKey as an identifier
|
||||||
exp.publicKey = edPublic;
|
exp.publicKey = edPublic;
|
||||||
|
|
||||||
|
// expose the RPC module's raw 'send' command
|
||||||
exp.send = rpc.send;
|
exp.send = rpc.send;
|
||||||
|
|
||||||
exp.uniqueChannelList = uniqueChannelList;
|
// you can ask the server to pin a particular channel for you
|
||||||
|
|
||||||
exp.getFileSize = function (file, cb) {
|
|
||||||
getFileSize(rpc, file, cb);
|
|
||||||
};
|
|
||||||
exp.getFileListSize = function (cb) {
|
|
||||||
getFileListSize(rpc, cb);
|
|
||||||
};
|
|
||||||
exp.getServerHash = function (cb) {
|
|
||||||
getServerHash(rpc, edPublic, cb);
|
|
||||||
};
|
|
||||||
|
|
||||||
exp.pin = function (channel, cb) {
|
exp.pin = function (channel, cb) {
|
||||||
pinChannel(rpc, channel, cb);
|
rpc.send('PIN', channel, cb);
|
||||||
};
|
|
||||||
exp.unpin = function (channel, cb) {
|
|
||||||
unpinChannel(rpc, channel, cb);
|
|
||||||
};
|
|
||||||
exp.reset = function (cb) {
|
|
||||||
reset(rpc, cb);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
exp.localChannelsHash = localChannelsHash;
|
// you can also ask to unpin a particular channel
|
||||||
|
exp.unpin = function (channel, cb) {
|
||||||
|
rpc.send('UNPIN', channel, cb);
|
||||||
|
};
|
||||||
|
|
||||||
|
// This implementation must match that on the server
|
||||||
|
// it's used for a checksum
|
||||||
|
exp.hashChannelList = function (list) {
|
||||||
|
return Nacl.util.encodeBase64(Nacl.hash(Nacl.util
|
||||||
|
.decodeUTF8(JSON.stringify(list))));
|
||||||
|
};
|
||||||
|
|
||||||
|
// ask the server what it thinks your hash is
|
||||||
|
exp.getServerHash = function (cb) {
|
||||||
|
rpc.send('GET_HASH', edPublic, function (e, hash) {
|
||||||
|
cb(e, hash[0]);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// if local and remote hashes don't match, send a reset
|
||||||
|
exp.reset = function (list, cb) {
|
||||||
|
rpc.send('RESET', list, cb);
|
||||||
|
};
|
||||||
|
|
||||||
|
// get the total stored size of a channel's patches (in bytes)
|
||||||
|
exp.getFileSize = function (file, cb) {
|
||||||
|
rpc.send('GET_FILE_SIZE', file, cb);
|
||||||
|
};
|
||||||
|
|
||||||
|
// get the combined size of all channels (in bytes) for all the
|
||||||
|
// channels which the server has pinned for your publicKey
|
||||||
|
exp.getFileListSize = function (cb) {
|
||||||
|
rpc.send('GET_TOTAL_SIZE', undefined, cb);
|
||||||
|
};
|
||||||
|
|
||||||
cb(e, exp);
|
cb(e, exp);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -53,7 +53,8 @@ types of messages:
|
|||||||
var pending = ctx.pending[txid];
|
var pending = ctx.pending[txid];
|
||||||
|
|
||||||
if (!(parsed && parsed.slice)) {
|
if (!(parsed && parsed.slice)) {
|
||||||
return void console.error('MALFORMED_RPC_RESPONSE');
|
// RPC responses are arrays. this message isn't meant for us.
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var response = parsed.slice(2);
|
var response = parsed.slice(2);
|
||||||
@ -70,9 +71,8 @@ types of messages:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
pending(void 0, response);
|
pending(void 0, response);
|
||||||
} else {
|
|
||||||
console.log("No callback provided");
|
|
||||||
}
|
}
|
||||||
|
//else { console.log("No callback provided"); }
|
||||||
};
|
};
|
||||||
|
|
||||||
var create = function (network, edPrivateKey, edPublicKey, cb) {
|
var create = function (network, edPrivateKey, edPublicKey, cb) {
|
||||||
|
|||||||
@ -9,46 +9,16 @@ define([
|
|||||||
Cryptpad: Cryptpad,
|
Cryptpad: Cryptpad,
|
||||||
};
|
};
|
||||||
|
|
||||||
var then = function (call) {
|
|
||||||
call.getFileSize('26f014b2ab959418605ea37a6785f317', function (e, msg) {
|
|
||||||
if (e) {
|
|
||||||
if (e === 'ENOENT') { return; }
|
|
||||||
return void console.error(e);
|
|
||||||
}
|
|
||||||
console.error("EXPECTED ENOENT");
|
|
||||||
console.log(msg);
|
|
||||||
});
|
|
||||||
|
|
||||||
call.getFileSize('pewpew', function (e, msg) {
|
|
||||||
if (e) {
|
|
||||||
if (e === 'INVALID_CHAN') { return; }
|
|
||||||
return void console.error(e);
|
|
||||||
}
|
|
||||||
console.log(msg);
|
|
||||||
});
|
|
||||||
|
|
||||||
var list = Cryptpad.getUserChannelList();
|
|
||||||
if (list.length) {
|
|
||||||
call.getFileSize(list[0], function (e, msg) {
|
|
||||||
if (e) {
|
|
||||||
return void console.error(e);
|
|
||||||
}
|
|
||||||
console.log(msg);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
call.getServerHash(function (e, hash) {
|
|
||||||
if (e) { return void console.error(e); }
|
|
||||||
console.log("the server believes your user hash is [%s]", hash);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var synchronize = function (call) {
|
var synchronize = function (call) {
|
||||||
var localHash = call.localChannelsHash();
|
// provide a sorted list of unique channels
|
||||||
|
var list = Cryptpad.getCanonicalChannelList();
|
||||||
|
|
||||||
|
var localHash = call.hashChannelList(list);
|
||||||
var serverHash;
|
var serverHash;
|
||||||
|
|
||||||
call.getFileListSize(function (e, bytes) {
|
call.getFileListSize(function (e, bytes) {
|
||||||
if (e) { return void console.error(e); }
|
if (e) { return void console.error(e); }
|
||||||
console.log("%s total bytes used", bytes);
|
console.log("total %sK bytes used", bytes / 1000);
|
||||||
});
|
});
|
||||||
|
|
||||||
call.getServerHash(function (e, hash) {
|
call.getServerHash(function (e, hash) {
|
||||||
@ -59,26 +29,22 @@ define([
|
|||||||
return console.log("all your pads are pinned. There is nothing to do");
|
return console.log("all your pads are pinned. There is nothing to do");
|
||||||
}
|
}
|
||||||
|
|
||||||
call.reset(function (e, response) {
|
call.reset(list, function (e, response) {
|
||||||
if (e) { return console.error(e); }
|
if (e) { return console.error(e); }
|
||||||
else {
|
else {
|
||||||
return console.log('reset pin list. new hash is [%s]', response);
|
return console.log('reset pin list. new hash is [%s]', response);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/*
|
|
||||||
console.log(JSON.stringify({
|
|
||||||
local: localHash,
|
|
||||||
remote: serverHash,
|
|
||||||
}, null, 2));*/
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
$(function () {
|
$(function () {
|
||||||
Cryptpad.ready(function (err, env) {
|
Cryptpad.ready(function (err, env) {
|
||||||
Pinpad.create(function (e, call) {
|
var network = Cryptpad.getNetwork();
|
||||||
|
var proxy = Cryptpad.getStore().getProxy().proxy;
|
||||||
|
|
||||||
|
Pinpad.create(network, proxy, function (e, call) {
|
||||||
if (e) { return void console.error(e); }
|
if (e) { return void console.error(e); }
|
||||||
// then(call);
|
|
||||||
synchronize(call);
|
synchronize(call);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -11,82 +11,7 @@
|
|||||||
id="favicon" />
|
id="favicon" />
|
||||||
<link rel="stylesheet" href="/bower_components/components-font-awesome/css/font-awesome.min.css">
|
<link rel="stylesheet" href="/bower_components/components-font-awesome/css/font-awesome.min.css">
|
||||||
<link rel="stylesheet" href="/customize/main.css" />
|
<link rel="stylesheet" href="/customize/main.css" />
|
||||||
<style>
|
<link rel="stylesheet" href="whiteboard.css" />
|
||||||
html, body{
|
|
||||||
padding: 0px;
|
|
||||||
margin: 0px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
body {
|
|
||||||
display: flex;
|
|
||||||
flex-flow: column;
|
|
||||||
height: 100%;
|
|
||||||
background: url('/customize/bg3.jpg') no-repeat center center;
|
|
||||||
background-size: cover;
|
|
||||||
background-position: center;
|
|
||||||
}
|
|
||||||
#canvas-area {
|
|
||||||
flex: 1;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
.canvas-container {
|
|
||||||
border: 5px solid black;
|
|
||||||
margin: auto;
|
|
||||||
background: white;
|
|
||||||
}
|
|
||||||
#clear, #toggleDraw {
|
|
||||||
display: inline;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
#colors {
|
|
||||||
z-index: 100;
|
|
||||||
border: 3px solid black;
|
|
||||||
padding: 5px;
|
|
||||||
vertical-align: top;
|
|
||||||
background: white;
|
|
||||||
}
|
|
||||||
.selected {
|
|
||||||
margin-left: 20px;
|
|
||||||
display: inline-block;
|
|
||||||
height: 100px;
|
|
||||||
}
|
|
||||||
.selected img {
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
#copy {
|
|
||||||
padding-left: 75px;
|
|
||||||
}
|
|
||||||
span.palette-color {
|
|
||||||
height: 4vw;
|
|
||||||
width: 4vw;
|
|
||||||
display: inline-block;
|
|
||||||
margin: 5px;
|
|
||||||
border: 2px solid black;
|
|
||||||
vertical-align: top;
|
|
||||||
}
|
|
||||||
#controls {
|
|
||||||
display: block;
|
|
||||||
position: relative;
|
|
||||||
border: 3px solid black;
|
|
||||||
background: white;
|
|
||||||
height: 100px;
|
|
||||||
line-height: 100px;
|
|
||||||
}
|
|
||||||
#width, #colors {
|
|
||||||
position: relative;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
#color-picker {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
#pickers {
|
|
||||||
visibility: hidden;
|
|
||||||
position: absolute;
|
|
||||||
width: 0;
|
|
||||||
height: 0;
|
|
||||||
z-index: -5;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="toolbar" class="toolbar-container"></div>
|
<div id="toolbar" class="toolbar-container"></div>
|
||||||
|
|||||||
@ -106,10 +106,9 @@ define([
|
|||||||
var $picker = $('<input>', {
|
var $picker = $('<input>', {
|
||||||
type: 'color',
|
type: 'color',
|
||||||
value: '#FFFFFF',
|
value: '#FFFFFF',
|
||||||
})
|
})
|
||||||
.css({
|
// TODO confirm that this is safe to remove
|
||||||
visibility: 'hidden'
|
//.css({ visibility: 'hidden' })
|
||||||
})
|
|
||||||
.on('change', function () {
|
.on('change', function () {
|
||||||
var color = this.value;
|
var color = this.value;
|
||||||
cb(color);
|
cb(color);
|
||||||
@ -242,6 +241,7 @@ define([
|
|||||||
};
|
};
|
||||||
|
|
||||||
var addColorToPalette = function (color, i) {
|
var addColorToPalette = function (color, i) {
|
||||||
|
if (readOnly) { return; }
|
||||||
var $color = $('<span>', {
|
var $color = $('<span>', {
|
||||||
'class': 'palette-color',
|
'class': 'palette-color',
|
||||||
})
|
})
|
||||||
@ -252,7 +252,6 @@ define([
|
|||||||
var c = rgb2hex($color.css('background-color'));
|
var c = rgb2hex($color.css('background-color'));
|
||||||
setColor(c);
|
setColor(c);
|
||||||
})
|
})
|
||||||
// FIXME double click doesn't seem to work in chromium currently
|
|
||||||
.on('dblclick', function (e) {
|
.on('dblclick', function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
pickColor(rgb2hex($color.css('background-color')), function (c) {
|
pickColor(rgb2hex($color.css('background-color')), function (c) {
|
||||||
@ -263,19 +262,17 @@ define([
|
|||||||
config.onLocal();
|
config.onLocal();
|
||||||
setColor(c);
|
setColor(c);
|
||||||
});
|
});
|
||||||
// TODO commit chosen color to pad metadata:
|
|
||||||
// json.metadata.palette[i]
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$colors.append($color);
|
$colors.append($color);
|
||||||
};
|
};
|
||||||
palette.forEach(addColorToPalette);
|
|
||||||
|
|
||||||
var updatePalette = function (newPalette) {
|
var updatePalette = function (newPalette) {
|
||||||
palette = newPalette;
|
palette = newPalette;
|
||||||
$colors.html(' ');
|
$colors.html('<div class="hidden"> </div>');
|
||||||
palette.forEach(addColorToPalette);
|
palette.forEach(addColorToPalette);
|
||||||
};
|
};
|
||||||
|
updatePalette(palette);
|
||||||
|
|
||||||
var suggestName = function (fallback) {
|
var suggestName = function (fallback) {
|
||||||
if (document.title === defaultName) {
|
if (document.title === defaultName) {
|
||||||
|
|||||||
82
www/whiteboard/whiteboard.css
Normal file
82
www/whiteboard/whiteboard.css
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
padding: 0px;
|
||||||
|
margin: 0px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column;
|
||||||
|
height: 100%;
|
||||||
|
background: url('/customize/bg3.jpg') no-repeat center center;
|
||||||
|
background-size: cover;
|
||||||
|
background-position: center;
|
||||||
|
}
|
||||||
|
#canvas-area {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
.canvas-container {
|
||||||
|
border: 1px solid black;
|
||||||
|
margin: auto;
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
#controls {
|
||||||
|
display: block;
|
||||||
|
position: relative;
|
||||||
|
border-top: 1px solid black;
|
||||||
|
background: white;
|
||||||
|
height: 100px;
|
||||||
|
line-height: 100px;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
}
|
||||||
|
#controls #width {
|
||||||
|
position: relative;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
#controls #clear,
|
||||||
|
#controls #toggleDraw {
|
||||||
|
display: inline;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
#controls .selected {
|
||||||
|
margin-left: 20px;
|
||||||
|
display: inline-block;
|
||||||
|
height: 135px;
|
||||||
|
width: 135px;
|
||||||
|
z-index: 9001;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
#controls .selected img {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
/* Colors */
|
||||||
|
#colors {
|
||||||
|
position: relative;
|
||||||
|
vertical-align: middle;
|
||||||
|
z-index: 100;
|
||||||
|
background: white;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
#colors span.palette-color {
|
||||||
|
height: 4vw;
|
||||||
|
width: 4vw;
|
||||||
|
display: inline-block;
|
||||||
|
margin: 5px;
|
||||||
|
border: 1px solid black;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
#color-picker {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
#pickers {
|
||||||
|
visibility: hidden;
|
||||||
|
position: absolute;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
z-index: -5;
|
||||||
|
}
|
||||||
97
www/whiteboard/whiteboard.less
Normal file
97
www/whiteboard/whiteboard.less
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
.middle () {
|
||||||
|
position: relative;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
html, body{
|
||||||
|
padding: 0px;
|
||||||
|
margin: 0px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column;
|
||||||
|
height: 100%;
|
||||||
|
background: url('/customize/bg3.jpg') no-repeat center center;
|
||||||
|
background-size: cover;
|
||||||
|
background-position: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
// created in the html
|
||||||
|
#canvas-area {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
// created by fabricjs. styled so defaults don't break anything
|
||||||
|
.canvas-container {
|
||||||
|
border: 1px solid black;
|
||||||
|
margin: auto;
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
// contains user tools
|
||||||
|
#controls {
|
||||||
|
display: block;
|
||||||
|
position: relative;
|
||||||
|
border-top: 1px solid black;
|
||||||
|
background: white;
|
||||||
|
height: 100px;
|
||||||
|
line-height: 100px;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
|
||||||
|
#width {
|
||||||
|
.middle;
|
||||||
|
}
|
||||||
|
#clear, #toggleDraw {
|
||||||
|
display: inline;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
.selected {
|
||||||
|
margin-left: 20px;
|
||||||
|
display: inline-block;
|
||||||
|
height: 135px;
|
||||||
|
width: 135px;
|
||||||
|
z-index: 9001;
|
||||||
|
text-align: center;
|
||||||
|
img {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Colors */
|
||||||
|
#colors {
|
||||||
|
.middle;
|
||||||
|
z-index: 100;
|
||||||
|
background: white;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
span.palette-color {
|
||||||
|
height: 4vw;
|
||||||
|
width: 4vw;
|
||||||
|
display: inline-block;
|
||||||
|
margin: 5px;
|
||||||
|
border: 1px solid black;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// used in the toolbar if supported
|
||||||
|
#color-picker {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
// input[type=color] must exist in the dom to work correctly
|
||||||
|
// styled so that they don't break layouts
|
||||||
|
#pickers {
|
||||||
|
visibility: hidden;
|
||||||
|
position: absolute;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
z-index: -5;
|
||||||
|
}
|
||||||
|
|
||||||
Loading…
x
Reference in New Issue
Block a user