diff --git a/src/MatrixClientPeg.js b/src/MatrixClientPeg.js index a6012f5213..fdd06b38c3 100644 --- a/src/MatrixClientPeg.js +++ b/src/MatrixClientPeg.js @@ -22,6 +22,7 @@ import EventTimeline from 'matrix-js-sdk/lib/models/event-timeline'; import EventTimelineSet from 'matrix-js-sdk/lib/models/event-timeline-set'; import createMatrixClient from './utils/createMatrixClient'; import SettingsStore from './settings/SettingsStore'; +import MatrixActionCreators from './actions/MatrixActionCreators'; interface MatrixClientCreds { homeserverUrl: string, @@ -68,6 +69,8 @@ class MatrixClientPeg { unset() { this.matrixClient = null; + + MatrixActionCreators.stop(); } /** @@ -108,6 +111,9 @@ class MatrixClientPeg { // regardless of errors, start the client. If we did error out, we'll // just end up doing a full initial /sync. + // Connect the matrix client to the dispatcher + MatrixActionCreators.start(this.matrixClient); + console.log(`MatrixClientPeg: really starting MatrixClient`); this.get().startClient(opts); console.log(`MatrixClientPeg: MatrixClient started`); diff --git a/src/actions/GroupActions.js b/src/actions/GroupActions.js index 30249f846c..da321af18b 100644 --- a/src/actions/GroupActions.js +++ b/src/actions/GroupActions.js @@ -14,7 +14,6 @@ See the License for the specific language governing permissions and limitations under the License. */ - import { createPromiseActionCreator } from './actionCreators'; const GroupActions = {}; diff --git a/src/actions/MatrixActionCreators.js b/src/actions/MatrixActionCreators.js new file mode 100644 index 0000000000..86d4a3456c --- /dev/null +++ b/src/actions/MatrixActionCreators.js @@ -0,0 +1,39 @@ +/* +Copyright 2017 Vector Creations Ltd + +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 { createMatrixActionCreator } from './actionCreators'; + +// Events emitted from the matrixClient that we want to dispatch as actions +// via MatrixActionCreators. See createMatrixActionCreator. +const REGISTERED_EVENTS = [ + "accountData", +]; + +export default { + actionCreators: [], + actionCreatorsStop: [], + + start(matrixClient) { + this.actionCreators = REGISTERED_EVENTS.map((eventId) => + createMatrixActionCreator(matrixClient, eventId), + ); + this.actionCreatorsStop = this.actionCreators.map((ac) => ac()); + }, + + stop() { + this.actionCreatorsStop.map((stop) => stop()); + }, +}; diff --git a/src/actions/actionCreators.js b/src/actions/actionCreators.js index c4e20a0a3f..5b2c25d023 100644 --- a/src/actions/actionCreators.js +++ b/src/actions/actionCreators.js @@ -16,6 +16,16 @@ limitations under the License. import dis from '../dispatcher'; +/** + * Create an action creator that will dispatch actions asynchronously that + * indicate the current status of promise returned by the given function, fn. + * @param {string} id the id to give the dispatched actions. This is given a + * suffix determining whether it is pending, successful or + * a failure. + * @param {function} fn the function to call with arguments given to the + * returned function. This function should return a Promise. + * @returns a function that dispatches asynchronous actions when called. + */ export function createPromiseActionCreator(id, fn) { return (...args) => { dis.dispatch({action: id + '.pending'}); @@ -26,3 +36,37 @@ export function createPromiseActionCreator(id, fn) { }) } } + +/** + * Create an action creator that will listen to events of type eventId emitted + * by matrixClient and dispatch a corresponding action of the following shape: + * { + * action: 'MatrixActions.' + eventId, + * event: matrixEvent, + * event_type: matrixEvent.getType(), + * event_content: matrixEvent.getContent(), + * } + * @param matrixClient{MatrixClient} the matrix client with which to register + * a listener. + * @param eventId{string} the ID of the event that hen emitted will cause the + * an action to be dispatched. + * @returns a function that, when called, will begin to listen to dispatches + * from matrixClient. The result from that function can be called to + * stop listening. + */ +export function createMatrixActionCreator(matrixClient, eventId) { + const listener = (matrixEvent) => { + dis.dispatch({ + action: 'MatrixActions.' + eventId, + event: matrixEvent, + event_type: matrixEvent.getType(), + event_content: matrixEvent.getContent(), + }); + }; + return () => { + matrixClient.on(eventId, listener); + return () => { + matrixClient.removeListener(listener); + } + } +} diff --git a/src/stores/TagOrderStore.js b/src/stores/TagOrderStore.js index 885eaafb38..a5eae3806e 100644 --- a/src/stores/TagOrderStore.js +++ b/src/stores/TagOrderStore.js @@ -41,17 +41,14 @@ class TagOrderStore extends Store { __onDispatch(payload) { switch (payload.action) { - // Get ordering from account data, once the client has synced - case 'sync_state': - if (payload.prevState === "PREPARED" && payload.state === "SYNCING") { - const accountDataEvent = MatrixClientPeg.get().getAccountData('im.vector.web.tag_ordering'); - - const orderedTags = accountDataEvent && accountDataEvent.getContent() ? - accountDataEvent.getContent().tags : null; - - this._setState({orderedTags}); - } - break; + // Get ordering from account data + case 'MatrixActions.accountData': { + if (payload.event_type !== 'im.vector.web.tag_ordering') break; + this._setState({ + orderedTags: payload.event_content ? payload.event_content.tags : null, + }); + break; + } // Initialise the state such that if account data is unset, default to joined groups case 'GroupActions.fetchJoinedGroups.success': this._setState({