feat(branding): Add custom avatar backgrounds
This commit is contained in:
parent
c10805f81b
commit
2bac757ca6
|
@ -574,6 +574,12 @@ function initCommands() {
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'get-custom-avatar-backgrounds' : {
|
||||||
|
callback({
|
||||||
|
avatarBackgrounds: APP.store.getState()['features/dynamic-branding'].avatarBackgrounds
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -769,6 +769,17 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
||||||
return getCurrentDevices(this._transport);
|
return getCurrentDevices(this._transport);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns any custom avatars backgrounds.
|
||||||
|
*
|
||||||
|
* @returns {Promise} - Resolves with the list of custom avatar backgrounds.
|
||||||
|
*/
|
||||||
|
getCustomAvatarBackgrounds() {
|
||||||
|
return this._transport.sendRequest({
|
||||||
|
name: 'get-custom-avatar-backgrounds'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current livestream url.
|
* Returns the current livestream url.
|
||||||
*
|
*
|
||||||
|
|
|
@ -21,6 +21,7 @@ const TOOLBAR_TIMEOUT = 4000;
|
||||||
*/
|
*/
|
||||||
type State = {
|
type State = {
|
||||||
avatarURL: string,
|
avatarURL: string,
|
||||||
|
customAvatarBackgrounds: Array<string>,
|
||||||
displayName: string,
|
displayName: string,
|
||||||
formattedDisplayName: string,
|
formattedDisplayName: string,
|
||||||
isVideoDisplayed: boolean,
|
isVideoDisplayed: boolean,
|
||||||
|
@ -48,6 +49,7 @@ export default class AlwaysOnTop extends Component<*, State> {
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
avatarURL: '',
|
avatarURL: '',
|
||||||
|
customAvatarBackgrounds: [],
|
||||||
displayName: '',
|
displayName: '',
|
||||||
formattedDisplayName: '',
|
formattedDisplayName: '',
|
||||||
isVideoDisplayed: true,
|
isVideoDisplayed: true,
|
||||||
|
@ -178,7 +180,14 @@ export default class AlwaysOnTop extends Component<*, State> {
|
||||||
* @returns {ReactElement}
|
* @returns {ReactElement}
|
||||||
*/
|
*/
|
||||||
_renderVideoNotAvailableScreen() {
|
_renderVideoNotAvailableScreen() {
|
||||||
const { avatarURL, displayName, formattedDisplayName, isVideoDisplayed, userID } = this.state;
|
const {
|
||||||
|
avatarURL,
|
||||||
|
customAvatarBackgrounds,
|
||||||
|
displayName,
|
||||||
|
formattedDisplayName,
|
||||||
|
isVideoDisplayed,
|
||||||
|
userID
|
||||||
|
} = this.state;
|
||||||
|
|
||||||
if (isVideoDisplayed) {
|
if (isVideoDisplayed) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -188,7 +197,7 @@ export default class AlwaysOnTop extends Component<*, State> {
|
||||||
<div id = 'videoNotAvailableScreen'>
|
<div id = 'videoNotAvailableScreen'>
|
||||||
<div id = 'avatarContainer'>
|
<div id = 'avatarContainer'>
|
||||||
<StatelessAvatar
|
<StatelessAvatar
|
||||||
color = { getAvatarColor(userID) }
|
color = { getAvatarColor(userID, customAvatarBackgrounds) }
|
||||||
id = 'avatar'
|
id = 'avatar'
|
||||||
initials = { getInitials(displayName) }
|
initials = { getInitials(displayName) }
|
||||||
url = { avatarURL } />)
|
url = { avatarURL } />)
|
||||||
|
@ -218,6 +227,12 @@ export default class AlwaysOnTop extends Component<*, State> {
|
||||||
window.addEventListener('mousemove', this._mouseMove);
|
window.addEventListener('mousemove', this._mouseMove);
|
||||||
|
|
||||||
this._hideToolbarAfterTimeout();
|
this._hideToolbarAfterTimeout();
|
||||||
|
api.getCustomAvatarBackgrounds()
|
||||||
|
.then(res =>
|
||||||
|
this.setState({
|
||||||
|
customAvatarBackgrounds: res.avatarBackgrounds || []
|
||||||
|
}))
|
||||||
|
.catch(console.error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -10,6 +10,11 @@ import { StatelessAvatar } from '.';
|
||||||
|
|
||||||
export type Props = {
|
export type Props = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom avatar backgrounds from branding.
|
||||||
|
*/
|
||||||
|
_customAvatarBackgrounds: Array<string>,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The string we base the initials on (this is generated from a list of precedences).
|
* The string we base the initials on (this is generated from a list of precedences).
|
||||||
*/
|
*/
|
||||||
|
@ -133,6 +138,7 @@ class Avatar<P: Props> extends PureComponent<P, State> {
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
|
_customAvatarBackgrounds,
|
||||||
_initialsBase,
|
_initialsBase,
|
||||||
_loadableAvatarUrl,
|
_loadableAvatarUrl,
|
||||||
className,
|
className,
|
||||||
|
@ -172,7 +178,7 @@ class Avatar<P: Props> extends PureComponent<P, State> {
|
||||||
|
|
||||||
if (initials) {
|
if (initials) {
|
||||||
if (dynamicColor) {
|
if (dynamicColor) {
|
||||||
avatarProps.color = getAvatarColor(colorBase || _initialsBase);
|
avatarProps.color = getAvatarColor(colorBase || _initialsBase, _customAvatarBackgrounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
avatarProps.initials = initials;
|
avatarProps.initials = initials;
|
||||||
|
@ -211,6 +217,7 @@ export function _mapStateToProps(state: Object, ownProps: Props) {
|
||||||
const _initialsBase = _participant?.name ?? displayName;
|
const _initialsBase = _participant?.name ?? displayName;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
_customAvatarBackgrounds: state['features/dynamic-branding'].avatarBackgrounds,
|
||||||
_initialsBase,
|
_initialsBase,
|
||||||
_loadableAvatarUrl: _participant?.loadableAvatarUrl,
|
_loadableAvatarUrl: _participant?.loadableAvatarUrl,
|
||||||
colorBase: !colorBase && _participant ? _participant.id : colorBase
|
colorBase: !colorBase && _participant ? _participant.id : colorBase
|
||||||
|
|
|
@ -125,7 +125,7 @@ export default class StatelessAvatar extends AbstractStatelessAvatar<Props> {
|
||||||
const { size } = this.props;
|
const { size } = this.props;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
backgroundColor: color || undefined,
|
background: color || undefined,
|
||||||
fontSize: size ? size * 0.5 : '180%',
|
fontSize: size ? size * 0.5 : '180%',
|
||||||
height: size || '100%',
|
height: size || '100%',
|
||||||
width: size || '100%'
|
width: size || '100%'
|
||||||
|
|
|
@ -16,9 +16,13 @@ const AVATAR_OPACITY = 0.4;
|
||||||
* Generates the background color of an initials based avatar.
|
* Generates the background color of an initials based avatar.
|
||||||
*
|
*
|
||||||
* @param {string?} initials - The initials of the avatar.
|
* @param {string?} initials - The initials of the avatar.
|
||||||
|
* @param {Array<strig>} customAvatarBackgrounds - Custom avatar background values.
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
export function getAvatarColor(initials: ?string) {
|
export function getAvatarColor(initials: ?string, customAvatarBackgrounds: Array<string>) {
|
||||||
|
const hasCustomAvatarBackgronds = customAvatarBackgrounds && customAvatarBackgrounds.length;
|
||||||
|
const colorsBase = hasCustomAvatarBackgronds ? customAvatarBackgrounds : AVATAR_COLORS;
|
||||||
|
|
||||||
let colorIndex = 0;
|
let colorIndex = 0;
|
||||||
|
|
||||||
if (initials) {
|
if (initials) {
|
||||||
|
@ -28,10 +32,10 @@ export function getAvatarColor(initials: ?string) {
|
||||||
nameHash += s.codePointAt(0);
|
nameHash += s.codePointAt(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
colorIndex = nameHash % AVATAR_COLORS.length;
|
colorIndex = nameHash % colorsBase.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
return `rgba(${AVATAR_COLORS[colorIndex]}, ${AVATAR_OPACITY})`;
|
return hasCustomAvatarBackgronds ? colorsBase[colorIndex] : `rgba(${colorsBase[colorIndex]}, ${AVATAR_OPACITY})`;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -15,6 +15,15 @@ import {
|
||||||
const STORE_NAME = 'features/dynamic-branding';
|
const STORE_NAME = 'features/dynamic-branding';
|
||||||
|
|
||||||
const DEFAULT_STATE = {
|
const DEFAULT_STATE = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The pool of avatar backgrounds.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
* @type {Array<string>}
|
||||||
|
*/
|
||||||
|
avatarBackgrounds: [],
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The custom background color for the LargeVideo.
|
* The custom background color for the LargeVideo.
|
||||||
*
|
*
|
||||||
|
@ -112,10 +121,12 @@ ReducerRegistry.register(STORE_NAME, (state = DEFAULT_STATE, action) => {
|
||||||
didPageUrl,
|
didPageUrl,
|
||||||
inviteDomain,
|
inviteDomain,
|
||||||
logoClickUrl,
|
logoClickUrl,
|
||||||
logoImageUrl
|
logoImageUrl,
|
||||||
|
avatarBackgrounds
|
||||||
} = action.value;
|
} = action.value;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
avatarBackgrounds,
|
||||||
backgroundColor,
|
backgroundColor,
|
||||||
backgroundImageUrl,
|
backgroundImageUrl,
|
||||||
defaultBranding,
|
defaultBranding,
|
||||||
|
|
Loading…
Reference in New Issue