/* Copyright 2024 New Vector Ltd. Copyright 2021 The Matrix.org Foundation C.I.C. SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ import React, { useCallback, useEffect } from "react"; import { MatrixEvent } from "matrix-js-sdk/src/matrix"; import { ButtonEvent } from "../elements/AccessibleButton"; import dis from "../../../dispatcher/dispatcher"; import { Action } from "../../../dispatcher/actions"; import { RoomPermalinkCreator } from "../../../utils/permalinks/Permalinks"; import { copyPlaintext } from "../../../utils/strings"; import { ChevronFace, ContextMenuTooltipButton, MenuProps, useContextMenu } from "../../structures/ContextMenu"; import { _t } from "../../../languageHandler"; import IconizedContextMenu, { IconizedContextMenuOption, IconizedContextMenuOptionList } from "./IconizedContextMenu"; import { WidgetLayoutStore } from "../../../stores/widgets/WidgetLayoutStore"; import { MatrixClientPeg } from "../../../MatrixClientPeg"; import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload"; export interface ThreadListContextMenuProps { mxEvent: MatrixEvent; permalinkCreator?: RoomPermalinkCreator; onMenuToggle?: (open: boolean) => void; } const contextMenuBelow = (elementRect: DOMRect): MenuProps => { // align the context menu's icons with the icon which opened the context menu const left = elementRect.left + window.scrollX + elementRect.width; const top = elementRect.bottom + window.scrollY; const chevronFace = ChevronFace.None; return { left, top, chevronFace }; }; const ThreadListContextMenu: React.FC = ({ mxEvent, permalinkCreator, onMenuToggle, ...props }) => { const [menuDisplayed, button, openMenu, closeThreadOptions] = useContextMenu(); const viewInRoom = useCallback( (evt: ButtonEvent): void => { evt.preventDefault(); evt.stopPropagation(); dis.dispatch({ action: Action.ViewRoom, event_id: mxEvent.getId(), highlighted: true, room_id: mxEvent.getRoomId(), metricsTrigger: undefined, // room doesn't change }); closeThreadOptions(); }, [mxEvent, closeThreadOptions], ); const copyLinkToThread = useCallback( async (evt: ButtonEvent | undefined): Promise => { if (permalinkCreator) { evt?.preventDefault(); evt?.stopPropagation(); const matrixToUrl = permalinkCreator.forEvent(mxEvent.getId()!); await copyPlaintext(matrixToUrl); closeThreadOptions(); } }, [mxEvent, closeThreadOptions, permalinkCreator], ); useEffect(() => { onMenuToggle?.(menuDisplayed); }, [menuDisplayed, onMenuToggle]); const room = MatrixClientPeg.safeGet().getRoom(mxEvent.getRoomId()); const isMainSplitTimelineShown = !!room && !WidgetLayoutStore.instance.hasMaximisedWidget(room); return ( {menuDisplayed && ( {isMainSplitTimelineShown && ( viewInRoom(e)} label={_t("timeline|mab|view_in_room")} iconClassName="mx_ThreadPanel_viewInRoom" /> )} {permalinkCreator && ( copyLinkToThread(e)} label={_t("timeline|mab|copy_link_thread")} iconClassName="mx_ThreadPanel_copyLinkToThread" /> )} )} ); }; export default ThreadListContextMenu;