mirror of
				https://github.com/vector-im/element-web.git
				synced 2025-10-31 16:21:46 +01:00 
			
		
		
		
	Merge remote-tracking branch 'origin/develop' into develop
This commit is contained in:
		
						commit
						520a4ce618
					
				| @ -99,6 +99,10 @@ class MatrixClientPeg { | ||||
|         // the react sdk doesn't work without this, so don't allow
 | ||||
|         opts.pendingEventOrdering = "detached"; | ||||
| 
 | ||||
|         if (SettingsStore.isFeatureEnabled('feature_lazyloading')) { | ||||
|             opts.lazyLoadMembers = true; | ||||
|         } | ||||
| 
 | ||||
|         try { | ||||
|             const promise = this.matrixClient.store.startup(); | ||||
|             console.log(`MatrixClientPeg: waiting for MatrixClient store to initialise`); | ||||
| @ -115,7 +119,7 @@ class MatrixClientPeg { | ||||
|         MatrixActionCreators.start(this.matrixClient); | ||||
| 
 | ||||
|         console.log(`MatrixClientPeg: really starting MatrixClient`); | ||||
|         this.get().startClient(opts); | ||||
|         await this.get().startClient(opts); | ||||
|         console.log(`MatrixClientPeg: MatrixClient started`); | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -194,8 +194,7 @@ function _getDirectMessageRooms(addr) { | ||||
|     const rooms = dmRooms.filter((dmRoom) => { | ||||
|         const room = MatrixClientPeg.get().getRoom(dmRoom); | ||||
|         if (room) { | ||||
|             const me = room.getMember(MatrixClientPeg.get().credentials.userId); | ||||
|             return me && me.membership == 'join'; | ||||
|             return room.getMyMembership() === 'join'; | ||||
|         } | ||||
|     }); | ||||
|     return rooms; | ||||
|  | ||||
							
								
								
									
										52
									
								
								src/Rooms.js
									
									
									
									
									
								
							
							
						
						
									
										52
									
								
								src/Rooms.js
									
									
									
									
									
								
							| @ -31,26 +31,26 @@ export function getDisplayAliasForRoom(room) { | ||||
|  * If the room contains only two members including the logged-in user, | ||||
|  * return the other one. Otherwise, return null. | ||||
|  */ | ||||
| export function getOnlyOtherMember(room, me) { | ||||
|     const joinedMembers = room.getJoinedMembers(); | ||||
| export function getOnlyOtherMember(room, myUserId) { | ||||
| 
 | ||||
|     if (joinedMembers.length === 2) { | ||||
|         return joinedMembers.filter(function(m) { | ||||
|             return m.userId !== me.userId; | ||||
|     if (room.currentState.getJoinedMemberCount() === 2) { | ||||
|         return room.getJoinedMembers().filter(function(m) { | ||||
|             return m.userId !== myUserId; | ||||
|         })[0]; | ||||
|     } | ||||
| 
 | ||||
|     return null; | ||||
| } | ||||
| 
 | ||||
| function _isConfCallRoom(room, me, conferenceHandler) { | ||||
| function _isConfCallRoom(room, myUserId, conferenceHandler) { | ||||
|     if (!conferenceHandler) return false; | ||||
| 
 | ||||
|     if (me.membership != "join") { | ||||
|     const myMembership = room.getMyMembership(); | ||||
|     if (myMembership != "join") { | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     const otherMember = getOnlyOtherMember(room, me); | ||||
|     const otherMember = getOnlyOtherMember(room, myUserId); | ||||
|     if (otherMember === null) { | ||||
|         return false; | ||||
|     } | ||||
| @ -68,29 +68,31 @@ const isConfCallRoomCache = { | ||||
|     // $roomId: bool
 | ||||
| }; | ||||
| 
 | ||||
| export function isConfCallRoom(room, me, conferenceHandler) { | ||||
| export function isConfCallRoom(room, myUserId, conferenceHandler) { | ||||
|     if (isConfCallRoomCache[room.roomId] !== undefined) { | ||||
|         return isConfCallRoomCache[room.roomId]; | ||||
|     } | ||||
| 
 | ||||
|     const result = _isConfCallRoom(room, me, conferenceHandler); | ||||
|     const result = _isConfCallRoom(room, myUserId, conferenceHandler); | ||||
| 
 | ||||
|     isConfCallRoomCache[room.roomId] = result; | ||||
| 
 | ||||
|     return result; | ||||
| } | ||||
| 
 | ||||
| export function looksLikeDirectMessageRoom(room, me) { | ||||
|     if (me.membership == "join" || me.membership === "ban" || | ||||
|         (me.membership === "leave" && me.events.member.getSender() !== me.events.member.getStateKey())) { | ||||
| export function looksLikeDirectMessageRoom(room, myUserId) { | ||||
|     const myMembership = room.getMyMembership(); | ||||
|     const me = room.getMember(myUserId); | ||||
| 
 | ||||
|     if (myMembership == "join" || myMembership === "ban" || (me && me.isKicked())) { | ||||
|         // Used to split rooms via tags
 | ||||
|         const tagNames = Object.keys(room.tags); | ||||
|         // Used for 1:1 direct chats
 | ||||
|         const members = room.currentState.getMembers(); | ||||
| 
 | ||||
|         // Show 1:1 chats in seperate "Direct Messages" section as long as they haven't
 | ||||
|         // been moved to a different tag section
 | ||||
|         if (members.length === 2 && !tagNames.length) { | ||||
|         const totalMemberCount = room.currentState.getJoinedMemberCount() + | ||||
|             room.currentState.getInvitedMemberCount(); | ||||
|         if (totalMemberCount === 2 && !tagNames.length) { | ||||
|             return true; | ||||
|         } | ||||
|     } | ||||
| @ -100,10 +102,10 @@ export function looksLikeDirectMessageRoom(room, me) { | ||||
| export function guessAndSetDMRoom(room, isDirect) { | ||||
|     let newTarget; | ||||
|     if (isDirect) { | ||||
|         const guessedTarget = guessDMRoomTarget( | ||||
|             room, room.getMember(MatrixClientPeg.get().credentials.userId), | ||||
|         const guessedUserId = guessDMRoomTargetId( | ||||
|             room, MatrixClientPeg.get().getUserId() | ||||
|         ); | ||||
|         newTarget = guessedTarget.userId; | ||||
|         newTarget = guessedUserId; | ||||
|     } else { | ||||
|         newTarget = null; | ||||
|     } | ||||
| @ -159,15 +161,15 @@ export function setDMRoom(roomId, userId) { | ||||
|  * Given a room, estimate which of its members is likely to | ||||
|  * be the target if the room were a DM room and return that user. | ||||
|  */ | ||||
| export function guessDMRoomTarget(room, me) { | ||||
| function guessDMRoomTargetId(room, myUserId) { | ||||
|     let oldestTs; | ||||
|     let oldestUser; | ||||
| 
 | ||||
|     // Pick the joined user who's been here longest (and isn't us),
 | ||||
|     for (const user of room.getJoinedMembers()) { | ||||
|         if (user.userId == me.userId) continue; | ||||
|         if (user.userId == myUserId) continue; | ||||
| 
 | ||||
|         if (oldestTs === undefined || user.events.member.getTs() < oldestTs) { | ||||
|         if (oldestTs === undefined || (user.events.member && user.events.member.getTs() < oldestTs)) { | ||||
|             oldestUser = user; | ||||
|             oldestTs = user.events.member.getTs(); | ||||
|         } | ||||
| @ -176,14 +178,14 @@ export function guessDMRoomTarget(room, me) { | ||||
| 
 | ||||
|     // if there are no joined members other than us, use the oldest member
 | ||||
|     for (const user of room.currentState.getMembers()) { | ||||
|         if (user.userId == me.userId) continue; | ||||
|         if (user.userId == myUserId) continue; | ||||
| 
 | ||||
|         if (oldestTs === undefined || user.events.member.getTs() < oldestTs) { | ||||
|         if (oldestTs === undefined || (user.events.member && user.events.member.getTs() < oldestTs)) { | ||||
|             oldestUser = user; | ||||
|             oldestTs = user.events.member.getTs(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if (oldestUser === undefined) return me; | ||||
|     if (oldestUser === undefined) return myUserId; | ||||
|     return oldestUser; | ||||
| } | ||||
|  | ||||
| @ -84,7 +84,7 @@ ConferenceCall.prototype._getConferenceUserRoom = function() { | ||||
|         preset: "private_chat", | ||||
|         invite: [this.confUserId] | ||||
|     }).then(function(res) { | ||||
|         return new Room(res.room_id); | ||||
|         return new Room(res.room_id, null, client.getUserId()); | ||||
|     }); | ||||
| }; | ||||
| 
 | ||||
|  | ||||
| @ -309,9 +309,21 @@ module.exports = React.createClass({ | ||||
|                     } | ||||
|                 }); | ||||
|             } else if (room) { | ||||
|                 //viewing a previously joined room, try to lazy load members
 | ||||
|                  | ||||
|                 // 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 ${this.roomId} failed.` + | ||||
|                             " Room members will appear incomplete."; | ||||
|                         console.error(errorMessage); | ||||
|                         console.error(err); | ||||
|                     }); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
| @ -746,40 +758,13 @@ module.exports = React.createClass({ | ||||
|     }, | ||||
| 
 | ||||
|     _updateDMState() { | ||||
|         const me = this.state.room.getMember(MatrixClientPeg.get().credentials.userId); | ||||
|         if (!me || me.membership !== "join") { | ||||
|         const room = this.state.room; | ||||
|         if (room.getMyMembership() != "join") { | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         // The user may have accepted an invite with is_direct set
 | ||||
|         if (me.events.member.getPrevContent().membership === "invite" && | ||||
|             me.events.member.getPrevContent().is_direct | ||||
|         ) { | ||||
|             // This is a DM with the sender of the invite event (which we assume
 | ||||
|             // preceded the join event)
 | ||||
|             Rooms.setDMRoom( | ||||
|                 this.state.room.roomId, | ||||
|                 me.events.member.getUnsigned().prev_sender, | ||||
|             ); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         const invitedMembers = this.state.room.getMembersWithMembership("invite"); | ||||
|         const joinedMembers = this.state.room.getMembersWithMembership("join"); | ||||
| 
 | ||||
|         // There must be one invited member and one joined member
 | ||||
|         if (invitedMembers.length !== 1 || joinedMembers.length !== 1) { | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         // The user may have sent an invite with is_direct sent
 | ||||
|         const other = invitedMembers[0]; | ||||
|         if (other && | ||||
|             other.membership === "invite" && | ||||
|             other.events.member.getContent().is_direct | ||||
|         ) { | ||||
|             Rooms.setDMRoom(this.state.room.roomId, other.userId); | ||||
|             return; | ||||
|         const dmInviter = room.getDMInviter(); | ||||
|         if (dmInviter) { | ||||
|             Rooms.setDMRoom(room.roomId, dmInviter); | ||||
|         } | ||||
|     }, | ||||
| 
 | ||||
|  | ||||
| @ -844,8 +844,16 @@ module.exports = React.createClass({ | ||||
|         SettingsStore.getLabsFeatures().forEach((featureId) => { | ||||
|             // TODO: this ought to be a separate component so that we don't need
 | ||||
|             // to rebind the onChange each time we render
 | ||||
|             const onChange = (e) => { | ||||
|                 SettingsStore.setFeatureEnabled(featureId, e.target.checked); | ||||
|             const onChange = async (e) => { | ||||
|                 const checked = e.target.checked; | ||||
|                 if (featureId === "feature_lazyloading") { | ||||
|                     const confirmed = await this._onLazyLoadChanging(checked); | ||||
|                     if (!confirmed) { | ||||
|                         e.preventDefault(); | ||||
|                         return; | ||||
|                     } | ||||
|                 } | ||||
|                 await SettingsStore.setFeatureEnabled(featureId, checked); | ||||
|                 this.forceUpdate(); | ||||
|             }; | ||||
| 
 | ||||
| @ -855,7 +863,7 @@ module.exports = React.createClass({ | ||||
|                         type="checkbox" | ||||
|                         id={featureId} | ||||
|                         name={featureId} | ||||
|                         defaultChecked={SettingsStore.isFeatureEnabled(featureId)} | ||||
|                         checked={SettingsStore.isFeatureEnabled(featureId)} | ||||
|                         onChange={onChange} | ||||
|                     /> | ||||
|                     <label htmlFor={featureId}>{ SettingsStore.getDisplayName(featureId) }</label> | ||||
| @ -878,6 +886,30 @@ module.exports = React.createClass({ | ||||
|         ); | ||||
|     }, | ||||
| 
 | ||||
|     _onLazyLoadChanging: async function(enabling) { | ||||
|         // don't prevent turning LL off when not supported
 | ||||
|         if (enabling) { | ||||
|             const supported = await MatrixClientPeg.get().doesServerSupportLazyLoading(); | ||||
|             if (!supported) { | ||||
|                 await new Promise((resolve) => { | ||||
|                     const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); | ||||
|                     Modal.createDialog(QuestionDialog, { | ||||
|                         title: _t("Lazy loading members not supported"), | ||||
|                         description: | ||||
|                             <div> | ||||
|                          { _t("Lazy loading is not supported by your " + | ||||
|                             "current homeserver.") } | ||||
|                             </div>, | ||||
|                         button: _t("OK"), | ||||
|                         onFinished: resolve, | ||||
|                     }); | ||||
|                 }); | ||||
|                 return false; | ||||
|             } | ||||
|         } | ||||
|         return true; | ||||
|     }, | ||||
| 
 | ||||
|     _renderDeactivateAccount: function() { | ||||
|         return <div> | ||||
|             <h3>{ _t("Deactivate Account") }</h3> | ||||
|  | ||||
| @ -54,8 +54,8 @@ export default class ChatCreateOrReuseDialog extends React.Component { | ||||
|         for (const roomId of dmRooms) { | ||||
|             const room = client.getRoom(roomId); | ||||
|             if (room) { | ||||
|                 const me = room.getMember(client.credentials.userId); | ||||
|                 const highlight = room.getUnreadNotificationCount('highlight') > 0 || me.membership === "invite"; | ||||
|                 const isInvite = room.getMyMembership() === "invite"; | ||||
|                 const highlight = room.getUnreadNotificationCount('highlight') > 0 || isInvite; | ||||
|                 tiles.push( | ||||
|                     <RoomTile key={room.roomId} room={room} | ||||
|                         transparent={true} | ||||
| @ -63,7 +63,7 @@ export default class ChatCreateOrReuseDialog extends React.Component { | ||||
|                         selected={false} | ||||
|                         unread={Unread.doesRoomHaveUnreadMessages(room)} | ||||
|                         highlight={highlight} | ||||
|                         isInvite={me.membership === "invite"} | ||||
|                         isInvite={isInvite} | ||||
|                         onClick={this.onRoomTileClick} | ||||
|                     />, | ||||
|                 ); | ||||
|  | ||||
| @ -187,6 +187,9 @@ const Pill = React.createClass({ | ||||
|                 getContent: () => { | ||||
|                     return {avatar_url: resp.avatar_url}; | ||||
|                 }, | ||||
|                 getDirectionalContent: function() { | ||||
|                     return this.getContent(); | ||||
|                 }, | ||||
|             }; | ||||
|             this.setState({member}); | ||||
|         }).catch((err) => { | ||||
|  | ||||
| @ -598,7 +598,7 @@ module.exports = withMatrixClient(React.createClass({ | ||||
| 
 | ||||
|     onMemberAvatarClick: function() { | ||||
|         const member = this.props.member; | ||||
|         const avatarUrl = member.user ? member.user.avatarUrl : member.events.member.getContent().avatar_url; | ||||
|         const avatarUrl = member.getMxcAvatarUrl(); | ||||
|         if (!avatarUrl) return; | ||||
| 
 | ||||
|         const httpUrl = this.props.matrixClient.mxcUrlToHttp(avatarUrl); | ||||
| @ -774,15 +774,15 @@ module.exports = withMatrixClient(React.createClass({ | ||||
|             for (const roomId of dmRooms) { | ||||
|                 const room = this.props.matrixClient.getRoom(roomId); | ||||
|                 if (room) { | ||||
|                     const me = room.getMember(this.props.matrixClient.credentials.userId); | ||||
| 
 | ||||
|                     const myMembership = room.getMyMembership(); | ||||
|                     // not a DM room if we have are not joined
 | ||||
|                     if (!me.membership || me.membership !== 'join') continue; | ||||
|                     // not a DM room if they are not joined
 | ||||
|                     if (myMembership !== 'join') continue; | ||||
|                      | ||||
|                     const them = this.props.member; | ||||
|                     // not a DM room if they are not joined
 | ||||
|                     if (!them.membership || them.membership !== 'join') continue; | ||||
| 
 | ||||
|                     const highlight = room.getUnreadNotificationCount('highlight') > 0 || me.membership === 'invite'; | ||||
|                     const highlight = room.getUnreadNotificationCount('highlight') > 0; | ||||
| 
 | ||||
|                     tiles.push( | ||||
|                         <RoomTile key={room.roomId} room={room} | ||||
| @ -791,7 +791,7 @@ module.exports = withMatrixClient(React.createClass({ | ||||
|                             selected={false} | ||||
|                             unread={Unread.doesRoomHaveUnreadMessages(room)} | ||||
|                             highlight={highlight} | ||||
|                             isInvite={me.membership === "invite"} | ||||
|                             isInvite={false} | ||||
|                             onClick={this.onRoomTileClick} | ||||
|                         />, | ||||
|                     ); | ||||
|  | ||||
| @ -347,8 +347,8 @@ module.exports = React.createClass({ | ||||
|                 if (!taggedRoom) { | ||||
|                     return; | ||||
|                 } | ||||
|                 const me = taggedRoom.getMember(MatrixClientPeg.get().credentials.userId); | ||||
|                 if (HIDE_CONFERENCE_CHANS && Rooms.isConfCallRoom(taggedRoom, me, this.props.ConferenceHandler)) { | ||||
|                 const myUserId = MatrixClientPeg.get().getUserId(); | ||||
|                 if (HIDE_CONFERENCE_CHANS && Rooms.isConfCallRoom(taggedRoom, myUserId, this.props.ConferenceHandler)) { | ||||
|                     return; | ||||
|                 } | ||||
| 
 | ||||
|  | ||||
| @ -98,15 +98,11 @@ module.exports = React.createClass({ | ||||
|             </div>); | ||||
|         } | ||||
| 
 | ||||
|         const myMember = this.props.room ? this.props.room.currentState.members[ | ||||
|             MatrixClientPeg.get().credentials.userId | ||||
|         ] : null; | ||||
|         const kicked = ( | ||||
|             myMember && | ||||
|             myMember.membership == 'leave' && | ||||
|             myMember.events.member.getSender() != MatrixClientPeg.get().credentials.userId | ||||
|         ); | ||||
|         const banned = myMember && myMember.membership == 'ban'; | ||||
|         const myMember = this.props.room ? | ||||
|             this.props.room.getMember(MatrixClientPeg.get().getUserId()) : | ||||
|             null; | ||||
|         const kicked = myMember && myMember.isKicked(); | ||||
|         const banned = myMember && myMember && myMember.membership == 'ban'; | ||||
| 
 | ||||
|         if (this.props.inviterName) { | ||||
|             let emailMatchBlock; | ||||
|  | ||||
| @ -243,9 +243,7 @@ module.exports = React.createClass({ | ||||
|     }, | ||||
| 
 | ||||
|     render: function() { | ||||
|         const myUserId = MatrixClientPeg.get().credentials.userId; | ||||
|         const me = this.props.room.currentState.members[myUserId]; | ||||
| 
 | ||||
|         const isInvite = this.props.room.getMyMembership() === "invite"; | ||||
|         const notificationCount = this.state.notificationCount; | ||||
|         // var highlightCount = this.props.room.getUnreadNotificationCount("highlight");
 | ||||
| 
 | ||||
| @ -259,7 +257,7 @@ module.exports = React.createClass({ | ||||
|             'mx_RoomTile_unread': this.props.unread, | ||||
|             'mx_RoomTile_unreadNotify': notifBadges, | ||||
|             'mx_RoomTile_highlight': mentionBadges, | ||||
|             'mx_RoomTile_invited': (me && me.membership === 'invite'), | ||||
|             'mx_RoomTile_invited': isInvite, | ||||
|             'mx_RoomTile_menuDisplayed': this.state.menuDisplayed, | ||||
|             'mx_RoomTile_noBadges': !badges, | ||||
|             'mx_RoomTile_transparent': this.props.transparent, | ||||
|  | ||||
| @ -43,27 +43,26 @@ export function markAllDevicesKnown(matrixClient, devices) { | ||||
|  * @return {Promise} A promise which resolves to a map userId->deviceId->{@link | ||||
|  * module:crypto~DeviceInfo|DeviceInfo}. | ||||
|  */ | ||||
| export function getUnknownDevicesForRoom(matrixClient, room) { | ||||
|     const roomMembers = room.getEncryptionTargetMembers().map((m) => { | ||||
| export async function getUnknownDevicesForRoom(matrixClient, room) { | ||||
|     const roomMembers = await room.getEncryptionTargetMembers().map((m) => { | ||||
|         return m.userId; | ||||
|     }); | ||||
|     return matrixClient.downloadKeys(roomMembers, false).then((devices) => { | ||||
|         const unknownDevices = {}; | ||||
|         // This is all devices in this room, so find the unknown ones.
 | ||||
|         Object.keys(devices).forEach((userId) => { | ||||
|             Object.keys(devices[userId]).map((deviceId) => { | ||||
|                 const device = devices[userId][deviceId]; | ||||
|     const devices = await matrixClient.downloadKeys(roomMembers, false); | ||||
|     const unknownDevices = {}; | ||||
|     // This is all devices in this room, so find the unknown ones.
 | ||||
|     Object.keys(devices).forEach((userId) => { | ||||
|         Object.keys(devices[userId]).map((deviceId) => { | ||||
|             const device = devices[userId][deviceId]; | ||||
| 
 | ||||
|                 if (device.isUnverified() && !device.isKnown()) { | ||||
|                     if (unknownDevices[userId] === undefined) { | ||||
|                         unknownDevices[userId] = {}; | ||||
|                     } | ||||
|                     unknownDevices[userId][deviceId] = device; | ||||
|             if (device.isUnverified() && !device.isKnown()) { | ||||
|                 if (unknownDevices[userId] === undefined) { | ||||
|                     unknownDevices[userId] = {}; | ||||
|                 } | ||||
|             }); | ||||
|                 unknownDevices[userId][deviceId] = device; | ||||
|             } | ||||
|         }); | ||||
|         return unknownDevices; | ||||
|     }); | ||||
|     return unknownDevices; | ||||
| } | ||||
| 
 | ||||
| function focusComposer() { | ||||
|  | ||||
| @ -1231,5 +1231,8 @@ | ||||
|     "Import": "Import", | ||||
|     "Failed to set direct chat tag": "Failed to set direct chat tag", | ||||
|     "Failed to remove tag %(tagName)s from room": "Failed to remove tag %(tagName)s from room", | ||||
|     "Failed to add tag %(tagName)s to room": "Failed to add tag %(tagName)s to room" | ||||
|     "Failed to add tag %(tagName)s to room": "Failed to add tag %(tagName)s to room", | ||||
|     "Increase performance by only loading room members on first view": "Increase performance by only loading room members on first view", | ||||
|     "Lazy loading members not supported": "Lazy load members not supported", | ||||
|     "Lazy loading is not supported by your current homeserver.": "Lazy loading is not supported by your current homeserver." | ||||
| } | ||||
|  | ||||
| @ -21,7 +21,7 @@ import { | ||||
|     NotificationBodyEnabledController, | ||||
|     NotificationsEnabledController, | ||||
| } from "./controllers/NotificationControllers"; | ||||
| 
 | ||||
| import LazyLoadingController from "./controllers/LazyLoadingController"; | ||||
| 
 | ||||
| // These are just a bunch of helper arrays to avoid copy/pasting a bunch of times
 | ||||
| const LEVELS_ROOM_SETTINGS = ['device', 'room-device', 'room-account', 'account', 'config']; | ||||
| @ -83,6 +83,13 @@ export const SETTINGS = { | ||||
|         supportedLevels: LEVELS_FEATURE, | ||||
|         default: false, | ||||
|     }, | ||||
|     "feature_lazyloading": { | ||||
|         isFeature: true, | ||||
|         displayName: _td("Increase performance by only loading room members on first view"), | ||||
|         supportedLevels: LEVELS_FEATURE, | ||||
|         controller: new LazyLoadingController(), | ||||
|         default: false, | ||||
|     }, | ||||
|     "MessageComposerInput.dontSuggestEmoji": { | ||||
|         supportedLevels: LEVELS_ACCOUNT_SETTINGS, | ||||
|         displayName: _td('Disable Emoji suggestions while typing'), | ||||
|  | ||||
| @ -248,7 +248,7 @@ export default class SettingsStore { | ||||
|         if (actualValue !== undefined && actualValue !== null) return actualValue; | ||||
|         return calculatedValue; | ||||
|     } | ||||
| 
 | ||||
|     /* eslint-disable valid-jsdoc */    //https://github.com/eslint/eslint/issues/7307
 | ||||
|     /** | ||||
|      * Sets the value for a setting. The room ID is optional if the setting is not being | ||||
|      * set for a particular room, otherwise it should be supplied. The value may be null | ||||
| @ -260,7 +260,8 @@ export default class SettingsStore { | ||||
|      * @param {*} value The new value of the setting, may be null. | ||||
|      * @return {Promise} Resolves when the setting has been changed. | ||||
|      */ | ||||
|     static setValue(settingName, roomId, level, value) { | ||||
|     /* eslint-enable valid-jsdoc */ | ||||
|     static async setValue(settingName, roomId, level, value) { | ||||
|         // Verify that the setting is actually a setting
 | ||||
|         if (!SETTINGS[settingName]) { | ||||
|             throw new Error("Setting '" + settingName + "' does not appear to be a setting."); | ||||
| @ -275,11 +276,12 @@ export default class SettingsStore { | ||||
|             throw new Error("User cannot set " + settingName + " at " + level + " in " + roomId); | ||||
|         } | ||||
| 
 | ||||
|         return handler.setValue(settingName, roomId, value).then(() => { | ||||
|             const controller = SETTINGS[settingName].controller; | ||||
|             if (!controller) return; | ||||
|         await handler.setValue(settingName, roomId, value); | ||||
| 
 | ||||
|         const controller = SETTINGS[settingName].controller; | ||||
|         if (controller) { | ||||
|             controller.onChange(level, roomId, value); | ||||
|         }); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
							
								
								
									
										29
									
								
								src/settings/controllers/LazyLoadingController.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/settings/controllers/LazyLoadingController.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,29 @@ | ||||
| /* | ||||
| Copyright 2018 New Vector | ||||
| 
 | ||||
| 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. | ||||
| */ | ||||
| 
 | ||||
| import SettingController from "./SettingController"; | ||||
| import MatrixClientPeg from "../../MatrixClientPeg"; | ||||
| import PlatformPeg from "../../PlatformPeg"; | ||||
| 
 | ||||
| export default class LazyLoadingController extends SettingController { | ||||
|     async onChange(level, roomId, newValue) { | ||||
|         if (!PlatformPeg.get()) return; | ||||
| 
 | ||||
|         MatrixClientPeg.get().stopClient(); | ||||
|         await MatrixClientPeg.get().store.deleteAllData(); | ||||
|         PlatformPeg.get().reload(); | ||||
|     } | ||||
| } | ||||
| @ -175,13 +175,13 @@ class RoomListStore extends Store { | ||||
|         if (!this._matrixClient) return; | ||||
| 
 | ||||
|         this._matrixClient.getRooms().forEach((room, index) => { | ||||
|             const me = room.getMember(this._matrixClient.credentials.userId); | ||||
|             if (!me) return; | ||||
|             const myUserId = this._matrixClient.getUserId(); | ||||
|             const membership = room.getMyMembership(); | ||||
|             const me = room.getMember(myUserId); | ||||
| 
 | ||||
|             if (me.membership == "invite") { | ||||
|             if (membership == "invite") { | ||||
|                 lists["im.vector.fake.invite"].push(room); | ||||
|             } else if (me.membership == "join" || me.membership === "ban" || | ||||
|                      (me.membership === "leave" && me.events.member.getSender() !== me.events.member.getStateKey())) { | ||||
|             } else if (membership == "join" || membership === "ban" || (me && me.isKicked())) { | ||||
|                 // Used to split rooms via tags
 | ||||
|                 let tagNames = Object.keys(room.tags); | ||||
| 
 | ||||
| @ -213,10 +213,10 @@ class RoomListStore extends Store { | ||||
|                 } else { | ||||
|                     lists["im.vector.fake.recent"].push(room); | ||||
|                 } | ||||
|             } else if (me.membership === "leave") { | ||||
|             } else if (membership === "leave") { | ||||
|                 lists["im.vector.fake.archived"].push(room); | ||||
|             } else { | ||||
|                 console.error("unrecognised membership: " + me.membership + " - this should never happen"); | ||||
|                 console.error("unrecognised membership: " + membership + " - this should never happen"); | ||||
|             } | ||||
|         }); | ||||
| 
 | ||||
|  | ||||
| @ -97,14 +97,7 @@ export default class DMRoomMap { | ||||
|             // no entry? if the room is an invite, look for the is_direct hint.
 | ||||
|             const room = this.matrixClient.getRoom(roomId); | ||||
|             if (room) { | ||||
|                 const me = room.getMember(this.matrixClient.credentials.userId); | ||||
|                 if (me.membership == 'invite') { | ||||
|                     // The 'direct' hihnt is there, so declare that this is a DM room for
 | ||||
|                     // whoever invited us.
 | ||||
|                     if (me.events.member.getContent().is_direct) { | ||||
|                         return me.events.member.getSender(); | ||||
|                     } | ||||
|                 } | ||||
|                 return room.getDMInviter(); | ||||
|             } | ||||
|         } | ||||
|         return this.roomToUser[roomId]; | ||||
|  | ||||
| @ -77,8 +77,7 @@ export default class WidgetUtils { | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         const member = room.getMember(me); | ||||
|         if (!member || member.membership !== "join") { | ||||
|         if (room.getMyMembership() !== "join") { | ||||
|             console.warn(`User ${me} is not in room ${roomId}`); | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
| @ -14,21 +14,22 @@ import dis from '../../../../src/dispatcher'; | ||||
| import DMRoomMap from '../../../../src/utils/DMRoomMap.js'; | ||||
| import GroupStore from '../../../../src/stores/GroupStore.js'; | ||||
| 
 | ||||
| import { Room, RoomMember } from 'matrix-js-sdk'; | ||||
| import { MatrixClient, Room, RoomMember } from 'matrix-js-sdk'; | ||||
| 
 | ||||
| function generateRoomId() { | ||||
|     return '!' + Math.random().toString().slice(2, 10) + ':domain'; | ||||
| } | ||||
| 
 | ||||
| function createRoom(opts) { | ||||
|     const room = new Room(generateRoomId()); | ||||
|     if (opts) { | ||||
|         Object.assign(room, opts); | ||||
|     } | ||||
|     return room; | ||||
| } | ||||
| 
 | ||||
| describe('RoomList', () => { | ||||
|     function createRoom(opts) { | ||||
|         const room = new Room(generateRoomId(), null, client.getUserId()); | ||||
|         if (opts) { | ||||
|             Object.assign(room, opts); | ||||
|         } | ||||
|         return room; | ||||
|     } | ||||
| 
 | ||||
|     let parentDiv = null; | ||||
|     let sandbox = null; | ||||
|     let client = null; | ||||
| @ -48,6 +49,8 @@ describe('RoomList', () => { | ||||
|         sandbox = TestUtils.stubClient(sandbox); | ||||
|         client = MatrixClientPeg.get(); | ||||
|         client.credentials = {userId: myUserId}; | ||||
|         //revert this to prototype method as the test-utils monkey-patches this to return a hardcoded value
 | ||||
|         client.getUserId = MatrixClient.prototype.getUserId; | ||||
| 
 | ||||
|         clock = lolex.install(); | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user