cryptpad/www/profile/inner.js
2019-05-29 19:00:20 +02:00

577 lines
20 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

define([
'jquery',
'/bower_components/chainpad-crypto/crypto.js',
'/bower_components/chainpad-listmap/chainpad-listmap.js',
'/common/toolbar3.js',
'/bower_components/nthen/index.js',
'/common/sframe-common.js',
'/common/common-util.js',
'/common/common-interface.js',
'/common/common-ui-elements.js',
'/common/common-realtime.js',
'/common/hyperscript.js',
'/customize/messages.js',
'/customize/application_config.js',
'/bower_components/marked/marked.min.js',
'cm/lib/codemirror',
'cm/mode/markdown/markdown',
'css!/bower_components/codemirror/lib/codemirror.css',
'css!/bower_components/codemirror/addon/dialog/dialog.css',
'css!/bower_components/codemirror/addon/fold/foldgutter.css',
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/profile/app-profile.less',
'/bower_components/croppie/croppie.min.js',
'css!/bower_components/croppie/croppie.css',
], function (
$,
Crypto,
Listmap,
Toolbar,
nThen,
SFCommon,
Util,
UI,
UIElements,
Realtime,
h,
Messages,
AppConfig,
Marked,
CodeMirror
)
{
var APP = window.APP = {
_onRefresh: []
};
$(window).click(function () {
$('.cp-dropdown-content').hide();
});
// Marked
var renderer = new Marked.Renderer();
Marked.setOptions({
renderer: renderer,
sanitize: true
});
// Tasks list
var checkedTaskItemPtn = /^\s*\[x\]\s*/;
var uncheckedTaskItemPtn = /^\s*\[ \]\s*/;
renderer.listitem = function (text) {
var isCheckedTaskItem = checkedTaskItemPtn.test(text);
var isUncheckedTaskItem = uncheckedTaskItemPtn.test(text);
if (isCheckedTaskItem) {
text = text.replace(checkedTaskItemPtn,
'<i class="fa fa-check-square" aria-hidden="true"></i>&nbsp;') + '\n';
}
if (isUncheckedTaskItem) {
text = text.replace(uncheckedTaskItemPtn,
'<i class="fa fa-square-o" aria-hidden="true"></i>&nbsp;') + '\n';
}
var cls = (isCheckedTaskItem || isUncheckedTaskItem) ? ' class="todo-list-item"' : '';
return '<li'+ cls + '>' + text + '</li>\n';
};
var DISPLAYNAME_ID = "cp-app-profile-displayname";
var LINK_ID = "cp-app-profile-link";
var AVATAR_ID = "cp-app-profile-avatar";
var DESCRIPTION_ID = "cp-app-profile-description";
var CREATE_ID = "cp-app-profile-create";
var HEADER_ID = "cp-app-profile-header";
var HEADER_RIGHT_ID = "cp-app-profile-rightside";
var CREATE_INVITE_BUTTON = 'cp-app-profile-invite-button'; /* jshint ignore: line */
var VIEW_PROFILE_BUTTON = 'cp-app-profile-viewprofile-button';
var common;
var sFrameChan;
var addViewButton = function ($container) {
if (APP.readOnly) {
return;
}
var hash = common.getMetadataMgr().getPrivateData().hashes.viewHash;
var url = APP.origin + '/profile/#' + hash;
var $button = $('<button>', {
'class': 'btn btn-success',
id: VIEW_PROFILE_BUTTON,
})
.text(Messages.profile_viewMyProfile)
.click(function () {
window.open(url, '_blank');
});
$container.append($button);
};
var addDisplayName = function ($container) {
var $block = $('<div>', {id: DISPLAYNAME_ID}).appendTo($container);
APP.$name = $('<span>', {'class': DISPLAYNAME_ID}).appendTo($block);
};
var refreshName = function (data) {
APP.$name.text(data.name || Messages.anonymous);
};
var addLink = function ($container) {
var $block = $('<div>', {id: LINK_ID}).appendTo($container);
APP.$link = $('<a>', {
'class': LINK_ID,
target: '_blank',
rel: 'noreferrer noopener'
}).appendTo($block).hide();
APP.$linkEdit = $();
if (APP.readOnly) { return; }
var button = h('button.btn.btn-primary', {
title: Messages.clickToEdit
}, Messages.profile_addLink);
APP.$linkEdit = $(button);
$block.append(button);
var save = h('button.btn.btn-success', Messages.settings_save);
var text = h('input');
var code = h('div.cp-app-profile-link-code', [
text,
save
]);
var div = h('div.cp-app-profile-link-edit', [
code
]);
$block.append(div);
$(button).click(function () {
$(text).val(APP.$link.attr('href'));
$(code).show();
APP.editor.refresh();
$(button).hide();
});
$(save).click(function () {
$(save).hide();
APP.module.execCommand('SET', {
key: 'url',
value: $(text).val()
}, function (data) {
APP.updateValues(data);
$(code).hide();
$(button).show();
$(save).show();
});
});
};
var refreshLink = function (data) {
APP.$linkEdit.removeClass('fa-pencil').removeClass('fa');
if (!data.url) {
APP.$linkEdit.text(Messages.profile_addLink);
return void APP.$link.hide();
}
APP.$link.attr('href', data.url).text(data.url).show();
APP.$linkEdit.text('').addClass('fa fa-pencil');
};
var addFriendRequest = function ($container) {
if (!APP.readOnly || !APP.common.isLoggedIn()) { return; }
APP.$friend = $('<button>', {
'class': 'btn btn-success cp-app-profile-friend-request',
});
APP.$friend = $(h('div.cp-app-profile-friend-container'));
$container.append(APP.$friend);
};
var refreshFriendRequest = function (data) {
if (!APP.$friend) { return; }
var me = common.getMetadataMgr().getUserData().curvePublic;
if (data.curvePublic === me) {
APP.$friend.remove();
return;
}
APP.$friend.html('');
var friends = common.getMetadataMgr().getPrivateData().friends;
if (friends[data.curvePublic]) {
APP.$friend.append(h('p.cp-app-profile-friend', Messages._getKey('profile_friend', [data.name || Messages.anonymous])));
return;
}
var $button = $('<button>', {
'class': 'btn btn-success cp-app-profile-friend-request',
}).appendTo(APP.$friend);
// If this curve has sent us a friend request, we should not be able to sent it to them
var friendRequests = common.getFriendRequests();
if (friendRequests[data.curvePublic]) {
$button.html(Messages._getKey('friendRequest_received', [data.name || Messages.anonymous]))
.click(function () {
UIElements.displayFriendRequestModal(common, friendRequests[data.curvePublic]);
});
return;
}
var pendingFriends = APP.common.getPendingFriends(); // Friend requests sent
if (pendingFriends[data.curvePublic]) {
$button.attr('disabled', 'disabled').text(Messages.profile_friendRequestSent);
return;
}
$button.text(Messages._getKey('userlist_addAsFriendTitle', [data.name || Messages.anonymous]))
.click(function () {
APP.common.sendFriendRequest({
curvePublic: data.curvePublic,
notifications: data.notifications
}, function () {
$button.attr('disabled', 'disabled').text(Messages.profile_friendRequestSent);
});
});
};
var AVATAR_SIZE_LIMIT = 0.5;
var allowedMediaTypes = [
'image/png',
'image/jpeg',
'image/jpg',
'image/gif',
];
var transformAvatar = function (file, cb) {
if (file.type === 'image/gif') { return void cb(file); }
var $croppie = $('<div>', {
'class': 'cp-app-profile-resizer'
});
if (typeof ($croppie.croppie) !== "function") {
return void cb(file);
}
var todo = function () {
UI.confirm($croppie[0], function (yes) {
if (!yes) { return; }
$croppie.croppie('result', {
type: 'blob',
size: {width: 300, height: 300}
}).then(function(blob) {
blob.lastModifiedDate = new Date();
blob.name = 'avatar';
cb(blob);
});
});
};
var reader = new FileReader();
reader.onload = function(e) {
$croppie.croppie({
url: e.target.result,
viewport: { width: 100, height: 100 },
boundary: { width: 400, height: 300 },
});
todo();
};
reader.readAsDataURL(file);
};
var displayAvatar = function (val) {
var sframeChan = common.getSframeChannel();
var $span = APP.$avatar;
$span.html('');
if (!val) {
$('<img>', {
src: '/customize/images/avatar.png',
title: Messages.profile_avatar,
alt: 'Avatar'
}).appendTo($span);
return;
}
common.displayAvatar($span, val);
if (APP.readOnly) { return; }
var $delButton = $('<button>', {
'class': 'cp-app-profile-avatar-delete btn btn-danger fa fa-times',
title: Messages.fc_delete
});
$span.append($delButton);
$delButton.click(function () {
var old = common.getMetadataMgr().getUserData().avatar;
APP.module.execCommand("SET", {
key: 'avatar',
value: ""
}, function () {
sframeChan.query("Q_PROFILE_AVATAR_REMOVE", old, function (err, err2) {
if (err || err2) { return void UI.log(err || err2); }
displayAvatar();
});
});
});
};
var addAvatar = function ($container) {
var $block = $('<div>', {id: AVATAR_ID}).appendTo($container);
APP.$avatar = $('<span>').appendTo($block);
var sframeChan = common.getSframeChannel();
displayAvatar();
if (APP.readOnly) { return; }
var fmConfig = {
noHandlers: true,
noStore: true,
body: $('body'),
onUploaded: function (ev, data) {
var old = common.getMetadataMgr().getUserData().avatar;
var todo = function () {
APP.module.execCommand("SET", {
key: 'avatar',
value: data.url
}, function () {
sframeChan.query("Q_PROFILE_AVATAR_ADD", data.url, function (err, err2) {
if (err || err2) { return void UI.log(err || err2); }
displayAvatar(data.url);
});
});
};
if (old) {
sframeChan.query("Q_PROFILE_AVATAR_REMOVE", old, function (err, err2) {
if (err || err2) { return void UI.log(err || err2); }
todo();
});
return;
}
todo();
}
};
APP.FM = common.createFileManager(fmConfig);
var accepted = ".gif,.jpg,.jpeg,.png";
var data = {
FM: APP.FM,
filter: function (file) {
var sizeMB = Util.bytesToMegabytes(file.size);
var type = file.type;
// We can't resize .gif so we have to display an error if it is too big
if (sizeMB > AVATAR_SIZE_LIMIT && type === 'image/gif') {
UI.log(Messages._getKey('profile_uploadSizeError', [
Messages._getKey('formattedMB', [AVATAR_SIZE_LIMIT])
]));
return false;
}
// Display an error if the image type is not allowed
if (allowedMediaTypes.indexOf(type) === -1) {
UI.log(Messages._getKey('profile_uploadTypeError', [
accepted.split(',').join(', ')
]));
return false;
}
return true;
},
transformer: transformAvatar,
accept: accepted
};
var $upButton = common.createButton('upload', false, data);
$upButton.text(Messages.profile_upload);
$upButton.prepend($('<span>', {'class': 'fa fa-upload'}));
$block.append($upButton);
};
var refreshAvatar = function (data) {
displayAvatar(data.avatar);
};
var addDescription = function ($container) {
var $block = $('<div>', {id: DESCRIPTION_ID}).appendTo($container);
APP.$description = $('<div>', {'class': 'cp-app-profile-description-rendered'}).appendTo($block);
APP.$descriptionEdit = $();
if (APP.readOnly) { return; }
var button = h('button.btn.btn-primary', [
h('i.fa.fa-pencil'),
h('span', Messages.profile_addDescription)
]);
APP.$descriptionEdit = $(button);
var save = h('button.btn.btn-primary', Messages.settings_save);
var text = h('textarea');
var code = h('div.cp-app-profile-description-code', [
text,
h('br'),
save
]);
var div = h('div.cp-app-profile-description-edit', [
h('p.cp-app-profile-info', Messages.profile_info),
button,
code
]);
$block.append(div);
var editor = APP.editor = CodeMirror.fromTextArea(text, {
lineNumbers: true,
lineWrapping: true,
styleActiveLine : true,
mode: "markdown",
});
var markdownTb = common.createMarkdownToolbar(editor);
$(code).prepend(markdownTb.toolbar);
$(markdownTb.toolbar).show();
$(button).click(function () {
$(code).show();
APP.editor.refresh();
$(button).hide();
});
$(save).click(function () {
$(save).hide();
APP.module.execCommand('SET', {
key: 'description',
value: editor.getValue()
}, function (data) {
APP.updateValues(data);
$(code).hide();
$(button).show();
$(save).show();
});
});
};
var refreshDescription = function (data) {
var val = Marked(data.description || "");
APP.$description.html(val);
APP.$descriptionEdit.find('span').text(val === "" ? Messages.profile_addDescription : Messages.profile_editDescription);
if (!APP.editor) { return; }
APP.editor.setValue(data.description || "");
APP.editor.save();
};
var createLeftside = function () {
var $categories = $('<div>', {'class': 'cp-sidebarlayout-categories'}).appendTo(APP.$leftside);
var $category = $('<div>', {'class': 'cp-sidebarlayout-category'}).appendTo($categories);
$category.append($('<span>', {'class': 'fa fa-user'}));
$category.addClass('cp-leftside-active');
$category.append(Messages.profileButton);
};
var init = function () {
APP.$container.find('#'+CREATE_ID).remove();
if (!APP.initialized) {
var $header = $('<div>', {id: HEADER_ID}).appendTo(APP.$rightside);
addAvatar($header);
var $rightside = $('<div>', {id: HEADER_RIGHT_ID}).appendTo($header);
addDisplayName($rightside);
addLink($rightside);
addFriendRequest($rightside);
addDescription(APP.$rightside);
addViewButton(APP.$rightside);
APP.initialized = true;
createLeftside();
}
};
var updateValues = APP.updateValues = function (data) {
refreshAvatar(data);
refreshName(data);
refreshLink(data);
refreshDescription(data);
refreshFriendRequest(data);
};
var createToolbar = function () {
var displayed = ['useradmin', 'newpad', 'limit', 'pageTitle', 'notifications'];
var configTb = {
displayed: displayed,
sfCommon: common,
$container: APP.$toolbar,
pageTitle: Messages.profileButton,
metadataMgr: common.getMetadataMgr(),
};
APP.toolbar = Toolbar.create(configTb);
APP.toolbar.$rightside.hide();
};
var onEvent = function (obj) {
var ev = obj.ev;
var data = obj.data;
if (ev === 'UPDATE') {
console.log('Update');
updateValues(data);
return;
}
};
nThen(function (waitFor) {
$(waitFor(UI.addLoadingScreen));
SFCommon.create(waitFor(function (c) { APP.common = common = c; }));
}).nThen(function (waitFor) {
if (AppConfig.disableProfile) {
common.gotoURL('/drive/');
return;
}
APP.$container = $('#cp-sidebarlayout-container');
APP.$toolbar = $('#cp-toolbar');
APP.$leftside = $('<div>', {id: 'cp-sidebarlayout-leftside'}).appendTo(APP.$container);
APP.$rightside = $('<div>', {id: 'cp-sidebarlayout-rightside'}).appendTo(APP.$container);
sFrameChan = common.getSframeChannel();
sFrameChan.onReady(waitFor());
}).nThen(function (/*waitFor*/) {
createToolbar();
var metadataMgr = common.getMetadataMgr();
var privateData = metadataMgr.getPrivateData();
APP.origin = privateData.origin;
APP.readOnly = privateData.readOnly;
// If not logged in, you can only view other users's profile
if (!privateData.readOnly && !common.isLoggedIn()) {
UI.removeLoadingScreen();
var $p = $('<p>', {id: CREATE_ID}).append(Messages.profile_register);
var $a = $('<a>', {
href: APP.origin + '/register/'
});
$('<button>', {
'class': 'btn btn-success',
}).text(Messages.login_register).appendTo($a);
$p.append($('<br>')).append($a);
APP.$rightside.append($p);
return;
}
if (privateData.isOwnProfile) {
APP.module = common.makeUniversal('profile', {
onEvent: onEvent
});
var execCommand = APP.module.execCommand;
init();
console.log('POST SUBSCRIBE');
execCommand('SUBSCRIBE', null, function (obj) {
updateValues(obj);
UI.removeLoadingScreen();
});
return;
}
var listmapConfig = {
data: {},
common: common,
userName: 'profile',
logLevel: 1
};
var lm = APP.lm = Listmap.create(listmapConfig);
init();
lm.proxy.on('ready', function () {
updateValues(lm.proxy);
UI.removeLoadingScreen();
common.mailbox.subscribe({
onMessage: function () {
refreshFriendRequest(lm.proxy);
},
onViewed: function () {
refreshFriendRequest(lm.proxy);
},
});
}).on('change', [], function () {
updateValues(lm.proxy);
});
metadataMgr.onChange(function () {
updateValues(lm.proxy);
});
});
});