cryptpad/www/common/toolbar.js

1551 lines
58 KiB
JavaScript
Raw Normal View History

2017-08-17 12:55:44 +00:00
define([
'jquery',
'/customize/application_config.js',
'/api/config',
2021-03-30 15:41:12 +00:00
'/api/broadcast',
'/common/common-ui-elements.js',
2017-11-13 15:32:40 +00:00
'/common/common-interface.js',
'/common/common-hash.js',
'/common/common-util.js',
2017-11-23 11:28:49 +00:00
'/common/common-feedback.js',
'/common/inner/common-mediatag.js',
2019-05-17 14:19:41 +00:00
'/common/hyperscript.js',
'/common/messenger-ui.js',
2017-11-13 15:32:40 +00:00
'/customize/messages.js',
'/customize/pages.js',
2021-03-30 15:41:12 +00:00
], function ($, Config, ApiConfig, Broadcast, UIElements, UI, Hash, Util, Feedback, MT, h,
MessengerUI, Messages, Pages) {
2017-08-17 16:28:05 +00:00
var Common;
2017-08-17 12:55:44 +00:00
var Bar = {
constants: {},
};
var SPINNER_DISAPPEAR_TIME = 1000;
// Toolbar parts
2017-09-04 13:09:54 +00:00
var TOOLBAR_CLS = Bar.constants.toolbar = 'cp-toolbar';
var TOP_CLS = Bar.constants.top = 'cp-toolbar-top';
2020-05-07 12:58:27 +00:00
var BOTTOM_CLS = Bar.constants.bottom = 'cp-toolbar-bottom';
var BOTTOM_LEFT_CLS = Bar.constants.bottomL = 'cp-toolbar-bottom-left';
var BOTTOM_MID_CLS = Bar.constants.bottomM = 'cp-toolbar-bottom-mid';
var BOTTOM_RIGHT_CLS = Bar.constants.bottomR = 'cp-toolbar-bottom-right';
2017-09-04 13:09:54 +00:00
var LEFTSIDE_CLS = Bar.constants.leftside = 'cp-toolbar-leftside';
var RIGHTSIDE_CLS = Bar.constants.rightside = 'cp-toolbar-rightside';
2020-05-07 16:16:36 +00:00
var FILE_CLS = Bar.constants.file = 'cp-toolbar-file';
2017-09-04 13:09:54 +00:00
var DRAWER_CLS = Bar.constants.drawer = 'cp-toolbar-drawer-content';
var HISTORY_CLS = Bar.constants.history = 'cp-toolbar-history';
2020-09-25 14:38:42 +00:00
var SNAPSHOTS_CLS = Bar.constants.history = 'cp-toolbar-snapshots';
2017-08-17 12:55:44 +00:00
// Userlist
2017-09-04 13:09:54 +00:00
var USERLIST_CLS = Bar.constants.userlist = "cp-toolbar-users";
2017-08-17 12:55:44 +00:00
// Top parts
2017-09-04 13:09:54 +00:00
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 LINK_CLS = Bar.constants.link = "cp-toolbar-link";
2019-05-16 14:09:42 +00:00
var NOTIFICATIONS_CLS = Bar.constants.user = 'cp-toolbar-notifications';
2021-03-30 15:41:12 +00:00
var MAINTENANCE_CLS = Bar.constants.user = 'cp-toolbar-maintenance';
2017-08-17 12:55:44 +00:00
// User admin menu
2017-09-04 13:09:54 +00:00
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";
2017-08-17 12:55:44 +00:00
// Create the toolbar element
var uid = function () {
2017-09-04 13:09:54 +00:00
return 'cp-toolbar-uid-' + String(Math.random()).substring(2);
2017-08-17 12:55:44 +00:00
};
var createRealtimeToolbar = function (config) {
if (!config.$container) { return; }
var $container = config.$container;
var isEmbed = Bar.isEmbed = config.metadataMgr.getPrivateData().isEmbed;
if (isEmbed) {
$container.hide();
}
2017-08-17 12:55:44 +00:00
var $toolbar = $('<div>', {
'class': TOOLBAR_CLS,
id: uid(),
});
var $topContainer = $('<div>', {'class': TOP_CLS});
2017-09-04 13:09:54 +00:00
$('<span>', {'class': 'cp-toolbar-top-filler'}).appendTo($topContainer);
2017-08-17 12:55:44 +00:00
var $userContainer = $('<span>', {
'class': USER_CLS
}).appendTo($topContainer);
$('<span>', {'class': LIMIT_CLS}).hide().appendTo($userContainer);
2021-03-30 15:41:12 +00:00
$('<span>', {'class': MAINTENANCE_CLS + ' cp-dropdown-container'}).hide().appendTo($userContainer);
2019-05-16 14:09:42 +00:00
$('<span>', {'class': NOTIFICATIONS_CLS + ' cp-dropdown-container'}).hide().appendTo($userContainer);
2017-09-04 13:09:54 +00:00
$('<span>', {'class': USERADMIN_CLS + ' cp-dropdown-container'}).hide().appendTo($userContainer);
2017-08-17 12:55:44 +00:00
2020-05-07 12:58:27 +00:00
$toolbar.append($topContainer);
var $bottom = $(h('div.'+BOTTOM_CLS, [
h('div.'+BOTTOM_LEFT_CLS),
h('div.'+BOTTOM_MID_CLS),
h('div.'+BOTTOM_RIGHT_CLS)
])).appendTo($toolbar);
$toolbar.append(h('div.'+HISTORY_CLS));
2020-09-25 14:38:42 +00:00
$toolbar.append(h('div.'+SNAPSHOTS_CLS));
2017-08-17 12:55:44 +00:00
2020-05-07 13:36:24 +00:00
var $file = $toolbar.find('.'+BOTTOM_LEFT_CLS);
2017-08-17 12:55:44 +00:00
if (!config.hideDrawer) {
2020-05-07 16:16:36 +00:00
var $drawer = $(h('button.' + FILE_CLS, [
h('i.fa.fa-file-o'),
h('span.cp-button-name', Messages.toolbar_file)
])).appendTo($file).hide();
2017-08-17 12:55:44 +00:00
var $drawerContent = $('<div>', {
2017-09-04 13:09:54 +00:00
'class': DRAWER_CLS,
2017-08-17 12:55:44 +00:00
'tabindex': 1
2020-05-26 16:51:37 +00:00
}).hide();
UI.createDrawer($drawer, $drawerContent);
2017-08-21 13:20:38 +00:00
}
2017-08-17 12:55:44 +00:00
// The 'notitle' class removes the line added for the title with a small screen
if (!config.title || typeof config.title !== "object") {
2017-09-04 13:09:54 +00:00
$toolbar.addClass('cp-toolbar-notitle');
2017-08-17 12:55:44 +00:00
}
$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();
2017-08-18 08:47:30 +00:00
var userData = config.metadataMgr.getMetadata().users;
2017-08-17 12:55:44 +00:00
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) {
2017-08-17 12:55:44 +00:00
//if (user !== userNetfluxId) {
var data = userData[user] || {};
var userId = data.uid;
if (!userId) { return; }
//data.netfluxId = user;
2017-08-17 12:55:44 +00:00
if (uids.indexOf(userId) === -1) {// && (!myUid || userId !== myUid)) {
uids.push(userId);
list.push(data);
} else { i++; }
//}
});
return {
list: list,
duplicates: i
};
};
var editingUserName = {
state: false
};
var setDisplayName = function (newName) {
Common.setDisplayName(newName, function (err) {
if (err) {
console.log("Couldn't set username");
console.error(err);
return;
}
});
};
var showColors = false;
2020-03-06 11:55:20 +00:00
var updateUserList = function (toolbar, config, forceOffline) {
2019-05-23 14:09:04 +00:00
if (!config.displayed || config.displayed.indexOf('userlist') === -1) { return; }
if (toolbar.isAlone) { return; }
2017-08-17 12:55:44 +00:00
// Make sure the elements are displayed
var $userButtons = toolbar.userlist;
var $userlistContent = toolbar.userlistContent;
2017-08-18 08:47:30 +00:00
var metadataMgr = config.metadataMgr;
2020-03-06 11:55:20 +00:00
var online = !forceOffline && metadataMgr.isConnected();
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();
2017-08-17 12:55:44 +00:00
// 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));
2017-08-17 12:55:44 +00:00
// 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;
2017-08-17 12:55:44 +00:00
// If the user was changing his username, do not reste the input, store the current value
// and cursor
if (editingUserName.state) {
var $input = $userlistContent.find('.cp-toolbar-userlist-name-input');
editingUserName.value = $input.val();
editingUserName.select = [$input[0].selectionStart, $input[0].selectionEnd];
}
2017-08-17 12:55:44 +00:00
// Update the userlist
var $editUsers = $userlistContent.find('.' + USERLIST_CLS).html('');
var $editUsersList = $('<div>', {'class': 'cp-toolbar-userlist-others'})
.appendTo($editUsers);
var degradedLimit = Config.degradedLimit || 8;
if (toolbar.isDeleted) {
$('<em>').text(Messages.deletedFromServer).appendTo($editUsersList);
numberOfEditUsers = '?';
numberOfViewUsers = '?';
} else if (!online) {
$('<em>').text(Messages.userlist_offline).appendTo($editUsersList);
numberOfEditUsers = '?';
numberOfViewUsers = '?';
2021-03-04 17:43:40 +00:00
} else if (metadataMgr.isDegraded() === true) {
numberOfEditUsers = Math.max(metadataMgr.getChannelMembers().length - 1, 0);
numberOfViewUsers = '';
$('<em>').text(Messages._getKey('toolbar_degraded', [degradedLimit])).appendTo($editUsersList);
}
// Update the buttons
var fa_editusers = '<span class="fa fa-users"></span>';
var fa_viewusers = numberOfViewUsers === '' ? '' : '<span class="fa fa-eye"></span>';
var $spansmall = $('<span>').html(fa_editusers + ' ' + numberOfEditUsers + '&nbsp;&nbsp; ' + fa_viewusers + ' ' + numberOfViewUsers);
$userButtons.find('.cp-dropdown-button-title').html('').append($spansmall);
if (!online || toolbar.isDeleted) { return; }
2021-03-04 17:43:40 +00:00
if (metadataMgr.isDegraded() === true) { return; }
// Display the userlist
2017-08-17 12:55:44 +00:00
// Editors
2019-05-21 16:43:11 +00:00
var pendingFriends = Common.getPendingFriends(); // Friend requests sent
var friendRequests = Common.getFriendRequests(); // Friend requests received
2017-08-17 12:55:44 +00:00
editUsersNames.forEach(function (data) {
var name = data.name || Messages.anonymous;
2017-09-04 13:09:54 +00:00
var $span = $('<span>', {'class': 'cp-avatar'});
if (data.color && showColors) {
2018-12-06 10:54:34 +00:00
$span.css('border-color', data.color);
}
2017-09-04 13:09:54 +00:00
var $rightCol = $('<span>', {'class': 'cp-toolbar-userlist-rightcol'});
2018-09-14 13:42:41 +00:00
var $nameSpan = $('<span>', {'class': 'cp-toolbar-userlist-name'}).appendTo($rightCol);
var $nameValue = $('<span>', {
'class': 'cp-toolbar-userlist-name-value'
}).text(name).appendTo($nameSpan);
var isMe = data.uid === user.uid;
if (isMe && !priv.readOnly) {
2018-01-23 13:24:40 +00:00
if (!Config.disableProfile) {
var $button = $('<button>', {
2018-09-14 13:42:41 +00:00
'class': 'fa fa-pencil cp-toolbar-userlist-button',
2018-01-23 13:24:40 +00:00
title: Messages.user_rename
}).appendTo($nameSpan);
$button.hover(function (e) { e.preventDefault(); e.stopPropagation(); });
$button.mouseenter(function (e) {
e.preventDefault();
e.stopPropagation();
window.setTimeout(function () {
$button.parents().mouseleave();
});
});
2018-01-23 13:24:40 +00:00
var $nameInput = $('<input>', {
'class': 'cp-toolbar-userlist-name-input'
}).val(name).appendTo($rightCol);
$button.click(function (e) {
e.stopPropagation();
$nameSpan.hide();
$nameInput.show().focus().select();
editingUserName.state = true;
editingUserName.oldName = $nameInput.val();
});
$nameInput.click(function (e) {
e.stopPropagation();
});
$nameInput.on('keydown', function (e) {
if (e.which === 13 || e.which === 27) {
$nameInput.hide();
$nameSpan.show();
$button.show();
editingUserName.state = false;
}
if (e.which === 13) {
var newName = $nameInput.val(); // TODO clean
$nameValue.text(newName);
setDisplayName(newName);
return;
}
if (e.which === 27) {
$nameValue.text(editingUserName.oldName);
return;
}
});
if (editingUserName.state) {
$button.click();
$nameInput.val(editingUserName.value);
$nameInput[0].setSelectionRange(editingUserName.select[0],
editingUserName.select[1]);
setTimeout(function () { $nameInput.focus(); });
2017-08-17 12:55:44 +00:00
}
}
} else if (Common.isLoggedIn() && data.curvePublic && !friends[data.curvePublic]
&& !priv.readOnly) {
2020-12-09 13:54:22 +00:00
if (pendingFriends[data.curvePublic]) {
2019-05-28 12:38:13 +00:00
$('<button>', {
'class': 'fa fa-hourglass-half cp-toolbar-userlist-button',
'title': Messages.profile_friendRequestSent
}).appendTo($nameSpan);
2019-05-21 16:43:11 +00:00
} else if (friendRequests[data.curvePublic]) {
$('<button>', {
'class': 'fa fa-bell cp-toolbar-userlist-button',
2020-04-29 10:30:59 +00:00
'data-cptippy-html': true,
'title': Messages._getKey('friendRequest_received', [Util.fixHTML(name)]),
2019-05-21 16:43:11 +00:00
}).appendTo($nameSpan).click(function (e) {
e.stopPropagation();
UIElements.displayFriendRequestModal(Common, friendRequests[data.curvePublic]);
});
} else {
2018-09-14 13:42:41 +00:00
$('<button>', {
'class': 'fa fa-user-plus cp-toolbar-userlist-button',
2020-04-29 10:30:59 +00:00
'data-cptippy-html': true,
'title': Messages._getKey('userlist_addAsFriendTitle', [
2020-04-29 10:30:59 +00:00
Util.fixHTML(name)
])
2018-09-14 13:42:41 +00:00
}).appendTo($nameSpan).click(function (e) {
e.stopPropagation();
2019-05-21 16:43:11 +00:00
Common.sendFriendRequest(data, function (err, obj) {
2020-12-09 13:54:22 +00:00
if (err || (obj && obj.error)) {
UI.warn(Messages.error);
return void console.error(err || obj.error);
}
2019-05-21 16:43:11 +00:00
});
});
2017-08-17 12:55:44 +00:00
}
2018-09-14 13:42:41 +00:00
} else if (Common.isLoggedIn() && data.curvePublic && friends[data.curvePublic]) {
$('<button>', {
'class': 'fa fa-comments-o cp-toolbar-userlist-button',
2020-04-29 10:30:59 +00:00
'title': Messages.contact_chat
2018-09-14 13:42:41 +00:00
}).appendTo($nameSpan).click(function (e) {
e.stopPropagation();
Common.openURL('/contacts/');
});
}
2017-08-17 12:55:44 +00:00
if (data.profile) {
// XXX title to visit their profile "Visit {0}'s profile"
// Messages.contacts_info3 "Double-click their icon to view their profile",
2017-09-04 13:09:54 +00:00
$span.addClass('cp-userlist-clickable');
2017-08-17 12:55:44 +00:00
$span.click(function () {
Common.openURL(origin+'/profile/#' + data.profile);
2017-08-17 12:55:44 +00:00
});
}
Common.displayAvatar($span, data.avatar, name, function () {
2017-08-17 12:55:44 +00:00
$span.append($rightCol);
}, data.uid);
2017-08-17 12:55:44 +00:00
$span.data('uid', data.uid);
$editUsersList.append($span);
});
// Viewers
if (numberOfViewUsers > 0) {
2017-09-04 13:09:54 +00:00
var viewText = '<div class="cp-toolbar-userlist-viewer">';
2017-08-17 12:55:44 +00:00
var viewerText = numberOfViewUsers !== 1 ? Messages.viewers : Messages.viewer;
viewText += numberOfViewUsers + ' ' + viewerText + '</div>';
$editUsers.append(viewText);
}
};
var initUserList = function (toolbar, config) {
if (config.metadataMgr) {
2017-08-18 08:47:30 +00:00
var metadataMgr = config.metadataMgr;
2017-08-17 12:55:44 +00:00
metadataMgr.onChange(function () {
if (metadataMgr.isConnected()) {toolbar.connected = true;}
2017-08-17 12:55:44 +00:00
if (!toolbar.connected) { return; }
updateUserList(toolbar, config);
2017-08-17 12:55:44 +00:00
});
2020-11-06 16:13:41 +00:00
setTimeout(function () {
updateUserList(toolbar, config, true);
});
2017-08-17 12:55:44 +00:00
}
};
// Create sub-elements
var createUserList = function (toolbar, config) {
if (!config.metadataMgr) {
2017-08-18 08:47:30 +00:00
throw new Error("You must provide a `metadataMgr` to display the userlist");
2017-08-17 12:55:44 +00:00
}
2017-09-04 13:09:54 +00:00
var $content = $('<div>', {'class': 'cp-toolbar-userlist-drawer'});
2017-08-17 12:55:44 +00:00
$content.on('drop dragover', function (e) {
e.preventDefault();
e.stopPropagation();
});
//var $closeIcon = $('<span>', {"class": "fa fa-times cp-toolbar-userlist-drawer-close"}).appendTo($content);
2017-08-17 12:55:44 +00:00
$('<h2>').text(Messages.users).appendTo($content);
$('<p>', {'class': USERLIST_CLS}).appendTo($content);
toolbar.userlistContent = $content;
2017-09-04 13:09:54 +00:00
var $container = $('<span>', {id: 'cp-toolbar-userlist-drawer-open', title: Messages.userListButton});
2017-08-17 12:55:44 +00:00
var $button = $('<button>').appendTo($container);
2017-09-04 13:09:54 +00:00
$('<span>',{'class': 'cp-dropdown-button-title'}).appendTo($button);
2017-08-17 12:55:44 +00:00
2020-05-07 12:58:27 +00:00
toolbar.$bottomR.prepend($container);
2017-08-17 12:55:44 +00:00
if (config.$contentContainer) {
config.$contentContainer.prepend($content);
}
var hide = function () {
$content.hide();
2017-09-04 13:09:54 +00:00
$button.removeClass('cp-toolbar-button-active');
2017-08-17 12:55:44 +00:00
};
var show = function () {
if (Bar.isEmbed) { $content.hide(); return; }
2017-08-17 12:55:44 +00:00
$content.show();
2017-09-04 13:09:54 +00:00
$button.addClass('cp-toolbar-button-active');
2017-08-17 12:55:44 +00:00
};
/*
2017-08-17 12:55:44 +00:00
$closeIcon.click(function () {
Common.setAttribute(['toolbar', 'userlist-drawer'], false);
2017-08-17 12:55:44 +00:00
hide();
});
*/
2017-08-17 12:55:44 +00:00
$button.click(function () {
var visible = $content.is(':visible');
if (visible) { hide(); }
else { show(); }
visible = !visible;
Common.setAttribute(['toolbar', 'userlist-drawer'], visible);
2017-11-23 11:28:49 +00:00
Feedback.send(visible?'USERLIST_SHOW': 'USERLIST_HIDE');
2017-08-17 12:55:44 +00:00
});
2017-08-18 09:07:42 +00:00
show();
Common.getAttribute(['toolbar', 'userlist-drawer'], function (err, val) {
2019-04-02 12:19:00 +00:00
if (val === false || window.innerWidth < 800) {
2018-03-19 15:27:33 +00:00
return void hide();
}
2017-08-17 12:55:44 +00:00
show();
});
2017-08-17 12:55:44 +00:00
2017-09-12 16:40:11 +00:00
initUserList(toolbar, config);
2017-08-17 12:55:44 +00:00
return $container;
};
2021-07-16 09:29:27 +00:00
createCollapse = function (toolbar) {
var up = h('i.fa.fa-chevron-up', {title: Messages.ui_collapse});
var down = h('i.fa.fa-chevron-down', {title: Messages.ui_expand});
var $button = $(h('button.cp-toolbar-collapse',[
up,
down
2021-07-16 09:29:27 +00:00
]));
var $up = $(up);
var $down = $(down);
2021-08-03 10:49:50 +00:00
toolbar.$bottomR.prepend($button);
$down.hide();
2021-07-16 09:29:27 +00:00
$button.click(function () {
toolbar.$top.toggleClass('toolbar-hidden');
2021-08-03 10:49:50 +00:00
var hidden = toolbar.$top.hasClass('toolbar-hidden');
$button.toggleClass('cp-toolbar-button-active');
if (hidden) {
$up.hide();
$down.show();
} else {
$up.show();
$down.hide();
}
2021-07-16 09:29:27 +00:00
});
};
2018-09-06 16:45:53 +00:00
var initChat = function (toolbar) {
2018-09-10 11:20:01 +00:00
var $container = $('<div>', {
id: 'cp-app-contacts-container',
'class': 'cp-app-contacts-inapp'
}).prependTo(toolbar.chatContent);
MessengerUI.create($container, Common, toolbar);
};
var createChat = function (toolbar, config) {
if (!config.metadataMgr) {
throw new Error("You must provide a `metadataMgr` to display the chat");
}
if (Config.availablePadTypes.indexOf('contacts') === -1) { return; }
var $content = $('<div>', {'class': 'cp-toolbar-chat-drawer'});
$content.on('drop dragover', function (e) {
e.preventDefault();
e.stopPropagation();
});
//var $closeIcon = $('<span>', {"class": "fa fa-times cp-toolbar-chat-drawer-close"}).appendTo($content);
//$('<h2>').text(Messages.users).appendTo($content);
//$('<p>', {'class': USERLIST_CLS}).appendTo($content);
toolbar.chatContent = $content;
2020-05-07 13:26:12 +00:00
var $container = $('<span>', {id: 'cp-toolbar-chat-drawer-open'});
2020-05-07 13:26:12 +00:00
var $button = $(h('button', [
h('i.fa.fa-comments'),
h('span.cp-button-name', Messages.chatButton)
])).appendTo($container);
2020-05-07 12:58:27 +00:00
toolbar.$bottomR.prepend($container);
if (config.$contentContainer) {
config.$contentContainer.prepend($content);
}
var hide = function (closed) {
if (!closed) {
// It means it's the initial state so we're going to make the icon blink
$button.addClass('cp-toolbar-notification');
}
$content.hide();
$button.removeClass('cp-toolbar-button-active');
2018-09-12 09:55:26 +00:00
config.$contentContainer.removeClass('cp-chat-visible');
};
var show = function () {
if (Bar.isEmbed) { $content.hide(); return; }
$content.show();
// scroll down chat
var $messagebox = $content.find('.cp-app-contacts-messages');
if ($messagebox.length) {
$messagebox.scrollTop($messagebox[0].scrollHeight);
}
$button.addClass('cp-toolbar-button-active');
2018-09-12 09:55:26 +00:00
config.$contentContainer.addClass('cp-chat-visible');
$button.removeClass('cp-toolbar-notification');
};
/*
$closeIcon.click(function () {
Common.setAttribute(['toolbar', 'chat-drawer'], false);
hide(true);
});
*/
$button.click(function () {
var visible = $content.is(':visible');
if (visible) { hide(true); }
else { show(); }
visible = !visible;
Common.setAttribute(['toolbar', 'chat-drawer'], visible);
});
show();
Common.getAttribute(['toolbar', 'chat-drawer'], function (err, val) {
if (!val || Util.isSmallScreen()) {
return void hide(val === false);
}
show();
});
initChat(toolbar);
return $container;
};
2017-08-17 12:55:44 +00:00
var createShare = function (toolbar, config) {
if (!config.metadataMgr) {
2020-05-07 13:26:12 +00:00
throw new Error("You must provide a `metadataMgr` to display the share button");
2017-08-17 12:55:44 +00:00
}
2017-08-18 16:43:04 +00:00
2020-05-07 13:26:12 +00:00
var $shareBlock = $(h('button.cp-toolar-share-button', [
h('i.fa.fa-shhare-alt'),
h('span.cp-button-name', Messages.shareButton)
]));
2019-05-29 17:00:20 +00:00
Common.getSframeChannel().event('EV_SHARE_OPEN', {
hidden: true
});
$shareBlock.click(function () {
if (toolbar.isDeleted) {
return void UI.warn(Messages.deletedFromServer);
}
var privateData = config.metadataMgr.getPrivateData();
2019-07-04 13:51:29 +00:00
var title = (config.title && config.title.getTitle && config.title.getTitle())
|| (config.title && config.title.defaultName)
|| "";
Common.getSframeChannel().event('EV_SHARE_OPEN', {
title: title,
auditorHash: privateData.form_auditorHash
});
2018-01-17 17:39:45 +00:00
});
2017-08-17 12:55:44 +00:00
2020-05-07 13:26:12 +00:00
toolbar.$bottomM.append($shareBlock);
toolbar.share = $shareBlock;
2017-08-17 12:55:44 +00:00
return "Loading share button";
};
2020-05-07 13:26:12 +00:00
var createAccess = function (toolbar, config) {
if (!config.metadataMgr) {
throw new Error("You must provide a `metadataMgr` to display the access button");
}
var $accessBlock = $(h('button.cp-toolar-access-button', [
h('i.fa.fa-unlock-alt'),
h('span.cp-button-name', Messages.accessButton)
]));
$accessBlock.click(function () {
if (toolbar.isDeleted) {
return void UI.warn(Messages.deletedFromServer);
}
var title = (config.title && config.title.getTitle && config.title.getTitle())
|| (config.title && config.title.defaultName)
|| "";
Common.getSframeChannel().event('EV_ACCESS_OPEN', {
title: title
});
2020-05-07 13:26:12 +00:00
});
toolbar.$bottomM.append($accessBlock);
toolbar.access = $accessBlock;
return "Loading access button";
};
2017-08-17 12:55:44 +00:00
2017-09-12 16:40:11 +00:00
var createFileShare = function (toolbar, config) {
if (!config.metadataMgr) {
throw new Error("You must provide a `metadataMgr` to display the userlist");
2017-08-17 12:55:44 +00:00
}
2017-09-12 16:40:11 +00:00
2020-05-15 10:02:27 +00:00
var $shareBlock = $(h('button.cp-toolar-share-button', [
h('i.fa.fa-shhare-alt'),
h('span.cp-button-name', Messages.shareButton)
]));
2019-05-29 17:00:20 +00:00
Common.getSframeChannel().event('EV_SHARE_OPEN', {
hidden: true,
file: true
});
2018-01-17 17:39:45 +00:00
$shareBlock.click(function () {
2019-07-04 13:51:29 +00:00
var title = (config.title && config.title.getTitle && config.title.getTitle())
|| "";
2019-05-29 17:00:20 +00:00
Common.getSframeChannel().event('EV_SHARE_OPEN', {
2019-07-04 13:51:29 +00:00
title: title,
2019-05-29 17:00:20 +00:00
file: true
});
2017-09-12 16:40:11 +00:00
});
2017-08-17 12:55:44 +00:00
2020-05-07 13:26:12 +00:00
toolbar.$bottomM.append($shareBlock);
2017-09-12 16:40:11 +00:00
return $shareBlock;
2017-08-17 12:55:44 +00:00
};
/*
2019-07-11 12:16:04 +00:00
var createRequest = function (toolbar, config) {
if (!config.metadataMgr) {
throw new Error("You must provide a `metadataMgr` to display the request access button");
}
// We can only requets more access if we're in read-only mode
if (config.readOnly !== 1) { return; }
var $requestBlock = $('<button>', {
'class': 'fa fa-lock cp-toolbar-share-button',
2019-07-16 15:29:55 +00:00
title: Messages.requestEdit_button
2019-07-11 12:16:04 +00:00
}).hide();
// If we have access to the owner's mailbox, display the button and enable it
2019-07-13 09:47:58 +00:00
// false => check if we can contact the owner
// true ==> send the request
Common.getSframeChannel().query('Q_REQUEST_ACCESS', {send:false}, function (err, obj) {
2019-07-11 12:16:04 +00:00
if (obj && obj.state) {
2019-07-16 15:29:55 +00:00
var locked = false;
2019-07-11 12:16:04 +00:00
$requestBlock.show().click(function () {
2019-07-16 15:29:55 +00:00
if (locked) { return; }
locked = true;
Common.getSframeChannel().query('Q_REQUEST_ACCESS', {send:true}, function (err, obj) {
2019-07-11 12:16:04 +00:00
if (obj && obj.state) {
2019-07-16 15:29:55 +00:00
UI.log(Messages.requestEdit_sent);
$requestBlock.hide();
} else {
locked = false;
2019-07-11 12:16:04 +00:00
}
});
});
}
});
toolbar.$leftside.append($requestBlock);
toolbar.request = $requestBlock;
return $requestBlock;
};
*/
2019-07-11 12:16:04 +00:00
2017-08-17 12:55:44 +00:00
var createTitle = function (toolbar, config) {
var $titleContainer = $('<span>', {
'class': TITLE_CLS
}).appendTo(toolbar.$top);
2017-09-04 13:09:54 +00:00
var $hoverable = $('<span>', {'class': 'cp-toolbar-title-hoverable'}).appendTo($titleContainer);
2017-08-17 12:55:44 +00:00
if (typeof config.title !== "object") {
console.error("config.title", config);
throw new Error("config.title is not an object");
}
2017-08-17 17:01:03 +00:00
var updateTitle = config.title.updateTitle;
2017-08-17 12:55:44 +00:00
var placeholder = config.title.defaultName;
var suggestName = config.title.suggestName;
// Buttons
var $text = $('<span>', {
2017-09-04 13:09:54 +00:00
'class': 'cp-toolbar-title-value'
2017-08-17 12:55:44 +00:00
}).appendTo($hoverable);
var $pencilIcon = $('<span>', {
2017-09-04 13:09:54 +00:00
'class': 'cp-toolbar-title-edit',
2017-08-17 12:55:44 +00:00
'title': Messages.clickToEdit
});
var $saveIcon = $('<span>', {
2017-09-04 13:09:54 +00:00
'class': 'cp-toolbar-title-save',
2017-08-17 12:55:44 +00:00
'title': Messages.saveTitle
}).hide();
if (config.readOnly === 1) {
2020-05-13 12:42:22 +00:00
$hoverable.append($('<span>', {'class': 'cp-toolbar-title-readonly'})
2017-08-17 12:55:44 +00:00
.text('('+Messages.readonly+')'));
2017-11-13 15:32:40 +00:00
return $titleContainer;
2017-08-17 12:55:44 +00:00
}
$hoverable.append($('<span>', {'class': 'cp-toolbar-title-readonly cp-toolbar-title-unsync'})
.text('('+Messages.readonly+')'));
2017-08-17 12:55:44 +00:00
var $input = $('<input>', {
type: 'text',
placeholder: placeholder
}).appendTo($hoverable).hide();
if (config.readOnly !== 1) {
$text.attr("title", Messages.clickToEdit);
2017-09-04 13:09:54 +00:00
$text.addClass("cp-toolbar-title-editable");
2017-08-17 12:55:44 +00:00
var $icon = $('<span>', {
2017-09-04 13:09:54 +00:00
'class': 'fa fa-pencil cp-toolbar-title-icon-readonly',
2017-08-17 12:55:44 +00:00
style: 'font-family: FontAwesome;'
});
$pencilIcon.append($icon).appendTo($hoverable);
var $icon2 = $('<span>', {
2017-09-04 13:09:54 +00:00
'class': 'fa fa-check cp-toolbar-title-icon-readonly',
2017-08-17 12:55:44 +00:00
style: 'font-family: FontAwesome;'
});
$saveIcon.append($icon2).appendTo($hoverable);
}
// Events
$input.on('mousedown', function (e) {
if (!$input.is(":focus")) {
$input.focus();
}
e.stopPropagation();
return true;
});
var save = function () {
2020-09-24 15:03:19 +00:00
if (toolbar.history) { return; }
2017-08-17 12:55:44 +00:00
var name = $input.val().trim();
if (name === "") {
name = $input.attr('placeholder');
}
2017-08-23 09:04:44 +00:00
updateTitle(name, function (err/*, newtitle*/) {
2017-08-17 12:55:44 +00:00
if (err) { return console.error(err); }
2017-08-17 17:01:03 +00:00
//$text.text(newtitle);
2017-08-17 12:55:44 +00:00
$input.hide();
$text.show();
$pencilIcon.show();
$saveIcon.hide();
});
};
$input.on('keyup', function (e) {
if (e.which === 13 && toolbar.connected === true) {
save();
} else if (e.which === 27) {
$input.hide();
$text.show();
$pencilIcon.show();
$saveIcon.hide();
//$pencilIcon.css('display', '');
} else if (e.which === 32) {
e.stopPropagation();
}
});
$saveIcon.click(save);
var displayInput = function () {
if (toolbar.connected === false) { return; }
2020-09-24 15:03:19 +00:00
if (toolbar.history) { return; }
2020-07-01 11:30:03 +00:00
$input.width(Math.max(($text.width() + 10), 300)+'px');
2017-08-17 12:55:44 +00:00
$text.hide();
//$pencilIcon.css('display', 'none');
var inputVal = suggestName() || "";
$input.val(inputVal);
$input.show();
$input.focus();
$pencilIcon.hide();
$saveIcon.show();
};
$text.on('click', displayInput);
$pencilIcon.on('click', displayInput);
return $titleContainer;
};
var createUnpinnedWarning0 = function (toolbar, config) {
if (true) { return; } // stub this call since it won't make it into the next release
if (Common.isLoggedIn()) { return; }
var pd = config.metadataMgr.getPrivateData();
var o = pd.origin;
2018-04-27 15:23:23 +00:00
var cid = pd.channel;
Common.sendAnonRpcMsg('IS_CHANNEL_PINNED', cid, function (x) {
if (x.error || !Array.isArray(x.response)) { return void console.log(x); }
if (x.response[0] === true) {
$('.cp-pad-not-pinned').remove();
return;
}
if (typeof(ApiConfig.inactiveTime) !== 'number') {
$('.cp-pad-not-pinned').remove();
return;
}
if ($('.cp-pad-not-pinned').length) { return; }
var pnpTitle = Messages._getKey('padNotPinnedVariable', ['','','','', ApiConfig.inactiveTime]);
var pnpMsg = Messages._getKey('padNotPinnedVariable', [
'<a href="' + o + '/login" class="cp-pnp-login" target="blank" title>',
'</a>',
'<a href="' + o + '/register" class="cp-pnp-register" target="blank" title>',
'</a>',
ApiConfig.inactiveTime
]);
var $msg = $('<span>', {
'class': 'cp-pad-not-pinned'
}).append([
$('<span>', {'class': 'fa fa-exclamation-triangle', 'title': pnpTitle}),
$('<span>', {'class': 'cp-pnp-msg'}).append(pnpMsg)
]);
$msg.find('a.cp-pnp-login').click(function (ev) {
ev.preventDefault();
Common.setLoginRedirect('login');
});
$msg.find('a.cp-pnp-register').click(function (ev) {
ev.preventDefault();
Common.setLoginRedirect('register');
});
$('.cp-toolbar-top').append($msg);
2018-03-02 17:33:43 +00:00
//UI.addTooltips();
});
};
var createUnpinnedWarning = function (toolbar, config) {
config.metadataMgr.onChange(function () {
createUnpinnedWarning0(toolbar, config);
});
createUnpinnedWarning0(toolbar, config);
};
2017-08-17 12:55:44 +00:00
var createPageTitle = function (toolbar, config) {
2019-07-04 13:51:29 +00:00
if (!config.pageTitle) { return; }
2017-08-17 12:55:44 +00:00
var $titleContainer = $('<span>', {
'class': TITLE_CLS
}).appendTo(toolbar.$top);
toolbar.$top.find('.filler').hide();
2017-09-04 13:09:54 +00:00
var $hoverable = $('<span>', {'class': 'cp-toolbar-title-hoverable'}).appendTo($titleContainer);
2017-08-17 12:55:44 +00:00
// Buttons
$('<span>', {
2017-09-04 13:09:54 +00:00
'class': 'cp-toolbar-title-value cp-toolbar-title-value-page'
2017-08-17 12:55:44 +00:00
}).appendTo($hoverable).text(config.pageTitle);
};
2017-08-28 12:18:33 +00:00
var createLinkToMain = function (toolbar, config) {
2017-08-17 12:55:44 +00:00
var $linkContainer = $('<span>', {
2017-09-04 13:09:54 +00:00
'class': LINK_CLS
2017-08-17 12:55:44 +00:00
}).appendTo(toolbar.$top);
// We need to override the "a" tag action here because it is inside the iframe!
var inDrive = /^\/drive/;
var privateData = config.metadataMgr.getPrivateData();
var origin = privateData.origin;
var pathname = privateData.pathname;
var isAnonSF = privateData.newSharedFolder && !privateData.accountName;
var toMain = inDrive.test(pathname) && !isAnonSF;
var href = toMain ? origin+'/index.html' : origin+'/drive/';
var buttonTitle = toMain ? Messages.header_homeTitle : Messages.header_logoTitle;
2017-08-17 12:55:44 +00:00
var $aTag = $('<a>', {
href: href,
title: buttonTitle,
2017-09-04 13:09:54 +00:00
'class': "cp-toolbar-link-logo"
2020-05-07 12:58:27 +00:00
}).append(UIElements.getSvgLogo());
2017-08-17 12:55:44 +00:00
var onClick = function (e) {
e.preventDefault();
if (e.ctrlKey) {
Common.openURL(href);
2017-08-17 12:55:44 +00:00
return;
}
Common.gotoURL(href);
2017-08-17 12:55:44 +00:00
};
var onContext = function (e) { e.stopPropagation(); };
$aTag.click(onClick).contextmenu(onContext);
$linkContainer.append($aTag);
return $linkContainer;
};
var typing = -1;
2017-09-25 12:47:19 +00:00
var kickSpinner = function (toolbar, config/*, local*/) {
2017-08-17 12:55:44 +00:00
if (!toolbar.spinner) { return; }
if (toolbar.isErrorState) { return; }
2017-08-17 12:55:44 +00:00
var $spin = toolbar.spinner;
if (typing === -1) {
typing = 1;
$spin.text(Messages.typing);
$spin.interval = window.setInterval(function () {
2018-02-13 17:20:13 +00:00
if (toolbar.isErrorState) { return; }
2017-08-17 12:55:44 +00:00
var dots = Array(typing+1).join('.');
$spin.text(Messages.typing + dots);
typing++;
if (typing > 3) { typing = 0; }
}, 500);
}
var onSynced = function () {
if ($spin.timeout) { clearTimeout($spin.timeout); }
$spin.timeout = setTimeout(function () {
2018-02-13 17:20:13 +00:00
if (toolbar.isErrorState) { return; }
2017-08-17 12:55:44 +00:00
window.clearInterval($spin.interval);
typing = -1;
$spin.text(Messages.saved);
}, /*local ? 0 :*/ SPINNER_DISAPPEAR_TIME);
2017-08-17 12:55:44 +00:00
};
if (config.spinner) {
var h = function () {
onSynced();
try { config.spinner.onSync.unreg(h); } catch (e) { console.error(e); }
};
config.spinner.onSync.reg(h);
return;
}
config.sfCommon.whenRealtimeSyncs(onSynced);
2017-08-17 12:55:44 +00:00
};
var ks = function (toolbar, config, local) {
return function () {
if (toolbar.connected) { kickSpinner(toolbar, config, local); }
};
};
var createSpinner = function (toolbar, config) {
2020-05-13 12:42:22 +00:00
if (config.readOnly === 1) { return; }
2020-05-07 12:58:27 +00:00
var $spin = $('<span>', {'class': SPINNER_CLS}).appendTo(toolbar.title);
2017-08-17 12:55:44 +00:00
$spin.text(Messages.synchronizing);
if (config.spinner) {
config.spinner.onPatch.reg(ks(toolbar, config));
typing = 0;
setTimeout(function () {
kickSpinner(toolbar, config);
});
return $spin;
}
2017-08-17 12:55:44 +00:00
if (config.realtime) {
config.realtime.onPatch(ks(toolbar, config));
config.realtime.onMessage(ks(toolbar, config, true));
}
// without this, users in read-only mode say 'synchronizing' until they
// receive a patch.
typing = 0;
config.sfCommon.whenRealtimeSyncs(function () {
kickSpinner(toolbar, config);
});
2017-08-17 12:55:44 +00:00
return $spin;
};
2019-06-25 13:07:43 +00:00
var createLimit = function (toolbar, config) {
2017-08-17 12:55:44 +00:00
var $limitIcon = $('<span>', {'class': 'fa fa-exclamation-triangle'});
var $limit = toolbar.$userAdmin.find('.'+LIMIT_CLS).attr({
'title': Messages.pinLimitReached
}).append($limitIcon).hide();
2019-06-25 13:07:43 +00:00
var priv = config.metadataMgr.getPrivateData();
var origin = priv.origin;
var l = document.createElement("a");
l.href = origin;
2017-08-17 12:55:44 +00:00
var todo = function (e, overLimit) {
if (e) { return void console.error("Unable to get the pinned usage", e); }
2017-08-17 12:55:44 +00:00
if (overLimit) {
$limit.show().click(function () {
if (ApiConfig.allowSubscriptions && Config.upgradeURL) {
var key = 'pinLimitReachedAlert'; // Msg.pinLimitReachedAlert
var msg = Pages.setHTML(h('span'), Messages.pinLimitReachedAlert);
$(msg).find('a').attr({
target: '_blank',
href: Config.upgradeURL,
});
UI.alert(msg);
} else {
UI.alert(Messages.pinLimitReachedAlertNoAccounts);
}
2017-08-17 12:55:44 +00:00
});
}
};
2017-08-21 10:24:33 +00:00
Common.isOverPinLimit(todo);
2017-08-17 12:55:44 +00:00
return $limit;
};
var createNewPad = function (toolbar, config) {
var $button = Common.createButton('newpad', true);
toolbar.$drawer.append($button);
return $button;
2017-08-17 12:55:44 +00:00
};
var createUserAdmin = function (toolbar, config) {
2017-08-18 09:07:42 +00:00
if (!config.metadataMgr) {
throw new Error("You must provide a `metadataMgr` to display the user menu");
}
var metadataMgr = config.metadataMgr;
2017-08-17 12:55:44 +00:00
var $userAdmin = toolbar.$userAdmin.find('.'+USERADMIN_CLS).show();
var userMenuCfg = {
$initBlock: $userAdmin,
2017-08-17 12:55:44 +00:00
};
if (!config.hideDisplayName) {
$.extend(true, userMenuCfg, {
displayNameCls: USERNAME_CLS,
changeNameButtonCls: USERBUTTON_CLS,
});
}
2017-08-17 12:55:44 +00:00
if (config.readOnly !== 1) {
userMenuCfg.displayName = 1;
userMenuCfg.displayChangeName = 1;
}
Common.createUserAdminMenu(userMenuCfg);
$userAdmin.find('> button').attr('title', Messages.userAccountButton);
2017-08-17 12:55:44 +00:00
return $userAdmin;
};
2021-03-30 15:41:12 +00:00
var createMaintenance = function (toolbar, config) {
var $notif = toolbar.$top.find('.'+MAINTENANCE_CLS);
var button = h('button.cp-maintenance-wrench.fa.fa-wrench');
2021-03-30 15:41:12 +00:00
$notif.append(button);
var m = Broadcast.maintenance;
$(button).click(function () {
if (!m || !m.start || !m.end) { return; }
UI.alert(Messages._getKey('broadcast_maintenance', [
new Date(m.start).toLocaleString(),
new Date(m.end).toLocaleString(),
]), null, true);
});
var to;
2021-03-30 15:41:12 +00:00
Common.makeUniversal('broadcast', {
onEvent: function (obj) {
var cmd = obj.ev;
if (cmd !== "MAINTENANCE") { return; }
var data = obj.data;
if (!data) {
return void $notif.hide();
}
if ((+new Date()) > data.end) {
return void $notif.hide();
}
2021-03-30 15:41:12 +00:00
m = data;
clearTimeout(to);
to = setTimeout(function () {
m = undefined;
$notif.hide();
}, m.end-(+new Date()));
2021-03-30 15:41:12 +00:00
$notif.css('display', '');
}
});
if (m && m.start && m.end) {
$notif.css('display', '');
to = setTimeout(function () {
m = undefined;
$notif.hide();
}, m.end-(+new Date()));
2021-03-30 15:41:12 +00:00
} else {
$notif.hide();
}
};
2019-05-22 16:03:52 +00:00
var createNotifications = function (toolbar, config) {
2019-05-17 14:19:41 +00:00
var $notif = toolbar.$top.find('.'+NOTIFICATIONS_CLS).show();
var openNotifsApp = h('div.cp-notifications-gotoapp', h('p', Messages.openNotificationsApp || "Open notifications App"));
$(openNotifsApp).click(function () {
2019-07-04 09:15:04 +00:00
Common.openURL("/notifications/");
});
2019-05-22 16:03:52 +00:00
var div = h('div.cp-notifications-container', [
2019-05-23 13:12:59 +00:00
h('div.cp-notifications-empty', Messages.notifications_empty)
2019-05-22 16:03:52 +00:00
]);
2019-05-17 14:19:41 +00:00
var pads_options = [div];
2020-11-12 10:22:46 +00:00
var metadataMgr = config.metadataMgr;
var privateData = metadataMgr.getPrivateData();
if (!privateData.notifications) {
var allowNotif = h('div.cp-notifications-gotoapp', h('p', Messages.allowNotifications));
pads_options.unshift(h("hr"));
pads_options.unshift(allowNotif);
var $allow = $(allowNotif).click(function () {
2020-11-12 10:29:05 +00:00
Common.getSframeChannel().event('Q_ASK_NOTIFICATION', null, function (e, allow) {
if (!allow) { return; }
2020-11-12 10:22:46 +00:00
$(allowNotif).remove();
});
});
2020-11-12 10:29:05 +00:00
var onChange = function () {
2020-11-12 10:22:46 +00:00
var privateData = metadataMgr.getPrivateData();
if (!privateData.notifications) { return; }
$allow.remove();
2020-11-12 10:29:05 +00:00
metadataMgr.off('change', onChange);
};
metadataMgr.onChange(onChange);
2020-11-12 10:22:46 +00:00
}
if (Common.isLoggedIn()) {
pads_options.unshift(h("hr"));
pads_options.unshift(openNotifsApp);
}
2019-05-17 14:19:41 +00:00
var dropdownConfig = {
text: '', // Button initial text
options: pads_options, // Entries displayed in the menu
container: $notif,
left: true,
common: Common
};
var $newPadBlock = UIElements.createDropdown(dropdownConfig);
2019-05-22 16:03:52 +00:00
var $button = $newPadBlock.find('button');
$button.attr('title', Messages.notificationsPage);
2021-02-15 14:10:31 +00:00
$button.addClass('fa fa-bell-o cp-notifications-bell');
2019-05-22 16:03:52 +00:00
var $n = $button.find('.cp-dropdown-button-title').hide();
var $empty = $(div).find('.cp-notifications-empty');
var refresh = function () {
updateUserList(toolbar, config);
var n = $(div).find('.cp-notification').length;
$button.removeClass('fa-bell-o').removeClass('fa-bell');
2019-05-23 09:34:56 +00:00
$n.removeClass('cp-notifications-small');
2019-05-22 16:03:52 +00:00
if (n === 0) {
$empty.show();
$n.hide();
return void $button.addClass('fa-bell-o');
}
2019-05-23 09:34:56 +00:00
if (n > 99) {
n = '99+';
$n.addClass('cp-notifications-small');
}
2019-05-22 16:03:52 +00:00
$empty.hide();
$n.text(n).show();
$button.addClass('fa-bell');
};
2019-05-17 14:19:41 +00:00
2021-04-09 16:10:13 +00:00
Common.mailbox.subscribe(['notifications', 'team', 'broadcast', 'reminders'], {
2019-05-17 14:19:41 +00:00
onMessage: function (data, el) {
2019-05-21 16:43:11 +00:00
if (el) {
$(div).prepend(el);
2019-05-21 16:43:11 +00:00
}
2019-05-22 16:03:52 +00:00
refresh();
},
2019-05-23 13:51:50 +00:00
onViewed: function () {
2019-05-22 16:03:52 +00:00
refresh();
2019-05-17 14:19:41 +00:00
}
});
return $newPadBlock;
2019-05-16 14:09:42 +00:00
};
2017-08-17 12:55:44 +00:00
// Events
2017-09-13 14:19:26 +00:00
var initClickEvents = function (toolbar) {
2017-08-17 12:55:44 +00:00
var removeDropdowns = function () {
2017-08-18 16:43:04 +00:00
window.setTimeout(function () {
$('body').find('.cp-dropdown-content').hide();
2017-08-18 16:43:04 +00:00
});
2017-08-17 12:55:44 +00:00
};
var cancelEditTitle = function (e) {
// Now we want to apply the title even if we click somewhere else
if ($(e.target).parents('.' + TITLE_CLS).length || !toolbar.title) {
return;
}
var $title = toolbar.title;
if (!$title.find('input').is(':visible')) { return; }
// Press enter
var ev = $.Event("keyup");
ev.which = 13;
$title.find('input').trigger(ev);
};
// Click in the main window
2017-09-12 16:40:11 +00:00
var w = window;
2017-08-17 12:55:44 +00:00
$(w).on('click', removeDropdowns);
$(w).on('click', cancelEditTitle);
// Click in iframes
try {
if (w.$ && w.$('iframe').length) {
2017-09-12 16:40:11 +00:00
w.$('iframe').each(function (i, el) {
2017-08-17 12:55:44 +00:00
$(el.contentWindow).on('click', removeDropdowns);
$(el.contentWindow).on('click', cancelEditTitle);
});
}
} catch (e) {
// empty try catch in case this iframe is problematic
}
};
// Notifications
var initNotifications = function (toolbar, config) {
// Display notifications when users are joining/leaving the session
var oldUserData;
2017-08-18 08:47:30 +00:00
if (!config.metadataMgr) { return; }
var metadataMgr = config.metadataMgr;
2017-11-13 15:32:40 +00:00
var notify = function(type, name, oldname) {
if (toolbar.isAlone) { return; }
2017-11-13 15:32:40 +00:00
// type : 1 (+1 user), 0 (rename existing user), -1 (-1 user)
if (typeof name === "undefined") { return; }
name = name || Messages.anonymous;
if (Config.disableUserlistNotifications) { return; }
switch(type) {
case 1:
UI.log(Messages._getKey("notifyJoined", [name]));
break;
case 0:
oldname = (!oldname) ? Messages.anonymous : oldname;
UI.log(Messages._getKey("notifyRenamed", [oldname, name]));
break;
case -1:
UI.log(Messages._getKey("notifyLeft", [name]));
break;
default:
console.log("Invalid type of notification");
break;
}
};
2017-08-17 12:55:44 +00:00
2017-11-13 15:32:40 +00:00
var userPresent = function (id, user, data) {
if (!(user && user.uid)) {
console.log('no uid');
return 0;
}
if (!data) {
console.log('no data');
return 0;
}
2017-08-17 12:55:44 +00:00
2017-11-13 15:32:40 +00:00
var count = 0;
Object.keys(data).forEach(function (k) {
if (data[k] && data[k].uid === user.uid) { count++; }
});
return count;
};
2017-08-17 12:55:44 +00:00
2017-11-13 15:32:40 +00:00
var joined = false;
metadataMgr.onChange(function () {
var newdata = metadataMgr.getMetadata().users;
var netfluxIds = Object.keys(newdata);
var userNetfluxId = metadataMgr.getNetfluxId();
2017-11-13 15:32:40 +00:00
// 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 (netfluxIds.indexOf(u) === -1) {
var temp = JSON.parse(JSON.stringify(oldUserData[u]));
delete oldUserData[u];
if (temp && newdata[userNetfluxId] && temp.uid === newdata[userNetfluxId].uid) { return; }
if (userPresent(u, temp, newdata || oldUserData) < 1) {
notify(-1, temp.name);
2017-08-17 12:55:44 +00:00
}
}
}
2017-11-13 15:32:40 +00:00
}
// 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 (config.readOnly === 0 && !oldUserData[userNetfluxId]) {
oldUserData = JSON.parse(JSON.stringify(newdata));
return;
}
for (var k in newdata) {
if (joined && k !== userNetfluxId && netfluxIds.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);
2017-08-17 12:55:44 +00:00
}
2017-11-13 15:32:40 +00:00
} else if (oldUserData[k].name !== newdata[k].name) {
notify(0, newdata[k].name, oldUserData[k].name);
2017-08-17 12:55:44 +00:00
}
}
2017-11-13 15:32:40 +00:00
}
joined = true;
oldUserData = JSON.parse(JSON.stringify(newdata));
});
2017-08-17 12:55:44 +00:00
};
// Main
Bar.create = function (cfg) {
var config = cfg || {};
2017-08-17 16:28:05 +00:00
Common = config.sfCommon;
2017-08-17 12:55:44 +00:00
config.readOnly = (typeof config.readOnly !== "undefined") ? (config.readOnly ? 1 : 0) : -1;
config.displayed = config.displayed || [];
var toolbar = {};
toolbar.connected = false;
toolbar.firstConnection = true;
var $toolbar = toolbar.$toolbar = createRealtimeToolbar(config);
2020-05-07 12:58:27 +00:00
toolbar.$bottom = $toolbar.find('.'+Bar.constants.bottom);
toolbar.$bottomL = $toolbar.find('.'+Bar.constants.bottomL);
toolbar.$bottomM = $toolbar.find('.'+Bar.constants.bottomM);
toolbar.$bottomR = $toolbar.find('.'+Bar.constants.bottomR);
2017-08-17 12:55:44 +00:00
toolbar.$leftside = $toolbar.find('.'+Bar.constants.leftside);
toolbar.$rightside = $toolbar.find('.'+Bar.constants.rightside);
2020-05-07 16:16:36 +00:00
toolbar.$file = $toolbar.find('.'+Bar.constants.file);
2017-08-17 12:55:44 +00:00
toolbar.$drawer = $toolbar.find('.'+Bar.constants.drawer);
toolbar.$top = $toolbar.find('.'+Bar.constants.top);
toolbar.$history = $toolbar.find('.'+Bar.constants.history);
toolbar.$userAdmin = $toolbar.find('.'+Bar.constants.userAdmin);
// Create the subelements
var tb = {};
tb['userlist'] = createUserList;
2021-08-03 10:49:50 +00:00
tb['collapse'] = createCollapse;
tb['chat'] = createChat;
2017-08-21 09:08:27 +00:00
tb['share'] = createShare;
2020-05-07 13:26:12 +00:00
tb['access'] = createAccess;
2017-09-12 16:40:11 +00:00
tb['fileshare'] = createFileShare;
2017-08-17 12:55:44 +00:00
tb['title'] = createTitle;
2017-09-12 16:40:11 +00:00
tb['pageTitle'] = createPageTitle;
//tb['request'] = createRequest;
2017-08-17 12:55:44 +00:00
tb['lag'] = $.noop;
tb['spinner'] = createSpinner;
tb['state'] = $.noop;
tb['limit'] = createLimit; // TODO
2017-08-17 12:55:44 +00:00
tb['upgrade'] = $.noop;
tb['newpad'] = createNewPad;
tb['useradmin'] = createUserAdmin;
tb['unpinnedWarning'] = createUnpinnedWarning;
2019-05-16 14:09:42 +00:00
tb['notifications'] = createNotifications;
2021-03-30 15:41:12 +00:00
tb['maintenance'] = createMaintenance;
2017-08-17 12:55:44 +00:00
2020-05-07 13:26:12 +00:00
tb['pad'] = function () {
2020-05-07 16:16:36 +00:00
toolbar.$file.show();
2020-05-07 13:26:12 +00:00
addElement([
2021-08-03 10:49:50 +00:00
'chat',
'collapse',
2021-08-03 10:49:50 +00:00
'userlist', 'title', 'useradmin', 'spinner',
2020-05-07 13:26:12 +00:00
'newpad', 'share', 'access', 'limit', 'unpinnedWarning',
'notifications'
], {});
};
2020-05-13 13:54:36 +00:00
var checkSize = function () {
toolbar.$bottom.removeClass('cp-toolbar-small');
var w = $(window).width();
var size = toolbar.$bottomL.width() + toolbar.$bottomM.width() +
toolbar.$bottomR.width();
if (size > w) {
toolbar.$bottom.addClass('cp-toolbar-small');
}
};
$(window).on('resize', checkSize);
2018-09-29 03:16:41 +00:00
var addElement = toolbar.addElement = function (arr, additionalCfg, init) {
if (typeof additionalCfg === "object") { $.extend(true, config, additionalCfg); }
2017-08-17 12:55:44 +00:00
arr.forEach(function (el) {
if (typeof el !== "string" || !el.trim()) { return; }
if (typeof tb[el] === "function") {
if (!init && config.displayed.indexOf(el) !== -1) { return; } // Already done
if (!init) { config.displayed.push(el); }
2020-11-06 16:13:41 +00:00
toolbar[el] = tb[el](toolbar, config);
2017-08-17 12:55:44 +00:00
}
});
2020-05-13 13:54:36 +00:00
checkSize();
2017-08-17 12:55:44 +00:00
};
addElement(config.displayed, {}, true);
2021-03-30 15:41:12 +00:00
addElement(['maintenance'], {}, true);
2017-08-17 12:55:44 +00:00
2020-05-13 13:54:36 +00:00
2017-08-17 12:55:44 +00:00
toolbar['linkToMain'] = createLinkToMain(toolbar, config);
if (!config.realtime) { toolbar.connected = true; }
initClickEvents(toolbar, config);
initNotifications(toolbar, config);
2020-03-06 11:55:20 +00:00
var failed = toolbar.failed = function (hideUserList) {
2017-08-17 12:55:44 +00:00
toolbar.connected = false;
if (toolbar.spinner) {
toolbar.spinner.text(Messages.disconnected);
}
2020-03-06 11:55:20 +00:00
if (hideUserList) {
updateUserList(toolbar, config, true);
}
2017-08-17 12:55:44 +00:00
//checkLag(toolbar, config);
};
2017-10-20 16:12:47 +00:00
toolbar.initializing = function (/*userId*/) {
2020-09-24 15:03:19 +00:00
if (toolbar.history) { return; }
2017-10-20 16:12:47 +00:00
toolbar.connected = false;
if (toolbar.spinner) {
toolbar.spinner.text(Messages.initializing);
}
};
2017-08-23 09:04:44 +00:00
toolbar.reconnecting = function (/*userId*/) {
2020-09-24 15:03:19 +00:00
if (toolbar.history) { return; }
2017-08-17 12:55:44 +00:00
toolbar.connected = false;
if (toolbar.spinner) {
var state = -1;
var interval = window.setInterval(function () {
if (toolbar.connected) { clearInterval(interval); }
var dots = Array(state+1).join('.');
toolbar.spinner.text(Messages.reconnecting + dots);
if (++state > 3) { state = 0; }
}, 500);
2017-08-17 12:55:44 +00:00
toolbar.spinner.text(Messages.reconnecting);
}
2017-10-20 16:12:47 +00:00
};
2020-12-08 10:19:38 +00:00
toolbar.ready = function () {
toolbar.connected = true;
kickSpinner(toolbar, config);
};
2017-10-20 16:12:47 +00:00
toolbar.errorState = function (state, error) {
toolbar.isErrorState = state;
if (state) { toolbar.connected = false; }
if (toolbar.spinner) {
if (!state) {
return void kickSpinner(toolbar, config);
}
var txt = Messages._getKey('errorState', [error]);
toolbar.spinner.text(txt);
}
};
2017-10-20 16:12:47 +00:00
// When the pad is moved to the trash (forget button)
toolbar.forgotten = function (/*userId*/) {
toolbar.connected = false;
if (toolbar.spinner) {
toolbar.spinner.text(Messages.forgotten);
}
2017-08-17 12:55:44 +00:00
};
2018-02-13 17:20:13 +00:00
// When the pad is deleted from the server
toolbar.deleted = function (/*userId*/) {
toolbar.isErrorState = true;
toolbar.connected = false;
toolbar.isDeleted = true;
2020-03-06 11:55:20 +00:00
updateUserList(toolbar, config, true);
toolbar.title.toggleClass('cp-toolbar-unsync', true); // "read only" next to the title
2018-02-13 17:20:13 +00:00
if (toolbar.spinner) {
toolbar.spinner.text(Messages.deletedFromServer);
}
};
// Show user colors in the userlist only if the app is compatible and if the user
// wants to see the cursors
toolbar.showColors = function () {
if (!config.metadataMgr) { return; }
var privateData = config.metadataMgr.getPrivateData();
var show = Util.find(privateData, ['settings', 'general', 'cursor', 'show']);
if (show === false) { return; }
showColors = true;
};
// If we had to create a new chainpad instance, reset the one used in the toolbar
toolbar.resetChainpad = function (chainpad) {
2020-05-13 12:42:22 +00:00
if (config.readOnly === 1) { return; }
if (config.realtime !== chainpad) {
config.realtime = chainpad;
config.realtime.onPatch(ks(toolbar, config));
config.realtime.onMessage(ks(toolbar, config, true));
}
};
toolbar.setSnapshot = function (bool) {
toolbar.history = bool;
toolbar.title.toggleClass('cp-toolbar-unsync', bool);
if (bool && toolbar.spinner) {
2020-10-01 09:50:38 +00:00
toolbar.spinner.text(Messages.snaphot_title);
} else {
kickSpinner(toolbar, config);
}
};
2020-09-24 15:03:19 +00:00
toolbar.setHistory = function (bool) {
toolbar.history = bool;
toolbar.title.toggleClass('cp-toolbar-unsync', bool);
2020-09-24 15:03:19 +00:00
if (bool && toolbar.spinner) {
2020-10-01 09:50:38 +00:00
toolbar.spinner.text(Messages.historyText);
} else {
kickSpinner(toolbar, config);
2020-09-24 15:03:19 +00:00
}
};
toolbar.offline = function (bool) {
toolbar.connected = !bool; // Can't edit title
toolbar.history = bool; // Stop "Initializing" state
toolbar.isErrorState = bool; // Stop kickSpinner
toolbar.title.toggleClass('cp-toolbar-unsync', bool); // "read only" next to the title
if (bool && toolbar.spinner) {
2021-01-07 11:58:41 +00:00
toolbar.spinner.text(Messages.Offline);
} else {
kickSpinner(toolbar, config);
}
};
// disable notification, userlist and chat
toolbar.alone = function () {
toolbar.userlist.hide();
toolbar.chat.hide();
$('.cp-toolbar-userlist-drawer').remove();
$('.cp-toolbar-chat-drawer').remove();
toolbar.isAlone = true;
};
2017-08-17 12:55:44 +00:00
// On log out, remove permanently the realtime elements of the toolbar
Common.onLogout(function () {
2017-08-17 12:55:44 +00:00
failed();
if (toolbar.useradmin) { toolbar.useradmin.hide(); }
if (toolbar.userlist) { toolbar.userlist.hide(); }
});
2017-08-17 12:55:44 +00:00
return toolbar;
};
return Bar;
});