diff --git a/src/component-index.js b/src/component-index.js
index 4e6eefb6fb..2b67aa15e5 100644
--- a/src/component-index.js
+++ b/src/component-index.js
@@ -30,12 +30,12 @@ import structures$BottomLeftMenu from './components/structures/BottomLeftMenu';
structures$BottomLeftMenu && (module.exports.components['structures.BottomLeftMenu'] = structures$BottomLeftMenu);
import structures$CompatibilityPage from './components/structures/CompatibilityPage';
structures$CompatibilityPage && (module.exports.components['structures.CompatibilityPage'] = structures$CompatibilityPage);
+import structures$HomePage from './components/structures/HomePage';
+structures$HomePage && (module.exports.components['structures.HomePage'] = structures$HomePage);
import structures$LeftPanel from './components/structures/LeftPanel';
structures$LeftPanel && (module.exports.components['structures.LeftPanel'] = structures$LeftPanel);
import structures$RightPanel from './components/structures/RightPanel';
structures$RightPanel && (module.exports.components['structures.RightPanel'] = structures$RightPanel);
-import structures$HomePage from './components/structures/HomePage';
-structures$HomePage && (module.exports.components['structures.HomePage'] = structures$HomePage);
import structures$RoomDirectory from './components/structures/RoomDirectory';
structures$RoomDirectory && (module.exports.components['structures.RoomDirectory'] = structures$RoomDirectory);
import structures$RoomSubList from './components/structures/RoomSubList';
@@ -46,10 +46,8 @@ import structures$ViewSource from './components/structures/ViewSource';
structures$ViewSource && (module.exports.components['structures.ViewSource'] = structures$ViewSource);
import views$context_menus$MessageContextMenu from './components/views/context_menus/MessageContextMenu';
views$context_menus$MessageContextMenu && (module.exports.components['views.context_menus.MessageContextMenu'] = views$context_menus$MessageContextMenu);
-import views$context_menus$NotificationStateContextMenu from './components/views/context_menus/NotificationStateContextMenu';
-views$context_menus$NotificationStateContextMenu && (module.exports.components['views.context_menus.NotificationStateContextMenu'] = views$context_menus$NotificationStateContextMenu);
-import views$context_menus$RoomTagContextMenu from './components/views/context_menus/RoomTagContextMenu';
-views$context_menus$RoomTagContextMenu && (module.exports.components['views.context_menus.RoomTagContextMenu'] = views$context_menus$RoomTagContextMenu);
+import views$context_menus$RoomTileContextMenu from './components/views/context_menus/RoomTileContextMenu';
+views$context_menus$RoomTileContextMenu && (module.exports.components['views.context_menus.RoomTileContextMenu'] = views$context_menus$RoomTileContextMenu);
import views$dialogs$BugReportDialog from './components/views/dialogs/BugReportDialog';
views$dialogs$BugReportDialog && (module.exports.components['views.dialogs.BugReportDialog'] = views$dialogs$BugReportDialog);
import views$dialogs$ChangelogDialog from './components/views/dialogs/ChangelogDialog';
diff --git a/src/components/views/context_menus/NotificationStateContextMenu.js b/src/components/views/context_menus/NotificationStateContextMenu.js
deleted file mode 100644
index d4b40d1732..0000000000
--- a/src/components/views/context_menus/NotificationStateContextMenu.js
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
-Copyright 2015, 2016 OpenMarket Ltd
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-'use strict';
-
-var q = require("q");
-var React = require('react');
-var classNames = require('classnames');
-var RoomNotifs = require('matrix-react-sdk/lib/RoomNotifs');
-var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
-
-module.exports = React.createClass({
- displayName: 'NotificationStateContextMenu',
-
- propTypes: {
- room: React.PropTypes.object.isRequired,
- /* callback called when the menu is dismissed */
- onFinished: React.PropTypes.func,
- },
-
- getInitialState() {
- return {
- roomNotifState: RoomNotifs.getRoomNotifsState(this.props.room.roomId),
- }
- },
-
- componentWillMount: function() {
- this._unmounted = false;
- },
-
- componentWillUnmount: function() {
- this._unmounted = true;
- },
-
- _save: function(newState) {
- const oldState = this.state.roomNotifState;
- const roomId = this.props.room.roomId;
- var cli = MatrixClientPeg.get();
-
- if (cli.isGuest()) return;
-
- this.setState({
- roomNotifState: newState,
- });
- RoomNotifs.setRoomNotifsState(this.props.room.roomId, newState).done(() => {
- // delay slightly so that the user can see their state change
- // before closing the menu
- return q.delay(500).then(() => {
- if (this._unmounted) return;
- // Close the context menu
- if (this.props.onFinished) {
- this.props.onFinished();
- };
- });
- }, (error) => {
- // TODO: some form of error notification to the user
- // to inform them that their state change failed.
- // For now we at least set the state back
- if (this._unmounted) return;
- this.setState({
- roomNotifState: oldState,
- });
- });
- },
-
- _onClickAlertMe: function() {
- this._save(RoomNotifs.ALL_MESSAGES_LOUD);
- },
-
- _onClickAllNotifs: function() {
- this._save(RoomNotifs.ALL_MESSAGES);
- },
-
- _onClickMentions: function() {
- this._save(RoomNotifs.MENTIONS_ONLY);
- },
-
- _onClickMute: function() {
- this._save(RoomNotifs.MUTE);
- },
-
- render: function() {
- var alertMeClasses = classNames({
- 'mx_NotificationStateContextMenu_field': true,
- 'mx_NotificationStateContextMenu_fieldSet': this.state.roomNotifState == RoomNotifs.ALL_MESSAGES_LOUD,
- });
-
- var allNotifsClasses = classNames({
- 'mx_NotificationStateContextMenu_field': true,
- 'mx_NotificationStateContextMenu_fieldSet': this.state.roomNotifState == RoomNotifs.ALL_MESSAGES,
- });
-
- var mentionsClasses = classNames({
- 'mx_NotificationStateContextMenu_field': true,
- 'mx_NotificationStateContextMenu_fieldSet': this.state.roomNotifState == RoomNotifs.MENTIONS_ONLY,
- });
-
- var muteNotifsClasses = classNames({
- 'mx_NotificationStateContextMenu_field': true,
- 'mx_NotificationStateContextMenu_fieldSet': this.state.roomNotifState == RoomNotifs.MUTE,
- });
-
- return (
-
-
-
-
-
-
-
- All messages (loud)
-
-
-
-
- All messages
-
-
-
-
- Mentions only
-
-
-
-
- Mute
-
-
- );
- }
-});
diff --git a/src/components/views/context_menus/RoomTagContextMenu.js b/src/components/views/context_menus/RoomTagContextMenu.js
deleted file mode 100644
index 8a44051f4f..0000000000
--- a/src/components/views/context_menus/RoomTagContextMenu.js
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
-Copyright 2015, 2016 OpenMarket Ltd
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-'use strict';
-
-import q from 'q';
-import React from 'react';
-import classNames from 'classnames';
-import sdk from 'matrix-react-sdk';
-import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg';
-import dis from 'matrix-react-sdk/lib/dispatcher';
-import DMRoomMap from 'matrix-react-sdk/lib/utils/DMRoomMap';
-import Rooms from 'matrix-react-sdk/lib/Rooms';
-import Modal from 'matrix-react-sdk/lib/Modal';
-
-module.exports = React.createClass({
- displayName: 'RoomTagContextMenu',
-
- propTypes: {
- room: React.PropTypes.object.isRequired,
- /* callback called when the menu is dismissed */
- onFinished: React.PropTypes.func,
- },
-
- getInitialState: function() {
- const dmRoomMap = new DMRoomMap(MatrixClientPeg.get());
- return {
- isFavourite: this.props.room.tags.hasOwnProperty("m.favourite"),
- isLowPriority: this.props.room.tags.hasOwnProperty("m.lowpriority"),
- isDirectMessage: Boolean(dmRoomMap.getUserIdForRoomId(this.props.room.roomId)),
- };
- },
-
- _toggleTag: function(tagNameOn, tagNameOff) {
- var self = this;
- const roomId = this.props.room.roomId;
- var cli = MatrixClientPeg.get();
- if (!cli.isGuest()) {
- q.delay(500).then(function() {
- if (tagNameOff !== null && tagNameOff !== undefined) {
- cli.deleteRoomTag(roomId, tagNameOff).finally(function() {
- // Close the context menu
- if (self.props.onFinished) {
- self.props.onFinished();
- };
- }).fail(function(err) {
- var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
- Modal.createDialog(ErrorDialog, {
- title: "Failed to remove tag " + tagNameOff + " from room",
- description: err.toString()
- });
- });
- }
-
- if (tagNameOn !== null && tagNameOn !== undefined) {
- // If the tag ordering meta data is required, it is added by
- // the RoomSubList when it sorts its rooms
- cli.setRoomTag(roomId, tagNameOn, {}).finally(function() {
- // Close the context menu
- if (self.props.onFinished) {
- self.props.onFinished();
- };
- }).fail(function(err) {
- var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
- Modal.createDialog(ErrorDialog, {
- title: "Failed to add tag " + tagNameOn + " to room",
- description: err.toString()
- });
- });
- }
- });
- }
- },
-
- _onClickFavourite: function() {
- // Tag room as 'Favourite'
- if (!this.state.isFavourite && this.state.isLowPriority) {
- this.setState({
- isFavourite: true,
- isLowPriority: false,
- });
- this._toggleTag("m.favourite", "m.lowpriority");
- } else if (this.state.isFavourite) {
- this.setState({isFavourite: false});
- this._toggleTag(null, "m.favourite");
- } else if (!this.state.isFavourite) {
- this.setState({isFavourite: true});
- this._toggleTag("m.favourite");
- }
- },
-
- _onClickLowPriority: function() {
- // Tag room as 'Low Priority'
- if (!this.state.isLowPriority && this.state.isFavourite) {
- this.setState({
- isFavourite: false,
- isLowPriority: true,
- });
- this._toggleTag("m.lowpriority", "m.favourite");
- } else if (this.state.isLowPriority) {
- this.setState({isLowPriority: false});
- this._toggleTag(null, "m.lowpriority");
- } else if (!this.state.isLowPriority) {
- this.setState({isLowPriority: true});
- this._toggleTag("m.lowpriority");
- }
- },
-
- _onClickDM: function() {
- const newIsDirectMessage = !this.state.isDirectMessage;
- this.setState({
- isDirectMessage: newIsDirectMessage,
- });
-
- if (MatrixClientPeg.get().isGuest()) return;
-
- let newTarget;
- if (newIsDirectMessage) {
- const guessedTarget = Rooms.guessDMRoomTarget(
- this.props.room,
- this.props.room.getMember(MatrixClientPeg.get().credentials.userId),
- );
- newTarget = guessedTarget.userId;
- } else {
- newTarget = null;
- }
-
- // give some time for the user to see the icon change first, since
- // this will hide the context menu once it completes
- q.delay(500).done(() => {
- return Rooms.setDMRoom(this.props.room.roomId, newTarget).finally(() => {
- // Close the context menu
- if (this.props.onFinished) {
- this.props.onFinished();
- };
- }, (err) => {
- var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
- Modal.createDialog(ErrorDialog, {
- title: "Failed to set Direct Message status of room",
- description: err.toString()
- });
- });
- });
- },
-
- _onClickLeave: function() {
- // Leave room
- dis.dispatch({
- action: 'leave_room',
- room_id: this.props.room.roomId,
- });
-
- // Close the context menu
- if (this.props.onFinished) {
- this.props.onFinished();
- };
- },
-
- _onClickForget: function() {
- // FIXME: duplicated with RoomSettings (and dead code in RoomView)
- MatrixClientPeg.get().forget(this.props.room.roomId).done(function() {
- dis.dispatch({ action: 'view_next_room' });
- }, function(err) {
- var errCode = err.errcode || "unknown error code";
- var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
- Modal.createDialog(ErrorDialog, {
- title: "Error",
- description: `Failed to forget room (${errCode})`
- });
- });
-
- // Close the context menu
- if (this.props.onFinished) {
- this.props.onFinished();
- };
- },
-
- render: function() {
- const myUserId = MatrixClientPeg.get().credentials.userId;
- const myMember = this.props.room.getMember(myUserId);
-
- const favouriteClasses = classNames({
- 'mx_RoomTagContextMenu_field': true,
- 'mx_RoomTagContextMenu_fieldSet': this.state.isFavourite,
- 'mx_RoomTagContextMenu_fieldDisabled': false,
- });
-
- const lowPriorityClasses = classNames({
- 'mx_RoomTagContextMenu_field': true,
- 'mx_RoomTagContextMenu_fieldSet': this.state.isLowPriority,
- 'mx_RoomTagContextMenu_fieldDisabled': false,
- });
-
- const leaveClasses = classNames({
- 'mx_RoomTagContextMenu_field': true,
- 'mx_RoomTagContextMenu_fieldSet': false,
- 'mx_RoomTagContextMenu_fieldDisabled': false,
- });
-
- const dmClasses = classNames({
- 'mx_RoomTagContextMenu_field': true,
- 'mx_RoomTagContextMenu_fieldSet': this.state.isDirectMessage,
- 'mx_RoomTagContextMenu_fieldDisabled': false,
- });
-
- if (myMember && (myMember.membership === "leave" || myMember.membership === "ban")) {
- return (
-
-
-
- Forget
-
-
- );
- }
-
- return (
-
-
-
-
- Favourite
-
-
-
-
- Low Priority
-
-
-
-
- Direct Chat
-
-
-
-
- Leave
-
-
- );
- }
-});
diff --git a/src/components/views/context_menus/RoomTileContextMenu.js b/src/components/views/context_menus/RoomTileContextMenu.js
new file mode 100644
index 0000000000..6430cd377c
--- /dev/null
+++ b/src/components/views/context_menus/RoomTileContextMenu.js
@@ -0,0 +1,404 @@
+/*
+Copyright 2015, 2016 OpenMarket Ltd
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+'use strict';
+
+import q from 'q';
+import React from 'react';
+import classNames from 'classnames';
+import sdk from 'matrix-react-sdk';
+import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg';
+import dis from 'matrix-react-sdk/lib/dispatcher';
+import DMRoomMap from 'matrix-react-sdk/lib/utils/DMRoomMap';
+import Rooms from 'matrix-react-sdk/lib/Rooms';
+import * as RoomNotifs from 'matrix-react-sdk/lib/RoomNotifs';
+import Modal from 'matrix-react-sdk/lib/Modal';
+
+module.exports = React.createClass({
+ displayName: 'RoomTileContextMenu',
+
+ propTypes: {
+ room: React.PropTypes.object.isRequired,
+ /* callback called when the menu is dismissed */
+ onFinished: React.PropTypes.func,
+ },
+
+ getInitialState() {
+ const dmRoomMap = new DMRoomMap(MatrixClientPeg.get());
+ return {
+ roomNotifState: RoomNotifs.getRoomNotifsState(this.props.room.roomId),
+ isFavourite: this.props.room.tags.hasOwnProperty("m.favourite"),
+ isLowPriority: this.props.room.tags.hasOwnProperty("m.lowpriority"),
+ isDirectMessage: Boolean(dmRoomMap.getUserIdForRoomId(this.props.room.roomId)),
+ }
+ },
+
+ componentWillMount: function() {
+ this._unmounted = false;
+ },
+
+ componentWillUnmount: function() {
+ this._unmounted = true;
+ },
+
+ _toggleTag: function(tagNameOn, tagNameOff) {
+ var self = this;
+ const roomId = this.props.room.roomId;
+ var cli = MatrixClientPeg.get();
+ if (!cli.isGuest()) {
+ q.delay(500).then(function() {
+ if (tagNameOff !== null && tagNameOff !== undefined) {
+ cli.deleteRoomTag(roomId, tagNameOff).finally(function() {
+ // Close the context menu
+ if (self.props.onFinished) {
+ self.props.onFinished();
+ };
+ }).fail(function(err) {
+ var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
+ Modal.createDialog(ErrorDialog, {
+ title: "Failed to remove tag " + tagNameOff + " from room",
+ description: err.toString()
+ });
+ });
+ }
+
+ if (tagNameOn !== null && tagNameOn !== undefined) {
+ // If the tag ordering meta data is required, it is added by
+ // the RoomSubList when it sorts its rooms
+ cli.setRoomTag(roomId, tagNameOn, {}).finally(function() {
+ // Close the context menu
+ if (self.props.onFinished) {
+ self.props.onFinished();
+ };
+ }).fail(function(err) {
+ var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
+ Modal.createDialog(ErrorDialog, {
+ title: "Failed to add tag " + tagNameOn + " to room",
+ description: err.toString()
+ });
+ });
+ }
+ });
+ }
+ },
+
+ _onClickFavourite: function() {
+ // Tag room as 'Favourite'
+ if (!this.state.isFavourite && this.state.isLowPriority) {
+ this.setState({
+ isFavourite: true,
+ isLowPriority: false,
+ });
+ this._toggleTag("m.favourite", "m.lowpriority");
+ } else if (this.state.isFavourite) {
+ this.setState({isFavourite: false});
+ this._toggleTag(null, "m.favourite");
+ } else if (!this.state.isFavourite) {
+ this.setState({isFavourite: true});
+ this._toggleTag("m.favourite");
+ }
+ },
+
+ _onClickLowPriority: function() {
+ // Tag room as 'Low Priority'
+ if (!this.state.isLowPriority && this.state.isFavourite) {
+ this.setState({
+ isFavourite: false,
+ isLowPriority: true,
+ });
+ this._toggleTag("m.lowpriority", "m.favourite");
+ } else if (this.state.isLowPriority) {
+ this.setState({isLowPriority: false});
+ this._toggleTag(null, "m.lowpriority");
+ } else if (!this.state.isLowPriority) {
+ this.setState({isLowPriority: true});
+ this._toggleTag("m.lowpriority");
+ }
+ },
+
+ _onClickDM: function() {
+ const newIsDirectMessage = !this.state.isDirectMessage;
+ this.setState({
+ isDirectMessage: newIsDirectMessage,
+ });
+
+ if (MatrixClientPeg.get().isGuest()) return;
+
+ let newTarget;
+ if (newIsDirectMessage) {
+ const guessedTarget = Rooms.guessDMRoomTarget(
+ this.props.room,
+ this.props.room.getMember(MatrixClientPeg.get().credentials.userId),
+ );
+ newTarget = guessedTarget.userId;
+ } else {
+ newTarget = null;
+ }
+
+ // give some time for the user to see the icon change first, since
+ // this will hide the context menu once it completes
+ q.delay(500).done(() => {
+ return Rooms.setDMRoom(this.props.room.roomId, newTarget).finally(() => {
+ // Close the context menu
+ if (this.props.onFinished) {
+ this.props.onFinished();
+ };
+ }, (err) => {
+ var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
+ Modal.createDialog(ErrorDialog, {
+ title: "Failed to set Direct Message status of room",
+ description: err.toString()
+ });
+ });
+ });
+ },
+
+ _onClickLeave: function() {
+ // Leave room
+ dis.dispatch({
+ action: 'leave_room',
+ room_id: this.props.room.roomId,
+ });
+
+ // Close the context menu
+ if (this.props.onFinished) {
+ this.props.onFinished();
+ };
+ },
+
+ _onClickReject: function() {
+ dis.dispatch({
+ action: 'reject_invite',
+ room_id: this.props.room.roomId,
+ });
+
+ // Close the context menu
+ if (this.props.onFinished) {
+ this.props.onFinished();
+ };
+ },
+
+ _onClickForget: function() {
+ // FIXME: duplicated with RoomSettings (and dead code in RoomView)
+ MatrixClientPeg.get().forget(this.props.room.roomId).done(function() {
+ dis.dispatch({ action: 'view_next_room' });
+ }, function(err) {
+ var errCode = err.errcode || "unknown error code";
+ var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
+ Modal.createDialog(ErrorDialog, {
+ title: "Error",
+ description: `Failed to forget room (${errCode})`
+ });
+ });
+
+ // Close the context menu
+ if (this.props.onFinished) {
+ this.props.onFinished();
+ };
+ },
+
+ _saveNotifState: function(newState) {
+ const oldState = this.state.roomNotifState;
+ const roomId = this.props.room.roomId;
+ var cli = MatrixClientPeg.get();
+
+ if (cli.isGuest()) return;
+
+ this.setState({
+ roomNotifState: newState,
+ });
+ RoomNotifs.setRoomNotifsState(this.props.room.roomId, newState).done(() => {
+ // delay slightly so that the user can see their state change
+ // before closing the menu
+ return q.delay(500).then(() => {
+ if (this._unmounted) return;
+ // Close the context menu
+ if (this.props.onFinished) {
+ this.props.onFinished();
+ };
+ });
+ }, (error) => {
+ // TODO: some form of error notification to the user
+ // to inform them that their state change failed.
+ // For now we at least set the state back
+ if (this._unmounted) return;
+ this.setState({
+ roomNotifState: oldState,
+ });
+ });
+ },
+
+ _onClickAlertMe: function() {
+ this._saveNotifState(RoomNotifs.ALL_MESSAGES_LOUD);
+ },
+
+ _onClickAllNotifs: function() {
+ this._saveNotifState(RoomNotifs.ALL_MESSAGES);
+ },
+
+ _onClickMentions: function() {
+ this._saveNotifState(RoomNotifs.MENTIONS_ONLY);
+ },
+
+ _onClickMute: function() {
+ this._saveNotifState(RoomNotifs.MUTE);
+ },
+
+ _renderNotifMenu: function() {
+ var alertMeClasses = classNames({
+ 'mx_RoomTileContextMenu_notif_field': true,
+ 'mx_RoomTileContextMenu_notif_fieldSet': this.state.roomNotifState == RoomNotifs.ALL_MESSAGES_LOUD,
+ });
+
+ var allNotifsClasses = classNames({
+ 'mx_RoomTileContextMenu_notif_field': true,
+ 'mx_RoomTileContextMenu_notif_fieldSet': this.state.roomNotifState == RoomNotifs.ALL_MESSAGES,
+ });
+
+ var mentionsClasses = classNames({
+ 'mx_RoomTileContextMenu_notif_field': true,
+ 'mx_RoomTileContextMenu_notif_fieldSet': this.state.roomNotifState == RoomNotifs.MENTIONS_ONLY,
+ });
+
+ var muteNotifsClasses = classNames({
+ 'mx_RoomTileContextMenu_notif_field': true,
+ 'mx_RoomTileContextMenu_notif_fieldSet': this.state.roomNotifState == RoomNotifs.MUTE,
+ });
+
+ return (
+
+
+
+
+
+
+
+ All messages (loud)
+
+
+
+
+ All messages
+
+
+
+
+ Mentions only
+
+
+
+
+ Mute
+
+
+ );
+ },
+
+ _renderLeaveMenu: function(membership) {
+ if (!membership) {
+ return null;
+ }
+
+ let leaveClickHandler = null;
+ let leaveText = null;
+
+ switch (membership) {
+ case "join":
+ leaveClickHandler = this._onClickLeave;
+ leaveText = "Leave";
+ break;
+ case "leave":
+ case "ban":
+ leaveClickHandler = this._onClickForget;
+ leaveText = "Forget";
+ break;
+ case "invite":
+ leaveClickHandler = this._onClickReject;
+ leaveText = "Reject";
+ break;
+ }
+
+ return (
+
+
+
+ { leaveText }
+
+
+ );
+ },
+
+ _renderRoomTagMenu: function() {
+ const favouriteClasses = classNames({
+ 'mx_RoomTileContextMenu_tag_field': true,
+ 'mx_RoomTileContextMenu_tag_fieldSet': this.state.isFavourite,
+ 'mx_RoomTileContextMenu_tag_fieldDisabled': false,
+ });
+
+ const lowPriorityClasses = classNames({
+ 'mx_RoomTileContextMenu_tag_field': true,
+ 'mx_RoomTileContextMenu_tag_fieldSet': this.state.isLowPriority,
+ 'mx_RoomTileContextMenu_tag_fieldDisabled': false,
+ });
+
+ const dmClasses = classNames({
+ 'mx_RoomTileContextMenu_tag_field': true,
+ 'mx_RoomTileContextMenu_tag_fieldSet': this.state.isDirectMessage,
+ 'mx_RoomTileContextMenu_tag_fieldDisabled': false,
+ });
+
+ return (
+
+
+
+
+ Favourite
+
+
+
+
+ Low Priority
+
+
+
+
+ Direct Chat
+
+
+ );
+ },
+
+ render: function() {
+ const myMember = this.props.room.getMember(
+ MatrixClientPeg.get().credentials.userId
+ );
+
+ // Can't set notif level or tags on non-join rooms
+ if (myMember.membership !== 'join') {
+ return this._renderLeaveMenu(myMember.membership);
+ }
+
+ return (
+
+ { this._renderNotifMenu() }
+
+ { this._renderLeaveMenu(myMember.membership) }
+
+ { this._renderRoomTagMenu() }
+
+ );
+ }
+});
diff --git a/src/skins/vector/css/_components.scss b/src/skins/vector/css/_components.scss
index 6a1fefb049..650cf3d502 100644
--- a/src/skins/vector/css/_components.scss
+++ b/src/skins/vector/css/_components.scss
@@ -61,8 +61,7 @@
@import "./vector-web/structures/_RoomSubList.scss";
@import "./vector-web/structures/_ViewSource.scss";
@import "./vector-web/views/context_menus/_MessageContextMenu.scss";
-@import "./vector-web/views/context_menus/_NotificationStateContextMenu.scss";
-@import "./vector-web/views/context_menus/_RoomTagContextMenu.scss";
+@import "./vector-web/views/context_menus/_RoomTileContextMenu.scss";
@import "./vector-web/views/dialogs/_ChangelogDialog.scss";
@import "./vector-web/views/directory/_NetworkDropdown.scss";
@import "./vector-web/views/elements/_ImageView.scss";
diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomTile.scss b/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomTile.scss
index 34cc21d4a3..08efa145e3 100644
--- a/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomTile.scss
+++ b/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomTile.scss
@@ -59,41 +59,6 @@ limitations under the License.
z-index: 2;
}
-.mx_RoomTile:hover .mx_RoomTile_avatar_container:before,
-.mx_RoomTile_avatar_container.mx_RoomTile_avatar_roomTagMenu:before {
- display: block;
- position: absolute;
- content: "";
- border-radius: 40px;
- background-image: url("../../img/icons_ellipsis.svg");
- background-size: 25px;
- width: 24px;
- height: 24px;
- z-index: 4;
-}
-
-.mx_RoomTile:hover .mx_RoomTile_avatar_container:after,
-.mx_RoomTile_avatar_container.mx_RoomTile_avatar_roomTagMenu:after {
- display: block;
- position: absolute;
- content: "";
- border-radius: 40px;
- background: $primary-fg-color;
- bottom: 0;
- width: 24px;
- height: 24px;
- opacity: 0.6;
- z-index: 1;
-}
-
-.collapsed .mx_RoomTile:hover .mx_RoomTile_avatar_container:before {
- display: none;
-}
-
-.collapsed .mx_RoomTile:hover .mx_RoomTile_avatar_container:after {
- display: none;
-}
-
.mx_RoomTile_name {
display: inline-block;
position: relative;
@@ -164,13 +129,13 @@ limitations under the License.
}
.mx_RoomTile .mx_RoomTile_badge.mx_RoomTile_badgeButton,
-.mx_RoomTile.mx_RoomTile_notificationStateMenu .mx_RoomTile_badge {
+.mx_RoomTile.mx_RoomTile_menuDisplayed .mx_RoomTile_badge {
letter-spacing: 0.1em;
opacity: 1;
}
.mx_RoomTile.mx_RoomTile_noBadges .mx_RoomTile_badge.mx_RoomTile_badgeButton,
-.mx_RoomTile.mx_RoomTile_notificationStateMenu.mx_RoomTile_noBadges .mx_RoomTile_badge {
+.mx_RoomTile.mx_RoomTile_menuDisplayed.mx_RoomTile_noBadges .mx_RoomTile_badge {
background-color: $neutral-badge-color;
}
diff --git a/src/skins/vector/css/vector-web/views/context_menus/_NotificationStateContextMenu.scss b/src/skins/vector/css/vector-web/views/context_menus/_NotificationStateContextMenu.scss
deleted file mode 100644
index 1f0685264b..0000000000
--- a/src/skins/vector/css/vector-web/views/context_menus/_NotificationStateContextMenu.scss
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
-Copyright 2015, 2016 OpenMarket Ltd
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-.mx_NotificationStateContextMenu_picker {
- position: absolute;
- top: 16px;
- left: 5px;
-}
-
-.mx_NotificationStateContextMenu_field {
- padding-top: 4px;
- padding-right: 6px;
- padding-bottom: 10px;
- padding-left: 8px; /* 20px */
- cursor: pointer;
- white-space: nowrap;
- display: flex;
- align-items: center;
-}
-
-.mx_NotificationStateContextMenu_field.mx_NotificationStateContextMenu_fieldSet {
- font-weight: bold;
-}
-
-.mx_NotificationStateContextMenu_field.mx_NotificationStateContextMenu_fieldDisabled {
- color: rgba(0, 0, 0, 0.2);
-}
-
-.mx_NotificationStateContextMenu_icon {
- padding-right: 4px;
- padding-left: 4px;
-}
-
-.mx_NotificationStateContextMenu_activeIcon {
- display: inline-block;
- opacity: 0;
- position: relative;
- left: -5px;
-}
-
-.mx_NotificationStateContextMenu_fieldSet .mx_NotificationStateContextMenu_activeIcon {
- opacity: 1;
-}
diff --git a/src/skins/vector/css/vector-web/views/context_menus/_RoomTagContextMenu.scss b/src/skins/vector/css/vector-web/views/context_menus/_RoomTagContextMenu.scss
deleted file mode 100644
index 16a3ab79b1..0000000000
--- a/src/skins/vector/css/vector-web/views/context_menus/_RoomTagContextMenu.scss
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
-Copyright 2015, 2016 OpenMarket Ltd
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-.mx_RoomTagContextMenu_field {
- padding-top: 8px;
- padding-right: 20px;
- padding-bottom: 8px;
- cursor: pointer;
- white-space: nowrap;
- display: flex;
- align-items: center;
- line-height: 16px;
-}
-
-.mx_RoomTagContextMenu_field:first-child {
- padding-top: 4px;
-}
-
-.mx_RoomTagContextMenu_field:last-child {
- padding-bottom: 4px;
- color: $warning-color;
-}
-
-.mx_RoomTagContextMenu_field.mx_RoomTagContextMenu_fieldSet {
- font-weight: bold;
-}
-
-.mx_RoomTagContextMenu_field.mx_RoomTagContextMenu_fieldSet .mx_RoomTagContextMenu_icon {
- display: none;
-}
-
-.mx_RoomTagContextMenu_field.mx_RoomTagContextMenu_fieldSet .mx_RoomTagContextMenu_icon_set {
- display: inline-block;
-}
-
-.mx_RoomTagContextMenu_field.mx_RoomTagContextMenu_fieldDisabled {
- color: rgba(0, 0, 0, 0.2);
-}
-
-.mx_RoomTagContextMenu_icon {
- padding-right: 8px;
- padding-left: 4px;
- display: inline-block
-}
-
-.mx_RoomTagContextMenu_icon_set {
- padding-right: 8px;
- padding-left: 4px;
- display: none;
-}
-
-.mx_RoomTagContextMenu_separator {
- margin-top: 0;
- margin-bottom: 0;
- border-bottom-style: none;
- border-left-style: none;
- border-right-style: none;
- border-top-style: solid;
- border-top-width: 1px;
- border-color: $menu-border-color;
-}
-
-.mx_RoomTagContextMenu_fieldSet .mx_RoomTagContextMenu_icon {
- /* Something to indicate that the icon is the set tag */
-}
diff --git a/src/skins/vector/css/vector-web/views/context_menus/_RoomTileContextMenu.scss b/src/skins/vector/css/vector-web/views/context_menus/_RoomTileContextMenu.scss
new file mode 100644
index 0000000000..598f8ac249
--- /dev/null
+++ b/src/skins/vector/css/vector-web/views/context_menus/_RoomTileContextMenu.scss
@@ -0,0 +1,114 @@
+/*
+Copyright 2015, 2016 OpenMarket Ltd
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+.mx_RoomTileContextMenu_tag_field, .mx_RoomTileContextMenu_leave {
+ padding-top: 8px;
+ padding-right: 20px;
+ padding-bottom: 8px;
+ cursor: pointer;
+ white-space: nowrap;
+ display: flex;
+ align-items: center;
+ line-height: 16px;
+}
+
+.mx_RoomTileContextMenu_tag_field.mx_RoomTileContextMenu_tag_fieldSet {
+ font-weight: bold;
+}
+
+.mx_RoomTileContextMenu_tag_field.mx_RoomTileContextMenu_tag_fieldSet .mx_RoomTileContextMenu_tag_icon {
+ display: none;
+}
+
+.mx_RoomTileContextMenu_tag_field.mx_RoomTileContextMenu_tag_fieldSet .mx_RoomTileContextMenu_tag_icon_set {
+ display: inline-block;
+}
+
+.mx_RoomTileContextMenu_tag_field.mx_RoomTileContextMenu_tag_fieldDisabled {
+ color: rgba(0, 0, 0, 0.2);
+}
+
+.mx_RoomTileContextMenu_tag_icon {
+ padding-right: 8px;
+ padding-left: 4px;
+ display: inline-block
+}
+
+.mx_RoomTileContextMenu_tag_icon_set {
+ padding-right: 8px;
+ padding-left: 4px;
+ display: none;
+}
+
+.mx_RoomTileContextMenu_separator {
+ margin-top: 0;
+ margin-bottom: 0;
+ border-bottom-style: none;
+ border-left-style: none;
+ border-right-style: none;
+ border-top-style: solid;
+ border-top-width: 1px;
+ border-color: $menu-border-color;
+}
+
+.mx_RoomTileContextMenu_leave {
+ color: $warning-color;
+}
+
+.mx_RoomTileContextMenu_tag_fieldSet .mx_RoomTileContextMenu_tag_icon {
+ /* Something to indicate that the icon is the set tag */
+}
+
+.mx_RoomTileContextMenu_notif_picker {
+ position: absolute;
+ top: 16px;
+ left: 5px;
+}
+
+.mx_RoomTileContextMenu_notif_field {
+ padding-top: 4px;
+ padding-right: 6px;
+ padding-bottom: 10px;
+ padding-left: 8px; /* 20px */
+ cursor: pointer;
+ white-space: nowrap;
+ display: flex;
+ align-items: center;
+}
+
+.mx_RoomTileContextMenu_notif_field.mx_RoomTileContextMenu_notif_fieldSet {
+ font-weight: bold;
+}
+
+.mx_RoomTileContextMenu_notif_field.mx_RoomTileContextMenu_notif_fieldDisabled {
+ color: rgba(0, 0, 0, 0.2);
+}
+
+.mx_RoomTileContextMenu_notif_icon {
+ padding-right: 4px;
+ padding-left: 4px;
+}
+
+.mx_RoomTileContextMenu_notif_activeIcon {
+ display: inline-block;
+ opacity: 0;
+ position: relative;
+ left: -5px;
+}
+
+.mx_RoomTileContextMenu_notif_fieldSet .mx_RoomTileContextMenu_notif_activeIcon {
+ opacity: 1;
+}