diff --git a/src/components/views/elements/Flair.js b/src/components/views/elements/Flair.js index 4a34dac0de..25a8d538e1 100644 --- a/src/components/views/elements/Flair.js +++ b/src/components/views/elements/Flair.js @@ -72,24 +72,19 @@ export default class Flair extends React.Component { this.state = { profiles: [], }; - this.onRoomStateEvents = this.onRoomStateEvents.bind(this); } componentWillUnmount() { this._unmounted = true; - this.context.matrixClient.removeListener('RoomState.events', this.onRoomStateEvents); } componentWillMount() { this._unmounted = false; - this._generateAvatars(); - this.context.matrixClient.on('RoomState.events', this.onRoomStateEvents); + this._generateAvatars(this.props.groups); } - onRoomStateEvents(event) { - if (event.getType() === 'm.room.related_groups' && FlairStore.groupSupport()) { - this._generateAvatars(); - } + componentWillReceiveProps(newProps) { + this._generateAvatars(newProps.groups); } async _getGroupProfiles(groups) { @@ -106,23 +101,7 @@ export default class Flair extends React.Component { return profiles.filter((p) => p !== null); } - async _generateAvatars() { - let groups = await FlairStore.getPublicisedGroupsCached(this.context.matrixClient, this.props.userId); - if (this.props.roomId && this.props.showRelated) { - const relatedGroupsEvent = this.context.matrixClient - .getRoom(this.props.roomId) - .currentState - .getStateEvents('m.room.related_groups', ''); - const relatedGroups = relatedGroupsEvent ? - relatedGroupsEvent.getContent().groups || [] : []; - if (relatedGroups && relatedGroups.length > 0) { - groups = groups.filter((groupId) => { - return relatedGroups.includes(groupId); - }); - } else { - groups = []; - } - } + async _generateAvatars(groups) { if (!groups || groups.length === 0) { return; } @@ -148,13 +127,7 @@ export default class Flair extends React.Component { } Flair.propTypes = { - userId: PropTypes.string, - - // Whether to show only the flair associated with related groups of the given room, - // or all flair associated with a user. - showRelated: PropTypes.bool, - // The room that this flair will be displayed in. Optional. Only applies when showRelated = true. - roomId: PropTypes.string, + groups: PropTypes.arrayOf(PropTypes.string), }; // TODO: We've decided that all components should follow this pattern, which means removing withMatrixClient and using diff --git a/src/components/views/messages/SenderProfile.js b/src/components/views/messages/SenderProfile.js index 28064070cb..5ca2fc6ed8 100644 --- a/src/components/views/messages/SenderProfile.js +++ b/src/components/views/messages/SenderProfile.js @@ -17,50 +17,128 @@ 'use strict'; import React from 'react'; +import PropTypes from 'prop-types'; +import {MatrixClient} from 'matrix-js-sdk'; import sdk from '../../../index'; import Flair from '../elements/Flair.js'; +import FlairStore from '../../../stores/FlairStore'; import { _t } from '../../../languageHandler'; -export default function SenderProfile(props) { - const EmojiText = sdk.getComponent('elements.EmojiText'); - const {mxEvent} = props; - const name = mxEvent.sender ? mxEvent.sender.name : mxEvent.getSender(); - const {msgtype} = mxEvent.getContent(); +export default React.createClass({ + displayName: 'SenderProfile', + propTypes: { + mxEvent: PropTypes.object.isRequired, // event whose sender we're showing + text: PropTypes.string, // Text to show. Defaults to sender name + onClick: PropTypes.func, + }, - if (msgtype === 'm.emote') { - return ; // emote message must include the name so don't duplicate it - } + contextTypes: { + matrixClient: PropTypes.instanceOf(MatrixClient), + }, - const nameElem = { name || '' }; + getInitialState() { + return { + userGroups: null, + relatedGroups: [], + }; + }, - // Name + flair - const nameFlair = - - { nameElem } - - { props.enableFlair ? - - : null + componentWillMount() { + this.unmounted = false; + this._updateRelatedGroups(); + + FlairStore.getPublicisedGroupsCached( + this.context.matrixClient, this.props.mxEvent.getSender(), + ).then((userGroups) => { + if (this.unmounted) return; + this.setState({userGroups}); + }); + + this.context.matrixClient.on('RoomState.events', this.onRoomStateEvents); + }, + + componentWillUnmount() { + this.unmounted = true; + this.context.matrixClient.removeListener('RoomState.events', this.onRoomStateEvents); + }, + + onRoomStateEvents(event) { + if (event.getType() === 'm.room.related_groups' && + event.getRoomId() === this.props.mxEvent.getRoomId() + ) { + this._updateRelatedGroups(); } - ; + }, - const content = props.text ? - - { _t(props.text, { senderName: () => nameElem }) } - : nameFlair; + _updateRelatedGroups() { + if (this.unmounted) return; + const relatedGroupsEvent = this.context.matrixClient + .getRoom(this.props.mxEvent.getRoomId()) + .currentState + .getStateEvents('m.room.related_groups', ''); + this.setState({ + relatedGroups: relatedGroupsEvent ? + relatedGroupsEvent.getContent().groups || [] + : [], + }); + }, - return ( -
- { content } -
- ); -} + _getDisplayedGroups(userGroups, relatedGroups) { + let displayedGroups = userGroups || []; + if (relatedGroups && relatedGroups.length > 0) { + displayedGroups = displayedGroups.filter((groupId) => { + return relatedGroups.includes(groupId); + }); + } else { + displayedGroups = []; + } + return displayedGroups; + }, -SenderProfile.propTypes = { - mxEvent: React.PropTypes.object.isRequired, // event whose sender we're showing - text: React.PropTypes.string, // Text to show. Defaults to sender name - onClick: React.PropTypes.func, -}; + render() { + const EmojiText = sdk.getComponent('elements.EmojiText'); + const {mxEvent} = this.props; + let name = mxEvent.sender ? mxEvent.sender.name : mxEvent.getSender(); + const {msgtype} = mxEvent.getContent(); + + if (msgtype === 'm.emote') { + return ; // emote message must include the name so don't duplicate it + } + + let flair =
; + if (this.props.enableFlair) { + const displayedGroups = this._getDisplayedGroups( + this.state.userGroups, this.state.relatedGroups, + ); + + // Backwards-compatible replacing of "(IRC)" with AS user flair + name = displayedGroups.length > 0 ? name.replace(' (IRC)', '') : name; + + flair = ; + } + + const nameElem = { name || '' }; + + // Name + flair + const nameFlair = + + { nameElem } + + { flair } + ; + + const content = this.props.text ? + + { _t(this.props.text, { senderName: () => nameElem }) } + : nameFlair; + + return ( +
+ { content } +
+ ); + }, +});