diff --git a/res/css/views/rooms/_RoomList.scss b/res/css/views/rooms/_RoomList.scss
index 89ab85e146..d210e118a2 100644
--- a/res/css/views/rooms/_RoomList.scss
+++ b/res/css/views/rooms/_RoomList.scss
@@ -17,3 +17,10 @@ limitations under the License.
.mx_RoomList {
padding-right: 7px; // width of the scrollbar, to line things up
}
+
+.mx_RoomList_iconPlus::before {
+ mask-image: url('$(res)/img/element-icons/roomlist/plus.svg');
+}
+.mx_RoomList_iconExplore::before {
+ mask-image: url('$(res)/img/element-icons/roomlist/explore.svg');
+}
diff --git a/res/css/views/rooms/_RoomSublist.scss b/res/css/views/rooms/_RoomSublist.scss
index fe80dfca22..543940fb78 100644
--- a/res/css/views/rooms/_RoomSublist.scss
+++ b/res/css/views/rooms/_RoomSublist.scss
@@ -120,7 +120,7 @@ limitations under the License.
}
.mx_RoomSublist_auxButton::before {
- mask-image: url('$(res)/img/feather-customised/plus.svg');
+ mask-image: url('$(res)/img/element-icons/roomlist/plus.svg');
}
.mx_RoomSublist_menuButton::before {
diff --git a/res/img/element-icons/roomlist/explore.svg b/res/img/element-icons/roomlist/explore.svg
new file mode 100644
index 0000000000..3786ce1153
--- /dev/null
+++ b/res/img/element-icons/roomlist/explore.svg
@@ -0,0 +1,4 @@
+
diff --git a/res/img/element-icons/roomlist/plus.svg b/res/img/element-icons/roomlist/plus.svg
new file mode 100644
index 0000000000..f6d80ac7ef
--- /dev/null
+++ b/res/img/element-icons/roomlist/plus.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/components/views/rooms/RoomList.tsx b/src/components/views/rooms/RoomList.tsx
index 0d90c04e13..0d3bbb7f8b 100644
--- a/src/components/views/rooms/RoomList.tsx
+++ b/src/components/views/rooms/RoomList.tsx
@@ -43,6 +43,7 @@ import SettingsStore from "../../../settings/SettingsStore";
import CustomRoomTagStore from "../../../stores/CustomRoomTagStore";
import { arrayFastClone, arrayHasDiff } from "../../../utils/arrays";
import { objectShallowClone, objectWithOnly } from "../../../utils/objects";
+import { IconizedContextMenuOption, IconizedContextMenuOptionList } from "../context_menus/IconizedContextMenu";
interface IProps {
onKeyDown: (ev: React.KeyboardEvent) => void;
@@ -81,6 +82,7 @@ interface ITagAesthetics {
sectionLabelRaw?: string;
addRoomLabel?: string;
onAddRoom?: (dispatcher?: Dispatcher) => void;
+ addRoomContextMenu?: (onFinished: () => void) => React.ReactNode;
isInvite: boolean;
defaultHidden: boolean;
}
@@ -112,9 +114,30 @@ const TAG_AESTHETICS: {
sectionLabel: _td("Rooms"),
isInvite: false,
defaultHidden: false,
- addRoomLabel: _td("Create room"),
- onAddRoom: (dispatcher?: Dispatcher) => {
- (dispatcher || defaultDispatcher).dispatch({action: 'view_create_room'})
+ addRoomLabel: _td("Add room"),
+ addRoomContextMenu: (onFinished: () => void) => {
+ return
+ {
+ e.preventDefault();
+ e.stopPropagation();
+ onFinished();
+ defaultDispatcher.dispatch({action: "view_create_room"});
+ }}
+ />
+ {
+ e.preventDefault();
+ e.stopPropagation();
+ onFinished();
+ defaultDispatcher.fire(Action.ViewRoomDirectory);
+ }}
+ />
+ ;
},
},
[DefaultTagID.LowPriority]: {
@@ -324,6 +347,7 @@ export default class RoomList extends React.PureComponent {
label={aesthetics.sectionLabelRaw ? aesthetics.sectionLabelRaw : _t(aesthetics.sectionLabel)}
onAddRoom={aesthetics.onAddRoom}
addRoomLabel={aesthetics.addRoomLabel ? _t(aesthetics.addRoomLabel) : aesthetics.addRoomLabel}
+ addRoomContextMenu={aesthetics.addRoomContextMenu}
isMinimized={this.props.isMinimized}
onResize={this.props.onResize}
extraBadTilesThatShouldntExist={extraTiles}
diff --git a/src/components/views/rooms/RoomSublist.tsx b/src/components/views/rooms/RoomSublist.tsx
index b2337c8c22..1e7ba3f77a 100644
--- a/src/components/views/rooms/RoomSublist.tsx
+++ b/src/components/views/rooms/RoomSublist.tsx
@@ -50,6 +50,7 @@ import { arrayFastClone, arrayHasOrderChange } from "../../../utils/arrays";
import { objectExcluding, objectHasDiff } from "../../../utils/objects";
import TemporaryTile from "./TemporaryTile";
import { ListNotificationState } from "../../../stores/notifications/ListNotificationState";
+import IconizedContextMenu from "../context_menus/IconizedContextMenu";
const SHOW_N_BUTTON_HEIGHT = 28; // As defined by CSS
const RESIZE_HANDLE_HEIGHT = 4; // As defined by CSS
@@ -65,6 +66,7 @@ interface IProps {
startAsHidden: boolean;
label: string;
onAddRoom?: () => void;
+ addRoomContextMenu?: (onFinished: () => void) => React.ReactNode;
addRoomLabel: string;
isMinimized: boolean;
tagId: TagID;
@@ -87,6 +89,7 @@ type PartialDOMRect = Pick;
interface IState {
contextMenuPosition: PartialDOMRect;
+ addRoomContextMenuPosition: PartialDOMRect;
isResizing: boolean;
isExpanded: boolean; // used for the for expand of the sublist when the room list is being filtered
height: number;
@@ -112,6 +115,7 @@ export default class RoomSublist extends React.Component {
this.notificationState = RoomNotificationStateStore.instance.getListState(this.props.tagId);
this.state = {
contextMenuPosition: null,
+ addRoomContextMenuPosition: null,
isResizing: false,
isExpanded: this.isBeingFiltered ? this.isBeingFiltered : !this.layout.isCollapsed,
height: 0, // to be fixed in a moment, we need `rooms` to calculate this.
@@ -376,10 +380,21 @@ export default class RoomSublist extends React.Component {
});
};
+ private onAddRoomContextMenu = (ev: React.MouseEvent) => {
+ ev.preventDefault();
+ ev.stopPropagation();
+ const target = ev.target as HTMLButtonElement;
+ this.setState({addRoomContextMenuPosition: target.getBoundingClientRect()});
+ };
+
private onCloseMenu = () => {
this.setState({contextMenuPosition: null});
};
+ private onCloseAddRoomMenu = () => {
+ this.setState({addRoomContextMenuPosition: null});
+ };
+
private onUnreadFirstChanged = async () => {
const isUnreadFirst = RoomListStore.instance.getListOrder(this.props.tagId) === ListAlgorithm.Importance;
const newAlgorithm = isUnreadFirst ? ListAlgorithm.Natural : ListAlgorithm.Importance;
@@ -594,6 +609,18 @@ export default class RoomSublist extends React.Component {
);
+ } else if (this.state.addRoomContextMenuPosition) {
+ contextMenu = (
+
+ {this.props.addRoomContextMenu(this.onCloseAddRoomMenu)}
+
+ );
}
return (
@@ -637,9 +664,21 @@ export default class RoomSublist extends React.Component {
tabIndex={tabIndex}
onClick={this.onAddRoom}
className="mx_RoomSublist_auxButton"
+ tooltipClassName="mx_RoomSublist_addRoomTooltip"
aria-label={this.props.addRoomLabel || _t("Add room")}
title={this.props.addRoomLabel}
- tooltipClassName={"mx_RoomSublist_addRoomTooltip"}
+ />
+ );
+ } else if (this.props.addRoomContextMenu) {
+ addRoomButton = (
+
);
}
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json
index b636b5470e..b311a0cd5b 100644
--- a/src/i18n/strings/en_EN.json
+++ b/src/i18n/strings/en_EN.json
@@ -1111,7 +1111,9 @@
"People": "People",
"Start chat": "Start chat",
"Rooms": "Rooms",
- "Create room": "Create room",
+ "Add room": "Add room",
+ "Create new room": "Create new room",
+ "Explore public rooms": "Explore public rooms",
"Low priority": "Low priority",
"System Alerts": "System Alerts",
"Historical": "Historical",
@@ -1168,7 +1170,6 @@
"List options": "List options",
"Jump to first unread room.": "Jump to first unread room.",
"Jump to first invite.": "Jump to first invite.",
- "Add room": "Add room",
"Show %(count)s more|other": "Show %(count)s more",
"Show %(count)s more|one": "Show %(count)s more",
"Use default": "Use default",