Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit fad65f9

Browse files
authored
Add body link fallback handler for in-app navigation (#7627)
1 parent 51fd4d8 commit fad65f9

File tree

4 files changed

+36
-11
lines changed

4 files changed

+36
-11
lines changed

src/HtmlUtils.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,9 @@ const transformTags: IExtendedSanitizeOptions["transformTags"] = { // custom to
176176
attribs.target = '_blank'; // by default
177177

178178
const transformed = tryTransformPermalinkToLocalHref(attribs.href); // only used to check if it is a link that can be handled locally
179-
if (transformed !== attribs.href || // it could be converted so handle locally symbols e.g. @user:server.tdl, matrix: and matrix.to
180-
attribs.href.match(ELEMENT_URL_PATTERN) // for https:vector|riot...
179+
if (
180+
transformed !== attribs.href || // it could be converted so handle locally symbols e.g. @user:server.tdl, matrix: and matrix.to
181+
attribs.href.match(ELEMENT_URL_PATTERN) // for https links to Element domains
181182
) {
182183
delete attribs.target;
183184
}

src/components/views/messages/TextualBody.tsx

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
import React, { createRef, SyntheticEvent } from 'react';
17+
import React, { createRef, SyntheticEvent, MouseEvent } from 'react';
1818
import ReactDOM from 'react-dom';
1919
import highlight from 'highlight.js';
2020
import { MsgType } from "matrix-js-sdk/src/@types/event";
@@ -31,7 +31,7 @@ import SettingsStore from "../../../settings/SettingsStore";
3131
import ReplyChain from "../elements/ReplyChain";
3232
import { pillifyLinks, unmountPills } from '../../../utils/pillify';
3333
import { IntegrationManagers } from "../../../integrations/IntegrationManagers";
34-
import { isPermalinkHost } from "../../../utils/permalinks/Permalinks";
34+
import { isPermalinkHost, tryTransformPermalinkToLocalHref } from "../../../utils/permalinks/Permalinks";
3535
import { copyPlaintext } from "../../../utils/strings";
3636
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
3737
import { replaceableComponent } from "../../../utils/replaceableComponent";
@@ -47,6 +47,7 @@ import LinkPreviewGroup from '../rooms/LinkPreviewGroup';
4747
import { IBodyProps } from "./IBodyProps";
4848
import RoomContext from "../../../contexts/RoomContext";
4949
import AccessibleButton from '../elements/AccessibleButton';
50+
import { options as linkifyOpts } from "../../../linkify-matrix";
5051

5152
const MAX_HIGHLIGHT_LENGTH = 4096;
5253

@@ -418,6 +419,23 @@ export default class TextualBody extends React.Component<IBodyProps, IState> {
418419
});
419420
};
420421

422+
/**
423+
* This acts as a fallback in-app navigation handler for any body links that
424+
* were ignored as part of linkification because they were already links
425+
* to start with (e.g. pills, links in the content).
426+
*/
427+
private onBodyLinkClick = (e: MouseEvent): void => {
428+
const target = e.target as Element;
429+
if (target.nodeName !== "A" || target.classList.contains(linkifyOpts.className)) return;
430+
const { href } = target as HTMLLinkElement;
431+
const localHref = tryTransformPermalinkToLocalHref(href);
432+
if (localHref !== href) {
433+
// it could be converted to a localHref -> therefore handle locally
434+
e.preventDefault();
435+
window.location.hash = localHref;
436+
}
437+
};
438+
421439
public getEventTileOps = () => ({
422440
isWidgetHidden: () => {
423441
return this.state.widgetHidden;
@@ -606,7 +624,9 @@ export default class TextualBody extends React.Component<IBodyProps, IState> {
606624

607625
if (isEmote) {
608626
return (
609-
<div className="mx_MEmoteBody mx_EventTile_content">
627+
<div className="mx_MEmoteBody mx_EventTile_content"
628+
onClick={this.onBodyLinkClick}
629+
>
610630
*&nbsp;
611631
<span
612632
className="mx_MEmoteBody_sender"
@@ -622,14 +642,18 @@ export default class TextualBody extends React.Component<IBodyProps, IState> {
622642
}
623643
if (isNotice) {
624644
return (
625-
<div className="mx_MNoticeBody mx_EventTile_content">
645+
<div className="mx_MNoticeBody mx_EventTile_content"
646+
onClick={this.onBodyLinkClick}
647+
>
626648
{ body }
627649
{ widgets }
628650
</div>
629651
);
630652
}
631653
return (
632-
<div className="mx_MTextBody mx_EventTile_content">
654+
<div className="mx_MTextBody mx_EventTile_content"
655+
onClick={this.onBodyLinkClick}
656+
>
633657
{ body }
634658
{ widgets }
635659
</div>

src/linkify-matrix.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import linkifyString from '@matrix-org/linkify-string';
2121
import { RoomMember } from 'matrix-js-sdk/src/models/room-member';
2222
import { registerCustomProtocol, registerPlugin } from '@matrix-org/linkifyjs';
2323

24-
//linkifyjs/src/core/fsm
2524
import { baseUrl } from "./utils/permalinks/MatrixToPermalinkConstructor";
2625
import {
2726
parsePermalink,
@@ -227,8 +226,9 @@ export const options = {
227226
if (type === Type.URL) {
228227
try {
229228
const transformed = tryTransformPermalinkToLocalHref(href);
230-
if (transformed !== href || // if it could be converted to handle locally for matrix symbols e.g. @user:server.tdl and matrix.to
231-
decodeURIComponent(href).match(ELEMENT_URL_PATTERN) // for https:vector|riot...
229+
if (
230+
transformed !== href || // if it could be converted to handle locally for matrix symbols e.g. @user:server.tdl and matrix.to
231+
decodeURIComponent(href).match(ELEMENT_URL_PATTERN) // for https links to Element domains
232232
) {
233233
return null;
234234
} else {

src/utils/permalinks/Permalinks.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ export function tryTransformEntityToPermalink(entity: string): string {
328328
if (!entity) return null;
329329

330330
// Check to see if it is a bare entity for starters
331-
{if (entity[0] === '#' || entity[0] === '!') return makeRoomPermalink(entity);}
331+
if (entity[0] === '#' || entity[0] === '!') return makeRoomPermalink(entity);
332332
if (entity[0] === '@') return makeUserPermalink(entity);
333333
if (entity[0] === '+') return makeGroupPermalink(entity);
334334

0 commit comments

Comments
 (0)