From 0bb3843726090a7fe5c8dad7e2c5d3adc241fb83 Mon Sep 17 00:00:00 2001
From: "J. Ryan Stinnett" <jryans@gmail.com>
Date: Thu, 7 Feb 2019 10:23:38 +0000
Subject: [PATCH 01/13] Remove unused iframeSrc from HomePage

---
 src/components/structures/HomePage.js | 21 +++++----------------
 1 file changed, 5 insertions(+), 16 deletions(-)

diff --git a/src/components/structures/HomePage.js b/src/components/structures/HomePage.js
index 18f1a2ba31..a5a5dfa25d 100644
--- a/src/components/structures/HomePage.js
+++ b/src/components/structures/HomePage.js
@@ -39,7 +39,6 @@ class HomePage extends React.Component {
     };
 
     state = {
-            iframeSrc: '',
             page: '',
     };
 
@@ -87,21 +86,11 @@ class HomePage extends React.Component {
             mx_HomePage_guest: isGuest,
         });
 
-        if (this.state.iframeSrc) {
-            return (
-                <div className={classes}>
-                    <iframe src={ this.state.iframeSrc } />
-                </div>
-            );
-        } else {
-            const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper");
-            return (
-                <GeminiScrollbarWrapper autoshow={true} className={classes}>
-                    <div className="mx_HomePage_body" dangerouslySetInnerHTML={{ __html: this.state.page }}>
-                    </div>
-                </GeminiScrollbarWrapper>
-            );
-        }
+        const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper");
+        return <GeminiScrollbarWrapper autoshow={true} className={classes}>
+            <div className="mx_HomePage_body" dangerouslySetInnerHTML={{ __html: this.state.page }}>
+            </div>
+        </GeminiScrollbarWrapper>;
     }
 }
 

From 2fde67787c4f1a692637c0673cbea9c4701edf7a Mon Sep 17 00:00:00 2001
From: "J. Ryan Stinnett" <jryans@gmail.com>
Date: Thu, 7 Feb 2019 10:33:03 +0000
Subject: [PATCH 02/13] Update code style in HomePage

---
 src/components/structures/HomePage.js | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/src/components/structures/HomePage.js b/src/components/structures/HomePage.js
