diff --git a/src/component-index.js b/src/component-index.js index 4e6eefb6..2b67aa15 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 d4b40d17..00000000 --- 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 8a44051f..00000000 --- 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 00000000..6430cd37 --- /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 6a1fefb0..650cf3d5 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 34cc21d4..08efa145 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 1f068526..00000000 --- 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 16a3ab79..00000000 --- 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 00000000..598f8ac2 --- /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; +}