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

Commit 11e0a3a

Browse files
Enable the message right-click context menu in the browser (#8336)
* Enable the message right-click context menu in the browser Signed-off-by: Šimon Brandner <[email protected]> * Move `getSelectedText()` to `strings.ts` Signed-off-by: Šimon Brandner <[email protected]> * Move `canCancel()` to `EventUtils.ts` Signed-off-by: Šimon Brandner <[email protected]>
1 parent 1afecc4 commit 11e0a3a

File tree

5 files changed

+32
-15
lines changed

5 files changed

+32
-15
lines changed

src/components/views/context_menus/MessageContextMenu.tsx

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ import { ReadPinsEventId } from "../right_panel/types";
3737
import { Action } from "../../../dispatcher/actions";
3838
import { RoomPermalinkCreator } from '../../../utils/permalinks/Permalinks';
3939
import { ButtonEvent } from '../elements/AccessibleButton';
40-
import { copyPlaintext } from '../../../utils/strings';
40+
import { copyPlaintext, getSelectedText } from '../../../utils/strings';
4141
import ContextMenu, { toRightOf } from '../../structures/ContextMenu';
4242
import ReactionPicker from '../emojipicker/ReactionPicker';
4343
import ViewSource from '../../structures/ViewSource';
@@ -54,10 +54,6 @@ import { OpenForwardDialogPayload } from "../../../dispatcher/payloads/OpenForwa
5454
import { OpenReportEventDialogPayload } from "../../../dispatcher/payloads/OpenReportEventDialogPayload";
5555
import { createMapSiteLink } from '../../../utils/location';
5656

57-
export function canCancel(status: EventStatus): boolean {
58-
return status === EventStatus.QUEUED || status === EventStatus.NOT_SENT || status === EventStatus.ENCRYPTING;
59-
}
60-
6157
export interface IEventTileOps {
6258
isWidgetHidden(): boolean;
6359
unhideWidget(): void;
@@ -263,7 +259,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
263259
};
264260

265261
private onCopyClick = (): void => {
266-
copyPlaintext(this.getSelectedText());
262+
copyPlaintext(getSelectedText());
267263
this.closeMenu();
268264
};
269265

@@ -310,10 +306,6 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
310306
});
311307
}
312308

313-
private getSelectedText(): string {
314-
return window.getSelection().toString();
315-
}
316-
317309
private getPermalink(): string {
318310
if (!this.props.permalinkCreator) return;
319311
return this.props.permalinkCreator.forEvent(this.props.mxEvent.getId());
@@ -539,7 +531,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
539531
);
540532
}
541533

542-
if (rightClick && this.getSelectedText()) {
534+
if (rightClick && getSelectedText()) {
543535
copyButton = (
544536
<IconizedContextMenuOption
545537
iconClassName="mx_MessageContextMenu_iconCopy"

src/components/views/messages/MessageActionBar.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@ import type { Relations } from 'matrix-js-sdk/src/models/relations';
2626
import { _t } from '../../../languageHandler';
2727
import dis from '../../../dispatcher/dispatcher';
2828
import ContextMenu, { aboveLeftOf, ContextMenuTooltipButton, useContextMenu } from '../../structures/ContextMenu';
29-
import { isContentActionable, canEditContent, editEvent } from '../../../utils/EventUtils';
29+
import { isContentActionable, canEditContent, editEvent, canCancel } from '../../../utils/EventUtils';
3030
import RoomContext, { TimelineRenderingType } from "../../../contexts/RoomContext";
3131
import Toolbar from "../../../accessibility/Toolbar";
3232
import { RovingAccessibleTooltipButton, useRovingTabIndex } from "../../../accessibility/RovingTabIndex";
33-
import MessageContextMenu, { canCancel } from "../context_menus/MessageContextMenu";
33+
import MessageContextMenu from "../context_menus/MessageContextMenu";
3434
import Resend from "../../../Resend";
3535
import { MatrixClientPeg } from "../../../MatrixClientPeg";
3636
import { MediaEventHelper } from "../../../utils/MediaEventHelper";

src/components/views/rooms/EventTile.tsx

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ import { RoomNotificationStateStore } from '../../../stores/notifications/RoomNo
7070
import { NotificationStateEvents } from '../../../stores/notifications/NotificationState';
7171
import { NotificationColor } from '../../../stores/notifications/NotificationColor';
7272
import AccessibleButton, { ButtonEvent } from '../elements/AccessibleButton';
73-
import { copyPlaintext } from '../../../utils/strings';
73+
import { copyPlaintext, getSelectedText } from '../../../utils/strings';
7474
import { DecryptionFailureTracker } from '../../../DecryptionFailureTracker';
7575
import RedactedBody from '../messages/RedactedBody';
7676
import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
@@ -947,13 +947,26 @@ export class UnwrappedEventTile extends React.Component<IProps, IState> {
947947
};
948948

949949
private showContextMenu(ev: React.MouseEvent, showPermalink?: boolean): void {
950+
// Return if message right-click context menu isn't enabled
950951
if (!SettingsStore.getValue("feature_message_right_click_context_menu")) return;
952+
953+
// Return if we're in a browser and click either an a tag or we have
954+
// selected text, as in those cases we want to use the native browser
955+
// menu
956+
const clickTarget = ev.target as HTMLElement;
957+
if (
958+
!PlatformPeg.get().allowOverridingNativeContextMenus() &&
959+
(clickTarget.tagName === "a" || clickTarget.closest("a") || getSelectedText())
960+
) return;
961+
951962
// There is no way to copy non-PNG images into clipboard, so we can't
952963
// have our own handling for copying images, so we leave it to the
953964
// Electron layer (webcontents-handler.ts)
954965
if (ev.target instanceof HTMLImageElement) return;
955-
if (!PlatformPeg.get().allowOverridingNativeContextMenus()) return;
966+
967+
// We don't want to show the menu when editing a message
956968
if (this.props.editState) return;
969+
957970
ev.preventDefault();
958971
ev.stopPropagation();
959972
this.setState({

src/utils/EventUtils.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,3 +258,7 @@ export function editEvent(
258258
});
259259
}
260260
}
261+
262+
export function canCancel(status: EventStatus): boolean {
263+
return status === EventStatus.QUEUED || status === EventStatus.NOT_SENT || status === EventStatus.ENCRYPTING;
264+
}

src/utils/strings.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,11 @@ const collator = new Intl.Collator();
8484
export function compare(a: string, b: string): number {
8585
return collator.compare(a, b);
8686
}
87+
88+
/**
89+
* Returns text which has been selected by the user
90+
* @returns the selected text
91+
*/
92+
export function getSelectedText(): string {
93+
return window.getSelection().toString();
94+
}

0 commit comments

Comments
 (0)