index a5a5dfa25d..f21af3a32c 100644
--- a/src/components/structures/HomePage.js
+++ b/src/components/structures/HomePage.js
@@ -1,6 +1,7 @@
 /*
 Copyright 2016 OpenMarket Ltd
 Copyright 2017 Vector Creations Ltd
+Copyright 2019 New Vector Ltd
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -26,9 +27,7 @@ import sdk from '../../index';
 import { MatrixClient } from 'matrix-js-sdk';
 import classnames from 'classnames';
 
-class HomePage extends React.Component {
-    static displayName = 'HomePage';
-
+export default class HomePage extends React.PureComponent {
     static propTypes = {
         // URL to use as the iFrame src. Defaults to /home.html.
         homePageUrl: PropTypes.string,
@@ -38,9 +37,13 @@ class HomePage extends React.Component {
         matrixClient: PropTypes.instanceOf(MatrixClient),
     };
 
-    state = {
+    constructor(props) {
+        super(props);
+
+        this.state = {
             page: '',
-    };
+        };
+    }
 
     translate(s) {
         // default implementation - skins may wish to extend this
@@ -93,5 +96,3 @@ class HomePage extends React.Component {
         </GeminiScrollbarWrapper>;
     }
 }
-
-module.exports = HomePage;

From 73de56d72d2a8d9c11de0c0603502f5ebc4aa840 Mon Sep 17 00:00:00 2001
From: "J. Ryan Stinnett" <jryans@gmail.com>
Date: Thu, 7 Feb 2019 11:12:28 +0000
Subject: [PATCH 03/13] Generalize HomePage into EmbeddedPage

---
 res/css/structures/_HomePage.scss             |  8 +------
 .../{HomePage.js => EmbeddedPage.js}          | 21 +++++++++++--------
 src/components/structures/LoggedInView.js     |  6 +++---
 3 files changed, 16 insertions(+), 19 deletions(-)
 rename src/components/structures/{HomePage.js => EmbeddedPage.js} (82%)

diff --git a/res/css/structures/_HomePage.scss b/res/css/structures/_HomePage.scss
index 5f1e035e99..3aa80f6f59 100644
--- a/res/css/structures/_HomePage.scss
+++ b/res/css/structures/_HomePage.scss
@@ -1,6 +1,7 @@
 /*
 Copyright 2016 OpenMarket Ltd
 Copyright 2017 Vector Creations Ltd
+Copyright 2019 New Vector Ltd
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -22,10 +23,3 @@ limitations under the License.
     margin-left: auto;
     margin-right: auto;
 }
-
-.mx_HomePage iframe {
-    display: block;
-	width: 100%;
-	height: 100%;
-	border: 0px;
-}
diff --git a/src/components/structures/HomePage.js b/src/components/structures/EmbeddedPage.js
similarity index 82%
rename from src/components/structures/HomePage.js
rename to src/components/structures/EmbeddedPage.js
index f21af3a32c..8e5be965e7 100644
--- a/src/components/structures/HomePage.js
+++ b/src/components/structures/EmbeddedPage.js
@@ -27,10 +27,12 @@ import sdk from '../../index';
 import { MatrixClient } from 'matrix-js-sdk';
 import classnames from 'classnames';
 
-export default class HomePage extends React.PureComponent {
+export default class EmbeddedPage extends React.PureComponent {
     static propTypes = {
-        // URL to use as the iFrame src. Defaults to /home.html.
-        homePageUrl: PropTypes.string,
+        // URL to request embedded page content from
+        url: PropTypes.string,
+        // Class name prefix to apply for a given instance
+        className: PropTypes.string,
     };
 
     static contextTypes = {
@@ -57,10 +59,8 @@ export default class HomePage extends React.PureComponent {
         // so that it can inherit CSS and theming easily rather than mess around
         // with iframes and trying to synchronise document.stylesheets.
 
-        const src = this.props.homePageUrl || 'home.html';
-
         request(
-            { method: "GET", url: src },
+            { method: "GET", url: this.props.url },
             (err, response, body) => {
                 if (this._unmounted) {
                     return;
@@ -84,14 +84,17 @@ export default class HomePage extends React.PureComponent {
 
     render() {
         const isGuest = this.context.matrixClient.isGuest();
+        const className = this.props.className;
         const classes = classnames({
-            mx_HomePage: true,
-            mx_HomePage_guest: isGuest,
+            [className]: true,
+            [`${className}_guest`]: isGuest,
         });
 
         const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper");
         return <GeminiScrollbarWrapper autoshow={true} className={classes}>
-            <div className="mx_HomePage_body" dangerouslySetInnerHTML={{ __html: this.state.page }}>
+            <div className={`${className}_body`}
+                dangerouslySetInnerHTML={{ __html: this.state.page }}
+            >
             </div>
         </GeminiScrollbarWrapper>;
     }
diff --git a/src/components/structures/LoggedInView.js b/src/components/structures/LoggedInView.js
index eac4422de0..22a6110674 100644
--- a/src/components/structures/LoggedInView.js
+++ b/src/components/structures/LoggedInView.js
@@ -420,7 +420,7 @@ const LoggedInView = React.createClass({
     render: function() {
         const LeftPanel = sdk.getComponent('structures.LeftPanel');
         const RoomView = sdk.getComponent('structures.RoomView');
-        const HomePage = sdk.getComponent('structures.HomePage');
+        const EmbeddedPage = sdk.getComponent('structures.EmbeddedPage');
         const GroupView = sdk.getComponent('structures.GroupView');
         const MyGroups = sdk.getComponent('structures.MyGroups');
         const MatrixToolbar = sdk.getComponent('globals.MatrixToolbar');
@@ -459,8 +459,8 @@ const LoggedInView = React.createClass({
 
             case PageTypes.HomePage:
                 {
-                    pageElement = <HomePage
-                        homePageUrl={this.props.config.welcomePageUrl}
+                    pageElement = <EmbeddedPage className="mx_HomePage"
+                        url={this.props.config.welcomePageUrl || 'home.html'}
                     />;
                 }
                 break;

From 843f86fc1c9b534f9b46445fd94ceb7f98733b71 Mon Sep 17 00:00:00 2001
From: "J. Ryan Stinnett" <jryans@gmail.com>
Date: Thu, 7 Feb 2019 16:25:09 +0000
Subject: [PATCH 04/13] Add separate welcome view

---
 src/components/structures/EmbeddedPage.js | 27 +++++++++++-----
 src/components/structures/LoggedInView.js |  1 +
 src/components/structures/MatrixChat.js   | 34 ++++++++++++++++----
 src/components/views/auth/Welcome.js      | 39 +++++++++++++++++++++++
 4 files changed, 87 insertions(+), 14 deletions(-)
 create mode 100644 src/components/views/auth/Welcome.js

diff --git a/src/components/structures/EmbeddedPage.js b/src/components/structures/EmbeddedPage.js
index 8e5be965e7..bb671094db 100644
--- a/src/components/structures/EmbeddedPage.js
+++ b/src/components/structures/EmbeddedPage.js
@@ -33,6 +33,8 @@ export default class EmbeddedPage extends React.PureComponent {
         url: PropTypes.string,
         // Class name prefix to apply for a given instance
         className: PropTypes.string,
+        // Whether to wrap the page in a scrollbar
+        scrollbar: PropTypes.bool,
     };
 
     static contextTypes = {
@@ -83,19 +85,28 @@ export default class EmbeddedPage extends React.PureComponent {
     }
 
     render() {
-        const isGuest = this.context.matrixClient.isGuest();
+        const client = this.context.matrixClient;
+        const isGuest = client ? client.isGuest() : true;
         const className = this.props.className;
         const classes = classnames({
             [className]: true,
             [`${className}_guest`]: isGuest,
         });
 
-        const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper");
-        return <GeminiScrollbarWrapper autoshow={true} className={classes}>
-            <div className={`${className}_body`}
-                dangerouslySetInnerHTML={{ __html: this.state.page }}
-            >
-            </div>
-        </GeminiScrollbarWrapper>;
+        const content = <div className={`${className}_body`}
+            dangerouslySetInnerHTML={{ __html: this.state.page }}
+        >
+        </div>;
+
+        if (this.props.scrollbar) {
+            const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper");
+            return <GeminiScrollbarWrapper autoshow={true} className={classes}>
+                {content}
+            </GeminiScrollbarWrapper>;
+        } else {
+            return <div className={classes}>
+                {content}
+            </div>;
+        }
     }
 }
diff --git a/src/components/structures/LoggedInView.js b/src/components/structures/LoggedInView.js
index 22a6110674..b285bdc782 100644
--- a/src/components/structures/LoggedInView.js
+++ b/src/components/structures/LoggedInView.js
@@ -461,6 +461,7 @@ const LoggedInView = React.createClass({
                 {
                     pageElement = <EmbeddedPage className="mx_HomePage"
                         url={this.props.config.welcomePageUrl || 'home.html'}
+                        scrollbar={true}
                     />;
                 }
                 break;
diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js
index bb90b2aeb5..a9918ff155 100644
--- a/src/components/structures/MatrixChat.js
+++ b/src/components/structures/MatrixChat.js
@@ -60,27 +60,30 @@ const VIEWS = {
     // trying to re-animate a matrix client or register as a guest.
     LOADING: 0,
 
+    // we are showing the welcome view
+    WELCOME: 1,
+
     // we are showing the login view
-    LOGIN: 1,
+    LOGIN: 2,
 
     // we are showing the registration view
-    REGISTER: 2,
+    REGISTER: 3,
 
     // completeing the registration flow
-    POST_REGISTRATION: 3,
+    POST_REGISTRATION: 4,
 
     // showing the 'forgot password' view
-    FORGOT_PASSWORD: 4,
+    FORGOT_PASSWORD: 5,
 
     // we have valid matrix credentials (either via an explicit login, via the
     // initial re-animation/guest registration, or via a registration), and are
     // now setting up a matrixclient to talk to it. This isn't an instant
     // process because we need to clear out indexeddb. While it is going on we
     // show a big spinner.
-    LOGGING_IN: 5,
+    LOGGING_IN: 6,
 
     // we are logged in with an active matrix client.
-    LOGGED_IN: 6,
+    LOGGED_IN: 7,
 };
 
 // Actions that are redirected through the onboarding process prior to being
@@ -606,6 +609,9 @@ export default React.createClass({
             case 'view_group':
                 this._viewGroup(payload);
                 break;
+            case 'view_welcome_page':
+                this._viewWelcome();
+                break;
             case 'view_home_page':
                 this._viewHome();
                 break;
@@ -881,6 +887,13 @@ export default React.createClass({
         this.notifyNewScreen('group/' + groupId);
     },
 
+    _viewWelcome() {
+        this.setStateForNewView({
+            view: VIEWS.WELCOME,
+        });
+        this.notifyNewScreen('welcome');
+    },
+
     _viewHome: function() {
         // The home page requires the "logged in" view, so we'll set that.
         this.setStateForNewView({
@@ -1466,6 +1479,10 @@ export default React.createClass({
             dis.dispatch({
                 action: 'view_user_settings',
             });
+        } else if (screen == 'welcome') {
+            dis.dispatch({
+                action: 'view_welcome_page',
+            });
         } else if (screen == 'home') {
             dis.dispatch({
                 action: 'view_home_page',
@@ -1849,6 +1866,11 @@ export default React.createClass({
             }
         }
 
+        if (this.state.view === VIEWS.WELCOME) {
+            const Welcome = sdk.getComponent('auth.Welcome');
+            return <Welcome />;
+        }
+
         if (this.state.view === VIEWS.REGISTER) {
             const Registration = sdk.getComponent('structures.auth.Registration');
             return (
diff --git a/src/components/views/auth/Welcome.js b/src/components/views/auth/Welcome.js
new file mode 100644
index 0000000000..162e549724
--- /dev/null
+++ b/src/components/views/auth/Welcome.js
@@ -0,0 +1,39 @@
+/*
+Copyright 2019 New Vector 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 sdk from '../../../index';
+import SdkConfig from '../../../SdkConfig';
+
+export default class Welcome extends React.PureComponent {
+    render() {
+        const AuthPage = sdk.getComponent("auth.AuthPage");
+        const AuthHeader = sdk.getComponent("auth.AuthHeader");
+        const AuthBody = sdk.getComponent("auth.AuthBody");
+        const EmbeddedPage = sdk.getComponent('structures.EmbeddedPage');
+
+        return (
+            <AuthPage>
+                <AuthHeader />
+                <AuthBody>
+                    <EmbeddedPage className="mx_WelcomePage"
+                        url={SdkConfig.get().welcomePageUrl || 'home.html'}
+                    />
+                </AuthBody>
+            </AuthPage>
+        );
+    }
+}

From b7c92ce3ffa7ab32b55265887175f082bf887dd1 Mon Sep 17 00:00:00 2001
From: "J. Ryan Stinnett" <jryans@gmail.com>
Date: Thu, 7 Feb 2019 16:31:44 +0000
Subject: [PATCH 05/13] Abort embedded page load for null URL

---
 src/components/structures/EmbeddedPage.js | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/components/structures/EmbeddedPage.js b/src/components/structures/EmbeddedPage.js
index bb671094db..b73ce21d5e 100644
--- a/src/components/structures/EmbeddedPage.js
+++ b/src/components/structures/EmbeddedPage.js
@@ -57,6 +57,10 @@ export default class EmbeddedPage extends React.PureComponent {
     componentWillMount() {
         this._unmounted = false;
 
+        if (!this.props.url) {
+            return;
+        }
+
         // we use request() to inline the homepage into the react component
         // so that it can inherit CSS and theming easily rather than mess around
         // with iframes and trying to synchronise document.stylesheets.

From 7cc38f9d96a2d26598ef734738e1c4c1b47782c2 Mon Sep 17 00:00:00 2001
From: "J. Ryan Stinnett" <jryans@gmail.com>
Date: Thu, 7 Feb 2019 16:32:33 +0000
Subject: [PATCH 06/13] Remove a few more references to home

---
 src/components/structures/EmbeddedPage.js | 6 +++---
 src/i18n/strings/en_EN.json               | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/components/structures/EmbeddedPage.js b/src/components/structures/EmbeddedPage.js
index b73ce21d5e..d10b7f8414 100644
--- a/src/components/structures/EmbeddedPage.js
+++ b/src/components/structures/EmbeddedPage.js
@@ -61,7 +61,7 @@ export default class EmbeddedPage extends React.PureComponent {
             return;
         }
 
-        // we use request() to inline the homepage into the react component
+        // we use request() to inline the page into the react component
         // so that it can inherit CSS and theming easily rather than mess around
         // with iframes and trying to synchronise document.stylesheets.
 
@@ -73,8 +73,8 @@ export default class EmbeddedPage extends React.PureComponent {
                 }
 
                 if (err || response.status < 200 || response.status >= 300) {
-                    console.warn(`Error loading home page: ${err}`);
-                    this.setState({ page: _t("Couldn't load home page") });
+                    console.warn(`Error loading page: ${err}`);
+                    this.setState({ page: _t("Couldn't load page") });
                     return;
                 }
 
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json
index 14e1a4dae5..f7e4f13ba7 100644
--- a/src/i18n/strings/en_EN.json
+++ b/src/i18n/strings/en_EN.json
@@ -1207,6 +1207,7 @@
     "<safariLink>Safari</safariLink> and <operaLink>Opera</operaLink> work too.": "<safariLink>Safari</safariLink> and <operaLink>Opera</operaLink> work too.",
     "With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!": "With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!",
     "I understand the risks and wish to continue": "I understand the risks and wish to continue",
+    "Couldn't load page": "Couldn't load page",
     "You must <a>register</a> to use this functionality": "You must <a>register</a> to use this functionality",
     "You must join the room to see its files": "You must join the room to see its files",
     "There are no visible files in this room": "There are no visible files in this room",
@@ -1251,7 +1252,6 @@
     "Community %(groupId)s not found": "Community %(groupId)s not found",
     "This homeserver does not support communities": "This homeserver does not support communities",
     "Failed to load %(groupId)s": "Failed to load %(groupId)s",
-    "Couldn't load home page": "Couldn't load home page",
     "Invalid configuration: Cannot supply a default homeserver URL and a default server name": "Invalid configuration: Cannot supply a default homeserver URL and a default server name",
     "Failed to reject invitation": "Failed to reject invitation",
     "This room is not public. You will not be able to rejoin without an invite.": "This room is not public. You will not be able to rejoin without an invite.",

From c587dcab927964f0664b27d28a45828eaf646165 Mon Sep 17 00:00:00 2001
From: "J. Ryan Stinnett" <jryans@gmail.com>
Date: Thu, 7 Feb 2019 17:16:02 +0000
Subject: [PATCH 07/13] Use separate config settings for each page

---
 src/components/structures/LoggedInView.js | 12 +++++++++++-
 src/components/views/auth/Welcome.js      |  5 ++++-
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/src/components/structures/LoggedInView.js b/src/components/structures/LoggedInView.js
index b285bdc782..dda974e41c 100644
--- a/src/components/structures/LoggedInView.js
+++ b/src/components/structures/LoggedInView.js
@@ -459,8 +459,18 @@ const LoggedInView = React.createClass({
 
             case PageTypes.HomePage:
                 {
+                    const pagesConfig = this.props.config.pages;
+                    let pageUrl;
+                    if (pagesConfig) {
+                        pageUrl = pagesConfig.homeUrl;
+                    } else {
+                        // This is a deprecated config option for the home page
+                        // (despite the name, given we also now have a welcome
+                        // page, which is not the same).
+                        pageUrl = this.props.config.welcomePageUrl;
+                    }
                     pageElement = <EmbeddedPage className="mx_HomePage"
-                        url={this.props.config.welcomePageUrl || 'home.html'}
+                        url={pageUrl}
                         scrollbar={true}
                     />;
                 }
diff --git a/src/components/views/auth/Welcome.js b/src/components/views/auth/Welcome.js
index 162e549724..0edbd192ea 100644
--- a/src/components/views/auth/Welcome.js
+++ b/src/components/views/auth/Welcome.js
@@ -25,12 +25,15 @@ export default class Welcome extends React.PureComponent {
         const AuthBody = sdk.getComponent("auth.AuthBody");
         const EmbeddedPage = sdk.getComponent('structures.EmbeddedPage');
 
+        const pagesConfig = SdkConfig.get().pages;
+        const pageUrl = pagesConfig ? pagesConfig.welcomeUrl : 'welcome.html';
+
         return (
             <AuthPage>
                 <AuthHeader />
                 <AuthBody>
                     <EmbeddedPage className="mx_WelcomePage"
-                        url={SdkConfig.get().welcomePageUrl || 'home.html'}
+                        url={pageUrl}
                     />
                 </AuthBody>
             </AuthPage>

From 1cf311da1070ad9a97e30e9ef6b278886161c398 Mon Sep 17 00:00:00 2001
From: "J. Ryan Stinnett" <jryans@gmail.com>
Date: Fri, 8 Feb 2019 09:16:46 +0000
Subject: [PATCH 08/13] Place welcome content directly on glass

---
 src/components/views/auth/Welcome.js | 11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/src/components/views/auth/Welcome.js b/src/components/views/auth/Welcome.js
index 0edbd192ea..96e71394d4 100644
--- a/src/components/views/auth/Welcome.js
+++ b/src/components/views/auth/Welcome.js
@@ -21,8 +21,6 @@ import SdkConfig from '../../../SdkConfig';
 export default class Welcome extends React.PureComponent {
     render() {
         const AuthPage = sdk.getComponent("auth.AuthPage");
-        const AuthHeader = sdk.getComponent("auth.AuthHeader");
-        const AuthBody = sdk.getComponent("auth.AuthBody");
         const EmbeddedPage = sdk.getComponent('structures.EmbeddedPage');
 
         const pagesConfig = SdkConfig.get().pages;
@@ -30,12 +28,9 @@ export default class Welcome extends React.PureComponent {
 
         return (
             <AuthPage>
-                <AuthHeader />
-                <AuthBody>
-                    <EmbeddedPage className="mx_WelcomePage"
-                        url={pageUrl}
-                    />
-                </AuthBody>
+                <EmbeddedPage className="mx_WelcomePage"
+                    url={pageUrl}
+                />
             </AuthPage>
         );
     }

From 7238c713d7912d73750ea88b6632994f1af1fc35 Mon Sep 17 00:00:00 2001
From: "J. Ryan Stinnett" <jryans@gmail.com>
Date: Fri, 8 Feb 2019 11:39:30 +0000
Subject: [PATCH 09/13] Add language selector to bottom of welcome

---
 res/css/_components.scss             |  1 +
 res/css/views/auth/_Welcome.scss     | 26 ++++++++++++++++++++++++++
 src/components/views/auth/Welcome.js | 10 +++++++---
 3 files changed, 34 insertions(+), 3 deletions(-)
 create mode 100644 res/css/views/auth/_Welcome.scss

diff --git a/res/css/_components.scss b/res/css/_components.scss
index dc2091b389..f5fc936bca 100644
--- a/res/css/_components.scss
+++ b/res/css/_components.scss
@@ -34,6 +34,7 @@
 @import "./views/auth/_LanguageSelector.scss";
 @import "./views/auth/_ServerConfig.scss";
 @import "./views/auth/_ServerTypeSelector.scss";
+@import "./views/auth/_Welcome.scss";
 @import "./views/avatars/_BaseAvatar.scss";
 @import "./views/avatars/_MemberStatusMessageAvatar.scss";
 @import "./views/context_menus/_MessageContextMenu.scss";
diff --git a/res/css/views/auth/_Welcome.scss b/res/css/views/auth/_Welcome.scss
new file mode 100644
index 0000000000..9043289184
--- /dev/null
+++ b/res/css/views/auth/_Welcome.scss
@@ -0,0 +1,26 @@
+/*
+Copyright 2019 New Vector 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.
+*/
+
+.mx_Welcome {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+}
+
+.mx_Welcome .mx_AuthBody_language {
+    width: 120px;
+    margin-bottom: 10px;
+}
diff --git a/src/components/views/auth/Welcome.js b/src/components/views/auth/Welcome.js
index 96e71394d4..848655d5f9 100644
--- a/src/components/views/auth/Welcome.js
+++ b/src/components/views/auth/Welcome.js
@@ -22,15 +22,19 @@ export default class Welcome extends React.PureComponent {
     render() {
         const AuthPage = sdk.getComponent("auth.AuthPage");
         const EmbeddedPage = sdk.getComponent('structures.EmbeddedPage');
+        const LanguageSelector = sdk.getComponent('auth.LanguageSelector');
 
         const pagesConfig = SdkConfig.get().pages;
         const pageUrl = pagesConfig ? pagesConfig.welcomeUrl : 'welcome.html';
 
         return (
             <AuthPage>
-                <EmbeddedPage className="mx_WelcomePage"
-                    url={pageUrl}
-                />
+                <div className="mx_Welcome">
+                    <EmbeddedPage className="mx_WelcomePage"
+                        url={pageUrl}
+                    />
+                    <LanguageSelector />
+                </div>
             </AuthPage>
         );
     }

From 5701bf89de36d144248b50182cd320cc6a0ec811 Mon Sep 17 00:00:00 2001
From: "J. Ryan Stinnett" <jryans@gmail.com>
Date: Fri, 8 Feb 2019 12:12:43 +0000
Subject: [PATCH 10/13] Direct some flows to the welcome page

---
 src/Registration.js                     |  8 ++++++--
 src/components/structures/MatrixChat.js | 18 +++++++++++-------
 2 files changed, 17 insertions(+), 9 deletions(-)

diff --git a/src/Registration.js b/src/Registration.js
index f3a2076ed6..42e172ca0b 100644
--- a/src/Registration.js
+++ b/src/Registration.js
@@ -35,8 +35,10 @@ export const SAFE_LOCALPART_REGEX = /^[a-z0-9=_\-./]+$/;
  * on what the HS supports
  *
  * @param {object} options
- * @param {bool} options.go_home_on_cancel If true, goes to
- *     the hame page if the user cancels the action
+ * @param {bool} options.go_home_on_cancel
+ *     If true, goes to the home page if the user cancels the action
+ * @param {bool} options.go_welcome_on_cancel
+ *     If true, goes to the welcome page if the user cancels the action
  */
 export async function startAnyRegistrationFlow(options) {
     if (options === undefined) options = {};
@@ -73,6 +75,8 @@ export async function startAnyRegistrationFlow(options) {
                     dis.dispatch({action: 'start_registration'});
                 } else if (options.go_home_on_cancel) {
                     dis.dispatch({action: 'view_home_page'});
+                } else if (options.go_welcome_on_cancel) {
+                    dis.dispatch({action: 'view_welcome_page'});
                 }
             },
         });
diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js
index a9918ff155..5b01912bb7 100644
--- a/src/components/structures/MatrixChat.js
+++ b/src/components/structures/MatrixChat.js
@@ -357,8 +357,8 @@ export default React.createClass({
                 });
             }).then((loadedSession) => {
                 if (!loadedSession) {
-                    // fall back to showing the login screen
-                    dis.dispatch({action: "start_login"});
+                    // fall back to showing the welcome screen
+                    dis.dispatch({action: "view_welcome_page"});
                 }
             });
             // Note we don't catch errors from this: we catch everything within
@@ -967,11 +967,11 @@ export default React.createClass({
             }
             dis.dispatch({
                 action: 'require_registration',
-                // If the set_mxid dialog is cancelled, view /home because if the browser
-                // was pointing at /user/@someone:domain?action=chat, the URL needs to be
-                // reset so that they can revisit /user/.. // (and trigger
+                // If the set_mxid dialog is cancelled, view /welcome because if the
+                // browser was pointing at /user/@someone:domain?action=chat, the URL
+                // needs to be reset so that they can revisit /user/.. // (and trigger
                 // `_chatCreateOrReuse` again)
-                go_home_on_cancel: true,
+                go_welcome_on_cancel: true,
             });
             return;
         }
@@ -1193,7 +1193,11 @@ export default React.createClass({
                 room_id: localStorage.getItem('mx_last_room_id'),
             });
         } else {
-            dis.dispatch({action: 'view_home_page'});
+            if (MatrixClientPeg.get().isGuest) {
+                dis.dispatch({action: 'view_welcome_page'});
+            } else {
+                dis.dispatch({action: 'view_home_page'});
+            }
         }
     },
 

