Add body link fallback handler for in-app navigation (#7627)
This commit is contained in:
parent
51fd4d82fd
commit
fad65f9582
4 changed files with 36 additions and 11 deletions
|
@ -176,8 +176,9 @@ const transformTags: IExtendedSanitizeOptions["transformTags"] = { // custom to
|
||||||
attribs.target = '_blank'; // by default
|
attribs.target = '_blank'; // by default
|
||||||
|
|
||||||
const transformed = tryTransformPermalinkToLocalHref(attribs.href); // only used to check if it is a link that can be handled locally
|
const transformed = tryTransformPermalinkToLocalHref(attribs.href); // only used to check if it is a link that can be handled locally
|
||||||
if (transformed !== attribs.href || // it could be converted so handle locally symbols e.g. @user:server.tdl, matrix: and matrix.to
|
if (
|
||||||
attribs.href.match(ELEMENT_URL_PATTERN) // for https:vector|riot...
|
transformed !== attribs.href || // it could be converted so handle locally symbols e.g. @user:server.tdl, matrix: and matrix.to
|
||||||
|
attribs.href.match(ELEMENT_URL_PATTERN) // for https links to Element domains
|
||||||
) {
|
) {
|
||||||
delete attribs.target;
|
delete attribs.target;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { createRef, SyntheticEvent } from 'react';
|
import React, { createRef, SyntheticEvent, MouseEvent } from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import highlight from 'highlight.js';
|
import highlight from 'highlight.js';
|
||||||
import { MsgType } from "matrix-js-sdk/src/@types/event";
|
import { MsgType } from "matrix-js-sdk/src/@types/event";
|
||||||
|
@ -31,7 +31,7 @@ import SettingsStore from "../../../settings/SettingsStore";
|
||||||
import ReplyChain from "../elements/ReplyChain";
|
import ReplyChain from "../elements/ReplyChain";
|
||||||
import { pillifyLinks, unmountPills } from '../../../utils/pillify';
|
import { pillifyLinks, unmountPills } from '../../../utils/pillify';
|
||||||
import { IntegrationManagers } from "../../../integrations/IntegrationManagers";
|
import { IntegrationManagers } from "../../../integrations/IntegrationManagers";
|
||||||
import { isPermalinkHost } from "../../../utils/permalinks/Permalinks";
|
import { isPermalinkHost, tryTransformPermalinkToLocalHref } from "../../../utils/permalinks/Permalinks";
|
||||||
import { copyPlaintext } from "../../../utils/strings";
|
import { copyPlaintext } from "../../../utils/strings";
|
||||||
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
|
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
|
||||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||||
|
@ -47,6 +47,7 @@ import LinkPreviewGroup from '../rooms/LinkPreviewGroup';
|
||||||
import { IBodyProps } from "./IBodyProps";
|
import { IBodyProps } from "./IBodyProps";
|
||||||
import RoomContext from "../../../contexts/RoomContext";
|
import RoomContext from "../../../contexts/RoomContext";
|
||||||
import AccessibleButton from '../elements/AccessibleButton';
|
import AccessibleButton from '../elements/AccessibleButton';
|
||||||
|
import { options as linkifyOpts } from "../../../linkify-matrix";
|
||||||
|
|
||||||
const MAX_HIGHLIGHT_LENGTH = 4096;
|
const MAX_HIGHLIGHT_LENGTH = 4096;
|
||||||
|
|
||||||
|
@ -418,6 +419,23 @@ export default class TextualBody extends React.Component<IBodyProps, IState> {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This acts as a fallback in-app navigation handler for any body links that
|
||||||
|
* were ignored as part of linkification because they were already links
|
||||||
|
* to start with (e.g. pills, links in the content).
|
||||||
|
*/
|
||||||
|
private onBodyLinkClick = (e: MouseEvent): void => {
|
||||||
|
const target = e.target as Element;
|
||||||
|
if (target.nodeName !== "A" || target.classList.contains(linkifyOpts.className)) return;
|
||||||
|
const { href } = target as HTMLLinkElement;
|
||||||
|
const localHref = tryTransformPermalinkToLocalHref(href);
|
||||||
|
if (localHref !== href) {
|
||||||
|
// it could be converted to a localHref -> therefore handle locally
|
||||||
|
e.preventDefault();
|
||||||
|
window.location.hash = localHref;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
public getEventTileOps = () => ({
|
public getEventTileOps = () => ({
|
||||||
isWidgetHidden: () => {
|
isWidgetHidden: () => {
|
||||||
return this.state.widgetHidden;
|
return this.state.widgetHidden;
|
||||||
|
@ -606,7 +624,9 @@ export default class TextualBody extends React.Component<IBodyProps, IState> {
|
||||||
|
|
||||||
if (isEmote) {
|
if (isEmote) {
|
||||||
return (
|
return (
|
||||||
<div className="mx_MEmoteBody mx_EventTile_content">
|
<div className="mx_MEmoteBody mx_EventTile_content"
|
||||||
|
onClick={this.onBodyLinkClick}
|
||||||
|
>
|
||||||
*
|
*
|
||||||
<span
|
<span
|
||||||
className="mx_MEmoteBody_sender"
|
className="mx_MEmoteBody_sender"
|
||||||
|
@ -622,14 +642,18 @@ export default class TextualBody extends React.Component<IBodyProps, IState> {
|
||||||
}
|
}
|
||||||
if (isNotice) {
|
if (isNotice) {
|
||||||
return (
|
return (
|
||||||
<div className="mx_MNoticeBody mx_EventTile_content">
|
<div className="mx_MNoticeBody mx_EventTile_content"
|
||||||
|
onClick={this.onBodyLinkClick}
|
||||||
|
>
|
||||||
{ body }
|
{ body }
|
||||||
{ widgets }
|
{ widgets }
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div className="mx_MTextBody mx_EventTile_content">
|
<div className="mx_MTextBody mx_EventTile_content"
|
||||||
|
onClick={this.onBodyLinkClick}
|
||||||
|
>
|
||||||
{ body }
|
{ body }
|
||||||
{ widgets }
|
{ widgets }
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -21,7 +21,6 @@ import linkifyString from '@matrix-org/linkify-string';
|
||||||
import { RoomMember } from 'matrix-js-sdk/src/models/room-member';
|
import { RoomMember } from 'matrix-js-sdk/src/models/room-member';
|
||||||
import { registerCustomProtocol, registerPlugin } from '@matrix-org/linkifyjs';
|
import { registerCustomProtocol, registerPlugin } from '@matrix-org/linkifyjs';
|
||||||
|
|
||||||
//linkifyjs/src/core/fsm
|
|
||||||
import { baseUrl } from "./utils/permalinks/MatrixToPermalinkConstructor";
|
import { baseUrl } from "./utils/permalinks/MatrixToPermalinkConstructor";
|
||||||
import {
|
import {
|
||||||
parsePermalink,
|
parsePermalink,
|
||||||
|
@ -227,8 +226,9 @@ export const options = {
|
||||||
if (type === Type.URL) {
|
if (type === Type.URL) {
|
||||||
try {
|
try {
|
||||||
const transformed = tryTransformPermalinkToLocalHref(href);
|
const transformed = tryTransformPermalinkToLocalHref(href);
|
||||||
if (transformed !== href || // if it could be converted to handle locally for matrix symbols e.g. @user:server.tdl and matrix.to
|
if (
|
||||||
decodeURIComponent(href).match(ELEMENT_URL_PATTERN) // for https:vector|riot...
|
transformed !== href || // if it could be converted to handle locally for matrix symbols e.g. @user:server.tdl and matrix.to
|
||||||
|
decodeURIComponent(href).match(ELEMENT_URL_PATTERN) // for https links to Element domains
|
||||||
) {
|
) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -328,7 +328,7 @@ export function tryTransformEntityToPermalink(entity: string): string {
|
||||||
if (!entity) return null;
|
if (!entity) return null;
|
||||||
|
|
||||||
// Check to see if it is a bare entity for starters
|
// Check to see if it is a bare entity for starters
|
||||||
{if (entity[0] === '#' || entity[0] === '!') return makeRoomPermalink(entity);}
|
if (entity[0] === '#' || entity[0] === '!') return makeRoomPermalink(entity);
|
||||||
if (entity[0] === '@') return makeUserPermalink(entity);
|
if (entity[0] === '@') return makeUserPermalink(entity);
|
||||||
if (entity[0] === '+') return makeGroupPermalink(entity);
|
if (entity[0] === '+') return makeGroupPermalink(entity);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue