From 2eddb6ca01dc17d41ee0601d3803461471cb78d4 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 12 Nov 2019 11:24:14 +0000 Subject: [PATCH] DRY context menu placement algorithms --- src/components/structures/ContextualMenu.js | 8 +++ src/components/views/elements/TagTile.js | 11 +--- .../views/groups/GroupInviteTile.js | 10 +--- .../views/messages/MessageActionBar.js | 60 +++++++------------ src/components/views/rooms/RoomTile.js | 10 +--- 5 files changed, 36 insertions(+), 63 deletions(-) diff --git a/src/components/structures/ContextualMenu.js b/src/components/structures/ContextualMenu.js index 6d046c08d4..c172daf991 100644 --- a/src/components/structures/ContextualMenu.js +++ b/src/components/structures/ContextualMenu.js @@ -559,6 +559,14 @@ MenuItemRadio.propTypes = { onClick: PropTypes.func.isRequired, }; +// Placement method for to position context menu to right of elementRect with chevronOffset +export const toRightOf = (elementRect, chevronOffset=12) => { + const left = elementRect.right + window.pageXOffset + 3; + let top = (elementRect.top + (elementRect.height / 2) + window.pageYOffset); + top = top - (chevronOffset + 8); // where 8 is half the height of the chevron + return {left, top}; +}; + export function createMenu(ElementClass, props, hasBackground=true) { const closeMenu = function(...args) { ReactDOM.unmountComponentAtNode(getOrCreateContainer()); diff --git a/src/components/views/elements/TagTile.js b/src/components/views/elements/TagTile.js index 03d7f61204..c9afd487cb 100644 --- a/src/components/views/elements/TagTile.js +++ b/src/components/views/elements/TagTile.js @@ -29,7 +29,7 @@ import * as FormattingUtils from '../../../utils/FormattingUtils'; import FlairStore from '../../../stores/FlairStore'; import GroupStore from '../../../stores/GroupStore'; import TagOrderStore from '../../../stores/TagOrderStore'; -import {ContextMenu} from "../../structures/ContextualMenu"; +import {ContextMenu, toRightOf} from "../../structures/ContextualMenu"; // A class for a child of TagPanel (possibly wrapped in a DNDTagTile) that represents // a thing to click on for the user to filter the visible rooms in the RoomList to: @@ -176,16 +176,9 @@ export default createReactClass({ let contextMenu; if (this.state.menuDisplayed) { const elementRect = this._contextMenuButton.current.getBoundingClientRect(); - - // The window X and Y offsets are to adjust position when zoomed in to page - const left = elementRect.right + window.pageXOffset + 3; - const chevronOffset = 12; - let top = (elementRect.top + (elementRect.height / 2) + window.pageYOffset); - top = top - (chevronOffset + 8); // where 8 is half the height of the chevron - const TagTileContextMenu = sdk.getComponent('context_menus.TagTileContextMenu'); contextMenu = ( - + ); diff --git a/src/components/views/groups/GroupInviteTile.js b/src/components/views/groups/GroupInviteTile.js index 99427acb03..cfc50cc008 100644 --- a/src/components/views/groups/GroupInviteTile.js +++ b/src/components/views/groups/GroupInviteTile.js @@ -24,7 +24,7 @@ import sdk from '../../../index'; import dis from '../../../dispatcher'; import classNames from 'classnames'; import MatrixClientPeg from "../../../MatrixClientPeg"; -import {ContextMenu} from "../../structures/ContextualMenu"; +import {ContextMenu, toRightOf} from "../../structures/ContextualMenu"; export default createReactClass({ displayName: 'GroupInviteTile', @@ -144,15 +144,9 @@ export default createReactClass({ let contextMenu; if (this.state.menuDisplayed) { const elementRect = this._contextMenuButton.current.getBoundingClientRect(); - // The window X and Y offsets are to adjust position when zoomed in to page - const left = elementRect.right + window.pageXOffset + 3; - const chevronOffset = 12; - let top = (elementRect.top + (elementRect.height / 2) + window.pageYOffset); - top = top - (chevronOffset + 8); // where 8 is half the height of the chevron - const GroupInviteTileContextMenu = sdk.getComponent('context_menus.GroupInviteTileContextMenu'); contextMenu = ( - + ); diff --git a/src/components/views/messages/MessageActionBar.js b/src/components/views/messages/MessageActionBar.js index b67107eebf..d59e74623a 100644 --- a/src/components/views/messages/MessageActionBar.js +++ b/src/components/views/messages/MessageActionBar.js @@ -27,6 +27,26 @@ import {ContextMenu} from '../../structures/ContextualMenu'; import { isContentActionable, canEditContent } from '../../../utils/EventUtils'; import {RoomContext} from "../../structures/RoomView"; +const contextMenuProps = (elementRect) => { + const menuOptions = { + chevronFace: "none", + }; + + const buttonRight = elementRect.right + window.pageXOffset; + const buttonBottom = elementRect.bottom + window.pageYOffset; + const buttonTop = elementRect.top + window.pageYOffset; + // Align the right edge of the menu to the right edge of the button + menuOptions.right = window.innerWidth - buttonRight; + // Align the menu vertically on whichever side of the button has more space available. + if (buttonBottom < window.innerHeight / 2) { + menuOptions.top = buttonBottom; + } else { + menuOptions.bottom = window.innerHeight - buttonTop; + } + + return menuOptions; +}; + const useContextMenu = () => { const _button = useRef(null); const [isOpen, setIsOpen] = useState(false); @@ -65,26 +85,8 @@ const OptionsButton = ({mxEvent, getTile, getReplyThread, permalinkCreator, onFo e2eInfoCallback = onCryptoClick; } - const menuOptions = { - chevronFace: "none", - }; - const buttonRect = _button.current.getBoundingClientRect(); - // The window X and Y offsets are to adjust position when zoomed in to page - const buttonRight = buttonRect.right + window.pageXOffset; - const buttonBottom = buttonRect.bottom + window.pageYOffset; - const buttonTop = buttonRect.top + window.pageYOffset; - // Align the right edge of the menu to the right edge of the button - menuOptions.right = window.innerWidth - buttonRight; - // Align the menu vertically on whichever side of the button has more - // space available. - if (buttonBottom < window.innerHeight / 2) { - menuOptions.top = buttonBottom; - } else { - menuOptions.bottom = window.innerHeight - buttonTop; - } - - contextMenu = + contextMenu = { let contextMenu; if (menuDisplayed) { - const menuOptions = { - chevronFace: "none", - }; - const buttonRect = _button.current.getBoundingClientRect(); - // The window X and Y offsets are to adjust position when zoomed in to page - const buttonRight = buttonRect.right + window.pageXOffset; - const buttonBottom = buttonRect.bottom + window.pageYOffset; - const buttonTop = buttonRect.top + window.pageYOffset; - // Align the right edge of the menu to the right edge of the button - menuOptions.right = window.innerWidth - buttonRight; - // Align the menu vertically on whichever side of the button has more - // space available. - if (buttonBottom < window.innerHeight / 2) { - menuOptions.top = buttonBottom; - } else { - menuOptions.bottom = window.innerHeight - buttonTop; - } - const ReactionPicker = sdk.getComponent('emojipicker.ReactionPicker'); - contextMenu = + contextMenu = ; } diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js index 9702b24eff..edd50d0330 100644 --- a/src/components/views/rooms/RoomTile.js +++ b/src/components/views/rooms/RoomTile.js @@ -25,7 +25,7 @@ import dis from '../../../dispatcher'; import MatrixClientPeg from '../../../MatrixClientPeg'; import DMRoomMap from '../../../utils/DMRoomMap'; import sdk from '../../../index'; -import {ContextMenu} from '../../structures/ContextualMenu'; +import {ContextMenu, toRightOf} from '../../structures/ContextualMenu'; import * as RoomNotifs from '../../../RoomNotifs'; import * as FormattingUtils from '../../../utils/FormattingUtils'; import ActiveRoomObserver from '../../../ActiveRoomObserver'; @@ -379,15 +379,9 @@ module.exports = createReactClass({ let contextMenu; if (this.state.menuDisplayed) { const elementRect = this._contextMenuButton.current.getBoundingClientRect(); - // The window X and Y offsets are to adjust position when zoomed in to page - const left = elementRect.right + window.pageXOffset + 3; - const chevronOffset = 12; - let top = (elementRect.top + (elementRect.height / 2) + window.pageYOffset); - top = top - (chevronOffset + 8); // where 8 is half the height of the chevron - const RoomTileContextMenu = sdk.getComponent('context_menus.RoomTileContextMenu'); contextMenu = ( - + );