Refactor GroupStores into one global GroupStore

Take a step closer to a flux-like architecture for group data, for
the purposes of providing features that require it.

Now the app has a single GroupStore that can be poked to fetch
updates for a particular group.
This commit is contained in:
Luke Barnard 2018-05-01 11:18:45 +01:00
parent fba8a7d7d6
commit 023daef4b7
13 changed files with 245 additions and 281 deletions

View file

@ -23,7 +23,7 @@ import Modal from '../../../Modal';
import sdk from '../../../index';
import { _t } from '../../../languageHandler';
import { GroupMemberType } from '../../../groups';
import GroupStoreCache from '../../../stores/GroupStoreCache';
import GroupStore from '../../../stores/GroupStore';
import AccessibleButton from '../elements/AccessibleButton';
module.exports = React.createClass({
@ -47,33 +47,37 @@ module.exports = React.createClass({
},
componentWillMount: function() {
this._unmounted = false;
this._initGroupStore(this.props.groupId);
},
componentWillReceiveProps(newProps) {
if (newProps.groupId !== this.props.groupId) {
this._unregisterGroupStore();
this._unregisterGroupStore(this.props.groupId);
this._initGroupStore(newProps.groupId);
}
},
_initGroupStore(groupId) {
this._groupStore = GroupStoreCache.getGroupStore(this.props.groupId);
this._groupStore.registerListener(this.onGroupStoreUpdated);
componentWillUnmount() {
this._unmounted = true;
this._unregisterGroupStore(this.props.groupId);
},
_unregisterGroupStore() {
if (this._groupStore) {
this._groupStore.unregisterListener(this.onGroupStoreUpdated);
}
_initGroupStore(groupId) {
GroupStore.registerListener(groupId, this.onGroupStoreUpdated);
},
_unregisterGroupStore(groupId) {
GroupStore.unregisterListener(this.onGroupStoreUpdated);
},
onGroupStoreUpdated: function() {
if (this._unmounted) return;
this.setState({
isUserInvited: this._groupStore.getGroupInvitedMembers().some(
isUserInvited: GroupStore.getGroupInvitedMembers(this.props.groupId).some(
(m) => m.userId === this.props.groupMember.userId,
),
isUserPrivilegedInGroup: this._groupStore.isUserPrivileged(),
isUserPrivilegedInGroup: GroupStore.isUserPrivileged(this.props.groupId),
});
},

View file

@ -17,7 +17,7 @@ limitations under the License.
import React from 'react';
import { _t } from '../../../languageHandler';
import sdk from '../../../index';
import GroupStoreCache from '../../../stores/GroupStoreCache';
import GroupStore from '../../../stores/GroupStore';
import PropTypes from 'prop-types';
const INITIAL_LOAD_NUM_MEMBERS = 30;
@ -42,9 +42,12 @@ export default React.createClass({
this._initGroupStore(this.props.groupId);
},
componentWillUnmount: function() {
this._unmounted = true;
},
_initGroupStore: function(groupId) {
this._groupStore = GroupStoreCache.getGroupStore(groupId);
this._groupStore.registerListener(() => {
GroupStore.registerListener(groupId, () => {
this._fetchMembers();
});
},
@ -52,8 +55,8 @@ export default React.createClass({
_fetchMembers: function() {
if (this._unmounted) return;
this.setState({
members: this._groupStore.getGroupMembers(),
invitedMembers: this._groupStore.getGroupInvitedMembers(),
members: GroupStore.getGroupMembers(this.props.groupId),
invitedMembers: GroupStore.getGroupInvitedMembers(this.props.groupId),
});
},

View file

@ -17,7 +17,6 @@ limitations under the License.
import React from 'react';
import PropTypes from 'prop-types';
import sdk from '../../../index';
import GroupStoreCache from '../../../stores/GroupStoreCache';
import GroupStore from '../../../stores/GroupStore';
import { _t } from '../../../languageHandler.js';
@ -41,11 +40,10 @@ export default React.createClass({
},
_initGroupStore: function(groupId) {
this._groupStore = GroupStoreCache.getGroupStore(groupId);
this._groupStore.registerListener(() => {
GroupStore.registerListener(groupId, () => {
this.setState({
isGroupPublicised: this._groupStore.getGroupPublicity(),
ready: this._groupStore.isStateReady(GroupStore.STATE_KEY.Summary),
isGroupPublicised: GroupStore.getGroupPublicity(groupId),
ready: GroupStore.isStateReady(groupId, GroupStore.STATE_KEY.Summary),
});
});
},
@ -57,7 +55,7 @@ export default React.createClass({
// Optimistic early update
isGroupPublicised: !this.state.isGroupPublicised,
});
this._groupStore.setGroupPublicity(!this.state.isGroupPublicised).then(() => {
GroupStore.setGroupPublicity(this.props.groupId, !this.state.isGroupPublicised).then(() => {
this.setState({
busy: false,
});

View file

@ -21,7 +21,7 @@ import dis from '../../../dispatcher';
import Modal from '../../../Modal';
import sdk from '../../../index';
import { _t } from '../../../languageHandler';
import GroupStoreCache from '../../../stores/GroupStoreCache';
import GroupStore from '../../../stores/GroupStore';
module.exports = React.createClass({
displayName: 'GroupRoomInfo',
@ -50,29 +50,26 @@ module.exports = React.createClass({
componentWillReceiveProps(newProps) {
if (newProps.groupId !== this.props.groupId) {
this._unregisterGroupStore();
this._unregisterGroupStore(this.props.groupId);
this._initGroupStore(newProps.groupId);
}
},
componentWillUnmount() {
this._unregisterGroupStore();
this._unregisterGroupStore(this.props.groupId);
},
_initGroupStore(groupId) {
this._groupStore = GroupStoreCache.getGroupStore(this.props.groupId);
this._groupStore.registerListener(this.onGroupStoreUpdated);
GroupStore.registerListener(groupId, this.onGroupStoreUpdated);
},
_unregisterGroupStore() {
if (this._groupStore) {
this._groupStore.unregisterListener(this.onGroupStoreUpdated);
}
_unregisterGroupStore(groupId) {
GroupStore.unregisterListener(this.onGroupStoreUpdated);
},
_updateGroupRoom() {
this.setState({
groupRoom: this._groupStore.getGroupRooms().find(
groupRoom: GroupStore.getGroupRooms(this.props.groupId).find(
(r) => r.roomId === this.props.groupRoomId,
),
});
@ -80,7 +77,7 @@ module.exports = React.createClass({
onGroupStoreUpdated: function() {
this.setState({
isUserPrivilegedInGroup: this._groupStore.isUserPrivileged(),
isUserPrivilegedInGroup: GroupStore.isUserPrivileged(this.props.groupId),
});
this._updateGroupRoom();
},
@ -100,7 +97,7 @@ module.exports = React.createClass({
this.setState({groupRoomRemoveLoading: true});
const groupId = this.props.groupId;
const roomId = this.props.groupRoomId;
this._groupStore.removeRoomFromGroup(roomId).then(() => {
GroupStore.removeRoomFromGroup(this.props.groupId, roomId).then(() => {
dis.dispatch({
action: "view_group_room_list",
});
@ -134,7 +131,7 @@ module.exports = React.createClass({
const groupId = this.props.groupId;
const roomId = this.props.groupRoomId;
const roomName = this.state.groupRoom.displayname;
this._groupStore.updateGroupRoomVisibility(roomId, isPublic).catch((err) => {
GroupStore.updateGroupRoomVisibility(this.props.groupId, roomId, isPublic).catch((err) => {
console.error(`Error whilst changing visibility of ${roomId} in ${groupId} to ${isPublic}`, err);
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createTrackedDialog('Failed to remove room from group', '', ErrorDialog, {

View file

@ -16,7 +16,7 @@ limitations under the License.
import React from 'react';
import { _t } from '../../../languageHandler';
import sdk from '../../../index';
import GroupStoreCache from '../../../stores/GroupStoreCache';
import GroupStore from '../../../stores/GroupStore';
import PropTypes from 'prop-types';
const INITIAL_LOAD_NUM_ROOMS = 30;
@ -39,22 +39,31 @@ export default React.createClass({
this._initGroupStore(this.props.groupId);
},
componentWillUnmount() {
this._unmounted = true;
this._unregisterGroupStore();
},
_unregisterGroupStore() {
GroupStore.unregisterListener(this.onGroupStoreUpdated);
},
_initGroupStore: function(groupId) {
this._groupStore = GroupStoreCache.getGroupStore(groupId);
this._groupStore.registerListener(() => {
this._fetchRooms();
});
this._groupStore.on('error', (err) => {
GroupStore.registerListener(groupId, this.onGroupStoreUpdated);
// XXX: This should be more fluxy - let's get the error from GroupStore .getError or something
// XXX: This is also leaked - we should remove it when unmounting
GroupStore.on('error', (err, errorGroupId) => {
if (errorGroupId !== groupId) return;
this.setState({
rooms: null,
});
});
},
_fetchRooms: function() {
onGroupStoreUpdated: function() {
if (this._unmounted) return;
this.setState({
rooms: this._groupStore.getGroupRooms(),
rooms: GroupStore.getGroupRooms(this.props.groupId),
});
},