mirror of https://github.com/vector-im/riot-web
Update pill processing to handle better permalinks
parent
2cb0b4903a
commit
2824f468d9
|
@ -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 || {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in New Issue