feat(avatar) add ability to customize Gravatar base URL

Also, default to libravatar.

Closes: https://github.com/jitsi/jitsi-meet/issues/4927
This commit is contained in:
Saúl Ibarra Corretgé 2020-11-15 22:33:55 +01:00 committed by Saúl Ibarra Corretgé
parent 696ec36c8c
commit a7de8be0aa
6 changed files with 44 additions and 18 deletions

View File

@ -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
//

20
package-lock.json generated
View File

@ -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",

View File

@ -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",

View File

@ -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<any, any>) {
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)) {

View File

@ -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));
});

View File

@ -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,