define([ 'jquery', '/customize/application_config.js', '/api/config', ], function ($, Config, ApiConfig) { var Messages = {}; var Cryptpad; var Common; var Bar = { constants: {}, }; var SPINNER_DISAPPEAR_TIME = 1000; // Toolbar parts var TOOLBAR_CLS = Bar.constants.toolbar = 'cp-toolbar'; var TOP_CLS = Bar.constants.top = 'cp-toolbar-top'; var LEFTSIDE_CLS = Bar.constants.leftside = 'cp-toolbar-leftside'; var RIGHTSIDE_CLS = Bar.constants.rightside = 'cp-toolbar-rightside'; var DRAWER_CLS = Bar.constants.drawer = 'cp-toolbar-drawer-content'; var HISTORY_CLS = Bar.constants.history = 'cp-toolbar-history'; // Userlist var USERLIST_CLS = Bar.constants.userlist = "cp-toolbar-users"; var EDITSHARE_CLS = Bar.constants.editShare = "cp-toolbar-share-edit"; var VIEWSHARE_CLS = Bar.constants.viewShare = "cp-toolbar-share-view"; var SHARE_CLS = Bar.constants.viewShare = "cp-toolbar-share"; // Top parts var USER_CLS = Bar.constants.userAdmin = "cp-toolbar-user"; var SPINNER_CLS = Bar.constants.spinner = 'cp-toolbar-spinner'; var LIMIT_CLS = Bar.constants.limit = 'cp-toolbar-limit'; var TITLE_CLS = Bar.constants.title = "cp-toolbar-title"; var NEWPAD_CLS = Bar.constants.newpad = "cp-toolbar-new"; var LINK_CLS = Bar.constants.link = "cp-toolbar-link"; // User admin menu var USERADMIN_CLS = Bar.constants.user = 'cp-toolbar-user-dropdown'; var USERNAME_CLS = Bar.constants.username = 'cp-toolbar-user-name'; /*var READONLY_CLS = */Bar.constants.readonly = 'cp-toolbar-readonly'; var USERBUTTON_CLS = Bar.constants.changeUsername = "cp-toolbar-user-rename"; // Create the toolbar element var uid = function () { return 'cp-toolbar-uid-' + String(Math.random()).substring(2); }; var createRealtimeToolbar = function (config) { if (!config.$container) { return; } var $container = config.$container; var $toolbar = $('
', { 'class': TOOLBAR_CLS, id: uid(), }); var $topContainer = $('
', {'class': TOP_CLS}); $('', {'class': 'cp-toolbar-top-filler'}).appendTo($topContainer); var $userContainer = $('', { 'class': USER_CLS }).appendTo($topContainer); $('', {'class': LIMIT_CLS}).hide().appendTo($userContainer); $('', {'class': NEWPAD_CLS + ' cp-dropdown-container'}).hide().appendTo($userContainer); $('', {'class': USERADMIN_CLS + ' cp-dropdown-container'}).hide().appendTo($userContainer); $toolbar.append($topContainer) .append($('
', {'class': LEFTSIDE_CLS})) .append($('
', {'class': RIGHTSIDE_CLS})) .append($('
', {'class': HISTORY_CLS})); var $rightside = $toolbar.find('.'+RIGHTSIDE_CLS); if (!config.hideDrawer) { var $drawerContent = $('
', { 'class': DRAWER_CLS, 'tabindex': 1 }).appendTo($rightside).hide(); var $drawer = Common.createButton('more', true).appendTo($rightside); $drawer.click(function () { $drawerContent.toggle(); $drawer.removeClass('cp-toolbar-button-active'); if ($drawerContent.is(':visible')) { $drawer.addClass('cp-toolbar-button-active'); $drawerContent.focus(); } }); var onBlur = function (e) { if (e.relatedTarget) { if ($(e.relatedTarget).is('.cp-toolbar-drawer-button')) { return; } if ($(e.relatedTarget).parents('.'+DRAWER_CLS).length) { $(e.relatedTarget).blur(onBlur); return; } } $drawer.removeClass('cp-toolbar-button-active'); $drawerContent.hide(); }; $drawerContent.blur(onBlur); } // The 'notitle' class removes the line added for the title with a small screen if (!config.title || typeof config.title !== "object") { $toolbar.addClass('cp-toolbar-notitle'); } $container.prepend($toolbar); $container.on('drop dragover', function (e) { e.preventDefault(); e.stopPropagation(); }); return $toolbar; }; // Userlist elements var getOtherUsers = function(config) { //var userList = config.userList.getUserlist(); var userData = config.metadataMgr.getMetadata().users; var i = 0; // duplicates counter var list = []; // Display only one time each user (if he is connected in multiple tabs) var uids = []; Object.keys(userData).forEach(function(user) { //if (user !== userNetfluxId) { var data = userData[user] || {}; var userId = data.uid; if (!userId) { return; } //data.netfluxId = user; if (uids.indexOf(userId) === -1) {// && (!myUid || userId !== myUid)) { uids.push(userId); list.push(data); } else { i++; } //} }); return { list: list, duplicates: i }; }; var avatars = {}; var updateUserList = function (toolbar, config) { // Make sure the elements are displayed var $userButtons = toolbar.userlist; var $userlistContent = toolbar.userlistContent; var metadataMgr = config.metadataMgr; var userData = metadataMgr.getMetadata().users; var viewers = metadataMgr.getViewers(); var priv = metadataMgr.getPrivateData(); var origin = priv.origin; var friends = priv.friends; var user = metadataMgr.getUserData(); // 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 = config.readOnly === -1 ? userList : arrayIntersect(userList, Object.keys(userData)); // Names of editing users var others = getOtherUsers(config); var editUsersNames = others.list; var duplicates = others.duplicates; // Number of duplicates editUsersNames.sort(function (a, b) { var na = a.name || Messages.anonymous; var nb = b.name || Messages.anonymous; return na.toLowerCase() > nb.toLowerCase(); }); var numberOfEditUsers = Object.keys(userData).length - duplicates; var numberOfViewUsers = viewers; // Update the userlist var $editUsers = $userlistContent.find('.' + USERLIST_CLS).html(''); Cryptpad.clearTooltips(); var $editUsersList = $('
', {'class': 'cp-toolbar-userlist-others'}); // Editors var pendingFriends = Common.getPendingFriends(); editUsersNames.forEach(function (data) { var name = data.name || Messages.anonymous; var $span = $('', {'class': 'cp-avatar'}); var $rightCol = $('', {'class': 'cp-toolbar-userlist-rightcol'}); var $nameSpan = $('', {'class': 'cp-toolbar-userlist-name'}).text(name).appendTo($rightCol); var isMe = data.curvePublic === user.curvePublic; if (Common.isLoggedIn() && data.curvePublic) { if (isMe) { $span.attr('title', Messages._getKey('userlist_thisIsYou', [ name ])); $nameSpan.text(name); } else if (!friends[data.curvePublic]) { if (pendingFriends.indexOf(data.netfluxId) !== -1) { $('', {'class': 'cp-toolbar-userlist-friend'}).text(Messages.userlist_pending) .appendTo($rightCol); } else { $('', { 'class': 'fa fa-user-plus cp-toolbar-userlist-friend', 'title': Messages._getKey('userlist_addAsFriendTitle', [ name ]) }).appendTo($rightCol).click(function (e) { e.stopPropagation(); Common.sendFriendRequest(data.netfluxId); }); } } } if (data.profile) { $span.addClass('cp-userlist-clickable'); $span.click(function () { window.open(origin+'/profile/#' + data.profile); }); } if (data.avatar && avatars[data.avatar]) { $span.append(avatars[data.avatar]); $span.append($rightCol); } else { Common.displayAvatar(Common, $span, data.avatar, name, function ($img) { if (data.avatar && $img) { avatars[data.avatar] = $img[0].outerHTML; } $span.append($rightCol); }); } $span.data('uid', data.uid); $editUsersList.append($span); }); $editUsers.append($editUsersList); // Viewers if (numberOfViewUsers > 0) { var viewText = '
'; var viewerText = numberOfViewUsers !== 1 ? Messages.viewers : Messages.viewer; viewText += numberOfViewUsers + ' ' + viewerText + '
'; $editUsers.append(viewText); } // Update the buttons var fa_editusers = ''; var fa_viewusers = ''; var $spansmall = $('').html(fa_editusers + ' ' + numberOfEditUsers + '   ' + fa_viewusers + ' ' + numberOfViewUsers); $userButtons.find('.cp-dropdown-button-title').html('').append($spansmall); }; var initUserList = function (toolbar, config) { // TODO clean comments if (config.metadataMgr) { /* && config.userList.list && config.userList.userNetfluxId) {*/ //var userList = config.userList.list; //userList.change.push var metadataMgr = config.metadataMgr; metadataMgr.onChange(function () { if (metadataMgr.isConnected()) {toolbar.connected = true;} if (!toolbar.connected) { return; } //if (config.userList.data) { updateUserList(toolbar, config); //} }); } }; // Create sub-elements var createUserList = function (toolbar, config) { if (!config.metadataMgr) { throw new Error("You must provide a `metadataMgr` to display the userlist"); } var $content = $('
', {'class': 'cp-toolbar-userlist-drawer'}); $content.on('drop dragover', function (e) { e.preventDefault(); e.stopPropagation(); }); var $closeIcon = $('', {"class": "fa fa-window-close cp-toolbar-userlist-drawer-close"}).appendTo($content); $('

').text(Messages.users).appendTo($content); $('

', {'class': USERLIST_CLS}).appendTo($content); toolbar.userlistContent = $content; var $container = $('', {id: 'cp-toolbar-userlist-drawer-open', title: Messages.userListButton}); var $button = $('