+
{chevron}
diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js
index dc9ca08e94..f1d69cada9 100644
--- a/src/components/structures/MatrixChat.js
+++ b/src/components/structures/MatrixChat.js
@@ -20,7 +20,7 @@ var Favico = require('favico.js');
var MatrixClientPeg = require("../../MatrixClientPeg");
var Notifier = require("../../Notifier");
-var ContextualMenu = require("../../ContextualMenu");
+var ContextualMenu = require("./ContextualMenu");
var RoomListSorter = require("../../RoomListSorter");
var UserActivity = require("../../UserActivity");
var Presence = require("../../Presence");
diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js
index 77be8226a2..7945debd1a 100644
--- a/src/components/views/rooms/EventTile.js
+++ b/src/components/views/rooms/EventTile.js
@@ -23,7 +23,7 @@ var sdk = require('../../../index');
var MatrixClientPeg = require('../../../MatrixClientPeg')
var TextForEvent = require('../../../TextForEvent');
-var ContextualMenu = require('../../../ContextualMenu');
+var ContextualMenu = require('../../structures/ContextualMenu');
var dispatcher = require("../../../dispatcher");
var ObjectUtils = require('../../../ObjectUtils');
@@ -249,12 +249,15 @@ module.exports = React.createClass({
},
onEditClicked: function(e) {
- var MessageContextMenu = sdk.getComponent('rooms.MessageContextMenu');
+ var MessageContextMenu = sdk.getComponent('context_menus.MessageContextMenu');
var buttonRect = e.target.getBoundingClientRect()
- var x = buttonRect.right;
- var y = buttonRect.top + (e.target.height / 2);
+
+ // The window X and Y offsets are to adjust position when zoomed in to page
+ var x = buttonRect.right + window.pageXOffset;
+ var y = (buttonRect.top + (e.target.height / 2) + window.pageYOffset) - 19;
var self = this;
ContextualMenu.createMenu(MessageContextMenu, {
+ chevronOffset: 10,
mxEvent: this.props.mxEvent,
left: x,
top: y,
diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js
index 0c8ac7ed8d..8e57ceab9b 100644
--- a/src/components/views/rooms/RoomList.js
+++ b/src/components/views/rooms/RoomList.js
@@ -268,9 +268,11 @@ module.exports = React.createClass({
},
_repositionTooltip: function(e) {
- if (this.tooltip && this.tooltip.parentElement) {
+ // We access the parent of the parent, as the tooltip is inside a container
+ // Needs refactoring into a better multipurpose tooltip
+ if (this.tooltip && this.tooltip.parentElement && this.tooltip.parentElement.parentElement) {
var scroll = ReactDOM.findDOMNode(this);
- this.tooltip.style.top = (70 + scroll.parentElement.offsetTop + this.tooltip.parentElement.offsetTop - this._getScrollNode().scrollTop) + "px";
+ this.tooltip.style.top = (3 + scroll.parentElement.offsetTop + this.tooltip.parentElement.parentElement.offsetTop - this._getScrollNode().scrollTop) + "px";
}
},
diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js
index aa83110632..602ed4ee04 100644
--- a/src/components/views/rooms/RoomTile.js
+++ b/src/components/views/rooms/RoomTile.js
@@ -21,6 +21,7 @@ var classNames = require('classnames');
var dis = require("../../../dispatcher");
var MatrixClientPeg = require('../../../MatrixClientPeg');
var sdk = require('../../../index');
+var ContextualMenu = require('../../structures/ContextualMenu');
import {emojifyText} from '../../../HtmlUtils';
module.exports = React.createClass({
@@ -43,16 +44,48 @@ module.exports = React.createClass({
},
getInitialState: function() {
+ var areNotifsMuted = false;
+ var cli = MatrixClientPeg.get();
+ if (!cli.isGuest()) {
+ var roomPushRule = cli.getRoomPushRule("global", this.props.room.roomId);
+ if (roomPushRule) {
+ if (0 <= roomPushRule.actions.indexOf("dont_notify")) {
+ areNotifsMuted = true;
+ }
+ }
+ }
+
return({
hover : false,
badgeHover : false,
+ menu: false,
+ areNotifsMuted: areNotifsMuted,
});
},
+ onAction: function(payload) {
+ switch (payload.action) {
+ case 'notification_change':
+ // Is the notification about this room?
+ if (payload.roomId === this.props.room.roomId) {
+ this.setState( { areNotifsMuted : payload.isMuted });
+ }
+ break;
+ }
+ },
+
+ componentDidMount: function() {
+ this.dispatcherRef = dis.register(this.onAction);
+ },
+
+ componentWillUnmount: function() {
+ dis.unregister(this.dispatcherRef);
+ },
+
onClick: function() {
dis.dispatch({
action: 'view_room',
- room_id: this.props.room.roomId
+ room_id: this.props.room.roomId,
});
},
@@ -65,13 +98,47 @@ module.exports = React.createClass({
},
badgeOnMouseEnter: function() {
- this.setState( { badgeHover : true } );
+ // Only allow none guests to access the context menu
+ // and only change it if it needs to change
+ if (!MatrixClientPeg.get().isGuest() && !this.state.badgeHover) {
+ this.setState( { badgeHover : true } );
+ }
},
badgeOnMouseLeave: function() {
this.setState( { badgeHover : false } );
},
+ onBadgeClicked: function(e) {
+ // Only allow none guests to access the context menu
+ if (!MatrixClientPeg.get().isGuest()) {
+
+ // If the badge is clicked, then no longer show tooltip
+ if (this.props.collapsed) {
+ this.setState({ hover: false });
+ }
+
+ var Menu = sdk.getComponent('context_menus.NotificationStateContextMenu');
+ var elementRect = e.target.getBoundingClientRect();
+ // The window X and Y offsets are to adjust position when zoomed in to page
+ var x = elementRect.right + window.pageXOffset + 3;
+ var y = (elementRect.top + (elementRect.height / 2) + window.pageYOffset) - 53;
+ var self = this;
+ ContextualMenu.createMenu(Menu, {
+ menuWidth: 188,
+ menuHeight: 126,
+ chevronOffset: 45,
+ left: x,
+ top: y,
+ room: this.props.room,
+ onFinished: function() {
+ self.setState({ menu: false });
+ }
+ });
+ this.setState({ menu: true });
+ }
+ },
+
render: function() {
var myUserId = MatrixClientPeg.get().credentials.userId;
var me = this.props.room.currentState.members[myUserId];
@@ -84,60 +151,63 @@ module.exports = React.createClass({
'mx_RoomTile_selected': this.props.selected,
'mx_RoomTile_unread': this.props.unread,
'mx_RoomTile_unreadNotify': notificationCount > 0,
+ 'mx_RoomTile_read': !(this.props.highlight || notificationCount > 0),
'mx_RoomTile_highlight': this.props.highlight,
'mx_RoomTile_invited': (me && me.membership == 'invite'),
+ 'mx_RoomTile_menu': this.state.menu,
+ });
+
+ var avatarClasses = classNames({
+ 'mx_RoomTile_avatar': true,
+ 'mx_RoomTile_mute': this.state.areNotifsMuted,
+ });
+
+ var badgeClasses = classNames({
+ 'mx_RoomTile_badge': true,
+ 'mx_RoomTile_badgeButton': this.state.badgeHover || this.state.menu,
+ 'mx_RoomTile_badgeMute': this.state.areNotifsMuted,
});
// XXX: We should never display raw room IDs, but sometimes the
// room name js sdk gives is undefined (cannot repro this -- k)
var name = this.props.room.name || this.props.room.roomId;
-
name = name.replace(":", ":\u200b"); // add a zero-width space to allow linewrapping after the colon
+
var badge;
var badgeContent;
- var badgeClasses;
- if (this.state.badgeHover) {
+ if (this.state.badgeHover || this.state.menu) {
badgeContent = "\u00B7\u00B7\u00B7";
} else if (this.props.highlight || notificationCount > 0) {
- badgeContent = notificationCount ? notificationCount : '!';
+ var limitedCount = (notificationCount > 99) ? '99+' : notificationCount;
+ badgeContent = notificationCount ? limitedCount : '!';
} else {
badgeContent = '\u200B';
}
- if (this.props.highlight || notificationCount > 0) {
- badgeClasses = "mx_RoomTile_badge";
+ if (this.state.areNotifsMuted && !(this.state.badgeHover || this.state.menu)) {
+ badge =
;
} else {
- badgeClasses = "mx_RoomTile_badge mx_RoomTile_badge_no_unread";
+ badge =
{ badgeContent }
;
}
- badge =
{ badgeContent }
;
-
- /*
- if (this.props.highlight) {
- badge =
!
;
- }
- else if (this.props.unread) {
- badge =
1
;
- }
- var nameCell;
- if (badge) {
- nameCell =
;
- }
- else {
- nameCell =
{name}
;
- }
- */
-
var label;
+ var tooltip;
if (!this.props.collapsed) {
- var className = 'mx_RoomTile_name' + (this.props.isInvite ? ' mx_RoomTile_invite' : '');
+ var nameClasses = classNames({
+ 'mx_RoomTile_name': true,
+ 'mx_RoomTile_invite': this.props.isInvite,
+ 'mx_RoomTile_mute': this.state.areNotifsMuted,
+ 'mx_RoomTile_badgeShown': this.props.highlight || notificationCount > 0 || this.state.badgeHover || this.state.menu || this.state.areNotifsMuted,
+ });
+
let nameHTML = emojifyText(name);
if (this.props.selected) {
- name =
;
- label =
{ name }
;
+ let nameSelected =
;
+
+ label =
{ nameSelected }
;
} else {
- label =
;
+ label =
;
}
}
else if (this.state.hover) {
@@ -160,13 +230,16 @@ module.exports = React.createClass({
var connectDropTarget = this.props.connectDropTarget;
return connectDragSource(connectDropTarget(
-
-
-
+
+
+
+
+
+ { label }
+ { badge }
- { label }
- { badge }
{ incomingCallBox }
+ { tooltip }
));
}