Merge pull request #3715 from matrix-org/t3chguy/fix_roomlist_context_menu_regression
Fix remaining context menu regressionspull/21833/head
commit
cb50f5ff5f
|
@ -419,7 +419,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 <ContextMenu /> to position context menu right-aligned and flowing to the left of elementRect
|
||||
|
|
|
@ -108,7 +108,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
|
||||
|
|
|
@ -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 = <BaseAvatar name={groupName} width={24} height={24} url={httpAvatarUrl} />;
|
||||
|
||||
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 = <div title={this.props.group.groupId} className={nameClasses} dir="auto">
|
||||
{ groupName }
|
||||
</div>;
|
||||
|
||||
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 = (
|
||||
<ContextMenuButton
|
||||
className={badgeClasses}
|
||||
inputRef={this._contextMenuButton}
|
||||
onClick={this.openMenu}
|
||||
onClick={this.onContextMenuButtonClick}
|
||||
label={_t("Options")}
|
||||
isExpanded={this.state.menuDisplayed}
|
||||
isExpanded={isMenuDisplayed}
|
||||
>
|
||||
{ badgeContent }
|
||||
</ContextMenuButton>
|
||||
|
@ -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 = (
|
||||
<ContextMenu {...toRightOf(elementRect)} onFinished={this.closeMenu}>
|
||||
<ContextMenu {...toRightOf(this.state.contextMenuPosition)} onFinished={this.closeMenu}>
|
||||
<GroupInviteTileContextMenu group={this.props.group} onFinished={this.closeMenu} />
|
||||
</ContextMenu>
|
||||
);
|
||||
|
|
|
@ -280,7 +280,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;
|
||||
|
|
|
@ -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 ? <span className="mx_RoomTile_subtext">{ subtext }</span> : null;
|
||||
|
@ -346,10 +361,9 @@ module.exports = createReactClass({
|
|||
contextMenuButton = (
|
||||
<ContextMenuButton
|
||||
className="mx_RoomTile_menuButton"
|
||||
inputRef={this._contextMenuButton}
|
||||
label={_t("Options")}
|
||||
isExpanded={this.state.menuDisplayed}
|
||||
onClick={this.openMenu} />
|
||||
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 = (
|
||||
<ContextMenu {...toRightOf(elementRect)} onFinished={this.closeMenu}>
|
||||
<ContextMenu {...toRightOf(this.state.contextMenuPosition)} onFinished={this.closeMenu}>
|
||||
<RoomTileContextMenu room={this.props.room} onFinished={this.closeMenu} />
|
||||
</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"
|
||||
|
|
Loading…
Reference in New Issue