Merge branch 'staging' into get_contacts
This commit is contained in:
@@ -159,6 +159,9 @@
|
|||||||
margin-bottom: @alertify_padding-base;
|
margin-bottom: @alertify_padding-base;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.alertify-tabs {
|
.alertify-tabs {
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
@@ -222,14 +225,22 @@
|
|||||||
background-color: @alertify-input-fg;
|
background-color: @alertify-input-fg;
|
||||||
color: @cryptpad_text_col;
|
color: @cryptpad_text_col;
|
||||||
border: 1px solid @alertify-input-bg;
|
border: 1px solid @alertify-input-bg;
|
||||||
margin-bottom: 15px;
|
margin-bottom: @alertify_padding-base;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
font-size: 100%;
|
font-size: 100%;
|
||||||
padding: @alertify_padding-base;
|
padding: @alertify_padding-base;
|
||||||
&[readonly] {
|
&[readonly] {
|
||||||
background-color: @alertify-light-bg;
|
background-color: @alertify-light-bg;
|
||||||
color: @cryptpad_text_col;
|
color: @cryptpad_text_col;
|
||||||
border-color: @alertify-input-fg;
|
border-color: @alertify-light-bg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 8px;
|
||||||
|
&[readonly] {
|
||||||
|
resize: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -509,5 +520,33 @@
|
|||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Bootstrap Alerts
|
||||||
|
.alert {
|
||||||
|
margin: 0px 0px @alertify_padding-base 0px;
|
||||||
|
font-size: 12px;
|
||||||
|
padding: 5px;
|
||||||
|
border-radius: 0px;
|
||||||
|
i {
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
&.alert-primary {
|
||||||
|
background-color: @alertify-base;
|
||||||
|
color: @alertify-fg;
|
||||||
|
border-color: @alertify-fg;
|
||||||
|
a {
|
||||||
|
color: @alertify-fg;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.dismissable {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
span.fa-times {
|
||||||
|
font-size: @colortheme_app-font-size;
|
||||||
|
margin-left: 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
@import (reference) "./tools.less";
|
@import (reference) "./tools.less";
|
||||||
|
@import (reference) "./colortheme-all.less";
|
||||||
.avatar_vars(
|
.avatar_vars(
|
||||||
@width: 30px
|
@width: 30px
|
||||||
) {
|
) {
|
||||||
@avatar-width: @width;
|
@avatar-width: @width;
|
||||||
@avatar-font-size: @width / 1.2;
|
@avatar-font-size: @width / 1.2;
|
||||||
|
@avatar-default-bg: #D9D8D8;
|
||||||
|
@avatar-default-fg: darken(@avatar-default-bg, 40%);
|
||||||
}
|
}
|
||||||
.avatar_main(@width: 30px) {
|
.avatar_main(@width: 30px) {
|
||||||
--LessLoader_require: LessLoader_currentFile();
|
--LessLoader_require: LessLoader_currentFile();
|
||||||
@@ -30,16 +33,16 @@
|
|||||||
|
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
border-radius: 4px;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
box-sizing: content-box;
|
box-sizing: content-box;
|
||||||
}
|
}
|
||||||
.cp-avatar-default {
|
.cp-avatar-default {
|
||||||
.tools_unselectable();
|
.tools_unselectable();
|
||||||
background: white;
|
background: @avatar-default-bg;
|
||||||
color: black;
|
color: @avatar-default-fg;
|
||||||
font-size: @avatar-font-size;
|
font-size: @avatar-font-size;
|
||||||
font-size: var(--avatar-font-size);
|
font-size: var(--avatar-font-size);
|
||||||
|
text-transform: capitalize;
|
||||||
}
|
}
|
||||||
media-tag {
|
media-tag {
|
||||||
min-height: @avatar-width;
|
min-height: @avatar-width;
|
||||||
|
|||||||
@@ -1,12 +1,16 @@
|
|||||||
@import (reference) "./colortheme-all.less";
|
@import (reference) "./colortheme-all.less";
|
||||||
|
@import (reference) "./variables.less";
|
||||||
.modals-ui-elements_main() {
|
.modals-ui-elements_main() {
|
||||||
--LessLoader_require: LessLoader_currentFile();
|
--LessLoader_require: LessLoader_currentFile();
|
||||||
}
|
}
|
||||||
& {
|
& {
|
||||||
|
.cp-spacer {
|
||||||
|
height: @variables_padding;
|
||||||
|
}
|
||||||
// Share modal
|
// Share modal
|
||||||
.msg.cp-inline-radio-group {
|
.msg.cp-inline-radio-group {
|
||||||
overflow: unset !important;
|
overflow: unset !important;
|
||||||
|
padding: 0px @variables_padding;
|
||||||
.radio-group {
|
.radio-group {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
@import (reference) "./colortheme-all.less";
|
||||||
.password_main() {
|
.password_main() {
|
||||||
--LessLoader_require: LessLoader_currentFile();
|
--LessLoader_require: LessLoader_currentFile();
|
||||||
}
|
}
|
||||||
@@ -17,7 +18,7 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: rgba(0,0,0,0.1);
|
color: darken(@colortheme_alertify-primary, 10%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,16 +6,18 @@
|
|||||||
--LessLoader_require: LessLoader_currentFile();
|
--LessLoader_require: LessLoader_currentFile();
|
||||||
};
|
};
|
||||||
& {
|
& {
|
||||||
|
|
||||||
.cp-usergrid-container {
|
.cp-usergrid-container {
|
||||||
|
margin-bottom: 12px !important; // even when last child of .msg
|
||||||
.cp-usergrid-grid {
|
.cp-usergrid-grid {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
margin: -3px;
|
||||||
margin-bottom: 6px;
|
margin-bottom: 6px;
|
||||||
}
|
max-height: 130px;
|
||||||
&:not(.large) {
|
overflow-y: auto;
|
||||||
.cp-usergrid-grid {
|
@media screen and (max-height: 515px) {
|
||||||
margin: -3px;
|
max-height: unset; // remove double scrollbar
|
||||||
margin-bottom: 6px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&.cp-usergrid-empty {
|
&.cp-usergrid-empty {
|
||||||
@@ -28,17 +30,22 @@
|
|||||||
input {
|
input {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
margin: 0;
|
||||||
margin-bottom: 0 !important;
|
margin-bottom: 0 !important;
|
||||||
|
height: 38px;
|
||||||
&::placeholder { /* Chrome, Firefox, Opera, Safari 10.1+ */
|
&::placeholder { /* Chrome, Firefox, Opera, Safari 10.1+ */
|
||||||
color: @cryptpad_color_grey;
|
color: @cryptpad_color_grey;
|
||||||
opacity: 1; /* Firefox */
|
opacity: 1; /* Firefox */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
margin-bottom: 15px;
|
margin-bottom: 10px;
|
||||||
&:empty {
|
&:empty {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
button:last-child {
|
||||||
|
margin-right: 0px !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.cp-usergrid-user {
|
.cp-usergrid-user {
|
||||||
width: 70px;
|
width: 70px;
|
||||||
@@ -58,33 +65,48 @@
|
|||||||
background-color: @colortheme_alertify-primary;
|
background-color: @colortheme_alertify-primary;
|
||||||
color: @colortheme_alertify-primary-text;
|
color: @colortheme_alertify-primary-text;
|
||||||
order: -1 !important;
|
order: -1 !important;
|
||||||
|
.cp-usergrid-avatar {
|
||||||
|
media-tag, .cp-avatar-default {
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.cp-usergrid-user-avatar {
|
.cp-usergrid-user-avatar {
|
||||||
min-height: 40px;
|
min-height: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cp-usergrid-user-name {
|
.cp-usergrid-user-name {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
line-height: 18px;
|
line-height: 20px;
|
||||||
|
flex: 1;
|
||||||
}
|
}
|
||||||
border: 1px solid @colortheme_alertify-primary;
|
|
||||||
|
|
||||||
&:not(.large) {
|
&:not(.large) {
|
||||||
.avatar_main(40px);
|
.avatar_main(40px);
|
||||||
}
|
}
|
||||||
&.large {
|
&.large {
|
||||||
.avatar_main(25px);
|
.avatar_main(25px);
|
||||||
width: 140px;
|
width: 145px;
|
||||||
height: 35px;
|
height: 35px;
|
||||||
flex-flow: row;
|
flex-flow: row;
|
||||||
margin: 0;
|
margin: 3px;
|
||||||
margin-right: 15px;
|
flex-basis: calc(33.3333333% - 6px);
|
||||||
margin-bottom: 1px;
|
flex-shrink: 1;
|
||||||
&:nth-child(3n) {
|
min-width: 0;
|
||||||
margin-right: 0;
|
.cp-usergrid-user-name {
|
||||||
|
margin-left: 5px;
|
||||||
|
text-align: left;
|
||||||
|
line-height: 150%;
|
||||||
|
color: @cryptpad_text_col;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.cp-selected {
|
||||||
|
.cp-usergrid-user-name {
|
||||||
|
color: @colortheme_alertify-primary-text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ If the result of IO or computation is requested while an identical request
|
|||||||
is already in progress, wait until the first one completes and provide its
|
is already in progress, wait until the first one completes and provide its
|
||||||
result to every routine that requested it.
|
result to every routine that requested it.
|
||||||
|
|
||||||
|
Asynchrony is guaranteed.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
Provide:
|
Provide:
|
||||||
@@ -51,11 +53,12 @@ module.exports = function (/* task */) {
|
|||||||
var args = Array.prototype.slice.call(arguments);
|
var args = Array.prototype.slice.call(arguments);
|
||||||
|
|
||||||
//if (map[id] && map[id].length > 1) { console.log("BATCH-READ DID ITS JOB for [%s][%s]", task, id); }
|
//if (map[id] && map[id].length > 1) { console.log("BATCH-READ DID ITS JOB for [%s][%s]", task, id); }
|
||||||
|
setTimeout(function () {
|
||||||
map[id].forEach(function (h) {
|
map[id].forEach(function (h) {
|
||||||
h.apply(null, args);
|
h.apply(null, args);
|
||||||
|
});
|
||||||
|
delete map[id];
|
||||||
});
|
});
|
||||||
delete map[id];
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ q(id, function (next) {
|
|||||||
// whatever you need to do....
|
// whatever you need to do....
|
||||||
|
|
||||||
// when you're done
|
// when you're done
|
||||||
next();
|
next(); // guaranteed to be asynchronous :D
|
||||||
});
|
});
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -16,9 +16,11 @@ module.exports = function () {
|
|||||||
var map = {};
|
var map = {};
|
||||||
|
|
||||||
var next = function (id) {
|
var next = function (id) {
|
||||||
if (map[id] && map[id].length === 0) { return void delete map[id]; }
|
setTimeout(function () {
|
||||||
var task = map[id].shift();
|
if (map[id] && map[id].length === 0) { return void delete map[id]; }
|
||||||
task(fix1(next, id));
|
var task = map[id].shift();
|
||||||
|
task(fix1(next, id));
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return function (id, task) {
|
return function (id, task) {
|
||||||
|
|||||||
@@ -1,12 +1,17 @@
|
|||||||
define([
|
define([
|
||||||
'jquery',
|
'jquery',
|
||||||
'/common/cryptpad-common.js',
|
'/common/cryptget.js',
|
||||||
|
'/common/pinpad.js',
|
||||||
'/common/common-constants.js',
|
'/common/common-constants.js',
|
||||||
'/common/outer/local-store.js',
|
'/common/outer/local-store.js',
|
||||||
|
'/common/outer/login-block.js',
|
||||||
|
'/common/outer/network-config.js',
|
||||||
|
'/customize/login.js',
|
||||||
'/common/test.js',
|
'/common/test.js',
|
||||||
'/bower_components/nthen/index.js',
|
'/bower_components/nthen/index.js',
|
||||||
|
'/bower_components/netflux-websocket/netflux-client.js',
|
||||||
'/bower_components/tweetnacl/nacl-fast.min.js'
|
'/bower_components/tweetnacl/nacl-fast.min.js'
|
||||||
], function ($, Cryptpad, Constants, LocalStore, Test, nThen) {
|
], function ($, Crypt, Pinpad, Constants, LocalStore, Block, NetConfig, Login, Test, nThen, Netflux) {
|
||||||
var Nacl = window.nacl;
|
var Nacl = window.nacl;
|
||||||
|
|
||||||
var signMsg = function (msg, privKey) {
|
var signMsg = function (msg, privKey) {
|
||||||
@@ -27,9 +32,57 @@ define([
|
|||||||
sessionStorage[Constants.userHashKey];
|
sessionStorage[Constants.userHashKey];
|
||||||
|
|
||||||
var proxy;
|
var proxy;
|
||||||
|
var rpc;
|
||||||
|
var network;
|
||||||
|
var rpcError;
|
||||||
|
|
||||||
|
var loadProxy = function (hash) {
|
||||||
|
nThen(function (waitFor) {
|
||||||
|
var wsUrl = NetConfig.getWebsocketURL();
|
||||||
|
var w = waitFor();
|
||||||
|
Netflux.connect(wsUrl).then(function (_network) {
|
||||||
|
network = _network;
|
||||||
|
w();
|
||||||
|
}, function (err) {
|
||||||
|
rpcError = err;
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
}).nThen(function (waitFor) {
|
||||||
|
Crypt.get(hash, waitFor(function (err, val) {
|
||||||
|
if (err) {
|
||||||
|
waitFor.abort();
|
||||||
|
console.error(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
var parsed = JSON.parse(val);
|
||||||
|
proxy = parsed;
|
||||||
|
} catch (e) {
|
||||||
|
console.log("Can't parse user drive", e);
|
||||||
|
}
|
||||||
|
}), {
|
||||||
|
network: network
|
||||||
|
});
|
||||||
|
}).nThen(function (waitFor) {
|
||||||
|
if (!network) { return void waitFor.abort(); }
|
||||||
|
Pinpad.create(network, proxy, waitFor(function (e, call) {
|
||||||
|
if (e) {
|
||||||
|
rpcError = e;
|
||||||
|
return void waitFor.abort();
|
||||||
|
}
|
||||||
|
rpc = call;
|
||||||
|
}));
|
||||||
|
}).nThen(function () {
|
||||||
|
Test(function () {
|
||||||
|
// This is only here to maybe trigger an error.
|
||||||
|
window.drive = proxy['drive'];
|
||||||
|
Test.passed();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
var whenReady = function (cb) {
|
var whenReady = function (cb) {
|
||||||
if (proxy) { return void cb(); }
|
if (proxy && (rpc || rpcError)) { return void cb(); }
|
||||||
console.log('CryptPad not ready...');
|
console.log('CryptPad not ready...');
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
whenReady(cb);
|
whenReady(cb);
|
||||||
@@ -45,6 +98,17 @@ define([
|
|||||||
console.log('CP receiving', data);
|
console.log('CP receiving', data);
|
||||||
if (data.cmd === 'PING') {
|
if (data.cmd === 'PING') {
|
||||||
ret.res = 'PONG';
|
ret.res = 'PONG';
|
||||||
|
} else if (data.cmd === 'LOGIN') {
|
||||||
|
Login.loginOrRegister(data.data.name, data.data.password, false, false, function (err) {
|
||||||
|
if (err) {
|
||||||
|
ret.error = 'LOGIN_ERROR';
|
||||||
|
srcWindow.postMessage(JSON.stringify(ret), domain);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
loadProxy(LocalStore.getUserHash());
|
||||||
|
srcWindow.postMessage(JSON.stringify(ret), domain);
|
||||||
|
});
|
||||||
|
return;
|
||||||
} else if (data.cmd === 'SIGN') {
|
} else if (data.cmd === 'SIGN') {
|
||||||
if (!AUTHORIZED_DOMAINS.filter(function (x) { return x.test(domain); }).length) {
|
if (!AUTHORIZED_DOMAINS.filter(function (x) { return x.test(domain); }).length) {
|
||||||
ret.error = "UNAUTH_DOMAIN";
|
ret.error = "UNAUTH_DOMAIN";
|
||||||
@@ -63,7 +127,16 @@ define([
|
|||||||
}
|
}
|
||||||
} else if (data.cmd === 'UPDATE_LIMIT') {
|
} else if (data.cmd === 'UPDATE_LIMIT') {
|
||||||
return void whenReady(function () {
|
return void whenReady(function () {
|
||||||
Cryptpad.updatePinLimit(function (e, limit, plan, note) {
|
if (rpcError) {
|
||||||
|
// Tell the user on accounts that there was an issue and they need to wait maximum 24h or contact an admin
|
||||||
|
ret.warning = true;
|
||||||
|
srcWindow.postMessage(JSON.stringify(ret), domain);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
rpc.updatePinLimits(function (e, limit, plan, note) {
|
||||||
|
if (e) {
|
||||||
|
ret.warning = true;
|
||||||
|
}
|
||||||
ret.res = [limit, plan, note];
|
ret.res = [limit, plan, note];
|
||||||
srcWindow.postMessage(JSON.stringify(ret), domain);
|
srcWindow.postMessage(JSON.stringify(ret), domain);
|
||||||
});
|
});
|
||||||
@@ -74,18 +147,8 @@ define([
|
|||||||
srcWindow.postMessage(JSON.stringify(ret), domain);
|
srcWindow.postMessage(JSON.stringify(ret), domain);
|
||||||
});
|
});
|
||||||
|
|
||||||
nThen(function (waitFor) {
|
var userHash = LocalStore.getUserHash();
|
||||||
Cryptpad.ready(waitFor());
|
if (userHash) {
|
||||||
}).nThen(function (waitFor) {
|
loadProxy(userHash);
|
||||||
Cryptpad.getUserObject(null, waitFor(function (obj) {
|
}
|
||||||
proxy = obj;
|
|
||||||
}));
|
|
||||||
}).nThen(function () {
|
|
||||||
console.log('IFRAME READY');
|
|
||||||
Test(function () {
|
|
||||||
// This is only here to maybe trigger an error.
|
|
||||||
window.drive = proxy['drive'];
|
|
||||||
Test.passed();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ define([
|
|||||||
if (['markdown', 'gfm'].indexOf(CodeMirror.highlightMode) === -1) { return; }
|
if (['markdown', 'gfm'].indexOf(CodeMirror.highlightMode) === -1) { return; }
|
||||||
if (!$previewButton.is('.cp-toolbar-button-active')) { return; }
|
if (!$previewButton.is('.cp-toolbar-button-active')) { return; }
|
||||||
forceDrawPreview();
|
forceDrawPreview();
|
||||||
}, 150);
|
}, 400);
|
||||||
|
|
||||||
var previewTo;
|
var previewTo;
|
||||||
$previewButton.click(function () {
|
$previewButton.click(function () {
|
||||||
|
|||||||
@@ -121,6 +121,10 @@ text.actor {
|
|||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
text-height: 14px;
|
text-height: 14px;
|
||||||
}
|
}
|
||||||
|
.sectionTitle, .titleText {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
/* Grid and axis */
|
/* Grid and axis */
|
||||||
.grid .tick {
|
.grid .tick {
|
||||||
stroke: lightgrey;
|
stroke: lightgrey;
|
||||||
|
|||||||
@@ -127,6 +127,18 @@ define([
|
|||||||
return input;
|
return input;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
dialog.selectableArea = function (value, opt) {
|
||||||
|
var attrs = merge({
|
||||||
|
readonly: 'readonly',
|
||||||
|
}, opt);
|
||||||
|
|
||||||
|
var input = h('textarea', attrs);
|
||||||
|
$(input).val(value).click(function () {
|
||||||
|
input.select();
|
||||||
|
});
|
||||||
|
return input;
|
||||||
|
};
|
||||||
|
|
||||||
dialog.okButton = function (content, classString) {
|
dialog.okButton = function (content, classString) {
|
||||||
var sel = typeof(classString) === 'string'? 'button.ok.' + classString:'button.ok.primary';
|
var sel = typeof(classString) === 'string'? 'button.ok.' + classString:'button.ok.primary';
|
||||||
return h(sel, { tabindex: '2', }, content || Messages.okButton);
|
return h(sel, { tabindex: '2', }, content || Messages.okButton);
|
||||||
|
|||||||
@@ -147,6 +147,7 @@ define([
|
|||||||
: Messages.owner_removeText;
|
: Messages.owner_removeText;
|
||||||
var removeCol = UIElements.getUserGrid(msg, {
|
var removeCol = UIElements.getUserGrid(msg, {
|
||||||
common: common,
|
common: common,
|
||||||
|
large: true,
|
||||||
data: _owners,
|
data: _owners,
|
||||||
noFilter: true
|
noFilter: true
|
||||||
}, function () {
|
}, function () {
|
||||||
@@ -238,6 +239,7 @@ define([
|
|||||||
});
|
});
|
||||||
var addCol = UIElements.getUserGrid(Messages.owner_addText, {
|
var addCol = UIElements.getUserGrid(Messages.owner_addText, {
|
||||||
common: common,
|
common: common,
|
||||||
|
large: true,
|
||||||
data: _friends
|
data: _friends
|
||||||
}, function () {
|
}, function () {
|
||||||
//console.log(arguments);
|
//console.log(arguments);
|
||||||
@@ -254,6 +256,7 @@ define([
|
|||||||
});
|
});
|
||||||
var teamsList = UIElements.getUserGrid(Messages.owner_addTeamText, {
|
var teamsList = UIElements.getUserGrid(Messages.owner_addTeamText, {
|
||||||
common: common,
|
common: common,
|
||||||
|
large: true,
|
||||||
noFilter: true,
|
noFilter: true,
|
||||||
data: teamsData
|
data: teamsData
|
||||||
}, function () {});
|
}, function () {});
|
||||||
@@ -551,9 +554,10 @@ define([
|
|||||||
$d.append(password);
|
$d.append(password);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!data.noEditPassword && owned && parsed.type !== "sheet") { // FIXME SHEET fix password change for sheets
|
if (!data.noEditPassword && owned) { // FIXME SHEET fix password change for sheets
|
||||||
var sframeChan = common.getSframeChannel();
|
var sframeChan = common.getSframeChannel();
|
||||||
|
|
||||||
|
var isOO = parsed.type === 'sheet';
|
||||||
var isFile = parsed.hashData.type === 'file';
|
var isFile = parsed.hashData.type === 'file';
|
||||||
var isSharedFolder = parsed.type === 'drive';
|
var isSharedFolder = parsed.type === 'drive';
|
||||||
|
|
||||||
@@ -586,7 +590,8 @@ define([
|
|||||||
UI.confirm(changePwConfirm, function (yes) {
|
UI.confirm(changePwConfirm, function (yes) {
|
||||||
if (!yes) { pLocked = false; return; }
|
if (!yes) { pLocked = false; return; }
|
||||||
$(passwordOk).html('').append(h('span.fa.fa-spinner.fa-spin', {style: 'margin-left: 0'}));
|
$(passwordOk).html('').append(h('span.fa.fa-spinner.fa-spin', {style: 'margin-left: 0'}));
|
||||||
var q = isFile ? 'Q_BLOB_PASSWORD_CHANGE' : 'Q_PAD_PASSWORD_CHANGE';
|
var q = isFile ? 'Q_BLOB_PASSWORD_CHANGE' :
|
||||||
|
(isOO ? 'Q_OO_PASSWORD_CHANGE' : 'Q_PAD_PASSWORD_CHANGE');
|
||||||
|
|
||||||
// If this is a file password change, register to the upload events:
|
// If this is a file password change, register to the upload events:
|
||||||
// * if there is a pending upload, ask if we shoudl interrupt
|
// * if there is a pending upload, ask if we shoudl interrupt
|
||||||
@@ -737,12 +742,22 @@ define([
|
|||||||
UIElements.getProperties = function (common, data, cb) {
|
UIElements.getProperties = function (common, data, cb) {
|
||||||
var c1;
|
var c1;
|
||||||
var c2;
|
var c2;
|
||||||
|
var button = [{
|
||||||
|
className: 'primary',
|
||||||
|
name: Messages.okButton,
|
||||||
|
onClick: function () {},
|
||||||
|
keys: [13]
|
||||||
|
}];
|
||||||
NThen(function (waitFor) {
|
NThen(function (waitFor) {
|
||||||
getPadProperties(common, data, waitFor(function (e, c) {
|
getPadProperties(common, data, waitFor(function (e, c) {
|
||||||
c1 = c[0];
|
c1 = UI.dialog.customModal(c[0], {
|
||||||
|
buttons: button
|
||||||
|
});
|
||||||
}));
|
}));
|
||||||
getRightsProperties(common, data, waitFor(function (e, c) {
|
getRightsProperties(common, data, waitFor(function (e, c) {
|
||||||
c2 = c[0];
|
c2 = UI.dialog.customModal(c[0], {
|
||||||
|
buttons: button
|
||||||
|
});
|
||||||
}));
|
}));
|
||||||
}).nThen(function () {
|
}).nThen(function () {
|
||||||
var tabs = UI.dialog.tabs([{
|
var tabs = UI.dialog.tabs([{
|
||||||
@@ -782,8 +797,6 @@ define([
|
|||||||
|
|
||||||
var noOthers = icons.length === 0 ? '.cp-usergrid-empty' : '';
|
var noOthers = icons.length === 0 ? '.cp-usergrid-empty' : '';
|
||||||
|
|
||||||
var buttonSelect = h('button', Messages.share_selectAll);
|
|
||||||
var buttonDeselect = h('button', Messages.share_deselectAll);
|
|
||||||
var inputFilter = h('input', {
|
var inputFilter = h('input', {
|
||||||
placeholder: Messages.share_filterFriend
|
placeholder: Messages.share_filterFriend
|
||||||
});
|
});
|
||||||
@@ -791,9 +804,7 @@ define([
|
|||||||
var div = h('div.cp-usergrid-container' + noOthers + (config.large?'.large':''), [
|
var div = h('div.cp-usergrid-container' + noOthers + (config.large?'.large':''), [
|
||||||
label ? h('label', label) : undefined,
|
label ? h('label', label) : undefined,
|
||||||
h('div.cp-usergrid-filter', (config.noFilter || config.noSelect) ? undefined : [
|
h('div.cp-usergrid-filter', (config.noFilter || config.noSelect) ? undefined : [
|
||||||
inputFilter,
|
inputFilter
|
||||||
buttonSelect,
|
|
||||||
buttonDeselect
|
|
||||||
]),
|
]),
|
||||||
]);
|
]);
|
||||||
var $div = $(div);
|
var $div = $(div);
|
||||||
@@ -806,23 +817,8 @@ define([
|
|||||||
$div.find('.cp-usergrid-user:not(.cp-selected):not([data-name*="'+name+'"])').hide();
|
$div.find('.cp-usergrid-user:not(.cp-selected):not([data-name*="'+name+'"])').hide();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
$(inputFilter).on('keydown keyup change', redraw);
|
$(inputFilter).on('keydown keyup change', redraw);
|
||||||
|
|
||||||
$(buttonSelect).click(function () {
|
|
||||||
$div.find('.cp-usergrid-user:not(.cp-selected):visible').addClass('cp-selected');
|
|
||||||
onSelect();
|
|
||||||
});
|
|
||||||
$(buttonDeselect).click(function () {
|
|
||||||
$div.find('.cp-usergrid-user.cp-selected').removeClass('cp-selected').each(function (i, el) {
|
|
||||||
var order = $(el).attr('data-order');
|
|
||||||
if (!order) { return; }
|
|
||||||
$(el).attr('style', 'order:'+order);
|
|
||||||
});
|
|
||||||
redraw();
|
|
||||||
onSelect();
|
|
||||||
});
|
|
||||||
|
|
||||||
$(div).append(h('div.cp-usergrid-grid', icons));
|
$(div).append(h('div.cp-usergrid-grid', icons));
|
||||||
if (!config.noSelect) {
|
if (!config.noSelect) {
|
||||||
$div.on('click', '.cp-usergrid-user', function () {
|
$div.on('click', '.cp-usergrid-user', function () {
|
||||||
@@ -883,7 +879,8 @@ define([
|
|||||||
var friendsList = UIElements.getUserGrid(null, {
|
var friendsList = UIElements.getUserGrid(null, {
|
||||||
common: common,
|
common: common,
|
||||||
data: friends,
|
data: friends,
|
||||||
noFilter: false
|
noFilter: false,
|
||||||
|
large: true
|
||||||
}, refreshButtons);
|
}, refreshButtons);
|
||||||
var friendDiv = friendsList.div;
|
var friendDiv = friendsList.div;
|
||||||
$div.append(friendDiv);
|
$div.append(friendDiv);
|
||||||
@@ -909,6 +906,7 @@ define([
|
|||||||
var teamsList = UIElements.getUserGrid(Messages.share_linkTeam, {
|
var teamsList = UIElements.getUserGrid(Messages.share_linkTeam, {
|
||||||
common: common,
|
common: common,
|
||||||
noFilter: true,
|
noFilter: true,
|
||||||
|
large: true,
|
||||||
data: teams
|
data: teams
|
||||||
}, refreshButtons);
|
}, refreshButtons);
|
||||||
$div.append(teamsList.div);
|
$div.append(teamsList.div);
|
||||||
@@ -1057,12 +1055,29 @@ define([
|
|||||||
|
|
||||||
if (!hashes || (!hashes.editHash && !hashes.viewHash)) { return; }
|
if (!hashes || (!hashes.editHash && !hashes.viewHash)) { return; }
|
||||||
|
|
||||||
|
// check if the pad is password protected
|
||||||
|
var hash = hashes.editHash || hashes.viewHash;
|
||||||
|
var href = origin + pathname + '#' + hash;
|
||||||
|
var parsedHref = Hash.parsePadUrl(href);
|
||||||
|
var hasPassword = parsedHref.hashData.password;
|
||||||
|
|
||||||
|
var makeFaqLink = function () {
|
||||||
|
var link = h('span', [
|
||||||
|
h('i.fa.fa-question-circle'),
|
||||||
|
h('a', {href: '#'}, Messages.passwordFaqLink)
|
||||||
|
]);
|
||||||
|
$(link).click(function () {
|
||||||
|
common.openURL(config.origin + "/faq.html#security-pad_password");
|
||||||
|
});
|
||||||
|
return link;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
var parsed = Hash.parsePadUrl(pathname);
|
var parsed = Hash.parsePadUrl(pathname);
|
||||||
var canPresent = ['code', 'slide'].indexOf(parsed.type) !== -1;
|
var canPresent = ['code', 'slide'].indexOf(parsed.type) !== -1;
|
||||||
|
|
||||||
var rights = h('div.msg.cp-inline-radio-group', [
|
var rights = h('div.msg.cp-inline-radio-group', [
|
||||||
h('label', Messages.share_linkAccess),
|
h('label', Messages.share_linkAccess),
|
||||||
h('br'),
|
|
||||||
h('div.radio-group',[
|
h('div.radio-group',[
|
||||||
UI.createRadio('accessRights', 'cp-share-editable-false',
|
UI.createRadio('accessRights', 'cp-share-editable-false',
|
||||||
Messages.share_linkView, true, { mark: {tabindex:1} }),
|
Messages.share_linkView, true, { mark: {tabindex:1} }),
|
||||||
@@ -1109,9 +1124,42 @@ define([
|
|||||||
h('br'),
|
h('br'),
|
||||||
] : [
|
] : [
|
||||||
UI.createCheckbox('cp-share-embed', Messages.share_linkEmbed, false, { mark: {tabindex:1} }),
|
UI.createCheckbox('cp-share-embed', Messages.share_linkEmbed, false, { mark: {tabindex:1} }),
|
||||||
h('br'),
|
|
||||||
];
|
];
|
||||||
linkContent.push(UI.dialog.selectable('', { id: 'cp-share-link-preview', tabindex: 1 }));
|
linkContent.push(h('div.cp-spacer'));
|
||||||
|
linkContent.push(UI.dialog.selectableArea('', { id: 'cp-share-link-preview', tabindex: 1, rows:3}));
|
||||||
|
|
||||||
|
// Show alert if the pad is password protected
|
||||||
|
if (hasPassword) {
|
||||||
|
linkContent.push(h('div.alert.alert-primary', [
|
||||||
|
h('i.fa.fa-lock'),
|
||||||
|
Messages.share_linkPasswordAlert, h('br'),
|
||||||
|
makeFaqLink()
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// warning about sharing links
|
||||||
|
var localStore = window.cryptpadStore;
|
||||||
|
var dismissButton = h('span.fa.fa-times');
|
||||||
|
var shareLinkWarning = h('div.alert.alert-warning.dismissable',
|
||||||
|
{ style: 'display: none;' },
|
||||||
|
[
|
||||||
|
h('span.cp-inline-alert-text', Messages.share_linkWarning),
|
||||||
|
dismissButton
|
||||||
|
]);
|
||||||
|
linkContent.push(shareLinkWarning);
|
||||||
|
|
||||||
|
localStore.get('hide-alert-shareLinkWarning', function (val) {
|
||||||
|
if (val === '1') { return; }
|
||||||
|
$(shareLinkWarning).show();
|
||||||
|
|
||||||
|
$(dismissButton).on('click', function () {
|
||||||
|
localStore.put('hide-alert-shareLinkWarning', '1');
|
||||||
|
$(shareLinkWarning).remove();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var link = h('div.cp-share-modal', linkContent);
|
var link = h('div.cp-share-modal', linkContent);
|
||||||
var $link = $(link);
|
var $link = $(link);
|
||||||
@@ -1177,7 +1225,19 @@ define([
|
|||||||
|
|
||||||
// XXX Don't display access rights if no contacts
|
// XXX Don't display access rights if no contacts
|
||||||
var contactsContent = h('div.cp-share-modal');
|
var contactsContent = h('div.cp-share-modal');
|
||||||
$(contactsContent).append(friendsList);
|
var $contactsContent = $(contactsContent);
|
||||||
|
|
||||||
|
$contactsContent.append(friendsList);
|
||||||
|
|
||||||
|
// Show alert if the pad is password protected
|
||||||
|
if (hasPassword) {
|
||||||
|
$contactsContent.append(h('div.alert.alert-primary', [
|
||||||
|
h('i.fa.fa-unlock'),
|
||||||
|
Messages.share_contactPasswordAlert, h('br'),
|
||||||
|
makeFaqLink()
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
var contactButtons = friendsObject.buttons;
|
var contactButtons = friendsObject.buttons;
|
||||||
contactButtons.unshift(makeCancelButton());
|
contactButtons.unshift(makeCancelButton());
|
||||||
@@ -1196,9 +1256,18 @@ define([
|
|||||||
};
|
};
|
||||||
var embedContent = [
|
var embedContent = [
|
||||||
h('p', Messages.viewEmbedTag),
|
h('p', Messages.viewEmbedTag),
|
||||||
h('br'),
|
UI.dialog.selectableArea(getEmbedValue(), { id: 'cp-embed-link-preview', tabindex: 1, rows: 3})
|
||||||
UI.dialog.selectable(getEmbedValue(), { id: 'cp-embed-link-preview', tabindex: 1 })
|
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// Show alert if the pad is password protected
|
||||||
|
if (hasPassword) {
|
||||||
|
embedContent.push(h('div.alert.alert-primary', [
|
||||||
|
h('i.fa.fa-lock'), ' ',
|
||||||
|
Messages.share_embedPasswordAlert, h('br'),
|
||||||
|
makeFaqLink()
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
var embedButtons = [
|
var embedButtons = [
|
||||||
makeCancelButton(), {
|
makeCancelButton(), {
|
||||||
className: 'primary',
|
className: 'primary',
|
||||||
@@ -1303,6 +1372,21 @@ define([
|
|||||||
if (!hashes.fileHash) { throw new Error("You must provide a file hash"); }
|
if (!hashes.fileHash) { throw new Error("You must provide a file hash"); }
|
||||||
var url = origin + pathname + '#' + hashes.fileHash;
|
var url = origin + pathname + '#' + hashes.fileHash;
|
||||||
|
|
||||||
|
// check if the file is password protected
|
||||||
|
var parsedHref = Hash.parsePadUrl(url);
|
||||||
|
var hasPassword = parsedHref.hashData.password;
|
||||||
|
|
||||||
|
var makeFaqLink = function () {
|
||||||
|
var link = h('span', [
|
||||||
|
h('i.fa.fa-question-circle'),
|
||||||
|
h('a', {href: '#'}, Messages.passwordFaqLink)
|
||||||
|
]);
|
||||||
|
$(link).click(function () {
|
||||||
|
common.openURL(config.origin + "/faq.html#security-pad_password");
|
||||||
|
});
|
||||||
|
return link;
|
||||||
|
};
|
||||||
|
|
||||||
var getLinkValue = function () { return url; };
|
var getLinkValue = function () { return url; };
|
||||||
|
|
||||||
var makeCancelButton = function() {
|
var makeCancelButton = function() {
|
||||||
@@ -1314,9 +1398,40 @@ define([
|
|||||||
|
|
||||||
// Share link tab
|
// Share link tab
|
||||||
var linkContent = [
|
var linkContent = [
|
||||||
UI.dialog.selectable(getLinkValue(), { id: 'cp-share-link-preview', tabindex: 1 })
|
UI.dialog.selectableArea(getLinkValue(), { id: 'cp-share-link-preview', tabindex: 1, rows:2 })
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// Show alert if the pad is password protected
|
||||||
|
if (hasPassword) {
|
||||||
|
linkContent.push(h('div.alert.alert-primary', [
|
||||||
|
h('i.fa.fa-lock'),
|
||||||
|
Messages.share_linkPasswordAlert, h('br'),
|
||||||
|
makeFaqLink()
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// warning about sharing links
|
||||||
|
var localStore = window.cryptpadStore;
|
||||||
|
var dismissButton = h('span.fa.fa-times');
|
||||||
|
var shareLinkWarning = h('div.alert.alert-warning.dismissable',
|
||||||
|
{ style: 'display: none;' },
|
||||||
|
[
|
||||||
|
h('span.cp-inline-alert-text', Messages.share_linkWarning),
|
||||||
|
dismissButton
|
||||||
|
]);
|
||||||
|
linkContent.push(shareLinkWarning);
|
||||||
|
|
||||||
|
localStore.get('hide-alert-shareLinkWarning', function (val) {
|
||||||
|
if (val === '1') { return; }
|
||||||
|
$(shareLinkWarning).show();
|
||||||
|
|
||||||
|
$(dismissButton).on('click', function () {
|
||||||
|
localStore.put('hide-alert-shareLinkWarning', '1');
|
||||||
|
$(shareLinkWarning).remove();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
var link = h('div.cp-share-modal', linkContent);
|
var link = h('div.cp-share-modal', linkContent);
|
||||||
|
|
||||||
var linkButtons = [
|
var linkButtons = [
|
||||||
@@ -1346,7 +1461,17 @@ define([
|
|||||||
var friendsList = friendsObject.content;
|
var friendsList = friendsObject.content;
|
||||||
|
|
||||||
var contactsContent = h('div.cp-share-modal');
|
var contactsContent = h('div.cp-share-modal');
|
||||||
$(contactsContent).append(friendsList);
|
var $contactsContent = $(contactsContent);
|
||||||
|
$contactsContent.append(friendsList);
|
||||||
|
|
||||||
|
// Show alert if the pad is password protected
|
||||||
|
if (hasPassword) {
|
||||||
|
$contactsContent.append(h('div.alert.alert-primary', [
|
||||||
|
h('i.fa.fa-unlock'),
|
||||||
|
Messages.share_contactPasswordAlert, h('br'),
|
||||||
|
makeFaqLink()
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
var contactButtons = friendsObject.buttons;
|
var contactButtons = friendsObject.buttons;
|
||||||
contactButtons.unshift(makeCancelButton());
|
contactButtons.unshift(makeCancelButton());
|
||||||
@@ -1360,12 +1485,20 @@ define([
|
|||||||
// Embed tab
|
// Embed tab
|
||||||
var embed = h('div.cp-share-modal', [
|
var embed = h('div.cp-share-modal', [
|
||||||
h('p', Messages.fileEmbedScript),
|
h('p', Messages.fileEmbedScript),
|
||||||
h('br'),
|
|
||||||
UI.dialog.selectable(common.getMediatagScript()),
|
UI.dialog.selectable(common.getMediatagScript()),
|
||||||
h('p', Messages.fileEmbedTag),
|
h('p', Messages.fileEmbedTag),
|
||||||
h('br'),
|
|
||||||
UI.dialog.selectable(common.getMediatagFromHref(fileData)),
|
UI.dialog.selectable(common.getMediatagFromHref(fileData)),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Show alert if the pad is password protected
|
||||||
|
if (hasPassword) {
|
||||||
|
embed.append(h('div.alert.alert-primary', [
|
||||||
|
h('i.fa.fa-lock'), ' ',
|
||||||
|
Messages.share_embedPasswordAlert, h('br'),
|
||||||
|
makeFaqLink()
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
var embedButtons = [{
|
var embedButtons = [{
|
||||||
className: 'cancel',
|
className: 'cancel',
|
||||||
name: Messages.cancel,
|
name: Messages.cancel,
|
||||||
@@ -1800,7 +1933,7 @@ define([
|
|||||||
if (e) { return void console.error(e); }
|
if (e) { return void console.error(e); }
|
||||||
UIElements.getProperties(common, data, function (e, $prop) {
|
UIElements.getProperties(common, data, function (e, $prop) {
|
||||||
if (e) { return void console.error(e); }
|
if (e) { return void console.error(e); }
|
||||||
UI.alert($prop[0], undefined, true);
|
UI.openCustomModal($prop[0]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1155,6 +1155,242 @@ define([
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
common.changeOOPassword = function (data, _cb) {
|
||||||
|
var cb = Util.once(Util.mkAsync(_cb));
|
||||||
|
var href = data.href;
|
||||||
|
var newPassword = data.password;
|
||||||
|
var teamId = data.teamId;
|
||||||
|
if (!href) { return void cb({ error: 'EINVAL_HREF' }); }
|
||||||
|
var parsed = Hash.parsePadUrl(href);
|
||||||
|
if (!parsed.hash) { return void cb({ error: 'EINVAL_HREF' }); }
|
||||||
|
if (parsed.type !== 'sheet') { return void cb({ error: 'EINVAL_TYPE' }); }
|
||||||
|
|
||||||
|
var warning = false;
|
||||||
|
var newHash, newRoHref;
|
||||||
|
var oldSecret;
|
||||||
|
var oldMetadata;
|
||||||
|
var oldRtChannel;
|
||||||
|
var privateData;
|
||||||
|
var padData;
|
||||||
|
|
||||||
|
var newSecret;
|
||||||
|
if (parsed.hashData.version >= 2) {
|
||||||
|
newSecret = Hash.getSecrets(parsed.type, parsed.hash, newPassword);
|
||||||
|
if (!(newSecret.keys && newSecret.keys.editKeyStr)) {
|
||||||
|
return void cb({error: 'EAUTH'});
|
||||||
|
}
|
||||||
|
newHash = Hash.getEditHashFromKeys(newSecret);
|
||||||
|
}
|
||||||
|
var newHref = '/' + parsed.type + '/#' + newHash;
|
||||||
|
var newRtChannel = Hash.createChannelId();
|
||||||
|
|
||||||
|
var Crypt, Crypto;
|
||||||
|
var cryptgetVal;
|
||||||
|
var optsPut = {
|
||||||
|
password: newPassword,
|
||||||
|
metadata: {
|
||||||
|
validateKey: newSecret.keys.validateKey
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
Nthen(function (waitFor) {
|
||||||
|
common.getPadAttribute('', waitFor(function (err, _data) {
|
||||||
|
padData = _data;
|
||||||
|
}), href);
|
||||||
|
}).nThen(function (waitFor) {
|
||||||
|
oldSecret = Hash.getSecrets(parsed.type, parsed.hash, padData.password);
|
||||||
|
|
||||||
|
require([
|
||||||
|
'/common/cryptget.js',
|
||||||
|
'/bower_components/chainpad-crypto/crypto.js',
|
||||||
|
], waitFor(function (_Crypt, _Crypto) {
|
||||||
|
Crypt = _Crypt;
|
||||||
|
Crypto = _Crypto;
|
||||||
|
}));
|
||||||
|
|
||||||
|
common.getPadMetadata({channel: oldSecret.channel}, waitFor(function (metadata) {
|
||||||
|
oldMetadata = metadata;
|
||||||
|
}));
|
||||||
|
common.getMetadata(waitFor(function (err, data) {
|
||||||
|
if (err) {
|
||||||
|
waitFor.abort();
|
||||||
|
return void cb({ error: err });
|
||||||
|
}
|
||||||
|
privateData = data.priv;
|
||||||
|
}));
|
||||||
|
}).nThen(function (waitFor) {
|
||||||
|
// Check if we're allowed to change the password
|
||||||
|
var owners = oldMetadata.owners;
|
||||||
|
optsPut.metadata.owners = owners;
|
||||||
|
var edPublic = teamId ? (privateData.teams[teamId] || {}).edPublic : privateData.edPublic;
|
||||||
|
var isOwner = Array.isArray(owners) && edPublic && owners.indexOf(edPublic) !== -1;
|
||||||
|
if (!isOwner) {
|
||||||
|
// We're not an owner, we shouldn't be able to change the password!
|
||||||
|
waitFor.abort();
|
||||||
|
return void cb({ error: 'EPERM' });
|
||||||
|
}
|
||||||
|
|
||||||
|
var mailbox = oldMetadata.mailbox;
|
||||||
|
if (mailbox) {
|
||||||
|
// Create the encryptors to be able to decrypt and re-encrypt the mailboxes
|
||||||
|
var oldCrypto = Crypto.createEncryptor(oldSecret.keys);
|
||||||
|
var newCrypto = Crypto.createEncryptor(newSecret.keys);
|
||||||
|
|
||||||
|
var m;
|
||||||
|
if (typeof(mailbox) === "string") {
|
||||||
|
try {
|
||||||
|
m = newCrypto.encrypt(oldCrypto.decrypt(mailbox, true, true));
|
||||||
|
} catch (e) {}
|
||||||
|
} else if (mailbox && typeof(mailbox) === "object") {
|
||||||
|
m = {};
|
||||||
|
Object.keys(mailbox).forEach(function (ed) {
|
||||||
|
try {
|
||||||
|
m[ed] = newCrypto.encrypt(oldCrypto.decrypt(mailbox[ed], true, true));
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
optsPut.metadata.mailbox = m;
|
||||||
|
}
|
||||||
|
|
||||||
|
var expire = oldMetadata.expire;
|
||||||
|
if (expire) {
|
||||||
|
optsPut.metadata.expire = (expire - (+new Date())) / 1000; // Lifetime in seconds
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get last cp (cryptget)
|
||||||
|
Crypt.get(parsed.hash, waitFor(function (err, val) {
|
||||||
|
if (err) {
|
||||||
|
waitFor.abort();
|
||||||
|
return void cb({ error: err });
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
cryptgetVal = JSON.parse(val);
|
||||||
|
if (!cryptgetVal.content) {
|
||||||
|
waitFor.abort();
|
||||||
|
return void cb({ error: 'INVALID_CONTENT' });
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
waitFor.abort();
|
||||||
|
return void cb({ error: 'CANT_PARSE' });
|
||||||
|
}
|
||||||
|
}), {
|
||||||
|
password: padData.password
|
||||||
|
});
|
||||||
|
}).nThen(function (waitFor) {
|
||||||
|
// Re-encrypt rtchannel
|
||||||
|
oldRtChannel = Util.find(cryptgetVal, ['content', 'channel']);
|
||||||
|
var newCrypto = Crypto.createEncryptor(newSecret.keys);
|
||||||
|
var oldCrypto = Crypto.createEncryptor(oldSecret.keys);
|
||||||
|
var cps = Util.find(cryptgetVal, ['content', 'hashes']);
|
||||||
|
var l = Object.keys(cps).length;
|
||||||
|
var lastCp = l ? cps[l] : {};
|
||||||
|
cryptgetVal.content.hashes = {};
|
||||||
|
common.getHistory({
|
||||||
|
channel: oldRtChannel,
|
||||||
|
lastKnownHash: lastCp.hash
|
||||||
|
}, waitFor(function (obj) {
|
||||||
|
if (obj && obj.error) {
|
||||||
|
waitFor.abort();
|
||||||
|
console.error(obj);
|
||||||
|
return void cb(obj.error);
|
||||||
|
}
|
||||||
|
var msgs = obj;
|
||||||
|
var newHistory = msgs.map(function (str) {
|
||||||
|
try {
|
||||||
|
var d = oldCrypto.decrypt(str, true, true);
|
||||||
|
return newCrypto.encrypt(d);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
waitFor.abort();
|
||||||
|
return void cb({error: e});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Update last knwon hash in cryptgetVal
|
||||||
|
if (lastCp) {
|
||||||
|
lastCp.hash = newHistory[0].slice(0, 64);
|
||||||
|
lastCp.index = 50;
|
||||||
|
cryptgetVal.content.hashes[1] = lastCp;
|
||||||
|
}
|
||||||
|
common.onlyoffice.execCommand({
|
||||||
|
cmd: 'REENCRYPT',
|
||||||
|
data: {
|
||||||
|
channel: newRtChannel,
|
||||||
|
msgs: newHistory,
|
||||||
|
metadata: optsPut.metadata
|
||||||
|
}
|
||||||
|
}, waitFor(function (obj) {
|
||||||
|
if (obj && obj.error) {
|
||||||
|
waitFor.abort();
|
||||||
|
console.warn(obj);
|
||||||
|
return void cb(obj.error);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}));
|
||||||
|
}).nThen(function (waitFor) {
|
||||||
|
// The new rt channel is ready
|
||||||
|
// The blob uses its own encryption and doesn't need to be reencrypted
|
||||||
|
cryptgetVal.content.channel = newRtChannel;
|
||||||
|
Crypt.put(newHash, JSON.stringify(cryptgetVal), waitFor(function (err) {
|
||||||
|
if (err) {
|
||||||
|
waitFor.abort();
|
||||||
|
return void cb({ error: err });
|
||||||
|
}
|
||||||
|
}), optsPut);
|
||||||
|
}).nThen(function (waitFor) {
|
||||||
|
pad.leavePad({
|
||||||
|
channel: oldSecret.channel
|
||||||
|
}, waitFor());
|
||||||
|
pad.onDisconnectEvent.fire(true);
|
||||||
|
}).nThen(function (waitFor) {
|
||||||
|
// Set the new password to our pad data
|
||||||
|
common.setPadAttribute('password', newPassword, waitFor(function (err) {
|
||||||
|
if (err) { warning = true; }
|
||||||
|
}), href);
|
||||||
|
common.setPadAttribute('channel', newSecret.channel, waitFor(function (err) {
|
||||||
|
if (err) { warning = true; }
|
||||||
|
}), href);
|
||||||
|
common.setPadAttribute('rtChannel', newRtChannel, waitFor(function (err) {
|
||||||
|
if (err) { warning = true; }
|
||||||
|
}), href);
|
||||||
|
var viewHash = Hash.getViewHashFromKeys(newSecret);
|
||||||
|
newRoHref = '/' + parsed.type + '/#' + viewHash;
|
||||||
|
common.setPadAttribute('roHref', newRoHref, waitFor(function (err) {
|
||||||
|
if (err) { warning = true; }
|
||||||
|
}), href);
|
||||||
|
|
||||||
|
if (parsed.hashData.password && newPassword) { return; } // same hash
|
||||||
|
common.setPadAttribute('href', newHref, waitFor(function (err) {
|
||||||
|
if (err) { warning = true; }
|
||||||
|
}), href);
|
||||||
|
}).nThen(function (waitFor) {
|
||||||
|
// delete the old pad
|
||||||
|
common.removeOwnedChannel({
|
||||||
|
channel: oldSecret.channel,
|
||||||
|
teamId: teamId
|
||||||
|
}, waitFor(function (obj) {
|
||||||
|
if (obj && obj.error) {
|
||||||
|
waitFor.abort();
|
||||||
|
console.info(obj);
|
||||||
|
return void cb(obj.error);
|
||||||
|
}
|
||||||
|
common.removeOwnedChannel({
|
||||||
|
channel: oldRtChannel,
|
||||||
|
teamId: teamId
|
||||||
|
}, waitFor());
|
||||||
|
}));
|
||||||
|
}).nThen(function () {
|
||||||
|
cb({
|
||||||
|
warning: warning,
|
||||||
|
hash: newHash,
|
||||||
|
href: newHref,
|
||||||
|
roHref: newRoHref
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
common.changeUserPassword = function (Crypt, edPublic, data, cb) {
|
common.changeUserPassword = function (Crypt, edPublic, data, cb) {
|
||||||
if (!edPublic) {
|
if (!edPublic) {
|
||||||
return void cb({
|
return void cb({
|
||||||
@@ -1350,6 +1586,9 @@ define([
|
|||||||
common.getFullHistory = function (data, cb) {
|
common.getFullHistory = function (data, cb) {
|
||||||
postMessage("GET_FULL_HISTORY", data, cb, {timeout: 180000});
|
postMessage("GET_FULL_HISTORY", data, cb, {timeout: 180000});
|
||||||
};
|
};
|
||||||
|
common.getHistory = function (data, cb) {
|
||||||
|
postMessage("GET_HISTORY", data, cb, {timeout: 180000});
|
||||||
|
};
|
||||||
common.getHistoryRange = function (data, cb) {
|
common.getHistoryRange = function (data, cb) {
|
||||||
postMessage("GET_HISTORY_RANGE", data, cb);
|
postMessage("GET_HISTORY_RANGE", data, cb);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -197,7 +197,6 @@ define([
|
|||||||
'APPLET',
|
'APPLET',
|
||||||
'VIDEO', // privacy implications of videos are the same as images
|
'VIDEO', // privacy implications of videos are the same as images
|
||||||
'AUDIO', // same with audio
|
'AUDIO', // same with audio
|
||||||
'SVG'
|
|
||||||
];
|
];
|
||||||
var unsafeTag = function (info) {
|
var unsafeTag = function (info) {
|
||||||
/*if (info.node && $(info.node).parents('media-tag').length) {
|
/*if (info.node && $(info.node).parents('media-tag').length) {
|
||||||
@@ -307,8 +306,39 @@ define([
|
|||||||
|
|
||||||
var Dom = domFromHTML($('<div>').append($div).html());
|
var Dom = domFromHTML($('<div>').append($div).html());
|
||||||
$content[0].normalize();
|
$content[0].normalize();
|
||||||
$content.find('pre.mermaid[data-processed="true"]').remove();
|
|
||||||
|
var mermaid_source = [];
|
||||||
|
var mermaid_cache = {};
|
||||||
|
|
||||||
|
// iterate over the unrendered mermaid inputs, caching their source as you go
|
||||||
|
$(newDomFixed).find('pre.mermaid').each(function (index, el) {
|
||||||
|
if (el.childNodes.length === 1 && el.childNodes[0].nodeType === 3) {
|
||||||
|
var src = el.childNodes[0].wholeText;
|
||||||
|
el.setAttribute('mermaid-source', src);
|
||||||
|
mermaid_source[index] = src;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// iterate over rendered mermaid charts
|
||||||
|
$content.find('pre.mermaid:not([processed="true"])').each(function (index, el) {
|
||||||
|
// retrieve the attached source code which it was drawn
|
||||||
|
var src = el.getAttribute('mermaid-source');
|
||||||
|
|
||||||
|
// check if that source exists in the set of charts which are about to be rendered
|
||||||
|
if (mermaid_source.indexOf(src) === -1) {
|
||||||
|
// if it's not, then you can remove it
|
||||||
|
if (el.parentNode && el.parentNode.children.length) {
|
||||||
|
el.parentNode.removeChild(el);
|
||||||
|
}
|
||||||
|
} else if (el.childNodes.length === 1 && el.childNodes[0].nodeType !== 3) {
|
||||||
|
// otherwise, confirm that the content of the rendered chart is not a text node
|
||||||
|
// and keep a copy of it
|
||||||
|
mermaid_cache[src] = el.childNodes[0];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
var oldDom = domFromHTML($content[0].outerHTML);
|
var oldDom = domFromHTML($content[0].outerHTML);
|
||||||
|
|
||||||
var patch = makeDiff(oldDom, Dom, id);
|
var patch = makeDiff(oldDom, Dom, id);
|
||||||
if (typeof(patch) === 'string') {
|
if (typeof(patch) === 'string') {
|
||||||
throw new Error(patch);
|
throw new Error(patch);
|
||||||
@@ -348,8 +378,32 @@ define([
|
|||||||
var target = document.getElementById($a.attr('data-href'));
|
var target = document.getElementById($a.attr('data-href'));
|
||||||
if (target) { target.scrollIntoView(); }
|
if (target) { target.scrollIntoView(); }
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// loop over mermaid elements in the rendered content
|
||||||
|
$content.find('pre.mermaid').each(function (index, el) {
|
||||||
|
// since you've simply drawn the content that was supplied via markdown
|
||||||
|
// you can assume that the index of your rendered charts matches that
|
||||||
|
// of those in the markdown source.
|
||||||
|
var src = mermaid_source[index];
|
||||||
|
el.setAttribute('mermaid-source', src);
|
||||||
|
var cached = mermaid_cache[src];
|
||||||
|
|
||||||
|
// check if you had cached a pre-rendered instance of the supplied source
|
||||||
|
if (typeof(cached) !== 'object') { return; }
|
||||||
|
|
||||||
|
// if there's a cached rendering, empty out the contained source code
|
||||||
|
// which would otherwise be drawn again.
|
||||||
|
// apparently this is the fastest way to empty out an element
|
||||||
|
while (el.firstChild) { el.removeChild(el.firstChild); } //el.innerHTML = '';
|
||||||
|
// insert the cached graph
|
||||||
|
el.appendChild(cached);
|
||||||
|
// and set a flag indicating that this graph need not be reprocessed
|
||||||
|
el.setAttribute('data-processed', true);
|
||||||
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Mermaid.init();
|
// finally, draw any graphs which have changed and were thus not cached
|
||||||
|
Mermaid.init(undefined, $content.find('pre.mermaid:not([data-processed="true"])'));
|
||||||
} catch (e) { console.error(e); }
|
} catch (e) { console.error(e); }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4187,7 +4187,7 @@ define([
|
|||||||
}
|
}
|
||||||
getProperties(el, function (e, $prop) {
|
getProperties(el, function (e, $prop) {
|
||||||
if (e) { return void logError(e); }
|
if (e) { return void logError(e); }
|
||||||
UI.alert($prop[0], undefined, true);
|
UI.openCustomModal($prop[0]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if ($this.hasClass("cp-app-drive-context-hashtag")) {
|
else if ($this.hasClass("cp-app-drive-context-hashtag")) {
|
||||||
|
|||||||
@@ -1693,7 +1693,7 @@ define([
|
|||||||
// GET_FULL_HISTORY from sframe-common-outer
|
// GET_FULL_HISTORY from sframe-common-outer
|
||||||
Store.getFullHistory = function (clientId, data, cb) {
|
Store.getFullHistory = function (clientId, data, cb) {
|
||||||
var network = store.network;
|
var network = store.network;
|
||||||
var hkn = network.historyKeeper;
|
var hk = network.historyKeeper;
|
||||||
//var crypto = Crypto.createEncryptor(data.keys);
|
//var crypto = Crypto.createEncryptor(data.keys);
|
||||||
// Get the history messages and send them to the iframe
|
// Get the history messages and send them to the iframe
|
||||||
var parse = function (msg) {
|
var parse = function (msg) {
|
||||||
@@ -1708,8 +1708,10 @@ define([
|
|||||||
var onMsg = function (msg) {
|
var onMsg = function (msg) {
|
||||||
if (completed) { return; }
|
if (completed) { return; }
|
||||||
var parsed = parse(msg);
|
var parsed = parse(msg);
|
||||||
|
if (!parsed) { return; }
|
||||||
if (parsed[0] === 'FULL_HISTORY_END') {
|
if (parsed[0] === 'FULL_HISTORY_END') {
|
||||||
cb(msgs);
|
cb(msgs);
|
||||||
|
network.off('message', onMsg);
|
||||||
completed = true;
|
completed = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1726,12 +1728,69 @@ define([
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
network.on('message', onMsg);
|
network.on('message', onMsg);
|
||||||
network.sendto(hkn, JSON.stringify(['GET_FULL_HISTORY', data.channel, data.validateKey]));
|
network.sendto(hk, JSON.stringify(['GET_FULL_HISTORY', data.channel, data.validateKey]));
|
||||||
|
};
|
||||||
|
|
||||||
|
Store.getHistory = function (clientId, data, cb) {
|
||||||
|
var network = store.network;
|
||||||
|
var hk = network.historyKeeper;
|
||||||
|
|
||||||
|
var parse = function (msg) {
|
||||||
|
try {
|
||||||
|
return JSON.parse(msg);
|
||||||
|
} catch (e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var msgs = [];
|
||||||
|
var completed = false;
|
||||||
|
var onMsg = function (msg, sender) {
|
||||||
|
if (completed) { return; }
|
||||||
|
if (sender !== hk) { return; }
|
||||||
|
var parsed = parse(msg);
|
||||||
|
if (!parsed) { return; }
|
||||||
|
|
||||||
|
// Ignore the metadata message
|
||||||
|
if (parsed.validateKey && parsed.channel) { return; }
|
||||||
|
if (parsed.error && parsed.channel) {
|
||||||
|
if (parsed.channel === data.channel) {
|
||||||
|
network.off('message', onMsg);
|
||||||
|
completed = true;
|
||||||
|
cb({error: parsed.error});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// End of history: cb
|
||||||
|
if (parsed.state === 1 && parsed.channel) {
|
||||||
|
if (parsed.channel !== data.channel) { return; }
|
||||||
|
cb(msgs);
|
||||||
|
network.off('message', onMsg);
|
||||||
|
completed = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
msg = parsed[4];
|
||||||
|
// Keep only the history for our channel
|
||||||
|
if (parsed[3] !== data.channel) { return; }
|
||||||
|
if (msg) {
|
||||||
|
msg = msg.replace(/cp\|(([A-Za-z0-9+\/=]+)\|)?/, '');
|
||||||
|
msgs.push(msg);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
network.on('message', onMsg);
|
||||||
|
|
||||||
|
var cfg = {
|
||||||
|
lastKnownHash: data.lastKnownHash
|
||||||
|
};
|
||||||
|
var msg = ['GET_HISTORY', data.channel, cfg];
|
||||||
|
network.sendto(hk, JSON.stringify(msg));
|
||||||
};
|
};
|
||||||
|
|
||||||
Store.getHistoryRange = function (clientId, data, cb) {
|
Store.getHistoryRange = function (clientId, data, cb) {
|
||||||
var network = store.network;
|
var network = store.network;
|
||||||
var hkn = network.historyKeeper;
|
var hk = network.historyKeeper;
|
||||||
var parse = function (msg) {
|
var parse = function (msg) {
|
||||||
try {
|
try {
|
||||||
return JSON.parse(msg);
|
return JSON.parse(msg);
|
||||||
@@ -1779,7 +1838,7 @@ define([
|
|||||||
};
|
};
|
||||||
|
|
||||||
network.on('message', onMsg);
|
network.on('message', onMsg);
|
||||||
network.sendto(hkn, JSON.stringify(['GET_HISTORY_RANGE', data.channel, {
|
network.sendto(hk, JSON.stringify(['GET_HISTORY_RANGE', data.channel, {
|
||||||
from: data.lastKnownHash,
|
from: data.lastKnownHash,
|
||||||
cpCount: 2,
|
cpCount: 2,
|
||||||
txid: txid
|
txid: txid
|
||||||
|
|||||||
@@ -200,6 +200,41 @@ define([
|
|||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var reencrypt = function (ctx, data, cId, cb) {
|
||||||
|
var channel = data.channel;
|
||||||
|
var network = ctx.store.network;
|
||||||
|
|
||||||
|
var onOpen = function (wc) {
|
||||||
|
var hk = network.historyKeeper;
|
||||||
|
var cfg = {
|
||||||
|
metadata: data.metadata
|
||||||
|
};
|
||||||
|
var msg = ['GET_HISTORY', wc.id, cfg];
|
||||||
|
network.sendto(hk, JSON.stringify(msg));
|
||||||
|
data.msgs.forEach(function (msg) {
|
||||||
|
wc.bcast(msg);
|
||||||
|
});
|
||||||
|
wc.leave();
|
||||||
|
cb();
|
||||||
|
};
|
||||||
|
|
||||||
|
ctx.store.anon_rpc.send("IS_NEW_CHANNEL", channel, function (e, response) {
|
||||||
|
if (e) { return void cb({error: e}); }
|
||||||
|
var isNew;
|
||||||
|
if (response && response.length && typeof(response[0]) === 'boolean') {
|
||||||
|
isNew = response[0];
|
||||||
|
} else {
|
||||||
|
cb({error: 'INVALID_RESPONSE'});
|
||||||
|
}
|
||||||
|
if (!isNew) { return void cb({error: 'EEXISTS'}); }
|
||||||
|
|
||||||
|
// Channel is new: we can push our reencrypted history
|
||||||
|
network.join(channel).then(onOpen, function (err) {
|
||||||
|
return void cb({error: err});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
var leaveChannel = function (ctx, padChan) {
|
var leaveChannel = function (ctx, padChan) {
|
||||||
// Leave channel and prevent reconnect when we leave a pad
|
// Leave channel and prevent reconnect when we leave a pad
|
||||||
Object.keys(ctx.channels).some(function (ooChan) {
|
Object.keys(ctx.channels).some(function (ooChan) {
|
||||||
@@ -267,6 +302,9 @@ define([
|
|||||||
if (cmd === 'OPEN_CHANNEL') {
|
if (cmd === 'OPEN_CHANNEL') {
|
||||||
return void openChannel(ctx, data, clientId, cb);
|
return void openChannel(ctx, data, clientId, cb);
|
||||||
}
|
}
|
||||||
|
if (cmd === 'REENCRYPT') {
|
||||||
|
return void reencrypt(ctx, data, clientId, cb);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return oo;
|
return oo;
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ define([
|
|||||||
JOIN_PAD: Store.joinPad,
|
JOIN_PAD: Store.joinPad,
|
||||||
LEAVE_PAD: Store.leavePad,
|
LEAVE_PAD: Store.leavePad,
|
||||||
GET_FULL_HISTORY: Store.getFullHistory,
|
GET_FULL_HISTORY: Store.getFullHistory,
|
||||||
|
GET_HISTORY: Store.getHistory,
|
||||||
GET_HISTORY_RANGE: Store.getHistoryRange,
|
GET_HISTORY_RANGE: Store.getHistoryRange,
|
||||||
IS_NEW_CHANNEL: Store.isNewChannel,
|
IS_NEW_CHANNEL: Store.isNewChannel,
|
||||||
REQUEST_PAD_ACCESS: Store.requestPadAccess,
|
REQUEST_PAD_ACCESS: Store.requestPadAccess,
|
||||||
|
|||||||
@@ -493,6 +493,20 @@ define([
|
|||||||
Cryptpad.storeInTeam(data, cb);
|
Cryptpad.storeInTeam(data, cb);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
sframeChan.on('EV_GOTO_URL', function (url) {
|
||||||
|
if (url) {
|
||||||
|
window.location.href = url;
|
||||||
|
} else {
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
sframeChan.on('EV_OPEN_URL', function (url) {
|
||||||
|
if (url) {
|
||||||
|
window.open(url);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
addCommonRpc(sframeChan);
|
addCommonRpc(sframeChan);
|
||||||
|
|
||||||
@@ -956,20 +970,6 @@ define([
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
sframeChan.on('EV_GOTO_URL', function (url) {
|
|
||||||
if (url) {
|
|
||||||
window.location.href = url;
|
|
||||||
} else {
|
|
||||||
window.location.reload();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
sframeChan.on('EV_OPEN_URL', function (url) {
|
|
||||||
if (url) {
|
|
||||||
window.open(url);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
sframeChan.on('Q_PIN_GET_USAGE', function (teamId, cb) {
|
sframeChan.on('Q_PIN_GET_USAGE', function (teamId, cb) {
|
||||||
Cryptpad.isOverPinLimit(teamId, function (err, overLimit, data) {
|
Cryptpad.isOverPinLimit(teamId, function (err, overLimit, data) {
|
||||||
cb({
|
cb({
|
||||||
@@ -1008,6 +1008,11 @@ define([
|
|||||||
}, cb);
|
}, cb);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
sframeChan.on('Q_OO_PASSWORD_CHANGE', function (data, cb) {
|
||||||
|
data.href = data.href || window.location.href;
|
||||||
|
Cryptpad.changeOOPassword(data, cb);
|
||||||
|
});
|
||||||
|
|
||||||
sframeChan.on('Q_PAD_PASSWORD_CHANGE', function (data, cb) {
|
sframeChan.on('Q_PAD_PASSWORD_CHANGE', function (data, cb) {
|
||||||
data.href = data.href || window.location.href;
|
data.href = data.href || window.location.href;
|
||||||
Cryptpad.changePadPassword(Cryptget, Crypto, data, cb);
|
Cryptpad.changePadPassword(Cryptget, Crypto, data, cb);
|
||||||
|
|||||||
@@ -286,7 +286,7 @@ define([
|
|||||||
kanban.inEditMode = true;
|
kanban.inEditMode = true;
|
||||||
// create a form to enter element
|
// create a form to enter element
|
||||||
var boardId = $(el.parentNode.parentNode).attr("data-id");
|
var boardId = $(el.parentNode.parentNode).attr("data-id");
|
||||||
var $item = $('<div>', {'class': 'kanban-item'});
|
var $item = $('<div>', {'class': 'kanban-item new-item'});
|
||||||
var $input = getInput().val(name).appendTo($item);
|
var $input = getInput().val(name).appendTo($item);
|
||||||
kanban.addForm(boardId, $item[0]);
|
kanban.addForm(boardId, $item[0]);
|
||||||
$input.focus();
|
$input.focus();
|
||||||
|
|||||||
@@ -147,9 +147,13 @@
|
|||||||
self.drake = self.dragula(self.boardContainer, {
|
self.drake = self.dragula(self.boardContainer, {
|
||||||
moves: function (el, source, handle, sibling) {
|
moves: function (el, source, handle, sibling) {
|
||||||
if (self.options.readOnly) { return false; }
|
if (self.options.readOnly) { return false; }
|
||||||
|
if (el.classList.contains('new-item')) { return false; }
|
||||||
return handle.classList.contains('kanban-item');
|
return handle.classList.contains('kanban-item');
|
||||||
},
|
},
|
||||||
accepts: function (el, target, source, sibling) {
|
accepts: function (el, target, source, sibling) {
|
||||||
|
if (sibling === null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (self.options.readOnly) { return false; }
|
if (self.options.readOnly) { return false; }
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ define([
|
|||||||
'cp-settings-info-block',
|
'cp-settings-info-block',
|
||||||
'cp-settings-displayname',
|
'cp-settings-displayname',
|
||||||
'cp-settings-language-selector',
|
'cp-settings-language-selector',
|
||||||
|
'cp-settings-resettips',
|
||||||
'cp-settings-logout-everywhere',
|
'cp-settings-logout-everywhere',
|
||||||
'cp-settings-autostore',
|
'cp-settings-autostore',
|
||||||
'cp-settings-userfeedback',
|
'cp-settings-userfeedback',
|
||||||
@@ -67,7 +68,6 @@ define([
|
|||||||
],
|
],
|
||||||
'drive': [
|
'drive': [
|
||||||
'cp-settings-drive-duplicate',
|
'cp-settings-drive-duplicate',
|
||||||
'cp-settings-resettips',
|
|
||||||
'cp-settings-thumbnails',
|
'cp-settings-thumbnails',
|
||||||
'cp-settings-drive-backup',
|
'cp-settings-drive-backup',
|
||||||
'cp-settings-drive-import-local',
|
'cp-settings-drive-import-local',
|
||||||
@@ -835,7 +835,7 @@ define([
|
|||||||
var localStore = window.cryptpadStore;
|
var localStore = window.cryptpadStore;
|
||||||
$button.click(function () {
|
$button.click(function () {
|
||||||
Object.keys(localStore.store).forEach(function (k) {
|
Object.keys(localStore.store).forEach(function (k) {
|
||||||
if(k.slice(0, 9) === "hide-info") {
|
if(/^(hide-(info|alert))/.test(k)) {
|
||||||
localStore.put(k, null);
|
localStore.put(k, null);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user