From 4ecf5f637225c21e01652d1e8f733d4f2edc2939 Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 26 Jul 2016 17:58:19 +0100 Subject: [PATCH 1/3] Fix bug where vector freezes on power level event Make rate_limited_function accept functions with args so we can just ratelimit the event handler & be done with it. Fixes https://github.com/vector-im/vector-web/issues/1877 --- src/components/structures/RoomView.js | 6 ++++-- src/ratelimitedfunc.js | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index accf96f349..9aa192d9ca 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -482,7 +482,9 @@ module.exports = React.createClass({ } }, - onRoomStateMember: function(ev, state, member) { + // rate limited because a power level change will emit an event for every + // member in the room. + onRoomStateMember: new rate_limited_func(function(ev, state, member) { // ignore if we don't have a room yet if (!this.state.room) { return; @@ -511,7 +513,7 @@ module.exports = React.createClass({ member.userId === this.props.ConferenceHandler.getConferenceUserIdForRoom(member.roomId)) { this._updateConfCallNotification(); } - }, + }, 500), _hasUnsentMessages: function(room) { return this._getUnsentMessages(room).length > 0; diff --git a/src/ratelimitedfunc.js b/src/ratelimitedfunc.js index 453669b477..94626d5ad9 100644 --- a/src/ratelimitedfunc.js +++ b/src/ratelimitedfunc.js @@ -23,13 +23,13 @@ module.exports = function(f, minIntervalMs) { var now = Date.now(); if (self.lastCall < now - minIntervalMs) { - f.apply(this); + f.apply(this, arguments); self.lastCall = now; } else if (self.scheduledCall === undefined) { self.scheduledCall = setTimeout( () => { self.scheduledCall = undefined; - f.apply(this); + f.apply(this, arguments); self.lastCall = now; }, (self.lastCall + minIntervalMs) - now From 31399254b62c49200f3d7cb04ca7ebb40cb52fda Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 26 Jul 2016 18:15:26 +0100 Subject: [PATCH 2/3] Fix onRoomStateMember debouncing Don't have debounced functions take arsg, because they won't be the same for each invocation. --- src/components/structures/RoomView.js | 18 ++++++++++-------- src/ratelimitedfunc.js | 12 ++++++++++-- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 9aa192d9ca..6d35f76529 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -482,9 +482,7 @@ module.exports = React.createClass({ } }, - // rate limited because a power level change will emit an event for every - // member in the room. - onRoomStateMember: new rate_limited_func(function(ev, state, member) { + onRoomStateMember: function(ev, state, member) { // ignore if we don't have a room yet if (!this.state.room) { return; @@ -495,6 +493,15 @@ module.exports = React.createClass({ return; } + if (this.props.ConferenceHandler && + member.userId === this.props.ConferenceHandler.getConferenceUserIdForRoom(member.roomId)) { + this._updateConfCallNotification(); + } + + this._updateRoomMembers(); + }, + + _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(); @@ -508,11 +515,6 @@ module.exports = React.createClass({ joining: false }); } - - if (this.props.ConferenceHandler && - member.userId === this.props.ConferenceHandler.getConferenceUserIdForRoom(member.roomId)) { - this._updateConfCallNotification(); - } }, 500), _hasUnsentMessages: function(room) { diff --git a/src/ratelimitedfunc.js b/src/ratelimitedfunc.js index 94626d5ad9..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; @@ -23,13 +31,13 @@ module.exports = function(f, minIntervalMs) { var now = Date.now(); if (self.lastCall < now - minIntervalMs) { - f.apply(this, arguments); + f.apply(this); self.lastCall = now; } else if (self.scheduledCall === undefined) { self.scheduledCall = setTimeout( () => { self.scheduledCall = undefined; - f.apply(this, arguments); + f.apply(this); self.lastCall = now; }, (self.lastCall + minIntervalMs) - now From 09993cd3bcc737c6b33b2d836bebe7342d879092 Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 26 Jul 2016 18:19:25 +0100 Subject: [PATCH 3/3] Add comment back --- src/components/structures/RoomView.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 6d35f76529..9fbdb51f11 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -501,6 +501,8 @@ module.exports = React.createClass({ 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);