From b153dda6ff95c8a41bc077bc3cd9431d0e584b9f Mon Sep 17 00:00:00 2001 From: yflory Date: Fri, 30 Jun 2017 16:57:23 +0200 Subject: [PATCH] Add avatars in the user list --- customize.dist/src/less/toolbar.less | 41 +++++++- customize.dist/translations/messages.fr.js | 10 ++ customize.dist/translations/messages.js | 11 +- www/common/common-userlist.js | 8 +- www/common/cryptpad-common.js | 117 ++++++++++++--------- www/common/fsStore.js | 4 + www/common/toolbar2.js | 24 ++++- www/profile/main.js | 28 ++--- 8 files changed, 174 insertions(+), 69 deletions(-) diff --git a/customize.dist/src/less/toolbar.less b/customize.dist/src/less/toolbar.less index dd189671c..076792dee 100644 --- a/customize.dist/src/less/toolbar.less +++ b/customize.dist/src/less/toolbar.less @@ -104,6 +104,43 @@ body .userlist-drawer { background: rgba(0,0,0,0.1); margin: 2px 0; font-size: 16px; + display: inline-flex; + align-items: center; + &.clickable { + cursor: pointer; + &:hover { + background-color: rgba(0,0,0,0.3); + } + } + .default, media-tag { + display: inline-flex; + width: 50px; + height: 50px; + justify-content: center; + align-items: center; + margin-right: 5px; + border-radius: 10px / 6px; + overflow: hidden; + border: 1px solid black; + box-sizing: content-box; + } + .default { + .unselectable(); + background: white; + color: black; + font-size: 40px; + } + media-tag { + max-height: 50px; + max-width: 50px; + img { + min-width: 100%; + min-height: 100%; + max-width: none; + max-height: none !important; // To override 'media-tag img' in slide.less + flex-shrink: 0; + } + } } } } @@ -850,8 +887,10 @@ body .cryptpad-toolbar { } } .cryptpad-toolbar-rightside { - height: 32px; + min-height: 32px; + overflow: hidden; &:empty { + min-height: 0; height: 0; } text-align: right; diff --git a/customize.dist/translations/messages.fr.js b/customize.dist/translations/messages.fr.js index 0e4cce6a7..5a087d8ee 100644 --- a/customize.dist/translations/messages.fr.js +++ b/customize.dist/translations/messages.fr.js @@ -240,6 +240,16 @@ define(function () { out.canvas_opacityLabel = "opacité: {0}"; out.canvas_widthLabel = "taille: {0}"; + // Profile + out.profile_urlPlaceholder = 'URL'; + out.profile_avatar = "Avatar"; + out.profile_upload = " Importer un nouvel avatar"; + out.profile_error = "Erreur lors de la création du profil : {0}"; + out.profile_register = "Vous devez vous inscrire pour pouvoir créer un profil !"; + out.profile_create = "Créer un profil"; + out.profile_description = "Description"; + out.profile_fieldSaved = 'Nouvelle valeur enregistrée: {0}'; + // File manager out.fm_rootName = "Documents"; diff --git a/customize.dist/translations/messages.js b/customize.dist/translations/messages.js index 3d84e9ecf..671109e12 100644 --- a/customize.dist/translations/messages.js +++ b/customize.dist/translations/messages.js @@ -241,7 +241,16 @@ define(function () { out.canvas_opacity = "Opacity"; out.canvas_opacityLabel = "opacity: {0}"; out.canvas_widthLabel = "Width: {0}"; - + + // Profile + out.profile_urlPlaceholder = 'URL'; + out.profile_avatar = "Avatar"; + out.profile_upload = " Upload a new avatar"; + out.profile_error = "Error while creating your profile: {0}"; + out.profile_register = "You have to sign up to create a profile!"; + out.profile_create = "Create a profile"; + out.profile_description = "Description"; + out.profile_fieldSaved = 'New value saved: {0}'; // File manager diff --git a/www/common/common-userlist.js b/www/common/common-userlist.js index 7b62d6566..2e1fe4adf 100644 --- a/www/common/common-userlist.js +++ b/www/common/common-userlist.js @@ -49,8 +49,10 @@ define(function () { exp.myUserName = myUserNameTemp; myData = {}; myData[exp.myNetfluxId] = { - name: exp.myUserName, - uid: Cryptpad.getUid(), + name: exp.myUserName, + uid: Cryptpad.getUid(), + avatar: Cryptpad.getAvatarUrl(), + profile: Cryptpad.getProfileUrl() }; addToUserData(myData); Cryptpad.setAttribute('username', exp.myUserName, function (err) { @@ -78,6 +80,8 @@ define(function () { myData[exp.myNetfluxId] = { name: "", uid: Cryptpad.getUid(), + avatar: Cryptpad.getAvatarUrl(), + profile: Cryptpad.getProfileUrl() }; addToUserData(myData); onLocal(); diff --git a/www/common/cryptpad-common.js b/www/common/cryptpad-common.js index 291062e83..0bc7c3680 100644 --- a/www/common/cryptpad-common.js +++ b/www/common/cryptpad-common.js @@ -146,6 +146,16 @@ define([ } return; }; + common.getProfileUrl = function () { + if (store && store.getProfile()) { + return store.getProfile().view; + } + }; + common.getAvatarUrl = function () { + if (store && store.getProfile()) { + return store.getProfile().avatar; + } + }; var feedback = common.feedback = function (action, force) { if (force !== true) { @@ -1168,61 +1178,70 @@ define([ 'image/jpg', 'image/gif', ]; - common.displayAvatar = function ($container, href) { + common.displayAvatar = function ($container, href, name, cb) { var MutationObserver = window.MutationObserver; - $container.html(''); - if (href) { - var parsed = common.parsePadUrl(href); - var secret = common.getSecrets('file', parsed.hash); - if (secret.keys && secret.channel) { - var cryptKey = secret.keys && secret.keys.fileKeyStr; - var hexFileName = common.base64ToHex(secret.channel); - var src = common.getBlobPathFromHex(hexFileName); - common.getFileSize(href, function (e, data) { - if (e) { return void console.error(e); } - if (typeof data !== "number") { return; } - if (common.bytesToMegabytes(data) > 0.5) { return; } - var $img = $('').appendTo($container); - $img.attr('src', src); - $img.attr('data-crypto-key', 'cryptpad:' + cryptKey); - require(['/common/media-tag.js'], function (MediaTag) { - MediaTag.CryptoFilter.setAllowedMediaTypes(common.avatarAllowedTypes); - MediaTag($img[0]); - var observer = new MutationObserver(function(mutations) { - mutations.forEach(function(mutation) { - if (mutation.type === 'childList' && mutation.addedNodes.length) { - console.log(mutation); - if (mutation.addedNodes.length > 1 || - mutation.addedNodes[0].nodeName !== 'IMG') { - $img.remove(); + var displayDefault = function () { + var text = name.trim().length ? name.trim().slice(0,1) : '?'; + var $avatar = $('', {'class': 'default'}).text(text); + $container.append($avatar); + if (cb) { cb(); } + }; + + if (!href) { return void displayDefault(); } + var parsed = common.parsePadUrl(href); + var secret = common.getSecrets('file', parsed.hash); + if (secret.keys && secret.channel) { + var cryptKey = secret.keys && secret.keys.fileKeyStr; + var hexFileName = common.base64ToHex(secret.channel); + var src = common.getBlobPathFromHex(hexFileName); + common.getFileSize(href, function (e, data) { + if (e) { + displayDefault(); + return void console.error(e); + } + if (typeof data !== "number") { return void displayDefault(); } + if (common.bytesToMegabytes(data) > 0.5) { return void displayDefault(); } + var $img = $('').appendTo($container); + $img.attr('src', src); + $img.attr('data-crypto-key', 'cryptpad:' + cryptKey); + require(['/common/media-tag.js'], function (MediaTag) { + MediaTag.CryptoFilter.setAllowedMediaTypes(common.avatarAllowedTypes); + MediaTag($img[0]); + var observer = new MutationObserver(function(mutations) { + mutations.forEach(function(mutation) { + if (mutation.type === 'childList' && mutation.addedNodes.length) { + console.log(mutation); + if (mutation.addedNodes.length > 1 || + mutation.addedNodes[0].nodeName !== 'IMG') { + $img.remove(); + return void displayDefault(); + } + var $image = $img.find('img'); + var onLoad = function () { + var w = $image.width(); + var h = $image.height(); + if (w>h) { + $image.css('max-height', '100%'); + $img.css('flex-direction', 'row'); + if (cb) { cb($img); } return; - //TODO display default avatar } - var $image = $img.find('img'); - var onLoad = function () { - var w = $image.width(); - var h = $image.height(); - if (w>h) { - $image.css('max-height', '100%'); - $img.css('flex-direction', 'row'); - return; - } - $image.css('max-width', '100%'); - $img.css('flex-direction', 'column'); - }; - if ($image[0].complete) { onLoad(); } - $image.on('load', onLoad); - } - }); - }); - observer.observe($img[0], { - attributes: false, - childList: true, - characterData: false + $image.css('max-width', '100%'); + $img.css('flex-direction', 'column'); + if (cb) { cb($img); } + }; + if ($image[0].complete) { onLoad(); } + $image.on('load', onLoad); + } }); }); + observer.observe($img[0], { + attributes: false, + childList: true, + characterData: false + }); }); - } + }); } }; diff --git a/www/common/fsStore.js b/www/common/fsStore.js index 05503beb8..aa3e69530 100644 --- a/www/common/fsStore.js +++ b/www/common/fsStore.js @@ -211,6 +211,10 @@ define([ if (typeof(n) !== "string") { return; } Cryptpad.changeDisplayName(n); }); + proxy.on('change', ['profile'], function () { + // Trigger userlist update when the avatar has changed + Cryptpad.changeDisplayName(proxy[Cryptpad.displayNameKey]); + }); proxy.on('change', [tokenKey], function () { console.log('wut'); var localToken = tryParsing(localStorage.getItem(tokenKey)); diff --git a/www/common/toolbar2.js b/www/common/toolbar2.js index 98c702b28..5983aa1c1 100644 --- a/www/common/toolbar2.js +++ b/www/common/toolbar2.js @@ -149,6 +149,7 @@ define([ return $.inArray(i, b) > -1; }); }; + var avatars = {}; var updateUserList = function (toolbar, config) { // Make sure the elements are displayed var $userButtons = toolbar.userlist; @@ -189,7 +190,24 @@ define([ // Editors editUsersNames.forEach(function (data) { var name = data.name || Messages.anonymous; - var $span = $('', {'title': name}).text(name); + var $span = $('', {'title': name}); + if (data.profile) { + $span.addClass('clickable'); + $span.click(function () { + window.open('/profile/#' + data.profile); + }); + } + if (data.avatar && avatars[data.avatar]) { + $span.append(avatars[data.avatar]); + $span.append(name); + } else { + Cryptpad.displayAvatar($span, data.avatar, name, function ($img) { + if (data.avatar && $img) { + avatars[data.avatar] = $img[0].outerHTML; + } + $span.append(name); + }); + } $span.data('uid', data.uid); $editUsersList.append($span); }); @@ -197,9 +215,9 @@ define([ // Viewers if (numberOfViewUsers > 0) { - var viewText = ''; + var viewText = '
'; var viewerText = numberOfViewUsers !== 1 ? Messages.viewers : Messages.viewer; - viewText += numberOfViewUsers + ' ' + viewerText + ''; + viewText += numberOfViewUsers + ' ' + viewerText + '
'; $editUsers.append(viewText); } diff --git a/www/profile/main.js b/www/profile/main.js index eb836d024..d901433b3 100644 --- a/www/profile/main.js +++ b/www/profile/main.js @@ -105,7 +105,7 @@ define([ if (err) { return void console.error(err); } Cryptpad.whenRealtimeSyncs(realtime, function () { lastVal = newVal; - Cryptpad.log('TODO: '+name+' saved'); + Cryptpad.log(Messages._getKey('profile_fieldSaved', [newVal])); editing = false; }); }); @@ -196,7 +196,7 @@ define([ cb(); }; var rt = APP.lm.realtime; - var placeholder = "URL"; //XXX + var placeholder = Messages.profile_urlPlaceholder; createEditableInput($block, LINK_ID, placeholder, getValue, setValue, rt); }; @@ -209,7 +209,7 @@ define([ if (!APP.lm.proxy.avatar) { $('', { src: '/customize/images/avatar.png', - title: 'Avatar', // XXX + title: Messages.profile_avatar, alt: 'Avatar' }).appendTo($span); return; @@ -218,21 +218,20 @@ define([ if (APP.readOnly) { return; } - var $delButton = $('