Merge remote-tracking branch 'origin/develop' into develop

This commit is contained in:
Weblate 2018-01-17 17:10:55 +00:00
commit 816a77c089

View file

@ -19,6 +19,14 @@ import { groupMemberFromApiObject, groupRoomFromApiObject } from '../groups';
import FlairStore from './FlairStore'; import FlairStore from './FlairStore';
import MatrixClientPeg from '../MatrixClientPeg'; import MatrixClientPeg from '../MatrixClientPeg';
function parseMembersResponse(response) {
return response.chunk.map((apiMember) => groupMemberFromApiObject(apiMember));
}
function parseRoomsResponse(response) {
return response.chunk.map((apiRoom) => groupRoomFromApiObject(apiRoom));
}
/** /**
* Stores the group summary for a room and provides an API to change it and * Stores the group summary for a room and provides an API to change it and
* other useful group APIs that may have an effect on the group summary. * other useful group APIs that may have an effect on the group summary.
@ -38,65 +46,68 @@ export default class GroupStore extends EventEmitter {
throw new Error('GroupStore needs a valid groupId to be created'); throw new Error('GroupStore needs a valid groupId to be created');
} }
this.groupId = groupId; this.groupId = groupId;
this._summary = {}; this._state = {};
this._rooms = []; this._state[GroupStore.STATE_KEY.Summary] = {};
this._members = []; this._state[GroupStore.STATE_KEY.GroupRooms] = [];
this._invitedMembers = []; this._state[GroupStore.STATE_KEY.GroupMembers] = [];
this._state[GroupStore.STATE_KEY.GroupInvitedMembers] = [];
this._ready = {}; this._ready = {};
this._fetchResourcePromise = {};
this._resourceFetcher = {
[GroupStore.STATE_KEY.Summary]: () => {
return MatrixClientPeg.get()
.getGroupSummary(this.groupId);
},
[GroupStore.STATE_KEY.GroupRooms]: () => {
return MatrixClientPeg.get()
.getGroupRooms(this.groupId)
.then(parseRoomsResponse);
},
[GroupStore.STATE_KEY.GroupMembers]: () => {
return MatrixClientPeg.get()
.getGroupUsers(this.groupId)
.then(parseMembersResponse);
},
[GroupStore.STATE_KEY.GroupInvitedMembers]: () => {
return MatrixClientPeg.get()
.getGroupInvitedUsers(this.groupId)
.then(parseMembersResponse);
},
};
this.on('error', (err) => { this.on('error', (err) => {
console.error(`GroupStore for ${this.groupId} encountered error`, err); console.error(`GroupStore for ${this.groupId} encountered error`, err);
}); });
} }
_fetchMembers() { _fetchResource(stateKey) {
MatrixClientPeg.get().getGroupUsers(this.groupId).then((result) => { // Ongoing request, ignore
this._members = result.chunk.map((apiMember) => { if (this._fetchResourcePromise[stateKey]) return;
return groupMemberFromApiObject(apiMember);
});
this._ready[GroupStore.STATE_KEY.GroupMembers] = true;
this._notifyListeners();
}).catch((err) => {
console.error("Failed to get group member list: " + err);
this.emit('error', err);
});
MatrixClientPeg.get().getGroupInvitedUsers(this.groupId).then((result) => { const clientPromise = this._resourceFetcher[stateKey]();
this._invitedMembers = result.chunk.map((apiMember) => {
return groupMemberFromApiObject(apiMember); // Indicate ongoing request
}); this._fetchResourcePromise[stateKey] = clientPromise;
this._ready[GroupStore.STATE_KEY.GroupInvitedMembers] = true;
clientPromise.then((result) => {
this._state[stateKey] = result;
this._ready[stateKey] = true;
this._notifyListeners(); this._notifyListeners();
}).catch((err) => { }).catch((err) => {
// Invited users not visible to non-members // Invited users not visible to non-members
if (err.httpStatus === 403) { if (stateKey === GroupStore.STATE_KEY.GroupInvitedMembers && err.httpStatus === 403) {
return; return;
} }
console.error("Failed to get group invited member list: " + err);
this.emit('error', err);
});
}
_fetchSummary() { console.error("Failed to get resource " + stateKey + ":" + err);
MatrixClientPeg.get().getGroupSummary(this.groupId).then((resp) => {
this._summary = resp;
this._ready[GroupStore.STATE_KEY.Summary] = true;
this._notifyListeners();
}).catch((err) => {
this.emit('error', err); this.emit('error', err);
}).finally(() => {
// Indicate finished request, allow for future fetches
delete this._fetchResourcePromise[stateKey];
}); });
}
_fetchRooms() { return clientPromise;
MatrixClientPeg.get().getGroupRooms(this.groupId).then((resp) => {
this._rooms = resp.chunk.map((apiRoom) => {
return groupRoomFromApiObject(apiRoom);
});
this._ready[GroupStore.STATE_KEY.GroupRooms] = true;
this._notifyListeners();
}).catch((err) => {
this.emit('error', err);
});
} }
_notifyListeners() { _notifyListeners() {
@ -108,10 +119,9 @@ export default class GroupStore extends EventEmitter {
* immediately triggers an update to send the current state of the * immediately triggers an update to send the current state of the
* store (which could be the initial state). * store (which could be the initial state).
* *
* XXX: This also causes a fetch of all group data, which effectively * This also causes a fetch of all group data, which might cause
* causes 4 separate HTTP requests. This is bad, we should at least * 4 separate HTTP requests, but only said requests aren't already
* deduplicate these in order to fix: * ongoing.
* https://github.com/vector-im/riot-web/issues/5901
* *
* @param {function} fn the function to call when the store updates. * @param {function} fn the function to call when the store updates.
* @return {Object} tok a registration "token" with a single * @return {Object} tok a registration "token" with a single
@ -123,9 +133,11 @@ export default class GroupStore extends EventEmitter {
this.on('update', fn); this.on('update', fn);
// Call to set initial state (before fetching starts) // Call to set initial state (before fetching starts)
this.emit('update'); this.emit('update');
this._fetchSummary();
this._fetchRooms(); this._fetchResource(GroupStore.STATE_KEY.Summary);
this._fetchMembers(); this._fetchResource(GroupStore.STATE_KEY.GroupRooms);
this._fetchResource(GroupStore.STATE_KEY.GroupMembers);
this._fetchResource(GroupStore.STATE_KEY.GroupInvitedMembers);
// Similar to the Store of flux/utils, we return a "token" that // Similar to the Store of flux/utils, we return a "token" that
// can be used to unregister the listener. // can be used to unregister the listener.
@ -145,90 +157,94 @@ export default class GroupStore extends EventEmitter {
} }
getSummary() { getSummary() {
return this._summary; return this._state[GroupStore.STATE_KEY.Summary];
} }
getGroupRooms() { getGroupRooms() {
return this._rooms; return this._state[GroupStore.STATE_KEY.GroupRooms];
} }
getGroupMembers( ) { getGroupMembers() {
return this._members; return this._state[GroupStore.STATE_KEY.GroupMembers];
} }
getGroupInvitedMembers( ) { getGroupInvitedMembers() {
return this._invitedMembers; return this._state[GroupStore.STATE_KEY.GroupInvitedMembers];
} }
getGroupPublicity() { getGroupPublicity() {
return this._summary.user ? this._summary.user.is_publicised : null; return this._state[GroupStore.STATE_KEY.Summary].user ?
this._state[GroupStore.STATE_KEY.Summary].user.is_publicised : null;
} }
isUserPrivileged() { isUserPrivileged() {
return this._summary.user ? this._summary.user.is_privileged : null; return this._state[GroupStore.STATE_KEY.Summary].user ?
this._state[GroupStore.STATE_KEY.Summary].user.is_privileged : null;
} }
addRoomToGroup(roomId, isPublic) { addRoomToGroup(roomId, isPublic) {
return MatrixClientPeg.get() return MatrixClientPeg.get()
.addRoomToGroup(this.groupId, roomId, isPublic) .addRoomToGroup(this.groupId, roomId, isPublic)
.then(this._fetchRooms.bind(this)); .then(this._fetchResource.bind(this, GroupStore.STATE_KEY.GroupRooms));
} }
updateGroupRoomVisibility(roomId, isPublic) { updateGroupRoomVisibility(roomId, isPublic) {
return MatrixClientPeg.get() return MatrixClientPeg.get()
.updateGroupRoomVisibility(this.groupId, roomId, isPublic) .updateGroupRoomVisibility(this.groupId, roomId, isPublic)
.then(this._fetchRooms.bind(this)); .then(this._fetchResource.bind(this, GroupStore.STATE_KEY.GroupRooms));
} }
removeRoomFromGroup(roomId) { removeRoomFromGroup(roomId) {
return MatrixClientPeg.get() return MatrixClientPeg.get()
.removeRoomFromGroup(this.groupId, roomId) .removeRoomFromGroup(this.groupId, roomId)
// Room might be in the summary, refresh just in case // Room might be in the summary, refresh just in case
.then(this._fetchSummary.bind(this)) .then(this._fetchResource.bind(this, GroupStore.STATE_KEY.Summary))
.then(this._fetchRooms.bind(this)); .then(this._fetchResource.bind(this, GroupStore.STATE_KEY.GroupRooms));
} }
inviteUserToGroup(userId) { inviteUserToGroup(userId) {
return MatrixClientPeg.get().inviteUserToGroup(this.groupId, userId) return MatrixClientPeg.get().inviteUserToGroup(this.groupId, userId)
.then(this._fetchMembers.bind(this)); .then(this._fetchResource.bind(this, GroupStore.STATE_KEY.GroupInvitedMembers));
} }
acceptGroupInvite() { acceptGroupInvite() {
return MatrixClientPeg.get().acceptGroupInvite(this.groupId) return MatrixClientPeg.get().acceptGroupInvite(this.groupId)
// The user might be able to see more rooms now // The user might be able to see more rooms now
.then(this._fetchRooms.bind(this)) .then(this._fetchResource.bind(this, GroupStore.STATE_KEY.GroupRooms))
// The user should now appear as a member // The user should now appear as a member
.then(this._fetchMembers.bind(this)); .then(this._fetchResource.bind(this, GroupStore.STATE_KEY.GroupMembers))
// The user should now not appear as an invited member
.then(this._fetchResource.bind(this, GroupStore.STATE_KEY.GroupInvitedMembers));
} }
addRoomToGroupSummary(roomId, categoryId) { addRoomToGroupSummary(roomId, categoryId) {
return MatrixClientPeg.get() return MatrixClientPeg.get()
.addRoomToGroupSummary(this.groupId, roomId, categoryId) .addRoomToGroupSummary(this.groupId, roomId, categoryId)
.then(this._fetchSummary.bind(this)); .then(this._fetchResource.bind(this, GroupStore.STATE_KEY.Summary));
} }
addUserToGroupSummary(userId, roleId) { addUserToGroupSummary(userId, roleId) {
return MatrixClientPeg.get() return MatrixClientPeg.get()
.addUserToGroupSummary(this.groupId, userId, roleId) .addUserToGroupSummary(this.groupId, userId, roleId)
.then(this._fetchSummary.bind(this)); .then(this._fetchResource.bind(this, GroupStore.STATE_KEY.Summary));
} }
removeRoomFromGroupSummary(roomId) { removeRoomFromGroupSummary(roomId) {
return MatrixClientPeg.get() return MatrixClientPeg.get()
.removeRoomFromGroupSummary(this.groupId, roomId) .removeRoomFromGroupSummary(this.groupId, roomId)
.then(this._fetchSummary.bind(this)); .then(this._fetchResource.bind(this, GroupStore.STATE_KEY.Summary));
} }
removeUserFromGroupSummary(userId) { removeUserFromGroupSummary(userId) {
return MatrixClientPeg.get() return MatrixClientPeg.get()
.removeUserFromGroupSummary(this.groupId, userId) .removeUserFromGroupSummary(this.groupId, userId)
.then(this._fetchSummary.bind(this)); .then(this._fetchResource.bind(this, GroupStore.STATE_KEY.Summary));
} }
setGroupPublicity(isPublished) { setGroupPublicity(isPublished) {
return MatrixClientPeg.get() return MatrixClientPeg.get()
.setGroupPublicity(this.groupId, isPublished) .setGroupPublicity(this.groupId, isPublished)
.then(() => { FlairStore.invalidatePublicisedGroups(MatrixClientPeg.get().credentials.userId); }) .then(() => { FlairStore.invalidatePublicisedGroups(MatrixClientPeg.get().credentials.userId); })
.then(this._fetchSummary.bind(this)); .then(this._fetchResource.bind(this, GroupStore.STATE_KEY.Summary));
} }
} }