From 5ab3c8b823d641bb7de7737fd6b8607817586bce Mon Sep 17 00:00:00 2001
From: "J. Ryan Stinnett" <jryans@gmail.com>
Date: Fri, 8 Feb 2019 13:48:51 +0000
Subject: [PATCH 11/13] Add top left home menu item when home page configured

---
 res/css/views/context_menus/_TopLeftMenu.scss |  4 +++
 res/img/feather-icons/home.svg                |  1 +
 .../views/context_menus/TopLeftMenu.js        | 28 ++++++++++++++++++-
 3 files changed, 32 insertions(+), 1 deletion(-)
 create mode 100644 res/img/feather-icons/home.svg

diff --git a/res/css/views/context_menus/_TopLeftMenu.scss b/res/css/views/context_menus/_TopLeftMenu.scss
index 18463da824..f305f0fae3 100644
--- a/res/css/views/context_menus/_TopLeftMenu.scss
+++ b/res/css/views/context_menus/_TopLeftMenu.scss
@@ -27,6 +27,10 @@ limitations under the License.
         margin: 5px 0;
         padding: 0;
 
+        li.mx_TopLeftMenu_icon_home::after {
+            mask-image: url('$(res)/img/feather-icons/home.svg');
+        }
+
         li.mx_TopLeftMenu_icon_settings::after {
             mask-image: url('$(res)/img/feather-icons/settings.svg');
         }
