jitsi-meet/react/features/toolbox/components/ProfileButton.web.js
virtuacoplenny 28013f6ffa ref(avatars): remove Avatar.js (#2289)
* ref(avatars): remove Avatar.js

- Rely on redux getting updated with new participant state
and any calls to getAvatarURL passing in the redux
participant state. This way the state within Avatar.js can
be removed.
- Clean up methods on UI.js. Because all state is in the
store, separate methods for updating the avatar aren't as
necessary. Instead centralize accessing of the avatar for
components outside of redux and centralize the call to
update avatars for non-react components.
- Controversial: cache a participant's avatarURL on the
participant state. Currently the participant's avatarURL
that is generated without jwt (which sets the avatarURL directly)
is not cached. Without cache, there can be many redundant
calls to APP.API.notifyAvatarChanged.

* Leverage middleware timing to diff avatars

One alternative implementation is to leverage middleware's
ability to intercept updates before and after redux has
upated and then compare avatarURLs.

* kill UI.getAvatarUrl

* profile button sets its own avatar url (solves update timing)

* remove calls to updating avatar outside of middleware

* update UI.js doc

* remove left over logic from initial implementation

* try to move local user fallback into selector func

* default to id 'local' in selector
2017-12-19 17:11:54 -06:00

143 lines
3.4 KiB
JavaScript

/* @flow */
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { TOOLBAR_PROFILE_TOGGLED, sendAnalyticsEvent } from '../../analytics';
import {
getAvatarURL,
getLocalParticipant
} from '../../base/participants';
import UIEvents from '../../../../service/UI/UIEvents';
import ToolbarButton from './ToolbarButton';
declare var APP: Object;
/**
* The default configuration for the button.
*
* @type {Object}
*/
const DEFAULT_BUTTON_CONFIGURATION = {
buttonName: 'profile',
classNames: [ 'button' ],
enabled: true,
id: 'toolbar_button_profile',
tooltipKey: 'profile.setDisplayNameLabel'
};
/**
* React {@code Component} for the profile button.
*
* @extends Component
*/
class ProfileButton extends Component<*> {
_onClick: Function;
/**
* {@code ProfileButton}'s property types.
*
* @static
*/
static propTypes = {
/**
* The redux representation of the local participant.
*/
_localParticipant: PropTypes.object,
/**
* Whether the button support clicking or not.
*/
_unclickable: PropTypes.bool,
/**
* Whether the side panel is opened or not.
*/
toggled: PropTypes.bool,
/**
* From which side tooltips should display. Will be re-used for
* displaying the inline dialog for video quality adjustment.
*/
tooltipPosition: PropTypes.string
};
/**
* Initializes a new {@code ProfileButton} instance.
*
* @param {Object} props - The read-only properties with which the new
* instance is to be initialized.
*/
constructor(props) {
super(props);
// Bind event handlers so they are only bound once for every instance.
this._onClick = this._onClick.bind(this);
}
/**
* Implements React's {@link Component#render()}.
*
* @inheritdoc
* @returns {ReactElement}
*/
render() {
const {
_localParticipant,
_unclickable,
tooltipPosition,
toggled
} = this.props;
const buttonConfiguration = {
...DEFAULT_BUTTON_CONFIGURATION,
unclickable: _unclickable,
toggled
};
return (
<ToolbarButton
button = { buttonConfiguration }
onClick = { this._onClick }
tooltipPosition = { tooltipPosition }>
<img
id = 'avatar'
src = { getAvatarURL(_localParticipant) } />
</ToolbarButton>
);
}
/**
* Click handler for the button.
*
* @returns {void}
*/
_onClick() {
if (!this.props._unclickable) {
sendAnalyticsEvent(TOOLBAR_PROFILE_TOGGLED);
APP.UI.emitEvent(UIEvents.TOGGLE_PROFILE);
}
}
}
/**
* Maps (parts of) the Redux state to the associated {@code ProfileButton}
* component's props.
*
* @param {Object} state - The Redux state.
* @private
* @returns {{
* _localParticipant: Object,
* _unclickable: boolean
* }}
*/
function _mapStateToProps(state) {
return {
_localParticipant: getLocalParticipant(state),
_unclickable: !state['features/base/jwt'].isGuest
};
}
export default connect(_mapStateToProps)(ProfileButton);