manual merge of staging

This commit is contained in:
Caleb James DeLisle
2017-07-13 10:30:42 +02:00
61 changed files with 805 additions and 739 deletions

View File

@@ -19,12 +19,12 @@
], ],
"dependencies": { "dependencies": {
"jquery": "~2.1.3", "jquery": "~2.1.3",
"tweetnacl": "~0.12.2", "tweetnacl": "0.12.2",
"components-font-awesome": "^4.6.3", "components-font-awesome": "^4.6.3",
"ckeditor": "~4.7", "ckeditor": "~4.7",
"codemirror": "^5.19.0", "codemirror": "^5.19.0",
"requirejs": "~2.1.15", "requirejs": "2.1.15",
"marked": "~0.3.5", "marked": "0.3.5",
"rangy": "rangy-release#~1.3.0", "rangy": "rangy-release#~1.3.0",
"json.sortify": "~2.1.0", "json.sortify": "~2.1.0",
"secure-fabric.js": "secure-v1.7.9", "secure-fabric.js": "secure-v1.7.9",
@@ -33,12 +33,12 @@
"chainpad-json-validator": "^0.2.0", "chainpad-json-validator": "^0.2.0",
"chainpad-crypto": "^0.1.3", "chainpad-crypto": "^0.1.3",
"chainpad-listmap": "^0.3.0", "chainpad-listmap": "^0.3.0",
"file-saver": "^1.3.1", "file-saver": "1.3.1",
"diff-dom": "^2.1.1", "alertifyjs": "1.0.11",
"alertifyjs": "^1.0.11", "scrypt-async": "1.2.0",
"scrypt-async": "^1.2.0", "require-css": "0.1.10",
"require-css": "^0.1.10",
"less": "^2.7.2", "less": "^2.7.2",
"bootstrap": "#v4.0.0-alpha.6" "bootstrap": "#v4.0.0-alpha.6",
"diff-dom": "2.1.1"
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 KiB

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 99 KiB

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@@ -171,6 +171,10 @@ define([
$('button.gotodrive').click(function () { $('button.gotodrive').click(function () {
document.location.href = '/drive/'; document.location.href = '/drive/';
}); });
$('button#loggedInLogout').click(function () {
$('#user-menu .logout').click();
});
}; };
displayCreateButtons(); displayCreateButtons();

View File

@@ -444,7 +444,7 @@ define([
h('div#poll', [ h('div#poll', [
h('div#howItWorks', [ h('div#howItWorks', [
h('h1', 'CryptPoll'), h('h1', 'CryptPoll'),
h('h2', Msg.poll_subtitle), setHTML(h('h2'), Msg.poll_subtitle),
h('p', Msg.poll_p_save), h('p', Msg.poll_p_save),
h('p', Msg.poll_p_encryption) h('p', Msg.poll_p_encryption)
]), ]),

View File

@@ -112,7 +112,8 @@ h6 {
padding-top: .65001rem; padding-top: .65001rem;
} }
a:not(.btn) { p {
a:not(.btn) {
cursor: pointer; cursor: pointer;
color: @cp-link; color: @cp-link;
@@ -124,6 +125,7 @@ a:not(.btn) {
&:visited { &:visited {
color: @cp-link-visited; color: @cp-link-visited;
} }
}
} }
a.btn { a.btn {
font-family: sans-serif; font-family: sans-serif;

View File

@@ -21,6 +21,10 @@
margin-right: 0px; margin-right: 0px;
margin-left: 5px; margin-left: 5px;
} }
* {
.unselectable();
cursor: default;
}
} }
.dropdown-bar-content { .dropdown-bar-content {

View File

@@ -16,15 +16,28 @@
color: inherit; color: inherit;
} }
#cke_editor1 { .padColor { color: @toolbar-pad-bg; }
.cke_inner { .codeColor { color: @toolbar-code-bg; }
.slideColor { color: @toolbar-slide-bg; }
.pollColor { color: @toolbar-poll-bg; }
.fileColor { color: @toolbar-file-bg; }
.whiteboardColor { color: @toolbar-whiteboard-bg; }
.driveColor { color: @toolbar-drive-bg; }
.defaultColor { color: @toolbar-default-bg; }
.toolbar-container {
display: flex;
}
#cke_editor1 .cke_inner {
position: absolute;
top: 0;
left: 0;
bottom: 0; bottom: 0;
right: 0; right: 0;
display: flex; display: flex;
flex-flow: column; flex-flow: column;
height: 100vh; height: 100vh;
width: 100vw; width: 100vw;
}
} }
.cke_toolbox_main { .cke_toolbox_main {
display: inline-block; display: inline-block;
@@ -35,17 +48,12 @@
margin-top: -1px; margin-top: -1px;
display: flex; display: flex;
overflow: visible; overflow: visible;
iframe {
height: auto;
width: 100%;
}
} }
.padColor { color: @toolbar-pad-bg; }
.codeColor { color: @toolbar-code-bg; }
.slideColor { color: @toolbar-slide-bg; }
.pollColor { color: @toolbar-poll-bg; }
.fileColor { color: @toolbar-file-bg; }
.whiteboardColor { color: @toolbar-whiteboard-bg; }
.driveColor { color: @toolbar-drive-bg; }
.defaultColor { color: @toolbar-default-bg; }
body .userlist-drawer { body .userlist-drawer {
font: normal normal normal 16px Arial,Helvetica,Tahoma,Verdana,Sans-Serif; font: normal normal normal 16px Arial,Helvetica,Tahoma,Verdana,Sans-Serif;
min-width: 175px; min-width: 175px;
@@ -104,6 +112,51 @@ body .userlist-drawer {
background: rgba(0,0,0,0.1); background: rgba(0,0,0,0.1);
margin: 2px 0; margin: 2px 0;
font-size: 16px; font-size: 16px;
display: inline-flex;
align-items: center;
&.clickable {
cursor: pointer;
&:hover {
background-color: rgba(0,0,0,0.3);
}
}
.default, media-tag {
display: inline-flex;
width: 50px;
height: 50px;
justify-content: center;
align-items: center;
margin-right: 5px;
border-radius: 10px / 6px;
overflow: hidden;
border: 1px solid black;
box-sizing: content-box;
}
.default {
.unselectable();
background: white;
color: black;
font-size: 40px;
}
.name {
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
media-tag {
min-height: 50px;
min-width: 50px;
max-height: 50px;
max-width: 50px;
img {
min-width: 100%;
min-height: 100%;
max-width: none;
max-height: none; // To override 'media-tag img' in slide.less
flex-shrink: 0;
}
}
} }
} }
} }
@@ -718,6 +771,8 @@ body .cryptpad-toolbar {
padding: 0px; padding: 0px;
margin: 0; margin: 0;
&::before { &::before {
width: 100%;
text-align: center;
padding-top: 4px; padding-top: 4px;
} }
&:hover { &:hover {
@@ -796,11 +851,10 @@ body .cryptpad-toolbar {
width: 64px; width: 64px;
padding: 0; padding: 0;
span { span {
text-align: center;
width: 100%;
cursor: default; cursor: default;
font-size: 32px; font-size: 32px;
.fa {
margin-left: 3px;
}
} }
} }
} }
@@ -850,8 +904,10 @@ body .cryptpad-toolbar {
} }
} }
.cryptpad-toolbar-rightside { .cryptpad-toolbar-rightside {
height: 32px; min-height: 32px;
overflow: hidden;
&:empty { &:empty {
min-height: 0;
height: 0; height: 0;
} }
text-align: right; text-align: right;
@@ -873,7 +929,7 @@ body .cryptpad-toolbar {
background: @dropdown-bg; background: @dropdown-bg;
display: flex; display: flex;
flex-flow: column; flex-flow: column;
z-index:1000; z-index:10000;
color: black; color: black;
.fa { .fa {
font-size: 17px; font-size: 17px;
@@ -881,7 +937,7 @@ body .cryptpad-toolbar {
&> span { &> span {
box-sizing: border-box; box-sizing: border-box;
min-width: 150px; min-width: 150px;
height: 26px; height: 32px;
border-radius: 0; border-radius: 0;
border: 0; border: 0;
} }

View File

@@ -72,7 +72,7 @@
} }
} }
} }
a { &.link a {
font-weight: 500; font-weight: 500;
font-size: 0.75em; font-size: 0.75em;
color: @cp-link; color: @cp-link;

View File

@@ -240,6 +240,18 @@ define(function () {
out.canvas_opacityLabel = "opacité: {0}"; out.canvas_opacityLabel = "opacité: {0}";
out.canvas_widthLabel = "taille: {0}"; out.canvas_widthLabel = "taille: {0}";
// Profile
out.profileButton = "Profil"; // dropdown menu
out.profile_urlPlaceholder = 'URL';
out.profile_namePlaceholder = 'Nom ou pseudo pour le profil';
out.profile_avatar = "Avatar";
out.profile_upload = " Importer un nouvel avatar";
out.profile_error = "Erreur lors de la création du profil : {0}";
out.profile_register = "Vous devez vous inscrire pour pouvoir créer un profil !";
out.profile_create = "Créer un profil";
out.profile_description = "Description";
out.profile_fieldSaved = 'Nouvelle valeur enregistrée: {0}';
// File manager // File manager
out.fm_rootName = "Documents"; out.fm_rootName = "Documents";

View File

@@ -242,6 +242,17 @@ define(function () {
out.canvas_opacityLabel = "opacity: {0}"; out.canvas_opacityLabel = "opacity: {0}";
out.canvas_widthLabel = "Width: {0}"; out.canvas_widthLabel = "Width: {0}";
// Profile
out.profileButton = "Profile"; // dropdown menu
out.profile_urlPlaceholder = 'URL';
out.profile_namePlaceholder = 'Name displayed in your profile';
out.profile_avatar = "Avatar";
out.profile_upload = " Upload a new avatar";
out.profile_error = "Error while creating your profile: {0}";
out.profile_register = "You have to sign up to create a profile!";
out.profile_create = "Create a profile";
out.profile_description = "Description";
out.profile_fieldSaved = 'New value saved: {0}';
// File manager // File manager

View File

@@ -1,7 +1,7 @@
{ {
"name": "cryptpad", "name": "cryptpad",
"description": "realtime collaborative visual editor with zero knowlege server", "description": "realtime collaborative visual editor with zero knowlege server",
"version": "1.9.0-1", "version": "1.10.0",
"dependencies": { "dependencies": {
"chainpad-server": "^1.0.1", "chainpad-server": "^1.0.1",
"express": "~4.10.1", "express": "~4.10.1",

View File

@@ -30,7 +30,7 @@ const sizeForHashes = (hashes, dsFileStats) => {
let sum = 0; let sum = 0;
hashes.forEach((h) => { hashes.forEach((h) => {
const s = dsFileStats[h]; const s = dsFileStats[h];
if (typeof(s) !== 'number') { if (typeof(s) !== 'object' || typeof(s.size) !== 'number') {
//console.log('missing ' + h + ' ' + typeof(s)); //console.log('missing ' + h + ' ' + typeof(s));
} else { } else {
sum += s.size; sum += s.size;
@@ -62,11 +62,26 @@ nThen((waitFor) => {
}); });
}); });
}).nThen((waitFor) => { }).nThen((waitFor) => {
Fs.readdir('./blob', waitFor((err, list) => {
if (err) { throw err; }
dirList = list;
}));
}).nThen((waitFor) => {
dirList.forEach((f) => {
sema.take((returnAfter) => {
Fs.readdir('./blob/' + f, waitFor(returnAfter((err, list2) => {
if (err) { throw err; }
list2.forEach((ff) => { fileList.push('./blob/' + f + '/' + ff); });
})));
});
});
}).nThen((waitFor) => {
fileList.forEach((f) => { fileList.forEach((f) => {
sema.take((returnAfter) => { sema.take((returnAfter) => {
Fs.stat(f, waitFor(returnAfter((err, st) => { Fs.stat(f, waitFor(returnAfter((err, st) => {
if (err) { throw err; } if (err) { throw err; }
dsFileStats[f.replace(/^.*\/([^\/]*)\.ndjson$/, (all, a) => (a))] = st; dsFileStats[f.replace(/^.*\/([^\/\.]*)(\.ndjson)?$/, (all, a) => (a))] = st;
}))); })));
}); });
}); });

62
rpc.js
View File

@@ -281,7 +281,7 @@ var getUploadSize = function (Env, channel, cb) {
var paths = Env.paths; var paths = Env.paths;
var path = makeFilePath(paths.blob, channel); var path = makeFilePath(paths.blob, channel);
if (!path) { if (!path) {
return cb('INVALID_UPLOAD_ID'); return cb('INVALID_UPLOAD_ID', path);
} }
Fs.stat(path, function (err, stats) { Fs.stat(path, function (err, stats) {
@@ -583,9 +583,10 @@ var resetUserPins = function (Env, publicKey, channelList, cb) {
if (e) { return void cb(e); } if (e) { return void cb(e); }
var pinSize = sumChannelSizes(sizes); var pinSize = sumChannelSizes(sizes);
getFreeSpace(Env, publicKey, function (e, free) {
getLimit(Env, publicKey, function (e, limit) {
if (e) { if (e) {
WARN('getFreeSpace', e); WARN('[RESET_ERR]', e);
return void cb(e); return void cb(e);
} }
@@ -597,7 +598,7 @@ var resetUserPins = function (Env, publicKey, channelList, cb) {
They will not be able to pin additional pads until they upgrade They will not be able to pin additional pads until they upgrade
or delete enough files to go back under their limit. */ or delete enough files to go back under their limit. */
if (pinSize > free && session.hasPinned) { return void(cb('E_OVER_LIMIT')); } if (pinSize > limit && session.hasPinned) { return void(cb('E_OVER_LIMIT')); }
pinStore.message(publicKey, JSON.stringify(['RESET', channelList]), pinStore.message(publicKey, JSON.stringify(['RESET', channelList]),
function (e) { function (e) {
if (e) { return void cb(e); } if (e) { return void cb(e); }
@@ -826,6 +827,13 @@ var upload_status = function (Env, publicKey, filesize, cb) {
}); });
}; };
var isUnauthenticatedCall = function (call) {
return [
'GET_FILE_SIZE',
'GET_MULTIPLE_FILE_SIZE',
].indexOf(call) !== -1;
};
var isAuthenticatedCall = function (call) { var isAuthenticatedCall = function (call) {
return [ return [
'COOKIE', 'COOKIE',
@@ -834,11 +842,8 @@ var isAuthenticatedCall = function (call) {
'UNPIN', 'UNPIN',
'GET_HASH', 'GET_HASH',
'GET_TOTAL_SIZE', 'GET_TOTAL_SIZE',
'GET_FILE_SIZE',
'UPDATE_LIMITS', 'UPDATE_LIMITS',
'GET_LIMIT', 'GET_LIMIT',
'GET_MULTIPLE_FILE_SIZE',
//'UPLOAD',
'UPLOAD_COMPLETE', 'UPLOAD_COMPLETE',
'UPLOAD_CANCEL', 'UPLOAD_CANCEL',
].indexOf(call) !== -1; ].indexOf(call) !== -1;
@@ -867,6 +872,34 @@ RPC.create = function (config /*:typeof(ConfigType)*/, cb /*:(?Error, ?Function)
var blobPath = paths.blob = keyOrDefaultString('blobPath', './blob'); var blobPath = paths.blob = keyOrDefaultString('blobPath', './blob');
var blobStagingPath = paths.staging = keyOrDefaultString('blobStagingPath', './blobstage'); var blobStagingPath = paths.staging = keyOrDefaultString('blobStagingPath', './blobstage');
var isUnauthenticateMessage = function (msg) {
return msg && msg.length === 2 && isUnauthenticatedCall(msg[0]);
};
var handleUnauthenticatedMessage = function (msg, respond) {
switch (msg[0]) {
case 'GET_FILE_SIZE':
return void getFileSize(Env, msg[1], function (e, size) {
if (e) {
console.error(e);
}
WARN(e, msg[1]);
respond(e, [null, size, null]);
});
case 'GET_MULTIPLE_FILE_SIZE':
return void getMultipleFileSize(Env, msg[1], function (e, dict) {
if (e) {
WARN(e, dict);
return respond(e);
}
respond(e, [null, dict, null]);
});
default:
console.error("unsupported!");
return respond('UNSUPPORTED_RPC_CALL', msg);
}
};
var rpc = function ( var rpc = function (
ctx /*:{ store: Object }*/, ctx /*:{ store: Object }*/,
data /*:Array<Array<any>>*/, data /*:Array<Array<any>>*/,
@@ -888,11 +921,19 @@ RPC.create = function (config /*:typeof(ConfigType)*/, cb /*:(?Error, ?Function)
return void respond('INVALID_ARG_FORMAT'); return void respond('INVALID_ARG_FORMAT');
} }
if (isUnauthenticateMessage(msg)) {
return handleUnauthenticatedMessage(msg, respond);
}
var signature = msg.shift(); var signature = msg.shift();
var publicKey = msg.shift(); var publicKey = msg.shift();
// make sure a user object is initialized in the cookie jar // make sure a user object is initialized in the cookie jar
if (publicKey) {
beginSession(Sessions, publicKey); beginSession(Sessions, publicKey);
} else {
console.log("No public key");
}
var cookie = msg[0]; var cookie = msg[0];
if (!isValidCookie(Sessions, publicKey, cookie)) { if (!isValidCookie(Sessions, publicKey, cookie)) {
@@ -928,7 +969,8 @@ RPC.create = function (config /*:typeof(ConfigType)*/, cb /*:(?Error, ?Function)
msg.shift(); msg.shift();
var Respond = function (e, msg) { var Respond = function (e, msg) {
var token = Sessions[safeKey].tokens.slice(-1)[0]; var session = Sessions[safeKey];
var token = session? session.tokens.slice(-1)[0]: '';
var cookie = makeCookie(token).join('|'); var cookie = makeCookie(token).join('|');
respond(e, [cookie].concat(typeof(msg) !== 'undefined' ?msg: [])); respond(e, [cookie].concat(typeof(msg) !== 'undefined' ?msg: []));
}; };
@@ -1046,8 +1088,8 @@ RPC.create = function (config /*:typeof(ConfigType)*/, cb /*:(?Error, ?Function)
return void handleMessage(false); return void handleMessage(false);
} }
// restrict upload capability unless explicitly disabled // allow unrestricted uploads unless restrictUploads is true
if (config.restrictUploads === false) { if (config.restrictUploads !== true) {
return void handleMessage(true); return void handleMessage(true);
} }

View File

@@ -3,33 +3,6 @@
<head> <head>
<meta content="text/html; charset=utf-8" http-equiv="content-type"/> <meta content="text/html; charset=utf-8" http-equiv="content-type"/>
<script src="/bower_components/jquery/dist/jquery.min.js"></script> <script src="/bower_components/jquery/dist/jquery.min.js"></script>
<script src="/bower_components/codemirror/lib/codemirror.js"></script>
<link rel="stylesheet" href="/bower_components/codemirror/lib/codemirror.css">
<link rel="stylesheet" href="/bower_components/codemirror/addon/dialog/dialog.css">
<link rel="stylesheet" href="/bower_components/codemirror/addon/fold/foldgutter.css" />
<script src="/bower_components/codemirror/mode/javascript/javascript.js"></script>
<script src="/bower_components/codemirror/addon/mode/loadmode.js"></script>
<script src="/bower_components/codemirror/mode/meta.js"></script>
<script src="/bower_components/codemirror/addon/mode/overlay.js"></script>
<script src="/bower_components/codemirror/addon/mode/multiplex.js"></script>
<script src="/bower_components/codemirror/addon/mode/simple.js"></script>
<script src="/bower_components/codemirror/addon/edit/closebrackets.js"></script>
<script src="/bower_components/codemirror/addon/edit/matchbrackets.js"></script>
<script src="/bower_components/codemirror/addon/edit/trailingspace.js"></script>
<script src="/bower_components/codemirror/addon/selection/active-line.js"></script>
<script src="/bower_components/codemirror/addon/search/search.js"></script>
<script src="/bower_components/codemirror/addon/search/match-highlighter.js"></script>
<script src="/bower_components/codemirror/addon/search/searchcursor.js"></script>
<script src="/bower_components/codemirror/addon/dialog/dialog.js"></script>
<script src="/bower_components/codemirror/addon/fold/foldcode.js"></script>
<script src="/bower_components/codemirror/addon/fold/foldgutter.js"></script>
<script src="/bower_components/codemirror/addon/fold/brace-fold.js"></script>
<script src="/bower_components/codemirror/addon/fold/xml-fold.js"></script>
<script src="/bower_components/codemirror/addon/fold/markdown-fold.js"></script>
<script src="/bower_components/codemirror/addon/fold/comment-fold.js"></script>
<script src="/bower_components/codemirror/addon/display/placeholder.js"></script>
<script async data-bootload="inner.js" data-main="/common/boot.js?ver=1.0" src="/bower_components/requirejs/require.js?ver=2.1.15"></script> <script async data-bootload="inner.js" data-main="/common/boot.js?ver=1.0" src="/bower_components/requirejs/require.js?ver=2.1.15"></script>
<style> .loading-hidden { display: none; } </style> <style> .loading-hidden { display: none; } </style>
</head> </head>

View File

@@ -1,8 +1,37 @@
define([ define([
'jquery', 'jquery',
'cm/lib/codemirror',
'css!/bower_components/components-font-awesome/css/font-awesome.min.css', 'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/code/code.less', 'less!/code/code.less',
'less!/customize/src/less/toolbar.less', 'less!/customize/src/less/toolbar.less',
], function ($) { 'css!cm/lib/codemirror.css',
'css!cm/addon/dialog/dialog.css',
'css!cm/addon/fold/foldgutter.css',
'cm/mode/markdown/markdown',
'cm/addon/mode/loadmode',
'cm/mode/meta',
'cm/addon/mode/overlay',
'cm/addon/mode/multiplex',
'cm/addon/mode/simple',
'cm/addon/edit/closebrackets',
'cm/addon/edit/matchbrackets',
'cm/addon/edit/trailingspace',
'cm/addon/selection/active-line',
'cm/addon/search/search',
'cm/addon/search/match-highlighter',
'cm/addon/search/searchcursor',
'cm/addon/dialog/dialog',
'cm/addon/fold/foldcode',
'cm/addon/fold/foldgutter',
'cm/addon/fold/brace-fold',
'cm/addon/fold/xml-fold',
'cm/addon/fold/markdown-fold',
'cm/addon/fold/comment-fold',
'cm/addon/display/placeholder',
], function ($, CMeditor) {
window.CodeMirror = CMeditor;
$('.loading-hidden').removeClass('loading-hidden'); $('.loading-hidden').removeClass('loading-hidden');
}); });

View File

@@ -9,7 +9,6 @@ define([
'/common/cryptpad-common.js', '/common/cryptpad-common.js',
'/common/cryptget.js', '/common/cryptget.js',
'/common/diffMarked.js', '/common/diffMarked.js',
'/bower_components/tweetnacl/nacl-fast.min.js', // needed for media-tag
'css!/bower_components/components-font-awesome/css/font-awesome.min.css', 'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/customize/src/less/cryptpad.less' 'less!/customize/src/less/cryptpad.less'
@@ -58,7 +57,7 @@ define([
} }
}); });
var CodeMirror = Cryptpad.createCodemirror(CMeditor, ifrw, Cryptpad); var CodeMirror = Cryptpad.createCodemirror(ifrw, Cryptpad, null, CMeditor);
$iframe.find('.CodeMirror').addClass('fullPage'); $iframe.find('.CodeMirror').addClass('fullPage');
editor = CodeMirror.editor; editor = CodeMirror.editor;
@@ -429,7 +428,6 @@ define([
}; };
var interval = 100; var interval = 100;
var second = function (CM) { var second = function (CM) {
Cryptpad.ready(function () { Cryptpad.ready(function () {
andThen(CM); andThen(CM);
@@ -444,11 +442,9 @@ define([
var first = function () { var first = function () {
if (ifrw.CodeMirror) { if (ifrw.CodeMirror) {
// it exists, call your continuation
second(ifrw.CodeMirror); second(ifrw.CodeMirror);
} else { } else {
console.log("CodeMirror was not defined. Trying again in %sms", interval); console.log("CodeMirror was not defined. Trying again in %sms", interval);
// try again in 'interval' ms
setTimeout(first, interval); setTimeout(first, interval);
} }
}; };

View File

@@ -10,6 +10,7 @@ define([], function () {
"json.sortify": "/bower_components/json.sortify/dist/JSON.sortify", "json.sortify": "/bower_components/json.sortify/dist/JSON.sortify",
//"pdfjs-dist/build/pdf": "/bower_components/pdfjs-dist/build/pdf", //"pdfjs-dist/build/pdf": "/bower_components/pdfjs-dist/build/pdf",
//"pdfjs-dist/build/pdf.worker": "/bower_components/pdfjs-dist/build/pdf.worker" //"pdfjs-dist/build/pdf.worker": "/bower_components/pdfjs-dist/build/pdf.worker"
cm: '/bower_components/codemirror'
}, },
map: { map: {
'*': { '*': {

View File

@@ -2,18 +2,18 @@ define([
'jquery', 'jquery',
'/common/modes.js', '/common/modes.js',
'/common/themes.js', '/common/themes.js',
'/bower_components/file-saver/FileSaver.min.js' '/bower_components/file-saver/FileSaver.min.js'
], function ($, Modes, Themes) { ], function ($, Modes, Themes) {
var saveAs = window.saveAs; var saveAs = window.saveAs;
var module = {}; var module = {};
module.create = function (CMeditor, ifrw, Cryptpad) { module.create = function (ifrw, Cryptpad, defaultMode, CMeditor) {
var exp = {}; var exp = {};
var Messages = Cryptpad.Messages; var Messages = Cryptpad.Messages;
var CodeMirror = exp.CodeMirror = CMeditor; var CodeMirror = exp.CodeMirror = CMeditor;
CodeMirror.modeURL = "/bower_components/codemirror/mode/%N/%N.js"; CodeMirror.modeURL = "cm/mode/%N/%N";
var $pad = $('#pad-iframe'); var $pad = $('#pad-iframe');
var $textarea = exp.$textarea = $pad.contents().find('#editor1'); var $textarea = exp.$textarea = $pad.contents().find('#editor1');
@@ -43,14 +43,16 @@ define([
extraKeys: {"Shift-Ctrl-R": undefined}, extraKeys: {"Shift-Ctrl-R": undefined},
foldGutter: true, foldGutter: true,
gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"], gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"],
mode: "javascript", mode: defaultMode || "javascript",
readOnly: true readOnly: true
}); });
editor.setValue(Messages.codeInitialState); editor.setValue(Messages.codeInitialState);
var setMode = exp.setMode = function (mode, cb) { var setMode = exp.setMode = function (mode, cb) {
exp.highlightMode = mode; exp.highlightMode = mode;
if (mode !== "text") { CMeditor.autoLoadMode(editor, mode); } if (mode !== "text") {
CMeditor.autoLoadMode(editor, mode);
}
editor.setOption('mode', mode); editor.setOption('mode', mode);
if (exp.$language) { if (exp.$language) {
var name = exp.$language.find('a[data-value="' + mode + '"]').text() || undefined; var name = exp.$language.find('a[data-value="' + mode + '"]').text() || undefined;

View File

@@ -1,4 +1,4 @@
define(function () { define(['jquery'], function ($) {
var module = {}; var module = {};
module.create = function (cfg, onLocal, Cryptpad) { module.create = function (cfg, onLocal, Cryptpad) {
@@ -45,7 +45,8 @@ define(function () {
}; };
// update title: href is optional; if not specified, we use window.location.href // update title: href is optional; if not specified, we use window.location.href
exp.updateTitle = function (newTitle, href) { exp.updateTitle = function (newTitle, href, cb) {
cb = cb || $.noop;
if (newTitle === exp.title) { return; } if (newTitle === exp.title) { return; }
// Change the title now, and set it back to the old value if there is an error // Change the title now, and set it back to the old value if there is an error
var oldTitle = exp.title; var oldTitle = exp.title;
@@ -54,9 +55,10 @@ define(function () {
console.log("Couldn't set pad title"); console.log("Couldn't set pad title");
console.error(err); console.error(err);
updateLocalTitle(oldTitle); updateLocalTitle(oldTitle);
return; return void cb(err);
} }
updateLocalTitle(data); updateLocalTitle(data);
cb(null, data);
if (!$title) { return; } if (!$title) { return; }
$title.find('span.title').text(data); $title.find('span.title').text(data);
$title.find('input').val(data); $title.find('input').val(data);

View File

@@ -51,6 +51,8 @@ define(function () {
myData[exp.myNetfluxId] = { myData[exp.myNetfluxId] = {
name: exp.myUserName, name: exp.myUserName,
uid: Cryptpad.getUid(), uid: Cryptpad.getUid(),
avatar: Cryptpad.getAvatarUrl(),
profile: Cryptpad.getProfileUrl()
}; };
addToUserData(myData); addToUserData(myData);
Cryptpad.setAttribute('username', exp.myUserName, function (err) { Cryptpad.setAttribute('username', exp.myUserName, function (err) {
@@ -78,6 +80,8 @@ define(function () {
myData[exp.myNetfluxId] = { myData[exp.myNetfluxId] = {
name: "", name: "",
uid: Cryptpad.getUid(), uid: Cryptpad.getUid(),
avatar: Cryptpad.getAvatarUrl(),
profile: Cryptpad.getProfileUrl()
}; };
addToUserData(myData); addToUserData(myData);
onLocal(); onLocal();

View File

@@ -16,9 +16,10 @@ define([
'/common/clipboard.js', '/common/clipboard.js',
'/common/pinpad.js', '/common/pinpad.js',
'/customize/application_config.js' '/customize/application_config.js',
'/common/media-tag.js',
], function ($, Config, Messages, Store, Util, Hash, UI, History, UserList, Title, Metadata, ], function ($, Config, Messages, Store, Util, Hash, UI, History, UserList, Title, Metadata,
CodeMirror, Files, FileCrypto, Clipboard, Pinpad, AppConfig) { CodeMirror, Files, FileCrypto, Clipboard, Pinpad, AppConfig, MediaTag) {
/* 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
@@ -49,6 +50,7 @@ define([
var store; var store;
var rpc; var rpc;
var anon_rpc;
// import UI elements // import UI elements
common.findCancelButton = UI.findCancelButton; common.findCancelButton = UI.findCancelButton;
@@ -76,7 +78,7 @@ define([
var deduplicateString = common.deduplicateString = Util.deduplicateString; var deduplicateString = common.deduplicateString = Util.deduplicateString;
common.uint8ArrayToHex = Util.uint8ArrayToHex; common.uint8ArrayToHex = Util.uint8ArrayToHex;
common.replaceHash = Util.replaceHash; common.replaceHash = Util.replaceHash;
var getHash = common.getHash = Util.getHash; common.getHash = Util.getHash;
common.fixFileName = Util.fixFileName; common.fixFileName = Util.fixFileName;
common.bytesToMegabytes = Util.bytesToMegabytes; common.bytesToMegabytes = Util.bytesToMegabytes;
common.bytesToKilobytes = Util.bytesToKilobytes; common.bytesToKilobytes = Util.bytesToKilobytes;
@@ -146,6 +148,16 @@ define([
} }
return; return;
}; };
common.getProfileUrl = function () {
if (store && store.getProfile()) {
return store.getProfile().view;
}
};
common.getAvatarUrl = function () {
if (store && store.getProfile()) {
return store.getProfile().avatar;
}
};
var feedback = common.feedback = function (action, force) { var feedback = common.feedback = function (action, force) {
if (force !== true) { if (force !== true) {
@@ -414,9 +426,8 @@ define([
// STORAGE // STORAGE
common.setPadAttribute = function (attr, value, cb) { common.setPadAttribute = function (attr, value, cb) {
getStore().setDrive([getHash(), attr].join('.'), value, function (err, data) { var href = getRelativeHref(window.location.href);
cb(err, data); getStore().setPadAttribute(href, attr, value, cb);
});
}; };
common.setAttribute = function (attr, value, cb) { common.setAttribute = function (attr, value, cb) {
getStore().set(["cryptpad", attr].join('.'), value, function (err, data) { getStore().set(["cryptpad", attr].join('.'), value, function (err, data) {
@@ -429,9 +440,8 @@ define([
// STORAGE // STORAGE
common.getPadAttribute = function (attr, cb) { common.getPadAttribute = function (attr, cb) {
getStore().getDrive([getHash(), attr].join('.'), function (err, data) { var href = getRelativeHref(window.location.href);
cb(err, data); getStore().getPadAttribute(href, attr, cb);
});
}; };
common.getAttribute = function (attr, cb) { common.getAttribute = function (attr, cb) {
getStore().get(["cryptpad", attr].join('.'), function (err, data) { getStore().get(["cryptpad", attr].join('.'), function (err, data) {
@@ -777,11 +787,32 @@ define([
}; };
common.getFileSize = function (href, cb) { common.getFileSize = function (href, cb) {
if (!pinsReady()) { return void cb('RPC_NOT_READY'); } if (!anon_rpc) { return void cb('ANON_RPC_NOT_READY'); }
//if (!pinsReady()) { return void cb('RPC_NOT_READY'); }
var channelId = Hash.hrefToHexChannelId(href); var channelId = Hash.hrefToHexChannelId(href);
rpc.getFileSize(channelId, function (e, bytes) { anon_rpc.send("GET_FILE_SIZE", channelId, function (e, response) {
if (e) { return void cb(e); } if (e) { return void cb(e); }
cb(void 0, bytes); if (response && response.length && typeof(response[0]) === 'number') {
return void cb(void 0, response[0]);
} else {
cb('INVALID_RESPONSE');
}
});
};
common.getMultipleFileSize = function (files, cb) {
if (!anon_rpc) { return void cb('ANON_RPC_NOT_READY'); }
if (!Array.isArray(files)) {
return void setTimeout(function () { cb('INVALID_FILE_LIST'); });
}
anon_rpc.send('GET_MULTIPLE_FILE_SIZE', files, function (e, res) {
if (e) { return cb(e); }
if (res && res.length && typeof(res[0]) === 'object') {
cb(void 0, res[0]);
} else {
cb('UNEXPECTED_RESPONSE');
}
}); });
}; };
@@ -800,7 +831,9 @@ define([
if (!pinsReady()) { return void cb('RPC_NOT_READY'); } if (!pinsReady()) { return void cb('RPC_NOT_READY'); }
var account = common.account; var account = common.account;
if (typeof(account.limit) !== 'number' ||
var ALWAYS_REVALIDATE = true;
if (ALWAYS_REVALIDATE || typeof(account.limit) !== 'number' ||
typeof(account.plan) !== 'string' || typeof(account.plan) !== 'string' ||
typeof(account.note) !== 'string') { typeof(account.note) !== 'string') {
return void rpc.getLimit(function (e, limit, plan, note) { return void rpc.getLimit(function (e, limit, plan, note) {
@@ -863,7 +896,6 @@ define([
var $container = $('<span>', {'class':'limit-container'}); var $container = $('<span>', {'class':'limit-container'});
var todo; var todo;
var updateUsage = window.updateUsage = common.notAgainForAnother(function () { var updateUsage = window.updateUsage = common.notAgainForAnother(function () {
console.log("updating usage bar");
common.getPinnedUsage(todo); common.getPinnedUsage(todo);
}, LIMIT_REFRESH_RATE); }, LIMIT_REFRESH_RATE);
@@ -933,21 +965,12 @@ define([
}; };
setInterval(function () { setInterval(function () {
var t = updateUsage(); updateUsage();
if (t) {
console.log("usage already updated. eligible for refresh in %sms", t);
}
}, LIMIT_REFRESH_RATE * 3); }, LIMIT_REFRESH_RATE * 3);
updateUsage(); updateUsage();
getProxy().on('change', ['drive'], function () { getProxy().on('change', ['drive'], function () {
var t = updateUsage(); updateUsage();
if (t) {
console.log("usage bar update throttled due to overuse." +
" Eligible for update in %sms", t);
} else {
console.log("usage bar updated");
}
}); });
cb(null, $container); cb(null, $container);
}; };
@@ -1162,16 +1185,82 @@ define([
return button; return button;
}; };
var emoji_patt = /([\uD800-\uDBFF][\uDC00-\uDFFF])/;
var isEmoji = function (str) {
return emoji_patt.test(str);
};
var emojiStringToArray = function (str) {
var split = str.split(emoji_patt);
var arr = [];
for (var i=0; i<split.length; i++) {
var char = split[i];
if (char !== "") {
arr.push(char);
}
}
return arr;
};
var getFirstEmojiOrCharacter = function (str) {
if (!str || !str.trim()) { return '?'; }
var emojis = emojiStringToArray(str);
return isEmoji(emojis[0])? emojis[0]: str[0];
};
$(window.document).on('decryption', function (e) {
var decrypted = e.originalEvent;
if (decrypted.callback) {
var cb = decrypted.callback;
cb(function (mediaObject) {
if (mediaObject.type !== 'download') { return; }
var root = mediaObject.rootElement;
if (!root) { return; }
var metadata = decrypted.metadata;
var title = '';
var size = 0;
if (metadata && metadata.name) {
title = metadata.name;
}
if (decrypted.blob) {
size = decrypted.blob.size;
}
var sizeMb = common.bytesToMegabytes(size);
var $btn = $(root).find('button');
$btn.addClass('btn btn-success')
.attr('type', 'download')
.html(function () {
var text = Messages.download_mt_button + '<br>';
if (title) {
text += '<b>' + common.fixHTML(title) + '</b><br>';
}
if (size) {
text += '<em>' + Messages._getKey('formattedMB', [sizeMb]) + '</em>';
}
return text;
});
});
}
});
common.avatarAllowedTypes = [ common.avatarAllowedTypes = [
'image/png', 'image/png',
'image/jpeg', 'image/jpeg',
'image/jpg', 'image/jpg',
'image/gif', 'image/gif',
]; ];
common.displayAvatar = function ($container, href) { common.displayAvatar = function ($container, href, name, cb) {
var MutationObserver = window.MutationObserver; var MutationObserver = window.MutationObserver;
$container.html(''); var displayDefault = function () {
if (href) { var text = getFirstEmojiOrCharacter(name);
var $avatar = $('<span>', {'class': 'default'}).text(text);
$container.append($avatar);
if (cb) { cb(); }
};
if (!href) { return void displayDefault(); }
var parsed = common.parsePadUrl(href); var parsed = common.parsePadUrl(href);
var secret = common.getSecrets('file', parsed.hash); var secret = common.getSecrets('file', parsed.hash);
if (secret.keys && secret.channel) { if (secret.keys && secret.channel) {
@@ -1179,24 +1268,23 @@ define([
var hexFileName = common.base64ToHex(secret.channel); var hexFileName = common.base64ToHex(secret.channel);
var src = common.getBlobPathFromHex(hexFileName); var src = common.getBlobPathFromHex(hexFileName);
common.getFileSize(href, function (e, data) { common.getFileSize(href, function (e, data) {
if (e) { return void console.error(e); } if (e) {
if (typeof data !== "number") { return; } displayDefault();
if (common.bytesToMegabytes(data) > 0.5) { return; } return void console.error(e);
}
if (typeof data !== "number") { return void displayDefault(); }
if (common.bytesToMegabytes(data) > 0.5) { return void displayDefault(); }
var $img = $('<media-tag>').appendTo($container); var $img = $('<media-tag>').appendTo($container);
$img.attr('src', src); $img.attr('src', src);
$img.attr('data-crypto-key', 'cryptpad:' + cryptKey); $img.attr('data-crypto-key', 'cryptpad:' + cryptKey);
require(['/common/media-tag.js'], function (MediaTag) {
MediaTag.CryptoFilter.setAllowedMediaTypes(common.avatarAllowedTypes);
MediaTag($img[0]); MediaTag($img[0]);
var observer = new MutationObserver(function(mutations) { var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) { mutations.forEach(function(mutation) {
if (mutation.type === 'childList' && mutation.addedNodes.length) { if (mutation.type === 'childList' && mutation.addedNodes.length) {
console.log(mutation);
if (mutation.addedNodes.length > 1 || if (mutation.addedNodes.length > 1 ||
mutation.addedNodes[0].nodeName !== 'IMG') { mutation.addedNodes[0].nodeName !== 'IMG') {
$img.remove(); $img.remove();
return; return void displayDefault();
//TODO display default avatar
} }
var $image = $img.find('img'); var $image = $img.find('img');
var onLoad = function () { var onLoad = function () {
@@ -1205,16 +1293,17 @@ define([
if (w>h) { if (w>h) {
$image.css('max-height', '100%'); $image.css('max-height', '100%');
$img.css('flex-direction', 'row'); $img.css('flex-direction', 'row');
if (cb) { cb($img); }
return; return;
} }
$image.css('max-width', '100%'); $image.css('max-width', '100%');
$img.css('flex-direction', 'column'); $img.css('flex-direction', 'column');
if (cb) { cb($img); }
}; };
if ($image[0].complete) { onLoad(); } if ($image[0].complete) { onLoad(); }
$image.on('load', onLoad); $image.on('load', onLoad);
} }
}); });
});
observer.observe($img[0], { observer.observe($img[0], {
attributes: false, attributes: false,
childList: true, childList: true,
@@ -1223,7 +1312,6 @@ define([
}); });
}); });
} }
}
}; };
// Create a button with a dropdown menu // Create a button with a dropdown menu
@@ -1301,7 +1389,7 @@ define([
setActive($val); setActive($val);
$innerblock.scrollTop($val.position().top + $innerblock.scrollTop()); $innerblock.scrollTop($val.position().top + $innerblock.scrollTop());
} }
if (config.feedback) { common.feedback(config.feedback); } if (config.feedback && store) { common.feedback(config.feedback); }
}; };
$container.click(function (e) { $container.click(function (e) {
@@ -1457,6 +1545,13 @@ define([
content: Messages.user_rename content: Messages.user_rename
}); });
} }
if (account) {
options.push({
tag: 'a',
attributes: {'class': 'profile'},
content: Messages.profileButton
});
}
if (parsed && (!parsed.type || parsed.type !== 'settings')) { if (parsed && (!parsed.type || parsed.type !== 'settings')) {
options.push({ options.push({
tag: 'a', tag: 'a',
@@ -1516,6 +1611,13 @@ define([
window.location.href = '/settings/'; window.location.href = '/settings/';
} }
}); });
$userAdmin.find('a.profile').click(function () {
if (parsed && parsed.type) {
window.open('/profile/');
} else {
window.location.href = '/profile/';
}
});
$userAdmin.find('a.login').click(function () { $userAdmin.find('a.login').click(function () {
if (window.location.pathname !== "/") { if (window.location.pathname !== "/") {
sessionStorage.redirectTo = window.location.href; sessionStorage.redirectTo = window.location.href;
@@ -1666,6 +1768,21 @@ define([
console.log('pinning disabled'); console.log('pinning disabled');
} }
block++;
require([
'/common/rpc.js',
], function (Rpc) {
Rpc.createAnonymous(network, function (e, call) {
if (e) {
console.error(e);
return void cb();
}
anon_rpc = common.anon_rpc = env.anon_rpc = call;
cb();
});
});
// Everything's ready, continue... // Everything's ready, continue...
if($('#pad-iframe').length) { if($('#pad-iframe').length) {
block++; block++;

View File

@@ -171,11 +171,6 @@ define([
} }
}; };
$(window.document).on('decryption', function (e) {
var decrypted = e.originalEvent;
if (decrypted.callback) { decrypted.callback(); }
});
return DiffMd; return DiffMd;
}); });

View File

@@ -60,6 +60,9 @@ define([
cb(void 0, res); cb(void 0, res);
}; };
ret.setPadAttribute = filesOp.setAttribute;
ret.getPadAttribute = filesOp.getAttribute;
ret.getDrive = function (key, cb) { ret.getDrive = function (key, cb) {
cb(void 0, storeObj.drive[key]); cb(void 0, storeObj.drive[key]);
}; };
@@ -211,6 +214,10 @@ define([
if (typeof(n) !== "string") { return; } if (typeof(n) !== "string") { return; }
Cryptpad.changeDisplayName(n); Cryptpad.changeDisplayName(n);
}); });
proxy.on('change', ['profile'], function () {
// Trigger userlist update when the avatar has changed
Cryptpad.changeDisplayName(proxy[Cryptpad.displayNameKey]);
});
proxy.on('change', [tokenKey], function () { proxy.on('change', [tokenKey], function () {
console.log('wut'); console.log('wut');
var localToken = tryParsing(localStorage.getItem(tokenKey)); var localToken = tryParsing(localStorage.getItem(tokenKey));

File diff suppressed because one or more lines are too long

View File

@@ -86,7 +86,7 @@ define([
exp.anonDriveIntoUser = function (proxy, cb) { exp.anonDriveIntoUser = function (proxy, cb) {
// Make sure we have an FS_hash and we don't use it, otherwise just stop the migration and cb // Make sure we have an FS_hash and we don't use it, otherwise just stop the migration and cb
if (!localStorage.FS_hash || !Cryptpad.isLoggedIn()) { if (!localStorage.FS_hash || !Cryptpad.isLoggedIn()) {
if (typeof(cb) === "function") { cb(); } if (typeof(cb) === "function") { return void cb(); }
} }
// Get the content of FS_hash and then merge the objects, remove the migration key and cb // Get the content of FS_hash and then merge the objects, remove the migration key and cb
var todo = function (err, doc) { var todo = function (err, doc) {

View File

@@ -54,11 +54,9 @@ define(function () {
"jsx jsx .jsx", "jsx jsx .jsx",
"julia julia", "julia julia",
"livescript livescript", "livescript livescript",
"loadmode.js loadmode.js",
"lua lua", "lua lua",
"markdown markdown .md", "markdown markdown .md",
"mathematica mathematica", "mathematica mathematica",
"meta.js meta.js",
"mirc mirc", "mirc mirc",
"mllike mllike", "mllike mllike",
"modelica modelica", "modelica modelica",

View File

@@ -100,21 +100,6 @@ define([
}); });
}; };
// take a list of channels and return a dictionary of their sizes
exp.getMultipleFileSize = function (files, cb) {
if (!Array.isArray(files)) {
return window.setTimeout(function () {
cb('[TypeError] pin expects an array');
});
}
rpc.send('GET_MULTIPLE_FILE_SIZE', files, function (e, res) {
if (e) { return void cb(e); }
if (typeof(res) !== 'object') {
return void cb('INVALID_RESPONSE');
}
});
};
// get the combined size of all channels (in bytes) for all the // get the combined size of all channels (in bytes) for all the
// channels which the server has pinned for your publicKey // channels which the server has pinned for your publicKey
exp.getFileListSize = function (cb) { exp.getFileListSize = function (cb) {

View File

@@ -99,7 +99,12 @@ types of messages:
delete ctx.pending[txid]; delete ctx.pending[txid];
return; return;
} }
// HACK to hide messages from the anon rpc
if (parsed.length !== 4) {
console.log(parsed);
console.error("received message [%s] for txid[%s] with no callback", msg, txid); console.error("received message [%s] for txid[%s] with no callback", msg, txid);
}
}; };
var create = function (network, edPrivateKey, edPublicKey, cb) { var create = function (network, edPrivateKey, edPublicKey, cb) {
@@ -217,5 +222,104 @@ types of messages:
}); });
}; };
return { create: create }; var onAnonMsg = function (ctx, msg) {
var parsed = parse(msg);
if (!parsed) {
return void console.error(new Error('could not parse message: %s', msg));
}
// RPC messages are always arrays.
if (!Array.isArray(parsed)) { return; }
var txid = parsed[0];
// txid must be a string, or this message is not meant for us
if (typeof(txid) !== 'string') { return; }
var pending = ctx.pending[txid];
if (!(parsed && parsed.slice)) {
// RPC responses are arrays. this message isn't meant for us.
return;
}
if (/FULL_HISTORY/.test(parsed[0])) { return; }
var response = parsed.slice(2);
if (typeof(pending) === 'function') {
if (parsed[1] === 'ERROR') {
pending(parsed[2]);
delete ctx.pending[txid];
return;
}
pending(void 0, response);
// if successful, delete the callback...
delete ctx.pending[txid];
return;
}
// HACK: filter out ugly messages we don't care about
if (typeof(msg) !== 'string') {
console.error("received message [%s] for txid[%s] with no callback", msg, txid);
}
};
var createAnonymous = function (network, cb) {
var ctx = {
network: network,
timeouts: {}, // timeouts
pending: {}, // callbacks
cookie: null,
connected: true,
};
var send = ctx.send = function (type, msg, cb) {
if (!ctx.connected) {
return void window.setTimeout(function () {
cb('DISCONNECTED');
});
}
// construct an unsigned message...
var data = [type, msg];
// [sig, edPublicKey, cookie, type, msg]
return sendMsg(ctx, data, cb);
};
ctx.resend = function (txid) {
var pending = ctx.pending[txid];
if (pending.called) {
console.error("[%s] called too many times", txid);
return true;
}
pending.called++;
try {
return ctx.network.sendto(ctx.network.historyKeeper,
JSON.stringify([txid, pending.data]));
} catch (e) {
console.log("failed to resend");
console.error(e);
}
};
network.on('message', function (msg) {
onAnonMsg(ctx, msg);
});
network.on('disconnect', function () {
ctx.connected = false;
});
network.on('reconnect', function () {
ctx.connected = true;
});
cb(void 0, {
send: send
});
};
return { create: create, createAnonymous: createAnonymous };
}); });

View File

@@ -81,15 +81,31 @@ define([
var $rightside = $toolbar.find('.'+RIGHTSIDE_CLS); var $rightside = $toolbar.find('.'+RIGHTSIDE_CLS);
if (!config.hideDrawer) { if (!config.hideDrawer) {
var $drawerContent = $('<div>', {'class': DRAWER_CLS}).appendTo($rightside).hide(); var $drawerContent = $('<div>', {
'class': DRAWER_CLS,// + ' dropdown-bar-content cryptpad-dropdown'
'tabindex': 1
}).appendTo($rightside).hide();
var $drawer = Cryptpad.createButton('more', true).appendTo($rightside); var $drawer = Cryptpad.createButton('more', true).appendTo($rightside);
$drawer.click(function () { $drawer.click(function () {
$drawerContent.toggle(); $drawerContent.toggle();
$drawer.removeClass('active'); $drawer.removeClass('active');
if ($drawerContent.is(':visible')) { if ($drawerContent.is(':visible')) {
$drawer.addClass('active'); $drawer.addClass('active');
$drawerContent.focus();
} }
}); });
var onBlur = function (e) {
if (e.relatedTarget) {
if ($(e.relatedTarget).is('.drawer-button')) { return; }
if ($(e.relatedTarget).parents('.'+DRAWER_CLS).length) {
$(e.relatedTarget).blur(onBlur);
return;
}
}
$drawer.removeClass('active');
$drawerContent.hide();
};
$drawerContent.blur(onBlur);
} }
// The 'notitle' class removes the line added for the title with a small screen // The 'notitle' class removes the line added for the title with a small screen
@@ -149,6 +165,7 @@ define([
return $.inArray(i, b) > -1; return $.inArray(i, b) > -1;
}); });
}; };
var avatars = {};
var updateUserList = function (toolbar, config) { var updateUserList = function (toolbar, config) {
// Make sure the elements are displayed // Make sure the elements are displayed
var $userButtons = toolbar.userlist; var $userButtons = toolbar.userlist;
@@ -189,7 +206,25 @@ define([
// Editors // Editors
editUsersNames.forEach(function (data) { editUsersNames.forEach(function (data) {
var name = data.name || Messages.anonymous; var name = data.name || Messages.anonymous;
var $span = $('<span>', {'title': name}).text(name); var $name = $('<span>', {'class': 'name'}).text(name);
var $span = $('<span>', {'title': name});
if (data.profile) {
$span.addClass('clickable');
$span.click(function () {
window.open('/profile/#' + data.profile);
});
}
if (data.avatar && avatars[data.avatar]) {
$span.append(avatars[data.avatar]);
$span.append($name);
} else {
Cryptpad.displayAvatar($span, data.avatar, name, function ($img) {
if (data.avatar && $img) {
avatars[data.avatar] = $img[0].outerHTML;
}
$span.append($name);
});
}
$span.data('uid', data.uid); $span.data('uid', data.uid);
$editUsersList.append($span); $editUsersList.append($span);
}); });
@@ -197,9 +232,9 @@ define([
// Viewers // Viewers
if (numberOfViewUsers > 0) { if (numberOfViewUsers > 0) {
var viewText = '<span class="viewer">'; var viewText = '<div class="viewer">';
var viewerText = numberOfViewUsers !== 1 ? Messages.viewers : Messages.viewer; var viewerText = numberOfViewUsers !== 1 ? Messages.viewers : Messages.viewer;
viewText += numberOfViewUsers + ' ' + viewerText + '</span>'; viewText += numberOfViewUsers + ' ' + viewerText + '</div>';
$editUsers.append(viewText); $editUsers.append(viewText);
} }
@@ -299,6 +334,11 @@ define([
if ($content.is(':visible')) { return void show(); } if ($content.is(':visible')) { return void show(); }
hide(); hide();
}); });
$(window).on('resize', function () {
mobile = $('body').width() <= 600;
var h = $ck.is(':visible') ? -$ck.height() : 0;
$content.css('margin-top', h+'px');
});
$closeIcon.click(hide); $closeIcon.click(hide);
$button.click(function () { $button.click(function () {
var visible = $content.is(':visible'); var visible = $content.is(':visible');
@@ -553,17 +593,17 @@ define([
// We need to override the "a" tag action here because it is inside the iframe! // We need to override the "a" tag action here because it is inside the iframe!
var $aTag = $('<a>', { var $aTag = $('<a>', {
href: "/", href: "/drive/",
title: Messages.header_logoTitle, title: Messages.header_logoTitle,
'class': "cryptpad-logo fa fa-hdd-o" 'class': "cryptpad-logo fa fa-hdd-o"
}); });
var onClick = function (e) { var onClick = function (e) {
e.preventDefault(); e.preventDefault();
if (e.ctrlKey) { if (e.ctrlKey) {
window.open('/drive'); window.open('/drive/');
return; return;
} }
window.location = "/drive"; window.location = "/drive/";
}; };
var onContext = function (e) { e.stopPropagation(); }; var onContext = function (e) { e.stopPropagation(); };

View File

@@ -132,6 +132,21 @@ define([
if (type === 'name') { return data.filename; } if (type === 'name') { return data.filename; }
return data.filename || data.title || NEW_FILE_NAME; return data.filename || data.title || NEW_FILE_NAME;
}; };
exp.getAttribute = function (href, attr, cb) {
cb = cb || $.noop;
var id = exp.getIdFromHref(href);
if (!id) { return void cb(null, undefined); }
var data = getFileData(id);
cb(null, data[attr]);
};
exp.setAttribute = function (href, attr, value, cb) {
cb = cb || $.noop;
var id = exp.getIdFromHref(href);
if (!id) { return void cb("E_INVAL_HREF"); }
if (!attr || !attr.trim()) { return void cb("E_INVAL_ATTR"); }
var data = getFileData(id);
data[attr] = value;
};
// PATHS // PATHS
@@ -970,6 +985,20 @@ define([
us.splice(idx, 1); us.splice(idx, 1);
}); });
}; };
var migrateAttributes = function (el, id, parsed) {
// Migrate old pad attributes
['userid', 'previewMode'].forEach(function (attr) {
var key = parsed.hash + '.' + attr;
var key2 = parsed.hash.slice(0,-1) + '.' + attr;// old pads not ending with /
if (files[key] || files[key2]) {
debug("Migrating pad attribute", attr, "for pad", id);
el[attr] = files[key] || files[key2];
}
delete files[key];
delete files[key2];
});
// Migration done
};
var fixFilesData = function () { var fixFilesData = function () {
if (typeof files[FILES_DATA] !== "object") { debug("OLD_FILES_DATA was not an object"); files[FILES_DATA] = {}; } if (typeof files[FILES_DATA] !== "object") { debug("OLD_FILES_DATA was not an object"); files[FILES_DATA] = {}; }
var fd = files[FILES_DATA]; var fd = files[FILES_DATA];
@@ -989,6 +1018,15 @@ define([
toClean.push(id); toClean.push(id);
continue; continue;
} }
var parsed = Cryptpad.parsePadUrl(el.href);
if (!parsed.hash) {
debug("Removing an element in filesData with a invalid href.", el);
toClean.push(id);
continue;
}
migrateAttributes(el, id, parsed);
if ((Cryptpad.isLoggedIn() || config.testMode) && rootFiles.indexOf(id) === -1) { if ((Cryptpad.isLoggedIn() || config.testMode) && rootFiles.indexOf(id) === -1) {
debug("An element in filesData was not in ROOT, TEMPLATE or TRASH.", id, el); debug("An element in filesData was not in ROOT, TEMPLATE or TRASH.", id, el);
var newName = Cryptpad.createChannelId(); var newName = Cryptpad.createChannelId();
@@ -1001,12 +1039,19 @@ define([
}); });
}; };
var fixDrive = function () {
Object.keys(files).forEach(function (key) {
if (key.slice(0,1) === '/') { delete files[key]; }
});
};
fixRoot(); fixRoot();
fixTrashRoot(); fixTrashRoot();
if (!workgroup) { if (!workgroup) {
fixTemplate(); fixTemplate();
fixFilesData(); fixFilesData();
} }
fixDrive();
if (JSON.stringify(files) !== before) { if (JSON.stringify(files) !== before) {
debug("Your file system was corrupted. It has been cleaned so that the pads you visit can be stored safely"); debug("Your file system was corrupted. It has been cleaned so that the pads you visit can be stored safely");

View File

@@ -621,7 +621,7 @@ span {
margin: 0; margin: 0;
} }
button { button {
height: 100%; height: 32px;
padding: 0 10px; padding: 0 10px;
border: none; border: none;
border-radius: 0; border-radius: 0;

View File

@@ -1170,7 +1170,7 @@ define([
var element = filesOp.find(newPath); var element = filesOp.find(newPath);
var $icon = !isFolder ? getFileIcon(element) : undefined; var $icon = !isFolder ? getFileIcon(element) : undefined;
var ro = filesOp.isReadOnlyFile(element); var ro = filesOp.isReadOnlyFile(element);
// ro undefined mens it's an old hash which doesn't support read-only // ro undefined means it's an old hash which doesn't support read-only
var roClass = typeof(ro) === 'undefined' ? ' noreadonly' : ro ? ' readonly' : ''; var roClass = typeof(ro) === 'undefined' ? ' noreadonly' : ro ? ' readonly' : '';
var liClass = 'file-item file-element element' + roClass; var liClass = 'file-item file-element element' + roClass;
if (isFolder) { if (isFolder) {
@@ -2140,6 +2140,7 @@ define([
$trashContextMenu.hide(); $trashContextMenu.hide();
$contentContextMenu.hide(); $contentContextMenu.hide();
$defaultContextMenu.hide(); $defaultContextMenu.hide();
$iframe.find('.cryptpad-dropdown').hide();
}; };
var stringifyPath = function (path) { var stringifyPath = function (path) {

View File

@@ -242,6 +242,18 @@ define([
fo.migrate(todo); fo.migrate(todo);
}, "DRIVE4: migration and fixFiles with a pad in trash not root"); }, "DRIVE4: migration and fixFiles with a pad in trash not root");
// Pad attributes migration
assert(function (cb) {
console.log('START PAD ATTRIBUTES');
var files = JSON.parse(JSON.stringify(example));
files[href1.slice(6) + '.userid'] = 'value';
files[href1.slice(6) + '.previewMode'] = true;
var fo = FO.init(files, config);
fo.fixFiles();
return cb(files.filesData[id1].userid === 'value'
&& files.filesData[id1].previewMode);
}, "PAD ATTRIBUTES");
// userObject Tests // userObject Tests
// UTILS // UTILS

View File

@@ -7,12 +7,14 @@ define([
'/common/visible.js', '/common/visible.js',
'/common/notify.js', '/common/notify.js',
'/file/file-crypto.js', '/file/file-crypto.js',
'/common/media-tag.js',
'/bower_components/file-saver/FileSaver.min.js', '/bower_components/file-saver/FileSaver.min.js',
'/bower_components/tweetnacl/nacl-fast.min.js',
'css!/bower_components/components-font-awesome/css/font-awesome.min.css', 'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/customize/src/less/cryptpad.less', 'less!/customize/src/less/cryptpad.less',
], function ($, Crypto, realtimeInput, Toolbar, Cryptpad, Visible, Notify, FileCrypto) { ], function ($, Crypto, realtimeInput, Toolbar, Cryptpad, Visible, Notify, FileCrypto, MediaTag) {
var Messages = Cryptpad.Messages; var Messages = Cryptpad.Messages;
var saveAs = window.saveAs; var saveAs = window.saveAs;
var Nacl = window.nacl; var Nacl = window.nacl;
@@ -91,7 +93,9 @@ define([
$(window.document).on('decryption', function (e) { $(window.document).on('decryption', function (e) {
var decrypted = e.originalEvent; var decrypted = e.originalEvent;
if (decrypted.callback) { decrypted.callback(); } if (decrypted.callback) {
decrypted.callback();
}
console.log(decrypted); console.log(decrypted);
$dlview.show(); $dlview.show();
@@ -131,7 +135,6 @@ define([
console.log(progress.percent); console.log(progress.percent);
}); });
require(['/common/media-tag.js'], function (MediaTag) {
/** /**
* Allowed mime types that have to be set for a rendering after a decryption. * Allowed mime types that have to be set for a rendering after a decryption.
* *
@@ -156,7 +159,6 @@ define([
MediaTag.CryptoFilter.setAllowedMediaTypes(allowedMediaTypes); MediaTag.CryptoFilter.setAllowedMediaTypes(allowedMediaTypes);
MediaTag($mt[0]); MediaTag($mt[0]);
});
}; };
var todoBigFile = function (sizeMb) { var todoBigFile = function (sizeMb) {
@@ -181,9 +183,6 @@ define([
}; };
Cryptpad.getFileSize(window.location.href, function (e, data) { Cryptpad.getFileSize(window.location.href, function (e, data) {
if (e) { if (e) {
// TODO when GET_FILE_SIZE is made unauthenticated
// you won't need to handle this error (there won't be one)
if (e === 'RPC_NOT_READY') { return todoBigFile(); }
return void Cryptpad.errorLoadingScreen(e); return void Cryptpad.errorLoadingScreen(e);
} }
var size = Cryptpad.bytesToMegabytes(data); var size = Cryptpad.bytesToMegabytes(data);

View File

@@ -14,6 +14,7 @@
#cke_1_top { #cke_1_top {
overflow: visible; overflow: visible;
padding: 0px; padding: 0px;
display: flex;
} }
#cke_1_toolbox { #cke_1_toolbox {
display: inline-block; display: inline-block;

View File

@@ -570,16 +570,10 @@ define([
// this should only ever get called once, when the chain syncs // this should only ever get called once, when the chain syncs
realtimeOptions.onReady = function (info) { realtimeOptions.onReady = function (info) {
if (!module.isMaximized) { if (!module.isMaximized) {
editor.execCommand('maximize');
module.isMaximized = true; module.isMaximized = true;
// We have to call it 3 times in Safari $iframe.find('iframe.cke_wysiwyg_frame').css('width', '');
// in order to have the editor fully maximized -_- $iframe.find('iframe.cke_wysiwyg_frame').css('height', '');
if ((''+window.navigator.vendor).indexOf('Apple') !== -1) {
editor.execCommand('maximize');
editor.execCommand('maximize');
} }
}
// editor.execCommand('maximize') removes all the classes from the body tag
$iframe.find('body').addClass('app-pad'); $iframe.find('body').addClass('app-pad');
if (module.realtime !== info.realtime) { if (module.realtime !== info.realtime) {
@@ -727,7 +721,6 @@ define([
if (Ckeditor) { if (Ckeditor) {
// mobile configuration // mobile configuration
Ckeditor.config.toolbarCanCollapse = true; Ckeditor.config.toolbarCanCollapse = true;
Ckeditor.config.height = '72vh';
if (screen.height < 800) { if (screen.height < 800) {
Ckeditor.config.toolbarStartupExpanded = false; Ckeditor.config.toolbarStartupExpanded = false;
$('meta[name=viewport]').attr('content', 'width=device-width, initial-scale=1.0, user-scalable=no'); $('meta[name=viewport]').attr('content', 'width=device-width, initial-scale=1.0, user-scalable=no');

View File

@@ -552,11 +552,19 @@ var ready = function (info, userid, readOnly) {
} else { } else {
APP.proxy.info.defaultTitle = Title.defaultTitle; APP.proxy.info.defaultTitle = Title.defaultTitle;
} }
var andThen = function () {
if (readOnly) { return; }
Cryptpad.setPadAttribute('userid', userid, function (e) {
if (e) { console.error(e); }
});
};
if (Cryptpad.initialName && !APP.proxy.info.title) { if (Cryptpad.initialName && !APP.proxy.info.title) {
APP.proxy.info.title = Cryptpad.initialName; APP.proxy.info.title = Cryptpad.initialName;
Title.updateTitle(Cryptpad.initialName); Title.updateTitle(Cryptpad.initialName, null, andThen);
} else { } else {
Title.updateTitle(APP.proxy.info.title || Title.defaultTitle); Title.updateTitle(APP.proxy.info.title || Title.defaultTitle, null, andThen);
} }
// Description // Description
@@ -621,6 +629,7 @@ var ready = function (info, userid, readOnly) {
} else { } else {
publish(true); publish(true);
} }
Cryptpad.removeLoadingScreen(); Cryptpad.removeLoadingScreen();
if (readOnly) { return; } if (readOnly) { return; }
@@ -760,11 +769,8 @@ var create = function (info) {
if (e) { console.error(e); } if (e) { console.error(e); }
if (!userid) { userid = Render.coluid(); } if (!userid) { userid = Render.coluid(); }
APP.userid = userid; APP.userid = userid;
Cryptpad.setPadAttribute('userid', userid, function (e) {
if (e) { console.error(e); }
ready(info, userid, readOnly); ready(info, userid, readOnly);
}); });
});
}) })
.on('disconnect', disconnect) .on('disconnect', disconnect)
.on('reconnect', reconnect); .on('reconnect', reconnect);

View File

@@ -1,422 +0,0 @@
html,
body {
width: 100%;
height: 100%;
margin: 0px;
padding: 0px;
border: 0px;
}
body {
display: flex;
flex-flow: column;
}
#content {
display: flex;
flex: 1;
}
#content #poll {
flex: 1;
}
.cryptpad-toolbar h2 {
font: normal normal normal 12px Arial, Helvetica, Tahoma, Verdana, Sans-Serif;
color: #000;
line-height: auto;
}
.cryptpad-toolbar {
display: inline-block;
}
.realtime {
display: block;
max-height: 100%;
max-width: 100%;
}
.realtime input[type="text"] {
height: 1em;
margin: 0px;
}
.text-cell input[type="text"] {
width: 400px;
}
input[type="text"][disabled],
textarea[disabled] {
background-color: transparent;
font: white;
border: 0px;
}
input[type="text"]::placeholder {
color: #666;
}
table#table {
margin: 0px;
}
#tableContainer {
position: relative;
padding: 29px;
padding-right: 79px;
}
#tableContainer button {
height: 2rem;
display: none;
}
#publish {
display: none;
}
#publish,
#admin {
margin-top: 15px;
margin-bottom: 15px;
}
#create-user {
position: absolute;
display: inline-block;
/*left: 0px;*/
top: 55px;
width: 50px;
overflow: hidden;
}
#create-option {
width: 50px;
}
#tableScroll {
overflow-y: hidden;
overflow-x: auto;
margin-left: calc(30% - 50px + 31px);
max-width: 70%;
width: auto;
display: inline-block;
}
#description {
padding: 15px;
margin: auto;
min-width: 80%;
width: 80%;
min-height: 5em;
font-size: 20px;
font-weight: bold;
}
#description[disabled] {
resize: none;
color: #000;
border: 1px solid #444;
}
#commit {
width: 100%;
}
#howItWorks {
width: 80%;
margin: auto;
}
div.upper {
width: 80%;
margin: auto;
}
table {
border-collapse: collapse;
border-spacing: 0;
margin: 20px;
}
tbody {
border: 1px solid #555;
}
tbody * {
box-sizing: border-box;
}
tbody tr {
text-align: center;
}
tbody tr:first-of-type th {
font-size: 20px;
border-top: 0px;
font-weight: bold;
padding: 10px;
text-decoration: underline;
}
tbody tr:first-of-type th.table-refresh {
color: #46E981;
text-decoration: none;
cursor: pointer;
}
tbody tr:nth-child(odd) {
background-color: #ffffff;
}
tbody tr th:first-of-type {
border-left: 0px;
}
tbody tr th {
box-sizing: border-box;
border: 1px solid #555;
}
tbody tr th,
tbody tr td {
color: #555;
}
tbody tr th.remove,
tbody tr td.remove {
cursor: pointer;
}
tbody tr th:last-child {
border-right: 0px;
}
tbody td {
border-right: 1px solid #555;
padding: 12px;
padding-top: 0px;
padding-bottom: 0px;
}
tbody td:last-child {
border-right: none;
}
form.realtime,
div.realtime {
padding: 0px;
margin: 0px;
}
form.realtime > textarea,
div.realtime > textarea {
width: 50%;
height: 15vh;
}
form.realtime table,
div.realtime table {
border-collapse: collapse;
width: calc(100% - 1px);
}
form.realtime table .editing,
div.realtime table .editing {
background-color: #88b8cc;
}
form.realtime table tr td:first-child,
div.realtime table tr td:first-child {
position: absolute;
left: 29px;
top: auto;
width: calc(30% - 50px);
}
form.realtime table tr td,
div.realtime table tr td {
padding: 0px;
margin: 0px;
}
form.realtime table tr td div.text-cell,
div.realtime table tr td div.text-cell {
padding: 0px;
margin: 0px;
height: 100%;
}
form.realtime table tr td div.text-cell input,
div.realtime table tr td div.text-cell input {
width: 80%;
width: 90%;
height: 100%;
border: 0px;
}
form.realtime table tr td div.text-cell input[disabled],
div.realtime table tr td div.text-cell input[disabled] {
background-color: transparent;
color: #000;
font-weight: bold;
}
form.realtime table tr td.checkbox-cell,
div.realtime table tr td.checkbox-cell {
margin: 0px;
padding: 0px;
height: 100%;
min-width: 150px;
}
form.realtime table tr td.checkbox-cell div.checkbox-contain,
div.realtime table tr td.checkbox-cell div.checkbox-contain {
display: inline-block;
height: 100%;
width: 100%;
position: relative;
}
form.realtime table tr td.checkbox-cell div.checkbox-contain label,
div.realtime table tr td.checkbox-cell div.checkbox-contain label {
background-color: transparent;
display: block;
position: absolute;
top: 0px;
left: 0px;
height: 100%;
width: 100%;
}
form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"]:not(.editable),
div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"]:not(.editable) {
display: none;
}
form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"]:not(.editable) ~ .cover,
div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"]:not(.editable) ~ .cover {
font-weight: bold;
color: #000;
display: block;
}
form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"]:not(.editable) ~ .cover:after,
div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"]:not(.editable) ~ .cover:after {
height: 100%;
}
form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"]:not(.editable) ~ .cover.yes,
div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"]:not(.editable) ~ .cover.yes {
background-color: #46E981;
}
form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"]:not(.editable) ~ .cover.uncommitted,
div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"]:not(.editable) ~ .cover.uncommitted {
background: #ddd;
}
form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"]:not(.editable) ~ .cover.mine,
div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"]:not(.editable) ~ .cover.mine {
display: none;
}
form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"][value="0"] ~ .cover,
div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"][value="0"] ~ .cover {
background-color: #FA5858;
}
form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"][value="0"] ~ .cover:after,
div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"][value="0"] ~ .cover:after {
content: "✖";
}
form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"][value="1"] ~ .cover,
div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"][value="1"] ~ .cover {
background-color: #46E981;
}
form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"][value="1"] ~ .cover:after,
div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"][value="1"] ~ .cover:after {
content: "✔";
}
form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"][value="2"] ~ .cover,
div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"][value="2"] ~ .cover {
background-color: #ff5;
}
form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"][value="2"] ~ .cover:after,
div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"][value="2"] ~ .cover:after {
content: "~";
}
form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"][value="3"] ~ .cover,
div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"][value="3"] ~ .cover {
background-color: #ccc;
}
form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"][value="3"] ~ .cover:after,
div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"][value="3"] ~ .cover:after {
content: "?";
}
form.realtime table input[type="text"],
div.realtime table input[type="text"] {
height: auto;
border: 1px solid #fff;
width: 80%;
}
form.realtime table span,
div.realtime table span {
user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
}
form.realtime table thead td,
div.realtime table thead td {
padding: 0px 5px;
background: #aaa;
border-radius: 20px 20px 0 0;
}
form.realtime table thead td:nth-of-type(2),
div.realtime table thead td:nth-of-type(2) {
background: #999;
}
form.realtime table thead td:nth-of-type(2) .lock,
div.realtime table thead td:nth-of-type(2) .lock {
cursor: default;
}
form.realtime table thead td input[type="text"],
div.realtime table thead td input[type="text"] {
width: 100%;
box-sizing: border-box;
padding: 1px 5px;
}
form.realtime table thead td input[type="text"][disabled],
div.realtime table thead td input[type="text"][disabled] {
color: #000;
border: 1px solid transparent;
}
form.realtime table tbody td:not(.editing) .text-cell,
div.realtime table tbody td:not(.editing) .text-cell {
background: #aaa;
}
form.realtime table tbody .text-cell input[type="text"],
div.realtime table tbody .text-cell input[type="text"] {
width: calc(100% - 50px);
}
form.realtime table tbody .text-cell .edit,
div.realtime table tbody .text-cell .edit {
float: right;
margin: 0 10px 0 0;
}
form.realtime table tbody .text-cell .remove,
div.realtime table tbody .text-cell .remove {
float: left;
margin: 0 0 0 10px;
}
form.realtime table tbody tr:not(:first-child) td:not(:first-child) label,
div.realtime table tbody tr:not(:first-child) td:not(:first-child) label {
border-top: 1px solid #555;
}
form.realtime table .edit,
div.realtime table .edit {
color: #000;
cursor: pointer;
float: left;
margin-left: 10px;
}
form.realtime table .lock,
div.realtime table .lock {
margin-left: calc(50% - 0.5em);
cursor: pointer;
width: 1em;
text-align: center;
}
form.realtime table .remove,
div.realtime table .remove {
float: right;
margin-right: 10px;
}
form.realtime table thead tr th input[type="text"][disabled],
div.realtime table thead tr th input[type="text"][disabled] {
background-color: transparent;
color: #555;
font-weight: bold;
}
form.realtime table thead tr th .remove,
div.realtime table thead tr th .remove {
cursor: pointer;
font-size: 20px;
}
form.realtime table tfoot tr,
div.realtime table tfoot tr {
border: none;
}
form.realtime table tfoot tr td,
div.realtime table tfoot tr td {
border: none;
text-align: center;
}
form.realtime table tfoot tr td .save,
div.realtime table tfoot tr td .save {
padding: 15px;
border-top-left-radius: 5px;
border-top-right-radius: 5px;
}
form.realtime #adduser,
div.realtime #adduser,
form.realtime #addoption,
div.realtime #addoption {
color: #46E981;
border: 1px solid #46E981;
padding: 15px;
cursor: pointer;
}
form.realtime #adduser,
div.realtime #adduser {
border-top-left-radius: 5px;
}
form.realtime #addoption,
div.realtime #addoption {
border-bottom-left-radius: 5px;
}

View File

@@ -22,6 +22,7 @@ html, body {
body { body {
display: flex; display: flex;
flex-flow: column; flex-flow: column;
overflow-x: hidden;
} }
#content { #content {
display: flex; display: flex;

View File

@@ -11,7 +11,6 @@ define([
'/bower_components/marked/marked.min.js', '/bower_components/marked/marked.min.js',
'cm/lib/codemirror', 'cm/lib/codemirror',
'cm/mode/markdown/markdown', 'cm/mode/markdown/markdown',
'/bower_components/tweetnacl/nacl-fast.min.js',
'less!/profile/main.less', 'less!/profile/main.less',
], function ($, Cryptpad, Listmap, Crypto, Marked, CodeMirror) { ], function ($, Cryptpad, Listmap, Crypto, Marked, CodeMirror) {
@@ -105,7 +104,7 @@ define([
if (err) { return void console.error(err); } if (err) { return void console.error(err); }
Cryptpad.whenRealtimeSyncs(realtime, function () { Cryptpad.whenRealtimeSyncs(realtime, function () {
lastVal = newVal; lastVal = newVal;
Cryptpad.log('TODO: '+name+' saved'); Cryptpad.log(Messages._getKey('profile_fieldSaved', [newVal]));
editing = false; editing = false;
}); });
}); });
@@ -156,11 +155,11 @@ define([
var getValue = function (cb) { var getValue = function (cb) {
cb(APP.lm.proxy.name); cb(APP.lm.proxy.name);
}; };
var placeholder = Messages.anonymous; var placeholder = Messages.profile_namePlaceholder;
if (APP.readOnly) { if (APP.readOnly) {
var $span = $('<span>', {'class': DISPLAYNAME_ID}).appendTo($block); var $span = $('<span>', {'class': DISPLAYNAME_ID}).appendTo($block);
getValue(function (value) { getValue(function (value) {
$span.text(value || placeholder); $span.text(value || Messages.anonymous);
}); });
return; return;
} }
@@ -196,7 +195,7 @@ define([
cb(); cb();
}; };
var rt = APP.lm.realtime; var rt = APP.lm.realtime;
var placeholder = "URL"; //XXX var placeholder = Messages.profile_urlPlaceholder;
createEditableInput($block, LINK_ID, placeholder, getValue, setValue, rt); createEditableInput($block, LINK_ID, placeholder, getValue, setValue, rt);
}; };
@@ -209,7 +208,7 @@ define([
if (!APP.lm.proxy.avatar) { if (!APP.lm.proxy.avatar) {
$('<img>', { $('<img>', {
src: '/customize/images/avatar.png', src: '/customize/images/avatar.png',
title: 'Avatar', // XXX title: Messages.profile_avatar,
alt: 'Avatar' alt: 'Avatar'
}).appendTo($span); }).appendTo($span);
return; return;
@@ -218,21 +217,20 @@ define([
if (APP.readOnly) { return; } if (APP.readOnly) { return; }
var $delButton = $('<button>', {'class': 'delete btn btn-danger fa fa-times'}); //XXX var $delButton = $('<button>', {
'class': 'delete btn btn-danger fa fa-times',
title: Messages.fc_delete
});
$span.append($delButton); $span.append($delButton);
$delButton.click(function () { $delButton.click(function () {
console.log('clicked');
var oldChanId = Cryptpad.hrefToHexChannelId(APP.lm.proxy.avatar); var oldChanId = Cryptpad.hrefToHexChannelId(APP.lm.proxy.avatar);
Cryptpad.unpinPads([oldChanId], function (e) { Cryptpad.unpinPads([oldChanId], function (e) {
if (e) { Cryptpad.log(e); } if (e) { Cryptpad.log(e); }
console.log('unpinned');
delete APP.lm.proxy.avatar; delete APP.lm.proxy.avatar;
delete Cryptpad.getProxy().profile.avatar; delete Cryptpad.getProxy().profile.avatar;
Cryptpad.whenRealtimeSyncs(APP.lm.realtime, function () { Cryptpad.whenRealtimeSyncs(APP.lm.realtime, function () {
console.log('synced1');
var driveRt = Cryptpad.getStore().getProxy().info.realtime; var driveRt = Cryptpad.getStore().getProxy().info.realtime;
Cryptpad.whenRealtimeSyncs(driveRt, function () { Cryptpad.whenRealtimeSyncs(driveRt, function () {
console.log('synced2');
displayAvatar(); displayAvatar();
}); });
}); });
@@ -285,7 +283,7 @@ define([
accept: ".gif,.jpg,.jpeg,.png" accept: ".gif,.jpg,.jpeg,.png"
}; };
var $upButton = Cryptpad.createButton('upload', false, data); var $upButton = Cryptpad.createButton('upload', false, data);
$upButton.text(" Upload a new avatar"); $upButton.text(Messages.profile_upload);
$upButton.prepend($('<span>', {'class': 'fa fa-upload'})); $upButton.prepend($('<span>', {'class': 'fa fa-upload'}));
$block.append($upButton); $block.append($upButton);
}; };
@@ -300,6 +298,7 @@ define([
$div.html(val); $div.html(val);
return; return;
} }
$('<h3>').text(Messages.profile_description).insertBefore($block);
var $ok = $('<span>', {'class': 'ok fa fa-check', title: Messages.saved}).appendTo($block); var $ok = $('<span>', {'class': 'ok fa fa-check', title: Messages.saved}).appendTo($block);
var $spinner = $('<span>', {'class': 'spin fa fa-spinner fa-pulse'}).appendTo($block); var $spinner = $('<span>', {'class': 'spin fa fa-spinner fa-pulse'}).appendTo($block);
@@ -388,17 +387,16 @@ define([
if (e === 'E_OVER_LIMIT') { if (e === 'E_OVER_LIMIT') {
Cryptpad.alert(Messages.pinLimitNotPinned, null, true); Cryptpad.alert(Messages.pinLimitNotPinned, null, true);
} }
return void Cryptpad.log('Error while creating your profile: ' + e); // XXX return void Cryptpad.log(Messages._getKey('profile_error', [e]));
} }
obj.profile.edit = Cryptpad.getEditHashFromKeys(channel, secret.keys); obj.profile.edit = Cryptpad.getEditHashFromKeys(channel, secret.keys);
obj.profile.view = Cryptpad.getViewHashFromKeys(channel, secret.keys); obj.profile.view = Cryptpad.getViewHashFromKeys(channel, secret.keys);
obj.profile.name = APP.rt.proxy[Cryptpad.displayNameKey] || '';
andThen(obj.profile.edit); andThen(obj.profile.edit);
}); });
}; };
if (!Cryptpad.isLoggedIn()) { // XXX if (!Cryptpad.isLoggedIn()) {
var $p = $('<p>').text('TODO: You have to register to create a profile'); var $p = $('<p>', {id: CREATE_ID}).append(Messages.profile_register);
var $a = $('<a>', { var $a = $('<a>', {
href: '/register/' href: '/register/'
}); });
@@ -411,7 +409,7 @@ define([
} }
var $create = $('<div>', {id: CREATE_ID}); var $create = $('<div>', {id: CREATE_ID});
var $button = $('<button>', {'class': 'btn btn-success'}); var $button = $('<button>', {'class': 'btn btn-success'});
$button.text('TODO: create a profile?').click(todo).appendTo($create); // XXX $button.text(Messages.profile_create).click(todo).appendTo($create);
APP.$container.append($create); APP.$container.append($create);
}; };

View File

@@ -4,8 +4,6 @@
width: 1000px; width: 1000px;
max-width: 90%; max-width: 90%;
margin: auto; margin: auto;
display: flex;
justify-content: center;
#container { #container {
font-size: 25px; font-size: 25px;
width: 100%; width: 100%;
@@ -129,4 +127,11 @@
} }
} }
} }
#createProfile {
height: 100%;
display: flex;
flex-flow: column;
align-items: center;
justify-content: center;
}
} }

