Merge pull request #2064 from matrix-org/t3chguy/slate_cont2

simplify MessageComposerStore and improve its performance
This commit is contained in:
David Baker 2018-07-16 17:20:48 +01:00 committed by GitHub
commit 379d65bd6c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 27 additions and 62 deletions

View file

@ -589,14 +589,8 @@ export default class MessageComposerInput extends React.Component {
this.props.onInputStateChanged(inputState); this.props.onInputStateChanged(inputState);
} }
// Record the editor state for this room so that it can be retrieved after // Record the editor state for this room so that it can be retrieved after switching to another room and back
// switching to another room and back MessageComposerStore.setEditorState(this.props.room.roomId, editorState, this.state.isRichTextEnabled);
dis.dispatch({
action: 'editor_state',
room_id: this.props.room.roomId,
rich_text: this.state.isRichTextEnabled,
editor_state: editorState,
});
this.setState({ this.setState({
editorState, editorState,

View file

@ -13,72 +13,43 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import dis from '../dispatcher';
import { Store } from 'flux/utils';
import { Value } from 'slate'; import { Value } from 'slate';
const INITIAL_STATE = { const localStoragePrefix = 'editor_state_';
// a map of room_id to rich text editor composer state
editorStateMap: localStorage.getItem('editor_state') ?
JSON.parse(localStorage.getItem('editor_state')) : {},
};
/** /**
* A class for storing application state to do with the message composer (specifically * A class for storing application state to do with the message composer (specifically in-progress message drafts).
* in-progress message drafts). This is a simple * It does not worry about cleaning up on log out as this is handled in Lifecycle.js by localStorage.clear()
* flux store that listens for actions and updates its state accordingly, informing any
* listeners (views) of state changes.
*/ */
class MessageComposerStore extends Store { class MessageComposerStore {
constructor() { constructor() {
super(dis); this.prefix = localStoragePrefix;
// Initialise state
this._state = Object.assign({}, INITIAL_STATE);
} }
_setState(newState) { _getKey(roomId: string): string {
this._state = Object.assign(this._state, newState); return this.prefix + roomId;
this.__emitChange();
} }
__onDispatch(payload) { setEditorState(roomId: string, editorState: Value, richText: boolean) {
switch (payload.action) { localStorage.setItem(this._getKey(roomId), JSON.stringify({
case 'editor_state': editor_state: editorState,
this._editorState(payload); rich_text: richText,
break; }));
case 'on_logged_out':
this.reset();
break;
}
} }
_editorState(payload) { getEditorState(roomId): {editor_state: Value, rich_text: boolean} {
const editorStateMap = this._state.editorStateMap; const stateStr = localStorage.getItem(this._getKey(roomId));
editorStateMap[payload.room_id] = {
editor_state: payload.editor_state, let state;
rich_text: payload.rich_text, if (stateStr) {
}; state = JSON.parse(stateStr);
localStorage.setItem('editor_state', JSON.stringify(editorStateMap));
this._setState({ // if it does not have the fields we expect then bail
editorStateMap: editorStateMap, if (!state || state.rich_text === undefined || state.editor_state === undefined) return;
}); state.editor_state = Value.fromJSON(state.editor_state);
} }
getEditorState(roomId) { return state;
const editorStateMap = this._state.editorStateMap;
// const entry = this._state.editorStateMap[roomId];
if (editorStateMap[roomId] && !Value.isValue(editorStateMap[roomId].editor_state)) {
// rehydrate lazily to prevent massive churn at launch and cache it
editorStateMap[roomId].editor_state = Value.fromJSON(editorStateMap[roomId].editor_state);
}
// explicitly don't setState here because the value didn't actually change, we just hydrated it,
// if a listener received an update they too would call this method and have a hydrated Value
return editorStateMap[roomId];
}
reset() {
this._state = Object.assign({}, INITIAL_STATE);
} }
} }