From 26c7c9e994012391fb79af4cc97d779d4620942e Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Wed, 10 Aug 2016 11:33:58 +0100 Subject: [PATCH] Make SessionLoader a function There's no point in it being a React component. --- src/Lifecycle.js | 115 +++++++++++-- src/component-index.js | 1 - src/components/structures/MatrixChat.js | 34 ++-- .../structures/login/SessionLoader.js | 152 ------------------ 4 files changed, 123 insertions(+), 179 deletions(-) delete mode 100644 src/components/structures/login/SessionLoader.js diff --git a/src/Lifecycle.js b/src/Lifecycle.js index 43c5c3aa8c9..60da4feb06a 100644 --- a/src/Lifecycle.js +++ b/src/Lifecycle.js @@ -14,19 +14,120 @@ See the License for the specific language governing permissions and limitations under the License. */ +import q from 'q'; + import MatrixClientPeg from './MatrixClientPeg'; import Notifier from './Notifier' import UserActivity from './UserActivity'; import Presence from './Presence'; import dis from './dispatcher'; +/** + * Called at startup, to attempt to build a logged-in Matrix session. It tries + * a number of things: + * + * 0. if it looks like we are in the middle of a registration process, it does + * nothing. + * + * 1. if we have a guest access token in the query params, it uses that. + * + * 2. if an access token is stored in local storage (from a previous session), + * it uses that. + * + * 3. it attempts to auto-register as a guest user. + * + * If any of steps 1-3 are successful, it will call {setLoggedIn}, which in + * turn will raise on_logged_in and will_start_client events. + * + * It returns a promise which resolves when the above process completes. + * + * @param {object} opts.queryParams: string->string map of the query-parameters + * extracted from the #-fragment of the starting URI. + * + * @param {boolean} opts.enableGuest: set to true to enable guest access tokens + * and auto-guest registrations. + * + * @params {string} opts.hsUrl: homeserver URL. Only used if enableGuest is + * true; defines the HS to register against. + * + * @params {string} opts.isUrl: homeserver URL. Only used if enableGuest is + * true; defines the IS to use. + * + */ +export function loadSession(opts) { + const queryParams = opts.queryParams || {}; + let enableGuest = opts.enableGuest || false; + const hsUrl = opts.hsUrl; + const isUrl = opts.isUrl; + + if (queryParams.client_secret && queryParams.sid) { + // this happens during email validation: the email contains a link to the + // IS, which in turn redirects back to vector. We let MatrixChat create a + // Registration component which completes the next stage of registration. + console.log("Not registering as guest: registration already in progress."); + return q(); + } + + if (!hsUrl) { + console.warn("Cannot enable guest access: can't determine HS URL to use"); + enableGuest = false; + } + + if (enableGuest && + queryParams.guest_user_id && + queryParams.guest_access_token + ) { + console.log("Using guest access credentials"); + setLoggedIn({ + userId: queryParams.guest_user_id, + accessToken: queryParams.guest_access_token, + homeserverUrl: hsUrl, + identityServerUrl: isUrl, + guest: true, + }); + return q(); + } + + if (MatrixClientPeg.get() && MatrixClientPeg.get().credentials) { + console.log("Using existing credentials"); + setLoggedIn(MatrixClientPeg.getCredentials()); + return q(); + } + + if (enableGuest) { + return _registerAsGuest(hsUrl, isUrl); + } + + // fall back to login screen + return q(); +} + +function _registerAsGuest(hsUrl, isUrl) { + console.log("Doing guest login on %s", hsUrl); + + MatrixClientPeg.replaceUsingUrls(hsUrl, isUrl); + return MatrixClientPeg.get().registerGuest().then((creds) => { + console.log("Registered as guest: %s", creds.user_id); + setLoggedIn({ + userId: creds.user_id, + accessToken: creds.access_token, + homeserverUrl: hsUrl, + identityServerUrl: isUrl, + guest: true, + }); + }, (err) => { + console.error("Failed to register as guest: " + err + " " + err.data); + }); +} + + /** * Transitions to a logged-in state using the given credentials * @param {MatrixClientCreds} credentials The credentials to use */ -function setLoggedIn(credentials) { +export function setLoggedIn(credentials) { credentials.guest = Boolean(credentials.guest); - console.log("onLoggedIn => %s (guest=%s) hs=%s", + console.log("setLoggedIn => %s (guest=%s) hs=%s", credentials.userId, credentials.guest, credentials.homeserverUrl); MatrixClientPeg.replaceUsingCreds(credentials); @@ -39,7 +140,7 @@ function setLoggedIn(credentials) { /** * Logs the current session out and transitions to the logged-out state */ -function logout() { +export function logout() { if (MatrixClientPeg.get().isGuest()) { // logout doesn't work for guest sessions // Also we sometimes want to re-log in a guest session @@ -67,7 +168,7 @@ function logout() { * Starts the matrix client and all other react-sdk services that * listen for events while a session is logged in. */ -function startMatrixClient() { +export function startMatrixClient() { // dispatch this before starting the matrix client: it's used // to add listeners for the 'sync' event so otherwise we'd have // a race condition (and we need to dispatch synchronously for this @@ -85,7 +186,7 @@ function startMatrixClient() { * Stops a running client and all related services, used after * a session has been logged out / ended. */ -function onLoggedOut() { +export function onLoggedOut() { if (window.localStorage) { const hsUrl = window.localStorage.getItem("mx_hs_url"); const isUrl = window.localStorage.getItem("mx_is_url"); @@ -112,7 +213,3 @@ function _stopMatrixClient() { MatrixClientPeg.get().removeAllListeners(); MatrixClientPeg.unset(); } - -module.exports = { - setLoggedIn, logout, startMatrixClient, onLoggedOut -}; diff --git a/src/component-index.js b/src/component-index.js index 2bde711c16d..97f8882b82b 100644 --- a/src/component-index.js +++ b/src/component-index.js @@ -39,7 +39,6 @@ module.exports.components['structures.login.ForgotPassword'] = require('./compon module.exports.components['structures.login.Login'] = require('./components/structures/login/Login'); module.exports.components['structures.login.PostRegistration'] = require('./components/structures/login/PostRegistration'); module.exports.components['structures.login.Registration'] = require('./components/structures/login/Registration'); -module.exports.components['structures.login.SessionLoader'] = require('./components/structures/login/SessionLoader'); module.exports.components['views.avatars.BaseAvatar'] = require('./components/views/avatars/BaseAvatar'); module.exports.components['views.avatars.MemberAvatar'] = require('./components/views/avatars/MemberAvatar'); module.exports.components['views.avatars.RoomAvatar'] = require('./components/views/avatars/RoomAvatar'); diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index b74a92bbf7e..6b7c99840af 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -26,7 +26,6 @@ var UserActivity = require("../../UserActivity"); var Presence = require("../../Presence"); var dis = require("../../dispatcher"); -var SessionLoader = require("./login/SessionLoader"); var Login = require("./login/Login"); var Registration = require("./login/Registration"); var PostRegistration = require("./login/PostRegistration"); @@ -145,14 +144,11 @@ module.exports = React.createClass({ if (this.props.config.sync_timeline_limit) { MatrixClientPeg.opts.initialSyncLimit = this.props.config.sync_timeline_limit; } - - // register our dispatcher listener here rather than in - // componentDidMount so that we hear about any actions raised during - // the loading process. - this.dispatcherRef = dis.register(this.onAction); }, componentDidMount: function() { + this.dispatcherRef = dis.register(this.onAction); + this.focusComposer = false; // scrollStateMap is a map from room id to the scroll state returned by // RoomView.getScrollState() @@ -171,6 +167,17 @@ module.exports = React.createClass({ window.addEventListener('resize', this.handleResize); this.handleResize(); + + Lifecycle.loadSession({ + queryParams: this.props.startingQueryParams, + enableGuest: this.props.enableGuest, + hsUrl: this.getDefaultHsUrl(), + isUrl: this.getDefaultIsUrl(), + }).done(()=>{ + // stuff this through the dispatcher so that it happens + // after the on_logged_in action. + dis.dispatch({action: 'load_completed'}); + }); }, componentWillUnmount: function() { @@ -990,18 +997,11 @@ module.exports = React.createClass({ // "; logged_in="+this.state.logged_in+"; ready="+this.state.ready); if (this.state.loading) { + var Spinner = sdk.getComponent('elements.Spinner'); return ( - {dis.dispatch({action: 'load_completed'});}} - /> +
+ +
); } // needs to be before normal PageTypes as you are logged in technically diff --git a/src/components/structures/login/SessionLoader.js b/src/components/structures/login/SessionLoader.js deleted file mode 100644 index 229f10d27a5..00000000000 --- a/src/components/structures/login/SessionLoader.js +++ /dev/null @@ -1,152 +0,0 @@ -/* -Copyright 2016 OpenMarket 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 React from 'react'; -import q from 'q'; - -import dis from '../../../dispatcher'; -import sdk from '../../../index'; -import MatrixClientPeg from '../../../MatrixClientPeg'; -import Lifecycle from '../../../Lifecycle'; - -/** - * A react component which is only used when the application first starts. - * - * Its job is to attempt to build a logged-in Matrix session. It tries a number - * of things: - * - * 0. if it looks like we are in the middle of a registration process, it does - * nothing. - * - * 1. if we have a guest access token in the query params, it uses that. - * - * 2. if an access token is stored in local storage (from a previous session), - * it uses that. - * - * 3. it attempts to auto-register as a guest user. - * - * If any of steps 1-3 are successful, it will call onLoggedIn (which is - * typically Lifecycle.setLoggedIn, which in turn will raise on_logged_in and - * will_start_client events). - * - * Finally, it calls onComplete, which makes MatrixChat move into its normal processing. - */ -export default class SessionLoader extends React.Component { - constructor(props, context) { - super(props, context); - } - - componentDidMount() { - this._loadSession().done(() => { - this.props.onComplete(); - }); - } - - componentWillReceiveProps(nextProps) { - if (nextProps.hsUrl != this.props.hsUrl || - nextProps.isUrl != this.props.isUrl - ) { - throw new Error("changing servers on a SessionLoader is not supported"); - }; - } - - _loadSession() { - if (this.props.queryParams.client_secret && this.props.queryParams.sid) { - // this happens during email validation: the email contains a link to the - // IS, which in turn redirects back to vector. We let MatrixChat create a - // Registration component which completes the next stage of registration. - console.log("Not registering as guest: registration already in progress."); - return q(); - } - - let enableGuest = false; - if (this.props.enableGuest) { - if (!this.props.hsUrl) { - console.warn("Cannot enable guest access: can't determine HS URL to use"); - } - else { - enableGuest = true; - } - } - - if (enableGuest && - this.props.queryParams.guest_user_id && - this.props.queryParams.guest_access_token - ) { - console.log("Using guest access credentials"); - this.props.onLoggedIn({ - userId: this.props.queryParams.guest_user_id, - accessToken: this.props.queryParams.guest_access_token, - homeserverUrl: this.props.hsUrl, - identityServerUrl: this.props.isUrl, - guest: true, - }); - return q(); - } - - if (MatrixClientPeg.get() && MatrixClientPeg.get().credentials) { - console.log("Using existing credentials"); - this.props.onLoggedIn(MatrixClientPeg.getCredentials()); - return q(); - } - - if (enableGuest) { - return this._registerAsGuest(); - } - - // fall back to login screen - return q(); - } - - _registerAsGuest() { - var hsUrl = this.props.hsUrl; - var isUrl = this.props.isUrl; - console.log("Doing guest login on %s", hsUrl); - - MatrixClientPeg.replaceUsingUrls(hsUrl, isUrl); - return MatrixClientPeg.get().registerGuest().then((creds) => { - console.log("Registered as guest: %s", creds.user_id); - this.props.onLoggedIn({ - userId: creds.user_id, - accessToken: creds.access_token, - homeserverUrl: hsUrl, - identityServerUrl: isUrl, - guest: true, - }); - }, (err) => { - console.error("Failed to register as guest: " + err + " " + err.data); - }); - } - - render() { - const Spinner = sdk.getComponent('elements.Spinner'); - return ( -
- -
- ); - } -} - - -SessionLoader.propTypes = { - queryParams: React.PropTypes.object.isRequired, - enableGuest: React.PropTypes.bool, - hsUrl: React.PropTypes.string, - isUrl: React.PropTypes.string, - onLoggedIn: React.PropTypes.func.isRequired, - onComplete: React.PropTypes.func.isRequired, -};