manual merge of staging

pull/1/head
Caleb James DeLisle 7 years ago
commit f6abdc2b86

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

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

@ -444,7 +444,7 @@ define([
h('div#poll', [
h('div#howItWorks', [
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_encryption)
]),

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

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

@ -16,15 +16,28 @@
color: inherit;
}
#cke_editor1 {
.cke_inner {
.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; }
.toolbar-container {
display: flex;
}
#cke_editor1 .cke_inner {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
display: flex;
flex-flow: column;
height: 100vh;
width: 100vw;
}
}
.cke_toolbox_main {
display: inline-block;
@ -35,17 +48,12 @@
margin-top: -1px;
display: flex;
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 {
font: normal normal normal 16px Arial,Helvetica,Tahoma,Verdana,Sans-Serif;
min-width: 175px;
@ -104,6 +112,51 @@ body .userlist-drawer {
background: rgba(0,0,0,0.1);
margin: 2px 0;
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;
margin: 0;
&::before {
width: 100%;
text-align: center;
padding-top: 4px;
}
&:hover {
@ -796,11 +851,10 @@ body .cryptpad-toolbar {
width: 64px;
padding: 0;
span {
text-align: center;
width: 100%;
cursor: default;
font-size: 32px;
.fa {
margin-left: 3px;
}
}
}
}
@ -850,8 +904,10 @@ body .cryptpad-toolbar {
}
}
.cryptpad-toolbar-rightside {
height: 32px;
min-height: 32px;
overflow: hidden;
&:empty {
min-height: 0;
height: 0;
}
text-align: right;
@ -873,7 +929,7 @@ body .cryptpad-toolbar {
background: @dropdown-bg;
display: flex;
flex-flow: column;
z-index:1000;
z-index:10000;
color: black;
.fa {
font-size: 17px;
@ -881,7 +937,7 @@ body .cryptpad-toolbar {
&> span {
box-sizing: border-box;
min-width: 150px;
height: 26px;
height: 32px;
border-radius: 0;
border: 0;
}

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

@ -240,6 +240,18 @@ define(function () {
out.canvas_opacityLabel = "opacité: {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
out.fm_rootName = "Documents";

@ -242,6 +242,17 @@ define(function () {
out.canvas_opacityLabel = "opacity: {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

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

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

@ -281,7 +281,7 @@ var getUploadSize = function (Env, channel, cb) {
var paths = Env.paths;
var path = makeFilePath(paths.blob, channel);
if (!path) {
return cb('INVALID_UPLOAD_ID');
return cb('INVALID_UPLOAD_ID', path);
}
Fs.stat(path, function (err, stats) {
@ -583,9 +583,10 @@ var resetUserPins = function (Env, publicKey, channelList, cb) {
if (e) { return void cb(e); }
var pinSize = sumChannelSizes(sizes);
getFreeSpace(Env, publicKey, function (e, free) {
getLimit(Env, publicKey, function (e, limit) {
if (e) {
WARN('getFreeSpace', e);
WARN('[RESET_ERR]', 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
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]),
function (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) {
return [
'COOKIE',
@ -834,11 +842,8 @@ var isAuthenticatedCall = function (call) {
'UNPIN',
'GET_HASH',
'GET_TOTAL_SIZE',
'GET_FILE_SIZE',
'UPDATE_LIMITS',
'GET_LIMIT',
'GET_MULTIPLE_FILE_SIZE',
//'UPLOAD',
'UPLOAD_COMPLETE',
'UPLOAD_CANCEL',
].indexOf(call) !== -1;
@ -867,6 +872,34 @@ RPC.create = function (config /*:typeof(ConfigType)*/, cb /*:(?Error, ?Function)
var blobPath = paths.blob = keyOrDefaultString('blobPath', './blob');
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 (
ctx /*:{ store: Object }*/,
data /*:Array<Array<any>>*/,
@ -888,11 +921,19 @@ RPC.create = function (config /*:typeof(ConfigType)*/, cb /*:(?Error, ?Function)
return void respond('INVALID_ARG_FORMAT');
}
if (isUnauthenticateMessage(msg)) {
return handleUnauthenticatedMessage(msg, respond);
}
var signature = msg.shift();
var publicKey = msg.shift();
// make sure a user object is initialized in the cookie jar
if (publicKey) {
beginSession(Sessions, publicKey);
} else {
console.log("No public key");
}
var cookie = msg[0];
if (!isValidCookie(Sessions, publicKey, cookie)) {
@ -928,7 +969,8 @@ RPC.create = function (config /*:typeof(ConfigType)*/, cb /*:(?Error, ?Function)
msg.shift();
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('|');
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);
}
// restrict upload capability unless explicitly disabled
if (config.restrictUploads === false) {
// allow unrestricted uploads unless restrictUploads is true
if (config.restrictUploads !== true) {
return void handleMessage(true);
}

@ -3,33 +3,6 @@
<head>
<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/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>
<style> .loading-hidden { display: none; } </style>
</head>

@ -1,8 +1,37 @@
define([
'jquery',
'cm/lib/codemirror',
'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/code/code.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');
});

@ -9,7 +9,6 @@ define([
'/common/cryptpad-common.js',
'/common/cryptget.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',
'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');
editor = CodeMirror.editor;
@ -429,7 +428,6 @@ define([
};
var interval = 100;
var second = function (CM) {
Cryptpad.ready(function () {
andThen(CM);
@ -444,11 +442,9 @@ define([
var first = function () {
if (ifrw.CodeMirror) {
// it exists, call your continuation
second(ifrw.CodeMirror);
} else {
console.log("CodeMirror was not defined. Trying again in %sms", interval);
// try again in 'interval' ms
setTimeout(first, interval);
}
};

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

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

@ -1,4 +1,4 @@
define(function () {
define(['jquery'], function ($) {
var module = {};
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
exp.updateTitle = function (newTitle, href) {
exp.updateTitle = function (newTitle, href, cb) {
cb = cb || $.noop;
if (newTitle === exp.title) { return; }
// Change the title now, and set it back to the old value if there is an error
var oldTitle = exp.title;
@ -54,9 +55,10 @@ define(function () {
console.log("Couldn't set pad title");
console.error(err);
updateLocalTitle(oldTitle);
return;
return void cb(err);
}
updateLocalTitle(data);
cb(null, data);
if (!$title) { return; }
$title.find('span.title').text(data);
$title.find('input').val(data);

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

@ -16,9 +16,10 @@ define([
'/common/clipboard.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,
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
any particular pad type. This includes functions for committing metadata
@ -49,6 +50,7 @@ define([
var store;
var rpc;
var anon_rpc;
// import UI elements
common.findCancelButton = UI.findCancelButton;
@ -76,7 +78,7 @@ define([
var deduplicateString = common.deduplicateString = Util.deduplicateString;
common.uint8ArrayToHex = Util.uint8ArrayToHex;
common.replaceHash = Util.replaceHash;
var getHash = common.getHash = Util.getHash;
common.getHash = Util.getHash;
common.fixFileName = Util.fixFileName;
common.bytesToMegabytes = Util.bytesToMegabytes;
common.bytesToKilobytes = Util.bytesToKilobytes;
@ -146,6 +148,16 @@ define([
}
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) {
if (force !== true) {
@ -414,9 +426,8 @@ define([
// STORAGE
common.setPadAttribute = function (attr, value, cb) {
getStore().setDrive([getHash(), attr].join('.'), value, function (err, data) {
cb(err, data);
});
var href = getRelativeHref(window.location.href);
getStore().setPadAttribute(href, attr, value, cb);
};
common.setAttribute = function (attr, value, cb) {
getStore().set(["cryptpad", attr].join('.'), value, function (err, data) {
@ -429,9 +440,8 @@ define([
// STORAGE
common.getPadAttribute = function (attr, cb) {
getStore().getDrive([getHash(), attr].join('.'), function (err, data) {
cb(err, data);
});
var href = getRelativeHref(window.location.href);
getStore().getPadAttribute(href, attr, cb);
};
common.getAttribute = function (attr, cb) {
getStore().get(["cryptpad", attr].join('.'), function (err, data) {
@ -777,11 +787,32 @@ define([
};
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);
rpc.getFileSize(channelId, function (e, bytes) {
anon_rpc.send("GET_FILE_SIZE", channelId, function (e, response) {
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'); }
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.note) !== 'string') {
return void rpc.getLimit(function (e, limit, plan, note) {
@ -863,7 +896,6 @@ define([
var $container = $('<span>', {'class':'limit-container'});
var todo;
var updateUsage = window.updateUsage = common.notAgainForAnother(function () {
console.log("updating usage bar");
common.getPinnedUsage(todo);
}, LIMIT_REFRESH_RATE);
@ -933,21 +965,12 @@ define([
};
setInterval(function () {
var t = updateUsage();
if (t) {
console.log("usage already updated. eligible for refresh in %sms", t);
}
updateUsage();
}, LIMIT_REFRESH_RATE * 3);
updateUsage();
getProxy().on('change', ['drive'], function () {
var t = updateUsage();
if (t) {
console.log("usage bar update throttled due to overuse." +
" Eligible for update in %sms", t);
} else {
console.log("usage bar updated");
}
updateUsage();
});
cb(null, $container);
};
@ -1162,16 +1185,82 @@ define([
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 = [
'image/png',
'image/jpeg',
'image/jpg',
'image/gif',
];
common.displayAvatar = function ($container, href) {
common.displayAvatar = function ($container, href, name, cb) {
var MutationObserver = window.MutationObserver;
$container.html('');
if (href) {
var displayDefault = function () {
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 secret = common.getSecrets('file', parsed.hash);
if (secret.keys && secret.channel) {
@ -1179,24 +1268,23 @@ define([
var hexFileName = common.base64ToHex(secret.channel);
var src = common.getBlobPathFromHex(hexFileName);
common.getFileSize(href, function (e, data) {
if (e) { return void console.error(e); }
if (typeof data !== "number") { return; }
if (common.bytesToMegabytes(data) > 0.5) { return; }
if (e) {
displayDefault();
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);
$img.attr('src', src);
$img.attr('data-crypto-key', 'cryptpad:' + cryptKey);
require(['/common/media-tag.js'], function (MediaTag) {
MediaTag.CryptoFilter.setAllowedMediaTypes(common.avatarAllowedTypes);
MediaTag($img[0]);
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if (mutation.type === 'childList' && mutation.addedNodes.length) {
console.log(mutation);
if (mutation.addedNodes.length > 1 ||
mutation.addedNodes[0].nodeName !== 'IMG') {
$img.remove();
return;
//TODO display default avatar
return void displayDefault();
}
var $image = $img.find('img');
var onLoad = function () {
@ -1205,16 +1293,17 @@ define([
if (w>h) {
$image.css('max-height', '100%');
$img.css('flex-direction', 'row');
if (cb) { cb($img); }
return;
}
$image.css('max-width', '100%');
$img.css('flex-direction', 'column');
if (cb) { cb($img); }
};
if ($image[0].complete) { onLoad(); }
$image.on('load', onLoad);
}
});
});
observer.observe($img[0], {
attributes: false,
childList: true,
@ -1223,7 +1312,6 @@ define([
});
});
}
}
};
// Create a button with a dropdown menu
@ -1301,7 +1389,7 @@ define([
setActive($val);
$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) {
@ -1457,6 +1545,13 @@ define([
content: Messages.user_rename
});
}
if (account) {
options.push({
tag: 'a',
attributes: {'class': 'profile'},
content: Messages.profileButton
});
}
if (parsed && (!parsed.type || parsed.type !== 'settings')) {
options.push({
tag: 'a',
@ -1516,6 +1611,13 @@ define([
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 () {
if (window.location.pathname !== "/") {
sessionStorage.redirectTo = window.location.href;
@ -1666,6 +1768,21 @@ define([
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...
if($('#pad-iframe').length) {
block++;

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

@ -60,6 +60,9 @@ define([
cb(void 0, res);
};
ret.setPadAttribute = filesOp.setAttribute;
ret.getPadAttribute = filesOp.getAttribute;
ret.getDrive = function (key, cb) {
cb(void 0, storeObj.drive[key]);
};
@ -211,6 +214,10 @@ define([
if (typeof(n) !== "string") { return; }
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 () {
console.log('wut');
var localToken = tryParsing(localStorage.getItem(tokenKey));

File diff suppressed because one or more lines are too long

@ -86,7 +86,7 @@ define([
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
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
var todo = function (err, doc) {

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

@ -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
// channels which the server has pinned for your publicKey
exp.getFileListSize = function (cb) {

@ -99,7 +99,12 @@ types of messages:
delete ctx.pending[txid];
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);
}
};
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 };
});

@ -81,15 +81,31 @@ define([
var $rightside = $toolbar.find('.'+RIGHTSIDE_CLS);
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);
$drawer.click(function () {
$drawerContent.toggle();
$drawer.removeClass('active');
if ($drawerContent.is(':visible')) {
$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
@ -149,6 +165,7 @@ define([
return $.inArray(i, b) > -1;
});
};
var avatars = {};
var updateUserList = function (toolbar, config) {
// Make sure the elements are displayed
var $userButtons = toolbar.userlist;
@ -189,7 +206,25 @@ define([
// Editors
editUsersNames.forEach(function (data) {
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);
$editUsersList.append($span);
});
@ -197,9 +232,9 @@ define([
// Viewers
if (numberOfViewUsers > 0) {
var viewText = '<span class="viewer">';
var viewText = '<div class="viewer">';
var viewerText = numberOfViewUsers !== 1 ? Messages.viewers : Messages.viewer;
viewText += numberOfViewUsers + ' ' + viewerText + '</span>';
viewText += numberOfViewUsers + ' ' + viewerText + '</div>';
$editUsers.append(viewText);
}
@ -299,6 +334,11 @@ define([
if ($content.is(':visible')) { return void show(); }
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);
$button.click(function () {
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!
var $aTag = $('<a>', {
href: "/",
href: "/drive/",
title: Messages.header_logoTitle,
'class': "cryptpad-logo fa fa-hdd-o"
});
var onClick = function (e) {
e.preventDefault();
if (e.ctrlKey) {
window.open('/drive');
window.open('/drive/');
return;
}
window.location = "/drive";
window.location = "/drive/";
};
var onContext = function (e) { e.stopPropagation(); };

@ -132,6 +132,21 @@ define([
if (type === 'name') { return data.filename; }
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
@ -970,6 +985,20 @@ define([
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 () {
if (typeof files[FILES_DATA] !== "object") { debug("OLD_FILES_DATA was not an object"); files[FILES_DATA] = {}; }
var fd = files[FILES_DATA];
@ -989,6 +1018,15 @@ define([
toClean.push(id);
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) {
debug("An element in filesData was not in ROOT, TEMPLATE or TRASH.", id, el);
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();
fixTrashRoot();
if (!workgroup) {
fixTemplate();
fixFilesData();
}
fixDrive();
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");

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

@ -1170,7 +1170,7 @@ define([
var element = filesOp.find(newPath);
var $icon = !isFolder ? getFileIcon(element) : undefined;
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 liClass = 'file-item file-element element' + roClass;
if (isFolder) {
@ -2140,6 +2140,7 @@ define([
$trashContextMenu.hide();
$contentContextMenu.hide();
$defaultContextMenu.hide();
$iframe.find('.cryptpad-dropdown').hide();
};
var stringifyPath = function (path) {

@ -242,6 +242,18 @@ define([
fo.migrate(todo);
}, "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
// UTILS

@ -7,12 +7,14 @@ define([
'/common/visible.js',
'/common/notify.js',
'/file/file-crypto.js',
'/common/media-tag.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',
'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 saveAs = window.saveAs;
var Nacl = window.nacl;
@ -91,7 +93,9 @@ define([
$(window.document).on('decryption', function (e) {
var decrypted = e.originalEvent;
if (decrypted.callback) { decrypted.callback(); }
if (decrypted.callback) {
decrypted.callback();
}
console.log(decrypted);
$dlview.show();
@ -131,7 +135,6 @@ define([
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.
*
@ -156,7 +159,6 @@ define([
MediaTag.CryptoFilter.setAllowedMediaTypes(allowedMediaTypes);
MediaTag($mt[0]);
});
};
var todoBigFile = function (sizeMb) {
@ -181,9 +183,6 @@ define([
};
Cryptpad.getFileSize(window.location.href, function (e, data) {
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);
}
var size = Cryptpad.bytesToMegabytes(data);

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

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

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

@ -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;
}

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

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

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

@ -118,6 +118,7 @@ define([
return void Cryptpad.alert(Messages.register_mustAcceptTerms);
}
setTimeout(function () {
Cryptpad.confirm("<h2 class='bright'>" + Messages.register_warning + "</h2>",
function (yes) {
if (!yes) { return; }
@ -200,6 +201,24 @@ define([
}, true, function ($dialog) {
$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 () {

@ -6,34 +6,6 @@
<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/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>
<style>.loading-hidden { display: none; } </style>
</head>

@ -1,8 +1,41 @@
define([
'jquery',
'cm/lib/codemirror',
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
'less!/customize/src/less/toolbar.less',
'less!/customize/src/less/cryptpad.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');
});

@ -9,7 +9,6 @@ define([
'/common/cryptpad-common.js',
'/common/cryptget.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',
'less!/customize/src/less/cryptpad.less',
@ -53,7 +52,7 @@ define([
var andThen = function (CMeditor) {
var $iframe = $('#pad-iframe').contents();
var $contentContainer = $iframe.find('#editorContainer');
var CodeMirror = Cryptpad.createCodemirror(CMeditor, ifrw, Cryptpad);
var CodeMirror = Cryptpad.createCodemirror(ifrw, Cryptpad, null, CMeditor);
editor = CodeMirror.editor;
var $bar = $('#pad-iframe')[0].contentWindow.$('#cme_toolbox');
@ -468,7 +467,10 @@ define([
Cryptpad.feedback('PRINT_SLIDES');
//$('body').append(createPrintDialog());
}).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>', {
title: Messages.slideOptionsTitle,
@ -590,7 +592,7 @@ define([
Cryptpad.getPadAttribute('previewMode', function (e, data) {
if (e) { return void console.error(e); }
if (data === true && APP.$previewButton) {
if ([true, undefined].indexOf(data) !== -1 && APP.$previewButton) {
APP.$previewButton.click();
}
});

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

Loading…
Cancel
Save