From 52c20db963dc4a6ed6a1a8ed8d649cd5a8d63b38 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Mon, 9 Dec 2019 23:58:09 +0000
Subject: [PATCH 1/3] Fix chevron offset for toRightOf
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
---
src/components/structures/ContextMenu.js | 2 +-
src/components/views/dialogs/ShareDialog.js | 2 +-
src/components/views/messages/TextualBody.js | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/components/structures/ContextMenu.js b/src/components/structures/ContextMenu.js
index 455deb4708..f9fc6b84ee 100644
--- a/src/components/structures/ContextMenu.js
+++ b/src/components/structures/ContextMenu.js
@@ -411,7 +411,7 @@ export const toRightOf = (elementRect, chevronOffset=12) => {
const left = elementRect.right + window.pageXOffset + 3;
let top = elementRect.top + (elementRect.height / 2) + window.pageYOffset;
top -= chevronOffset + 8; // where 8 is half the height of the chevron
- return {left, top};
+ return {left, top, chevronOffset};
};
// Placement method for to position context menu right-aligned and flowing to the left of elementRect
diff --git a/src/components/views/dialogs/ShareDialog.js b/src/components/views/dialogs/ShareDialog.js
index a45eff0d53..97e29bb7d2 100644
--- a/src/components/views/dialogs/ShareDialog.js
+++ b/src/components/views/dialogs/ShareDialog.js
@@ -106,7 +106,7 @@ export default class ShareDialog extends React.Component {
const buttonRect = e.target.getBoundingClientRect();
const GenericTextContextMenu = sdk.getComponent('context_menus.GenericTextContextMenu');
const {close} = ContextMenu.createMenu(GenericTextContextMenu, {
- ...toRightOf(buttonRect, 11),
+ ...toRightOf(buttonRect, 2),
message: successful ? _t('Copied!') : _t('Failed to copy'),
});
// Drop a reference to this close handler for componentWillUnmount
diff --git a/src/components/views/messages/TextualBody.js b/src/components/views/messages/TextualBody.js
index 6e06a6e7b5..fc55612b57 100644
--- a/src/components/views/messages/TextualBody.js
+++ b/src/components/views/messages/TextualBody.js
@@ -276,7 +276,7 @@ module.exports = createReactClass({
const buttonRect = e.target.getBoundingClientRect();
const GenericTextContextMenu = sdk.getComponent('context_menus.GenericTextContextMenu');
const {close} = ContextMenu.createMenu(GenericTextContextMenu, {
- ...toRightOf(buttonRect, 11),
+ ...toRightOf(buttonRect, 2),
message: successful ? _t('Copied!') : _t('Failed to copy'),
});
e.target.onmouseleave = close;
From 5c92f8ab256de473de57bbd8597749ca6cad652a Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Tue, 10 Dec 2019 00:08:45 +0000
Subject: [PATCH 2/3] Fix RoomTile right click context menu
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
---
src/components/views/rooms/RoomTile.js | 55 ++++++++++++++++----------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js
index 313f013de4..817ada9706 100644
--- a/src/components/views/rooms/RoomTile.js
+++ b/src/components/views/rooms/RoomTile.js
@@ -17,7 +17,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import React, {createRef} from 'react';
+import React from 'react';
import PropTypes from 'prop-types';
import createReactClass from 'create-react-class';
import classNames from 'classnames';
@@ -59,7 +59,7 @@ module.exports = createReactClass({
return ({
hover: false,
badgeHover: false,
- menuDisplayed: false,
+ contextMenuPosition: null, // DOM bounding box, null if non-shown
roomName: this.props.room.name,
notifState: RoomNotifs.getRoomNotifsState(this.props.room.roomId),
notificationCount: this.props.room.getUnreadNotificationCount(),
@@ -145,8 +145,6 @@ module.exports = createReactClass({
},
componentDidMount: function() {
- this._contextMenuButton = createRef();
-
const cli = MatrixClientPeg.get();
cli.on("accountData", this.onAccountData);
cli.on("Room.name", this.onRoomName);
@@ -241,16 +239,12 @@ module.exports = createReactClass({
this.setState( { badgeHover: false } );
},
- openMenu: function(e) {
+ _showContextMenu: function(boundingClientRect) {
// Only allow non-guests to access the context menu
if (MatrixClientPeg.get().isGuest()) return;
- // Prevent the RoomTile onClick event firing as well
- e.stopPropagation();
- e.preventDefault();
-
const state = {
- menuDisplayed: true,
+ contextMenuPosition: boundingClientRect,
};
// If the badge is clicked, then no longer show tooltip
@@ -261,9 +255,28 @@ module.exports = createReactClass({
this.setState(state);
},
+ onContextMenuButtonClick: function(e) {
+ // Prevent the RoomTile onClick event firing as well
+ e.stopPropagation();
+ e.preventDefault();
+
+ this._showContextMenu(e.target.getBoundingClientRect());
+ },
+
+ onContextMenu: function(e) {
+ // Prevent the native context menu
+ e.preventDefault();
+
+ this._showContextMenu({
+ right: e.clientX,
+ top: e.clientY,
+ height: 0,
+ });
+ },
+
closeMenu: function() {
this.setState({
- menuDisplayed: false,
+ contextMenuPosition: null,
});
this.props.refreshSubList();
},
@@ -282,6 +295,8 @@ module.exports = createReactClass({
subtext = this.state.statusMessage;
}
+ const isMenuDisplayed = Boolean(this.state.contextMenuPosition);
+
const classes = classNames({
'mx_RoomTile': true,
'mx_RoomTile_selected': this.state.selected,
@@ -289,7 +304,7 @@ module.exports = createReactClass({
'mx_RoomTile_unreadNotify': notifBadges,
'mx_RoomTile_highlight': mentionBadges,
'mx_RoomTile_invited': isInvite,
- 'mx_RoomTile_menuDisplayed': this.state.menuDisplayed,
+ 'mx_RoomTile_menuDisplayed': isMenuDisplayed,
'mx_RoomTile_noBadges': !badges,
'mx_RoomTile_transparent': this.props.transparent,
'mx_RoomTile_hasSubtext': subtext && !this.props.collapsed,
@@ -301,7 +316,7 @@ module.exports = createReactClass({
const badgeClasses = classNames({
'mx_RoomTile_badge': true,
- 'mx_RoomTile_badgeButton': this.state.badgeHover || this.state.menuDisplayed,
+ 'mx_RoomTile_badgeButton': this.state.badgeHover || isMenuDisplayed,
});
let name = this.state.roomName;
@@ -323,7 +338,7 @@ module.exports = createReactClass({
const nameClasses = classNames({
'mx_RoomTile_name': true,
'mx_RoomTile_invite': this.props.isInvite,
- 'mx_RoomTile_badgeShown': badges || this.state.badgeHover || this.state.menuDisplayed,
+ 'mx_RoomTile_badgeShown': badges || this.state.badgeHover || isMenuDisplayed,
});
subtextLabel = subtext ? { subtext } : null;
@@ -346,10 +361,9 @@ module.exports = createReactClass({
contextMenuButton = (
+ isExpanded={isMenuDisplayed}
+ onClick={this.onContextMenuButtonClick} />
);
}
@@ -382,11 +396,10 @@ module.exports = createReactClass({
}
let contextMenu;
- if (this.state.menuDisplayed && this._contextMenuButton.current) {
- const elementRect = this._contextMenuButton.current.getBoundingClientRect();
+ if (isMenuDisplayed) {
const RoomTileContextMenu = sdk.getComponent('context_menus.RoomTileContextMenu');
contextMenu = (
-
+
);
@@ -399,7 +412,7 @@ module.exports = createReactClass({
onClick={this.onClick}
onMouseEnter={this.onMouseEnter}
onMouseLeave={this.onMouseLeave}
- onContextMenu={this.openMenu}
+ onContextMenu={this.onContextMenu}
aria-label={ariaLabel}
aria-selected={this.state.selected}
role="treeitem"
From 44adda354763b0332373439df3d60c1dc0e98662 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Tue, 10 Dec 2019 00:14:36 +0000
Subject: [PATCH 3/3] Add right-click context menu to GroupInviteTile.js
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
---
.../views/groups/GroupInviteTile.js | 53 +++++++++++--------
1 file changed, 32 insertions(+), 21 deletions(-)
diff --git a/src/components/views/groups/GroupInviteTile.js b/src/components/views/groups/GroupInviteTile.js
index bc861eb156..a21b091145 100644
--- a/src/components/views/groups/GroupInviteTile.js
+++ b/src/components/views/groups/GroupInviteTile.js
@@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import React, {createRef} from 'react';
+import React from 'react';
import PropTypes from 'prop-types';
import createReactClass from 'create-react-class';
import { MatrixClient } from 'matrix-js-sdk';
@@ -27,6 +27,7 @@ import classNames from 'classnames';
import MatrixClientPeg from "../../../MatrixClientPeg";
import {ContextMenu, ContextMenuButton, toRightOf} from "../../structures/ContextMenu";
+// XXX this class copies a lot from RoomTile.js
export default createReactClass({
displayName: 'GroupInviteTile',
@@ -47,10 +48,6 @@ export default createReactClass({
});
},
- componentDidMount: function() {
- this._contextMenuButton = createRef();
- },
-
onClick: function(e) {
dis.dispatch({
action: 'view_group',
@@ -74,16 +71,12 @@ export default createReactClass({
});
},
- openMenu: function(e) {
+ _showContextMenu: function(boundingClientRect) {
// Only allow non-guests to access the context menu
if (MatrixClientPeg.get().isGuest()) return;
- // Prevent the GroupInviteTile onClick event firing as well
- e.stopPropagation();
- e.preventDefault();
-
const state = {
- menuDisplayed: true,
+ contextMenuPosition: boundingClientRect,
};
// If the badge is clicked, then no longer show tooltip
@@ -94,9 +87,28 @@ export default createReactClass({
this.setState(state);
},
+ onContextMenuButtonClick: function(e) {
+ // Prevent the RoomTile onClick event firing as well
+ e.stopPropagation();
+ e.preventDefault();
+
+ this._showContextMenu(e.target.getBoundingClientRect());
+ },
+
+ onContextMenu: function(e) {
+ // Prevent the native context menu
+ e.preventDefault();
+
+ this._showContextMenu({
+ right: e.clientX,
+ top: e.clientY,
+ height: 0,
+ });
+ },
+
closeMenu: function() {
this.setState({
- menuDisplayed: false,
+ contextMenuPosition: null,
});
},
@@ -110,15 +122,16 @@ export default createReactClass({
const av = ;
+ const isMenuDisplayed = Boolean(this.state.contextMenuPosition);
const nameClasses = classNames('mx_RoomTile_name mx_RoomTile_invite mx_RoomTile_badgeShown', {
- 'mx_RoomTile_badgeShown': this.state.badgeHover || this.state.menuDisplayed,
+ 'mx_RoomTile_badgeShown': this.state.badgeHover || isMenuDisplayed,
});
const label =
{ groupName }
;
- const badgeEllipsis = this.state.badgeHover || this.state.menuDisplayed;
+ const badgeEllipsis = this.state.badgeHover || isMenuDisplayed;
const badgeClasses = classNames('mx_RoomTile_badge mx_RoomTile_highlight', {
'mx_RoomTile_badgeButton': badgeEllipsis,
});
@@ -127,10 +140,9 @@ export default createReactClass({
const badge = (
{ badgeContent }
@@ -143,17 +155,16 @@ export default createReactClass({
}
const classes = classNames('mx_RoomTile mx_RoomTile_highlight', {
- 'mx_RoomTile_menuDisplayed': this.state.menuDisplayed,
+ 'mx_RoomTile_menuDisplayed': isMenuDisplayed,
'mx_RoomTile_selected': this.state.selected,
'mx_GroupInviteTile': true,
});
let contextMenu;
- if (this.state.menuDisplayed) {
- const elementRect = this._contextMenuButton.current.getBoundingClientRect();
+ if (isMenuDisplayed) {
const GroupInviteTileContextMenu = sdk.getComponent('context_menus.GroupInviteTileContextMenu');
contextMenu = (
-
+
);