mirror of
https://github.com/element-hq/element-web.git
synced 2024-12-11 10:32:09 +03:00
Merge pull request #1227 from matrix-org/luke/feature-matrixto-timeline-pills
Decorate matrix.to anchor tags as mx_UserPill and mx_RoomPill
This commit is contained in:
commit
d179398cf2
2 changed files with 55 additions and 25 deletions
|
@ -113,31 +113,6 @@ let emojiDecorator = {
|
||||||
* Returns a composite decorator which has access to provided scope.
|
* Returns a composite decorator which has access to provided scope.
|
||||||
*/
|
*/
|
||||||
export function getScopedRTDecorators(scope: any): CompositeDecorator {
|
export function getScopedRTDecorators(scope: any): CompositeDecorator {
|
||||||
let MemberAvatar = sdk.getComponent('avatars.MemberAvatar');
|
|
||||||
|
|
||||||
let usernameDecorator = {
|
|
||||||
strategy: (contentBlock, callback) => {
|
|
||||||
findWithRegex(USERNAME_REGEX, contentBlock, callback);
|
|
||||||
},
|
|
||||||
component: (props) => {
|
|
||||||
let member = scope.room.getMember(props.children[0].props.text);
|
|
||||||
// unused until we make these decorators immutable (autocomplete needed)
|
|
||||||
let name = member ? member.name : null;
|
|
||||||
let avatar = member ? <MemberAvatar member={member} width={16} height={16}/> : null;
|
|
||||||
return <span className="mx_UserPill">{avatar}{props.children}</span>;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let roomDecorator = {
|
|
||||||
strategy: (contentBlock, callback) => {
|
|
||||||
findWithRegex(ROOM_REGEX, contentBlock, callback);
|
|
||||||
},
|
|
||||||
component: (props) => {
|
|
||||||
return <span className="mx_RoomPill">{props.children}</span>;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO Re-enable usernameDecorator and roomDecorator
|
|
||||||
return [emojiDecorator];
|
return [emojiDecorator];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,8 @@ import SdkConfig from '../../../SdkConfig';
|
||||||
import dis from '../../../dispatcher';
|
import dis from '../../../dispatcher';
|
||||||
import { _t } from '../../../languageHandler';
|
import { _t } from '../../../languageHandler';
|
||||||
import UserSettingsStore from "../../../UserSettingsStore";
|
import UserSettingsStore from "../../../UserSettingsStore";
|
||||||
|
import MatrixClientPeg from '../../../MatrixClientPeg';
|
||||||
|
import {RoomMember} from 'matrix-js-sdk';
|
||||||
|
|
||||||
linkifyMatrix(linkify);
|
linkifyMatrix(linkify);
|
||||||
|
|
||||||
|
@ -80,6 +82,10 @@ module.exports = React.createClass({
|
||||||
componentDidMount: function() {
|
componentDidMount: function() {
|
||||||
this._unmounted = false;
|
this._unmounted = false;
|
||||||
|
|
||||||
|
// pillifyLinks BEFORE linkifyElement because plain room/user URLs in the composer
|
||||||
|
// are still sent as plaintext URLs. If these are ever pillified in the composer,
|
||||||
|
// we should be pillify them here by doing the linkifying BEFORE the pillifying.
|
||||||
|
this.pillifyLinks(this.refs.content.children);
|
||||||
linkifyElement(this.refs.content, linkifyMatrix.options);
|
linkifyElement(this.refs.content, linkifyMatrix.options);
|
||||||
this.calculateUrlPreview();
|
this.calculateUrlPreview();
|
||||||
|
|
||||||
|
@ -162,6 +168,55 @@ module.exports = React.createClass({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
pillifyLinks: function(nodes) {
|
||||||
|
const MemberAvatar = sdk.getComponent('avatars.MemberAvatar');
|
||||||
|
const RoomAvatar = sdk.getComponent('avatars.RoomAvatar');
|
||||||
|
for (let i = 0; i < nodes.length; i++) {
|
||||||
|
const node = nodes[i];
|
||||||
|
if (node.tagName === "A" && node.getAttribute("href")) {
|
||||||
|
const href = node.getAttribute("href");
|
||||||
|
// HtmlUtils transforms `matrix.to` links to local links, so match against
|
||||||
|
// user or room app links.
|
||||||
|
const match = /^#\/(user|room)\/(.*)$/.exec(href) || [];
|
||||||
|
const resourceType = match[1]; // "user" or "room"
|
||||||
|
const resourceId = match[2]; // user ID or room ID
|
||||||
|
if (match && resourceType && resourceId) {
|
||||||
|
let avatar;
|
||||||
|
let roomId;
|
||||||
|
let room;
|
||||||
|
let member;
|
||||||
|
switch (resourceType) {
|
||||||
|
case "user":
|
||||||
|
roomId = this.props.mxEvent.getRoomId();
|
||||||
|
room = MatrixClientPeg.get().getRoom(roomId);
|
||||||
|
member = room.getMember(resourceId) ||
|
||||||
|
new RoomMember(null, resourceId);
|
||||||
|
avatar = <MemberAvatar member={member} width={16} height={16} name={resourceId}/>;
|
||||||
|
break;
|
||||||
|
case "room":
|
||||||
|
room = resourceId[0] === '#' ?
|
||||||
|
MatrixClientPeg.get().getRooms().find((r) => {
|
||||||
|
return r.getCanonicalAlias() === resourceId;
|
||||||
|
}) : MatrixClientPeg.get().getRoom(resourceId);
|
||||||
|
if (room) {
|
||||||
|
avatar = <RoomAvatar room={room} width={16} height={16}/>;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (avatar) {
|
||||||
|
const avatarContainer = document.createElement('span');
|
||||||
|
node.className = "mx_MTextBody_pill " +
|
||||||
|
(resourceType === "user" ? "mx_UserPill" : "mx_RoomPill");
|
||||||
|
ReactDOM.render(avatar, avatarContainer);
|
||||||
|
node.insertBefore(avatarContainer, node.firstChild);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (node.children && node.children.length) {
|
||||||
|
this.pillifyLinks(node.children);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
findLinks: function(nodes) {
|
findLinks: function(nodes) {
|
||||||
var links = [];
|
var links = [];
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue