From 3ff19dc4db18db52ac4fc8651366a7f7db46b1bc Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Thu, 17 Dec 2015 14:14:26 +0000 Subject: [PATCH 1/7] Fix issue with rooms not scrolling down when new events arrive Remove an optimisation which tried to avoid recalculating the scroll on every render. The problem is that sometimes, when new events, the number of event tiles remains the same, but we still need to do a scroll, because the height of the message list changes. The optimisation was a bit of a waste of time anyway - the actual render will always be much more difficult than recalculating the scroll position. --- src/components/structures/RoomView.js | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index a7944f91f5..2e8a39aae9 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -318,11 +318,7 @@ module.exports = React.createClass({ if (this.state.searchResults) return; - if (this.needsScrollReset) { - if (DEBUG_SCROLL) console.log("Resetting scroll position after tile count change"); - this._restoreSavedScrollState(); - this.needsScrollReset = false; - } + this._restoreSavedScrollState(); // have to fill space in case we're accepting an invite if (!this.state.paginating) this.fillSpace(); @@ -683,10 +679,6 @@ module.exports = React.createClass({ } ++count; } - if (count != this.lastEventTileCount) { - if (DEBUG_SCROLL) console.log("Queuing scroll reset (event count changed; now "+count+"; was "+this.lastEventTileCount+")"); - this.needsScrollReset = true; - } this.lastEventTileCount = count; return ret; }, From 1eeb732625632e1b676bb72d96143786b3b55e42 Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Thu, 17 Dec 2015 14:34:45 +0000 Subject: [PATCH 2/7] Supply bind_email=true at registration time - required for 3pid invites to work. --- src/Signup.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Signup.js b/src/Signup.js index 02ddaacc6d..74c4ad5f19 100644 --- a/src/Signup.js +++ b/src/Signup.js @@ -116,8 +116,17 @@ class Register extends Signup { _tryRegister(authDict) { var self = this; + + var bindEmail; + + if (this.username && this.password) { + // only need to bind_email when sending u/p - sending it at other + // times clobbers the u/p resulting in M_MISSING_PARAM (password) + bindEmail = true; + } + return MatrixClientPeg.get().register( - this.username, this.password, this.params.sessionId, authDict + this.username, this.password, this.params.sessionId, authDict, bindEmail ).then(function(result) { self.credentials = result; self.setStep("COMPLETE"); From 32bd9d155cfd00e1e0a66d050f1bd2d0e5d5e98e Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Thu, 17 Dec 2015 14:56:55 +0000 Subject: [PATCH 3/7] Pass a new prop 'startingQueryParams' to pluck out the email from the URL This is preferable to doing the way other QPs are passed (secret, etc) because the link in the email wants to look like "#/room/" for guest read-access (only bouncing you to /login if that room is not readable by guests). This is hard to do in the current arch because we don't preserve QPs on /room paths, and we do conditional executions depending on if it is a room ID or alias. Rather than threading through the email in each section and creating a fragile mess, just pass the *starting* set of query parameters through to MatrixChat which can then do the Right Thing when the time comes. --- src/components/structures/MatrixChat.js | 14 +++++++++++--- src/components/structures/login/Registration.js | 2 ++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index f2424dc06e..f38c75d676 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -41,7 +41,8 @@ module.exports = React.createClass({ config: React.PropTypes.object.isRequired, ConferenceHandler: React.PropTypes.any, onNewScreen: React.PropTypes.func, - registrationUrl: React.PropTypes.string + registrationUrl: React.PropTypes.string, + startingQueryParams: React.PropTypes.object }, PageTypes: { @@ -75,6 +76,12 @@ module.exports = React.createClass({ return s; }, + getDefaultProps: function() { + return { + startingQueryParams: {} + }; + }, + componentDidMount: function() { this.dispatcherRef = dis.register(this.onAction); if (this.state.logged_in) { @@ -540,9 +547,9 @@ module.exports = React.createClass({ } }, - notifyNewScreen: function(screen) { + notifyNewScreen: function(screen, queryParamString) { if (this.props.onNewScreen) { - this.props.onNewScreen(screen); + this.props.onNewScreen(screen, queryParamString); } }, @@ -706,6 +713,7 @@ module.exports = React.createClass({ clientSecret={this.state.register_client_secret} sessionId={this.state.register_session_id} idSid={this.state.register_id_sid} + email={this.props.startingQueryParams.email} hsUrl={this.props.config.default_hs_url} isUrl={this.props.config.default_is_url} registrationUrl={this.props.registrationUrl} diff --git a/src/components/structures/login/Registration.js b/src/components/structures/login/Registration.js index 1570641556..19e55c4d76 100644 --- a/src/components/structures/login/Registration.js +++ b/src/components/structures/login/Registration.js @@ -39,6 +39,7 @@ module.exports = React.createClass({ idSid: React.PropTypes.string, hsUrl: React.PropTypes.string, isUrl: React.PropTypes.string, + email: React.PropTypes.string, // registration shouldn't know or care how login is done. onLoginClick: React.PropTypes.func.isRequired }, @@ -185,6 +186,7 @@ module.exports = React.createClass({ registerStep = ( From 6e324a0dd159afadc2f626333f489a07e50dfcf4 Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Thu, 17 Dec 2015 15:12:09 +0000 Subject: [PATCH 4/7] Whoops, didn't mean to add this --- src/components/structures/MatrixChat.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index f38c75d676..8ad5b44762 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -547,9 +547,9 @@ module.exports = React.createClass({ } }, - notifyNewScreen: function(screen, queryParamString) { + notifyNewScreen: function(screen) { if (this.props.onNewScreen) { - this.props.onNewScreen(screen, queryParamString); + this.props.onNewScreen(screen); } }, From 17a8eb010996d1235c803b36b668f9113356c8b5 Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Thu, 17 Dec 2015 15:48:14 +0000 Subject: [PATCH 5/7] Display m.room.third_party_invite events. Display sensible text transitions. --- src/TextForEvent.js | 18 +++++++++++++++++- src/components/views/rooms/EventTile.js | 1 + 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/TextForEvent.js b/src/TextForEvent.js index 439d7b9ef5..22ada8849e 100644 --- a/src/TextForEvent.js +++ b/src/TextForEvent.js @@ -9,7 +9,16 @@ function textForMemberEvent(ev) { ) : ""; switch (ev.getContent().membership) { case 'invite': - return senderName + " invited " + targetName + "."; + var threePidContent = ev.getContent().third_party_invite; + if (threePidContent) { + // TODO: When we have third_party_invite.display_name we should + // do this as "$displayname received the invitation from $sender" + // or equiv + return targetName + " received an invitation from " + senderName; + } + else { + return senderName + " invited " + targetName + "."; + } case 'ban': return senderName + " banned " + targetName + "." + reason; case 'join': @@ -101,6 +110,12 @@ function textForCallInviteEvent(event) { return senderName + " placed a " + type + " call." + supported; }; +function textForThreePidInviteEvent(event) { + var senderName = event.sender ? event.sender.name : event.getSender(); + return senderName + " sent an invitation to " + event.getContent().display_name + + " to join the room."; +}; + var handlers = { 'm.room.message': textForMessageEvent, 'm.room.name': textForRoomNameEvent, @@ -109,6 +124,7 @@ var handlers = { 'm.call.invite': textForCallInviteEvent, 'm.call.answer': textForCallAnswerEvent, 'm.call.hangup': textForCallHangupEvent, + 'm.room.third_party_invite': textForThreePidInviteEvent }; module.exports = { diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js index 8292cdf826..0b26000207 100644 --- a/src/components/views/rooms/EventTile.js +++ b/src/components/views/rooms/EventTile.js @@ -44,6 +44,7 @@ var eventTileTypes = { 'm.call.hangup' : 'messages.TextualEvent', 'm.room.name' : 'messages.TextualEvent', 'm.room.topic' : 'messages.TextualEvent', + 'm.room.third_party_invite': 'messages.TextualEvent' }; var MAX_READ_AVATARS = 5; From 12943b11fc3c46cc09c5a86fe0ff310b1ec9b9c7 Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Thu, 17 Dec 2015 16:40:46 +0000 Subject: [PATCH 6/7] Full Stop. --- src/TextForEvent.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/TextForEvent.js b/src/TextForEvent.js index 22ada8849e..5296ef833e 100644 --- a/src/TextForEvent.js +++ b/src/TextForEvent.js @@ -14,7 +14,8 @@ function textForMemberEvent(ev) { // TODO: When we have third_party_invite.display_name we should // do this as "$displayname received the invitation from $sender" // or equiv - return targetName + " received an invitation from " + senderName; + return targetName + " received an invitation from " + senderName + + "."; } else { return senderName + " invited " + targetName + "."; From 0f82b72e075f91d8adca122edfc30d16cd038690 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Fri, 18 Dec 2015 00:13:49 +0000 Subject: [PATCH 7/7] lost copyright --- src/Resend.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/Resend.js b/src/Resend.js index 0e67a306bd..e07e571455 100644 --- a/src/Resend.js +++ b/src/Resend.js @@ -1,3 +1,19 @@ +/* +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. +*/ + var MatrixClientPeg = require('./MatrixClientPeg'); var dis = require('./dispatcher');