Factor out shared logic in two code-paths for pill rendering

This isn't an entirely side-effect-free refactoring:
 - the text of the timeline pills is now either the room ID/alias or user ID/ display name of the linked resource (which means that until we do a roundtrip to get user displaynames, mentions for users not in the current room will have their user IDs shown instead of what was in the link body).
 - timeline links to rooms without avatars are now rendered as links
 - fixed issue that would throw an error whilst rendering (i.e. unusable client) a room link to a room that the client doesn't know about
This commit is contained in:
Luke Barnard 2017-07-21 13:41:23 +01:00
parent 8c531a85e9
commit 7db7192701
3 changed files with 132 additions and 100 deletions

View file

@ -26,7 +26,6 @@ import Promise from 'bluebird';
import MatrixClientPeg from '../../../MatrixClientPeg';
import type {MatrixClient} from 'matrix-js-sdk/lib/matrix';
import {RoomMember} from 'matrix-js-sdk';
import SlashCommands from '../../../SlashCommands';
import KeyCode from '../../../KeyCode';
import Modal from '../../../Modal';
@ -43,10 +42,6 @@ import {Completion} from "../../../autocomplete/Autocompleter";
import Markdown from '../../../Markdown';
import ComposerHistoryManager from '../../../ComposerHistoryManager';
import MessageComposerStore from '../../../stores/MessageComposerStore';
import { getDisplayAliasForRoom } from '../../../Rooms';
import {MATRIXTO_URL_PATTERN} from '../../../linkify-matrix';
const REGEX_MATRIXTO = new RegExp(MATRIXTO_URL_PATTERN);
import {asciiRegexp, shortnameToUnicode, emojioneList, asciiList, mapUnicodeToShort} from 'emojione';
const EMOJI_SHORTNAMES = Object.keys(emojioneList);
@ -188,56 +183,10 @@ export default class MessageComposerInput extends React.Component {
decorators.push({
strategy: this.findLinkEntities.bind(this),
component: (props) => {
const MemberAvatar = sdk.getComponent('avatars.MemberAvatar');
const RoomAvatar = sdk.getComponent('avatars.RoomAvatar');
const Pill = sdk.getComponent('elements.Pill');
const {url} = Entity.get(props.entityKey).getData();
// Default to the empty array if no match for simplicity
// resource and prefix will be undefined instead of throwing
const matrixToMatch = REGEX_MATRIXTO.exec(url) || [];
const resource = matrixToMatch[1]; // The room/user ID
const prefix = matrixToMatch[2]; // The first character of prefix
// Default to the room/user ID
let linkText = resource;
const isUserPill = prefix === '@';
const isRoomPill = prefix === '#' || prefix === '!';
const classes = classNames({
"mx_UserPill": isUserPill,
"mx_RoomPill": isRoomPill,
});
let avatar = null;
if (isUserPill) {
// If this user is not a member of this room, default to the empty
// member. This could be improved by doing an async profile lookup.
const member = this.props.room.getMember(resource) ||
new RoomMember(null, resource);
linkText = member.name;
avatar = member ? <MemberAvatar member={member} width={16} height={16}/> : null;
} else if (isRoomPill) {
const room = prefix === '#' ?
MatrixClientPeg.get().getRooms().find((r) => {
return r.getCanonicalAlias() === resource;
}) : MatrixClientPeg.get().getRoom(resource);
linkText = getDisplayAliasForRoom(room) || resource;
avatar = room ? <RoomAvatar room={room} width={16} height={16}/> : null;
}
if (isUserPill || isRoomPill) {
return (
<span className={classes}>
{avatar}
{linkText}
</span>
);
if (Pill.isPillUrl(url)) {
return <Pill url={url} room={this.props.room}/>;
}
return (