diff --git a/res/css/structures/_LeftPanel.scss b/res/css/structures/_LeftPanel.scss
index f1f27014ee..10357117da 100644
--- a/res/css/structures/_LeftPanel.scss
+++ b/res/css/structures/_LeftPanel.scss
@@ -19,7 +19,8 @@ $roomListCollapsedWidth: 68px;
 
 .mx_LeftPanel {
     background-color: $roomlist-bg-color;
-    min-width: 260px;
+    // TODO decrease this once Spaces launches as it'll no longer need to include the 56px Community Panel
+    min-width: 206px;
     max-width: 50%;
 
     // Create a row-based flexbox for the GroupFilterPanel and the room list
diff --git a/res/css/structures/_MatrixChat.scss b/res/css/structures/_MatrixChat.scss
index 812a7f8472..a220c5d505 100644
--- a/res/css/structures/_MatrixChat.scss
+++ b/res/css/structures/_MatrixChat.scss
@@ -66,7 +66,7 @@ limitations under the License.
 }
 
 /* not the left panel, and not the resize handle, so the roomview/groupview/... */
-.mx_MatrixChat > :not(.mx_LeftPanel):not(.mx_ResizeHandle) {
+.mx_MatrixChat > :not(.mx_LeftPanel):not(.mx_SpacePanel):not(.mx_ResizeHandle) {
     background-color: $primary-bg-color;
 
     flex: 1 1 0;
diff --git a/src/components/structures/LeftPanel.tsx b/src/components/structures/LeftPanel.tsx
index 9a1ce63785..f46319235a 100644
--- a/src/components/structures/LeftPanel.tsx
+++ b/src/components/structures/LeftPanel.tsx
@@ -38,7 +38,6 @@ import AccessibleTooltipButton from "../views/elements/AccessibleTooltipButton";
 import { OwnProfileStore } from "../../stores/OwnProfileStore";
 import RoomListNumResults from "../views/rooms/RoomListNumResults";
 import LeftPanelWidget from "./LeftPanelWidget";
-import SpacePanel from "../views/spaces/SpacePanel";
 import {replaceableComponent} from "../../utils/replaceableComponent";
 import {mediaFromMxc} from "../../customisations/Media";
 
@@ -392,11 +391,7 @@ export default class LeftPanel extends React.Component<IProps, IState> {
 
     public render(): React.ReactNode {
         let leftLeftPanel;
-        // Currently TagPanel.enableTagPanel is disabled when Legacy Communities are disabled so for now
-        // ignore it and force the rendering of SpacePanel if that Labs flag is enabled.
-        if (SettingsStore.getValue("feature_spaces")) {
-            leftLeftPanel = <SpacePanel />;
-        } else if (this.state.showGroupFilterPanel) {
+        if (this.state.showGroupFilterPanel) {
             leftLeftPanel = (
                 <div className="mx_LeftPanel_GroupFilterPanelContainer">
                     <GroupFilterPanel />
diff --git a/src/components/structures/LoggedInView.tsx b/src/components/structures/LoggedInView.tsx
index 936eb819ba..60a2bf4ada 100644
--- a/src/components/structures/LoggedInView.tsx
+++ b/src/components/structures/LoggedInView.tsx
@@ -56,6 +56,7 @@ import Modal from "../../Modal";
 import { ICollapseConfig } from "../../resizer/distributors/collapse";
 import HostSignupContainer from '../views/host_signup/HostSignupContainer';
 import { IOpts } from "../../createRoom";
+import SpacePanel from "../views/spaces/SpacePanel";
 import {replaceableComponent} from "../../utils/replaceableComponent";
 
 // We need to fetch each pinned message individually (if we don't already have it)
@@ -229,14 +230,8 @@ class LoggedInView extends React.Component<IProps, IState> {
         let size;
         let collapsed;
         const collapseConfig: ICollapseConfig = {
-            // TODO: the space panel currently does not have a fixed width,
-            // just the headers at each level have a max-width of 150px
-            // Taking 222px for the space panel for now,
-            // so this will look slightly off for now,
-            // depending on the depth of your space tree.
-            // To fix this, we'll need to turn toggleSize
-            // into a callback so it can be measured when starting the resize operation
-            toggleSize: 222 + 68,
+            // TODO decrease this once Spaces launches as it'll no longer need to include the 56px Community Panel
+            toggleSize: 206 - 50,
             onCollapsed: (_collapsed) => {
                 collapsed = _collapsed;
                 if (_collapsed) {
@@ -670,13 +665,6 @@ class LoggedInView extends React.Component<IProps, IState> {
             bodyClasses += ' mx_MatrixChat_useCompactLayout';
         }
 
-        const leftPanel = (
-            <LeftPanel
-                isMinimized={this.props.collapseLhs || false}
-                resizeNotifier={this.props.resizeNotifier}
-            />
-        );
-
         return (
             <MatrixClientContext.Provider value={this._matrixClient}>
                 <div
@@ -688,7 +676,11 @@ class LoggedInView extends React.Component<IProps, IState> {
                     <ToastContainer />
                     <DragDropContext onDragEnd={this._onDragEnd}>
                         <div ref={this._resizeContainer} className={bodyClasses}>
-                            { leftPanel }
+                            { SettingsStore.getValue("feature_spaces") ? <SpacePanel /> : null }
+                            <LeftPanel
+                                isMinimized={this.props.collapseLhs || false}
+                                resizeNotifier={this.props.resizeNotifier}
+                            />
                             <ResizeHandle />
                             { pageElement }
                         </div>
diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js
index 439bdbcef5..f4334ffe87 100644
--- a/src/components/structures/MessagePanel.js
+++ b/src/components/structures/MessagePanel.js
@@ -23,7 +23,6 @@ import classNames from 'classnames';
 import shouldHideEvent from '../../shouldHideEvent';
 import {wantsDateSeparator} from '../../DateUtils';
 import * as sdk from '../../index';
-import dis from "../../dispatcher/dispatcher";
 
 import {MatrixClientPeg} from '../../MatrixClientPeg';
 import SettingsStore from '../../settings/SettingsStore';
@@ -210,13 +209,11 @@ export default class MessagePanel extends React.Component {
 
     componentDidMount() {
         this._isMounted = true;
-        this.dispatcherRef = dis.register(this.onAction);
     }
 
     componentWillUnmount() {
         this._isMounted = false;
         SettingsStore.unwatchSetting(this._showTypingNotificationsWatcherRef);
-        dis.unregister(this.dispatcherRef);
     }
 
     componentDidUpdate(prevProps, prevState) {
@@ -229,14 +226,6 @@ export default class MessagePanel extends React.Component {
         }
     }
 
-    onAction = (payload) => {
-        switch (payload.action) {
-            case "scroll_to_bottom":
-                this.scrollToBottom();
-                break;
-        }
-    }
-
     onShowTypingNotificationsChange = () => {
         this.setState({
             showTypingNotifications: SettingsStore.getValue("showTypingNotifications"),
diff --git a/src/components/structures/TimelinePanel.js b/src/components/structures/TimelinePanel.js
index f32b8ed0a9..84193eae4c 100644
--- a/src/components/structures/TimelinePanel.js
+++ b/src/components/structures/TimelinePanel.js
@@ -463,6 +463,9 @@ class TimelinePanel extends React.Component {
                 }
             });
         }
+        if (payload.action === "scroll_to_bottom") {
+            this.jumpToLiveTimeline();
+        }
     };
 
     onRoomTimeline = (ev, room, toStartOfTimeline, removed, data) => {
diff --git a/src/components/structures/auth/Registration.tsx b/src/components/structures/auth/Registration.tsx
index 32bdddb82a..9d004de2ec 100644
--- a/src/components/structures/auth/Registration.tsx
+++ b/src/components/structures/auth/Registration.tsx
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import Matrix from 'matrix-js-sdk';
+import {createClient} from 'matrix-js-sdk/src/matrix';
 import React, {ReactNode} from 'react';
 import {MatrixClient} from "matrix-js-sdk/src/client";
 
@@ -181,7 +181,7 @@ export default class Registration extends React.Component<IProps, IState> {
         }
 
         const {hsUrl, isUrl} = serverConfig;
-        const cli = Matrix.createClient({
+        const cli = createClient({
             baseUrl: hsUrl,
             idBaseUrl: isUrl,
         });
diff --git a/src/components/views/settings/tabs/user/VoiceUserSettingsTab.js b/src/components/views/settings/tabs/user/VoiceUserSettingsTab.js
index bc6fe796b8..d8adab55f6 100644
--- a/src/components/views/settings/tabs/user/VoiceUserSettingsTab.js
+++ b/src/components/views/settings/tabs/user/VoiceUserSettingsTab.js
@@ -84,6 +84,7 @@ export default class VoiceUserSettingsTab extends React.Component {
             }
         }
         if (error) {
+            console.log("Failed to list userMedia devices", error);
             const brand = SdkConfig.get().brand;
             const ErrorDialog = sdk.getComponent('dialogs.ErrorDialog');
             Modal.createTrackedDialog('No media permissions', '', ErrorDialog, {
diff --git a/src/rageshake/rageshake.js b/src/rageshake/rageshake.js
index 8eb77bb3ae..b886f369df 100644
--- a/src/rageshake/rageshake.js
+++ b/src/rageshake/rageshake.js
@@ -434,15 +434,37 @@ function selectQuery(store, keyRange, resultMapper) {
 /**
  * Configure rage shaking support for sending bug reports.
  * Modifies globals.
+ * @param {boolean} setUpPersistence When true (default), the persistence will
+ * be set up immediately for the logs.
  * @return {Promise} Resolves when set up.
  */
-export function init() {
+export function init(setUpPersistence = true) {
     if (global.mx_rage_initPromise) {
         return global.mx_rage_initPromise;
     }
     global.mx_rage_logger = new ConsoleLogger();
     global.mx_rage_logger.monkeyPatch(window.console);
 
+    if (setUpPersistence) {
+        return tryInitStorage();
+    }
+
+    global.mx_rage_initPromise = Promise.resolve();
+    return global.mx_rage_initPromise;
+}
+
+/**
+ * Try to start up the rageshake storage for logs. If not possible (client unsupported)
+ * then this no-ops.
+ * @return {Promise} Resolves when complete.
+ */
+export function tryInitStorage() {
+    if (global.mx_rage_initStoragePromise) {
+        return global.mx_rage_initStoragePromise;
+    }
+
+    console.log("Configuring rageshake persistence...");
+
     // just *accessing* indexedDB throws an exception in firefox with
     // indexeddb disabled.
     let indexedDB;
@@ -452,11 +474,11 @@ export function init() {
 
     if (indexedDB) {
         global.mx_rage_store = new IndexedDBLogStore(indexedDB, global.mx_rage_logger);
-        global.mx_rage_initPromise = global.mx_rage_store.connect();
-        return global.mx_rage_initPromise;
+        global.mx_rage_initStoragePromise = global.mx_rage_store.connect();
+        return global.mx_rage_initStoragePromise;
     }
-    global.mx_rage_initPromise = Promise.resolve();
-    return global.mx_rage_initPromise;
+    global.mx_rage_initStoragePromise = Promise.resolve();
+    return global.mx_rage_initStoragePromise;
 }
 
 export function flush() {