View File

@@ -118,6 +118,7 @@ define([
return void Cryptpad.alert(Messages.register_mustAcceptTerms); return void Cryptpad.alert(Messages.register_mustAcceptTerms);
} }
setTimeout(function () {
Cryptpad.confirm("<h2 class='bright'>" + Messages.register_warning + "</h2>", Cryptpad.confirm("<h2 class='bright'>" + Messages.register_warning + "</h2>",
function (yes) { function (yes) {
if (!yes) { return; } if (!yes) { return; }
@@ -200,6 +201,24 @@ define([
}, true, function ($dialog) { }, true, function ($dialog) {
$dialog.find('> div').addClass('half'); $dialog.find('> div').addClass('half');
}); });
}, 150);
});
var clickRegister = Cryptpad.notAgainForAnother(function () {
$register.click();
}, 500);
$register.on('keypress', function (e) {
e.preventDefault();
e.stopPropagation();
console.error(e.which);
switch (e.which) {
case 13: return clickRegister();
case 13: return clickRegister();
default:
//console.log(e.which);
}
}); });
Test(function () { Test(function () {

View File

@@ -6,34 +6,6 @@
<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">
<script src="/bower_components/jquery/dist/jquery.min.js"></script> <script src="/bower_components/jquery/dist/jquery.min.js"></script>
<script src="/bower_components/codemirror/lib/codemirror.js"></script>
<link rel="stylesheet" href="/bower_components/codemirror/lib/codemirror.css">
<link rel="stylesheet" href="/bower_components/codemirror/addon/dialog/dialog.css">
<link rel="stylesheet" href="/bower_components/codemirror/addon/fold/foldgutter.css" />
<script src="/bower_components/codemirror/mode/javascript/javascript.js"></script>
<script src="/bower_components/codemirror/addon/mode/loadmode.js"></script>
<script src="/bower_components/codemirror/mode/meta.js"></script>
<script src="/bower_components/codemirror/addon/mode/overlay.js"></script>
<script src="/bower_components/codemirror/addon/mode/multiplex.js"></script>
<script src="/bower_components/codemirror/addon/mode/simple.js"></script>
<script src="/bower_components/codemirror/addon/edit/closebrackets.js"></script>
<script src="/bower_components/codemirror/addon/edit/matchbrackets.js"></script>
<script src="/bower_components/codemirror/addon/edit/trailingspace.js"></script>
<script src="/bower_components/codemirror/addon/selection/active-line.js"></script>
<script src="/bower_components/codemirror/addon/search/search.js"></script>
<script src="/bower_components/codemirror/addon/search/match-highlighter.js"></script>
<script src="/bower_components/codemirror/addon/search/searchcursor.js"></script>
<script src="/bower_components/codemirror/addon/dialog/dialog.js"></script>
<script src="/bower_components/codemirror/addon/fold/foldcode.js"></script>
<script src="/bower_components/codemirror/addon/fold/foldgutter.js"></script>
<script src="/bower_components/codemirror/addon/fold/brace-fold.js"></script>
<script src="/bower_components/codemirror/addon/fold/xml-fold.js"></script>
<script src="/bower_components/codemirror/addon/fold/markdown-fold.js"></script>
<script src="/bower_components/codemirror/addon/fold/comment-fold.js"></script>
<script src="/bower_components/codemirror/addon/display/placeholder.js"></script>
<script async data-bootload="inner.js" data-main="/common/boot.js?ver=1.0" src="/bower_components/requirejs/require.js?ver=2.1.15"></script> <script async data-bootload="inner.js" data-main="/common/boot.js?ver=1.0" src="/bower_components/requirejs/require.js?ver=2.1.15"></script>
<style>.loading-hidden { display: none; } </style> <style>.loading-hidden { display: none; } </style>
</head> </head>

View File

@@ -1,8 +1,41 @@
define([ define([
'jquery', 'jquery',
'cm/lib/codemirror',
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
'less!/customize/src/less/toolbar.less', 'less!/customize/src/less/toolbar.less',
'less!/customize/src/less/cryptpad.less', 'less!/customize/src/less/cryptpad.less',
'less!/slide/slide.less', 'less!/slide/slide.less',
], function ($) {
'css!cm/lib/codemirror.css',
'css!cm/addon/dialog/dialog.css',
'css!cm/addon/fold/foldgutter.css',
'cm/mode/markdown/markdown',
'cm/addon/mode/loadmode',
'cm/mode/meta',
'cm/addon/mode/overlay',
'cm/addon/mode/multiplex',
'cm/addon/mode/simple',
'cm/addon/edit/closebrackets',
'cm/addon/edit/matchbrackets',
'cm/addon/edit/trailingspace',
'cm/addon/selection/active-line',
'cm/addon/search/search',
'cm/addon/search/match-highlighter',
'cm/addon/search/searchcursor',
'cm/addon/dialog/dialog',
'cm/addon/fold/foldcode',
'cm/addon/fold/foldgutter',
'cm/addon/fold/brace-fold',
'cm/addon/fold/xml-fold',
'cm/addon/fold/markdown-fold',
'cm/addon/fold/comment-fold',
'cm/addon/display/placeholder',
], function ($, CMeditor) {
window.CodeMirror = CMeditor;
$('.loading-hidden').removeClass('loading-hidden'); $('.loading-hidden').removeClass('loading-hidden');
}); });

View File

@@ -9,7 +9,6 @@ define([
'/common/cryptpad-common.js', '/common/cryptpad-common.js',
'/common/cryptget.js', '/common/cryptget.js',
'/slide/slide.js', '/slide/slide.js',
'/bower_components/tweetnacl/nacl-fast.min.js', // needed for media-tag
'css!/bower_components/components-font-awesome/css/font-awesome.min.css', 'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/customize/src/less/cryptpad.less', 'less!/customize/src/less/cryptpad.less',
@@ -53,7 +52,7 @@ define([
var andThen = function (CMeditor) { var andThen = function (CMeditor) {
var $iframe = $('#pad-iframe').contents(); var $iframe = $('#pad-iframe').contents();
var $contentContainer = $iframe.find('#editorContainer'); var $contentContainer = $iframe.find('#editorContainer');
var CodeMirror = Cryptpad.createCodemirror(CMeditor, ifrw, Cryptpad); var CodeMirror = Cryptpad.createCodemirror(ifrw, Cryptpad, null, CMeditor);
editor = CodeMirror.editor; editor = CodeMirror.editor;
var $bar = $('#pad-iframe')[0].contentWindow.$('#cme_toolbox'); var $bar = $('#pad-iframe')[0].contentWindow.$('#cme_toolbox');
@@ -468,7 +467,10 @@ define([
Cryptpad.feedback('PRINT_SLIDES'); Cryptpad.feedback('PRINT_SLIDES');
//$('body').append(createPrintDialog()); //$('body').append(createPrintDialog());
}).append($('<span>', {'class': 'drawer'}).text(Messages.printText)); }).append($('<span>', {'class': 'drawer'}).text(Messages.printText));
$drawer.append($printButton);
// TODO reenable this when it is working again
$printButton = $printButton;
//$drawer.append($printButton);
var $slideOptions = $('<button>', { var $slideOptions = $('<button>', {
title: Messages.slideOptionsTitle, title: Messages.slideOptionsTitle,
@@ -590,7 +592,7 @@ define([
Cryptpad.getPadAttribute('previewMode', function (e, data) { Cryptpad.getPadAttribute('previewMode', function (e, data) {
if (e) { return void console.error(e); } if (e) { return void console.error(e); }
if (data === true && APP.$previewButton) { if ([true, undefined].indexOf(data) !== -1 && APP.$previewButton) {
APP.$previewButton.click(); APP.$previewButton.click();
} }
}); });

View File

@@ -19,6 +19,7 @@ html, body{
position: relative; position: relative;
} }
body { body {
font-size: unset;
display: flex; display: flex;
flex-flow: column; flex-flow: column;
} }
@@ -238,6 +239,9 @@ div.modal, div#modal {
transition: margin-left 1s; transition: margin-left 1s;
} }
} }
media-tag button {
max-height: none;
}
} }
box-sizing: border-box; box-sizing: border-box;
@@ -321,8 +325,6 @@ div#modal #content, #print {
img { img {
position: relative; position: relative;
min-width: 1%; min-width: 1%;
max-width: 90%;
max-height: 90%;
margin: auto; margin: auto;
} }
.slideNumber { .slideNumber {