Update pill processing to handle better permalinks

This commit is contained in:
Travis Ralston 2019-09-30 20:27:51 -06:00
parent 2cb0b4903a
commit 2824f468d9
3 changed files with 45 additions and 26 deletions

View file

@ -1,6 +1,7 @@
/* /*
Copyright 2017 Vector Creations Ltd Copyright 2017 Vector Creations Ltd
Copyright 2018 New Vector Ltd Copyright 2018 New Vector Ltd
Copyright 2019 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -22,23 +23,21 @@ import classNames from 'classnames';
import { Room, RoomMember, MatrixClient } from 'matrix-js-sdk'; import { Room, RoomMember, MatrixClient } from 'matrix-js-sdk';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import MatrixClientPeg from '../../../MatrixClientPeg'; import MatrixClientPeg from '../../../MatrixClientPeg';
import { MATRIXTO_URL_PATTERN } from '../../../linkify-matrix';
import { getDisplayAliasForRoom } from '../../../Rooms'; import { getDisplayAliasForRoom } from '../../../Rooms';
import FlairStore from "../../../stores/FlairStore"; import FlairStore from "../../../stores/FlairStore";
import {getPrimaryPermalinkEntity} from "../../../utils/permalinks/RoomPermalinkCreator";
const REGEX_MATRIXTO = new RegExp(MATRIXTO_URL_PATTERN);
// For URLs of matrix.to links in the timeline which have been reformatted by // For URLs of matrix.to links in the timeline which have been reformatted by
// HttpUtils transformTags to relative links. This excludes event URLs (with `[^\/]*`) // HttpUtils transformTags to relative links. This excludes event URLs (with `[^\/]*`)
const REGEX_LOCAL_MATRIXTO = /^#\/(?:user|room|group)\/(([#!@+])[^/]*)$/; const REGEX_LOCAL_PERMALINK = /^#\/(?:user|room|group)\/(([#!@+])[^/]*)$/;
const Pill = createReactClass({ const Pill = createReactClass({
statics: { statics: {
isPillUrl: (url) => { isPillUrl: (url) => {
return !!REGEX_MATRIXTO.exec(url); return !!getPrimaryPermalinkEntity(url);
}, },
isMessagePillUrl: (url) => { isMessagePillUrl: (url) => {
return !!REGEX_LOCAL_MATRIXTO.exec(url); return !!REGEX_LOCAL_PERMALINK.exec(url);
}, },
roomNotifPos: (text) => { roomNotifPos: (text) => {
return text.indexOf("@room"); return text.indexOf("@room");
@ -95,22 +94,21 @@ const Pill = createReactClass({
}, },
async componentWillReceiveProps(nextProps) { async componentWillReceiveProps(nextProps) {
let regex = REGEX_MATRIXTO;
if (nextProps.inMessage) {
regex = REGEX_LOCAL_MATRIXTO;
}
let matrixToMatch;
let resourceId; let resourceId;
let prefix; let prefix;
if (nextProps.url) { if (nextProps.url) {
if (nextProps.inMessage) {
// Default to the empty array if no match for simplicity // Default to the empty array if no match for simplicity
// resource and prefix will be undefined instead of throwing // resource and prefix will be undefined instead of throwing
matrixToMatch = regex.exec(nextProps.url) || []; const matrixToMatch = REGEX_LOCAL_PERMALINK.exec(nextProps.url) || [];
resourceId = matrixToMatch[1]; // The room/user ID resourceId = matrixToMatch[1]; // The room/user ID
prefix = matrixToMatch[2]; // The first character of prefix prefix = matrixToMatch[2]; // The first character of prefix
} else {
resourceId = getPrimaryPermalinkEntity(nextProps.url);
prefix = resourceId ? resourceId[0] : undefined;
}
} }
const pillType = this.props.type || { const pillType = this.props.type || {

View file

@ -48,13 +48,11 @@ import Markdown from '../../../Markdown';
import MessageComposerStore from '../../../stores/MessageComposerStore'; import MessageComposerStore from '../../../stores/MessageComposerStore';
import ContentMessages from '../../../ContentMessages'; import ContentMessages from '../../../ContentMessages';
import {MATRIXTO_URL_PATTERN} from '../../../linkify-matrix';
import EMOJIBASE from 'emojibase-data/en/compact.json'; import EMOJIBASE from 'emojibase-data/en/compact.json';
import EMOTICON_REGEX from 'emojibase-regex/emoticon'; import EMOTICON_REGEX from 'emojibase-regex/emoticon';
import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore"; import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
import {makeUserPermalink} from "../../../utils/permalinks/RoomPermalinkCreator"; import {getPrimaryPermalinkEntity, makeUserPermalink} from "../../../utils/permalinks/RoomPermalinkCreator";
import ReplyPreview from "./ReplyPreview"; import ReplyPreview from "./ReplyPreview";
import RoomViewStore from '../../../stores/RoomViewStore'; import RoomViewStore from '../../../stores/RoomViewStore';
import ReplyThread from "../elements/ReplyThread"; import ReplyThread from "../elements/ReplyThread";
@ -224,18 +222,15 @@ export default class MessageComposerInput extends React.Component {
// special case links // special case links
if (tag === 'a') { if (tag === 'a') {
const href = el.getAttribute('href'); const href = el.getAttribute('href');
let m; const permalinkEntity = getPrimaryPermalinkEntity(href);
if (href) { if (permalinkEntity) {
m = href.match(MATRIXTO_URL_PATTERN);
}
if (m) {
return { return {
object: 'inline', object: 'inline',
type: 'pill', type: 'pill',
data: { data: {
href, href,
completion: el.innerText, completion: el.innerText,
completionId: m[1], completionId: permalinkEntity,
}, },
}; };
} else { } else {

View file

@ -321,6 +321,32 @@ export function tryTransformPermalinkToLocalHref(permalink: string): string {
return permalink; return permalink;
} }
export function getPrimaryPermalinkEntity(permalink: string): string {
try {
let permalinkParts = parsePermalink(permalink);
// If not a permalink, try the vector patterns.
if (!permalinkParts) {
let m = permalink.match(matrixLinkify.VECTOR_URL_PATTERN);
if (m) {
// A bit of a hack, but it gets the job done
const handler = new RiotPermalinkConstructor("http://localhost");
const entityInfo = m[1].split('#').slice(1).join('#');
permalinkParts = handler.parsePermalink(`http://localhost/#${entityInfo}`);
}
}
if (!permalinkParts) return null; // not processable
if (permalinkParts.userId) return permalinkParts.userId;
if (permalinkParts.groupId) return permalinkParts.groupId;
if (permalinkParts.roomIdOrAlias) return permalinkParts.roomIdOrAlias;
} catch (e) {
// no entity - not a permalink
}
return null;
}
function getPermalinkConstructor(): PermalinkConstructor { function getPermalinkConstructor(): PermalinkConstructor {
const riotPrefix = SdkConfig.get()['permalinkPrefix']; const riotPrefix = SdkConfig.get()['permalinkPrefix'];
if (riotPrefix && riotPrefix !== matrixtoBaseUrl) { if (riotPrefix && riotPrefix !== matrixtoBaseUrl) {