From a7de8be0aaf0e1d4ce9252fcd56e47a76e5c1966 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C3=BAl=20Ibarra=20Corretg=C3=A9?= Date: Sun, 15 Nov 2020 22:33:55 +0100 Subject: [PATCH] feat(avatar) add ability to customize Gravatar base URL Also, default to libravatar. Closes: https://github.com/jitsi/jitsi-meet/issues/4927 --- config.js | 3 +++ package-lock.json | 20 +++++++++++--- package.json | 2 +- react/features/base/participants/functions.js | 27 ++++++++++++------- .../features/base/participants/middleware.js | 5 ++-- react/features/lobby/middleware.js | 5 ++-- 6 files changed, 44 insertions(+), 18 deletions(-) diff --git a/config.js b/config.js index 2ccb6335c..af5973268 100644 --- a/config.js +++ b/config.js @@ -393,6 +393,9 @@ var config = { // Document should be focused for this option to work // enableAutomaticUrlCopy: false, + // Base URL for a Gravatar-compatible service. Defaults to libravatar. + // gravatarBaseURL: 'https://seccdn.libravatar.org/avatar/'; + // Stats // diff --git a/package-lock.json b/package-lock.json index 247806c1a..9a7ef5723 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3302,9 +3302,9 @@ } }, "@jitsi/js-utils": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@jitsi/js-utils/-/js-utils-1.0.2.tgz", - "integrity": "sha512-ls+X9tn9EemUQwPEBr7Z0UD4sjRtwcu1Bh4MUo0Hv4arp0KVzcCYCW+mofsvuZvHg8xJX12LLNVgUKi1X5XTGg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@jitsi/js-utils/-/js-utils-1.0.3.tgz", + "integrity": "sha512-m6mZz7R716mHP21lTKQffyM0nNFu3Fe/EHCaOVLFY/vdPsaUl9DhypJqtPIYzRUfPnmnugdaxcxrUeSZQXQzVA==", "requires": { "bowser": "2.7.0", "js-md5": "0.7.3" @@ -10792,6 +10792,20 @@ "webrtc-adapter": "7.5.0" }, "dependencies": { + "@jitsi/js-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@jitsi/js-utils/-/js-utils-1.0.2.tgz", + "integrity": "sha512-ls+X9tn9EemUQwPEBr7Z0UD4sjRtwcu1Bh4MUo0Hv4arp0KVzcCYCW+mofsvuZvHg8xJX12LLNVgUKi1X5XTGg==", + "requires": { + "bowser": "2.7.0", + "js-md5": "0.7.3" + } + }, + "js-md5": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/js-md5/-/js-md5-0.7.3.tgz", + "integrity": "sha512-ZC41vPSTLKGwIRjqDh8DfXoCrdQIyBgspJVPXHBGu4nZlAEvG3nf+jO9avM9RmLiGakg7vz974ms99nEV0tmTQ==" + }, "uuid": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.1.0.tgz", diff --git a/package.json b/package.json index 6018d40d3..c48e9e662 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "@atlaskit/theme": "7.0.2", "@atlaskit/toggle": "5.0.14", "@atlaskit/tooltip": "12.1.13", - "@jitsi/js-utils": "1.0.2", + "@jitsi/js-utils": "1.0.3", "@microsoft/microsoft-graph-client": "1.1.0", "@react-native-community/async-storage": "1.3.4", "@react-native-community/google-signin": "3.0.1", diff --git a/react/features/base/participants/functions.js b/react/features/base/participants/functions.js index 28d39f8fe..e1b25ebc7 100644 --- a/react/features/base/participants/functions.js +++ b/react/features/base/participants/functions.js @@ -1,6 +1,7 @@ // @flow import { getGravatarURL } from '@jitsi/js-utils/avatar'; +import type { Store } from 'redux'; import { JitsiParticipantConnectionStatus } from '../lib-jitsi-meet'; import { MEDIA_TYPE, shouldRenderVideoTrack } from '../media'; @@ -23,30 +24,35 @@ declare var interfaceConfig: Object; */ const AVATAR_QUEUE = []; const AVATAR_CHECKED_URLS = new Map(); -/* eslint-disable arrow-body-style */ +/* eslint-disable arrow-body-style, no-unused-vars */ const AVATAR_CHECKER_FUNCTIONS = [ - participant => { + (participant, _) => { return participant && participant.isJigasi ? JIGASI_PARTICIPANT_ICON : null; }, - participant => { + (participant, _) => { return participant && participant.avatarURL ? participant.avatarURL : null; }, - participant => { - return participant && participant.email ? getGravatarURL(participant.email) : null; + (participant, store) => { + if (participant && participant.email) { + return getGravatarURL(participant.email, store.getState()['features/base/config'].gravatarBaseURL); + } + + return null; } ]; -/* eslint-enable arrow-body-style */ +/* eslint-enable arrow-body-style, no-unused-vars */ /** * Resolves the first loadable avatar URL for a participant. * * @param {Object} participant - The participant to resolve avatars for. + * @param {Store} store - Redux store. * @returns {Promise} */ -export function getFirstLoadableAvatarUrl(participant: Object) { +export function getFirstLoadableAvatarUrl(participant: Object, store: Store) { const deferred = createDeferred(); const fullPromise = deferred.promise - .then(() => _getFirstLoadableAvatarUrl(participant)) + .then(() => _getFirstLoadableAvatarUrl(participant, store)) .then(src => { if (AVATAR_QUEUE.length) { @@ -402,11 +408,12 @@ export function figureOutMutedWhileDisconnectedStatus( * Resolves the first loadable avatar URL for a participant. * * @param {Object} participant - The participant to resolve avatars for. + * @param {Store} store - Redux store. * @returns {?string} */ -async function _getFirstLoadableAvatarUrl(participant) { +async function _getFirstLoadableAvatarUrl(participant, store) { for (let i = 0; i < AVATAR_CHECKER_FUNCTIONS.length; i++) { - const url = AVATAR_CHECKER_FUNCTIONS[i](participant); + const url = AVATAR_CHECKER_FUNCTIONS[i](participant, store); if (url) { if (AVATAR_CHECKED_URLS.has(url)) { diff --git a/react/features/base/participants/middleware.js b/react/features/base/participants/middleware.js index d03ccd877..5f4a6f1f3 100644 --- a/react/features/base/participants/middleware.js +++ b/react/features/base/participants/middleware.js @@ -365,7 +365,8 @@ function _maybePlaySounds({ getState, dispatch }, action) { * @private * @returns {Object} The value returned by {@code next(action)}. */ -function _participantJoinedOrUpdated({ dispatch, getState }, next, action) { +function _participantJoinedOrUpdated(store, next, action) { + const { dispatch, getState } = store; const { participant: { avatarURL, e2eeEnabled, email, id, local, name, raisedHand } } = action; // Send an external update of the local participant's raised hand state @@ -401,7 +402,7 @@ function _participantJoinedOrUpdated({ dispatch, getState }, next, action) { const participantId = !id && local ? getLocalParticipant(getState()).id : id; const updatedParticipant = getParticipantById(getState(), participantId); - getFirstLoadableAvatarUrl(updatedParticipant) + getFirstLoadableAvatarUrl(updatedParticipant, store) .then(url => { dispatch(setLoadableAvatarUrl(participantId, url)); }); diff --git a/react/features/lobby/middleware.js b/react/features/lobby/middleware.js index 1fd81eec7..bd707c4d1 100644 --- a/react/features/lobby/middleware.js +++ b/react/features/lobby/middleware.js @@ -144,12 +144,13 @@ function _conferenceJoined({ dispatch }, next, action) { * @param {Object} participant - The knocking participant. * @returns {void} */ -function _findLoadableAvatarForKnockingParticipant({ dispatch, getState }, { id }) { +function _findLoadableAvatarForKnockingParticipant(store, { id }) { + const { dispatch, getState } = store; const updatedParticipant = getState()['features/lobby'].knockingParticipants.find(p => p.id === id); const { disableThirdPartyRequests } = getState()['features/base/config']; if (!disableThirdPartyRequests && updatedParticipant && !updatedParticipant.loadableAvatarUrl) { - getFirstLoadableAvatarUrl(updatedParticipant).then(loadableAvatarUrl => { + getFirstLoadableAvatarUrl(updatedParticipant, store).then(loadableAvatarUrl => { if (loadableAvatarUrl) { dispatch(participantIsKnockingOrUpdated({ loadableAvatarUrl,