diff --git a/res/img/feather-icons/home.svg b/res/img/feather-icons/home.svg
new file mode 100644
index 0000000000..7bb31b23dc
--- /dev/null
+++ b/res/img/feather-icons/home.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-home"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path><polyline points="9 22 9 12 15 12 15 22"></polyline></svg>
\ No newline at end of file
diff --git a/src/components/views/context_menus/TopLeftMenu.js b/src/components/views/context_menus/TopLeftMenu.js
index 87b277215b..8459db684c 100644
--- a/src/components/views/context_menus/TopLeftMenu.js
+++ b/src/components/views/context_menus/TopLeftMenu.js
@@ -1,5 +1,5 @@
 /*
-Copyright 2018 New Vector Ltd
+Copyright 2018, 2019 New Vector Ltd
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@ import dis from '../../../dispatcher';
 import { _t } from '../../../languageHandler';
 import LogoutDialog from "../dialogs/LogoutDialog";
 import Modal from "../../../Modal";
+import SdkConfig from '../../../SdkConfig';
 
 export class TopLeftMenu extends React.Component {
     constructor() {
@@ -27,8 +28,28 @@ export class TopLeftMenu extends React.Component {
         this.signOut = this.signOut.bind(this);
     }
 
+    hasHomePage() {
+        const config = SdkConfig.get();
+        const pagesConfig = config.pages;
+        if (pagesConfig) {
+            return !!pagesConfig.homeUrl;
+        }
+        // This is a deprecated config option for the home page
+        // (despite the name, given we also now have a welcome
+        // page, which is not the same).
+        return !!config.welcomePageUrl;
+    }
+
     render() {
+        let homePageSection = null;
+        if (this.hasHomePage()) {
+            homePageSection = <ul className="mx_TopLeftMenu_section">
+                <li className="mx_TopLeftMenu_icon_home" onClick={this.viewHomePage}>{_t("Home")}</li>
+            </ul>;
+        }
+
         return <div className="mx_TopLeftMenu">
+            {homePageSection}
             <ul className="mx_TopLeftMenu_section">
                 <li className="mx_TopLeftMenu_icon_settings" onClick={this.openSettings}>{_t("Settings")}</li>
             </ul>
@@ -38,6 +59,11 @@ export class TopLeftMenu extends React.Component {
         </div>;
     }
 
+    viewHomePage() {
+        dis.dispatch({action: 'view_home_page'});
+        this.closeMenu();
+    }
+
     openSettings() {
         dis.dispatch({action: 'view_user_settings'});
         this.closeMenu();

From 7a15bb65c48eca00dcbbdce54bf7e756f02f3fff Mon Sep 17 00:00:00 2001
From: "J. Ryan Stinnett" <jryans@gmail.com>
Date: Fri, 8 Feb 2019 13:53:17 +0000
Subject: [PATCH 12/13] Tweak page URL defaulting

---
 src/components/structures/LoggedInView.js         | 5 +++--
 src/components/views/auth/Welcome.js              | 8 +++++++-
 src/components/views/context_menus/TopLeftMenu.js | 4 ++--
 3 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/src/components/structures/LoggedInView.js b/src/components/structures/LoggedInView.js
index dda974e41c..45bfefefb4 100644
--- a/src/components/structures/LoggedInView.js
+++ b/src/components/structures/LoggedInView.js
@@ -460,10 +460,11 @@ const LoggedInView = React.createClass({
             case PageTypes.HomePage:
                 {
                     const pagesConfig = this.props.config.pages;
-                    let pageUrl;
+                    let pageUrl = null;
                     if (pagesConfig) {
                         pageUrl = pagesConfig.homeUrl;
-                    } else {
+                    }
+                    if (!pageUrl) {
                         // This is a deprecated config option for the home page
                         // (despite the name, given we also now have a welcome
                         // page, which is not the same).
diff --git a/src/components/views/auth/Welcome.js b/src/components/views/auth/Welcome.js
index 848655d5f9..87cc6aca53 100644
--- a/src/components/views/auth/Welcome.js
+++ b/src/components/views/auth/Welcome.js
@@ -25,7 +25,13 @@ export default class Welcome extends React.PureComponent {
         const LanguageSelector = sdk.getComponent('auth.LanguageSelector');
 
         const pagesConfig = SdkConfig.get().pages;
-        const pageUrl = pagesConfig ? pagesConfig.welcomeUrl : 'welcome.html';
+        let pageUrl = null;
+        if (pagesConfig) {
+            pageUrl = pagesConfig.welcomeUrl;
+        }
+        if (!pageUrl) {
+            pageUrl = 'welcome.html';
+        }
 
         return (
             <AuthPage>
diff --git a/src/components/views/context_menus/TopLeftMenu.js b/src/components/views/context_menus/TopLeftMenu.js
index 8459db684c..29118ed785 100644
--- a/src/components/views/context_menus/TopLeftMenu.js
+++ b/src/components/views/context_menus/TopLeftMenu.js
@@ -31,8 +31,8 @@ export class TopLeftMenu extends React.Component {
     hasHomePage() {
         const config = SdkConfig.get();
         const pagesConfig = config.pages;
-        if (pagesConfig) {
-            return !!pagesConfig.homeUrl;
+        if (pagesConfig && pagesConfig.homeUrl) {
+            return true;
         }
         // This is a deprecated config option for the home page
         // (despite the name, given we also now have a welcome

From 705c3248d4dbdb68a28770e230656f6afb81e5e1 Mon Sep 17 00:00:00 2001
From: "J. Ryan Stinnett" <jryans@gmail.com>
Date: Fri, 8 Feb 2019 13:55:23 +0000
Subject: [PATCH 13/13] Tweak embedded pages config name

---
 src/components/structures/LoggedInView.js         | 2 +-
 src/components/views/auth/Welcome.js              | 2 +-
 src/components/views/context_menus/TopLeftMenu.js | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/components/structures/LoggedInView.js b/src/components/structures/LoggedInView.js
index 45bfefefb4..2303083d98 100644
--- a/src/components/structures/LoggedInView.js
+++ b/src/components/structures/LoggedInView.js
@@ -459,7 +459,7 @@ const LoggedInView = React.createClass({
 
             case PageTypes.HomePage:
                 {
-                    const pagesConfig = this.props.config.pages;
+                    const pagesConfig = this.props.config.embeddedPages;
                     let pageUrl = null;
                     if (pagesConfig) {
                         pageUrl = pagesConfig.homeUrl;
diff --git a/src/components/views/auth/Welcome.js b/src/components/views/auth/Welcome.js
index 87cc6aca53..9cc398329d 100644
--- a/src/components/views/auth/Welcome.js
+++ b/src/components/views/auth/Welcome.js
@@ -24,7 +24,7 @@ export default class Welcome extends React.PureComponent {
         const EmbeddedPage = sdk.getComponent('structures.EmbeddedPage');
         const LanguageSelector = sdk.getComponent('auth.LanguageSelector');
 
-        const pagesConfig = SdkConfig.get().pages;
+        const pagesConfig = SdkConfig.get().embeddedPages;
         let pageUrl = null;
         if (pagesConfig) {
             pageUrl = pagesConfig.welcomeUrl;
diff --git a/src/components/views/context_menus/TopLeftMenu.js b/src/components/views/context_menus/TopLeftMenu.js
index 29118ed785..1d58db3c49 100644
--- a/src/components/views/context_menus/TopLeftMenu.js
+++ b/src/components/views/context_menus/TopLeftMenu.js
@@ -30,7 +30,7 @@ export class TopLeftMenu extends React.Component {
 
     hasHomePage() {
         const config = SdkConfig.get();
-        const pagesConfig = config.pages;
+        const pagesConfig = config.embeddedPages;
         if (pagesConfig && pagesConfig.homeUrl) {
             return true;
         }