mirror of https://github.com/vector-im/riot-web
Support right click context menu interactions on Room List 2
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>pull/21833/head
parent
89bd572371
commit
5c2b291510
|
@ -42,8 +42,10 @@ interface IProps {
|
||||||
isMinimized: boolean;
|
isMinimized: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PartialDOMRect = Pick<DOMRect, "width" | "left" | "top" | "height">;
|
||||||
|
|
||||||
interface IState {
|
interface IState {
|
||||||
menuDisplayed: boolean;
|
contextMenuPosition: PartialDOMRect;
|
||||||
isDarkTheme: boolean;
|
isDarkTheme: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +58,7 @@ export default class UserMenu extends React.Component<IProps, IState> {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
menuDisplayed: false,
|
contextMenuPosition: null,
|
||||||
isDarkTheme: this.isUserOnDarkTheme(),
|
isDarkTheme: this.isUserOnDarkTheme(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -106,13 +108,27 @@ export default class UserMenu extends React.Component<IProps, IState> {
|
||||||
private onOpenMenuClick = (ev: InputEvent) => {
|
private onOpenMenuClick = (ev: InputEvent) => {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
this.setState({menuDisplayed: true});
|
const target = ev.target as HTMLButtonElement;
|
||||||
|
this.setState({contextMenuPosition: target.getBoundingClientRect()});
|
||||||
|
};
|
||||||
|
|
||||||
|
private onContextMenu = (ev: React.MouseEvent) => {
|
||||||
|
ev.preventDefault();
|
||||||
|
ev.stopPropagation();
|
||||||
|
this.setState({
|
||||||
|
contextMenuPosition: {
|
||||||
|
left: ev.clientX,
|
||||||
|
top: ev.clientY,
|
||||||
|
width: 20,
|
||||||
|
height: 0,
|
||||||
|
},
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
private onCloseMenu = (ev: InputEvent) => {
|
private onCloseMenu = (ev: InputEvent) => {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
this.setState({menuDisplayed: false});
|
this.setState({contextMenuPosition: null});
|
||||||
};
|
};
|
||||||
|
|
||||||
private onSwitchThemeClick = () => {
|
private onSwitchThemeClick = () => {
|
||||||
|
@ -129,7 +145,7 @@ export default class UserMenu extends React.Component<IProps, IState> {
|
||||||
|
|
||||||
const payload: OpenToTabPayload = {action: Action.ViewUserSettings, initialTabId: tabId};
|
const payload: OpenToTabPayload = {action: Action.ViewUserSettings, initialTabId: tabId};
|
||||||
defaultDispatcher.dispatch(payload);
|
defaultDispatcher.dispatch(payload);
|
||||||
this.setState({menuDisplayed: false}); // also close the menu
|
this.setState({contextMenuPosition: null}); // also close the menu
|
||||||
};
|
};
|
||||||
|
|
||||||
private onShowArchived = (ev: ButtonEvent) => {
|
private onShowArchived = (ev: ButtonEvent) => {
|
||||||
|
@ -145,7 +161,7 @@ export default class UserMenu extends React.Component<IProps, IState> {
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
|
|
||||||
Modal.createTrackedDialog('Report bugs & give feedback', '', RedesignFeedbackDialog);
|
Modal.createTrackedDialog('Report bugs & give feedback', '', RedesignFeedbackDialog);
|
||||||
this.setState({menuDisplayed: false}); // also close the menu
|
this.setState({contextMenuPosition: null}); // also close the menu
|
||||||
};
|
};
|
||||||
|
|
||||||
private onSignOutClick = (ev: ButtonEvent) => {
|
private onSignOutClick = (ev: ButtonEvent) => {
|
||||||
|
@ -153,7 +169,7 @@ export default class UserMenu extends React.Component<IProps, IState> {
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
|
|
||||||
Modal.createTrackedDialog('Logout from LeftPanel', '', LogoutDialog);
|
Modal.createTrackedDialog('Logout from LeftPanel', '', LogoutDialog);
|
||||||
this.setState({menuDisplayed: false}); // also close the menu
|
this.setState({contextMenuPosition: null}); // also close the menu
|
||||||
};
|
};
|
||||||
|
|
||||||
private onHomeClick = (ev: ButtonEvent) => {
|
private onHomeClick = (ev: ButtonEvent) => {
|
||||||
|
@ -164,7 +180,7 @@ export default class UserMenu extends React.Component<IProps, IState> {
|
||||||
};
|
};
|
||||||
|
|
||||||
private renderContextMenu = (): React.ReactNode => {
|
private renderContextMenu = (): React.ReactNode => {
|
||||||
if (!this.state.menuDisplayed) return null;
|
if (!this.state.contextMenuPosition) return null;
|
||||||
|
|
||||||
let hostingLink;
|
let hostingLink;
|
||||||
const signupLink = getHostingLink("user-context-menu");
|
const signupLink = getHostingLink("user-context-menu");
|
||||||
|
@ -198,13 +214,12 @@ export default class UserMenu extends React.Component<IProps, IState> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const elementRect = this.buttonRef.current.getBoundingClientRect();
|
|
||||||
return (
|
return (
|
||||||
<ContextMenu
|
<ContextMenu
|
||||||
chevronFace="none"
|
chevronFace="none"
|
||||||
// -20 to overlap the context menu by just over the width of the `...` icon and make it look connected
|
// -20 to overlap the context menu by just over the width of the `...` icon and make it look connected
|
||||||
left={elementRect.width + elementRect.left - 20}
|
left={this.state.contextMenuPosition.width + this.state.contextMenuPosition.left - 20}
|
||||||
top={elementRect.top + elementRect.height}
|
top={this.state.contextMenuPosition.top + this.state.contextMenuPosition.height}
|
||||||
onFinished={this.onCloseMenu}
|
onFinished={this.onCloseMenu}
|
||||||
>
|
>
|
||||||
<div className="mx_IconizedContextMenu mx_UserMenu_contextMenu">
|
<div className="mx_IconizedContextMenu mx_UserMenu_contextMenu">
|
||||||
|
@ -290,7 +305,8 @@ export default class UserMenu extends React.Component<IProps, IState> {
|
||||||
onClick={this.onOpenMenuClick}
|
onClick={this.onOpenMenuClick}
|
||||||
inputRef={this.buttonRef}
|
inputRef={this.buttonRef}
|
||||||
label={_t("Account settings")}
|
label={_t("Account settings")}
|
||||||
isExpanded={this.state.menuDisplayed}
|
isExpanded={!!this.state.contextMenuPosition}
|
||||||
|
onContextMenu={this.onContextMenu}
|
||||||
>
|
>
|
||||||
<div className="mx_UserMenu_row">
|
<div className="mx_UserMenu_row">
|
||||||
<span className="mx_UserMenu_userAvatarContainer">
|
<span className="mx_UserMenu_userAvatarContainer">
|
||||||
|
|
|
@ -65,22 +65,21 @@ interface IProps {
|
||||||
// TODO: Account for https://github.com/vector-im/riot-web/issues/14179
|
// TODO: Account for https://github.com/vector-im/riot-web/issues/14179
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PartialDOMRect = Pick<DOMRect, "left" | "top" | "height">;
|
||||||
|
|
||||||
interface IState {
|
interface IState {
|
||||||
notificationState: ListNotificationState;
|
notificationState: ListNotificationState;
|
||||||
menuDisplayed: boolean;
|
contextMenuPosition: PartialDOMRect;
|
||||||
isResizing: boolean;
|
isResizing: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class RoomSublist2 extends React.Component<IProps, IState> {
|
export default class RoomSublist2 extends React.Component<IProps, IState> {
|
||||||
private headerButton = createRef();
|
|
||||||
private menuButtonRef: React.RefObject<HTMLButtonElement> = createRef();
|
|
||||||
|
|
||||||
constructor(props: IProps) {
|
constructor(props: IProps) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
notificationState: new ListNotificationState(this.props.isInvite, this.props.tagId),
|
notificationState: new ListNotificationState(this.props.isInvite, this.props.tagId),
|
||||||
menuDisplayed: false,
|
contextMenuPosition: null,
|
||||||
isResizing: false,
|
isResizing: false,
|
||||||
};
|
};
|
||||||
this.state.notificationState.setRooms(this.props.rooms);
|
this.state.notificationState.setRooms(this.props.rooms);
|
||||||
|
@ -132,11 +131,24 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
|
||||||
private onOpenMenuClick = (ev: InputEvent) => {
|
private onOpenMenuClick = (ev: InputEvent) => {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
this.setState({menuDisplayed: true});
|
const target = ev.target as HTMLButtonElement;
|
||||||
|
this.setState({contextMenuPosition: target.getBoundingClientRect()});
|
||||||
|
};
|
||||||
|
|
||||||
|
private onContextMenu = (ev: React.MouseEvent) => {
|
||||||
|
ev.preventDefault();
|
||||||
|
ev.stopPropagation();
|
||||||
|
this.setState({
|
||||||
|
contextMenuPosition: {
|
||||||
|
left: ev.clientX,
|
||||||
|
top: ev.clientY,
|
||||||
|
height: 0,
|
||||||
|
},
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
private onCloseMenu = () => {
|
private onCloseMenu = () => {
|
||||||
this.setState({menuDisplayed: false});
|
this.setState({contextMenuPosition: null});
|
||||||
};
|
};
|
||||||
|
|
||||||
private onUnreadFirstChanged = async () => {
|
private onUnreadFirstChanged = async () => {
|
||||||
|
@ -202,15 +214,14 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let contextMenu = null;
|
let contextMenu = null;
|
||||||
if (this.state.menuDisplayed) {
|
if (this.state.contextMenuPosition) {
|
||||||
const elementRect = this.menuButtonRef.current.getBoundingClientRect();
|
|
||||||
const isAlphabetical = RoomListStore.instance.getTagSorting(this.props.tagId) === SortAlgorithm.Alphabetic;
|
const isAlphabetical = RoomListStore.instance.getTagSorting(this.props.tagId) === SortAlgorithm.Alphabetic;
|
||||||
const isUnreadFirst = RoomListStore.instance.getListOrder(this.props.tagId) === ListAlgorithm.Importance;
|
const isUnreadFirst = RoomListStore.instance.getListOrder(this.props.tagId) === ListAlgorithm.Importance;
|
||||||
contextMenu = (
|
contextMenu = (
|
||||||
<ContextMenu
|
<ContextMenu
|
||||||
chevronFace="none"
|
chevronFace="none"
|
||||||
left={elementRect.left}
|
left={this.state.contextMenuPosition.left}
|
||||||
top={elementRect.top + elementRect.height}
|
top={this.state.contextMenuPosition.top + this.state.contextMenuPosition.height}
|
||||||
onFinished={this.onCloseMenu}
|
onFinished={this.onCloseMenu}
|
||||||
>
|
>
|
||||||
<div className="mx_RoomSublist2_contextMenu">
|
<div className="mx_RoomSublist2_contextMenu">
|
||||||
|
@ -261,9 +272,8 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
|
||||||
<ContextMenuButton
|
<ContextMenuButton
|
||||||
className="mx_RoomSublist2_menuButton"
|
className="mx_RoomSublist2_menuButton"
|
||||||
onClick={this.onOpenMenuClick}
|
onClick={this.onOpenMenuClick}
|
||||||
inputRef={this.menuButtonRef}
|
|
||||||
label={_t("List options")}
|
label={_t("List options")}
|
||||||
isExpanded={this.state.menuDisplayed}
|
isExpanded={!!this.state.contextMenuPosition}
|
||||||
/>
|
/>
|
||||||
{contextMenu}
|
{contextMenu}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
|
@ -272,7 +282,7 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
|
||||||
|
|
||||||
private renderHeader(): React.ReactElement {
|
private renderHeader(): React.ReactElement {
|
||||||
return (
|
return (
|
||||||
<RovingTabIndexWrapper inputRef={this.headerButton}>
|
<RovingTabIndexWrapper>
|
||||||
{({onFocus, isActive, ref}) => {
|
{({onFocus, isActive, ref}) => {
|
||||||
// TODO: Use onFocus: https://github.com/vector-im/riot-web/issues/14180
|
// TODO: Use onFocus: https://github.com/vector-im/riot-web/issues/14180
|
||||||
const tabIndex = isActive ? 0 : -1;
|
const tabIndex = isActive ? 0 : -1;
|
||||||
|
@ -317,12 +327,14 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
|
||||||
<div className={classes}>
|
<div className={classes}>
|
||||||
<div className='mx_RoomSublist2_stickable'>
|
<div className='mx_RoomSublist2_stickable'>
|
||||||
<AccessibleButton
|
<AccessibleButton
|
||||||
|
onFocus={onFocus}
|
||||||
inputRef={ref}
|
inputRef={ref}
|
||||||
tabIndex={tabIndex}
|
tabIndex={tabIndex}
|
||||||
className={"mx_RoomSublist2_headerText"}
|
className={"mx_RoomSublist2_headerText"}
|
||||||
role="treeitem"
|
role="treeitem"
|
||||||
aria-level={1}
|
aria-level={1}
|
||||||
onClick={this.onHeaderClick}
|
onClick={this.onHeaderClick}
|
||||||
|
onContextMenu={this.onContextMenu}
|
||||||
>
|
>
|
||||||
<span className={collapseClasses} />
|
<span className={collapseClasses} />
|
||||||
<span>{this.props.label}</span>
|
<span>{this.props.label}</span>
|
||||||
|
@ -347,7 +359,7 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
|
||||||
|
|
||||||
const classes = classNames({
|
const classes = classNames({
|
||||||
'mx_RoomSublist2': true,
|
'mx_RoomSublist2': true,
|
||||||
'mx_RoomSublist2_hasMenuOpen': this.state.menuDisplayed,
|
'mx_RoomSublist2_hasMenuOpen': !!this.state.contextMenuPosition,
|
||||||
'mx_RoomSublist2_minimized': this.props.isMinimized,
|
'mx_RoomSublist2_minimized': this.props.isMinimized,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -60,15 +60,17 @@ interface IProps {
|
||||||
// TODO: Incoming call boxes: https://github.com/vector-im/riot-web/issues/14177
|
// TODO: Incoming call boxes: https://github.com/vector-im/riot-web/issues/14177
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PartialDOMRect = Pick<DOMRect, "left" | "bottom">;
|
||||||
|
|
||||||
interface IState {
|
interface IState {
|
||||||
hover: boolean;
|
hover: boolean;
|
||||||
notificationState: INotificationState;
|
notificationState: INotificationState;
|
||||||
selected: boolean;
|
selected: boolean;
|
||||||
notificationsMenuDisplayed: boolean;
|
notificationsMenuPosition: PartialDOMRect;
|
||||||
generalMenuDisplayed: boolean;
|
generalMenuPosition: PartialDOMRect;
|
||||||
}
|
}
|
||||||
|
|
||||||
const contextMenuBelow = (elementRect) => {
|
const contextMenuBelow = (elementRect: PartialDOMRect) => {
|
||||||
// align the context menu's icons with the icon which opened the context menu
|
// align the context menu's icons with the icon which opened the context menu
|
||||||
const left = elementRect.left + window.pageXOffset - 9;
|
const left = elementRect.left + window.pageXOffset - 9;
|
||||||
let top = elementRect.bottom + window.pageYOffset + 17;
|
let top = elementRect.bottom + window.pageYOffset + 17;
|
||||||
|
@ -103,9 +105,6 @@ const NotifOption: React.FC<INotifOptionProps> = ({active, onClick, iconClassNam
|
||||||
};
|
};
|
||||||
|
|
||||||
export default class RoomTile2 extends React.Component<IProps, IState> {
|
export default class RoomTile2 extends React.Component<IProps, IState> {
|
||||||
private notificationsMenuButtonRef: React.RefObject<HTMLButtonElement> = createRef();
|
|
||||||
private generalMenuButtonRef: React.RefObject<HTMLButtonElement> = createRef();
|
|
||||||
|
|
||||||
// TODO: a11y: https://github.com/vector-im/riot-web/issues/14180
|
// TODO: a11y: https://github.com/vector-im/riot-web/issues/14180
|
||||||
|
|
||||||
constructor(props: IProps) {
|
constructor(props: IProps) {
|
||||||
|
@ -115,8 +114,8 @@ export default class RoomTile2 extends React.Component<IProps, IState> {
|
||||||
hover: false,
|
hover: false,
|
||||||
notificationState: new TagSpecificNotificationState(this.props.room, this.props.tag),
|
notificationState: new TagSpecificNotificationState(this.props.room, this.props.tag),
|
||||||
selected: ActiveRoomObserver.activeRoomId === this.props.room.roomId,
|
selected: ActiveRoomObserver.activeRoomId === this.props.room.roomId,
|
||||||
notificationsMenuDisplayed: false,
|
notificationsMenuPosition: null,
|
||||||
generalMenuDisplayed: false,
|
generalMenuPosition: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
ActiveRoomObserver.addListener(this.props.room.roomId, this.onActiveRoomUpdate);
|
ActiveRoomObserver.addListener(this.props.room.roomId, this.onActiveRoomUpdate);
|
||||||
|
@ -137,6 +136,8 @@ export default class RoomTile2 extends React.Component<IProps, IState> {
|
||||||
};
|
};
|
||||||
|
|
||||||
private onTileClick = (ev: React.KeyboardEvent) => {
|
private onTileClick = (ev: React.KeyboardEvent) => {
|
||||||
|
ev.preventDefault();
|
||||||
|
ev.stopPropagation();
|
||||||
dis.dispatch({
|
dis.dispatch({
|
||||||
action: 'view_room',
|
action: 'view_room',
|
||||||
// TODO: Support show_room_tile in new room list: https://github.com/vector-im/riot-web/issues/14233
|
// TODO: Support show_room_tile in new room list: https://github.com/vector-im/riot-web/issues/14233
|
||||||
|
@ -153,25 +154,34 @@ export default class RoomTile2 extends React.Component<IProps, IState> {
|
||||||
private onNotificationsMenuOpenClick = (ev: InputEvent) => {
|
private onNotificationsMenuOpenClick = (ev: InputEvent) => {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
this.setState({notificationsMenuDisplayed: true});
|
const target = ev.target as HTMLButtonElement;
|
||||||
|
this.setState({notificationsMenuPosition: target.getBoundingClientRect()});
|
||||||
};
|
};
|
||||||
|
|
||||||
private onCloseNotificationsMenu = (ev: InputEvent) => {
|
private onCloseNotificationsMenu = () => {
|
||||||
ev.preventDefault();
|
this.setState({notificationsMenuPosition: null});
|
||||||
ev.stopPropagation();
|
|
||||||
this.setState({notificationsMenuDisplayed: false});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private onGeneralMenuOpenClick = (ev: InputEvent) => {
|
private onGeneralMenuOpenClick = (ev: InputEvent) => {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
this.setState({generalMenuDisplayed: true});
|
const target = ev.target as HTMLButtonElement;
|
||||||
|
this.setState({generalMenuPosition: target.getBoundingClientRect()});
|
||||||
};
|
};
|
||||||
|
|
||||||
private onCloseGeneralMenu = (ev: InputEvent) => {
|
private onContextMenu = (ev: React.MouseEvent) => {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
this.setState({generalMenuDisplayed: false});
|
this.setState({
|
||||||
|
generalMenuPosition: {
|
||||||
|
left: ev.clientX,
|
||||||
|
bottom: ev.clientY,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
private onCloseGeneralMenu = () => {
|
||||||
|
this.setState({generalMenuPosition: null});
|
||||||
};
|
};
|
||||||
|
|
||||||
private onTagRoom = (ev: ButtonEvent, tagId: TagID) => {
|
private onTagRoom = (ev: ButtonEvent, tagId: TagID) => {
|
||||||
|
@ -190,7 +200,7 @@ export default class RoomTile2 extends React.Component<IProps, IState> {
|
||||||
action: 'leave_room',
|
action: 'leave_room',
|
||||||
room_id: this.props.room.roomId,
|
room_id: this.props.room.roomId,
|
||||||
});
|
});
|
||||||
this.setState({generalMenuDisplayed: false}); // hide the menu
|
this.setState({generalMenuPosition: null}); // hide the menu
|
||||||
};
|
};
|
||||||
|
|
||||||
private onOpenRoomSettings = (ev: ButtonEvent) => {
|
private onOpenRoomSettings = (ev: ButtonEvent) => {
|
||||||
|
@ -201,7 +211,7 @@ export default class RoomTile2 extends React.Component<IProps, IState> {
|
||||||
action: 'open_room_settings',
|
action: 'open_room_settings',
|
||||||
room_id: this.props.room.roomId,
|
room_id: this.props.room.roomId,
|
||||||
});
|
});
|
||||||
this.setState({generalMenuDisplayed: false}); // hide the menu
|
this.setState({generalMenuPosition: null}); // hide the menu
|
||||||
};
|
};
|
||||||
|
|
||||||
private async saveNotifState(ev: ButtonEvent, newState: ALL_MESSAGES_LOUD | ALL_MESSAGES | MENTIONS_ONLY | MUTE) {
|
private async saveNotifState(ev: ButtonEvent, newState: ALL_MESSAGES_LOUD | ALL_MESSAGES | MENTIONS_ONLY | MUTE) {
|
||||||
|
@ -218,10 +228,7 @@ export default class RoomTile2 extends React.Component<IProps, IState> {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close the context menu
|
this.setState({notificationsMenuPosition: null}); // Close the context menu
|
||||||
this.setState({
|
|
||||||
notificationsMenuDisplayed: false,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private onClickAllNotifs = ev => this.saveNotifState(ev, ALL_MESSAGES);
|
private onClickAllNotifs = ev => this.saveNotifState(ev, ALL_MESSAGES);
|
||||||
|
@ -238,10 +245,9 @@ export default class RoomTile2 extends React.Component<IProps, IState> {
|
||||||
const state = getRoomNotifsState(this.props.room.roomId);
|
const state = getRoomNotifsState(this.props.room.roomId);
|
||||||
|
|
||||||
let contextMenu = null;
|
let contextMenu = null;
|
||||||
if (this.state.notificationsMenuDisplayed) {
|
if (this.state.notificationsMenuPosition) {
|
||||||
const elementRect = this.notificationsMenuButtonRef.current.getBoundingClientRect();
|
|
||||||
contextMenu = (
|
contextMenu = (
|
||||||
<ContextMenu {...contextMenuBelow(elementRect)} onFinished={this.onCloseNotificationsMenu}>
|
<ContextMenu {...contextMenuBelow(this.state.notificationsMenuPosition)} onFinished={this.onCloseNotificationsMenu}>
|
||||||
<div className="mx_IconizedContextMenu mx_IconizedContextMenu_compact mx_RoomTile2_contextMenu">
|
<div className="mx_IconizedContextMenu mx_IconizedContextMenu_compact mx_RoomTile2_contextMenu">
|
||||||
<div className="mx_IconizedContextMenu_optionList">
|
<div className="mx_IconizedContextMenu_optionList">
|
||||||
<NotifOption
|
<NotifOption
|
||||||
|
@ -289,9 +295,8 @@ export default class RoomTile2 extends React.Component<IProps, IState> {
|
||||||
<ContextMenuButton
|
<ContextMenuButton
|
||||||
className={classes}
|
className={classes}
|
||||||
onClick={this.onNotificationsMenuOpenClick}
|
onClick={this.onNotificationsMenuOpenClick}
|
||||||
inputRef={this.notificationsMenuButtonRef}
|
|
||||||
label={_t("Notification options")}
|
label={_t("Notification options")}
|
||||||
isExpanded={this.state.notificationsMenuDisplayed}
|
isExpanded={!!this.state.notificationsMenuPosition}
|
||||||
/>
|
/>
|
||||||
{contextMenu}
|
{contextMenu}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
|
@ -307,10 +312,9 @@ export default class RoomTile2 extends React.Component<IProps, IState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let contextMenu = null;
|
let contextMenu = null;
|
||||||
if (this.state.generalMenuDisplayed) {
|
if (this.state.generalMenuPosition) {
|
||||||
const elementRect = this.generalMenuButtonRef.current.getBoundingClientRect();
|
|
||||||
contextMenu = (
|
contextMenu = (
|
||||||
<ContextMenu {...contextMenuBelow(elementRect)} onFinished={this.onCloseGeneralMenu}>
|
<ContextMenu {...contextMenuBelow(this.state.generalMenuPosition)} onFinished={this.onCloseGeneralMenu}>
|
||||||
<div className="mx_IconizedContextMenu mx_IconizedContextMenu_compact mx_RoomTile2_contextMenu">
|
<div className="mx_IconizedContextMenu mx_IconizedContextMenu_compact mx_RoomTile2_contextMenu">
|
||||||
<div className="mx_IconizedContextMenu_optionList">
|
<div className="mx_IconizedContextMenu_optionList">
|
||||||
<AccessibleButton onClick={(e) => this.onTagRoom(e, DefaultTagID.Favourite)}>
|
<AccessibleButton onClick={(e) => this.onTagRoom(e, DefaultTagID.Favourite)}>
|
||||||
|
@ -338,9 +342,8 @@ export default class RoomTile2 extends React.Component<IProps, IState> {
|
||||||
<ContextMenuButton
|
<ContextMenuButton
|
||||||
className="mx_RoomTile2_menuButton"
|
className="mx_RoomTile2_menuButton"
|
||||||
onClick={this.onGeneralMenuOpenClick}
|
onClick={this.onGeneralMenuOpenClick}
|
||||||
inputRef={this.generalMenuButtonRef}
|
|
||||||
label={_t("Room options")}
|
label={_t("Room options")}
|
||||||
isExpanded={this.state.generalMenuDisplayed}
|
isExpanded={!!this.state.generalMenuPosition}
|
||||||
/>
|
/>
|
||||||
{contextMenu}
|
{contextMenu}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
|
@ -354,7 +357,7 @@ export default class RoomTile2 extends React.Component<IProps, IState> {
|
||||||
const classes = classNames({
|
const classes = classNames({
|
||||||
'mx_RoomTile2': true,
|
'mx_RoomTile2': true,
|
||||||
'mx_RoomTile2_selected': this.state.selected,
|
'mx_RoomTile2_selected': this.state.selected,
|
||||||
'mx_RoomTile2_hasMenuOpen': this.state.generalMenuDisplayed || this.state.notificationsMenuDisplayed,
|
'mx_RoomTile2_hasMenuOpen': !!(this.state.generalMenuPosition || this.state.notificationsMenuPosition),
|
||||||
'mx_RoomTile2_minimized': this.props.isMinimized,
|
'mx_RoomTile2_minimized': this.props.isMinimized,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -416,6 +419,7 @@ export default class RoomTile2 extends React.Component<IProps, IState> {
|
||||||
onMouseLeave={this.onTileMouseLeave}
|
onMouseLeave={this.onTileMouseLeave}
|
||||||
onClick={this.onTileClick}
|
onClick={this.onTileClick}
|
||||||
role="treeitem"
|
role="treeitem"
|
||||||
|
onContextMenu={this.onContextMenu}
|
||||||
>
|
>
|
||||||
<div className="mx_RoomTile2_avatarContainer">
|
<div className="mx_RoomTile2_avatarContainer">
|
||||||
<RoomAvatar room={this.props.room} width={avatarSize} height={avatarSize} />
|
<RoomAvatar room={this.props.room} width={avatarSize} height={avatarSize} />
|
||||||
|
|
Loading…
Reference in New Issue