Fix issues with the new topic dialog (#8608)

This commit is contained in:
Šimon Brandner 2022-05-16 14:10:00 +02:00 committed by GitHub
parent e1d11db256
commit fb30b67b14
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 112 additions and 51 deletions

View file

@ -14,26 +14,31 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { useEffect, useRef } from "react";
import linkifyElement from "linkify-element";
import React, { useLayoutEffect, useRef } from "react";
import { linkifyElement } from "../../../HtmlUtils";
interface Props {
as?: string;
children: React.ReactNode;
onClick?: (ev: MouseEvent) => void;
}
export function Linkify({
as = "div",
children,
onClick,
}: Props): JSX.Element {
const ref = useRef();
useEffect(() => {
useLayoutEffect(() => {
linkifyElement(ref.current);
}, [children]);
return React.createElement(as, {
children,
ref,
onClick,
});
}

View file

@ -14,15 +14,13 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { useCallback, useContext, useEffect, useRef } from "react";
import React, { useCallback, useContext, useRef } from "react";
import { Room } from "matrix-js-sdk/src/models/room";
import classNames from "classnames";
import { EventType } from "matrix-js-sdk/src/@types/event";
import { linkifyElement } from "../../../HtmlUtils";
import { useTopic } from "../../../hooks/room/useTopic";
import useHover from "../../../hooks/useHover";
import Tooltip, { Alignment } from "./Tooltip";
import { Alignment } from "./Tooltip";
import { _t } from "../../../languageHandler";
import dis from "../../../dispatcher/dispatcher";
import { Action } from "../../../dispatcher/actions";
@ -32,6 +30,7 @@ import { useDispatcher } from "../../../hooks/useDispatcher";
import MatrixClientContext from "../../../contexts/MatrixClientContext";
import AccessibleButton from "./AccessibleButton";
import { Linkify } from "./Linkify";
import TooltipTarget from "./TooltipTarget";
interface IProps extends React.HTMLProps<HTMLDivElement> {
room?: Room;
@ -43,7 +42,6 @@ export default function RoomTopic({
}: IProps) {
const client = useContext(MatrixClientContext);
const ref = useRef<HTMLDivElement>();
const hovered = useHover(ref);
const topic = useTopic(room);
@ -57,6 +55,10 @@ export default function RoomTopic({
dis.fire(Action.ShowRoomTopic);
}, [props]);
const ignoreHover = (ev: React.MouseEvent): boolean => {
return (ev.target as HTMLElement).tagName.toUpperCase() === "A";
};
useDispatcher(dis, (payload) => {
if (payload.action === Action.ShowRoomTopic) {
const canSetTopic = room.currentState.maySendStateEvent(EventType.RoomTopic, client.getUserId());
@ -64,7 +66,16 @@ export default function RoomTopic({
const modal = Modal.createDialog(InfoDialog, {
title: room.name,
description: <div>
<Linkify as="p">{ topic }</Linkify>
<Linkify
as="p"
onClick={(ev: MouseEvent) => {
if ((ev.target as HTMLElement).tagName.toUpperCase() === "A") {
modal.close();
}
}}
>
{ topic }
</Linkify>
{ canSetTopic && <AccessibleButton
kind="primary_outline"
onClick={() => {
@ -80,10 +91,6 @@ export default function RoomTopic({
}
});
useEffect(() => {
linkifyElement(ref.current);
}, [topic]);
const className = classNames(props.className, "mx_RoomTopic");
return <div {...props}
@ -92,9 +99,10 @@ export default function RoomTopic({
dir="auto"
className={className}
>
{ topic }
{ hovered && (
<Tooltip label={_t("Click to read topic")} alignment={Alignment.Bottom} />
) }
<TooltipTarget label={_t("Click to read topic")} alignment={Alignment.Bottom} ignoreHover={ignoreHover}>
<Linkify>
{ topic }
</Linkify>
</TooltipTarget>
</div>;
}

View file

@ -14,12 +14,15 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { useState, HTMLAttributes } from 'react';
import React, { HTMLAttributes } from 'react';
import useFocus from "../../../hooks/useFocus";
import useHover from "../../../hooks/useHover";
import Tooltip, { ITooltipProps } from './Tooltip';
interface IProps extends HTMLAttributes<HTMLSpanElement>, Omit<ITooltipProps, 'visible'> {
tooltipTargetClassName?: string;
ignoreHover?: (ev: React.MouseEvent) => boolean;
}
/**
@ -36,34 +39,31 @@ const TooltipTarget: React.FC<IProps> = ({
alignment,
tooltipClassName,
maxParentWidth,
ignoreHover,
...rest
}) => {
const [isVisible, setIsVisible] = useState(false);
const show = () => setIsVisible(true);
const hide = () => setIsVisible(false);
const [isFocused, focusProps] = useFocus();
const [isHovering, hoverProps] = useHover(ignoreHover);
// No need to fill up the DOM with hidden tooltip elements. Only add the
// tooltip when we're hovering over the item (performance)
const tooltip = isVisible && <Tooltip
const tooltip = (isFocused || isHovering) && <Tooltip
id={id}
className={className}
tooltipClassName={tooltipClassName}
label={label}
alignment={alignment}
visible={isVisible}
visible={isFocused || isHovering}
maxParentWidth={maxParentWidth}
/>;
return (
<div
{...hoverProps}
{...focusProps}
tabIndex={0}
aria-describedby={id}
className={tooltipTargetClassName}
onMouseOver={show}
onMouseLeave={hide}
onFocus={show}
onBlur={hide}
{...rest}
>
{ children }