From 917957c1dcb8911c2013fa8862a885a26227f3c1 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 5 Oct 2017 14:30:04 +0100 Subject: [PATCH] Modify the group store to include group rooms and modify components to use this new part of the store such that feedback can be given when adding or removing a room from the room list. --- .../views/dialogs/AddressPickerDialog.js | 42 ++++++++----------- src/components/views/groups/GroupRoomList.js | 39 +++++++++-------- src/components/views/groups/GroupRoomTile.js | 5 ++- src/stores/GroupStore.js | 26 +++++++++++- src/stores/GroupStoreCache.js | 1 + 5 files changed, 68 insertions(+), 45 deletions(-) diff --git a/src/components/views/dialogs/AddressPickerDialog.js b/src/components/views/dialogs/AddressPickerDialog.js index 6a027ac034..2637f9d466 100644 --- a/src/components/views/dialogs/AddressPickerDialog.js +++ b/src/components/views/dialogs/AddressPickerDialog.js @@ -23,6 +23,7 @@ import MatrixClientPeg from '../../../MatrixClientPeg'; import AccessibleButton from '../elements/AccessibleButton'; import Promise from 'bluebird'; import { addressTypes, getAddressType } from '../../../UserAddress.js'; +import GroupStoreCache from '../../../stores/GroupStoreCache'; const TRUNCATE_QUERY_LIST = 40; const QUERY_USER_DIRECTORY_DEBOUNCE_MS = 200; @@ -241,32 +242,25 @@ module.exports = React.createClass({ _doNaiveGroupRoomSearch: function(query) { const lowerCaseQuery = query.toLowerCase(); - MatrixClientPeg.get().getGroupRooms(this.props.groupId).then((resp) => { - const results = []; - resp.chunk.forEach((r) => { - const nameMatch = (r.name || '').toLowerCase().includes(lowerCaseQuery); - const topicMatch = (r.topic || '').toLowerCase().includes(lowerCaseQuery); - const aliasMatch = (r.canonical_alias || '').toLowerCase().includes(lowerCaseQuery); - if (!(nameMatch || topicMatch || aliasMatch)) { - return; - } - results.push({ - room_id: r.room_id, - avatar_url: r.avatar_url, - name: r.name || r.canonical_alias, - }); - }); - this._processResults(results, query); - }).catch((err) => { - console.error('Error whilst searching group users: ', err); - this.setState({ - searchError: err.errcode ? err.message : _t('Something went wrong!'), - }); - }).done(() => { - this.setState({ - busy: false, + const groupStore = GroupStoreCache.getGroupStore(MatrixClientPeg.get(), this.props.groupId); + const results = []; + groupStore.getGroupRooms().forEach((r) => { + const nameMatch = (r.name || '').toLowerCase().includes(lowerCaseQuery); + const topicMatch = (r.topic || '').toLowerCase().includes(lowerCaseQuery); + const aliasMatch = (r.canonical_alias || '').toLowerCase().includes(lowerCaseQuery); + if (!(nameMatch || topicMatch || aliasMatch)) { + return; + } + results.push({ + room_id: r.room_id, + avatar_url: r.avatar_url, + name: r.name || r.canonical_alias, }); }); + this._processResults(results, query); + this.setState({ + busy: false, + }); }, _doRoomSearch: function(query) { diff --git a/src/components/views/groups/GroupRoomList.js b/src/components/views/groups/GroupRoomList.js index 39ff3e4a07..4ff68a7f4d 100644 --- a/src/components/views/groups/GroupRoomList.js +++ b/src/components/views/groups/GroupRoomList.js @@ -17,6 +17,7 @@ import React from 'react'; import { _t } from '../../../languageHandler'; import sdk from '../../../index'; import { groupRoomFromApiObject } from '../../../groups'; +import GroupStoreCache from '../../../stores/GroupStoreCache'; import GeminiScrollbar from 'react-gemini-scrollbar'; import PropTypes from 'prop-types'; import {MatrixClient} from 'matrix-js-sdk'; @@ -34,7 +35,6 @@ export default React.createClass({ getInitialState: function() { return { - fetching: false, rooms: null, truncateAt: INITIAL_LOAD_NUM_ROOMS, searchQuery: "", @@ -43,21 +43,29 @@ export default React.createClass({ componentWillMount: function() { this._unmounted = false; + this._initGroupStore(this.props.groupId); + }, + + _initGroupStore: function(groupId) { + this._groupStore = GroupStoreCache.getGroupStore(this.context.matrixClient, groupId); + this._groupStore.on('update', () => { + this._fetchRooms(); + }); + this._groupStore.on('error', (err) => { + console.error('Error in group store (listened to by GroupRoomList)', err); + this.setState({ + rooms: null, + }); + }); this._fetchRooms(); }, _fetchRooms: function() { - this.setState({fetching: true}); - this.context.matrixClient.getGroupRooms(this.props.groupId).then((result) => { - this.setState({ - rooms: result.chunk.map((apiRoom) => { - return groupRoomFromApiObject(apiRoom); - }), - fetching: false, - }); - }).catch((e) => { - this.setState({fetching: false}); - console.error("Failed to get group room list: ", e); + if (this._unmounted) return; + this.setState({ + rooms: this._groupStore.getGroupRooms().map((apiRoom) => { + return groupRoomFromApiObject(apiRoom); + }), }); }, @@ -110,12 +118,7 @@ export default React.createClass({ }, render: function() { - if (this.state.fetching) { - const Spinner = sdk.getComponent("elements.Spinner"); - return (
- -
); - } else if (this.state.rooms === null) { + if (this.state.rooms === null) { return null; } diff --git a/src/components/views/groups/GroupRoomTile.js b/src/components/views/groups/GroupRoomTile.js index b6bdb9735b..bb0fdb03f4 100644 --- a/src/components/views/groups/GroupRoomTile.js +++ b/src/components/views/groups/GroupRoomTile.js @@ -21,6 +21,7 @@ import PropTypes from 'prop-types'; import sdk from '../../../index'; import dis from '../../../dispatcher'; import { GroupRoomType } from '../../../groups'; +import GroupStoreCache from '../../../stores/GroupStoreCache'; import Modal from '../../../Modal'; const GroupRoomTile = React.createClass({ @@ -49,10 +50,10 @@ const GroupRoomTile = React.createClass({ removeRoomFromGroup: function() { const groupId = this.props.groupId; + const groupStore = GroupStoreCache.getGroupStore(this.context.matrixClient, groupId); const roomName = this.state.name; const roomId = this.props.groupRoom.roomId; - this.context.matrixClient - .removeRoomFromGroup(groupId, roomId) + groupStore.removeRoomFromGroup(roomId) .catch((err) => { console.error(`Error whilst removing ${roomId} from ${groupId}`, err); const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); diff --git a/src/stores/GroupStore.js b/src/stores/GroupStore.js index 941f4c8ec2..73118993f9 100644 --- a/src/stores/GroupStore.js +++ b/src/stores/GroupStore.js @@ -26,7 +26,9 @@ export default class GroupStore extends EventEmitter { this.groupId = groupId; this._matrixClient = matrixClient; this._summary = {}; + this._rooms = []; this._fetchSummary(); + this._fetchRooms(); } _fetchSummary() { @@ -38,6 +40,15 @@ export default class GroupStore extends EventEmitter { }); } + _fetchRooms() { + this._matrixClient.getGroupRooms(this.groupId).then((resp) => { + this._rooms = resp.chunk; + this._notifyListeners(); + }).catch((err) => { + this.emit('error', err); + }); + } + _notifyListeners() { this.emit('update'); } @@ -46,9 +57,22 @@ export default class GroupStore extends EventEmitter { return this._summary; } + getGroupRooms() { + return this._rooms; + } + addRoomToGroup(roomId) { return this._matrixClient - .addRoomToGroup(this.groupId, roomId); + .addRoomToGroup(this.groupId, roomId) + .then(this._fetchRooms.bind(this)); + } + + removeRoomFromGroup(roomId) { + return this._matrixClient + .removeRoomFromGroup(this.groupId, roomId) + // Room might be in the summary, refresh just in case + .then(this._fetchSummary.bind(this)) + .then(this._fetchRooms.bind(this)); } addRoomToGroupSummary(roomId, categoryId) { diff --git a/src/stores/GroupStoreCache.js b/src/stores/GroupStoreCache.js index bf340521b5..551b155615 100644 --- a/src/stores/GroupStoreCache.js +++ b/src/stores/GroupStoreCache.js @@ -28,6 +28,7 @@ class GroupStoreCache { // referencing it. this.groupStore = new GroupStore(matrixClient, groupId); } + this.groupStore._fetchSummary(); return this.groupStore; } }