From 0abcb5c78d9b36ddc948ec950ca14497bdc7c8a9 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 10 Oct 2018 17:07:17 +0100 Subject: [PATCH 1/2] Handle InvalidStoreError from js-sdk js-sdk now emits sync state ERROR with an InvalidStoreError if the store needs to be cleared before it can be used. Requires https://github.com/matrix-org/matrix-js-sdk/pull/759 --- src/Lifecycle.js | 68 +++++++++---------- src/components/structures/MatrixChat.js | 47 ++++++++++++- .../views/dialogs/QuestionDialog.js | 1 + 3 files changed, 80 insertions(+), 36 deletions(-) diff --git a/src/Lifecycle.js b/src/Lifecycle.js index b3178710a1..b0912c759e 100644 --- a/src/Lifecycle.js +++ b/src/Lifecycle.js @@ -159,6 +159,40 @@ export function attemptTokenLogin(queryParams, defaultDeviceDisplayName) { }); } +export function handleInvalidStoreError(e) { + if (e.reason === Matrix.InvalidStoreError.TOGGLED_LAZY_LOADING) { + return Promise.resolve().then(() => { + const lazyLoadEnabled = e.value; + if (lazyLoadEnabled) { + const LazyLoadingResyncDialog = + sdk.getComponent("views.dialogs.LazyLoadingResyncDialog"); + return new Promise((resolve) => { + Modal.createDialog(LazyLoadingResyncDialog, { + onFinished: resolve, + }); + }); + } else { + // show warning about simultaneous use + // between LL/non-LL version on same host. + // as disabling LL when previously enabled + // is a strong indicator of this (/develop & /app) + const LazyLoadingDisabledDialog = + sdk.getComponent("views.dialogs.LazyLoadingDisabledDialog"); + return new Promise((resolve) => { + Modal.createDialog(LazyLoadingDisabledDialog, { + onFinished: resolve, + host: window.location.host, + }); + }); + } + }).then(() => { + return MatrixClientPeg.get().store.deleteAllData(); + }).then(() => { + PlatformPeg.get().reload(); + }); + } +} + function _registerAsGuest(hsUrl, isUrl, defaultDeviceDisplayName) { console.log(`Doing guest login on ${hsUrl}`); @@ -238,40 +272,6 @@ async function _restoreFromLocalStorage() { function _handleLoadSessionFailure(e) { console.log("Unable to load session", e); - if (e instanceof Matrix.InvalidStoreError) { - if (e.reason === Matrix.InvalidStoreError.TOGGLED_LAZY_LOADING) { - return Promise.resolve().then(() => { - const lazyLoadEnabled = e.value; - if (lazyLoadEnabled) { - const LazyLoadingResyncDialog = - sdk.getComponent("views.dialogs.LazyLoadingResyncDialog"); - return new Promise((resolve) => { - Modal.createDialog(LazyLoadingResyncDialog, { - onFinished: resolve, - }); - }); - } else { - // show warning about simultaneous use - // between LL/non-LL version on same host. - // as disabling LL when previously enabled - // is a strong indicator of this (/develop & /app) - const LazyLoadingDisabledDialog = - sdk.getComponent("views.dialogs.LazyLoadingDisabledDialog"); - return new Promise((resolve) => { - Modal.createDialog(LazyLoadingDisabledDialog, { - onFinished: resolve, - host: window.location.host, - }); - }); - } - }).then(() => { - return MatrixClientPeg.get().store.deleteAllData(); - }).then(() => { - PlatformPeg.get().reload(); - }); - } - } - const def = Promise.defer(); const SessionRestoreErrorDialog = sdk.getComponent('views.dialogs.SessionRestoreErrorDialog'); diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 3f213c5a83..909d0b2d42 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -1266,6 +1266,9 @@ export default React.createClass({ dis.dispatch({action: 'sync_state', prevState, state}); if (state === "ERROR" || state === "RECONNECTING") { + if (data.error instanceof Matrix.InvalidStoreError) { + Lifecycle.handleInvalidStoreError(data.error); + } self.setState({syncError: data.error || true}); } else if (self.state.syncError) { self.setState({syncError: null}); @@ -1419,6 +1422,42 @@ export default React.createClass({ } }, + _handleSyncError(e) { + if (e instanceof Matrix.InvalidStoreError) { + if (e.reason === Matrix.InvalidStoreError.TOGGLED_LAZY_LOADING) { + return Promise.resolve().then(() => { + const lazyLoadEnabled = e.value; + if (lazyLoadEnabled) { + const LazyLoadingResyncDialog = + sdk.getComponent("views.dialogs.LazyLoadingResyncDialog"); + return new Promise((resolve) => { + Modal.createDialog(LazyLoadingResyncDialog, { + onFinished: resolve, + }); + }); + } else { + // show warning about simultaneous use + // between LL/non-LL version on same host. + // as disabling LL when previously enabled + // is a strong indicator of this (/develop & /app) + const LazyLoadingDisabledDialog = + sdk.getComponent("views.dialogs.LazyLoadingDisabledDialog"); + return new Promise((resolve) => { + Modal.createDialog(LazyLoadingDisabledDialog, { + onFinished: resolve, + host: window.location.host, + }); + }); + } + }).then(() => { + return MatrixClientPeg.get().store.deleteAllData(); + }).then(() => { + PlatformPeg.get().reload(); + }); + } + } + }, + showScreen: function(screen, params) { if (screen == 'register') { dis.dispatch({ @@ -1742,10 +1781,14 @@ export default React.createClass({ } if (this.state.view === VIEWS.LOGGED_IN) { + // store errors stop the client syncing and require user intervention, so we'll + // be showing a dialog. Don't show anything else. + const isStoreError = this.state.syncError && this.state.syncError instanceof Matrix.InvalidStoreError; + // `ready` and `view==LOGGED_IN` may be set before `page_type` (because the // latter is set via the dispatcher). If we don't yet have a `page_type`, // keep showing the spinner for now. - if (this.state.ready && this.state.page_type) { + if (this.state.ready && this.state.page_type && !isStoreError) { /* for now, we stuff the entirety of our props and state into the LoggedInView. * we should go through and figure out what we actually need to pass down, as well * as using something like redux to avoid having a billion bits of state kicking around. @@ -1767,7 +1810,7 @@ export default React.createClass({ // we think we are logged in, but are still waiting for the /sync to complete const Spinner = sdk.getComponent('elements.Spinner'); let errorBox; - if (this.state.syncError) { + if (this.state.syncError && !isStoreError) { errorBox =
{messageForSyncError(this.state.syncError)}
; diff --git a/src/components/views/dialogs/QuestionDialog.js b/src/components/views/dialogs/QuestionDialog.js index ed73bdcbdf..4d0defadc2 100644 --- a/src/components/views/dialogs/QuestionDialog.js +++ b/src/components/views/dialogs/QuestionDialog.js @@ -62,6 +62,7 @@ export default React.createClass({
{ this.props.description } From 655627209a95254e83deeab10e90006e6a074a9b Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 10 Oct 2018 17:25:32 +0100 Subject: [PATCH 2/2] unused function --- src/components/structures/MatrixChat.js | 36 ------------------------- 1 file changed, 36 deletions(-) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 909d0b2d42..db5e898946 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -1422,42 +1422,6 @@ export default React.createClass({ } }, - _handleSyncError(e) { - if (e instanceof Matrix.InvalidStoreError) { - if (e.reason === Matrix.InvalidStoreError.TOGGLED_LAZY_LOADING) { - return Promise.resolve().then(() => { - const lazyLoadEnabled = e.value; - if (lazyLoadEnabled) { - const LazyLoadingResyncDialog = - sdk.getComponent("views.dialogs.LazyLoadingResyncDialog"); - return new Promise((resolve) => { - Modal.createDialog(LazyLoadingResyncDialog, { - onFinished: resolve, - }); - }); - } else { - // show warning about simultaneous use - // between LL/non-LL version on same host. - // as disabling LL when previously enabled - // is a strong indicator of this (/develop & /app) - const LazyLoadingDisabledDialog = - sdk.getComponent("views.dialogs.LazyLoadingDisabledDialog"); - return new Promise((resolve) => { - Modal.createDialog(LazyLoadingDisabledDialog, { - onFinished: resolve, - host: window.location.host, - }); - }); - } - }).then(() => { - return MatrixClientPeg.get().store.deleteAllData(); - }).then(() => { - PlatformPeg.get().reload(); - }); - } - } - }, - showScreen: function(screen, params) { if (screen == 'register') { dis.dispatch({