Separate UI elements from cryptpad-common

pull/1/head
yflory 7 years ago
parent 354c63bd64
commit dc207393fd

@ -2,7 +2,8 @@ define([
'jquery', 'jquery',
'/customize/application_config.js', '/customize/application_config.js',
'/common/cryptpad-common.js', '/common/cryptpad-common.js',
], function ($, Config, Cryptpad) { '/common/common-interface.js',
], function ($, Config, Cryptpad, UI) {
window.APP = { window.APP = {
Cryptpad: Cryptpad, Cryptpad: Cryptpad,
@ -57,34 +58,6 @@ define([
$('#name').focus(); $('#name').focus();
} }
var displayCreateButtons = function () {
var $parent = $('#buttons');
var options = [];
var $container = $('<div>', {'class': 'cp-dropdown-container'}).appendTo($parent);
Config.availablePadTypes.forEach(function (el) {
if (el === 'drive') { return; }
if (!Cryptpad.isLoggedIn() && Config.registeredOnlyTypes &&
Config.registeredOnlyTypes.indexOf(el) !== -1) { return; }
options.push({
tag: 'a',
attributes: {
'class': 'newdoc',
'href': '/' + el + '/',
'target': '_blank'
},
content: Messages['button_new' + el] // Pretty name of the language value
});
});
var dropdownConfig = {
text: Messages.login_makeAPad, // Button initial text
options: options, // Entries displayed in the menu
container: $container
};
var $block = Cryptpad.createDropdown(dropdownConfig);
$block.find('button').addClass('btn').addClass('btn-primary');
$block.appendTo($parent);
};
/* Log in UI */ /* Log in UI */
var Login; var Login;
// deferred execution to avoid unnecessary asset loading // deferred execution to avoid unnecessary asset loading
@ -144,17 +117,17 @@ define([
switch (err) { switch (err) {
case 'NO_SUCH_USER': case 'NO_SUCH_USER':
Cryptpad.removeLoadingScreen(function () { Cryptpad.removeLoadingScreen(function () {
Cryptpad.alert(Messages.login_noSuchUser); UI.alert(Messages.login_noSuchUser);
}); });
break; break;
case 'INVAL_USER': case 'INVAL_USER':
Cryptpad.removeLoadingScreen(function () { Cryptpad.removeLoadingScreen(function () {
Cryptpad.alert(Messages.login_invalUser); UI.alert(Messages.login_invalUser);
}); });
break; break;
case 'INVAL_PASS': case 'INVAL_PASS':
Cryptpad.removeLoadingScreen(function () { Cryptpad.removeLoadingScreen(function () {
Cryptpad.alert(Messages.login_invalPass); UI.alert(Messages.login_invalPass);
}); });
break; break;
default: // UNHANDLED ERROR default: // UNHANDLED ERROR
@ -166,27 +139,6 @@ define([
}, 100); }, 100);
}); });
/* End Log in UI */ /* End Log in UI */
var addButtonHandlers = function () {
$('button.register').click(function () {
var username = $('#name').val();
var passwd = $('#password').val();
sessionStorage.login_user = username;
sessionStorage.login_pass = passwd;
document.location.href = '/register/';
});
$('button.gotodrive').click(function () {
document.location.href = '/drive/';
});
$('button#loggedInLogout').click(function () {
$('#user-menu .logout').click();
});
};
displayCreateButtons();
addButtonHandlers();
console.log("ready"); console.log("ready");
}); });
}); });

