Add option to display tooltip on link hover (#8394)

* Add option to display tooltip on link hover

This makes it possible for platforms like Electron apps, which lack
a built-in URL preview in the status bar, to enable tooltip previews
of links.

Relates to: vector-im/element-web#6532
Signed-off-by: Johannes Marbach <johannesm@element.io>

* Gracefully handle missing platform

* Use public access modifier

Co-authored-by: Travis Ralston <travpc@gmail.com>

* Use exact inequality

Co-authored-by: Travis Ralston <travpc@gmail.com>

* Document getAbsoluteUrl

* Appease the linter

* Clarify performance impact in comment

Co-authored-by: Travis Ralston <travpc@gmail.com>

* Use URL instead of anchor element hack

* Wrap anchor in tooltip target and only allow focus on anchor

* Use optional chaining

Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>

* Use double quotes for consistency

* Accumulate and unmount tooltips and extract tooltipify.tsx

* Fix indentation

* Blur tooltip target on click

* Remove space

* Mention platform flag in comment

* Add (simplistic) tests

* Fix lint errors

* Fix lint errors ... for real

* Replace snapshot tests with structural assertions

* Add missing semicolon

* Add tooltips in link previews

* Fix copyright

Co-authored-by: Travis Ralston <travpc@gmail.com>
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
Johannes Marbach 2022-07-06 11:43:30 +02:00 committed by GitHub
parent 530b51a5ac
commit 6f21a155a4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 223 additions and 3 deletions

View file

@ -22,6 +22,7 @@ import * as HtmlUtils from '../../../HtmlUtils';
import { editBodyDiffToHtml } from '../../../utils/MessageDiffUtils';
import { formatTime } from '../../../DateUtils';
import { pillifyLinks, unmountPills } from '../../../utils/pillify';
import { tooltipifyLinks, unmountTooltips } from '../../../utils/tooltipify';
import { _t } from '../../../languageHandler';
import { MatrixClientPeg } from '../../../MatrixClientPeg';
import Modal from '../../../Modal';
@ -52,6 +53,7 @@ interface IState {
export default class EditHistoryMessage extends React.PureComponent<IProps, IState> {
private content = createRef<HTMLDivElement>();
private pills: Element[] = [];
private tooltips: Element[] = [];
constructor(props: IProps) {
super(props);
@ -93,12 +95,21 @@ export default class EditHistoryMessage extends React.PureComponent<IProps, ISta
}
}
private tooltipifyLinks(): void {
// not present for redacted events
if (this.content.current) {
tooltipifyLinks(this.content.current.children, this.pills, this.tooltips);
}
}
public componentDidMount(): void {
this.pillifyLinks();
this.tooltipifyLinks();
}
public componentWillUnmount(): void {
unmountPills(this.pills);
unmountTooltips(this.tooltips);
const event = this.props.mxEvent;
if (event.localRedactionEvent()) {
event.localRedactionEvent().off(MatrixEventEvent.Status, this.onAssociatedStatusChanged);
@ -107,6 +118,7 @@ export default class EditHistoryMessage extends React.PureComponent<IProps, ISta
public componentDidUpdate(): void {
this.pillifyLinks();
this.tooltipifyLinks();
}
private renderActionBar(): JSX.Element {

View file

@ -29,6 +29,7 @@ import * as ContextMenu from '../../structures/ContextMenu';
import { ChevronFace, toRightOf } from '../../structures/ContextMenu';
import SettingsStore from "../../../settings/SettingsStore";
import { pillifyLinks, unmountPills } from '../../../utils/pillify';
import { tooltipifyLinks, unmountTooltips } from '../../../utils/tooltipify';
import { IntegrationManagers } from "../../../integrations/IntegrationManagers";
import { isPermalinkHost, tryTransformPermalinkToLocalHref } from "../../../utils/permalinks/Permalinks";
import { copyPlaintext } from "../../../utils/strings";
@ -63,6 +64,7 @@ export default class TextualBody extends React.Component<IBodyProps, IState> {
private unmounted = false;
private pills: Element[] = [];
private tooltips: Element[] = [];
static contextType = RoomContext;
public context!: React.ContextType<typeof RoomContext>;
@ -91,6 +93,7 @@ export default class TextualBody extends React.Component<IBodyProps, IState> {
// we should be pillify them here by doing the linkifying BEFORE the pillifying.
pillifyLinks([this.contentRef.current], this.props.mxEvent, this.pills);
HtmlUtils.linkifyElement(this.contentRef.current);
tooltipifyLinks([this.contentRef.current], this.pills, this.tooltips);
this.calculateUrlPreview();
if (this.props.mxEvent.getContent().format === "org.matrix.custom.html") {
@ -283,6 +286,7 @@ export default class TextualBody extends React.Component<IBodyProps, IState> {
componentWillUnmount() {
this.unmounted = true;
unmountPills(this.pills);
unmountTooltips(this.tooltips);
}
shouldComponentUpdate(nextProps, nextState) {