Cleanup `MessageContextMenu` code (#8351)

t3chguy/dedup-icons-17oct
Šimon Brandner 2022-04-19 09:59:23 +02:00 committed by GitHub
parent 2f3249793f
commit 511965b840
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 52 additions and 52 deletions

View File

@ -21,7 +21,6 @@ import { EventStatus, MatrixEvent } from 'matrix-js-sdk/src/models/event';
import { EventType, RelationType } from "matrix-js-sdk/src/@types/event"; import { EventType, RelationType } from "matrix-js-sdk/src/@types/event";
import { Relations } from 'matrix-js-sdk/src/models/relations'; import { Relations } from 'matrix-js-sdk/src/models/relations';
import { RoomMemberEvent } from "matrix-js-sdk/src/models/room-member"; import { RoomMemberEvent } from "matrix-js-sdk/src/models/room-member";
import { M_LOCATION } from 'matrix-js-sdk/src/@types/location';
import { M_POLL_START } from "matrix-events-sdk"; import { M_POLL_START } from "matrix-events-sdk";
import { MatrixClientPeg } from '../../../MatrixClientPeg'; import { MatrixClientPeg } from '../../../MatrixClientPeg';
@ -31,7 +30,7 @@ import Modal from '../../../Modal';
import Resend from '../../../Resend'; import Resend from '../../../Resend';
import SettingsStore from '../../../settings/SettingsStore'; import SettingsStore from '../../../settings/SettingsStore';
import { isUrlPermitted } from '../../../HtmlUtils'; import { isUrlPermitted } from '../../../HtmlUtils';
import { canEditContent, editEvent, isContentActionable } from '../../../utils/EventUtils'; import { canEditContent, canForward, editEvent, isContentActionable, isLocationEvent } from '../../../utils/EventUtils';
import IconizedContextMenu, { IconizedContextMenuOption, IconizedContextMenuOptionList } from './IconizedContextMenu'; import IconizedContextMenu, { IconizedContextMenuOption, IconizedContextMenuOptionList } from './IconizedContextMenu';
import { ReadPinsEventId } from "../right_panel/types"; import { ReadPinsEventId } from "../right_panel/types";
import { Action } from "../../../dispatcher/actions"; import { Action } from "../../../dispatcher/actions";
@ -49,20 +48,11 @@ import { ComposerInsertPayload } from "../../../dispatcher/payloads/ComposerInse
import EndPollDialog from '../dialogs/EndPollDialog'; import EndPollDialog from '../dialogs/EndPollDialog';
import { isPollEnded } from '../messages/MPollBody'; import { isPollEnded } from '../messages/MPollBody';
import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload"; import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
import { GetRelationsForEvent } from "../rooms/EventTile"; import { GetRelationsForEvent, IEventTileOps } from "../rooms/EventTile";
import { OpenForwardDialogPayload } from "../../../dispatcher/payloads/OpenForwardDialogPayload"; import { OpenForwardDialogPayload } from "../../../dispatcher/payloads/OpenForwardDialogPayload";
import { OpenReportEventDialogPayload } from "../../../dispatcher/payloads/OpenReportEventDialogPayload"; import { OpenReportEventDialogPayload } from "../../../dispatcher/payloads/OpenReportEventDialogPayload";
import { createMapSiteLink } from '../../../utils/location'; import { createMapSiteLink } from '../../../utils/location';
export interface IEventTileOps {
isWidgetHidden(): boolean;
unhideWidget(): void;
}
export interface IOperableEventTile {
getEventTileOps(): IEventTileOps;
}
interface IProps extends IPosition { interface IProps extends IPosition {
chevronFace: ChevronFace; chevronFace: ChevronFace;
/* the MatrixEvent associated with the context menu */ /* the MatrixEvent associated with the context menu */
@ -343,28 +333,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
); );
const isThreadRootEvent = isThread && mxEvent?.getThread()?.rootEvent === mxEvent; const isThreadRootEvent = isThread && mxEvent?.getThread()?.rootEvent === mxEvent;
let openInMapSiteButton: JSX.Element;
let endPollButton: JSX.Element;
let resendReactionsButton: JSX.Element; let resendReactionsButton: JSX.Element;
let redactButton: JSX.Element;
let forwardButton: JSX.Element;
let pinButton: JSX.Element;
let unhidePreviewButton: JSX.Element;
let externalURLButton: JSX.Element;
let quoteButton: JSX.Element;
let redactItemList: JSX.Element;
let reportEventButton: JSX.Element;
let copyButton: JSX.Element;
let editButton: JSX.Element;
let replyButton: JSX.Element;
let reactButton: JSX.Element;
let reactionPicker: JSX.Element;
let quickItemsList: JSX.Element;
let nativeItemsList: JSX.Element;
let permalinkButton: JSX.Element;
let collapseReplyChainButton: JSX.Element;
let viewInRoomButton: JSX.Element;
if (!mxEvent.isRedacted() && unsentReactionsCount !== 0) { if (!mxEvent.isRedacted() && unsentReactionsCount !== 0) {
resendReactionsButton = ( resendReactionsButton = (
<IconizedContextMenuOption <IconizedContextMenuOption
@ -375,6 +344,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
); );
} }
let redactButton: JSX.Element;
if (isSent && this.state.canRedact) { if (isSent && this.state.canRedact) {
redactButton = ( redactButton = (
<IconizedContextMenuOption <IconizedContextMenuOption
@ -385,6 +355,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
); );
} }
let openInMapSiteButton: JSX.Element;
if (this.canOpenInMapSite(mxEvent)) { if (this.canOpenInMapSite(mxEvent)) {
const mapSiteLink = createMapSiteLink(mxEvent); const mapSiteLink = createMapSiteLink(mxEvent);
openInMapSiteButton = ( openInMapSiteButton = (
@ -404,6 +375,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
); );
} }
let forwardButton: JSX.Element;
if (contentActionable && canForward(mxEvent)) { if (contentActionable && canForward(mxEvent)) {
forwardButton = ( forwardButton = (
<IconizedContextMenuOption <IconizedContextMenuOption
@ -414,6 +386,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
); );
} }
let pinButton: JSX.Element;
if (contentActionable && this.state.canPin) { if (contentActionable && this.state.canPin) {
pinButton = ( pinButton = (
<IconizedContextMenuOption <IconizedContextMenuOption
@ -435,6 +408,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
); );
} }
let unhidePreviewButton: JSX.Element;
if (eventTileOps?.isWidgetHidden()) { if (eventTileOps?.isWidgetHidden()) {
unhidePreviewButton = ( unhidePreviewButton = (
<IconizedContextMenuOption <IconizedContextMenuOption
@ -445,6 +419,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
); );
} }
let permalinkButton: JSX.Element;
if (permalink) { if (permalink) {
permalinkButton = ( permalinkButton = (
<IconizedContextMenuOption <IconizedContextMenuOption
@ -468,6 +443,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
); );
} }
let endPollButton: JSX.Element;
if (this.canEndPoll(mxEvent)) { if (this.canEndPoll(mxEvent)) {
endPollButton = ( endPollButton = (
<IconizedContextMenuOption <IconizedContextMenuOption
@ -478,6 +454,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
); );
} }
let quoteButton: JSX.Element;
if (eventTileOps) { // this event is rendered using TextualBody if (eventTileOps) { // this event is rendered using TextualBody
quoteButton = ( quoteButton = (
<IconizedContextMenuOption <IconizedContextMenuOption
@ -489,6 +466,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
} }
// Bridges can provide a 'external_url' to link back to the source. // Bridges can provide a 'external_url' to link back to the source.
let externalURLButton: JSX.Element;
if ( if (
typeof (mxEvent.getContent().external_url) === "string" && typeof (mxEvent.getContent().external_url) === "string" &&
isUrlPermitted(mxEvent.getContent().external_url) isUrlPermitted(mxEvent.getContent().external_url)
@ -511,6 +489,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
); );
} }
let collapseReplyChainButton: JSX.Element;
if (collapseReplyChain) { if (collapseReplyChain) {
collapseReplyChainButton = ( collapseReplyChainButton = (
<IconizedContextMenuOption <IconizedContextMenuOption
@ -521,6 +500,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
); );
} }
let reportEventButton: JSX.Element;
if (mxEvent.getSender() !== me) { if (mxEvent.getSender() !== me) {
reportEventButton = ( reportEventButton = (
<IconizedContextMenuOption <IconizedContextMenuOption
@ -531,6 +511,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
); );
} }
let copyButton: JSX.Element;
if (rightClick && getSelectedText()) { if (rightClick && getSelectedText()) {
copyButton = ( copyButton = (
<IconizedContextMenuOption <IconizedContextMenuOption
@ -542,6 +523,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
); );
} }
let editButton: JSX.Element;
if (rightClick && canEditContent(mxEvent)) { if (rightClick && canEditContent(mxEvent)) {
editButton = ( editButton = (
<IconizedContextMenuOption <IconizedContextMenuOption
@ -552,6 +534,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
); );
} }
let replyButton: JSX.Element;
if (rightClick && contentActionable && canSendMessages) { if (rightClick && contentActionable && canSendMessages) {
replyButton = ( replyButton = (
<IconizedContextMenuOption <IconizedContextMenuOption
@ -562,6 +545,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
); );
} }
let reactButton;
if (rightClick && contentActionable && canReact) { if (rightClick && contentActionable && canReact) {
reactButton = ( reactButton = (
<IconizedContextMenuOption <IconizedContextMenuOption
@ -573,6 +557,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
); );
} }
let viewInRoomButton: JSX.Element;
if (isThreadRootEvent) { if (isThreadRootEvent) {
viewInRoomButton = ( viewInRoomButton = (
<IconizedContextMenuOption <IconizedContextMenuOption
@ -583,6 +568,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
); );
} }
let nativeItemsList: JSX.Element;
if (copyButton) { if (copyButton) {
nativeItemsList = ( nativeItemsList = (
<IconizedContextMenuOptionList> <IconizedContextMenuOptionList>
@ -591,6 +577,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
); );
} }
let quickItemsList: JSX.Element;
if (editButton || replyButton || reactButton) { if (editButton || replyButton || reactButton) {
quickItemsList = ( quickItemsList = (
<IconizedContextMenuOptionList> <IconizedContextMenuOptionList>
@ -619,6 +606,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
</IconizedContextMenuOptionList> </IconizedContextMenuOptionList>
); );
let redactItemList: JSX.Element;
if (redactButton) { if (redactButton) {
redactItemList = ( redactItemList = (
<IconizedContextMenuOptionList red> <IconizedContextMenuOptionList red>
@ -627,6 +615,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
); );
} }
let reactionPicker: JSX.Element;
if (this.state.reactionPickerDisplayed) { if (this.state.reactionPickerDisplayed) {
const buttonRect = (this.reactButtonRef.current as HTMLElement)?.getBoundingClientRect(); const buttonRect = (this.reactButtonRef.current as HTMLElement)?.getBoundingClientRect();
reactionPicker = ( reactionPicker = (
@ -662,20 +651,3 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
} }
} }
function canForward(event: MatrixEvent): boolean {
return !(
isLocationEvent(event) ||
M_POLL_START.matches(event.getType())
);
}
function isLocationEvent(event: MatrixEvent): boolean {
const eventType = event.getType();
return (
M_LOCATION.matches(eventType) ||
(
eventType === EventType.RoomMessage &&
M_LOCATION.matches(event.getContent().msgtype)
)
);
}

View File

@ -26,7 +26,6 @@ import { Mjolnir } from "../../../mjolnir/Mjolnir";
import RedactedBody from "./RedactedBody"; import RedactedBody from "./RedactedBody";
import UnknownBody from "./UnknownBody"; import UnknownBody from "./UnknownBody";
import { IMediaBody } from "./IMediaBody"; import { IMediaBody } from "./IMediaBody";
import { IOperableEventTile } from "../context_menus/MessageContextMenu";
import { MediaEventHelper } from "../../../utils/MediaEventHelper"; import { MediaEventHelper } from "../../../utils/MediaEventHelper";
import { ReactAnyComponent } from "../../../@types/common"; import { ReactAnyComponent } from "../../../@types/common";
import { IBodyProps } from "./IBodyProps"; import { IBodyProps } from "./IBodyProps";
@ -41,6 +40,7 @@ import MPollBody from "./MPollBody";
import MLocationBody from "./MLocationBody"; import MLocationBody from "./MLocationBody";
import MjolnirBody from "./MjolnirBody"; import MjolnirBody from "./MjolnirBody";
import MBeaconBody from "./MBeaconBody"; import MBeaconBody from "./MBeaconBody";
import { IEventTileOps } from "../rooms/EventTile";
// onMessageAllowed is handled internally // onMessageAllowed is handled internally
interface IProps extends Omit<IBodyProps, "onMessageAllowed" | "mediaEventHelper"> { interface IProps extends Omit<IBodyProps, "onMessageAllowed" | "mediaEventHelper"> {
@ -54,6 +54,10 @@ interface IProps extends Omit<IBodyProps, "onMessageAllowed" | "mediaEventHelper
isSeeingThroughMessageHiddenForModeration?: boolean; isSeeingThroughMessageHiddenForModeration?: boolean;
} }
export interface IOperableEventTile {
getEventTileOps(): IEventTileOps;
}
export default class MessageEvent extends React.Component<IProps> implements IMediaBody, IOperableEventTile { export default class MessageEvent extends React.Component<IProps> implements IMediaBody, IOperableEventTile {
private body: React.RefObject<React.Component | IOperableEventTile> = createRef(); private body: React.RefObject<React.Component | IOperableEventTile> = createRef();
private mediaHelper: MediaEventHelper; private mediaHelper: MediaEventHelper;

View File

@ -38,7 +38,7 @@ import MatrixClientContext from "../../../contexts/MatrixClientContext";
import { E2EState } from "./E2EIcon"; import { E2EState } from "./E2EIcon";
import { toRem } from "../../../utils/units"; import { toRem } from "../../../utils/units";
import RoomAvatar from "../avatars/RoomAvatar"; import RoomAvatar from "../avatars/RoomAvatar";
import MessageContextMenu, { IEventTileOps } from "../context_menus/MessageContextMenu"; import MessageContextMenu from "../context_menus/MessageContextMenu";
import { aboveRightOf } from '../../structures/ContextMenu'; import { aboveRightOf } from '../../structures/ContextMenu';
import { objectHasDiff } from "../../../utils/objects"; import { objectHasDiff } from "../../../utils/objects";
import Tooltip from "../elements/Tooltip"; import Tooltip from "../elements/Tooltip";
@ -99,6 +99,11 @@ export interface IReadReceiptProps {
ts: number; ts: number;
} }
export interface IEventTileOps {
isWidgetHidden(): boolean;
unhideWidget(): void;
}
export interface IEventTileType extends React.Component { export interface IEventTileType extends React.Component {
getEventTileOps?(): IEventTileOps; getEventTileOps?(): IEventTileOps;
} }

View File

@ -19,6 +19,7 @@ import { EventType, EVENT_VISIBILITY_CHANGE_TYPE, MsgType, RelationType } from "
import { MatrixClient } from 'matrix-js-sdk/src/client'; import { MatrixClient } from 'matrix-js-sdk/src/client';
import { logger } from 'matrix-js-sdk/src/logger'; import { logger } from 'matrix-js-sdk/src/logger';
import { M_POLL_START } from "matrix-events-sdk"; import { M_POLL_START } from "matrix-events-sdk";
import { M_LOCATION } from "matrix-js-sdk/src/@types/location";
import { MatrixClientPeg } from '../MatrixClientPeg'; import { MatrixClientPeg } from '../MatrixClientPeg';
import shouldHideEvent from "../shouldHideEvent"; import shouldHideEvent from "../shouldHideEvent";
@ -262,3 +263,21 @@ export function editEvent(
export function canCancel(status: EventStatus): boolean { export function canCancel(status: EventStatus): boolean {
return status === EventStatus.QUEUED || status === EventStatus.NOT_SENT || status === EventStatus.ENCRYPTING; return status === EventStatus.QUEUED || status === EventStatus.NOT_SENT || status === EventStatus.ENCRYPTING;
} }
export const isLocationEvent = (event: MatrixEvent): boolean => {
const eventType = event.getType();
return (
M_LOCATION.matches(eventType) ||
(
eventType === EventType.RoomMessage &&
M_LOCATION.matches(event.getContent().msgtype)
)
);
};
export function canForward(event: MatrixEvent): boolean {
return !(
isLocationEvent(event) ||
M_POLL_START.matches(event.getType())
);
}