Put the right-click message context menu to the right (#8339)

* Improve `alwaysAboveRightOf()` typing

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>

* Improve typing of `alwaysAboveLeftOf()`

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>

* Add `aboveRightOf()`

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>

* Use `aboveRightOf()`

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>

* Fix typo

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
This commit is contained in:
Šimon Brandner 2022-04-17 15:50:13 +02:00 committed by GitHub
parent 741b13ab6f
commit 7c41b8612d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 38 additions and 6 deletions

View file

@ -450,9 +450,37 @@ export const aboveLeftOf = (
return menuOptions; return menuOptions;
}; };
// Placement method for <ContextMenu /> to position context menu right-aligned and flowing to the right of elementRect,
// and either above or below: wherever there is more space (maybe this should be aboveOrBelowRightOf?)
export const aboveRightOf = (
elementRect: Pick<DOMRect, "left" | "top" | "bottom">,
chevronFace = ChevronFace.None,
vPadding = 0,
): AboveLeftOf => {
const menuOptions: IPosition & { chevronFace: ChevronFace } = { chevronFace };
const buttonLeft = elementRect.left + window.pageXOffset;
const buttonBottom = elementRect.bottom + window.pageYOffset;
const buttonTop = elementRect.top + window.pageYOffset;
// Align the left edge of the menu to the left edge of the button
menuOptions.left = buttonLeft;
// Align the menu vertically on whichever side of the button has more space available.
if (buttonBottom < UIStore.instance.windowHeight / 2) {
menuOptions.top = buttonBottom + vPadding;
} else {
menuOptions.bottom = (UIStore.instance.windowHeight - buttonTop) + vPadding;
}
return menuOptions;
};
// Placement method for <ContextMenu /> to position context menu right-aligned and flowing to the left of elementRect // Placement method for <ContextMenu /> to position context menu right-aligned and flowing to the left of elementRect
// and always above elementRect // and always above elementRect
export const alwaysAboveLeftOf = (elementRect: DOMRect, chevronFace = ChevronFace.None, vPadding = 0) => { export const alwaysAboveLeftOf = (
elementRect: Pick<DOMRect, "right" | "bottom" | "top">,
chevronFace = ChevronFace.None,
vPadding = 0,
) => {
const menuOptions: IPosition & { chevronFace: ChevronFace } = { chevronFace }; const menuOptions: IPosition & { chevronFace: ChevronFace } = { chevronFace };
const buttonRight = elementRect.right + window.pageXOffset; const buttonRight = elementRect.right + window.pageXOffset;
@ -472,7 +500,11 @@ export const alwaysAboveLeftOf = (elementRect: DOMRect, chevronFace = ChevronFac
// Placement method for <ContextMenu /> to position context menu right-aligned and flowing to the right of elementRect // Placement method for <ContextMenu /> to position context menu right-aligned and flowing to the right of elementRect
// and always above elementRect // and always above elementRect
export const alwaysAboveRightOf = (elementRect: DOMRect, chevronFace = ChevronFace.None, vPadding = 0) => { export const alwaysAboveRightOf = (
elementRect: Pick<DOMRect, "left" | "top">,
chevronFace = ChevronFace.None,
vPadding = 0,
) => {
const menuOptions: IPosition & { chevronFace: ChevronFace } = { chevronFace }; const menuOptions: IPosition & { chevronFace: ChevronFace } = { chevronFace };
const buttonLeft = elementRect.left + window.pageXOffset; const buttonLeft = elementRect.left + window.pageXOffset;

View file

@ -39,7 +39,7 @@ 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, { IEventTileOps } from "../context_menus/MessageContextMenu";
import { aboveLeftOf } 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";
import EditorStateTransfer from "../../../utils/EditorStateTransfer"; import EditorStateTransfer from "../../../utils/EditorStateTransfer";
@ -230,7 +230,7 @@ interface IState {
// Position of the context menu // Position of the context menu
contextMenu?: { contextMenu?: {
position: Pick<DOMRect, "right" | "top" | "bottom">; position: Pick<DOMRect, "top" | "left" | "bottom">;
showPermalink?: boolean; showPermalink?: boolean;
}; };
@ -972,7 +972,7 @@ export class UnwrappedEventTile extends React.Component<IProps, IState> {
this.setState({ this.setState({
contextMenu: { contextMenu: {
position: { position: {
right: ev.clientX, left: ev.clientX,
top: ev.clientY, top: ev.clientY,
bottom: ev.clientY, bottom: ev.clientY,
}, },
@ -1017,7 +1017,7 @@ export class UnwrappedEventTile extends React.Component<IProps, IState> {
return ( return (
<MessageContextMenu <MessageContextMenu
{...aboveLeftOf(this.state.contextMenu.position)} {...aboveRightOf(this.state.contextMenu.position)}
mxEvent={this.props.mxEvent} mxEvent={this.props.mxEvent}
permalinkCreator={this.props.permalinkCreator} permalinkCreator={this.props.permalinkCreator}
eventTileOps={eventTileOps} eventTileOps={eventTileOps}