From 3addb924b1caa60d96886596d9245421d2b01f0a Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Tue, 28 Nov 2017 10:04:34 +0000 Subject: [PATCH 1/4] Replace (IRC) with flair If a user has public groups that are honoured in their flair, remove the (IRC) to give the appearance that the flair replaces it. --- src/components/views/elements/Flair.js | 37 +---- .../views/messages/SenderProfile.js | 140 +++++++++++++----- 2 files changed, 109 insertions(+), 68 deletions(-) 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..e2f2eb3cea 100644 --- a/src/components/views/messages/SenderProfile.js +++ b/src/components/views/messages/SenderProfile.js @@ -17,50 +17,118 @@ '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 { + groups: 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((groups) => { + if (this.unmounted) return; + this.setState({groups}); + }); + + 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 } -
- ); -} + render() { + const EmojiText = sdk.getComponent('elements.EmojiText'); + const {mxEvent} = this.props; + let name = mxEvent.sender ? mxEvent.sender.name : mxEvent.getSender(); + const {msgtype} = mxEvent.getContent(); -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, -}; + if (msgtype === 'm.emote') { + return ; // emote message must include the name so don't duplicate it + } + + let groups = this.state.groups || []; + if (this.state.relatedGroups && this.state.relatedGroups.length > 0) { + groups = groups.filter((groupId) => { + return this.state.relatedGroups.includes(groupId); + }); + } else { + groups = []; + } + + name = groups.length > 0 ? name.replace(' (IRC)', '') : name; + + const nameElem = { name || '' }; + + // Name + flair + const nameFlair = + + { nameElem } + + { this.props.enableFlair ? + + : null + } + ; + + const content = this.props.text ? + + { _t(this.props.text, { senderName: () => nameElem }) } + : nameFlair; + + return ( +
+ { content } +
+ ); + }, +}); From b748c6288064e0557f349cf9eb4b11b6dc427b00 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Tue, 28 Nov 2017 15:40:36 +0000 Subject: [PATCH 2/4] Renames for clarification --- src/components/views/messages/SenderProfile.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/components/views/messages/SenderProfile.js b/src/components/views/messages/SenderProfile.js index e2f2eb3cea..d2ef8fe3a3 100644 --- a/src/components/views/messages/SenderProfile.js +++ b/src/components/views/messages/SenderProfile.js @@ -38,7 +38,7 @@ export default React.createClass({ getInitialState() { return { - groups: null, + userGroups: null, relatedGroups: [], }; }, @@ -49,9 +49,9 @@ export default React.createClass({ FlairStore.getPublicisedGroupsCached( this.context.matrixClient, this.props.mxEvent.getSender(), - ).then((groups) => { + ).then((userGroups) => { if (this.unmounted) return; - this.setState({groups}); + this.setState({userGroups}); }); this.context.matrixClient.on('RoomState.events', this.onRoomStateEvents); @@ -93,16 +93,16 @@ export default React.createClass({ return ; // emote message must include the name so don't duplicate it } - let groups = this.state.groups || []; + let displayedGroups = this.state.userGroups || []; if (this.state.relatedGroups && this.state.relatedGroups.length > 0) { - groups = groups.filter((groupId) => { + displayedGroups = displayedGroups.filter((groupId) => { return this.state.relatedGroups.includes(groupId); }); } else { - groups = []; + displayedGroups = []; } - name = groups.length > 0 ? name.replace(' (IRC)', '') : name; + name = displayedGroups.length > 0 ? name.replace(' (IRC)', '') : name; const nameElem = { name || '' }; @@ -114,7 +114,7 @@ export default React.createClass({ { this.props.enableFlair ? : null } From b32e4a57bc99a1efbd7422514f2f4ca169122e61 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Tue, 28 Nov 2017 15:46:23 +0000 Subject: [PATCH 3/4] Factor out _getDisplayeDGroups --- .../views/messages/SenderProfile.js | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/components/views/messages/SenderProfile.js b/src/components/views/messages/SenderProfile.js index d2ef8fe3a3..1d21ffd0fd 100644 --- a/src/components/views/messages/SenderProfile.js +++ b/src/components/views/messages/SenderProfile.js @@ -83,6 +83,18 @@ export default React.createClass({ }); }, + _getDisplayedGroups(userGroups, relatedGroups) { + let displayedGroups = userGroups || []; + if (relatedGroups && relatedGroups.length > 0) { + displayedGroups = displayedGroups.filter((groupId) => { + return relatedGroups.includes(groupId); + }); + } else { + displayedGroups = []; + } + return displayedGroups; + }, + render() { const EmojiText = sdk.getComponent('elements.EmojiText'); const {mxEvent} = this.props; @@ -93,14 +105,9 @@ export default React.createClass({ return ; // emote message must include the name so don't duplicate it } - let displayedGroups = this.state.userGroups || []; - if (this.state.relatedGroups && this.state.relatedGroups.length > 0) { - displayedGroups = displayedGroups.filter((groupId) => { - return this.state.relatedGroups.includes(groupId); - }); - } else { - displayedGroups = []; - } + const displayedGroups = this._getDisplayedGroups( + this.state.userGroups, this.state.relatedGroups, + ); name = displayedGroups.length > 0 ? name.replace(' (IRC)', '') : name; From 204bbebfca696a331b9e4b1260c72b6135998823 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Tue, 28 Nov 2017 15:49:11 +0000 Subject: [PATCH 4/4] Only calculate displayed groups if flair enabled --- .../views/messages/SenderProfile.js | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/components/views/messages/SenderProfile.js b/src/components/views/messages/SenderProfile.js index 1d21ffd0fd..5ca2fc6ed8 100644 --- a/src/components/views/messages/SenderProfile.js +++ b/src/components/views/messages/SenderProfile.js @@ -105,11 +105,20 @@ export default React.createClass({ return ; // emote message must include the name so don't duplicate it } - const displayedGroups = this._getDisplayedGroups( - this.state.userGroups, this.state.relatedGroups, - ); + let flair =
; + if (this.props.enableFlair) { + const displayedGroups = this._getDisplayedGroups( + this.state.userGroups, this.state.relatedGroups, + ); - name = displayedGroups.length > 0 ? name.replace(' (IRC)', '') : name; + // Backwards-compatible replacing of "(IRC)" with AS user flair + name = displayedGroups.length > 0 ? name.replace(' (IRC)', '') : name; + + flair = ; + } const nameElem = { name || '' }; @@ -118,13 +127,7 @@ export default React.createClass({ { nameElem } - { this.props.enableFlair ? - - : null - } + { flair } ; const content = this.props.text ?