Merge branch 'infiniteSpinner' into fileManager

This commit is contained in:
yflory
2016-12-08 16:01:59 +01:00
20 changed files with 588 additions and 72 deletions

View File

@@ -4,7 +4,8 @@ define([
'/bower_components/hyperjson/hyperjson.js',
'/bower_components/textpatcher/TextPatcher.amd.js',
'json.sortify',
], function (jQuery, Hyperjson, TextPatcher, Sortify) {
'/common/cryptpad-common.js',
], function (jQuery, Hyperjson, TextPatcher, Sortify, Cryptpad) {
var $ = window.jQuery;
window.Hyperjson = Hyperjson;
window.TextPatcher = TextPatcher;
@@ -140,6 +141,19 @@ define([
strungJSON(orig);
});
assert(function () {
var missing = Cryptpad.Messages._checkTranslationState();
if (missing.length !== 0) {
missing.forEach(function (msg) {
console.log('* ' + msg);
});
return false;
}
return true;
}, "expected all translation keys in default language to be present in all translations. See console for details.");
var swap = function (str, dict) {
return str.replace(/\{\{(.*?)\}\}/g, function (all, key) {
return typeof dict[key] !== 'undefined'? dict[key] : all;

View File

@@ -253,18 +253,21 @@ define([
var clike = /^\s*(\/\*|\/\/)(.*)?(\*\/)*$/;
if (clike.test(line)) {
line.replace(clike, function (a, one, two) {
if (!(two && two.replace)) { return; }
text = two.replace(/\*\/\s*$/, '').trim();
});
return true;
}
// TODO make one more pass for multiline comments
});
return text.trim();
};
var suggestName = function () {
var suggestName = function (fallback) {
if (document.title === defaultName) {
return getHeadingText() || "";
return getHeadingText() || fallback || "";
} else {
return document.title || getHeadingText() || defaultName;
}
@@ -275,7 +278,7 @@ define([
var ext = Modes.extensionOf(module.highlightMode);
var title = Cryptpad.fixFileName(suggestName()) + ext;
var title = Cryptpad.fixFileName(suggestName('cryptpad')) + (ext || '.txt');
Cryptpad.prompt(Messages.exportPrompt, title, function (filename) {
if (filename === null) { return; }
@@ -495,9 +498,7 @@ define([
}
// set the hash
if (!readOnly) {
window.location.hash = editHash;
}
if (!readOnly) { Cryptpad.replaceHash(editHash); }
Cryptpad.getPadTitle(function (err, title) {
if (err) {
@@ -686,6 +687,11 @@ define([
}
};
var onError = config.onError = function (info) {
module.spinner.hide();
Cryptpad.alert(Messages.websocketError);
};
var realtime = module.realtime = Realtime.start(config);
editor.on('change', onLocal);

View File

@@ -28,6 +28,7 @@ define([
var common = {
User: User,
Messages: Messages,
};
var store;
var fsStore;
@@ -238,6 +239,14 @@ define([
return secret;
};
var replaceHash = common.replaceHash = function (hash) {
if (window.history && window.history.replaceState) {
if (!/^#/.test(hash)) { hash = '#' + hash; }
return void window.history.replaceState({}, window.document.title, hash);
}
window.location.hash = hash;
};
var storageKey = common.storageKey = 'CryptPad_RECENTPADS';
/*
@@ -580,6 +589,7 @@ define([
$(function() {
// Race condition : if document.body is undefined when alertify.js is loaded, Alertify
// won't work. We have to reset it now to make sure it uses a correct "body"
Alertify.reset();
if($('#pad-iframe').length) {
var $iframe = $('#pad-iframe');
@@ -869,6 +879,7 @@ define([
var styleAlerts = common.styleAlerts = function (href) {
var $link = $('link[href="/customize/alertify.css"]');
if ($link.length) {
return;
$link.attr('href', '');
$link.attr('href', '/customize/alertify.css');
return;

View File

@@ -313,12 +313,11 @@ define([
}
}
else if (!firstConnection) {
lagErrors++;
// Display the red light at the 2nd failed attemp to get the lag
if (lagErrors > 1) {
//if (lagErrors > 1) {
lagLight.addClass('lag-red');
title = Messages.redLight;
}
//}
}
if (title) {
lagLight.attr('title', title);

View File

@@ -35,8 +35,23 @@ define([
window.Toolbar = Toolbar;
window.Hyperjson = Hyperjson;
var slice = function (coll) {
return Array.prototype.slice.call(coll);
};
var removeListeners = function (root) {
slice(root.attributes).map(function (attr) {
if (/^on/.test(attr.name)) {
root.attributes.removeNamedItem(attr.name);
}
});
slice(root.children).forEach(removeListeners);
};
var hjsonToDom = function (H) {
return Hyperjson.toDOM(H); //callOn(H, Hyperscript);
var dom = Hyperjson.toDOM(H);
removeListeners(dom);
return dom;
};
var module = window.REALTIME_MODULE = window.APP = {
@@ -321,9 +336,9 @@ define([
})) { return text; }
};
var suggestName = function () {
var suggestName = function (fallback) {
if (document.title === defaultName) {
return getHeadingText() || "";
return getHeadingText() || fallback || "";
} else {
return document.title || getHeadingText() || defaultName;
}
@@ -510,7 +525,7 @@ define([
var exportFile = function () {
var html = getHTML();
var suggestion = suggestName();
var suggestion = suggestName('cryptpad-document');
Cryptpad.prompt(Messages.exportPrompt,
Cryptpad.fixFileName(suggestion) + '.html', function (filename) {
if (!(typeof(filename) === 'string' && filename)) { return; }
@@ -601,9 +616,7 @@ define([
}
// set the hash
if (!readOnly) {
window.location.hash = editHash;
}
if (!readOnly) { Cryptpad.replaceHash(editHash); }
Cryptpad.getPadTitle(function (err, title) {
if (err) {
@@ -678,6 +691,11 @@ define([
}
};
var onError = realtimeOptions.onError = function (info) {
module.spinner.hide();
Cryptpad.alert(Messages.websocketError);
};
var onLocal = realtimeOptions.onLocal = function () {
if (initializing) { return; }
if (readOnly) { return; }

View File

@@ -72,6 +72,23 @@ define([
});
};
var getLastName = module.getLastName = function (cb) {
Cryptpad.getAttribute('username', function (err, userName) {
cb(err, userName || '');
});
};
var setName = module.setName = function (uname, cb) {
if (typeof(uname) !== 'string') {
return void cb(new Error('expected string'));
}
uname = Cryptpad.fixHTML(uname.trim()).slice(0, 32);
Cryptpad.setAttribute('username', uname, function (err, data) {
if (err) { return void cb(err); }
cb(void 0, uname);
});
};
module.Wizard = Wizard;
// special UI elements
@@ -320,12 +337,19 @@ define([
};
var scrollDown = module.scrollDown = function (px) {
if (module.scrolling) { return; }
module.scrolling = true;
var top = $(window).scrollTop() + px + 'px';
$('html, body').animate({
scrollTop: top,
}, {
duration: 200,
easing: 'swing',
complete: function () {
module.scrolling = false;
}
});
};
@@ -397,7 +421,10 @@ define([
addIfAbsent(proxy.table.rowsOrder, id);
var $row = table.addRow($wrapper, Checkbox, id);
scrollDown($row.height());
if (module.ready) {
scrollDown($row.height());
}
return $option;
};
@@ -408,7 +435,7 @@ define([
var msg = Messages.poll_addUser;
Cryptpad.prompt(msg, "", function (name) {
if (name === null) { return; }
if (!(name && name.trim())) { return; }
makeUser(module.rt.proxy, id, name).val(name);
makeUserEditable(id, true).focus();
});
@@ -439,7 +466,7 @@ define([
var id = rowuid();
makeOption(proxy, id, text).val(text);
});
//console.log(options);
Wizard.hide();
});
});
@@ -755,14 +782,16 @@ define([
}));
}
/*
if (!readOnly && module.viewHash) {
/* add a 'links' button */
/* add a 'links' button
var $links = Cryptpad.createButton('readonly', true, {viewHash: module.viewHash})
.text(Messages.getViewButton)
.removeAttr('style')
.attr('class', 'action button readonly');
$toolbar.append($links);
}
*/
/* Import/Export buttons */
/*
@@ -815,7 +844,11 @@ define([
setEditable(true);
return;
// shortcircuiting before all of this code since it's not quite the
// behaviour we want, and it's a bit of work to make it Do The Right Thing
/*
if (First) {
// assume the first user to the poll wants to be the administrator...
// TODO prompt them with questions to set up their poll...
@@ -830,40 +863,34 @@ define([
module.activeColumn = '';
var promptForName = function () {
// HERE
Cryptpad.prompt(Messages.promptName, "", function (name, ev) {
if (name === null) {
name = '';
}
if (!module.isEditable) { return; }
var followUp = function (name) {
if (!name) { return; }
var id = module.activeColumn = coluid();
Cryptpad.setPadAttribute('column', id, function (err) {
if (err) {
console.error("Couldn't remember your column id");
return;
}
console.log(id);
if (err) { return void console.error("Couldn't remember your column id"); }
makeUser(module.rt.proxy, id, name).focus().val(name);
makeUserEditable(id, true);
});
};
getLastName(function (err, uname) {
if (!uname) {
return void Cryptpad.prompt(Messages.promptName, "", function (name, ev) {
if (!(name || module.isEditable)) { return; }
followUp(name);
});
}
followUp(uname);
});
};
if (column === null) {
//console.log("Looks like you're new to this poll, why don't you make a column");
promptForName();
return;
}
if (column === null) { return void promptForName(); }
// column might be defined, but that column might have been deleted...
if (proxy.table.colsOrder.indexOf(column) === -1) {
promptForName();
return;
}
});
if (proxy.table.colsOrder.indexOf(column) === -1) { return void promptForName(); }
});*/
};
var config = {
@@ -889,9 +916,7 @@ define([
editHash = Cryptpad.getEditHashFromKeys(info.channel, secret.keys);
}
// set the hash
if (!readOnly) {
window.location.hash = editHash;
}
if (!readOnly) { Cryptpad.replaceHash(editHash); }
module.patchText = TextPatcher.create({
realtime: realtime,

View File

@@ -585,7 +585,7 @@ define([
// set the hash
if (!window.location.hash || window.location.hash === '#') {
window.location.hash = editHash;
Cryptpad.replaceHash(editHash);
}
Cryptpad.getPadTitle(function (err, title) {
@@ -786,6 +786,11 @@ define([
}
};
var onError = config.onError = function (info) {
module.spinner.hide();
Cryptpad.alert(Messages.websocketError);
};
var realtime = module.realtime = Realtime.start(config);
editor.on('change', onLocal);

View File

@@ -45,7 +45,7 @@ define([
var unsafeTag = function (info) {
if (['addAttribute', 'modifyAttribute'].indexOf(info.diff.action) !== -1) {
if (/^on/.test(info.diff.name)) {
console.log("Rejecting forbidden element attribute with name", info.diff.element.nodeName);
console.log("Rejecting forbidden element attribute with name", info.diff.name);
return true;
}
}
@@ -91,12 +91,28 @@ define([
return patch;
};
var slice = function (coll) {
return Array.prototype.slice.call(coll);
};
/* remove listeners from the DOM */
var removeListeners = function (root) {
slice(root.attributes).map(function (attr) {
if (/^on/.test(attr.name)) {
root.attributes.removeNamedItem(attr.name);
}
});
// all the way down
slice(root.children).forEach(removeListeners);
};
var draw = Slide.draw = function (i) {
console.log("Trying to draw slide #%s", i);
if (typeof(Slide.content[i]) !== 'string') { return; }
var c = Slide.content[i];
var Dom = domFromHTML('<div id="content">' + Marked(c) + '</div>');
removeListeners(Dom.body);
var patch = makeDiff(domFromHTML($content[0].outerHTML), Dom);
if (typeof(patch) === 'string') {