@ -30,7 +30,6 @@ if (language && map[language]) { req.push('/customize/translations/messages.' +
define(req, function($, Default, Language) { define(req, function($, Default, Language) {
map.en = 'English'; map.en = 'English';
var defaultLanguage = 'en'; var defaultLanguage = 'en';
console.log(messages);
if (!Language || language === defaultLanguage || !map[language]) { if (!Language || language === defaultLanguage || !map[language]) {
messages = $.extend(true, messages, Default); messages = $.extend(true, messages, Default);
@ -39,7 +38,6 @@ console.log(messages);
// Add the translated keys to the returned object // Add the translated keys to the returned object
messages = $.extend(true, messages, Default, Language); messages = $.extend(true, messages, Default, Language);
} }
console.log(messages);
messages._languages = map; messages._languages = map;
messages._languageUsed = language; messages._languageUsed = language;

@ -488,12 +488,12 @@ define(function () {
out.settings_resetTipsButton = "Réinitialiser les astuces visibles dans CryptDrive"; out.settings_resetTipsButton = "Réinitialiser les astuces visibles dans CryptDrive";
out.settings_resetTipsDone = "Toutes les astuces sont de nouveau visibles."; out.settings_resetTipsDone = "Toutes les astuces sont de nouveau visibles.";
out.settings_thumbnails = "Vignettes"; out.settings_thumbnails = "Miniatures";
out.settings_disableThumbnailsAction = "Désactiver la création de vignettes dans CryptDrive"; out.settings_disableThumbnailsAction = "Désactiver la création de miniatures dans CryptDrive";
out.settings_disableThumbnailsDescription = "Des vignettes de vos pads sont automatiquement créées et stockées dans votre navigateur. Vous pouvez désactiver cette fonctionnalité."; out.settings_disableThumbnailsDescription = "Des miniatures de vos pads sont automatiquement créées et stockées dans votre navigateur. Vous pouvez désactiver cette fonctionnalité.";
out.settings_resetThumbnailsAction = "Nettoyer"; out.settings_resetThumbnailsAction = "Nettoyer";
out.settings_resetThumbnailsDescription = "Nettoyer toutes les vignettes stockées dans votre navigateur."; out.settings_resetThumbnailsDescription = "Nettoyer toutes les miniatures stockées dans votre navigateur.";
out.settings_resetThumbnailsDone = "Toutes les vignettes ont été effacées."; out.settings_resetThumbnailsDone = "Toutes les miniatures ont été effacées.";
out.settings_importTitle = "Importer les pads récents de ce navigateur dans votre CryptDrive"; out.settings_importTitle = "Importer les pads récents de ce navigateur dans votre CryptDrive";
out.settings_import = "Importer"; out.settings_import = "Importer";

@ -3,10 +3,12 @@ define([
'/bower_components/chainpad-crypto/crypto.js', '/bower_components/chainpad-crypto/crypto.js',
'/common/curve.js', '/common/curve.js',
'/common/common-hash.js', '/common/common-hash.js',
'/common/common-util.js',
'/customize/messages.js',
'/bower_components/marked/marked.min.js', '/bower_components/marked/marked.min.js',
'/common/common-realtime.js', '/common/common-realtime.js',
], function ($, Crypto, Curve, Hash, Marked, Realtime) { ], function ($, Crypto, Curve, Hash, Util, Messages, Marked, Realtime) {
var Msg = { var Msg = {
inputs: [], inputs: [],
}; };
@ -98,7 +100,7 @@ define([
var msg; var msg;
if (sender === network.historyKeeper) { return; } if (sender === network.historyKeeper) { return; }
try { try {
var parsed = common.parsePadUrl(window.location.href); var parsed = Hash.parsePadUrl(window.location.href);
if (!parsed.hashData) { return; } if (!parsed.hashData) { return; }
var chan = parsed.hashData.channel; var chan = parsed.hashData.channel;
// Decrypt // Decrypt
@ -132,11 +134,11 @@ define([
todo(true); todo(true);
return; return;
} }
var confirmMsg = common.Messages._getKey('contacts_request', [ var confirmMsg = Messages._getKey('contacts_request', [
common.fixHTML(msgData.displayName) Util.fixHTML(msgData.displayName)
]); ]);
common.onFriendRequest(confirmMsg, todo); common.onFriendRequest(confirmMsg, todo);
//common.confirm(confirmMsg, todo, null, true); //UI.confirm(confirmMsg, todo, null, true);
return; return;
} }
if (msg[0] === "FRIEND_REQ_OK") { if (msg[0] === "FRIEND_REQ_OK") {
@ -147,12 +149,12 @@ define([
addToFriendList(common, msgData, function (err) { addToFriendList(common, msgData, function (err) {
if (err) { if (err) {
return void common.onFriendComplete({ return void common.onFriendComplete({
logText: common.Messages.contacts_addError, logText: Messages.contacts_addError,
netfluxId: sender netfluxId: sender
}); });
} }
common.onFriendComplete({ common.onFriendComplete({
logText: common.Messages.contacts_added, logText: Messages.contacts_added,
netfluxId: sender netfluxId: sender
}); });
var msg = ["FRIEND_REQ_ACK", chan]; var msg = ["FRIEND_REQ_ACK", chan];
@ -165,7 +167,7 @@ define([
var i = pendingRequests.indexOf(sender); var i = pendingRequests.indexOf(sender);
if (i !== -1) { pendingRequests.splice(i, 1); } if (i !== -1) { pendingRequests.splice(i, 1); }
common.onFriendComplete({ common.onFriendComplete({
logText: common.Messages.contacts_rejected, logText: Messages.contacts_rejected,
netfluxId: sender netfluxId: sender
}); });
common.changeDisplayName(proxy[common.displayNameKey]); common.changeDisplayName(proxy[common.displayNameKey]);
@ -177,12 +179,12 @@ define([
addToFriendList(common, data, function (err) { addToFriendList(common, data, function (err) {
if (err) { if (err) {
return void common.onFriendComplete({ return void common.onFriendComplete({
logText: common.Messages.contacts_addError, logText: Messages.contacts_addError,
netfluxId: sender netfluxId: sender
}); });
} }
common.onFriendComplete({ common.onFriendComplete({
logText: common.Messages.contacts_added, logText: Messages.contacts_added,
netfluxId: sender netfluxId: sender
}); });
}); });
@ -201,7 +203,7 @@ define([
Msg.inviteFromUserlist = function (common, netfluxId) { Msg.inviteFromUserlist = function (common, netfluxId) {
var network = common.getNetwork(); var network = common.getNetwork();
var parsed = common.parsePadUrl(window.location.href); var parsed = Hash.parsePadUrl(window.location.href);
if (!parsed.hashData) { return; } if (!parsed.hashData) { return; }
// Message // Message
var chan = parsed.hashData.channel; var chan = parsed.hashData.channel;

@ -1,7 +1,8 @@
define([ define([
'/customize/application_config.js', '/customize/application_config.js',
'/customize/messages.js', '/customize/messages.js',
], function (AppConfig, Messages) { '/common/common-interface.js',
], function (AppConfig, Messages, UI) {
var common = {}; var common = {};
common.infiniteSpinnerDetected = false; common.infiniteSpinnerDetected = false;
@ -44,7 +45,7 @@ define([
infiniteSpinnerHandlers.forEach(function (ish) { ish(); }); infiniteSpinnerHandlers.forEach(function (ish) { ish(); });
// inform the user their session is in a bad state // inform the user their session is in a bad state
Cryptpad.confirm(Messages.realtime_unrecoverableError, function (yes) { UI.confirm(Messages.realtime_unrecoverableError, function (yes) {
if (!yes) { return; } if (!yes) { return; }
window.parent.location.reload(); window.parent.location.reload();
}); });

@ -4,13 +4,14 @@ define([
'/common/cryptpad-common.js', '/common/cryptpad-common.js',
'/common/common-util.js', '/common/common-util.js',
'/common/common-language.js', '/common/common-language.js',
'/common/common-interface.js',
'/common/media-tag.js', '/common/media-tag.js',
'/common/tippy.min.js', '/common/tippy.min.js',
'/customize/application_config.js', '/customize/application_config.js',
'css!/common/tippy.css', 'css!/common/tippy.css',
], function ($, Config, Cryptpad, Util, Language, MediaTag, Tippy, AppConfig) { ], function ($, Config, Cryptpad, Util, UI, Language, MediaTag, Tippy, AppConfig) {
var UI = {}; var UIElements = {};
var Messages = Cryptpad.Messages; var Messages = Cryptpad.Messages;
/** /**
@ -24,17 +25,14 @@ define([
* - base64ToHex * - base64ToHex
* - getBlobPathFromHex * - getBlobPathFromHex
* - bytesToMegabytes * - bytesToMegabytes
* createUserAdminMenu
* - fixHTML
* - createDropdown
*/ */
UI.updateTags = function (common, href) { UIElements.updateTags = function (common, href) {
var sframeChan = common.getSframeChannel(); var sframeChan = common.getSframeChannel();
sframeChan.query('Q_TAGS_GET', href || null, function (err, res) { sframeChan.query('Q_TAGS_GET', href || null, function (err, res) {
if (err || res.error) { if (err || res.error) {
if (res.error === 'NO_ENTRY') { if (res.error === 'NO_ENTRY') {
Cryptpad.alert(Messages.tags_noentry); UI.alert(Messages.tags_noentry);
} }
return void console.error(err || res.error); return void console.error(err || res.error);
} }
@ -48,7 +46,7 @@ define([
}); });
}; };
UI.createButton = function (common, type, rightside, data, callback) { UIElements.createButton = function (common, type, rightside, data, callback) {
var AppConfig = common.getAppConfig(); var AppConfig = common.getAppConfig();
var button; var button;
var size = "17px"; var size = "17px";
@ -93,7 +91,7 @@ define([
target: data.target target: data.target
}; };
if (data.filter && !data.filter(file)) { if (data.filter && !data.filter(file)) {
Cryptpad.log('Invalid avatar (type or size)'); UI.log('Invalid avatar (type or size)');
return; return;
} }
data.FM.handleFile(file, ev); data.FM.handleFile(file, ev);
@ -142,11 +140,11 @@ define([
title: title, title: title,
toSave: toSave toSave: toSave
}, function () { }, function () {
Cryptpad.alert(Messages.templateSaved); UI.alert(Messages.templateSaved);
common.feedback('TEMPLATE_CREATED'); common.feedback('TEMPLATE_CREATED');
}); });
}; };
Cryptpad.prompt(Messages.saveTemplatePrompt, title, todo); UI.prompt(Messages.saveTemplatePrompt, title, todo);
}); });
} }
break; break;
@ -162,12 +160,12 @@ define([
.click(common.prepareFeedback(type)) .click(common.prepareFeedback(type))
.click(function() { .click(function() {
var msg = common.isLoggedIn() ? Messages.forgetPrompt : Messages.fm_removePermanentlyDialog; var msg = common.isLoggedIn() ? Messages.forgetPrompt : Messages.fm_removePermanentlyDialog;
Cryptpad.confirm(msg, function (yes) { UI.confirm(msg, function (yes) {
if (!yes) { return; } if (!yes) { return; }
sframeChan.query('Q_MOVE_TO_TRASH', null, function (err) { sframeChan.query('Q_MOVE_TO_TRASH', null, function (err) {
if (err) { return void callback(err); } if (err) { return void callback(err); }
var cMsg = common.isLoggedIn() ? Messages.movedToTrash : Messages.deleted; var cMsg = common.isLoggedIn() ? Messages.movedToTrash : Messages.deleted;
Cryptpad.alert(cMsg, undefined, true); UI.alert(cMsg, undefined, true);
callback(); callback();
return; return;
}); });
@ -220,7 +218,7 @@ define([
title: Messages.tags_title, title: Messages.tags_title,
}) })
.click(common.prepareFeedback(type)) .click(common.prepareFeedback(type))
.click(function () { UI.updateTags(common, null); }); .click(function () { UIElements.updateTags(common, null); });
break; break;
default: default:
button = $('<button>', { button = $('<button>', {
@ -236,7 +234,7 @@ define([
}; };
// Avatars // Avatars
UI.displayMediatagImage = function (Common, $tag, cb) { UIElements.displayMediatagImage = function (Common, $tag, cb) {
if (!$tag.length || !$tag.is('media-tag')) { return void cb('NOT_MEDIATAG'); } if (!$tag.length || !$tag.is('media-tag')) { return void cb('NOT_MEDIATAG'); }
var observer = new MutationObserver(function(mutations) { var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) { mutations.forEach(function(mutation) {
@ -267,9 +265,30 @@ define([
}); });
MediaTag($tag[0]); MediaTag($tag[0]);
}; };
UI.displayAvatar = function (Common, $container, href, name, cb) {
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];
};
UIElements.displayAvatar = function (Common, $container, href, name, cb) {
var displayDefault = function () { var displayDefault = function () {
var text = Cryptpad.getFirstEmojiOrCharacter(name); var text = getFirstEmojiOrCharacter(name);
var $avatar = $('<span>', {'class': 'cp-avatar-default'}).text(text); var $avatar = $('<span>', {'class': 'cp-avatar-default'}).text(text);
$container.append($avatar); $container.append($avatar);
if (cb) { cb(); } if (cb) { cb(); }
@ -291,7 +310,7 @@ define([
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);
UI.displayMediatagImage(Common, $img, function (err, $image, img) { UIElements.displayMediatagImage(Common, $img, function (err, $image, img) {
if (err) { return void console.error(err); } if (err) { return void console.error(err); }
var w = img.width; var w = img.width;
var h = img.height; var h = img.height;
@ -317,7 +336,7 @@ define([
update. update.
*/ */
var LIMIT_REFRESH_RATE = 30000; // milliseconds var LIMIT_REFRESH_RATE = 30000; // milliseconds
UI.createUsageBar = function (common, cb) { UIElements.createUsageBar = function (common, cb) {
if (!common.isLoggedIn()) { return cb("NOT_LOGGED_IN"); } if (!common.isLoggedIn()) { return cb("NOT_LOGGED_IN"); }
// getPinnedUsage updates common.account.usage, and other values // getPinnedUsage updates common.account.usage, and other values
// so we can just use those and only check for errors // so we can just use those and only check for errors
@ -404,7 +423,158 @@ define([
cb(null, $container); cb(null, $container);
}; };
UI.createUserAdminMenu = function (Common, config) { // Create a button with a dropdown menu
// input is a config object with parameters:
// - container (optional): the dropdown container (span)
// - text (optional): the button text value
// - options: array of {tag: "", attributes: {}, content: "string"}
//
// allowed options tags: ['a', 'hr', 'p']
UIElements.createDropdown = function (config) {
if (typeof config !== "object" || !Array.isArray(config.options)) { return; }
var allowedTags = ['a', 'p', 'hr'];
var isValidOption = function (o) {
if (typeof o !== "object") { return false; }
if (!o.tag || allowedTags.indexOf(o.tag) === -1) { return false; }
return true;
};
// Container
var $container = $(config.container);
var containerConfig = {
'class': 'cp-dropdown-container'
};
if (config.buttonTitle) {
containerConfig.title = config.buttonTitle;
}
if (!config.container) {
$container = $('<span>', containerConfig);
}
// Button
var $button = $('<button>', {
'class': ''
}).append($('<span>', {'class': 'cp-dropdown-button-title'}).html(config.text || ""));
/*$('<span>', {
'class': 'fa fa-caret-down',
}).appendTo($button);*/
// Menu
var $innerblock = $('<div>', {'class': 'cp-dropdown-content'});
if (config.left) { $innerblock.addClass('cp-dropdown-left'); }
config.options.forEach(function (o) {
if (!isValidOption(o)) { return; }
$('<' + o.tag + '>', o.attributes || {}).html(o.content || '').appendTo($innerblock);
});
$container.append($button).append($innerblock);
var value = config.initialValue || '';
var setActive = function ($el) {
if ($el.length !== 1) { return; }
$innerblock.find('.cp-dropdown-element-active').removeClass('cp-dropdown-element-active');
$el.addClass('cp-dropdown-element-active');
var scroll = $el.position().top + $innerblock.scrollTop();
if (scroll < $innerblock.scrollTop()) {
$innerblock.scrollTop(scroll);
} else if (scroll > ($innerblock.scrollTop() + 280)) {
$innerblock.scrollTop(scroll-270);
}
};
var hide = function () {
window.setTimeout(function () { $innerblock.hide(); }, 0);
};
var show = function () {
$innerblock.show();
$innerblock.find('.cp-dropdown-element-active').removeClass('cp-dropdown-element-active');
if (config.isSelect && value) {
var $val = $innerblock.find('[data-value="'+value+'"]');
setActive($val);
$innerblock.scrollTop($val.position().top + $innerblock.scrollTop());
}
if (config.feedback) { Cryptpad.feedback(config.feedback); }
};
$container.click(function (e) {
e.stopPropagation();
var state = $innerblock.is(':visible');
$('.cp-dropdown-content').hide();
try {
$('iframe').each(function (idx, ifrw) {
$(ifrw).contents().find('.cp-dropdown-content').hide();
});
} catch (er) {
// empty try catch in case this iframe is problematic (cross-origin)
}
if (state) {
hide();
return;
}
show();
});
if (config.isSelect) {
var pressed = '';
var to;
$container.keydown(function (e) {
var $value = $innerblock.find('[data-value].cp-dropdown-element-active');
if (e.which === 38) { // Up
if ($value.length) {
var $prev = $value.prev();
setActive($prev);
}
}
if (e.which === 40) { // Down
if ($value.length) {
var $next = $value.next();
setActive($next);
}
}
if (e.which === 13) { //Enter
if ($value.length) {
$value.click();
hide();
}
}
if (e.which === 27) { // Esc
hide();
}
});
$container.keypress(function (e) {
window.clearTimeout(to);
var c = String.fromCharCode(e.which);
pressed += c;
var $value = $innerblock.find('[data-value^="'+pressed+'"]:first');
if ($value.length) {
setActive($value);
$innerblock.scrollTop($value.position().top + $innerblock.scrollTop());
}
to = window.setTimeout(function () {
pressed = '';
}, 1000);
});
$container.setValue = function (val, name) {
value = val;
var $val = $innerblock.find('[data-value="'+val+'"]');
var textValue = name || $val.html() || val;
$button.find('.cp-dropdown-button-title').html(textValue);
};
$container.getValue = function () {
return value || '';
};
}
return $container;
};
UIElements.createUserAdminMenu = function (Common, config) {
var metadataMgr = Common.getMetadataMgr(); var metadataMgr = Common.getMetadataMgr();
var displayNameCls = config.displayNameCls || 'displayName'; var displayNameCls = config.displayNameCls || 'displayName';
@ -419,7 +589,7 @@ define([
if (config.displayNameCls) { if (config.displayNameCls) {
var $userAdminContent = $('<p>'); var $userAdminContent = $('<p>');
if (accountName) { if (accountName) {
var $userAccount = $('<span>', {'class': 'userAccount'}).append(Messages.user_accountName + ': ' + Cryptpad.fixHTML(accountName)); var $userAccount = $('<span>', {'class': 'userAccount'}).append(Messages.user_accountName + ': ' + Util.fixHTML(accountName));
$userAdminContent.append($userAccount); $userAdminContent.append($userAccount);
$userAdminContent.append($('<br>')); $userAdminContent.append($('<br>'));
} }
@ -505,7 +675,7 @@ define([
container: config.$initBlock, // optional container: config.$initBlock, // optional
feedback: "USER_ADMIN", feedback: "USER_ADMIN",
}; };
var $userAdmin = Cryptpad.createDropdown(dropdownConfigUser); var $userAdmin = UIElements.createDropdown(dropdownConfigUser);
var $displayName = $userAdmin.find('.'+displayNameCls); var $displayName = $userAdmin.find('.'+displayNameCls);
@ -528,7 +698,7 @@ define([
$displayName.text(newName || Messages.anonymous); $displayName.text(newName || Messages.anonymous);
if (accountName && oldUrl !== url) { if (accountName && oldUrl !== url) {
$avatar.html(''); $avatar.html('');
UI.displayAvatar(Common, $avatar, url, newName || Messages.anonymous, function ($img) { UIElements.displayAvatar(Common, $avatar, url, newName || Messages.anonymous, function ($img) {
oldUrl = url; oldUrl = url;
if ($img) { if ($img) {
$userAdmin.find('button').addClass('cp-avatar'); $userAdmin.find('button').addClass('cp-avatar');
@ -577,7 +747,7 @@ define([
// Provide $container if you want to put the generated block in another element // Provide $container if you want to put the generated block in another element
// Provide $initBlock if you already have the menu block and you want the content inserted in it // Provide $initBlock if you already have the menu block and you want the content inserted in it
UI.createLanguageSelector = function (common, $container, $initBlock) { UIElements.createLanguageSelector = function (common, $container, $initBlock) {
var options = []; var options = [];
var languages = Messages._languages; var languages = Messages._languages;
var keys = Object.keys(languages).sort(); var keys = Object.keys(languages).sort();
@ -599,7 +769,7 @@ define([
container: $initBlock, // optional container: $initBlock, // optional
isSelect: true isSelect: true
}; };
var $block = Cryptpad.createDropdown(dropdownConfig); var $block = UIElements.createDropdown(dropdownConfig);
$block.attr('id', 'cp-language-selector'); $block.attr('id', 'cp-language-selector');
if ($container) { if ($container) {
@ -612,19 +782,19 @@ define([
}; };
UI.initFilePicker = function (common, cfg) { UIElements.initFilePicker = function (common, cfg) {
var onSelect = cfg.onSelect || $.noop; var onSelect = cfg.onSelect || $.noop;
var sframeChan = common.getSframeChannel(); var sframeChan = common.getSframeChannel();
sframeChan.on("EV_FILE_PICKED", function (data) { sframeChan.on("EV_FILE_PICKED", function (data) {
onSelect(data); onSelect(data);
}); });
}; };
UI.openFilePicker = function (common, types) { UIElements.openFilePicker = function (common, types) {
var sframeChan = common.getSframeChannel(); var sframeChan = common.getSframeChannel();
sframeChan.event("EV_FILE_PICKER_OPEN", types); sframeChan.event("EV_FILE_PICKER_OPEN", types);
}; };
UI.openTemplatePicker = function (common) { UIElements.openTemplatePicker = function (common) {
var metadataMgr = common.getMetadataMgr(); var metadataMgr = common.getMetadataMgr();
var type = metadataMgr.getMetadataLazy().type; var type = metadataMgr.getMetadataLazy().type;
var sframeChan = common.getSframeChannel(); var sframeChan = common.getSframeChannel();
@ -664,7 +834,7 @@ define([
if (data) { if (data) {
common.openFilePicker(pickerCfg); common.openFilePicker(pickerCfg);
focus = document.activeElement; focus = document.activeElement;
Cryptpad.confirm(Messages.useTemplate, onConfirm, { UI.confirm(Messages.useTemplate, onConfirm, {
ok: Messages.useTemplateOK, ok: Messages.useTemplateOK,
cancel: Messages.useTemplateCancel, cancel: Messages.useTemplateCancel,
}); });
@ -672,7 +842,7 @@ define([
}); });
}; };
UI.addTooltips = function () { UIElements.addTooltips = function () {
var MutationObserver = window.MutationObserver; var MutationObserver = window.MutationObserver;
var delay = typeof(AppConfig.tooltipDelay) === "number" ? AppConfig.tooltipDelay : 500; var delay = typeof(AppConfig.tooltipDelay) === "number" ? AppConfig.tooltipDelay : 500;
var addTippy = function (i, el) { var addTippy = function (i, el) {
@ -725,5 +895,5 @@ define([
}); });
}; };
return UI; return UIElements;
}); });

@ -59,14 +59,14 @@ define([
var anon_rpc; var anon_rpc;
// import UI elements // import UI elements
common.findCancelButton = UI.findCancelButton; //common.findCancelButton = UI.findCancelButton; REFACTOR
common.findOKButton = UI.findOKButton; //common.findOKButton = UI.findOKButton;
common.listenForKeys = UI.listenForKeys; //common.listenForKeys = UI.listenForKeys;
common.stopListening = UI.stopListening; //common.stopListening = UI.stopListening;
common.prompt = UI.prompt; //common.prompt = UI.prompt;
common.confirm = UI.confirm; //common.confirm = UI.confirm;
common.alert = UI.alert; //common.alert = UI.alert;
common.log = UI.log; //common.log = UI.log;
common.warn = UI.warn; common.warn = UI.warn;
common.spinner = UI.spinner; common.spinner = UI.spinner;
common.addLoadingScreen = UI.addLoadingScreen; common.addLoadingScreen = UI.addLoadingScreen;
@ -83,7 +83,6 @@ define([
// import common utilities for export // import common utilities for export
common.find = Util.find; common.find = Util.find;
var fixHTML = common.fixHTML = Util.fixHTML;
common.hexToBase64 = Util.hexToBase64; common.hexToBase64 = Util.hexToBase64;
common.base64ToHex = Util.base64ToHex; common.base64ToHex = Util.base64ToHex;
var deduplicateString = common.deduplicateString = Util.deduplicateString; var deduplicateString = common.deduplicateString = Util.deduplicateString;
@ -168,14 +167,6 @@ define([
common.setLanguage = function (l, cb) { common.setLanguage = function (l, cb) {
Language.setLanguage(l, null, cb); Language.setLanguage(l, null, cb);
}; };
common.getUserlist = function () {
if (store) {
if (store.getProxy() && store.getProxy().info) {
return store.getProxy().info.userList;
}
}
return;
};
common.getProfileUrl = function () { common.getProfileUrl = function () {
if (store && store.getProfile()) { if (store && store.getProfile()) {
return store.getProfile().view; return store.getProfile().view;
@ -642,7 +633,7 @@ define([
var $content = $('<div>'); var $content = $('<div>');
$('<b>').text(Messages.selectTemplate).appendTo($content); $('<b>').text(Messages.selectTemplate).appendTo($content);
$('<p>', {id:"selectTemplate"}).appendTo($content); $('<p>', {id:"selectTemplate"}).appendTo($content);
common.alert($content.html(), null, true); UI.alert($content.html(), null, true);
var $p = $('#selectTemplate'); var $p = $('#selectTemplate');
temps.forEach(function (t, i) { temps.forEach(function (t, i) {
$('<a>', {href: t.href, title: t.title}).text(t.title).click(function (e) { $('<a>', {href: t.href, title: t.title}).text(t.title).click(function (e) {
@ -654,7 +645,7 @@ define([
if (err) { throw new Error(err); } if (err) { throw new Error(err); }
var p = parsePadUrl(window.location.href); var p = parsePadUrl(window.location.href);
Crypt.put(p.hash, val, function () { Crypt.put(p.hash, val, function () {
common.findOKButton().click(); UI.findOKButton().click();
common.removeLoadingScreen(); common.removeLoadingScreen();
common.feedback('TEMPLATE_USED'); common.feedback('TEMPLATE_USED');
}); });
@ -662,7 +653,7 @@ define([
}).appendTo($p); }).appendTo($p);
if (i !== temps.length) { $('<br>').appendTo($p); } if (i !== temps.length) { $('<br>').appendTo($p); }
}); });
common.findOKButton().text(Messages.cancelButton); UI.findOKButton().text(Messages.cancelButton);
}; };
// Secure iframes // Secure iframes
common.useTemplate = function (href, Crypt, cb) { common.useTemplate = function (href, Crypt, cb) {
@ -791,7 +782,7 @@ define([
getStore().pushData(data, function (e, id) { getStore().pushData(data, function (e, id) {
if (e) { if (e) {
if (e === 'E_OVER_LIMIT') { if (e === 'E_OVER_LIMIT') {
common.alert(Messages.pinLimitNotPinned, null, true); UI.alert(Messages.pinLimitNotPinned, null, true);
} }
return void cb(e); return void cb(e);
} }
@ -1239,26 +1230,6 @@ define([
}); });
}; };
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 = common.getFirstEmojiOrCharacter = function (str) {
if (!str || !str.trim()) { return '?'; }
var emojis = emojiStringToArray(str);
return isEmoji(emojis[0])? emojis[0]: str[0];
};
common.getMediatagScript = function () { common.getMediatagScript = function () {
var origin = window.location.origin; var origin = window.location.origin;
@ -1311,7 +1282,7 @@ define([
.html(function () { .html(function () {
var text = Messages.download_mt_button + '<br>'; var text = Messages.download_mt_button + '<br>';
if (title) { if (title) {
text += '<b>' + common.fixHTML(title) + '</b><br>'; text += '<b>' + Util.fixHTML(title) + '</b><br>';
} }
if (size) { if (size) {
text += '<em>' + Messages._getKey('formattedMB', [sizeMb]) + '</em>'; text += '<em>' + Messages._getKey('formattedMB', [sizeMb]) + '</em>';
@ -1427,157 +1398,6 @@ define([
// Create a button with a dropdown menu
// input is a config object with parameters:
// - container (optional): the dropdown container (span)
// - text (optional): the button text value
// - options: array of {tag: "", attributes: {}, content: "string"}
//
// allowed options tags: ['a', 'hr', 'p']
var createDropdown = common.createDropdown = function (config) {
if (typeof config !== "object" || !Array.isArray(config.options)) { return; }
var allowedTags = ['a', 'p', 'hr'];
var isValidOption = function (o) {
if (typeof o !== "object") { return false; }
if (!o.tag || allowedTags.indexOf(o.tag) === -1) { return false; }
return true;
};
// Container
var $container = $(config.container);
var containerConfig = {
'class': 'cp-dropdown-container'
};
if (config.buttonTitle) {
containerConfig.title = config.buttonTitle;
}
if (!config.container) {
$container = $('<span>', containerConfig);
}
// Button
var $button = $('<button>', {
'class': ''
}).append($('<span>', {'class': 'cp-dropdown-button-title'}).html(config.text || ""));
/*$('<span>', {
'class': 'fa fa-caret-down',
}).appendTo($button);*/
// Menu
var $innerblock = $('<div>', {'class': 'cp-dropdown-content'});
if (config.left) { $innerblock.addClass('cp-dropdown-left'); }
config.options.forEach(function (o) {
if (!isValidOption(o)) { return; }
$('<' + o.tag + '>', o.attributes || {}).html(o.content || '').appendTo($innerblock);
});
$container.append($button).append($innerblock);
var value = config.initialValue || '';
var setActive = function ($el) {
if ($el.length !== 1) { return; }
$innerblock.find('.cp-dropdown-element-active').removeClass('cp-dropdown-element-active');
$el.addClass('cp-dropdown-element-active');
var scroll = $el.position().top + $innerblock.scrollTop();
if (scroll < $innerblock.scrollTop()) {
$innerblock.scrollTop(scroll);
} else if (scroll > ($innerblock.scrollTop() + 280)) {
$innerblock.scrollTop(scroll-270);
}
};
var hide = function () {
window.setTimeout(function () { $innerblock.hide(); }, 0);
};
var show = function () {
$innerblock.show();
$innerblock.find('.cp-dropdown-element-active').removeClass('cp-dropdown-element-active');
if (config.isSelect && value) {
var $val = $innerblock.find('[data-value="'+value+'"]');
setActive($val);
$innerblock.scrollTop($val.position().top + $innerblock.scrollTop());
}
if (config.feedback && store) { common.feedback(config.feedback); }
};
$container.click(function (e) {
e.stopPropagation();
var state = $innerblock.is(':visible');
$('.cp-dropdown-content').hide();
try {
$('iframe').each(function (idx, ifrw) {
$(ifrw).contents().find('.cp-dropdown-content').hide();
});
} catch (er) {
// empty try catch in case this iframe is problematic (cross-origin)
}
if (state) {
hide();
return;
}
show();
});
if (config.isSelect) {
var pressed = '';
var to;
$container.keydown(function (e) {
var $value = $innerblock.find('[data-value].cp-dropdown-element-active');
if (e.which === 38) { // Up
if ($value.length) {
var $prev = $value.prev();
setActive($prev);
}
}
if (e.which === 40) { // Down
if ($value.length) {
var $next = $value.next();
setActive($next);
}
}
if (e.which === 13) { //Enter
if ($value.length) {
$value.click();
hide();
}
}
if (e.which === 27) { // Esc
hide();
}
});
$container.keypress(function (e) {
window.clearTimeout(to);
var c = String.fromCharCode(e.which);
pressed += c;
var $value = $innerblock.find('[data-value^="'+pressed+'"]:first');
if ($value.length) {
setActive($value);
$innerblock.scrollTop($value.position().top + $innerblock.scrollTop());
}
to = window.setTimeout(function () {
pressed = '';
}, 1000);
});
$container.setValue = function (val, name) {
value = val;
var $val = $innerblock.find('[data-value="'+val+'"]');
var textValue = name || $val.html() || val;
$button.find('.cp-dropdown-button-title').html(textValue);
};
$container.getValue = function () {
return value || '';
};
}
return $container;
};
common.getShareHashes = function (secret, cb) { common.getShareHashes = function (secret, cb) {
if (!window.location.hash) { if (!window.location.hash) {
var hashes = common.getHashes(secret.channel, secret); var hashes = common.getHashes(secret.channel, secret);
@ -1623,7 +1443,7 @@ define([
(parseInt(verArr[0]) === parseInt(storedArr[0]) && (parseInt(verArr[0]) === parseInt(storedArr[0]) &&
parseInt(verArr[1]) > parseInt(storedArr[1])); parseInt(verArr[1]) > parseInt(storedArr[1]));
if (!shouldUpdate) { return; } if (!shouldUpdate) { return; }
//common.alert(Messages._getKey('newVersion', [verArr.join('.')]), null, true); //UI.alert(Messages._getKey('newVersion', [verArr.join('.')]), null, true);
localStorage[CRYPTPAD_VERSION] = ver; localStorage[CRYPTPAD_VERSION] = ver;
}; };
@ -1645,10 +1465,10 @@ define([
delete sessionStorage[newPadPathKey]; delete sessionStorage[newPadPathKey];
} }
common.onFriendRequest = function (confirmText, cb) { common.onFriendRequest = function (confirmText, cb) {
common.confirm(confirmText, cb, null, true); UI.confirm(confirmText, cb, null, true);
}; };
common.onFriendComplete = function (data) { common.onFriendComplete = function (data) {
common.log(data.logText); UI.log(data.logText);
}; };
var proxy; var proxy;

@ -4,8 +4,9 @@ define([
'/bower_components/chainpad-crypto/crypto.js?v=0.1.5', '/bower_components/chainpad-crypto/crypto.js?v=0.1.5',
'/bower_components/textpatcher/TextPatcher.amd.js', '/bower_components/textpatcher/TextPatcher.amd.js',
'/common/userObject.js', '/common/userObject.js',
'/common/common-interface.js',
'/common/migrate-user-object.js', '/common/migrate-user-object.js',
], function ($, Listmap, Crypto, TextPatcher, FO, Migrate) { ], function ($, Listmap, Crypto, TextPatcher, FO, UI, Migrate) {
/* /*
This module uses localStorage, which is synchronous, but exposes an This module uses localStorage, which is synchronous, but exposes an
asyncronous API. This is so that we can substitute other storage asyncronous API. This is so that we can substitute other storage
@ -361,7 +362,7 @@ define([
if (path[0] === 'drive' && path[1] === "migrate" && value === 1) { if (path[0] === 'drive' && path[1] === "migrate" && value === 1) {
rt.network.disconnect(); rt.network.disconnect();
rt.realtime.abort(); rt.realtime.abort();
Cryptpad.alert(Cryptpad.Messages.fs_migration, null, true); UI.alert(Cryptpad.Messages.fs_migration, null, true);
} }
}); });
}; };

@ -10,6 +10,7 @@ define([
'/common/sframe-common.js', '/common/sframe-common.js',
'/customize/messages.js', '/customize/messages.js',
'/common/common-util.js', '/common/common-util.js',
'/common/common-interface.js',
'/common/common-thumbnail.js', '/common/common-thumbnail.js',
'/customize/application_config.js', '/customize/application_config.js',
@ -28,6 +29,7 @@ define([
SFCommon, SFCommon,
Messages, Messages,
Util, Util,
UI,
Thumb, Thumb,
AppConfig) AppConfig)
{ {
@ -287,9 +289,9 @@ define([
var onConnectionChange = function (info) { var onConnectionChange = function (info) {
stateChange(info.state ? STATE.INITIALIZING : STATE.DISCONNECTED); stateChange(info.state ? STATE.INITIALIZING : STATE.DISCONNECTED);
if (info.state) { if (info.state) {
Cryptpad.findOKButton().click(); UI.findOKButton().click();
} else { } else {
Cryptpad.alert(Messages.common_connectionLost, undefined, true); UI.alert(Messages.common_connectionLost, undefined, true);
} }
}; };
@ -297,7 +299,7 @@ define([
var $export = common.createButton('export', true, {}, function () { var $export = common.createButton('export', true, {}, function () {
var ext = (typeof(extension) === 'function') ? extension() : extension; var ext = (typeof(extension) === 'function') ? extension() : extension;
var suggestion = title.suggestTitle('cryptpad-document'); var suggestion = title.suggestTitle('cryptpad-document');
Cryptpad.prompt(Messages.exportPrompt, UI.prompt(Messages.exportPrompt,
Cryptpad.fixFileName(suggestion) + '.' + ext, function (filename) Cryptpad.fixFileName(suggestion) + '.' + ext, function (filename)
{ {
if (!(typeof(filename) === 'string' && filename)) { return; } if (!(typeof(filename) === 'string' && filename)) { return; }
@ -426,13 +428,13 @@ define([
if (infiniteSpinnerModal) { return; } if (infiniteSpinnerModal) { return; }
infiniteSpinnerModal = true; infiniteSpinnerModal = true;
stateChange(STATE.INFINITE_SPINNER); stateChange(STATE.INFINITE_SPINNER);
Cryptpad.confirm(Messages.realtime_unrecoverableError, function (yes) { UI.confirm(Messages.realtime_unrecoverableError, function (yes) {
if (!yes) { return; } if (!yes) { return; }
common.gotoURL(); common.gotoURL();
}); });
cpNfInner.chainpad.onSettle(function () { cpNfInner.chainpad.onSettle(function () {
infiniteSpinnerModal = false; infiniteSpinnerModal = false;
Cryptpad.findCancelButton().click(); UI.findCancelButton().click();
stateChange(STATE.READY); stateChange(STATE.READY);
onRemote(); onRemote();
}); });

@ -2,9 +2,12 @@ define([
'jquery', 'jquery',
'/common/modes.js', '/common/modes.js',
'/common/themes.js', '/common/themes.js',
'/common/cryptpad-common.js', '/customize/messages.js',
'/common/common-ui-elements.js',
'/common/common-hash.js',
'/common/common-util.js',
'/bower_components/textpatcher/TextPatcher.js', '/bower_components/textpatcher/TextPatcher.js',
], function ($, Modes, Themes, Cryptpad, TextPatcher) { ], function ($, Modes, Themes, Messages, UIElements, Hash, Util, TextPatcher) {
var module = {}; var module = {};
var cursorToPos = function(cursor, oldText) { var cursorToPos = function(cursor, oldText) {
@ -101,7 +104,6 @@ define([
module.create = function (Common, defaultMode, CMeditor) { module.create = function (Common, defaultMode, CMeditor) {
var exp = {}; var exp = {};
var Messages = Cryptpad.Messages;
var CodeMirror = exp.CodeMirror = CMeditor; var CodeMirror = exp.CodeMirror = CMeditor;
CodeMirror.modeURL = "cm/mode/%N/%N"; CodeMirror.modeURL = "cm/mode/%N/%N";
@ -211,7 +213,7 @@ define([
isSelect: true, isSelect: true,
feedback: 'CODE_LANGUAGE', feedback: 'CODE_LANGUAGE',
}; };
var $block = exp.$language = Cryptpad.createDropdown(dropdownConfig); var $block = exp.$language = UIElements.createDropdown(dropdownConfig);
$block.find('button').attr('title', Messages.languageButtonTitle); $block.find('button').attr('title', Messages.languageButtonTitle);
$block.find('a').click(function () { $block.find('a').click(function () {
setMode($(this).attr('data-value'), onModeChanged); setMode($(this).attr('data-value'), onModeChanged);
@ -248,7 +250,7 @@ define([
initialValue: lastTheme, initialValue: lastTheme,
feedback: 'CODE_THEME', feedback: 'CODE_THEME',
}; };
var $block = exp.$theme = Cryptpad.createDropdown(dropdownConfig); var $block = exp.$theme = UIElements.createDropdown(dropdownConfig);
$block.find('button').attr('title', Messages.themeButtonTitle); $block.find('button').attr('title', Messages.themeButtonTitle);
setTheme(lastTheme, $block); setTheme(lastTheme, $block);
@ -324,8 +326,8 @@ define([
//var cursor = editor.getCursor(); //var cursor = editor.getCursor();
//var cleanName = data.name.replace(/[\[\]]/g, ''); //var cleanName = data.name.replace(/[\[\]]/g, '');
//var text = '!['+cleanName+']('+data.url+')'; //var text = '!['+cleanName+']('+data.url+')';
var parsed = Cryptpad.parsePadUrl(data.url); var parsed = Hash.parsePadUrl(data.url);
var hexFileName = Cryptpad.base64ToHex(parsed.hashData.channel); var hexFileName = Util.base64ToHex(parsed.hashData.channel);
var src = '/blob/' + hexFileName.slice(0,2) + '/' + hexFileName; var src = '/blob/' + hexFileName.slice(0,2) + '/' + hexFileName;
var mt = '<media-tag src="' + src + '" data-crypto-key="cryptpad:' + var mt = '<media-tag src="' + src + '" data-crypto-key="cryptpad:' +
parsed.hashData.key + '"></media-tag>'; parsed.hashData.key + '"></media-tag>';

@ -2,8 +2,10 @@ define([
'jquery', 'jquery',
'/file/file-crypto.js', '/file/file-crypto.js',
'/common/common-thumbnail.js', '/common/common-thumbnail.js',
'/common/common-interface.js',
'/bower_components/tweetnacl/nacl-fast.min.js', '/bower_components/tweetnacl/nacl-fast.min.js',
], function ($, FileCrypto, Thumb) { ], function ($, FileCrypto, Thumb, UI) {
var Nacl = window.nacl; var Nacl = window.nacl;
var module = {}; var module = {};
@ -123,7 +125,7 @@ define([
window.open(origin + $link.attr('href'), '_blank'); window.open(origin + $link.attr('href'), '_blank');
}); });
var title = metadata.name; var title = metadata.name;
Cryptpad.log(Messages._getKey('upload_success', [title])); UI.log(Messages._getKey('upload_success', [title]));
common.prepareFeedback('upload')(); common.prepareFeedback('upload')();
if (config.onUploaded) { if (config.onUploaded) {
@ -140,18 +142,18 @@ define([
queue.next(); queue.next();
if (e === 'TOO_LARGE') { if (e === 'TOO_LARGE') {
// TODO update table to say too big? // TODO update table to say too big?
return void Cryptpad.alert(Messages.upload_tooLarge); return void UI.alert(Messages.upload_tooLarge);
} }
if (e === 'NOT_ENOUGH_SPACE') { if (e === 'NOT_ENOUGH_SPACE') {
// TODO update table to say not enough space? // TODO update table to say not enough space?
return void Cryptpad.alert(Messages.upload_notEnoughSpace); return void UI.alert(Messages.upload_notEnoughSpace);
} }
console.error(e); console.error(e);
return void Cryptpad.alert(Messages.upload_serverError); return void UI.alert(Messages.upload_serverError);
}; };
onPending = function (cb) { onPending = function (cb) {
Cryptpad.confirm(Messages.upload_uploadPending, cb); UI.confirm(Messages.upload_uploadPending, cb);
}; };
file.noStore = config.noStore; file.noStore = config.noStore;
@ -161,7 +163,7 @@ define([
console.log('Upload started...'); console.log('Upload started...');
}); });
} catch (e) { } catch (e) {
Cryptpad.alert(Messages.upload_serverError); UI.alert(Messages.upload_serverError);
} }
}; };
@ -260,7 +262,7 @@ define([
var onFileDrop = File.onFileDrop = function (file, e) { var onFileDrop = File.onFileDrop = function (file, e) {
if (!common.isLoggedIn()) { if (!common.isLoggedIn()) {
return Cryptpad.alert(common.Messages.upload_mustLogin); return UI.alert(common.Messages.upload_mustLogin);
} }
Array.prototype.slice.call(file).forEach(function (d) { Array.prototype.slice.call(file).forEach(function (d) {

@ -1,8 +1,10 @@
define([ define([
'jquery', 'jquery',
'/common/common-interface.js',
'/bower_components/chainpad-json-validator/json-ot.js', '/bower_components/chainpad-json-validator/json-ot.js',
'/bower_components/chainpad/chainpad.dist.js', '/bower_components/chainpad/chainpad.dist.js',
], function ($, JsonOT) { ], function ($, UI, JsonOT) {
var ChainPad = window.ChainPad; var ChainPad = window.ChainPad;
var History = {}; var History = {};
@ -203,11 +205,11 @@ define([
onClose(); onClose();
}); });
$rev.click(function () { $rev.click(function () {
Cryptpad.confirm(Messages.history_restorePrompt, function (yes) { UI.confirm(Messages.history_restorePrompt, function (yes) {
if (!yes) { return; } if (!yes) { return; }
close(); close();
onRevert(); onRevert();
Cryptpad.log(Messages.history_restoreDone); UI.log(Messages.history_restoreDone);
}); });
}); });

@ -16,6 +16,7 @@ define([
'/common/common-realtime.js', '/common/common-realtime.js',
'/common/common-util.js', '/common/common-util.js',
'/common/common-thumbnail.js', '/common/common-thumbnail.js',
'/common/common-interface.js',
'/bower_components/localforage/dist/localforage.min.js' '/bower_components/localforage/dist/localforage.min.js'
], function ( ], function (
$, $,
@ -24,7 +25,7 @@ define([
CpNfInner, CpNfInner,
SFrameChannel, SFrameChannel,
Title, Title,
UI, UIElements,
History, History,
File, File,
CodeMirror, CodeMirror,
@ -34,6 +35,7 @@ define([
CommonRealtime, CommonRealtime,
Util, Util,
Thumb, Thumb,
UI,
localForage localForage
) { ) {
// Chainpad Netflux Inner // Chainpad Netflux Inner
@ -74,16 +76,16 @@ define([
}; };
// UI // UI
funcs.createUserAdminMenu = callWithCommon(UI.createUserAdminMenu); funcs.createUserAdminMenu = callWithCommon(UIElements.createUserAdminMenu);
funcs.initFilePicker = callWithCommon(UI.initFilePicker); funcs.initFilePicker = callWithCommon(UIElements.initFilePicker);
funcs.openFilePicker = callWithCommon(UI.openFilePicker); funcs.openFilePicker = callWithCommon(UIElements.openFilePicker);
funcs.openTemplatePicker = callWithCommon(UI.openTemplatePicker); funcs.openTemplatePicker = callWithCommon(UIElements.openTemplatePicker);
funcs.displayMediatagImage = callWithCommon(UI.displayMediatagImage); funcs.displayMediatagImage = callWithCommon(UIElements.displayMediatagImage);
funcs.displayAvatar = callWithCommon(UI.displayAvatar); funcs.displayAvatar = callWithCommon(UIElements.displayAvatar);
funcs.createButton = callWithCommon(UI.createButton); funcs.createButton = callWithCommon(UIElements.createButton);
funcs.createUsageBar = callWithCommon(UI.createUsageBar); funcs.createUsageBar = callWithCommon(UIElements.createUsageBar);
funcs.updateTags = callWithCommon(UI.updateTags); funcs.updateTags = callWithCommon(UIElements.updateTags);
funcs.createLanguageSelector = callWithCommon(UI.createLanguageSelector); funcs.createLanguageSelector = callWithCommon(UIElements.createLanguageSelector);
// Thumb // Thumb
funcs.displayThumbnail = callWithCommon(Thumb.displayThumbnail); funcs.displayThumbnail = callWithCommon(Thumb.displayThumbnail);
@ -357,19 +359,19 @@ define([
}; };
}); });
UI.addTooltips(); UIElements.addTooltips();
ctx.sframeChan.on('EV_RT_CONNECT', function () { CommonRealtime.setConnectionState(true); }); ctx.sframeChan.on('EV_RT_CONNECT', function () { CommonRealtime.setConnectionState(true); });
ctx.sframeChan.on('EV_RT_DISCONNECT', function () { CommonRealtime.setConnectionState(false); }); ctx.sframeChan.on('EV_RT_DISCONNECT', function () { CommonRealtime.setConnectionState(false); });
ctx.sframeChan.on('Q_INCOMING_FRIEND_REQUEST', function (confirmMsg, cb) { ctx.sframeChan.on('Q_INCOMING_FRIEND_REQUEST', function (confirmMsg, cb) {
Cryptpad.confirm(confirmMsg, cb, null, true); UI.confirm(confirmMsg, cb, null, true);
}); });
ctx.sframeChan.on('EV_FRIEND_REQUEST', function (data) { ctx.sframeChan.on('EV_FRIEND_REQUEST', function (data) {
var i = pendingFriends.indexOf(data.netfluxId); var i = pendingFriends.indexOf(data.netfluxId);
if (i !== -1) { pendingFriends.splice(i, 1); } if (i !== -1) { pendingFriends.splice(i, 1); }
Cryptpad.log(data.logText); UI.log(data.logText);
}); });
ctx.sframeChan.ready(); ctx.sframeChan.ready();

@ -1,865 +0,0 @@
define([
'jquery',
'/customize/application_config.js',
'/api/config'
], function ($, Config, ApiConfig) {
var urlArgs = ApiConfig.requireConf.urlArgs;
var Messages = {};
var Bar = {
constants: {},
};
/** Id of the div containing the user list. */
var USER_LIST_CLS = Bar.constants.userlist = 'cryptpad-user-list';
/** Id of the div containing the lag info. */
var LAG_ELEM_CLS = Bar.constants.lag = 'cryptpad-lag';
var LIMIT_ELEM_CLS = Bar.constants.lag = 'cryptpad-limit';
/** The toolbar class which contains the user list, debug link and lag. */
var TOOLBAR_CLS = Bar.constants.toolbar = 'cryptpad-toolbar';
var TOP_CLS = Bar.constants.top = 'cryptpad-toolbar-top';
var LEFTSIDE_CLS = Bar.constants.leftside = 'cryptpad-toolbar-leftside';
var RIGHTSIDE_CLS = Bar.constants.rightside = 'cryptpad-toolbar-rightside';
var HISTORY_CLS = Bar.constants.history = 'cryptpad-toolbar-history';
var SPINNER_CLS = Bar.constants.spinner = 'cryptpad-spinner';
var STATE_CLS = Bar.constants.state = 'cryptpad-state';
var USERNAME_CLS = Bar.constants.username = 'cryptpad-toolbar-username';
var READONLY_CLS = Bar.constants.readonly = 'cryptpad-readonly';
var USERBUTTONS_CONTAINER_CLS = Bar.constants.userButtonsContainer = "cryptpad-userbuttons-container";
var USERLIST_CLS = Bar.constants.userlist = "cryptpad-dropdown-users";
var EDITSHARE_CLS = Bar.constants.editShare = "cryptpad-dropdown-editShare";
var VIEWSHARE_CLS = Bar.constants.viewShare = "cryptpad-dropdown-viewShare";
var SHARE_CLS = Bar.constants.viewShare = "cryptpad-dropdown-share";
var DROPDOWN_CONTAINER_CLS = Bar.constants.dropdownContainer = "cryptpad-dropdown-container";
var DROPDOWN_CLS = Bar.constants.dropdown = "cryptpad-dropdown";
var TITLE_CLS = Bar.constants.title = "cryptpad-title";
var USER_CLS = Bar.constants.userAdmin = "cryptpad-user";
var USERBUTTON_CLS = Bar.constants.changeUsername = "cryptpad-change-username";
var SPINNER_DISAPPEAR_TIME = 3000;
var uid = function () {
return 'cryptpad-uid-' + String(Math.random()).substring(2);
};
var $style;
var connected = false;
var firstConnection = true;
var lagErrors = 0;
var styleToolbar = function ($container, href, version) {
href = href || '/customize/toolbar.css' + (version?('?' + version): '');
$.ajax({
url: href,
dataType: 'text',
success: function (data) {
$container.append($('<style>').text(data));
},
});
};
var createRealtimeToolbar = function ($container, config) {
var $toolbar = $('<div>', {
'class': TOOLBAR_CLS,
id: uid(),
})
.append($('<div>', {'class': TOP_CLS}))
.append($('<div>', {'class': LEFTSIDE_CLS}))
.append($('<div>', {'class': RIGHTSIDE_CLS}))
.append($('<div>', {'class': HISTORY_CLS}));
// The 'notitle' class removes the line added for the title with a small screen
if (!config || typeof config !== "object") {
$toolbar.addClass('notitle');
}
$container.prepend($toolbar);
if (ApiConfig && ApiConfig.requireConf && ApiConfig.requireConf.urlArgs) {
styleToolbar($container, undefined, ApiConfig.requireConf.urlArgs);
} else {
styleToolbar($container);
}
return $toolbar;
};
var createSpinner = function ($container, config) {
if (config.displayed.indexOf('spinner') !== -1) {
var $spin = $('<span>', {'class':SPINNER_CLS});
var $spinner = $('<span>', {
id: uid(),
'class': 'spin fa fa-spinner fa-pulse',
}).appendTo($spin).hide();
$('<span>', {
id: uid(),
'class': 'synced fa fa-check',
title: Messages.synced
}).appendTo($spin);
$container.prepend($spin);
return $spin[0];
}
};
var kickSpinner = function (Cryptpad, realtime, local, spinnerElement) {
if (!spinnerElement) { return; }
$(spinnerElement).find('.spin').show();
$(spinnerElement).find('.synced').hide();
var onSynced = function () {
if (spinnerElement.timeout) { clearTimeout(spinnerElement.timeout); }
spinnerElement.timeout = setTimeout(function () {
$(spinnerElement).find('.spin').hide();
$(spinnerElement).find('.synced').show();
}, local ? 0 : SPINNER_DISAPPEAR_TIME);
};
if (Cryptpad) {
Cryptpad.whenRealtimeSyncs(realtime, onSynced);
return;
}
onSynced();
};
var createUserButtons = function ($userlistElement, config, readOnly, Cryptpad) {
// User list button
if (config.displayed.indexOf('userlist') !== -1) {
if (!config.userData) {
throw new Error("You must provide a `userData` object to display the userlist");
}
var dropdownConfig = {
options: [{
tag: 'p',
attributes: {'class': USERLIST_CLS},
}] // Entries displayed in the menu
};
var $block = Cryptpad.createDropdown(dropdownConfig);
$block.attr('id', 'userButtons');
$userlistElement.append($block);
}
// Share button
if (config.displayed.indexOf('share') !== -1) {
var secret = Cryptpad.find(config, ['share', 'secret']);
var channel = Cryptpad.find(config, ['share', 'channel']);
if (!secret || !channel) {
throw new Error("Unable to display the share button: share.secret and share.channel required");
}
Cryptpad.getRecentPads(function (err, recent) {
var $shareIcon = $('<span>', {'class': 'fa fa-share-alt'});
var $span = $('<span>', {'class': 'large'}).append(' ' +Messages.shareButton);
var hashes = Cryptpad.getHashes(channel, secret);
var options = [];
// If we have a stronger version in drive, add it and add a redirect button
var stronger = recent && Cryptpad.findStronger(null, recent);
if (stronger) {
var parsed = Cryptpad.parsePadUrl(stronger);
hashes.editHash = parsed.hash;
}
if (hashes.editHash) {
options.push({
tag: 'a',
attributes: {title: Messages.editShareTitle, 'class': 'editShare'},
content: '<span class="fa fa-users"></span> ' + Messages.editShare
});
if (stronger) {
// We're in view mode, display the "open editing link" button
options.push({
tag: 'a',
attributes: {
title: Messages.editOpenTitle,
'class': 'editOpen',
href: window.location.pathname + '#' + hashes.editHash,
target: '_blank'
},
content: '<span class="fa fa-users"></span> ' + Messages.editOpen
});
}
options.push({tag: 'hr'});
}
if (hashes.viewHash) {
options.push({
tag: 'a',
attributes: {title: Messages.viewShareTitle, 'class': 'viewShare'},
content: '<span class="fa fa-eye"></span> ' + Messages.viewShare
});
if (hashes.editHash && !stronger) {
// We're in edit mode, display the "open readonly" button
options.push({
tag: 'a',
attributes: {
title: Messages.viewOpenTitle,
'class': 'viewOpen',
href: window.location.pathname + '#' + hashes.viewHash,
target: '_blank'
},
content: '<span class="fa fa-eye"></span> ' + Messages.viewOpen
});
}
}
if (hashes.fileHash) {
options.push({
tag: 'a',
attributes: {title: Messages.viewShareTitle, 'class': 'fileShare'},
content: '<span class="fa fa-eye"></span> ' + Messages.viewShare
});
}
var dropdownConfigShare = {
text: $('<div>').append($shareIcon).append($span).html(),
options: options
};
var $shareBlock = Cryptpad.createDropdown(dropdownConfigShare);
$shareBlock.find('button').attr('id', 'shareButton');
$shareBlock.find('.dropdown-bar-content').addClass(SHARE_CLS).addClass(EDITSHARE_CLS).addClass(VIEWSHARE_CLS);
$userlistElement.append($shareBlock);
if (hashes.editHash) {
$shareBlock.find('a.editShare').click(function () {
var url = window.location.origin + window.location.pathname + '#' + hashes.editHash;
var success = Cryptpad.Clipboard.copy(url);
if (success) { Cryptpad.log(Messages.shareSuccess); }
});
}
if (hashes.viewHash) {
$shareBlock.find('a.viewShare').click(function () {
var url = window.location.origin + window.location.pathname + '#' + hashes.viewHash ;
var success = Cryptpad.Clipboard.copy(url);
if (success) { Cryptpad.log(Messages.shareSuccess); }
});
}
if (hashes.fileHash) {
$shareBlock.find('a.fileShare').click(function () {
var url = window.location.origin + window.location.pathname + '#' + hashes.fileHash ;
var success = Cryptpad.Clipboard.copy(url);
if (success) { Cryptpad.log(Messages.shareSuccess); }
});
}
});
}
};
var createUserList = function ($container, config, readOnly, Cryptpad) {
if (config.displayed.indexOf('userlist') === -1 && config.displayed.indexOf('share') === -1) { return; }
var $userlist = $('<div>', {
'class': USER_LIST_CLS,
id: uid(),
});
createUserButtons($userlist, config, readOnly, Cryptpad);
$container.append($userlist);
return $userlist[0];
};
var getOtherUsers = function(myUserName, userList, userData) {
var i = 0; // duplicates counter
var list = [];
var myUid = userData[myUserName] ? userData[myUserName].uid : undefined;
var uids = [];
userList.forEach(function(user) {
if(user !== myUserName) {
var data = (userData) ? (userData[user] || null) : null;
var userName = (data) ? data.name : null;
var userId = (data) ? data.uid : null;
if (userName && uids.indexOf(userId) === -1 && (!myUid || userId !== myUid)) {
uids.push(userId);
list.push(userName);
} else { i++; }
}
});
return {
list: list,
duplicates: i
};
};
var arrayIntersect = function(a, b) {
return $.grep(a, function(i) {
return $.inArray(i, b) > -1;
});
};
var getViewers = function (n) {
if (!n || !parseInt(n) || n === 0) { return ''; }
if (n === 1) { return '; + ' + Messages.oneViewer; }
return '; + ' + Messages._getKey('viewers', [n]);
};
var checkSynchronizing = function (userList, myUserName, $stateElement) {
var meIdx = userList.indexOf(myUserName);
if (meIdx === -1) {
$stateElement.text(Messages.synchronizing);
return;
}
$stateElement.text('');
};
var updateUserList = function (config, myUserName, userlistElement, userList, userData, readOnly, $userAdminElement) {
// Make sure the elements are displayed
var $userButtons = $(userlistElement).find("#userButtons");
$userButtons.attr('display', 'inline');
if (config.displayed.indexOf('userlist') !== -1) {
var numberOfUsers = userList.length;
// If we are using old pads (readonly unavailable), only editing users are in userList.
// With new pads, we also have readonly users in userList, so we have to intersect with
// the userData to have only the editing users. We can't use userData directly since it
// may contain data about users that have already left the channel.
userList = readOnly === -1 ? userList : arrayIntersect(userList, Object.keys(userData));
// Names of editing users
var others = getOtherUsers(myUserName, userList, userData);
var editUsersNames = others.list;
var duplicates = others.duplicates;
var numberOfEditUsers = userList.length - duplicates;
var numberOfViewUsers = numberOfUsers - numberOfEditUsers - duplicates;
// Number of anonymous editing users
var anonymous = numberOfEditUsers - editUsersNames.length;
// Update the userlist
var $usersTitle = $('<h2>').text(Messages.users);
var $editUsers = $userButtons.find('.' + USERLIST_CLS);
$editUsers.html('').append($usersTitle);
var $editUsersList = $('<pre>');
if (readOnly !== 1) { // Yourself - edit
$editUsers.append('<span class="yourself">' + Messages.yourself + '</span>');
anonymous--;
}
// Editors
$editUsersList.text(editUsersNames.join('\n')); // .text() to avoid XSS
$editUsers.append($editUsersList);
if (anonymous > 0) { // Anonymous editors
var text = anonymous === 1 ? Messages.anonymousUser : Messages.anonymousUsers;
$editUsers.append('<span class="anonymous">' + anonymous + ' ' + text + '</span>');
}
if (numberOfViewUsers > 0) { // Viewers
var viewText = '<span class="viewer">';
if (numberOfEditUsers > 0) {
$editUsers.append('<br>');
viewText += Messages.and + ' ';
}
var viewerText = numberOfViewUsers !== 1 ? Messages.viewers : Messages.viewer;
viewText += numberOfViewUsers + ' ' + viewerText + '</span>';
$editUsers.append(viewText);
}
// Update the buttons
var fa_editusers = '<span class="fa fa-users"></span>';
var fa_viewusers = '<span class="fa fa-eye"></span>';
var viewersText = numberOfViewUsers !== 1 ? Messages.viewers : Messages.viewer;
var editorsText = numberOfEditUsers !== 1 ? Messages.editors : Messages.editor;
var $span = $('<span>', {'class': 'large'}).html(fa_editusers + ' ' + numberOfEditUsers + ' ' + editorsText + '&nbsp;&nbsp; ' + fa_viewusers + ' ' + numberOfViewUsers + ' ' + viewersText);
var $spansmall = $('<span>', {'class': 'narrow'}).html(fa_editusers + ' ' + numberOfEditUsers + '&nbsp;&nbsp; ' + fa_viewusers + ' ' + numberOfViewUsers);
$userButtons.find('.buttonTitle').html('').append($span).append($spansmall);
}
if (config.displayed.indexOf('useradmin') !== -1) {
// Change username in useradmin dropdown
var $userElement = $userAdminElement.find('.' + USERNAME_CLS);
$userElement.show();
if (readOnly === 1) {
$userElement.addClass(READONLY_CLS).text(Messages.readonly);
}
else {
var name = userData[myUserName] && userData[myUserName].name;
if (!name) {
name = Messages.anonymous;
}
$userElement.removeClass(READONLY_CLS).text(name);
}
}
};
var createLagElement = function () {
var $lag = $('<span>', {
'class': LAG_ELEM_CLS,
id: uid(),
});
var $a = $('<span>', {'class': 'cryptpad-lag', id: 'newLag'});
$('<span>', {'class': 'bar1'}).appendTo($a);
$('<span>', {'class': 'bar2'}).appendTo($a);
$('<span>', {'class': 'bar3'}).appendTo($a);
$('<span>', {'class': 'bar4'}).appendTo($a);
return $a[0];
};
var checkLag = function (getLag, lagElement) {
var lag;
if(typeof getLag === "function") {
lag = getLag();
}
var lagLight = $('<div>', {
'class': 'lag'
});
var title;
var $lag = $(lagElement);
if (lag) {
$lag.attr('class', 'cryptpad-lag');
firstConnection = false;
title = Messages.lag + ' : ' + lag + ' ms\n';
if (lag > 30000) {
$lag.addClass('lag0');
title = Messages.redLight;
} else if (lag > 5000) {
$lag.addClass('lag1');
title += Messages.orangeLight;
} else if (lag > 1000) {
$lag.addClass('lag2');
title += Messages.orangeLight;
} else if (lag > 300) {
$lag.addClass('lag3');
title += Messages.greenLight;
} else {
$lag.addClass('lag4');
title += Messages.greenLight;
}
}
else if (!firstConnection) {
$lag.attr('class', 'cryptpad-lag');
// Display the red light at the 2nd failed attemp to get the lag
lagLight.addClass('lag-red');
title = Messages.redLight;
}
if (title) {
$lag.attr('title', title);
}
};
var createLinkToMain = function ($topContainer) {
var $linkContainer = $('<span>', {
'class': "cryptpad-link"
}).appendTo($topContainer);
var $imgTag = $('<img>', {
src: "/customize/cryptofist_mini.png?" + urlArgs,
alt: "Cryptpad"
});
// We need to override the "a" tag action here because it is inside the iframe!
var $aTagSmall = $('<a>', {
href: "/",
title: Messages.header_logoTitle,
'class': "cryptpad-logo"
}).append($imgTag);
var $span = $('<span>').text('CryptPad');
var $aTagBig = $aTagSmall.clone().addClass('large').append($span);
$aTagSmall.addClass('narrow');
var onClick = function (e) {
e.preventDefault();
if (e.ctrlKey) {
window.open('/');
return;
}
window.location = "/";
};
var onContext = function (e) { e.stopPropagation(); };
$aTagBig.click(onClick).contextmenu(onContext);
$aTagSmall.click(onClick).contextmenu(onContext);
$linkContainer.append($aTagSmall).append($aTagBig);
};
var createUserAdmin = function ($topContainer, config, readOnly, lagElement, Cryptpad) {
var $lag = $(lagElement);
var $userContainer = $('<span>', {
'class': USER_CLS
}).appendTo($topContainer);
if (config.displayed.indexOf('state') !== -1) {
var $state = $('<span>', {
'class': STATE_CLS
}).text(Messages.synchronizing).appendTo($userContainer);
}
if (config.displayed.indexOf('lag') !== -1) {
$userContainer.append($lag);
}
if (config.displayed.indexOf('limit') !== -1 && Config.enablePinning) {
var usage;
var $limitIcon = $('<span>', {'class': 'fa fa-exclamation-triangle'});
var $limit = $('<span>', {
'class': LIMIT_ELEM_CLS,
'title': Messages.pinLimitReached
}).append($limitIcon).hide().appendTo($userContainer);
var todo = function (e, overLimit) {
if (e) { return void console.error("Unable to get the pinned usage"); }
if (overLimit) {
var message = Messages.pinLimitReachedAlert;
if (ApiConfig.noSubscriptionButton === true) {
message = Messages.pinLimitReachedAlertNoAccounts;
}
$limit.show().click(function () {
Cryptpad.alert(message, null, true);
});
}
};
Cryptpad.isOverPinLimit(todo);
}
if (config.displayed.indexOf('newpad') !== -1) {
var pads_options = [];
Config.availablePadTypes.forEach(function (p) {
if (p === 'drive') { return; }
pads_options.push({
tag: 'a',
attributes: {
'target': '_blank',
'href': '/' + p + '/',
},
content: Messages.type[p]
});
});
var $plusIcon = $('<span>', {'class': 'fa fa-plus'});
var $newbig = $('<span>', {'class': 'big'}).append(' ' +Messages.newButton);
var $newButton = $('<div>').append($plusIcon).append($newbig);
var dropdownConfig = {
text: $newButton.html(), // Button initial text
options: pads_options, // Entries displayed in the menu
left: true, // Open to the left of the button
};
var $newPadBlock = Cryptpad.createDropdown(dropdownConfig);
$newPadBlock.find('button').attr('title', Messages.newButtonTitle);
$newPadBlock.find('button').attr('id', 'newdoc');
$newPadBlock.appendTo($userContainer);
}
// User dropdown
if (config.displayed.indexOf('useradmin') !== -1) {
var userMenuCfg = {};
if (!config.hideDisplayName) {
userMenuCfg = {
displayNameCls: USERNAME_CLS,
changeNameButtonCls: USERBUTTON_CLS,
};
}
if (readOnly !== 1) {
userMenuCfg.displayName = 1;
userMenuCfg.displayChangeName = 1;
}
var $userAdmin = Cryptpad.createUserAdminMenu(userMenuCfg);
$userAdmin.attr('id', 'userDropdown');
$userContainer.append($userAdmin);
var $userButton = $userAdmin.find('a.' + USERBUTTON_CLS);
var renameAlertOpened;
$userButton.click(function (e) {
e.preventDefault();
e.stopPropagation();
Cryptpad.getLastName(function (err, lastName) {
if (err) { return void console.error("Cannot get last name", err); }
Cryptpad.prompt(Messages.changeNamePrompt, lastName || '', function (newName) {
if (newName === null && typeof(lastName) === "string") { return; }
if (newName === null) { newName = ''; }
Cryptpad.changeDisplayName(newName);
});
});
});
Cryptpad.onDisplayNameChanged(function (newName) {
Cryptpad.findCancelButton().click();
});
}
return $userContainer;
};
var createTitle = function ($container, readOnly, config, Cryptpad) {
var $titleContainer = $('<span>', {
id: 'toolbarTitle',
'class': TITLE_CLS
}).appendTo($container);
if (!config || typeof config !== "object") { return; }
var callback = config.onRename;
var placeholder = config.defaultName;
var suggestName = config.suggestName;
// Buttons
var $text = $('<span>', {
'class': 'title'
}).appendTo($titleContainer);
var $pencilIcon = $('<span>', {
'class': 'pencilIcon',
'title': Messages.clickToEdit
});
if (readOnly === 1 || typeof(Cryptpad) === "undefined") { return $titleContainer; }
var $input = $('<input>', {
type: 'text',
placeholder: placeholder
}).appendTo($titleContainer).hide();
if (readOnly !== 1) {
$text.attr("title", Messages.clickToEdit);
$text.addClass("editable");
var $icon = $('<span>', {
'class': 'fa fa-pencil readonly',
style: 'font-family: FontAwesome;'
});
$pencilIcon.append($icon).appendTo($titleContainer);
}
// Events
$input.on('mousedown', function (e) {
if (!$input.is(":focus")) {
$input.focus();
}
e.stopPropagation();
return true;
});
$input.on('keyup', function (e) {
if (e.which === 13 && connected === true) {
var name = $input.val().trim();
if (name === "") {
name = $input.attr('placeholder');
}
Cryptpad.renamePad(name, function (err, newtitle) {
if (err) { return; }
$text.text(newtitle);
callback(null, newtitle);
$input.hide();
$text.show();
//$pencilIcon.css('display', '');
});
}
else if (e.which === 27) {
$input.hide();
$text.show();
//$pencilIcon.css('display', '');
}
});
var displayInput = function () {
if (connected === false) { return; }
$text.hide();
//$pencilIcon.css('display', 'none');
var inputVal = suggestName() || "";
$input.val(inputVal);
$input.show();
$input.focus();
};
$text.on('click', displayInput);
$pencilIcon.on('click', displayInput);
return $titleContainer;
};
var create = Bar.create = function ($container, myUserName, realtime, getLag, userList, config) {
config = config || {};
var readOnly = (typeof config.readOnly !== "undefined") ? (config.readOnly ? 1 : 0) : -1;
var Cryptpad = config.common;
Messages = Cryptpad.Messages;
config.displayed = config.displayed || [];
var toolbar = createRealtimeToolbar($container, config.title);
var userListElement = createUserList(toolbar.find('.' + LEFTSIDE_CLS), config, readOnly, Cryptpad);
var $titleElement = createTitle(toolbar.find('.' + TOP_CLS), readOnly, config.title, Cryptpad);
var $linkElement = createLinkToMain(toolbar.find('.' + TOP_CLS));
var lagElement = createLagElement();
var $userAdminElement = createUserAdmin(toolbar.find('.' + TOP_CLS), config, readOnly, lagElement, Cryptpad);
var spinner = createSpinner($userAdminElement, config);
var userData = config.userData;
// readOnly = 1 (readOnly enabled), 0 (disabled), -1 (old pad without readOnly mode)
var saveElement;
var loadElement;
var $stateElement = toolbar.find('.' + STATE_CLS);
if (config.ifrw) {
var removeDropdowns = function (e) {
$container.find('.cryptpad-dropdown').hide();
};
var cancelEditTitle = function (e) {
// Now we want to apply the title even if we click somewhere else
if ($(e.target).parents('.' + TITLE_CLS).length || !$titleElement) {
return;
}
if (!$titleElement.find('input').is(':visible')) { return; }
var ev = $.Event("keyup");
ev.which = 13;
$titleElement.find('input').trigger(ev);
/*
$titleElement.find('input').hide();
$titleElement.find('span.title').show();
$titleElement.find('span.pencilIcon').css('display', '');
*/
};
$(config.ifrw).on('click', removeDropdowns);
$(config.ifrw).on('click', cancelEditTitle);
try {
if (config.ifrw.$('iframe').length) {
var innerIfrw = config.ifrw.$('iframe').each(function (i, el) {
$(el.contentWindow).on('click', removeDropdowns);
$(el.contentWindow).on('click', cancelEditTitle);
});
}
} catch (e) {
// empty try catch in case this iframe is problematic
}
}
// Update user list
if (userList) {
if (userData) {
userList.change.push(function (newUserData) {
var users = userList.users;
if (users.indexOf(myUserName) !== -1) { connected = true; }
if (!connected) { return; }
checkSynchronizing(users, myUserName, $stateElement);
updateUserList(config, myUserName, userListElement, users, userData, readOnly, $userAdminElement);
});
} else {
userList.change.push(function () {
var users = userList.users;
if (users.indexOf(myUserName) !== -1) { connected = true; }
if (!connected) { return; }
checkSynchronizing(users, myUserName, $stateElement);
});
}
}
// Display notifications when users are joining/leaving the session
var oldUserData;
if (typeof Cryptpad !== "undefined" && userList) {
var notify = function(type, name, oldname) {
// type : 1 (+1 user), 0 (rename existing user), -1 (-1 user)
if (typeof name === "undefined") { return; }
name = (name === "") ? Messages.anonymous : name;
switch(type) {
case 1:
Cryptpad.log(Messages._getKey("notifyJoined", [name]));
break;
case 0:
oldname = (oldname === "") ? Messages.anonymous : oldname;
Cryptpad.log(Messages._getKey("notifyRenamed", [oldname, name]));
break;
case -1:
Cryptpad.log(Messages._getKey("notifyLeft", [name]));
break;
default:
console.log("Invalid type of notification");
break;
}
};
var userPresent = function (id, user, data) {
if (!(user && user.uid)) {
console.log('no uid');
return 0;
}
if (!data) {
console.log('no data');
return 0;
}
var count = 0;
Object.keys(data).forEach(function (k) {
if (data[k] && data[k].uid === user.uid) { count++; }
});
return count;
};
userList.change.push(function (newdata) {
// Notify for disconnected users
if (typeof oldUserData !== "undefined") {
for (var u in oldUserData) {
// if a user's uid is still present after having left, don't notify
if (userList.users.indexOf(u) === -1) {
var temp = JSON.parse(JSON.stringify(oldUserData[u]));
delete oldUserData[u];
if (userPresent(u, temp, newdata || oldUserData) < 1) {
notify(-1, temp.name);
}
}
}
}
// Update the "oldUserData" object and notify for new users and names changed
if (typeof newdata === "undefined") { return; }
if (typeof oldUserData === "undefined") {
oldUserData = JSON.parse(JSON.stringify(newdata));
return;
}
if (readOnly === 0 && !oldUserData[myUserName]) {
oldUserData = JSON.parse(JSON.stringify(newdata));
return;
}
for (var k in newdata) {
if (k !== myUserName && userList.users.indexOf(k) !== -1) {
if (typeof oldUserData[k] === "undefined") {
// if the same uid is already present in the userdata, don't notify
if (!userPresent(k, newdata[k], oldUserData)) {
notify(1, newdata[k].name);
}
} else if (oldUserData[k].name !== newdata[k].name) {
notify(0, newdata[k].name, oldUserData[k].name);
}
}
}
oldUserData = JSON.parse(JSON.stringify(newdata));
});
}
var ks = function (local) {
return function () {
if (connected) { kickSpinner(Cryptpad, realtime, local, spinner); }
};
};
if (realtime) {
realtime.onPatch(ks());
realtime.onMessage(ks(true));
checkLag(getLag, lagElement);
setInterval(function () {
if (!connected) { return; }
checkLag(getLag, lagElement);
}, 3000);
} else { connected = true; }
var failed = function () {
connected = false;
$stateElement.text(Messages.disconnected);
checkLag(undefined, lagElement);
};
// On log out, remove permanently the realtime elements of the toolbar
Cryptpad.onLogout(function () {
failed();
$userAdminElement.find('#userDropdown').hide();
$(userListElement).hide();
});
return {
failed: failed,
reconnecting: function (userId) {
myUserName = userId;
connected = false;
$stateElement.text(Messages.reconnecting);
checkLag(getLag, lagElement);
},
connected: function () {
connected = true;
}
};
};
return Bar;
});

@ -2,7 +2,9 @@ define([
'jquery', 'jquery',
'/customize/application_config.js', '/customize/application_config.js',
'/api/config', '/api/config',
], function ($, Config, ApiConfig) { '/common/common-ui-elements.js',
'/common/common-interface.js'
], function ($, Config, ApiConfig, UIElements, UI) {
var Messages = {}; var Messages = {};
var Cryptpad; var Cryptpad;
var Common; var Common;
@ -426,7 +428,7 @@ define([
options: options, options: options,
feedback: 'SHARE_MENU', feedback: 'SHARE_MENU',
}; };
var $shareBlock = Cryptpad.createDropdown(dropdownConfigShare); var $shareBlock = UIElements.createDropdown(dropdownConfigShare);
$shareBlock.find('.cp-dropdown-content').addClass(SHARE_CLS).addClass(EDITSHARE_CLS).addClass(VIEWSHARE_CLS); $shareBlock.find('.cp-dropdown-content').addClass(SHARE_CLS).addClass(EDITSHARE_CLS).addClass(VIEWSHARE_CLS);
$shareBlock.addClass('cp-toolbar-share-button'); $shareBlock.addClass('cp-toolbar-share-button');
$shareBlock.find('button').attr('title', Messages.shareButton); $shareBlock.find('button').attr('title', Messages.shareButton);
@ -434,21 +436,21 @@ define([
if (hashes.editHash) { if (hashes.editHash) {
$shareBlock.find('a.cp-toolbar-share-edit-copy').click(function () { $shareBlock.find('a.cp-toolbar-share-edit-copy').click(function () {
/*Common.storeLinkToClipboard(false, function (err) { /*Common.storeLinkToClipboard(false, function (err) {
if (!err) { Cryptpad.log(Messages.shareSuccess); } if (!err) { UI.log(Messages.shareSuccess); }
});*/ });*/
var url = origin + pathname + '#' + hashes.editHash; var url = origin + pathname + '#' + hashes.editHash;
var success = Cryptpad.Clipboard.copy(url); var success = Cryptpad.Clipboard.copy(url);
if (success) { Cryptpad.log(Messages.shareSuccess); } if (success) { UI.log(Messages.shareSuccess); }
}); });
} }
if (hashes.viewHash) { if (hashes.viewHash) {
$shareBlock.find('a.cp-toolbar-share-view-copy').click(function () { $shareBlock.find('a.cp-toolbar-share-view-copy').click(function () {
/*Common.storeLinkToClipboard(true, function (err) { /*Common.storeLinkToClipboard(true, function (err) {
if (!err) { Cryptpad.log(Messages.shareSuccess); } if (!err) { UI.log(Messages.shareSuccess); }
});*/ });*/
var url = origin + pathname + '#' + hashes.viewHash; var url = origin + pathname + '#' + hashes.viewHash;
var success = Cryptpad.Clipboard.copy(url); var success = Cryptpad.Clipboard.copy(url);
if (success) { Cryptpad.log(Messages.shareSuccess); } if (success) { UI.log(Messages.shareSuccess); }
}); });
$shareBlock.find('a.cp-toolbar-share-view-embed').click(function () { $shareBlock.find('a.cp-toolbar-share-view-embed').click(function () {
var url = origin + pathname + '#' + hashes.viewHash; var url = origin + pathname + '#' + hashes.viewHash;
@ -468,12 +470,12 @@ define([
readonly: 'readonly', readonly: 'readonly',
value: iframeEmbed, value: iframeEmbed,
}).appendTo($tag); }).appendTo($tag);
Cryptpad.alert($content.html(), null, true); UI.alert($content.html(), null, true);
$('#'+iframeId).click(function () { $('#'+iframeId).click(function () {
this.select(); this.select();
}); });
//var success = Cryptpad.Clipboard.copy(url); //var success = Cryptpad.Clipboard.copy(url);
//if (success) { Cryptpad.log(Messages.shareSuccess); } //if (success) { UI.log(Messages.shareSuccess); }
}); });
} }
@ -511,7 +513,7 @@ define([
options: options, options: options,
feedback: 'FILESHARE_MENU', feedback: 'FILESHARE_MENU',
}; };
var $shareBlock = Cryptpad.createDropdown(dropdownConfigShare); var $shareBlock = UIElements.createDropdown(dropdownConfigShare);
$shareBlock.find('.cp-dropdown-content').addClass(SHARE_CLS); $shareBlock.find('.cp-dropdown-content').addClass(SHARE_CLS);
$shareBlock.addClass('cp-toolbar-share-button'); $shareBlock.addClass('cp-toolbar-share-button');
$shareBlock.find('button').attr('title', Messages.shareButton); $shareBlock.find('button').attr('title', Messages.shareButton);
@ -519,7 +521,7 @@ define([
// Add handlers // Add handlers
$shareBlock.find('a.cp-toolbar-share-file-copy').click(function () { $shareBlock.find('a.cp-toolbar-share-file-copy').click(function () {
var success = Cryptpad.Clipboard.copy(url); var success = Cryptpad.Clipboard.copy(url);
if (success) { Cryptpad.log(Messages.shareSuccess); } if (success) { UI.log(Messages.shareSuccess); }
}); });
$shareBlock.find('a.cp-toolbar-share-file-embed').click(function () { $shareBlock.find('a.cp-toolbar-share-file-embed').click(function () {
var $content = $('<div>'); var $content = $('<div>');
@ -531,7 +533,7 @@ define([
var $tag = $('<p>').text(Messages.fileEmbedTag).appendTo($content); var $tag = $('<p>').text(Messages.fileEmbedTag).appendTo($content);
$('<br>').appendTo($tag); $('<br>').appendTo($tag);
$tag.append(Cryptpad.dialog.selectable(Common.getMediatagFromHref(url))); $tag.append(Cryptpad.dialog.selectable(Common.getMediatagFromHref(url)));
Cryptpad.alert($content[0], null, true); UI.alert($content[0], null, true);
}); });
toolbar.$leftside.append($shareBlock); toolbar.$leftside.append($shareBlock);
@ -760,7 +762,7 @@ define([
key = 'pinLimitReachedAlertNoAccounts'; key = 'pinLimitReachedAlertNoAccounts';
} }
$limit.show().click(function () { $limit.show().click(function () {
Cryptpad.alert(Messages._getKey(key, [encodeURIComponent(window.location.hostname)]), null, true); UI.alert(Messages._getKey(key, [encodeURIComponent(window.location.hostname)]), null, true);
}); });
} }
}; };
@ -796,7 +798,7 @@ define([
feedback: /drive/.test(window.location.pathname)? feedback: /drive/.test(window.location.pathname)?
'DRIVE_NEWPAD': 'NEWPAD', 'DRIVE_NEWPAD': 'NEWPAD',
}; };
var $newPadBlock = Cryptpad.createDropdown(dropdownConfig); var $newPadBlock = UIElements.createDropdown(dropdownConfig);
$newPadBlock.find('button').attr('title', Messages.newButtonTitle); $newPadBlock.find('button').attr('title', Messages.newButtonTitle);
$newPadBlock.find('button').addClass('fa fa-th'); $newPadBlock.find('button').addClass('fa fa-th');
return $newPadBlock; return $newPadBlock;
@ -830,7 +832,7 @@ define([
e.stopPropagation(); e.stopPropagation();
var myData = metadataMgr.getMetadata().users[metadataMgr.getNetfluxId()]; var myData = metadataMgr.getMetadata().users[metadataMgr.getNetfluxId()];
var lastName = myData.name; var lastName = myData.name;
Cryptpad.prompt(Messages.changeNamePrompt, lastName || '', function (newName) { UI.prompt(Messages.changeNamePrompt, lastName || '', function (newName) {
if (newName === null && typeof(lastName) === "string") { return; } if (newName === null && typeof(lastName) === "string") { return; }
if (newName === null) { newName = ''; } if (newName === null) { newName = ''; }
else { Common.feedback('NAME_CHANGED'); } else { Common.feedback('NAME_CHANGED'); }
@ -900,14 +902,14 @@ define([
if (Config.disableUserlistNotifications) { return; } if (Config.disableUserlistNotifications) { return; }
switch(type) { switch(type) {
case 1: case 1:
Cryptpad.log(Messages._getKey("notifyJoined", [name])); UI.log(Messages._getKey("notifyJoined", [name]));
break; break;
case 0: case 0:
oldname = (!oldname) ? Messages.anonymous : oldname; oldname = (!oldname) ? Messages.anonymous : oldname;
Cryptpad.log(Messages._getKey("notifyRenamed", [oldname, name])); UI.log(Messages._getKey("notifyRenamed", [oldname, name]));
break; break;
case -1: case -1:
Cryptpad.log(Messages._getKey("notifyLeft", [name])); UI.log(Messages._getKey("notifyLeft", [name]));
break; break;
default: default:
console.log("Invalid type of notification"); console.log("Invalid type of notification");

@ -95,7 +95,7 @@ define([
if (data.error) { if (data.error) {
Cryptpad.warn(data.error); Cryptpad.warn(data.error);
} else { } else {
Cryptpad.log(data.response); UI.log(data.response);
} }
});*/ });*/
}); });

@ -1,14 +1,16 @@
define([ define([
'jquery', 'jquery',
'/common/cryptpad-common.js', '/common/cryptpad-common.js',
'/customize/messages.js',
'/common/common-util.js',
'/common/common-interface.js',
'/common/hyperscript.js', '/common/hyperscript.js',
'/bower_components/marked/marked.min.js', '/bower_components/marked/marked.min.js',
'/common/media-tag.js', '/common/media-tag.js',
], function ($, Cryptpad, h, Marked, MediaTag) { ], function ($, Cryptpad, Messages, Util, UI, h, Marked, MediaTag) {
'use strict'; 'use strict';
var UI = {}; var UI = {};
var Messages = Cryptpad.Messages;
var m = function (md) { var m = function (md) {
var d = h('div.cp-app-contacts-content'); var d = h('div.cp-app-contacts-content');
@ -163,12 +165,12 @@ define([
}); });
$(removeHistory).click(function () { $(removeHistory).click(function () {
Cryptpad.confirm(Messages.contacts_confirmRemoveHistory, function (yes) { UI.confirm(Messages.contacts_confirmRemoveHistory, function (yes) {
if (!yes) { return; } if (!yes) { return; }
Cryptpad.clearOwnedChannel(data.channel, function (e) { Cryptpad.clearOwnedChannel(data.channel, function (e) {
if (e) { if (e) {
console.error(e); console.error(e);
Cryptpad.alert(Messages.contacts_removeHistoryServerError); UI.alert(Messages.contacts_removeHistoryServerError);
return; return;
} }
}); });
@ -355,8 +357,8 @@ define([
$(remove).click(function (e) { $(remove).click(function (e) {
e.stopPropagation(); e.stopPropagation();
Cryptpad.confirm(Messages._getKey('contacts_confirmRemove', [ UI.confirm(Messages._getKey('contacts_confirmRemove', [
Cryptpad.fixHTML(data.displayName) Util.fixHTML(data.displayName)
]), function (yes) { ]), function (yes) {
if (!yes) { return; } if (!yes) { return; }
removeFriend(curvePublic, function (e) { removeFriend(curvePublic, function (e) {

@ -5,6 +5,8 @@ define([
'json.sortify', 'json.sortify',
'/common/cryptpad-common.js', '/common/cryptpad-common.js',
'/common/common-util.js', '/common/common-util.js',
'/common/common-ui-elements.js',
'/common/common-interface.js',
'/common/cryptget.js', '/common/cryptget.js',
'/bower_components/nthen/index.js', '/bower_components/nthen/index.js',
'/common/sframe-common.js', '/common/sframe-common.js',
@ -23,6 +25,8 @@ define([
JSONSortify, JSONSortify,
Cryptpad, Cryptpad,
Util, Util,
UIElements,
UI,
Cryptget, Cryptget,
nThen, nThen,
SFCommon, SFCommon,
@ -76,7 +80,7 @@ define([
var logError = config.logError = function () { var logError = config.logError = function () {
console.error.apply(console, arguments); console.error.apply(console, arguments);
}; };
var log = config.log = Cryptpad.log; var log = config.log = UI.log;
var localStore = window.cryptpadStore; var localStore = window.cryptpadStore;
APP.store = {}; APP.store = {};
@ -255,7 +259,7 @@ define([
currentPath = [FILES_DATA]; currentPath = [FILES_DATA];
$tree.hide(); $tree.hide();
if (Object.keys(files.root).length && !proxy.anonymousAlert) { if (Object.keys(files.root).length && !proxy.anonymousAlert) {
Cryptpad.alert(Messages.fm_alert_anonymous, null, true); UI.alert(Messages.fm_alert_anonymous, null, true);
proxy.anonymousAlert = true; proxy.anonymousAlert = true;
} }
} }
@ -1442,7 +1446,7 @@ define([
$button.addClass('cp-app-drive-toolbar-emptytrash'); $button.addClass('cp-app-drive-toolbar-emptytrash');
$button.attr('title', Messages.fc_empty); $button.attr('title', Messages.fc_empty);
$button.click(function () { $button.click(function () {
Cryptpad.confirm(Messages.fm_emptyTrashDialog, function(res) { UI.confirm(Messages.fm_emptyTrashDialog, function(res) {
if (!res) { return; } if (!res) { return; }
filesOp.emptyTrash(refresh); filesOp.emptyTrash(refresh);
}); });
@ -1471,9 +1475,9 @@ define([
var onCreated = function (err, info) { var onCreated = function (err, info) {
if (err) { if (err) {
if (err === E_OVER_LIMIT) { if (err === E_OVER_LIMIT) {
return void Cryptpad.alert(Messages.pinLimitDrive, null, true); return void UI.alert(Messages.pinLimitDrive, null, true);
} }
return void Cryptpad.alert(Messages.fm_error_cantPin); return void UI.alert(Messages.fm_error_cantPin);
} }
APP.newFolder = info.newPath; APP.newFolder = info.newPath;
refresh(); refresh();
@ -1549,7 +1553,7 @@ define([
options: options, options: options,
feedback: 'DRIVE_NEWPAD_LOCALFOLDER', feedback: 'DRIVE_NEWPAD_LOCALFOLDER',
}; };
var $block = Cryptpad.createDropdown(dropdownConfig); var $block = UIElements.createDropdown(dropdownConfig);
// Custom style: // Custom style:
$block.find('button').addClass('cp-app-drive-toolbar-new'); $block.find('button').addClass('cp-app-drive-toolbar-new');
@ -2593,7 +2597,7 @@ define([
el = filesOp.find(paths[0].path); el = filesOp.find(paths[0].path);
getProperties(el, function (e, $prop) { getProperties(el, function (e, $prop) {
if (e) { return void logError(e); } if (e) { return void logError(e); }
Cryptpad.alert($prop[0], undefined, true); UI.alert($prop[0], undefined, true);
}); });
} }
else if ($(this).hasClass("cp-app-drive-context-hashtag")) { else if ($(this).hasClass("cp-app-drive-context-hashtag")) {
@ -2639,7 +2643,7 @@ define([
if (paths.length === 1) { if (paths.length === 1) {
msg = Messages.fm_removePermanentlyDialog; msg = Messages.fm_removePermanentlyDialog;
} }
Cryptpad.confirm(msg, function(res) { UI.confirm(msg, function(res) {
$(window).focus(); $(window).focus();
if (!res) { return; } if (!res) { return; }
filesOp.delete(pathsList, refresh); filesOp.delete(pathsList, refresh);
@ -2653,7 +2657,7 @@ define([
el = filesOp.find(paths[0].path); el = filesOp.find(paths[0].path);
getProperties(el, function (e, $prop) { getProperties(el, function (e, $prop) {
if (e) { return void logError(e); } if (e) { return void logError(e); }
Cryptpad.alert($prop[0], undefined, true); UI.alert($prop[0], undefined, true);
}); });
} }
else if ($(this).hasClass("cp-app-drive-context-hashtag")) { else if ($(this).hasClass("cp-app-drive-context-hashtag")) {
@ -2672,10 +2676,10 @@ define([
var path = $(this).data('path'); var path = $(this).data('path');
var onCreated = function (err, info) { var onCreated = function (err, info) {
if (err === E_OVER_LIMIT) { if (err === E_OVER_LIMIT) {
return void Cryptpad.alert(Messages.pinLimitDrive, null, true); return void UI.alert(Messages.pinLimitDrive, null, true);
} }
if (err) { if (err) {
return void Cryptpad.alert(Messages.fm_error_cantPin); return void UI.alert(Messages.fm_error_cantPin);
} }
APP.newFolder = info.newPath; APP.newFolder = info.newPath;
refresh(); refresh();
@ -2700,7 +2704,7 @@ define([
return; return;
} }
if ($(this).hasClass("cp-app-drive-context-empty")) { if ($(this).hasClass("cp-app-drive-context-empty")) {
Cryptpad.confirm(Messages.fm_emptyTrashDialog, function(res) { UI.confirm(Messages.fm_emptyTrashDialog, function(res) {
if (!res) { return; } if (!res) { return; }
filesOp.emptyTrash(refresh); filesOp.emptyTrash(refresh);
}); });
@ -2720,7 +2724,7 @@ define([
var name = paths[0].path[paths[0].path.length - 1]; var name = paths[0].path[paths[0].path.length - 1];
if ($(this).hasClass("cp-app-drive-context-remove")) { if ($(this).hasClass("cp-app-drive-context-remove")) {
if (paths.length === 1) { if (paths.length === 1) {
Cryptpad.confirm(Messages.fm_removePermanentlyDialog, function(res) { UI.confirm(Messages.fm_removePermanentlyDialog, function(res) {
if (!res) { return; } if (!res) { return; }
filesOp.delete([path], refresh); filesOp.delete([path], refresh);
}); });
@ -2729,7 +2733,7 @@ define([
var pathsList = []; var pathsList = [];
paths.forEach(function (p) { pathsList.push(p.path); }); paths.forEach(function (p) { pathsList.push(p.path); });
var msg = Messages._getKey("fm_removeSeveralPermanentlyDialog", [paths.length]); var msg = Messages._getKey("fm_removeSeveralPermanentlyDialog", [paths.length]);
Cryptpad.confirm(msg, function(res) { UI.confirm(msg, function(res) {
if (!res) { return; } if (!res) { return; }
filesOp.delete(pathsList, refresh); filesOp.delete(pathsList, refresh);
}); });
@ -2744,7 +2748,7 @@ define([
name = path[1]; name = path[1];
} }
} }
Cryptpad.confirm(Messages._getKey("fm_restoreDialog", [name]), function(res) { UI.confirm(Messages._getKey("fm_restoreDialog", [name]), function(res) {
if (!res) { return; } if (!res) { return; }
filesOp.restore(path, refresh); filesOp.restore(path, refresh);
}); });
@ -2753,7 +2757,7 @@ define([
if (paths.length !== 1 || path.length !== 4) { return; } if (paths.length !== 1 || path.length !== 4) { return; }
var element = filesOp.find(path.slice(0,3)); // element containing the oldpath var element = filesOp.find(path.slice(0,3)); // element containing the oldpath
var sPath = stringifyPath(element.path); var sPath = stringifyPath(element.path);
Cryptpad.alert('<strong>' + Messages.fm_originalPath + "</strong>:<br>" + sPath, undefined, true); UI.alert('<strong>' + Messages.fm_originalPath + "</strong>:<br>" + sPath, undefined, true);
} }
APP.hideMenu(); APP.hideMenu();
}); });
@ -2802,7 +2806,7 @@ define([
msg = Messages.fm_removePermanentlyDialog; msg = Messages.fm_removePermanentlyDialog;
} }
Cryptpad.confirm(msg, function(res) { UI.confirm(msg, function(res) {
$(window).focus(); $(window).focus();
if (!res) { return; } if (!res) { return; }
filesOp.delete(paths, refresh); filesOp.delete(paths, refresh);
@ -2996,7 +3000,7 @@ define([
$backupButton.on('click', function() { $backupButton.on('click', function() {
var url = window.location.origin + window.location.pathname + '#' + editHash; var url = window.location.origin + window.location.pathname + '#' + editHash;
var msg = Messages.fm_alert_backupUrl + '<input type="text" readonly="readonly" id="fm_backupUrl" value="'+url+'">'; var msg = Messages.fm_alert_backupUrl + '<input type="text" readonly="readonly" id="fm_backupUrl" value="'+url+'">';
Cryptpad.alert(msg, undefined, true); UI.alert(msg, undefined, true);
$('#fm_backupUrl').val(url); $('#fm_backupUrl').val(url);
$('#fm_backupUrl').click(function () { $('#fm_backupUrl').click(function () {
$(this).select(); $(this).select();
@ -3025,13 +3029,13 @@ define([
setEditable(false); setEditable(false);
if (APP.refresh) { APP.refresh(); } if (APP.refresh) { APP.refresh(); }
APP.toolbar.failed(); APP.toolbar.failed();
if (!noAlert) { Cryptpad.alert(Messages.common_connectionLost, undefined, true); } if (!noAlert) { UI.alert(Messages.common_connectionLost, undefined, true); }
}; };
var onReconnect = function (info) { var onReconnect = function (info) {
setEditable(true); setEditable(true);
if (APP.refresh) { APP.refresh(); } if (APP.refresh) { APP.refresh(); }
APP.toolbar.reconnecting(info.myId); APP.toolbar.reconnecting(info.myId);
Cryptpad.findOKButton().click(); UI.findOKButton().click();
}; };
proxy.on('create', function (info) { proxy.on('create', function (info) {

@ -49,7 +49,7 @@ define([
}); });
var firstUser = function () { var firstUser = function () {
Cryptpad.log("You are the first user to visit this board"); UI.log("You are the first user to visit this board");
}; };
var whenReady = function () { var whenReady = function () {
@ -81,7 +81,7 @@ define([
window.location.hash = info.channel + secret.key; window.location.hash = info.channel + secret.key;
}) })
.on('ready', function () { .on('ready', function () {
Cryptpad.log("Ready!"); UI.log("Ready!");
whenReady({ whenReady({
}); });

@ -6,6 +6,8 @@ define([
'/bower_components/nthen/index.js', '/bower_components/nthen/index.js',
'/common/sframe-common.js', '/common/sframe-common.js',
'/common/common-realtime.js', '/common/common-realtime.js',
'/common/common-util.js',
'/common/common-interface.js',
'/file/file-crypto.js', '/file/file-crypto.js',
'/common/media-tag.js', '/common/media-tag.js',
@ -24,6 +26,8 @@ define([
nThen, nThen,
SFCommon, SFCommon,
CommonRealtime, CommonRealtime,
Util,
UI,
FileCrypto, FileCrypto,
MediaTag) MediaTag)
{ {
@ -128,7 +132,7 @@ define([
} }
$dlButton.addClass('btn btn-success'); $dlButton.addClass('btn btn-success');
var text = Messages.download_mt_button + '<br>'; var text = Messages.download_mt_button + '<br>';
text += '<b>' + Cryptpad.fixHTML(title) + '</b><br>'; text += '<b>' + Util.fixHTML(title) + '</b><br>';
text += '<em>' + Messages._getKey('formattedMB', [sizeMb]) + '</em>'; text += '<em>' + Messages._getKey('formattedMB', [sizeMb]) + '</em>';
$dlButton.html(text); $dlButton.html(text);
@ -165,7 +169,7 @@ define([
}) })
.on('decryptionError', function (e) { .on('decryptionError', function (e) {
var error = e.originalEvent; var error = e.originalEvent;
//Cryptpad.alert(error.message); //UI.alert(error.message);
cb(error.message); cb(error.message);
}) })
.on('decryptionProgress', function (e) { .on('decryptionProgress', function (e) {
@ -205,7 +209,7 @@ define([
$dlform.show(); $dlform.show();
Cryptpad.removeLoadingScreen(); Cryptpad.removeLoadingScreen();
$dllabel.append($('<br>')); $dllabel.append($('<br>'));
$dllabel.append(Cryptpad.fixHTML(metadata.name)); $dllabel.append(Util.fixHTML(metadata.name));
// don't display the size if you don't know it. // don't display the size if you don't know it.
if (typeof(sizeM) === 'number') { if (typeof(sizeM) === 'number') {
@ -217,7 +221,7 @@ define([
if (decrypting) { return; } if (decrypting) { return; }
decrypting = true; decrypting = true;
displayFile(ev, sizeMb, function (err) { displayFile(ev, sizeMb, function (err) {
if (err) { Cryptpad.alert(err); } if (err) { UI.alert(err); }
}); });
}; };
if (typeof(sizeMb) === 'number' && sizeMb < 5) { return void onClick(); } if (typeof(sizeMb) === 'number' && sizeMb < 5) { return void onClick(); }
@ -238,7 +242,7 @@ define([
// we're in upload mode // we're in upload mode
if (!common.isLoggedIn()) { if (!common.isLoggedIn()) {
return Cryptpad.alert(Messages.upload_mustLogin, function () { return UI.alert(Messages.upload_mustLogin, function () {
Cryptpad.errorLoadingScreen(Messages.upload_mustLogin); Cryptpad.errorLoadingScreen(Messages.upload_mustLogin);
common.setLoginRedirect(function () { common.setLoginRedirect(function () {
common.gotoURL('/login/'); common.gotoURL('/login/');

@ -1,10 +1,11 @@
define([ define([
'jquery', 'jquery',
'/common/cryptpad-common.js', '/common/cryptpad-common.js',
'/bower_components/chainpad-listmap/chainpad-listmap.js', '/common/common-interface.js',
//'/bower_components/chainpad-listmap/chainpad-listmap.js',
//'/common/curve.js', //'/common/curve.js',
'less!/invite/main.less', 'less!/invite/main.less',
], function ($, Cryptpad /*, Listmap, Curve*/) { ], function ($, Cryptpad, UI /*, Listmap, Curve*/) {
var Messages = Cryptpad.Messages; var Messages = Cryptpad.Messages;
var comingSoon = function () { var comingSoon = function () {
return $('<div>', { return $('<div>', {
@ -38,7 +39,7 @@ define([
if (!info.pubkey) { if (!info.pubkey) {
Cryptpad.removeLoadingScreen(); Cryptpad.removeLoadingScreen();
Cryptpad.alert('invalid invite'); UI.alert('invalid invite');
return; return;
} }

@ -2,9 +2,10 @@ define([
'jquery', 'jquery',
'/common/cryptpad-common.js', '/common/cryptpad-common.js',
'/common/login.js', '/common/login.js',
'/common/common-interface.js',
'less!/bower_components/components-font-awesome/css/font-awesome.min.css', 'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
], function ($, Cryptpad, Login) { ], function ($, Cryptpad, Login, UI) {
$(function () { $(function () {
var $main = $('#mainBlock'); var $main = $('#mainBlock');
var Messages = Cryptpad.Messages; var Messages = Cryptpad.Messages;
@ -103,21 +104,21 @@ define([
switch (err) { switch (err) {
case 'NO_SUCH_USER': case 'NO_SUCH_USER':
Cryptpad.removeLoadingScreen(function () { Cryptpad.removeLoadingScreen(function () {
Cryptpad.alert(Messages.login_noSuchUser, function () { UI.alert(Messages.login_noSuchUser, function () {
hashing = false; hashing = false;
}); });
}); });
break; break;
case 'INVAL_USER': case 'INVAL_USER':
Cryptpad.removeLoadingScreen(function () { Cryptpad.removeLoadingScreen(function () {
Cryptpad.alert(Messages.login_invalUser, function () { UI.alert(Messages.login_invalUser, function () {
hashing = false; hashing = false;
}); });
}); });
break; break;
case 'INVAL_PASS': case 'INVAL_PASS':
Cryptpad.removeLoadingScreen(function () { Cryptpad.removeLoadingScreen(function () {
Cryptpad.alert(Messages.login_invalPass, function () { UI.alert(Messages.login_invalPass, function () {
hashing = false; hashing = false;
}); });
}); });

@ -14,8 +14,8 @@ define([
'/poll/render.js', '/poll/render.js',
'/common/diffMarked.js', '/common/diffMarked.js',
'/common/sframe-common-codemirror.js', '/common/sframe-common-codemirror.js',
'/common/common-ui-elements.js',
'/common/common-thumbnail.js', '/common/common-thumbnail.js',
'/common/common-interface.js',
'cm/lib/codemirror', 'cm/lib/codemirror',
'cm/addon/display/placeholder', 'cm/addon/display/placeholder',
@ -44,8 +44,8 @@ define([
Renderer, Renderer,
DiffMd, DiffMd,
SframeCM, SframeCM,
SFUI,
Thumb, Thumb,
UI,
CMeditor) CMeditor)
{ {
var Messages = Cryptpad.Messages; var Messages = Cryptpad.Messages;
@ -118,7 +118,7 @@ define([
var exportFile = function () { var exportFile = function () {
var csv = getCSV(); var csv = getCSV();
var suggestion = Title.suggestTitle(Title.defaultTitle); var suggestion = Title.suggestTitle(Title.defaultTitle);
Cryptpad.prompt(Messages.exportPrompt, UI.prompt(Messages.exportPrompt,
Cryptpad.fixFileName(suggestion) + '.csv', function (filename) { Cryptpad.fixFileName(suggestion) + '.csv', function (filename) {
if (!(typeof(filename) === 'string' && filename)) { return; } if (!(typeof(filename) === 'string' && filename)) { return; }
var blob = new Blob([csv], {type: "application/csv;charset=utf-8"}); var blob = new Blob([csv], {type: "application/csv;charset=utf-8"});
@ -495,7 +495,7 @@ define([
var isLocked = span.className && span.className.split(' ').indexOf('fa-lock') !== -1; var isLocked = span.className && span.className.split(' ').indexOf('fa-lock') !== -1;
if (type === 'row') { if (type === 'row') {
if (isRemove) { if (isRemove) {
Cryptpad.confirm(Messages.poll_removeOption, function (res) { UI.confirm(Messages.poll_removeOption, function (res) {
if (!res) { return; } if (!res) { return; }
Render.removeRow(APP.proxy, id, function () { Render.removeRow(APP.proxy, id, function () {
change(); change();
@ -508,7 +508,7 @@ define([
} }
} else if (type === 'col') { } else if (type === 'col') {
if (isRemove) { if (isRemove) {
Cryptpad.confirm(Messages.poll_removeUser, function (res) { UI.confirm(Messages.poll_removeUser, function (res) {
if (!res) { return; } if (!res) { return; }
Render.removeColumn(APP.proxy, id, function () { Render.removeColumn(APP.proxy, id, function () {
change(); change();
@ -1051,12 +1051,12 @@ define([
var onDisconnect = function () { var onDisconnect = function () {
setEditable(false); setEditable(false);
Cryptpad.alert(Messages.common_connectionLost, undefined, true); UI.alert(Messages.common_connectionLost, undefined, true);
}; };
var onReconnect = function () { var onReconnect = function () {
setEditable(true); setEditable(true);
Cryptpad.findOKButton().click(); UI.findOKButton().click();
}; };
var getHeadingText = function () { var getHeadingText = function () {

@ -6,6 +6,8 @@ define([
'/common/cryptpad-common.js', '/common/cryptpad-common.js',
'/bower_components/nthen/index.js', '/bower_components/nthen/index.js',
'/common/sframe-common.js', '/common/sframe-common.js',
'/common/common-util.js',
'/common/common-interface.js',
'/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',
@ -24,6 +26,8 @@ define([
Cryptpad, Cryptpad,
nThen, nThen,
SFCommon, SFCommon,
Util,
UI,
Marked, Marked,
CodeMirror CodeMirror
) )
@ -44,7 +48,7 @@ define([
}) })
.on('decryptionError', function (e) { .on('decryptionError', function (e) {
var error = e.originalEvent; var error = e.originalEvent;
Cryptpad.alert(error.message); UI.alert(error.message);
}); });
$(window).click(function () { $(window).click(function () {
@ -114,7 +118,7 @@ define([
setValue(newVal, function (err) { setValue(newVal, function (err) {
if (err) { return void console.error(err); } if (err) { return void console.error(err); }
lastVal = newVal; lastVal = newVal;
Cryptpad.log(Messages._getKey('profile_fieldSaved', [newVal || fallbackValue])); UI.log(Messages._getKey('profile_fieldSaved', [newVal || fallbackValue]));
editing = false; editing = false;
}); });
}; };
@ -158,7 +162,7 @@ define([
var unsafeName = obj.name || ''; var unsafeName = obj.name || '';
console.log(unsafeName); console.log(unsafeName);
var name = Cryptpad.fixHTML(unsafeName) || Messages.anonymous; var name = Util.fixHTML(unsafeName) || Messages.anonymous;
console.log(name); console.log(name);
console.log("Creating invite button"); console.log("Creating invite button");
@ -169,10 +173,10 @@ define([
.addClass('btn btn-success') .addClass('btn btn-success')
.text(Messages.profile_inviteButton) .text(Messages.profile_inviteButton)
.click(function () { .click(function () {
Cryptpad.confirm(Messages._getKey('profile_inviteExplanation', [name]), function (yes) { UI.confirm(Messages._getKey('profile_inviteExplanation', [name]), function (yes) {
if (!yes) { return; } if (!yes) { return; }
console.log(obj.curveKey); console.log(obj.curveKey);
Cryptpad.alert("TODO"); UI.alert("TODO");
// TODO create a listmap object using your curve keys // TODO create a listmap object using your curve keys
// TODO fill the listmap object with your invite data // TODO fill the listmap object with your invite data
// TODO generate link to invite object // TODO generate link to invite object
@ -280,7 +284,7 @@ define([
$delButton.click(function () { $delButton.click(function () {
var old = common.getMetadataMgr().getUserData().avatar; var old = common.getMetadataMgr().getUserData().avatar;
sframeChan.query("Q_PROFILE_AVATAR_REMOVE", old, function (err, err2) { sframeChan.query("Q_PROFILE_AVATAR_REMOVE", old, function (err, err2) {
if (err || err2) { return void Cryptpad.log(err || err2); } if (err || err2) { return void UI.log(err || err2); }
delete APP.lm.proxy.avatar; delete APP.lm.proxy.avatar;
displayAvatar(); displayAvatar();
}); });
@ -297,14 +301,14 @@ define([
var old = common.getMetadataMgr().getUserData().avatar; var old = common.getMetadataMgr().getUserData().avatar;
var todo = function () { var todo = function () {
sframeChan.query("Q_PROFILE_AVATAR_ADD", data.url, function (err, err2) { sframeChan.query("Q_PROFILE_AVATAR_ADD", data.url, function (err, err2) {
if (err || err2) { return void Cryptpad.log(err || err2); } if (err || err2) { return void UI.log(err || err2); }
APP.lm.proxy.avatar = data.url; APP.lm.proxy.avatar = data.url;
displayAvatar(); displayAvatar();
}); });
}; };
if (old) { if (old) {
sframeChan.query("Q_PROFILE_AVATAR_REMOVE", old, function (err, err2) { sframeChan.query("Q_PROFILE_AVATAR_REMOVE", old, function (err, err2) {
if (err || err2) { return void Cryptpad.log(err || err2); } if (err || err2) { return void UI.log(err || err2); }
todo(); todo();
}); });
return; return;

@ -56,7 +56,7 @@ define([
// TODO // TODO
} }
return; return;
//return void Cryptpad.log(Messages._getKey('profile_error', [e])) // TODO //return void UI.log(Messages._getKey('profile_error', [e])) // TODO
} }
obj.profile = {}; obj.profile = {};
obj.profile.edit = Cryptpad.getEditHashFromKeys(secret.channel, secret.keys); obj.profile.edit = Cryptpad.getEditHashFromKeys(secret.channel, secret.keys);

@ -4,9 +4,10 @@ define([
'/common/cryptpad-common.js', '/common/cryptpad-common.js',
'/common/test.js', '/common/test.js',
'/common/credential.js', // preloaded for login.js '/common/credential.js', // preloaded for login.js
'/common/common-interface.js',
'less!/bower_components/components-font-awesome/css/font-awesome.min.css', 'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
], function ($, Login, Cryptpad, Test, Cred) { ], function ($, Login, Cryptpad, Test, Cred, UI) {
var Messages = Cryptpad.Messages; var Messages = Cryptpad.Messages;
$(function () { $(function () {
@ -100,21 +101,21 @@ define([
var warning = Messages._getKey('register_passwordTooShort', [ var warning = Messages._getKey('register_passwordTooShort', [
Cred.MINIMUM_PASSWORD_LENGTH Cred.MINIMUM_PASSWORD_LENGTH
]); ]);
return void Cryptpad.alert(warning, function () { return void UI.alert(warning, function () {
registering = false; registering = false;
}); });
} }
if (passwd !== confirmPassword) { // do their passwords match? if (passwd !== confirmPassword) { // do their passwords match?
return void Cryptpad.alert(Messages.register_passwordsDontMatch); return void UI.alert(Messages.register_passwordsDontMatch);
} }
if (!doesAccept) { // do they accept the terms of service? if (!doesAccept) { // do they accept the terms of service?
return void Cryptpad.alert(Messages.register_mustAcceptTerms); return void UI.alert(Messages.register_mustAcceptTerms);
} }
setTimeout(function () { setTimeout(function () {
Cryptpad.confirm("<h2 class='bright msg'>" + Messages.register_warning + "</h2>", UI.confirm("<h2 class='bright msg'>" + Messages.register_warning + "</h2>",
function (yes) { function (yes) {
if (!yes) { return; } if (!yes) { return; }
@ -135,21 +136,21 @@ define([
switch (err) { switch (err) {
case 'NO_SUCH_USER': case 'NO_SUCH_USER':
Cryptpad.removeLoadingScreen(function () { Cryptpad.removeLoadingScreen(function () {
Cryptpad.alert(Messages.login_noSuchUser, function () { UI.alert(Messages.login_noSuchUser, function () {
registering = false; registering = false;
}); });
}); });
break; break;
case 'INVAL_USER': case 'INVAL_USER':
Cryptpad.removeLoadingScreen(function () { Cryptpad.removeLoadingScreen(function () {
Cryptpad.alert(Messages.login_invalUser, function () { UI.alert(Messages.login_invalUser, function () {
registering = false; registering = false;
}); });
}); });
break; break;
case 'INVAL_PASS': case 'INVAL_PASS':
Cryptpad.removeLoadingScreen(function () { Cryptpad.removeLoadingScreen(function () {
Cryptpad.alert(Messages.login_invalPass, function () { UI.alert(Messages.login_invalPass, function () {
registering = false; registering = false;
}); });
}); });
@ -159,7 +160,7 @@ define([
var warning = Messages._getKey('register_passwordTooShort', [ var warning = Messages._getKey('register_passwordTooShort', [
Cred.MINIMUM_PASSWORD_LENGTH Cred.MINIMUM_PASSWORD_LENGTH
]); ]);
Cryptpad.alert(warning, function () { UI.alert(warning, function () {
registering = false; registering = false;
}); });
}); });
@ -167,7 +168,7 @@ define([
case 'ALREADY_REGISTERED': case 'ALREADY_REGISTERED':
// logMeIn should reset registering = false // logMeIn should reset registering = false
Cryptpad.removeLoadingScreen(function () { Cryptpad.removeLoadingScreen(function () {
Cryptpad.confirm(Messages.register_alreadyRegistered, function (yes) { UI.confirm(Messages.register_alreadyRegistered, function (yes) {
if (!yes) { return; } if (!yes) { return; }
proxy.login_name = uname; proxy.login_name = uname;
@ -240,7 +241,7 @@ define([
$register.click(); $register.click();
window.setTimeout(function () { window.setTimeout(function () {
Cryptpad.findOKButton().click(); UI.findOKButton().click();
}, 1000); }, 1000);
}); });
}); });

@ -4,6 +4,7 @@ define([
'/common/cryptpad-common.js', '/common/cryptpad-common.js',
'/bower_components/nthen/index.js', '/bower_components/nthen/index.js',
'/common/sframe-common.js', '/common/sframe-common.js',
'/common/common-interface.js',
'/bower_components/file-saver/FileSaver.min.js', '/bower_components/file-saver/FileSaver.min.js',
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css', 'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
@ -14,7 +15,8 @@ define([
Toolbar, Toolbar,
Cryptpad, Cryptpad,
nThen, nThen,
SFCommon SFCommon,
UI
) )
{ {
var saveAs = window.saveAs; var saveAs = window.saveAs;
@ -198,7 +200,7 @@ define([
localStore.put(k, undefined); localStore.put(k, undefined);
} }
}); });
Cryptpad.alert(Messages.settings_resetTipsDone); UI.alert(Messages.settings_resetTipsDone);
}); });
return $div; return $div;
@ -249,7 +251,7 @@ define([
$button.click(function () { $button.click(function () {
sframeChan.query("Q_THUMBNAIL_CLEAR", null, function (err) { sframeChan.query("Q_THUMBNAIL_CLEAR", null, function (err) {
if (err) { return void console.error("Cannot clear localForage"); } if (err) { return void console.error("Cannot clear localForage"); }
Cryptpad.alert(Messages.settings_resetThumbnailsDone); UI.alert(Messages.settings_resetThumbnailsDone);
}); });
}); });
@ -268,7 +270,7 @@ define([
var sjson = JSON.stringify(data); var sjson = JSON.stringify(data);
var name = displayName || accountName || Messages.anonymous; var name = displayName || accountName || Messages.anonymous;
var suggestion = name + '-' + new Date().toDateString(); var suggestion = name + '-' + new Date().toDateString();
Cryptpad.prompt(Cryptpad.Messages.exportPrompt, UI.prompt(Cryptpad.Messages.exportPrompt,
Cryptpad.fixFileName(suggestion) + '.json', function (filename) { Cryptpad.fixFileName(suggestion) + '.json', function (filename) {
if (!(typeof(filename) === 'string' && filename)) { return; } if (!(typeof(filename) === 'string' && filename)) { return; }
var blob = new Blob([sjson], {type: "application/json;charset=utf-8"}); var blob = new Blob([sjson], {type: "application/json;charset=utf-8"});
@ -314,14 +316,14 @@ define([
.text(Messages.settings_resetButton).appendTo($div); .text(Messages.settings_resetButton).appendTo($div);
$button.click(function () { $button.click(function () {
Cryptpad.prompt(Messages.settings_resetPrompt, "", function (val) { UI.prompt(Messages.settings_resetPrompt, "", function (val) {
if (val !== "I love CryptPad") { if (val !== "I love CryptPad") {
Cryptpad.alert(Messages.settings_resetError); UI.alert(Messages.settings_resetError);
return; return;
} }
sframeChan.query("Q_SETTINGS_DRIVE_RESET", null, function (err) { sframeChan.query("Q_SETTINGS_DRIVE_RESET", null, function (err) {
if (err) { return void console.error(err); } if (err) { return void console.error(err); }
Cryptpad.alert(Messages.settings_resetDone); UI.alert(Messages.settings_resetDone);
}); });
}, undefined, true); }, undefined, true);
}); });
@ -392,7 +394,7 @@ define([
$button.click(function () { $button.click(function () {
Cryptpad.confirm(Messages.settings_logoutEverywhereConfirm, function (yes) { UI.confirm(Messages.settings_logoutEverywhereConfirm, function (yes) {
if (!yes) { return; } if (!yes) { return; }
$spinner.show(); $spinner.show();
$ok.hide(); $ok.hide();
@ -424,14 +426,14 @@ define([
var $spinner = $('<span>', {'class': 'fa fa-spinner fa-pulse'}).hide().appendTo($div); var $spinner = $('<span>', {'class': 'fa fa-spinner fa-pulse'}).hide().appendTo($div);
$button.click(function () { $button.click(function () {
Cryptpad.confirm(Messages.settings_importConfirm, function (yes) { UI.confirm(Messages.settings_importConfirm, function (yes) {
if (!yes) { return; } if (!yes) { return; }
$spinner.show(); $spinner.show();
$ok.hide(); $ok.hide();
sframeChan.query('Q_SETTINGS_IMPORT_LOCAL', null, function () { sframeChan.query('Q_SETTINGS_IMPORT_LOCAL', null, function () {
$spinner.hide(); $spinner.hide();
$ok.show(); $ok.show();
Cryptpad.alert(Messages.settings_importDone); UI.alert(Messages.settings_importDone);
}); });
}, undefined, true); }, undefined, true);
}); });

@ -1,528 +0,0 @@
define([
'jquery',
'/common/cryptpad-common.js',
'/common/hyperscript.js',
'/bower_components/marked/marked.min.js',
'/common/media-tag.js',
], function ($, Cryptpad, h, Marked, MediaTag) {
'use strict';
var UI = {};
var Messages = Cryptpad.Messages;
var m = function (md) {
var d = h('div.cp-app-contacts-content');
try {
d.innerHTML = Marked(md || '');
var $d = $(d);
// remove potentially malicious elements
$d.find('script, iframe, object, applet, video, audio').remove();
// activate media-tags
$d.find('media-tag').each(function (i, e) { MediaTag(e); });
} catch (e) {
console.error(md);
console.error(e);
}
return d;
};
var dataQuery = function (curvePublic) {
return '[data-key="' + curvePublic + '"]';
};
var initChannel = function (state, curvePublic, info) {
console.log('initializing channel for [%s]', curvePublic);
state.channels[curvePublic] = {
messages: [],
HEAD: info.lastKnownHash,
TAIL: null,
};
};
UI.create = function (messenger, $userlist, $messages, common) {
var origin = common.getMetadataMgr().getPrivateData().origin;
var state = window.state = {
active: '',
};
state.channels = {};
var displayNames = state.displayNames = {};
var avatars = state.avatars = {};
var setActive = function (curvePublic) {
state.active = curvePublic;
};
var isActive = function (curvePublic) {
return curvePublic === state.active;
};
var find = {};
find.inList = function (curvePublic) {
return $userlist.find(dataQuery(curvePublic));
};
var notify = function (curvePublic) {
find.inList(curvePublic).addClass('cp-app-contacts-notify');
};
var unnotify = function (curvePublic) {
find.inList(curvePublic).removeClass('cp-app-contacts-notify');
};
var markup = {};
markup.message = function (msg) {
var curvePublic = msg.author;
var name = displayNames[msg.author];
return h('div.cp-app-contacts-message', {
title: msg.time? new Date(msg.time).toLocaleString(): '?',
'data-key': curvePublic,
}, [
name? h('div.cp-app-contacts-sender', name): undefined,
m(msg.text),
]);
};
var getChat = function (curvePublic) {
return $messages.find(dataQuery(curvePublic));
};
var normalizeLabels = function ($messagebox) {
$messagebox.find('div.cp-app-contacts-message').toArray().reduce(function (a, b) {
var $b = $(b);
if ($(a).data('key') === $b.data('key')) {
$b.find('.cp-app-contacts-sender').hide();
return a;
}
return b;
}, []);
};
markup.chatbox = function (curvePublic, data) {
var moreHistory = h('span.cp-app-contacts-more-history.fa.fa-history', {
title: Messages.contacts_fetchHistory,
});
var displayName = data.displayName;
var fetching = false;
var $moreHistory = $(moreHistory).click(function () {
if (fetching) { return; }
// get oldest known message...
var channel = state.channels[curvePublic];
if (channel.exhausted) {
return void $moreHistory.addClass('cp-app-contacts-faded');
}
console.log('getting history');
var sig = channel.TAIL || channel.HEAD;
fetching = true;
var $messagebox = $(getChat(curvePublic)).find('.cp-app-contacts-messages');
messenger.getMoreHistory(curvePublic, sig, 10, function (e, history) {
fetching = false;
if (e) { return void console.error(e); }
if (history.length === 0) {
channel.exhausted = true;
return;
}
history.forEach(function (msg) {
if (channel.exhausted) { return; }
if (msg.sig) {
if (msg.sig === channel.TAIL) {
console.error('No more messages to fetch');
channel.exhausted = true;
console.log(channel);
return void $moreHistory.addClass('cp-app-contacts-faded');
} else {
channel.TAIL = msg.sig;
}
} else {
return void console.error('expected signature');
}
if (msg.type !== 'MSG') { return; }
// FIXME Schlameil the painter (performance does not scale well)
if (channel.messages.some(function (old) {
return msg.sig === old.sig;
})) { return; }
channel.messages.unshift(msg);
var el_message = markup.message(msg);
$messagebox.prepend(el_message);
});
normalizeLabels($messagebox);
});
});
var removeHistory = h('span.cp-app-contacts-remove-history.fa.fa-eraser', {
title: Messages.contacts_removeHistoryTitle
});
$(removeHistory).click(function () {
Cryptpad.confirm(Messages.contacts_confirmRemoveHistory, function (yes) {
if (!yes) { return; }
Cryptpad.clearOwnedChannel(data.channel, function (e) {
if (e) {
console.error(e);
Cryptpad.alert(Messages.contacts_removeHistoryServerError);
return;
}
});
});
});
var avatar = h('div.cp-avatar');
var header = h('div.cp-app-contacts-header', [
avatar,
moreHistory,
removeHistory,
]);
var messages = h('div.cp-app-contacts-messages');
var input = h('textarea', {
placeholder: Messages.contacts_typeHere
});
var sendButton = h('button.btn.btn-primary.fa.fa-paper-plane', {
title: Messages.contacts_send,
});
var rightCol = h('span.cp-app-contacts-right-col', [
h('span.cp-app-contacts-name', displayName),
]);
var $avatar = $(avatar);
if (data.avatar && avatars[data.avatar]) {
$avatar.append(avatars[data.avatar]).append(rightCol);
} else {
common.displayAvatar($avatar, data.avatar, data.displayName, function ($img) {
if (data.avatar && $img) {
avatars[data.avatar] = $img[0].outerHTML;
}
$(rightCol).insertAfter($avatar);
});
}
var sending = false;
var send = function (content) {
if (typeof(content) !== 'string' || !content.trim()) { return; }
if (sending) { return false; }
sending = true;
messenger.sendMessage(curvePublic, content, function (e) {
if (e) {
// failed to send
return void console.error('failed to send');
}
input.value = '';
sending = false;
console.log('sent successfully');
var $messagebox = $(messages);
var height = $messagebox[0].scrollHeight;
$messagebox.scrollTop(height);
});
};
var onKeyDown = function (e) {
// ignore anything that isn't 'enter'
if (e.keyCode !== 13) { return; }
// send unless they're holding a ctrl-key or shift
if (!e.ctrlKey && !e.shiftKey) {
send(this.value);
return false;
}
// insert a newline if they're holding either
var val = this.value;
var start = this.selectionState;
var end = this.selectionEnd;
if (![start,end].some(function (x) {
return typeof(x) !== 'number';
})) {
this.value = val.slice(0, start) + '\n' + val.slice(end);
this.selectionStart = this.selectionEnd = start + 1;
} else if (document.selection && document.selection.createRange) {
this.focus();
var range = document.selection.createRange();
range.text = '\r\n';
range.collapse(false);
range.select();
}
return false;
};
$(input).on('keydown', onKeyDown);
$(sendButton).click(function () { send(input.value); });
return h('div.cp-app-contacts-chat', {
'data-key': curvePublic,
}, [
header,
messages,
h('div.cp-app-contacts-input', [
input,
sendButton,
]),
]);
};
var hideInfo = function () {
$messages.find('.cp-app-contacts-info').hide();
};
var updateStatus = function (curvePublic) {
var $status = find.inList(curvePublic).find('.cp-app-contacts-status');
// FIXME this stopped working :(
messenger.getStatus(curvePublic, function (e, online) {
// if error maybe you shouldn't display this friend...
if (e) {
find.inList(curvePublic).hide();
getChat(curvePublic).hide();
return void console.error(curvePublic, e);
}
if (online) {
return void $status
.removeClass('cp-app-contacts-offline').addClass('cp-app-contacts-online');
}
$status.removeClass('cp-app-contacts-online').addClass('cp-app-contacts-offline');
});
};
var display = function (curvePublic) {
var channel = state.channels[curvePublic];
var lastMsg = channel.messages.slice(-1)[0];
if (lastMsg) {
channel.HEAD = lastMsg.sig;
messenger.setChannelHead(curvePublic, channel.HEAD, function (e) {
if (e) { console.error(e); }
});
}
setActive(curvePublic);
unnotify(curvePublic);
var $chat = getChat(curvePublic);
hideInfo();
$messages.find('div.cp-app-contacts-chat[data-key]').hide();
if ($chat.length) {
var $chat_messages = $chat.find('div.cp-app-contacts-message');
if (!$chat_messages.length) {
var $more = $chat.find('.cp-app-contacts-more-history');
$more.click();
}
return void $chat.show();
}
messenger.getFriendInfo(curvePublic, function (e, info) {
if (e) { return void console.error(e); } // FIXME
var chatbox = markup.chatbox(curvePublic, info);
$messages.append(chatbox);
});
};
var removeFriend = function (curvePublic) {
messenger.removeFriend(curvePublic, function (e /*, removed */) {
if (e) { return void console.error(e); }
find.inList(curvePublic).remove();
//console.log(removed);
});
};
markup.friend = function (data) {
var curvePublic = data.curvePublic;
var friend = h('div.cp-app-contacts-friend.cp-avatar', {
'data-key': curvePublic,
});
var remove = h('span.cp-app-contacts-remove.fa.fa-user-times', {
title: Messages.contacts_remove
});
var status = h('span.cp-app-contacts-status');
var rightCol = h('span.cp-app-contacts-right-col', [
h('span.cp-app-contacts-name', [data.displayName]),
remove,
]);
var $friend = $(friend)
.click(function () {
display(curvePublic);
})
.dblclick(function () {
if (data.profile) { window.open(origin + '/profile/#' + data.profile); }
});
$(remove).click(function (e) {
e.stopPropagation();
Cryptpad.confirm(Messages._getKey('contacts_confirmRemove', [
Cryptpad.fixHTML(data.displayName)
]), function (yes) {
if (!yes) { return; }
removeFriend(curvePublic, function (e) {
if (e) { return void console.error(e); }
});
// TODO remove friend from userlist ui
// FIXME seems to trigger EJOINED from netflux-websocket (from server);
// (tried to join a channel in which you were already present)
}, undefined, true);
});
if (data.avatar && avatars[data.avatar]) {
$friend.append(avatars[data.avatar]);
$friend.append(rightCol);
} else {
common.displayAvatar($friend, data.avatar, data.displayName, function ($img) {
if (data.avatar && $img) {
avatars[data.avatar] = $img[0].outerHTML;
}
$friend.append(rightCol);
});
}
$friend.append(status);
return $friend;
};
var isBottomedOut = function ($elem) {
return ($elem[0].scrollHeight - $elem.scrollTop() === $elem.outerHeight());
};
var initializing = true;
messenger.on('message', function (message) {
if (!initializing) { Cryptpad.notify(); }
var curvePublic = message.curve;
var name = displayNames[curvePublic];
var chat = getChat(curvePublic, name);
console.log(message);
var el_message = markup.message(message);
state.channels[curvePublic].messages.push(message);
var $chat = $(chat);
if (!$chat.length) {
console.error("Got a message but the chat isn't open");
}
var $messagebox = $chat.find('.cp-app-contacts-messages');
var shouldScroll = isBottomedOut($messagebox);
$messagebox.append(el_message);
if (shouldScroll) {
$messagebox.scrollTop($messagebox.outerHeight());
}
normalizeLabels($messagebox);
var channel = state.channels[curvePublic];
if (!channel) {
console.error('expected channel [%s] to be open', curvePublic);
return;
}
if (isActive(curvePublic)) {
channel.HEAD = message.sig;
messenger.setChannelHead(curvePublic, message.sig, function (e) {
if (e) { return void console.error(e); }
});
return;
}
var lastMsg = channel.messages.slice(-1)[0];
if (lastMsg.sig !== channel.HEAD) {
return void notify(curvePublic);
}
unnotify(curvePublic);
});
messenger.on('join', function (curvePublic, channel) {
channel = channel;
updateStatus(curvePublic);
});
messenger.on('leave', function (curvePublic, channel) {
channel = channel;
updateStatus(curvePublic);
});
// change in your friend list
messenger.on('update', function (info, curvePublic) {
var name = displayNames[curvePublic] = info.displayName;
// update label in friend list
find.inList(curvePublic).find('.cp-app-contacts-name').text(name);
// update title bar and messages
$messages.find(dataQuery(curvePublic) + ' .cp-app-contacts-header ' +
'.cp-app-contacts-name, div.cp-app-contacts-message'+
dataQuery(curvePublic) + ' div.cp-app-contacts-sender').text(name).text(name);
});
var connectToFriend = function (curvePublic, cb) {
messenger.getFriendInfo(curvePublic, function (e, info) {
if (e) { return void console.error(e); }
var name = displayNames[curvePublic] = info.displayName;
initChannel(state, curvePublic, info);
var chatbox = markup.chatbox(curvePublic, info);
$(chatbox).hide();
$messages.append(chatbox);
var friend = markup.friend(info, name);
$userlist.append(friend);
messenger.openFriendChannel(curvePublic, function (e) {
if (e) { return void console.error(e); }
cb();
updateStatus(curvePublic);
// don't add friends that are already in your userlist
//if (friendExistsInUserList(k)) { return; }
});
});
};
messenger.on('friend', function (curvePublic) {
console.log('new friend: ', curvePublic);
//console.error("TODO redraw user list");
//console.error("TODO connect to new friend");
// FIXME this doesn't work right now because the friend hasn't been fully added?
connectToFriend(curvePublic, function () {
//console.error('connected');
});
});
messenger.on('unfriend', function (curvePublic) {
console.log('unfriend', curvePublic);
find.inList(curvePublic).remove();
console.error('TODO remove chatbox');
console.error('TODO show something if that chatbox was active');
});
Cryptpad.onDisplayNameChanged(function () {
//messenger.checkNewFriends();
messenger.updateMyData();
});
// FIXME dirty hack
messenger.getMyInfo(function (e, info) {
displayNames[info.curvePublic] = info.displayName;
});
messenger.getFriendList(function (e, keys) {
var count = keys.length + 1;
var ready = function () {
count--;
if (count === 0) {
initializing = false;
Cryptpad.removeLoadingScreen();
}
};
ready();
keys.forEach(function (curvePublic) {
connectToFriend(curvePublic, ready);
});
});
};
return UI;
});

@ -7,6 +7,7 @@ define([
'/slide/slide.js', '/slide/slide.js',
'/common/sframe-app-framework.js', '/common/sframe-app-framework.js',
'/common/common-util.js', '/common/common-util.js',
'/common/common-interface.js',
'cm/lib/codemirror', 'cm/lib/codemirror',
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css', 'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
@ -48,6 +49,7 @@ define([
Slide, Slide,
Framework, Framework,
Util, Util,
UI,
CMeditor) CMeditor)
{ {
window.CodeMirror = CMeditor; window.CodeMirror = CMeditor;
@ -104,7 +106,7 @@ define([
Slide.update(editor.getValue(), true); Slide.update(editor.getValue(), true);
$print.html($content.html()); $print.html($content.html());
// TODO use translation key // TODO use translation key
Cryptpad.confirm("Are you sure you want to print?", function (yes) { UI.confirm("Are you sure you want to print?", function (yes) {
if (yes) { if (yes) {
window.focus(); window.focus();
window.print(); window.print();
@ -224,7 +226,7 @@ define([
slideOptionsTmp.style = ''; slideOptionsTmp.style = '';
parseLess(mkLess(less), function (err, css) { parseLess(mkLess(less), function (err, css) {
if (err) { if (err) {
Cryptpad.alert( UI.alert(
'<strong>' + Messages.slide_invalidLess + '</strong>' + '<strong>' + Messages.slide_invalidLess + '</strong>' +
'<br>' + '<br>' +
'<pre class="cp-slide-css-error">' + Util.fixHTML( '<pre class="cp-slide-css-error">' + Util.fixHTML(
@ -245,14 +247,14 @@ define([
updateLocalOptions(slideOptionsTmp); updateLocalOptions(slideOptionsTmp);
} }
$container.remove(); $container.remove();
Cryptpad.stopListening(h); UI.stopListening(h);
}; };
var todoCancel = function () { var todoCancel = function () {
$container.remove(); $container.remove();
Cryptpad.stopListening(h); UI.stopListening(h);
}; };
h = Cryptpad.listenForKeys(todo, todoCancel); h = UI.listenForKeys(todo, todoCancel);
var $nav = $('<nav>').appendTo($div); var $nav = $('<nav>').appendTo($div);
$('<button>', {'class': 'cancel'}).text(Messages.cancelButton).appendTo($nav).click(todoCancel); $('<button>', {'class': 'cancel'}).text(Messages.cancelButton).appendTo($nav).click(todoCancel);

@ -10,7 +10,7 @@ define([
'/common/cryptget.js', '/common/cryptget.js',
'/bower_components/nthen/index.js', '/bower_components/nthen/index.js',
'/common/sframe-common.js', '/common/sframe-common.js',
'/common/common-ui-elements.js', '/common/common-interface.js',
'/api/config', '/api/config',
'/common/common-realtime.js', '/common/common-realtime.js',
'/customize/pages.js', '/customize/pages.js',
@ -37,7 +37,7 @@ define([
Cryptget, Cryptget,
nThen, nThen,
SFCommon, SFCommon,
SFUI, UI,
ApiConfig, ApiConfig,
CommonRealtime, CommonRealtime,
Pages, Pages,
@ -228,7 +228,7 @@ define([
var saveImage = APP.saveImage = function () { var saveImage = APP.saveImage = function () {
var defaultName = "pretty-picture.png"; var defaultName = "pretty-picture.png";
Cryptpad.prompt(Messages.exportPrompt, defaultName, function (filename) { UI.prompt(Messages.exportPrompt, defaultName, function (filename) {
if (!(typeof(filename) === 'string' && filename)) { return; } if (!(typeof(filename) === 'string' && filename)) { return; }
$canvas[0].toBlob(function (blob) { $canvas[0].toBlob(function (blob) {
saveAs(blob, filename); saveAs(blob, filename);
@ -436,7 +436,7 @@ define([
if (common.isLoggedIn()) { if (common.isLoggedIn()) {
common.createButton('savetodrive', true, {}, function () {}) common.createButton('savetodrive', true, {}, function () {})
.click(function () { .click(function () {
Cryptpad.prompt(Messages.exportPrompt, document.title + '.png', UI.prompt(Messages.exportPrompt, document.title + '.png',
function (name) { function (name) {
if (name === null || !name.trim()) { return; } if (name === null || !name.trim()) { return; }
APP.upload(name); APP.upload(name);
@ -592,16 +592,16 @@ define([
// inform of network disconnect // inform of network disconnect
setEditable(false); setEditable(false);
toolbar.failed(); toolbar.failed();
Cryptpad.alert(Messages.common_connectionLost, undefined, true); UI.alert(Messages.common_connectionLost, undefined, true);
}; };
config.onConnectionChange = function (info) { config.onConnectionChange = function (info) {
setEditable(info.state); setEditable(info.state);
if (info.state) { if (info.state) {
initializing = true; initializing = true;
Cryptpad.findOKButton().click(); UI.findOKButton().click();
} else { } else {
Cryptpad.alert(Messages.common_connectionLost, undefined, true); UI.alert(Messages.common_connectionLost, undefined, true);
} }
}; };
@ -612,7 +612,7 @@ define([
cpNfInner.onInfiniteSpinner(function () { cpNfInner.onInfiniteSpinner(function () {
setEditable(false); setEditable(false);
Cryptpad.confirm(Messages.realtime_unrecoverableError, function (yes) { UI.confirm(Messages.realtime_unrecoverableError, function (yes) {
if (!yes) { return; } if (!yes) { return; }
common.gotoURL(); common.gotoURL();
}); });

Loading…
Cancel
Save