From f194f323f4c0ae98dfb8fc9e558516d92e132ada Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 13 Sep 2018 18:43:24 +0200 Subject: [PATCH 1/3] postpone loading the members until the user joined the room when peeking, the members weren't being loaded at all because the room wasn't available yet, and the need for loading the members was never re-evaluated after that. This only loads the members once the user has joined the room, which also helps to avoid load all the members before an invite is accepted. --- src/components/structures/RoomView.js | 28 +++++++----- src/components/views/rooms/MemberList.js | 56 ++++++++++++++++-------- 2 files changed, 56 insertions(+), 28 deletions(-) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 88c1d153eb..3a2a80f06a 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -314,16 +314,6 @@ module.exports = React.createClass({ // Stop peeking because we have joined this room previously MatrixClientPeg.get().stopPeeking(); this.setState({isPeeking: false}); - - // lazy load members if enabled - if (SettingsStore.isFeatureEnabled('feature_lazyloading')) { - room.loadMembersIfNeeded().catch((err) => { - const errorMessage = `Fetching room members for ${room.roomId} failed.` + - " Room members will appear incomplete."; - console.error(errorMessage); - console.error(err); - }); - } } } }, @@ -592,6 +582,23 @@ module.exports = React.createClass({ this._warnAboutEncryption(room); this._calculatePeekRules(room); this._updatePreviewUrlVisibility(room); + this._loadMembersIfJoined(); + }, + + _loadMembersIfJoined: function() { + // lazy load members if enabled + if (SettingsStore.isFeatureEnabled('feature_lazyloading')) { + const cli = MatrixClientPeg.get(); + const room = cli.getRoom(this.state.roomId); + if (room && room.getMyMembership() === 'join') { + room.loadMembersIfNeeded().catch((err) => { + const errorMessage = `Fetching room members for ${room.roomId} failed.` + + " Room members will appear incomplete."; + console.error(errorMessage); + console.error(err); + }); + } + } }, _warnAboutEncryption: function(room) { @@ -705,6 +712,7 @@ module.exports = React.createClass({ onRoomMemberMembership: function(ev, member, oldMembership) { if (member.userId == MatrixClientPeg.get().credentials.userId) { + this._loadMembersIfJoined(); this.forceUpdate(); } }, diff --git a/src/components/views/rooms/MemberList.js b/src/components/views/rooms/MemberList.js index 8d12a8187e..d1eacf5396 100644 --- a/src/components/views/rooms/MemberList.js +++ b/src/components/views/rooms/MemberList.js @@ -46,6 +46,8 @@ module.exports = React.createClass({ if (!cli.hasLazyLoadMembersEnabled()) { this._listenForMembersChanges(); } + cli.on("Room", this.onRoom); // invites & joining after peek + cli.on("RoomMember.membership", this.onRoomMembership); // update when accepting an invite const enablePresenceByHsUrl = SdkConfig.get()["enable_presence_by_hs_url"]; const hsUrl = MatrixClientPeg.get().baseUrl; this._showPresence = true; @@ -59,7 +61,6 @@ module.exports = React.createClass({ cli.on("RoomState.members", this.onRoomStateMember); cli.on("RoomMember.name", this.onRoomMemberName); cli.on("RoomState.events", this.onRoomStateEvent); - cli.on("Room", this.onRoom); // invites // We listen for changes to the lastPresenceTs which is essentially // listening for all presence events (we display most of not all of // the information contained in presence events). @@ -69,14 +70,7 @@ module.exports = React.createClass({ componentDidMount: async function() { this._mounted = true; - const cli = MatrixClientPeg.get(); - if (cli.hasLazyLoadMembersEnabled()) { - await this._waitForMembersToLoad(); - if (this._mounted) { - this.setState(this._getMembersState()); - this._listenForMembersChanges(); - } - } + this._loadMembersIfNeeded(true); }, componentWillUnmount: function() { @@ -85,6 +79,7 @@ module.exports = React.createClass({ if (cli) { cli.removeListener("RoomState.members", this.onRoomStateMember); cli.removeListener("RoomMember.name", this.onRoomMemberName); + cli.removeListener("RoomMember.membership", this.onRoomMembership); cli.removeListener("RoomState.events", this.onRoomStateEvent); cli.removeListener("Room", this.onRoom); cli.removeListener("User.lastPresenceTs", this.onUserLastPresenceTs); @@ -95,14 +90,24 @@ module.exports = React.createClass({ this._updateList.cancelPendingCall(); }, - _waitForMembersToLoad: async function() { - if (!this.props.roomId) return {}; + _loadMembersIfNeeded: async function(initial) { const cli = MatrixClientPeg.get(); - const room = cli.getRoom(this.props.roomId); - if (room) { - try { - await room.loadMembersIfNeeded(); - } catch(ex) {/* already logged in RoomView */} + if (cli.hasLazyLoadMembersEnabled()) { + const cli = MatrixClientPeg.get(); + const room = cli.getRoom(this.props.roomId); + if (room && room.getMyMembership() === 'join') { + this.setState({loading: true}); + try { + await room.loadMembersIfNeeded(); + } catch(ex) {/* already logged in RoomView */} + if (this._mounted) { + this.setState(this._getMembersState()); + this._listenForMembersChanges(); + } + } else if(initial) { + // show the members we've got + this.setState(this._getMembersState()); + } } }, @@ -163,14 +168,28 @@ module.exports = React.createClass({ } }, - onRoom: function(room) { + onRoom: async function(room) { if (room.roomId !== this.props.roomId) { return; } // We listen for room events because when we accept an invite // we need to wait till the room is fully populated with state // before refreshing the member list else we get a stale list. - this._updateList(); + + // also when peeking, we need to await the members being loaded + // before showing them. + + this._loadMembersIfNeeded(); + }, + + onRoomMembership: async function(ev, member, oldMembership) { + const cli = MatrixClientPeg.get(); + const myId = cli.getUserId(); + if (member.userId === myId && oldMembership !== "join" && member.membership === "join") { + // once we've joined, no need to listen for membership anymore + cli.removeListener("RoomMember.membership", this.onRoomMembership); + this._loadMembersIfNeeded(); + } }, onRoomStateMember: function(ev, state, member) { @@ -197,6 +216,7 @@ module.exports = React.createClass({ _updateList: new rate_limited_func(function() { // console.log("Updating memberlist"); const newState = { + loading: false, members: this.roomMembers(), }; newState.filteredJoinedMembers = this._filterMembers(newState.members, 'join', this.state.searchQuery); From fe734b944e6b94804db58a82f91a3ff45f9e2431 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 13 Sep 2018 18:45:38 +0200 Subject: [PATCH 2/3] remove obsolete warning as peeking will cause the membership to be null --- src/stores/RoomListStore.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/stores/RoomListStore.js b/src/stores/RoomListStore.js index 02d728ff2e..5a041f52ac 100644 --- a/src/stores/RoomListStore.js +++ b/src/stores/RoomListStore.js @@ -214,8 +214,6 @@ class RoomListStore extends Store { } } else if (membership === "leave") { lists["im.vector.fake.archived"].push(room); - } else { - console.error("unrecognised membership: " + membership + " - this should never happen"); } }); From 27c496aecb87ce28654e0d0a4a2936e449049885 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 14 Sep 2018 13:55:47 +0200 Subject: [PATCH 3/3] remove unneeded async keywords --- src/components/views/rooms/MemberList.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/rooms/MemberList.js b/src/components/views/rooms/MemberList.js index d1eacf5396..6a00c88d37 100644 --- a/src/components/views/rooms/MemberList.js +++ b/src/components/views/rooms/MemberList.js @@ -168,7 +168,7 @@ module.exports = React.createClass({ } }, - onRoom: async function(room) { + onRoom: function(room) { if (room.roomId !== this.props.roomId) { return; } @@ -182,7 +182,7 @@ module.exports = React.createClass({ this._loadMembersIfNeeded(); }, - onRoomMembership: async function(ev, member, oldMembership) { + onRoomMembership: function(ev, member, oldMembership) { const cli = MatrixClientPeg.get(); const myId = cli.getUserId(); if (member.userId === myId && oldMembership !== "join" && member.membership === "join") {