From 775fc971020772c2ee80e0b291b2d1e00b88840a Mon Sep 17 00:00:00 2001 From: wmwragg Date: Thu, 21 Jul 2016 14:33:54 +0100 Subject: [PATCH 01/38] Slight refactor to better match current code --- src/components/views/rooms/RoomTile.js | 28 +++----------------------- 1 file changed, 3 insertions(+), 25 deletions(-) diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js index aa83110632..3dccb6ee6a 100644 --- a/src/components/views/rooms/RoomTile.js +++ b/src/components/views/rooms/RoomTile.js @@ -84,6 +84,7 @@ 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'), }); @@ -91,11 +92,10 @@ module.exports = React.createClass({ // 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) { badgeContent = "\u00B7\u00B7\u00B7"; @@ -105,29 +105,7 @@ module.exports = React.createClass({ badgeContent = '\u200B'; } - if (this.props.highlight || notificationCount > 0) { - badgeClasses = "mx_RoomTile_badge"; - } else { - badgeClasses = "mx_RoomTile_badge mx_RoomTile_badge_no_unread"; - } - - badge =
{ badgeContent }
; - - /* - if (this.props.highlight) { - badge =
!
; - } - else if (this.props.unread) { - badge =
1
; - } - var nameCell; - if (badge) { - nameCell =
{name}
{badge}
; - } - else { - nameCell =
{name}
; - } - */ + badge =
{ badgeContent }
; var label; if (!this.props.collapsed) { From 4013ea75d0f9eba00a24816213ad1a5f68b4d926 Mon Sep 17 00:00:00 2001 From: wmwragg Date: Thu, 21 Jul 2016 17:44:31 +0100 Subject: [PATCH 02/38] Testing out the context menu --- src/components/views/rooms/RoomTile.js | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js index aa83110632..2b8d98d42d 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('../../../ContextualMenu'); import {emojifyText} from '../../../HtmlUtils'; module.exports = React.createClass({ @@ -46,6 +47,7 @@ module.exports = React.createClass({ return({ hover : false, badgeHover : false, + menu: false, }); }, @@ -72,6 +74,22 @@ module.exports = React.createClass({ this.setState( { badgeHover : false } ); }, + onBadgeClicked: function(e) { + var Label = sdk.getComponent('elements.Label'); + var elementRect = e.target.getBoundingClientRect(); + var x = elementRect.right; + var y = elementRect.height + (elementRect.height / 2); + var self = this; + ContextualMenu.createMenu(Label, { + left: x, + top: y, + 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]; @@ -111,7 +129,7 @@ module.exports = React.createClass({ badgeClasses = "mx_RoomTile_badge mx_RoomTile_badge_no_unread"; } - badge =
{ badgeContent }
; + badge =
{ badgeContent }
; /* if (this.props.highlight) { @@ -160,9 +178,9 @@ module.exports = React.createClass({ var connectDropTarget = this.props.connectDropTarget; return connectDragSource(connectDropTarget( -
+
- +
{ label } { badge } From 762873350a5489f77e8b256f35a29aeff03a6c64 Mon Sep 17 00:00:00 2001 From: wmwragg Date: Thu, 21 Jul 2016 18:20:12 +0100 Subject: [PATCH 03/38] Badge dohickey shown on name hover and badge hover --- src/components/views/rooms/RoomTile.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js index 3dccb6ee6a..2857a99aa2 100644 --- a/src/components/views/rooms/RoomTile.js +++ b/src/components/views/rooms/RoomTile.js @@ -97,6 +97,11 @@ module.exports = React.createClass({ var badge; var badgeContent; + var badgeClasses = classNames({ + 'mx_RoomTile_badge': true, + 'mx_RoomTile_badgeButton': this.state.badgeHover, + }); + if (this.state.badgeHover) { badgeContent = "\u00B7\u00B7\u00B7"; } else if (this.props.highlight || notificationCount > 0) { @@ -105,7 +110,7 @@ module.exports = React.createClass({ badgeContent = '\u200B'; } - badge =
{ badgeContent }
; + badge =
{ badgeContent }
; var label; if (!this.props.collapsed) { @@ -113,9 +118,9 @@ module.exports = React.createClass({ let nameHTML = emojifyText(name); if (this.props.selected) { name = ; - label =
{ name }
; + label =
{ name }
; } else { - label =
; + label =
; } } else if (this.state.hover) { @@ -138,9 +143,9 @@ module.exports = React.createClass({ var connectDropTarget = this.props.connectDropTarget; return connectDragSource(connectDropTarget( -
+
- +
{ label } { badge } From 922bb0f40204763794c353958632d4ccc794da60 Mon Sep 17 00:00:00 2001 From: wmwragg Date: Thu, 21 Jul 2016 18:50:07 +0100 Subject: [PATCH 04/38] +99 badge when notifications are greater the 99 --- src/components/views/rooms/RoomTile.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js index 2857a99aa2..0012f66306 100644 --- a/src/components/views/rooms/RoomTile.js +++ b/src/components/views/rooms/RoomTile.js @@ -105,7 +105,8 @@ module.exports = React.createClass({ if (this.state.badgeHover) { 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'; } From 3dd83922f17dbe3d8282d8db89d327e246d52afe Mon Sep 17 00:00:00 2001 From: wmwragg Date: Fri, 22 Jul 2016 11:12:11 +0100 Subject: [PATCH 05/38] Tooltip positioning tweaked --- src/components/views/rooms/RoomList.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index aff03182a1..7d41b69567 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -270,7 +270,7 @@ module.exports = React.createClass({ _repositionTooltip: function(e) { if (this.tooltip && this.tooltip.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.offsetTop - this._getScrollNode().scrollTop) + "px"; } }, From 5d4b03c1f4e9790ce6bb589c899b13ba02e953e5 Mon Sep 17 00:00:00 2001 From: wmwragg Date: Fri, 22 Jul 2016 11:28:11 +0100 Subject: [PATCH 06/38] Put back clicking on the name to acces the room --- src/components/views/rooms/RoomTile.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js index 2b8d98d42d..f0ac208ef9 100644 --- a/src/components/views/rooms/RoomTile.js +++ b/src/components/views/rooms/RoomTile.js @@ -153,9 +153,9 @@ module.exports = React.createClass({ let nameHTML = emojifyText(name); if (this.props.selected) { name = ; - label =
{ name }
; + label =
{ name }
; } else { - label =
; + label =
; } } else if (this.state.hover) { From ca75d93434ad840cc2f76f3cd3dfc470b0839fbe Mon Sep 17 00:00:00 2001 From: wmwragg Date: Fri, 22 Jul 2016 11:31:26 +0100 Subject: [PATCH 07/38] Tweaked the offset for the tooltip so that it is next to the element it is tipping --- src/components/views/rooms/RoomList.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index aff03182a1..7d41b69567 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -270,7 +270,7 @@ module.exports = React.createClass({ _repositionTooltip: function(e) { if (this.tooltip && this.tooltip.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.offsetTop - this._getScrollNode().scrollTop) + "px"; } }, From 6984a55b11a9e87100d19b3e6c43f89c973f99d0 Mon Sep 17 00:00:00 2001 From: wmwragg Date: Fri, 22 Jul 2016 14:58:09 +0100 Subject: [PATCH 08/38] The tooltip now appears even when not collapsed when hover over the avater, to allow the full name to be shown --- src/components/views/rooms/RoomTile.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js index 0012f66306..20d0c9824c 100644 --- a/src/components/views/rooms/RoomTile.js +++ b/src/components/views/rooms/RoomTile.js @@ -114,6 +114,7 @@ module.exports = React.createClass({ badge =
{ badgeContent }
; var label; + var tooltip; if (!this.props.collapsed) { var className = 'mx_RoomTile_name' + (this.props.isInvite ? ' mx_RoomTile_invite' : ''); let nameHTML = emojifyText(name); @@ -123,6 +124,11 @@ module.exports = React.createClass({ } else { label =
; } + + if (this.state.hover) { + var RoomTooltip = sdk.getComponent("rooms.RoomTooltip"); + tooltip = ; + } } else if (this.state.hover) { var RoomTooltip = sdk.getComponent("rooms.RoomTooltip"); @@ -151,6 +157,7 @@ module.exports = React.createClass({ { label } { badge } { incomingCallBox } + { tooltip }
)); } From e4dd6c8dbeced4604dea6d28970f6d0162fac3fd Mon Sep 17 00:00:00 2001 From: wmwragg Date: Fri, 22 Jul 2016 15:15:24 +0100 Subject: [PATCH 09/38] Browser tooltip being used instead of the HTML styled one. --- src/components/views/rooms/RoomTile.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js index 20d0c9824c..47d61cf95a 100644 --- a/src/components/views/rooms/RoomTile.js +++ b/src/components/views/rooms/RoomTile.js @@ -120,15 +120,17 @@ module.exports = React.createClass({ let nameHTML = emojifyText(name); if (this.props.selected) { name = ; - label =
{ name }
; + label =
{ name }
; } else { - label =
; + label =
; } + /* if (this.state.hover) { var RoomTooltip = sdk.getComponent("rooms.RoomTooltip"); tooltip = ; } + */ } else if (this.state.hover) { var RoomTooltip = sdk.getComponent("rooms.RoomTooltip"); From 9b318e8f610af905c6b7b1aab82e98405a011a2e Mon Sep 17 00:00:00 2001 From: wmwragg Date: Fri, 22 Jul 2016 16:12:20 +0100 Subject: [PATCH 10/38] Getting the corrct height for the placing the context menu --- src/components/views/rooms/RoomTile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js index f0ac208ef9..48cb345d91 100644 --- a/src/components/views/rooms/RoomTile.js +++ b/src/components/views/rooms/RoomTile.js @@ -78,7 +78,7 @@ module.exports = React.createClass({ var Label = sdk.getComponent('elements.Label'); var elementRect = e.target.getBoundingClientRect(); var x = elementRect.right; - var y = elementRect.height + (elementRect.height / 2); + var y = elementRect.top + (elementRect.height / 2); var self = this; ContextualMenu.createMenu(Label, { left: x, From c89904bc25136a9520f798b4e6cc61335f18b5f1 Mon Sep 17 00:00:00 2001 From: wmwragg Date: Fri, 22 Jul 2016 17:30:31 +0100 Subject: [PATCH 11/38] Initial unstyled mentions state notifier context menu --- src/components/views/rooms/RoomTile.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js index 48cb345d91..9c39b50427 100644 --- a/src/components/views/rooms/RoomTile.js +++ b/src/components/views/rooms/RoomTile.js @@ -75,7 +75,7 @@ module.exports = React.createClass({ }, onBadgeClicked: function(e) { - var Label = sdk.getComponent('elements.Label'); + var Label = sdk.getComponent('rooms.NotificationStateContextMenu'); var elementRect = e.target.getBoundingClientRect(); var x = elementRect.right; var y = elementRect.top + (elementRect.height / 2); @@ -83,6 +83,7 @@ module.exports = React.createClass({ ContextualMenu.createMenu(Label, { left: x, top: y, + room: this.props.room, onFinished: function() { self.setState({menu: false}); } From a69107f4f1d5351a6bda37bd5c5608fd9b22a96f Mon Sep 17 00:00:00 2001 From: wmwragg Date: Mon, 25 Jul 2016 10:58:43 +0100 Subject: [PATCH 12/38] Trying to get the context menu dohicky to stick when menu open --- src/components/views/rooms/RoomTile.js | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js index 9c39b50427..387cca6775 100644 --- a/src/components/views/rooms/RoomTile.js +++ b/src/components/views/rooms/RoomTile.js @@ -75,20 +75,27 @@ module.exports = React.createClass({ }, onBadgeClicked: function(e) { - var Label = sdk.getComponent('rooms.NotificationStateContextMenu'); + console.log("DEBUG: MENU FALSE"); + var Menu = sdk.getComponent('rooms.NotificationStateContextMenu'); var elementRect = e.target.getBoundingClientRect(); var x = elementRect.right; var y = elementRect.top + (elementRect.height / 2); var self = this; - ContextualMenu.createMenu(Label, { + ContextualMenu.createMenu(Menu, { left: x, top: y, room: this.props.room, onFinished: function() { - self.setState({menu: false}); + self.setState({ + menu: false, + badgeHover: false, + }); } }); - this.setState({menu: true}); + this.setState({ + menu: true, + badgeHover: true, + }); }, render: function() { From 8b8486a8d096b285e2b03032aedf5917afcdfa7d Mon Sep 17 00:00:00 2001 From: wmwragg Date: Mon, 25 Jul 2016 14:39:15 +0100 Subject: [PATCH 13/38] Move from +99 to 99+ for more than 99 messages --- src/components/views/rooms/RoomTile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js index 47d61cf95a..b39e80cb54 100644 --- a/src/components/views/rooms/RoomTile.js +++ b/src/components/views/rooms/RoomTile.js @@ -105,7 +105,7 @@ module.exports = React.createClass({ if (this.state.badgeHover) { badgeContent = "\u00B7\u00B7\u00B7"; } else if (this.props.highlight || notificationCount > 0) { - var limitedCount = (notificationCount > 99) ? '+99' : notificationCount; + var limitedCount = (notificationCount > 99) ? '99+' : notificationCount; badgeContent = notificationCount ? limitedCount : '!'; } else { badgeContent = '\u200B'; From 9c9c5ec4588e56ddd3b3ad56619b452454f84e4b Mon Sep 17 00:00:00 2001 From: wmwragg Date: Mon, 25 Jul 2016 17:18:45 +0100 Subject: [PATCH 14/38] Menu context dohickey now sticks when menu shown --- src/components/views/rooms/RoomTile.js | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js index 85a19eeb6e..d373cbc69c 100644 --- a/src/components/views/rooms/RoomTile.js +++ b/src/components/views/rooms/RoomTile.js @@ -86,16 +86,10 @@ module.exports = React.createClass({ top: y, room: this.props.room, onFinished: function() { - self.setState({ - menu: false, - badgeHover: false, - }); + self.setState({ menu: false }); } }); - this.setState({ - menu: true, - badgeHover: true, - }); + this.setState({ menu: true }); }, render: function() { @@ -113,6 +107,7 @@ module.exports = React.createClass({ '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, }); // XXX: We should never display raw room IDs, but sometimes the @@ -128,7 +123,7 @@ module.exports = React.createClass({ 'mx_RoomTile_badgeButton': this.state.badgeHover, }); - if (this.state.badgeHover) { + if (this.state.badgeHover || this.state.menu) { badgeContent = "\u00B7\u00B7\u00B7"; } else if (this.props.highlight || notificationCount > 0) { var limitedCount = (notificationCount > 99) ? '99+' : notificationCount; From 8f3e93214c73531808f1153b735c680c370cefed Mon Sep 17 00:00:00 2001 From: wmwragg Date: Mon, 25 Jul 2016 18:02:30 +0100 Subject: [PATCH 15/38] Drawing cheveron with CSS so it can be styled --- src/ContextualMenu.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ContextualMenu.js b/src/ContextualMenu.js index e720b69eda..65d3e98910 100644 --- a/src/ContextualMenu.js +++ b/src/ContextualMenu.js @@ -54,10 +54,10 @@ module.exports = { var chevron = null; if (props.left) { - chevron = + chevron =
position.left = props.left + 8; } else { - chevron = + chevron =
position.right = props.right + 8; } From 477a17b49f0aeb94f5ed803463502138d116cca6 Mon Sep 17 00:00:00 2001 From: wmwragg Date: Tue, 26 Jul 2016 10:39:34 +0100 Subject: [PATCH 16/38] Removed debug statement --- src/components/views/rooms/RoomTile.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js index d373cbc69c..28574fcec5 100644 --- a/src/components/views/rooms/RoomTile.js +++ b/src/components/views/rooms/RoomTile.js @@ -75,7 +75,6 @@ module.exports = React.createClass({ }, onBadgeClicked: function(e) { - console.log("DEBUG: MENU FALSE"); var Menu = sdk.getComponent('rooms.NotificationStateContextMenu'); var elementRect = e.target.getBoundingClientRect(); var x = elementRect.right; From 0eb15085e97c55238089f9f8ae3b76eac66e7052 Mon Sep 17 00:00:00 2001 From: wmwragg Date: Tue, 26 Jul 2016 17:25:16 +0100 Subject: [PATCH 17/38] some code tidyup --- src/ContextualMenu.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/ContextualMenu.js b/src/ContextualMenu.js index 65d3e98910..695b8445ab 100644 --- a/src/ContextualMenu.js +++ b/src/ContextualMenu.js @@ -45,7 +45,9 @@ module.exports = { var closeMenu = function() { ReactDOM.unmountComponentAtNode(self.getOrCreateContainer()); - if (props && props.onFinished) props.onFinished.apply(null, arguments); + if (props && props.onFinished) { + props.onFinished.apply(null, arguments); + } }; var position = { @@ -54,10 +56,10 @@ module.exports = { var chevron = null; if (props.left) { - chevron =
+ chevron =
position.left = props.left + 8; } else { - chevron =
+ chevron =
position.right = props.right + 8; } From dca4702b7b3df510e9b9fd28524e5e5ac0b57448 Mon Sep 17 00:00:00 2001 From: wmwragg Date: Wed, 27 Jul 2016 09:51:50 +0100 Subject: [PATCH 18/38] Fixed a bug where the contextual menu was being incorrectly positioned when zoom in on the webpage --- src/components/views/rooms/EventTile.js | 6 ++++-- src/components/views/rooms/RoomTile.js | 5 +++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js index 77be8226a2..129eb120fa 100644 --- a/src/components/views/rooms/EventTile.js +++ b/src/components/views/rooms/EventTile.js @@ -251,8 +251,10 @@ module.exports = React.createClass({ onEditClicked: function(e) { var MessageContextMenu = sdk.getComponent('rooms.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; var self = this; ContextualMenu.createMenu(MessageContextMenu, { mxEvent: this.props.mxEvent, diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js index 28574fcec5..ce4888e896 100644 --- a/src/components/views/rooms/RoomTile.js +++ b/src/components/views/rooms/RoomTile.js @@ -77,8 +77,9 @@ module.exports = React.createClass({ onBadgeClicked: function(e) { var Menu = sdk.getComponent('rooms.NotificationStateContextMenu'); var elementRect = e.target.getBoundingClientRect(); - var x = elementRect.right; - var y = elementRect.top + (elementRect.height / 2); + // The window X and Y offsets are to adjust position when zoomed in to page + var x = elementRect.right + window.pageXOffset; + var y = elementRect.top + (elementRect.height / 2) + window.pageYOffset; var self = this; ContextualMenu.createMenu(Menu, { left: x, From 4b26ac58afeff66af403ef4110f32e95c75a4d08 Mon Sep 17 00:00:00 2001 From: wmwragg Date: Wed, 27 Jul 2016 10:41:24 +0100 Subject: [PATCH 19/38] Re-modularised the context menus --- src/{ => components/structures}/ContextualMenu.js | 0 src/components/views/rooms/EventTile.js | 2 +- src/components/views/rooms/RoomTile.js | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename src/{ => components/structures}/ContextualMenu.js (100%) diff --git a/src/ContextualMenu.js b/src/components/structures/ContextualMenu.js similarity index 100% rename from src/ContextualMenu.js rename to src/components/structures/ContextualMenu.js diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js index 129eb120fa..6006ff3ebd 100644 --- a/src/components/views/rooms/EventTile.js +++ b/src/components/views/rooms/EventTile.js @@ -249,7 +249,7 @@ 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() // The window X and Y offsets are to adjust position when zoomed in to page diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js index ce4888e896..654bf268e1 100644 --- a/src/components/views/rooms/RoomTile.js +++ b/src/components/views/rooms/RoomTile.js @@ -75,7 +75,7 @@ module.exports = React.createClass({ }, onBadgeClicked: function(e) { - var Menu = sdk.getComponent('rooms.NotificationStateContextMenu'); + 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; From 6d141d1a7ba1929799edc109fb1a8b632349c120 Mon Sep 17 00:00:00 2001 From: wmwragg Date: Wed, 27 Jul 2016 11:58:40 +0100 Subject: [PATCH 20/38] Only allow none guests to access the context menu --- src/components/views/rooms/RoomTile.js | 38 +++++++++++++++----------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js index 654bf268e1..43d6a31738 100644 --- a/src/components/views/rooms/RoomTile.js +++ b/src/components/views/rooms/RoomTile.js @@ -67,7 +67,10 @@ module.exports = React.createClass({ }, badgeOnMouseEnter: function() { - this.setState( { badgeHover : true } ); + // Only allow none guests to access the context menu + if (!MatrixClientPeg.get().isGuest()) { + this.setState( { badgeHover : true } ); + } }, badgeOnMouseLeave: function() { @@ -75,21 +78,24 @@ module.exports = React.createClass({ }, onBadgeClicked: function(e) { - 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; - var y = elementRect.top + (elementRect.height / 2) + window.pageYOffset; - var self = this; - ContextualMenu.createMenu(Menu, { - left: x, - top: y, - room: this.props.room, - onFinished: function() { - self.setState({ menu: false }); - } - }); - this.setState({ menu: true }); + // Only allow none guests to access the context menu + if (!MatrixClientPeg.get().isGuest()) { + 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; + var y = elementRect.top + (elementRect.height / 2) + window.pageYOffset; + var self = this; + ContextualMenu.createMenu(Menu, { + left: x, + top: y, + room: this.props.room, + onFinished: function() { + self.setState({ menu: false }); + } + }); + this.setState({ menu: true }); + } }, render: function() { From 3df746ef143a02103272081f384280961bc18b81 Mon Sep 17 00:00:00 2001 From: wmwragg Date: Wed, 27 Jul 2016 14:16:17 +0100 Subject: [PATCH 21/38] Revert merge up from develop --- package.json | 10 +- src/GuestAccess.js | 51 ------- src/MatrixClientPeg.js | 171 +++++++++++++---------- src/TabComplete.js | 7 +- src/components/structures/RoomView.js | 18 ++- src/components/views/rooms/MemberInfo.js | 8 +- src/ratelimitedfunc.js | 8 ++ 7 files changed, 130 insertions(+), 143 deletions(-) delete mode 100644 src/GuestAccess.js diff --git a/package.json b/package.json index cd81ad7c56..60fc45db77 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "reskindex": "./reskindex.js" }, "scripts": { - "reskindex": "reskindex -h header", + "reskindex": "./reskindex.js -h header", "build": "babel src -d lib --source-maps --stage 1", "start": "babel src -w -d lib --source-maps --stage 1", "lint": "eslint src/", @@ -42,10 +42,10 @@ "matrix-js-sdk": "matrix-org/matrix-js-sdk#develop", "optimist": "^0.6.1", "q": "^1.4.1", - "react": "^15.0.1", - "react-addons-css-transition-group": "^15.1.0", - "react-dom": "^15.0.1", - "react-gemini-scrollbar": "matrix-org/react-gemini-scrollbar#c3d942e", + "react": "^15.2.1", + "react-addons-css-transition-group": "^15.2.1", + "react-dom": "^15.2.1", + "react-gemini-scrollbar": "matrix-org/react-gemini-scrollbar#dbf0abf", "sanitize-html": "^1.11.1", "velocity-vector": "vector-im/velocity#059e3b2", "whatwg-fetch": "^1.0.0" diff --git a/src/GuestAccess.js b/src/GuestAccess.js deleted file mode 100644 index ef48d23ded..0000000000 --- a/src/GuestAccess.js +++ /dev/null @@ -1,51 +0,0 @@ -/* -Copyright 2015 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. -*/ -const IS_GUEST_KEY = "matrix-is-guest"; - -class GuestAccess { - - constructor(localStorage) { - this.localStorage = localStorage; - try { - this._isGuest = localStorage.getItem(IS_GUEST_KEY) === "true"; - } - catch (e) {} // don't care - } - - setPeekedRoom(roomId) { - // we purposefully do not persist this to local storage as peeking is - // entirely transient. - this._peekedRoomId = roomId; - } - - getPeekedRoom() { - return this._peekedRoomId; - } - - isGuest() { - return this._isGuest; - } - - markAsGuest(isGuest) { - try { - this.localStorage.setItem(IS_GUEST_KEY, JSON.stringify(isGuest)); - } catch (e) {} // ignore. If they don't do LS, they'll just get a new account. - this._isGuest = isGuest; - this._peekedRoomId = null; - } -} - -module.exports = GuestAccess; diff --git a/src/MatrixClientPeg.js b/src/MatrixClientPeg.js index 7c1c5b34d7..ce4b5ba743 100644 --- a/src/MatrixClientPeg.js +++ b/src/MatrixClientPeg.js @@ -16,13 +16,9 @@ limitations under the License. 'use strict'; -// A thing that holds your Matrix Client -var Matrix = require("matrix-js-sdk"); -var GuestAccess = require("./GuestAccess"); +import Matrix from 'matrix-js-sdk'; -let matrixClient: MatrixClient = null; - -var localStorage = window.localStorage; +const localStorage = window.localStorage; function deviceId() { // XXX: is Math.random()'s deterministicity a problem here? @@ -35,82 +31,42 @@ function deviceId() { return id; } -function createClientForPeg(hs_url, is_url, user_id, access_token, guestAccess) { - var opts = { - baseUrl: hs_url, - idBaseUrl: is_url, - accessToken: access_token, - userId: user_id, - timelineSupport: true, - }; - - if (localStorage) { - opts.sessionStore = new Matrix.WebStorageSessionStore(localStorage); - opts.deviceId = deviceId(); - } - - matrixClient = Matrix.createClient(opts); - - // we're going to add eventlisteners for each matrix event tile, so the - // potential number of event listeners is quite high. - matrixClient.setMaxListeners(500); - - if (guestAccess) { - console.log("Guest: %s", guestAccess.isGuest()); - matrixClient.setGuest(guestAccess.isGuest()); - var peekedRoomId = guestAccess.getPeekedRoom(); - if (peekedRoomId) { - console.log("Peeking in room %s", peekedRoomId); - matrixClient.peekInRoom(peekedRoomId); - } - } -} - -if (localStorage) { - var hs_url = localStorage.getItem("mx_hs_url"); - var is_url = localStorage.getItem("mx_is_url") || 'https://matrix.org'; - var access_token = localStorage.getItem("mx_access_token"); - var user_id = localStorage.getItem("mx_user_id"); - var guestAccess = new GuestAccess(localStorage); - if (access_token && user_id && hs_url) { - console.log("Restoring session for %s", user_id); - createClientForPeg(hs_url, is_url, user_id, access_token, guestAccess); - } - else { - console.log("Session not found."); - } -} - -class MatrixClient { - - constructor(guestAccess) { - this.guestAccess = guestAccess; +/** + * Wrapper object for handling the js-sdk Matrix Client object in the react-sdk + * Handles the creation/initialisation of client objects. + * This module provides a singleton instance of this class so the 'current' + * Matrix Client object is available easily. + */ +class MatrixClientPeg { + constructor() { + this.matrixClient = null; } get(): MatrixClient { - return matrixClient; + return this.matrixClient; } unset() { - matrixClient = null; + this.matrixClient = null; } - // FIXME, XXX: this all seems very convoluted :( - // - // Why do we have this peg wrapper rather than just MatrixClient.get()? - // Why do we name MatrixClient as MatrixClientPeg when we export it? - // - // -matthew - + /** + * Replace this MatrixClientPeg's client with a client instance that has + * Home Server / Identity Server URLs but no credentials + */ replaceUsingUrls(hs_url, is_url) { - this.replaceClient(hs_url, is_url); + this._replaceClient(hs_url, is_url); } + /** + * Replace this MatrixClientPeg's client with a client instance that has + * Home Server / Identity Server URLs and active credentials + */ replaceUsingAccessToken(hs_url, is_url, user_id, access_token, isGuest) { - this.replaceClient(hs_url, is_url, user_id, access_token, isGuest); + this._replaceClient(hs_url, is_url, user_id, access_token, isGuest); } - replaceClient(hs_url, is_url, user_id, access_token, isGuest) { + _replaceClient(hs_url, is_url, user_id, access_token, isGuest) { if (localStorage) { try { localStorage.clear(); @@ -118,15 +74,19 @@ class MatrixClient { console.warn("Error clearing local storage", e); } } - this.guestAccess.markAsGuest(Boolean(isGuest)); - createClientForPeg(hs_url, is_url, user_id, access_token, this.guestAccess); + this._createClient(hs_url, is_url, user_id, access_token, isGuest); + if (localStorage) { try { localStorage.setItem("mx_hs_url", hs_url); localStorage.setItem("mx_is_url", is_url); - localStorage.setItem("mx_user_id", user_id); - localStorage.setItem("mx_access_token", access_token); - console.log("Session persisted for %s", user_id); + + if (user_id !== undefined && access_token !== undefined) { + localStorage.setItem("mx_user_id", user_id); + localStorage.setItem("mx_access_token", access_token); + localStorage.setItem("mx_is_guest", JSON.stringify(isGuest)); + console.log("Session persisted for %s", user_id); + } } catch (e) { console.warn("Error using local storage: can't persist session!", e); } @@ -134,9 +94,68 @@ class MatrixClient { console.warn("No local storage available: can't persist session!"); } } + + getCredentials() { + return [ + this.matrixClient.baseUrl, + this.matrixClient.idBaseUrl, + this.matrixClient.credentials.userId, + this.matrixClient.getAccessToken(), + this.matrixClient.isGuest(), + ]; + } + + tryRestore() { + if (localStorage) { + const hs_url = localStorage.getItem("mx_hs_url"); + const is_url = localStorage.getItem("mx_is_url") || 'https://matrix.org'; + const access_token = localStorage.getItem("mx_access_token"); + const user_id = localStorage.getItem("mx_user_id"); + + let is_guest; + if (localStorage.getItem("mx_is_guest") !== null) { + is_guest = localStorage.getItem("mx_is_guest") === "true"; + } else { + // legacy key name + is_guest = localStorage.getItem("matrix-is-guest") === "true"; + } + + if (access_token && user_id && hs_url) { + console.log("Restoring session for %s", user_id); + this._createClient(hs_url, is_url, user_id, access_token); + this.matrixClient.setGuest(is_guest); + } else { + console.log("Session not found."); + } + } + } + + _createClient(hs_url, is_url, user_id, access_token, isGuest) { + var opts = { + baseUrl: hs_url, + idBaseUrl: is_url, + accessToken: access_token, + userId: user_id, + timelineSupport: true, + }; + + if (localStorage) { + opts.sessionStore = new Matrix.WebStorageSessionStore(localStorage); + opts.deviceId = deviceId(); + } + + this.matrixClient = Matrix.createClient(opts); + + // we're going to add eventlisteners for each matrix event tile, so the + // potential number of event listeners is quite high. + this.matrixClient.setMaxListeners(500); + + this.matrixClient.setGuest(Boolean(isGuest)); + } } -if (!global.mxMatrixClient) { - global.mxMatrixClient = new MatrixClient(new GuestAccess(localStorage)); +if (!global.mxMatrixClientPeg) { + global.mxMatrixClientPeg = new MatrixClientPeg(); + global.mxMatrixClientPeg.tryRestore(); } -module.exports = global.mxMatrixClient; +module.exports = global.mxMatrixClientPeg; diff --git a/src/TabComplete.js b/src/TabComplete.js index 0ec0b77802..65441c9381 100644 --- a/src/TabComplete.js +++ b/src/TabComplete.js @@ -341,7 +341,12 @@ class TabComplete { } if (a.kind == 'member') { - return this.memberTabOrder[b.member.userId] - this.memberTabOrder[a.member.userId]; + let orderA = this.memberTabOrder[a.member.userId]; + let orderB = this.memberTabOrder[b.member.userId]; + if (orderA === undefined) orderA = -1; + if (orderB === undefined) orderB = -1; + + return orderB - orderA; } // anything else we have no ordering for diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index accf96f349..9fbdb51f11 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -493,6 +493,17 @@ module.exports = React.createClass({ return; } + if (this.props.ConferenceHandler && + member.userId === this.props.ConferenceHandler.getConferenceUserIdForRoom(member.roomId)) { + this._updateConfCallNotification(); + } + + this._updateRoomMembers(); + }, + + // rate limited because a power level change will emit an event for every + // member in the room. + _updateRoomMembers: new rate_limited_func(function() { // a member state changed in this room, refresh the tab complete list this.tabComplete.loadEntries(this.state.room); this._updateAutoComplete(); @@ -506,12 +517,7 @@ module.exports = React.createClass({ joining: false }); } - - if (this.props.ConferenceHandler && - member.userId === this.props.ConferenceHandler.getConferenceUserIdForRoom(member.roomId)) { - this._updateConfCallNotification(); - } - }, + }, 500), _hasUnsentMessages: function(room) { return this._getUnsentMessages(room).length > 0; diff --git a/src/components/views/rooms/MemberInfo.js b/src/components/views/rooms/MemberInfo.js index c439f8b40c..07a7b9398d 100644 --- a/src/components/views/rooms/MemberInfo.js +++ b/src/components/views/rooms/MemberInfo.js @@ -406,14 +406,14 @@ module.exports = React.createClass({ this.props.onFinished(); } else { - self.setState({ updating: self.state.updating + 1 }); + this.setState({ updating: this.state.updating + 1 }); createRoom({ createOpts: { invite: [this.props.member.userId], }, - }).finally(function() { - self.props.onFinished(); - self.setState({ updating: self.state.updating - 1 }); + }).finally(() => { + this.props.onFinished(); + this.setState({ updating: this.state.updating - 1 }); }).done(); } }, diff --git a/src/ratelimitedfunc.js b/src/ratelimitedfunc.js index 453669b477..ed892f4eac 100644 --- a/src/ratelimitedfunc.js +++ b/src/ratelimitedfunc.js @@ -14,6 +14,14 @@ See the License for the specific language governing permissions and limitations under the License. */ +/** + * 'debounces' a function to only execute every n milliseconds. + * Useful when react-sdk gets many, many events but only wants + * to update the interface once for all of them. + * + * Note that the function must not take arguments, since the args + * could be different for each invocarion of the function. + */ module.exports = function(f, minIntervalMs) { this.lastCall = 0; this.scheduledCall = undefined; From 3cb3dd96a64d6929bc161e458e3d61e67f89ee9d Mon Sep 17 00:00:00 2001 From: wmwragg Date: Wed, 27 Jul 2016 14:23:37 +0100 Subject: [PATCH 22/38] Added the moved ContextualMenu to the components list --- src/component-index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/component-index.js b/src/component-index.js index 5fadb18b6a..7dfdcd6f8b 100644 --- a/src/component-index.js +++ b/src/component-index.js @@ -25,6 +25,7 @@ limitations under the License. */ module.exports.components = {}; +module.exports.components['structures.ContextualMenu'] = require('./components/structures/ContextualMenu'); module.exports.components['structures.CreateRoom'] = require('./components/structures/CreateRoom'); module.exports.components['structures.MatrixChat'] = require('./components/structures/MatrixChat'); module.exports.components['structures.MessagePanel'] = require('./components/structures/MessagePanel'); From 0660b9feff800761731d06a60246c7be8e9165ee Mon Sep 17 00:00:00 2001 From: wmwragg Date: Wed, 27 Jul 2016 14:49:10 +0100 Subject: [PATCH 23/38] Fixes to properly point to the moved components --- .DS_Store | Bin 0 -> 6148 bytes src/components/structures/MatrixChat.js | 2 +- src/components/views/rooms/EventTile.js | 2 +- src/components/views/rooms/RoomTile.js | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0 Date: Wed, 27 Jul 2016 16:09:07 +0100 Subject: [PATCH 24/38] Refactor so that chevron and menu can be positioned independantly --- src/components/structures/ContextualMenu.js | 19 +++++++++++++------ src/components/views/rooms/EventTile.js | 3 ++- src/components/views/rooms/RoomTile.js | 3 ++- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/components/structures/ContextualMenu.js b/src/components/structures/ContextualMenu.js index 695b8445ab..c6f8e32b11 100644 --- a/src/components/structures/ContextualMenu.js +++ b/src/components/structures/ContextualMenu.js @@ -17,6 +17,7 @@ limitations under the License. 'use strict'; +var classNames = require('classnames'); var React = require('react'); var ReactDOM = require('react-dom'); @@ -51,25 +52,31 @@ module.exports = { }; var position = { - top: props.top - 20, + top: props.top, }; var chevron = null; if (props.left) { - chevron =
- position.left = props.left + 8; + chevron =
+ position.left = props.left; } else { chevron =
- position.right = props.right + 8; + position.right = props.right; } var className = 'mx_ContextualMenu_wrapper'; + var menuClasses = classNames({ + 'mx_ContextualMenu': true, + 'mx_ContextualMenu_left': props.left, + 'mx_ContextualMenu_right': !props.left, + }); + // FIXME: If a menu uses getDefaultProps it clobbers the onFinished // property set here so you can't close the menu from a button click! var menu = ( -
-
+
+
{chevron}
diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js index a24c597ad4..7945debd1a 100644 --- a/src/components/views/rooms/EventTile.js +++ b/src/components/views/rooms/EventTile.js @@ -254,9 +254,10 @@ module.exports = React.createClass({ // 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; + 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/RoomTile.js b/src/components/views/rooms/RoomTile.js index a3ebf3ed45..13b20118e3 100644 --- a/src/components/views/rooms/RoomTile.js +++ b/src/components/views/rooms/RoomTile.js @@ -84,9 +84,10 @@ module.exports = React.createClass({ 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; - var y = elementRect.top + (elementRect.height / 2) + window.pageYOffset; + var y = (elementRect.top + (elementRect.height / 2) + window.pageYOffset) - 43; var self = this; ContextualMenu.createMenu(Menu, { + chevronOffset: 35, left: x, top: y, room: this.props.room, From 8246d9148cc4d1345d28be54c979021e686773e1 Mon Sep 17 00:00:00 2001 From: wmwragg Date: Wed, 27 Jul 2016 17:43:48 +0100 Subject: [PATCH 25/38] Initial context menu with all it's elements --- src/components/structures/ContextualMenu.js | 11 ++++++++++- src/components/views/rooms/RoomTile.js | 2 ++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/components/structures/ContextualMenu.js b/src/components/structures/ContextualMenu.js index c6f8e32b11..bf63227283 100644 --- a/src/components/structures/ContextualMenu.js +++ b/src/components/structures/ContextualMenu.js @@ -72,11 +72,20 @@ module.exports = { 'mx_ContextualMenu_right': !props.left, }); + var menuSize = {}; + if (props.menuWidth) { + menuSize.width = props.menuWidth; + } + + if (props.menuHeight) { + menuSize.height = props.menuHeight; + } + // FIXME: If a menu uses getDefaultProps it clobbers the onFinished // property set here so you can't close the menu from a button click! var menu = (
-
+
{chevron}
diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js index 13b20118e3..a500f18cb1 100644 --- a/src/components/views/rooms/RoomTile.js +++ b/src/components/views/rooms/RoomTile.js @@ -87,6 +87,8 @@ module.exports = React.createClass({ var y = (elementRect.top + (elementRect.height / 2) + window.pageYOffset) - 43; var self = this; ContextualMenu.createMenu(Menu, { + menuWidth: 188, + menuHeight: 126, chevronOffset: 35, left: x, top: y, From 46a643ac38b5b9b93e368c64c5f9752477650448 Mon Sep 17 00:00:00 2001 From: wmwragg Date: Wed, 27 Jul 2016 18:10:45 +0100 Subject: [PATCH 26/38] Now the text spaceing is correct need to align cheveron --- src/components/views/rooms/RoomTile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js index a500f18cb1..1f77c6a110 100644 --- a/src/components/views/rooms/RoomTile.js +++ b/src/components/views/rooms/RoomTile.js @@ -89,7 +89,7 @@ module.exports = React.createClass({ ContextualMenu.createMenu(Menu, { menuWidth: 188, menuHeight: 126, - chevronOffset: 35, + chevronOffset: 45, left: x, top: y, room: this.props.room, From 867b14d2cacd6db7eb5a1e1404b40081d44eb836 Mon Sep 17 00:00:00 2001 From: wmwragg Date: Wed, 27 Jul 2016 18:14:46 +0100 Subject: [PATCH 27/38] Reposition context menu now that the styling is final --- src/components/views/rooms/RoomTile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js index 1f77c6a110..a0af243ea4 100644 --- a/src/components/views/rooms/RoomTile.js +++ b/src/components/views/rooms/RoomTile.js @@ -84,7 +84,7 @@ module.exports = React.createClass({ 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; - var y = (elementRect.top + (elementRect.height / 2) + window.pageYOffset) - 43; + var y = (elementRect.top + (elementRect.height / 2) + window.pageYOffset) - 53; var self = this; ContextualMenu.createMenu(Menu, { menuWidth: 188, From bc902a9741c4d72e3bf9c8c7079f5564fefab5a3 Mon Sep 17 00:00:00 2001 From: wmwragg Date: Thu, 28 Jul 2016 14:32:59 +0100 Subject: [PATCH 28/38] Tidy up of the contextual menu refactor --- src/components/structures/ContextualMenu.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/components/structures/ContextualMenu.js b/src/components/structures/ContextualMenu.js index bf63227283..114bdaad1b 100644 --- a/src/components/structures/ContextualMenu.js +++ b/src/components/structures/ContextualMenu.js @@ -28,6 +28,12 @@ var ReactDOM = require('react-dom'); module.exports = { ContextualMenuContainerId: "mx_ContextualMenu_Container", + propTypes: { + menuWidth: React.PropTypes.number, + menuHeight: React.PropTypes.number, + chevronOffset: React.PropTypes.number, + }, + getOrCreateContainer: function() { var container = document.getElementById(this.ContextualMenuContainerId); @@ -55,12 +61,16 @@ module.exports = { top: props.top, }; + var chevronOffset = { + top: props.cheveronOffset, + } + var chevron = null; if (props.left) { - chevron =
+ chevron =
position.left = props.left; } else { - chevron =
+ chevron =
position.right = props.right; } From 94350bc780f17bba6b9e050e876c1beb761e3520 Mon Sep 17 00:00:00 2001 From: wmwragg Date: Thu, 28 Jul 2016 15:51:46 +0100 Subject: [PATCH 29/38] Fixed spelling mistake --- src/components/structures/ContextualMenu.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/ContextualMenu.js b/src/components/structures/ContextualMenu.js index 114bdaad1b..fcfc5d5e50 100644 --- a/src/components/structures/ContextualMenu.js +++ b/src/components/structures/ContextualMenu.js @@ -62,7 +62,7 @@ module.exports = { }; var chevronOffset = { - top: props.cheveronOffset, + top: props.chevronOffset, } var chevron = null; From 5889beacf3452883e9c7c1d197f9fd01f4fd651a Mon Sep 17 00:00:00 2001 From: wmwragg Date: Thu, 28 Jul 2016 17:24:58 +0100 Subject: [PATCH 30/38] Mute state now handled correctly --- src/components/views/rooms/RoomTile.js | 68 +++++++++++++++++++++----- 1 file changed, 57 insertions(+), 11 deletions(-) diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js index a0af243ea4..48b2ea84f4 100644 --- a/src/components/views/rooms/RoomTile.js +++ b/src/components/views/rooms/RoomTile.js @@ -44,17 +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 notificaion 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, }); }, @@ -119,6 +150,17 @@ module.exports = React.createClass({ '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; @@ -127,11 +169,6 @@ module.exports = React.createClass({ var badge; var badgeContent; - var badgeClasses = classNames({ - 'mx_RoomTile_badge': true, - 'mx_RoomTile_badgeButton': this.state.badgeHover, - }); - if (this.state.badgeHover || this.state.menu) { badgeContent = "\u00B7\u00B7\u00B7"; } else if (this.props.highlight || notificationCount > 0) { @@ -141,19 +178,28 @@ module.exports = React.createClass({ badgeContent = '\u200B'; } - badge =
{ badgeContent }
; + if (this.state.areNotifsMuted && !(this.state.badgeHover || this.state.menu)) { + badge =
; + } else { + badge =
{ badgeContent }
; + } 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, + }); + let nameHTML = emojifyText(name); if (this.props.selected) { name = ; - label =
{ name }
; + label =
{ name }
; } else { - label =
; + label =
; } } else if (this.state.hover) { @@ -177,7 +223,7 @@ module.exports = React.createClass({ return connectDragSource(connectDropTarget(
-
+
{ label } From 38f504bdcbaf6c57bdc7ab6ab8512154cff76efb Mon Sep 17 00:00:00 2001 From: wmwragg Date: Fri, 29 Jul 2016 11:10:16 +0100 Subject: [PATCH 31/38] Hide tooltip when badge clicked and collapsed --- src/components/views/rooms/RoomTile.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js index 48b2ea84f4..3f6704c2a2 100644 --- a/src/components/views/rooms/RoomTile.js +++ b/src/components/views/rooms/RoomTile.js @@ -111,6 +111,12 @@ module.exports = React.createClass({ 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 From 229664a624eac2768c6522511431188e00fc81d0 Mon Sep 17 00:00:00 2001 From: wmwragg Date: Fri, 29 Jul 2016 17:49:42 +0100 Subject: [PATCH 32/38] first pass on css re-write --- src/components/views/rooms/RoomTile.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js index 3f6704c2a2..e74647f717 100644 --- a/src/components/views/rooms/RoomTile.js +++ b/src/components/views/rooms/RoomTile.js @@ -229,11 +229,15 @@ module.exports = React.createClass({ return connectDragSource(connectDropTarget(
-
- +
+
+ +
{ label } - { badge } +
+ { badge } +
{ incomingCallBox } { tooltip }
From 1487c600ee5510ba8dd9bd3a2d6166d9d98224bb Mon Sep 17 00:00:00 2001 From: wmwragg Date: Fri, 29 Jul 2016 17:53:18 +0100 Subject: [PATCH 33/38] Revert so that the --- src/components/views/rooms/RoomTile.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js index e74647f717..3f6704c2a2 100644 --- a/src/components/views/rooms/RoomTile.js +++ b/src/components/views/rooms/RoomTile.js @@ -229,15 +229,11 @@ module.exports = React.createClass({ return connectDragSource(connectDropTarget(
-
-
- -
+
+
{ label } -
- { badge } -
+ { badge } { incomingCallBox } { tooltip }
From 398e56c9f9eec489be6b80dd9f208e5185742485 Mon Sep 17 00:00:00 2001 From: wmwragg Date: Sat, 30 Jul 2016 12:28:10 +0100 Subject: [PATCH 34/38] Fixed bug where the long hover tooltip for a room name show an object rather than the name --- src/components/views/rooms/RoomTile.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js index 3f6704c2a2..e31514e015 100644 --- a/src/components/views/rooms/RoomTile.js +++ b/src/components/views/rooms/RoomTile.js @@ -201,9 +201,9 @@ module.exports = React.createClass({ let nameHTML = emojifyText(name); if (this.props.selected) { - name = ; + let nameSelected = ; - label =
{ name }
; + label =
{ nameSelected }
; } else { label =
; } From d16aa276e2a29ea0ece9f5e39e0ef7afe7ed4879 Mon Sep 17 00:00:00 2001 From: wmwragg Date: Sat, 30 Jul 2016 12:52:39 +0100 Subject: [PATCH 35/38] Positional tweaks for the name, badge and context menu, to better match design in both normal and collapsed states --- src/components/views/rooms/RoomTile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js index e31514e015..d6b33b9409 100644 --- a/src/components/views/rooms/RoomTile.js +++ b/src/components/views/rooms/RoomTile.js @@ -120,7 +120,7 @@ module.exports = React.createClass({ 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; + var x = elementRect.right + window.pageXOffset + 3; var y = (elementRect.top + (elementRect.height / 2) + window.pageYOffset) - 53; var self = this; ContextualMenu.createMenu(Menu, { From 2c2f689361d1fa12352acd8555d2db831d30ad61 Mon Sep 17 00:00:00 2001 From: wmwragg Date: Tue, 2 Aug 2016 14:46:47 +0100 Subject: [PATCH 36/38] New design for long names --- src/components/views/rooms/RoomList.js | 6 ++++-- src/components/views/rooms/RoomTile.js | 18 +++++++++++------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index e2bc25653c..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 = (3 + 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 d6b33b9409..5e367ffd80 100644 --- a/src/components/views/rooms/RoomTile.js +++ b/src/components/views/rooms/RoomTile.js @@ -99,7 +99,8 @@ module.exports = React.createClass({ badgeOnMouseEnter: function() { // Only allow none guests to access the context menu - if (!MatrixClientPeg.get().isGuest()) { + // and only change it if it needs to change + if (!MatrixClientPeg.get().isGuest() && !this.state.badgeHover) { this.setState( { badgeHover : true } ); } }, @@ -185,9 +186,9 @@ module.exports = React.createClass({ } if (this.state.areNotifsMuted && !(this.state.badgeHover || this.state.menu)) { - badge =
; + badge =
; } else { - badge =
{ badgeContent }
; + badge =
{ badgeContent }
; } var label; @@ -197,15 +198,16 @@ module.exports = React.createClass({ '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) { let nameSelected = ; - label =
{ nameSelected }
; + label =
{ nameSelected }
; } else { - label =
; + label =
; } } else if (this.state.hover) { @@ -232,8 +234,10 @@ module.exports = React.createClass({
- { label } - { badge } +
+ { label } + { badge } +
{ incomingCallBox } { tooltip }
From 8e19532e5a231c3331bc91e5dadcafc8209ebb46 Mon Sep 17 00:00:00 2001 From: wmwragg Date: Wed, 3 Aug 2016 14:09:10 +0100 Subject: [PATCH 37/38] Hover state for badges, now only on the badges themselves --- src/components/views/rooms/RoomTile.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js index 5e367ffd80..30245f61ee 100644 --- a/src/components/views/rooms/RoomTile.js +++ b/src/components/views/rooms/RoomTile.js @@ -186,9 +186,9 @@ module.exports = React.createClass({ } if (this.state.areNotifsMuted && !(this.state.badgeHover || this.state.menu)) { - badge =
; + badge =
; } else { - badge =
{ badgeContent }
; + badge =
{ badgeContent }
; } var label; @@ -234,7 +234,7 @@ module.exports = React.createClass({
-
+
{ label } { badge }
From c1cfbd6b59ed9b4a7b1eaea7706b11b50aea00fe Mon Sep 17 00:00:00 2001 From: wmwragg Date: Wed, 3 Aug 2016 14:47:53 +0100 Subject: [PATCH 38/38] Corrected comment typo --- src/components/views/rooms/RoomTile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js index 30245f61ee..602ed4ee04 100644 --- a/src/components/views/rooms/RoomTile.js +++ b/src/components/views/rooms/RoomTile.js @@ -66,7 +66,7 @@ module.exports = React.createClass({ onAction: function(payload) { switch (payload.action) { case 'notification_change': - // Is the notificaion about this room + // Is the notification about this room? if (payload.roomId === this.props.room.roomId) { this.setState( { areNotifsMuted : payload.isMuted }); }