Display whether the group summary/room list is loading

This uses a `ready` flag assigned to each fetching API used by the GroupServer. I've avoided making this generic for now for want of not doing so early.
This commit is contained in:
Luke Barnard 2017-10-31 11:42:09 +00:00
parent deebd4cbcf
commit 775468e71a
3 changed files with 28 additions and 2 deletions

View file

@ -407,6 +407,10 @@ export default React.createClass({
getInitialState: function() { getInitialState: function() {
return { return {
summary: null, summary: null,
isGroupPublicised: null,
isUserPrivileged: null,
groupRooms: null,
groupRoomsLoading: null,
error: null, error: null,
editing: false, editing: false,
saving: false, saving: false,
@ -458,8 +462,11 @@ export default React.createClass({
} }
this.setState({ this.setState({
summary, summary,
summaryLoading: !this._groupStore.isStateReady('GroupStore.Summary'),
isGroupPublicised: this._groupStore.getGroupPublicity(), isGroupPublicised: this._groupStore.getGroupPublicity(),
isUserPrivileged: this._groupStore.isUserPrivileged(), isUserPrivileged: this._groupStore.isUserPrivileged(),
groupRooms: this._groupStore.getGroupRooms(),
groupRoomsLoading: !this._groupStore.isStateReady('GroupStore.GroupRooms'),
error: null, error: null,
}); });
}); });
@ -667,7 +674,7 @@ export default React.createClass({
<h3>{ _t('Rooms') }</h3> <h3>{ _t('Rooms') }</h3>
{ addRoomRow } { addRoomRow }
</div> </div>
<RoomDetailList rooms={this._groupStore.getGroupRooms()} /> <RoomDetailList rooms={this.state.groupRooms} loading={this.state.groupRoomsLoading} />
</div>; </div>;
}, },
@ -863,7 +870,7 @@ export default React.createClass({
const Spinner = sdk.getComponent("elements.Spinner"); const Spinner = sdk.getComponent("elements.Spinner");
const TintableSvg = sdk.getComponent("elements.TintableSvg"); const TintableSvg = sdk.getComponent("elements.TintableSvg");
if (this.state.summary === null && this.state.error === null || this.state.saving) { if (this.state.summaryLoading && this.state.error === null || this.state.saving) {
return <Spinner />; return <Spinner />;
} else if (this.state.summary) { } else if (this.state.summary) {
const summary = this.state.summary; const summary = this.state.summary;

View file

@ -113,6 +113,8 @@ export default React.createClass({
worldReadable: PropTypes.bool, worldReadable: PropTypes.bool,
guestCanJoin: PropTypes.bool, guestCanJoin: PropTypes.bool,
loading: PropTypes.bool,
})), })),
}, },
@ -124,6 +126,10 @@ export default React.createClass({
}, },
render() { render() {
const Spinner = sdk.getComponent('elements.Spinner');
if (this.props.loading) {
return <Spinner />;
}
const rows = this.getRows(); const rows = this.getRows();
let rooms; let rooms;
if (rows.length == 0) { if (rows.length == 0) {

View file

@ -29,6 +29,9 @@ export default class GroupStore extends EventEmitter {
this._matrixClient = matrixClient; this._matrixClient = matrixClient;
this._summary = {}; this._summary = {};
this._rooms = []; this._rooms = [];
this._members = [];
this._invitedMembers = [];
this._ready = {};
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);
@ -40,6 +43,7 @@ export default class GroupStore extends EventEmitter {
this._members = result.chunk.map((apiMember) => { this._members = result.chunk.map((apiMember) => {
return groupMemberFromApiObject(apiMember); return groupMemberFromApiObject(apiMember);
}); });
this._ready['GroupStore.GroupMembers'] = true;
this._notifyListeners(); this._notifyListeners();
}).catch((err) => { }).catch((err) => {
console.error("Failed to get group member list: " + err); console.error("Failed to get group member list: " + err);
@ -50,6 +54,7 @@ export default class GroupStore extends EventEmitter {
this._invitedMembers = result.chunk.map((apiMember) => { this._invitedMembers = result.chunk.map((apiMember) => {
return groupMemberFromApiObject(apiMember); return groupMemberFromApiObject(apiMember);
}); });
this._ready['GroupStore.GroupInvitedMembers'] = true;
this._notifyListeners(); this._notifyListeners();
}).catch((err) => { }).catch((err) => {
// Invited users not visible to non-members // Invited users not visible to non-members
@ -64,6 +69,7 @@ export default class GroupStore extends EventEmitter {
_fetchSummary() { _fetchSummary() {
this._matrixClient.getGroupSummary(this.groupId).then((resp) => { this._matrixClient.getGroupSummary(this.groupId).then((resp) => {
this._summary = resp; this._summary = resp;
this._ready['GroupStore.Summary'] = true;
this._notifyListeners(); this._notifyListeners();
}).catch((err) => { }).catch((err) => {
this.emit('error', err); this.emit('error', err);
@ -75,6 +81,7 @@ export default class GroupStore extends EventEmitter {
this._rooms = resp.chunk.map((apiRoom) => { this._rooms = resp.chunk.map((apiRoom) => {
return groupRoomFromApiObject(apiRoom); return groupRoomFromApiObject(apiRoom);
}); });
this._ready['GroupStore.GroupRooms'] = true;
this._notifyListeners(); this._notifyListeners();
}).catch((err) => { }).catch((err) => {
this.emit('error', err); this.emit('error', err);
@ -87,6 +94,8 @@ export default class GroupStore extends EventEmitter {
registerListener(fn) { registerListener(fn) {
this.on('update', fn); this.on('update', fn);
// Call to set initial state (before fetching starts)
this.emit('update');
this._fetchSummary(); this._fetchSummary();
this._fetchRooms(); this._fetchRooms();
this._fetchMembers(); this._fetchMembers();
@ -96,6 +105,10 @@ export default class GroupStore extends EventEmitter {
this.removeListener('update', fn); this.removeListener('update', fn);
} }
isStateReady(id) {
return this._ready[id];
}
getSummary() { getSummary() {
return this._summary; return this._summary;
} }