From 982e81f9a38573c303b7989a29ea180d18b12acb Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Mon, 25 May 2020 15:43:21 -0600
Subject: [PATCH 1/5] Rename MatrixClientPeg to ts

---
 src/{MatrixClientPeg.js => MatrixClientPeg.ts} | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename src/{MatrixClientPeg.js => MatrixClientPeg.ts} (100%)

diff --git a/src/MatrixClientPeg.js b/src/MatrixClientPeg.ts
similarity index 100%
rename from src/MatrixClientPeg.js
rename to src/MatrixClientPeg.ts

From bd2d13edd23aa341f14081e5b536f614b82eb2bf Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Mon, 25 May 2020 15:52:05 -0600
Subject: [PATCH 2/5] Convert the MatrixClientPeg to TypeScript

---
 src/MatrixClientPeg.ts | 90 +++++++++++++++++++++++++-----------------
 1 file changed, 53 insertions(+), 37 deletions(-)

diff --git a/src/MatrixClientPeg.ts b/src/MatrixClientPeg.ts
index 21f05b9759..2c35129734 100644
--- a/src/MatrixClientPeg.ts
+++ b/src/MatrixClientPeg.ts
@@ -17,8 +17,8 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import {MatrixClient, MemoryStore} from 'matrix-js-sdk';
-
+import {MatrixClient} from 'matrix-js-sdk/src/client';
+import {MemoryStore} from 'matrix-js-sdk/src/store/memory';
 import * as utils from 'matrix-js-sdk/src/utils';
 import {EventTimeline} from 'matrix-js-sdk/src/models/event-timeline';
 import {EventTimelineSet} from 'matrix-js-sdk/src/models/event-timeline-set';
@@ -34,7 +34,7 @@ import IdentityAuthClient from './IdentityAuthClient';
 import { crossSigningCallbacks } from './CrossSigningManager';
 import {SHOW_QR_CODE_METHOD} from "matrix-js-sdk/src/crypto/verification/QRCode";
 
-interface MatrixClientCreds {
+interface ICredentials {
     homeserverUrl: string,
     identityServerUrl: string,
     userId: string,
@@ -43,6 +43,13 @@ interface MatrixClientCreds {
     guest: boolean,
 }
 
+// TODO: Move this to the js-sdk
+interface IOpts {
+    initialSyncLimit?: number;
+    pendingEventOrdering?: "detached" | "chronological";
+    lazyLoadMembers?: boolean;
+}
+
 /**
  * Wrapper object for handling the js-sdk Matrix Client object in the react-sdk
  * Handles the creation/initialisation of client objects.
@@ -50,20 +57,22 @@ interface MatrixClientCreds {
  * Matrix Client object is available easily.
  */
 class _MatrixClientPeg {
-    constructor() {
-        this.matrixClient = null;
-        this._justRegisteredUserId = null;
+    private matrixClient: MatrixClient;
+    private justRegisteredUserId: string;
 
-        // These are the default options used when when the
-        // client is started in 'start'. These can be altered
-        // at any time up to after the 'will_start_client'
-        // event is finished processing.
-        this.opts = {
-            initialSyncLimit: 20,
-        };
-        // the credentials used to init the current client object.
-        // used if we tear it down & recreate it with a different store
-        this._currentClientCreds = null;
+    // These are the default options used when when the
+    // client is started in 'start'. These can be altered
+    // at any time up to after the 'will_start_client'
+    // event is finished processing.
+    private opts: IOpts = {
+        initialSyncLimit: 20,
+    };
+
+    // the credentials used to init the current client object.
+    // used if we tear it down & recreate it with a different store
+    private currentClientCreds: ICredentials;
+
+    constructor() {
     }
 
     /**
@@ -73,15 +82,15 @@ class _MatrixClientPeg {
      *
      * @param {string} script href to the script to be passed to the web worker
      */
-    setIndexedDbWorkerScript(script) {
+    public setIndexedDbWorkerScript(script: string): void {
         createMatrixClient.indexedDbWorkerScript = script;
     }
 
-    get(): MatrixClient {
+    public get(): MatrixClient {
         return this.matrixClient;
     }
 
-    unset() {
+    public unset(): void {
         this.matrixClient = null;
 
         MatrixActionCreators.stop();
@@ -95,8 +104,8 @@ class _MatrixClientPeg {
      *
      * @param {string} uid The user ID of the user we've just registered
      */
-    setJustRegisteredUserId(uid) {
-        this._justRegisteredUserId = uid;
+    public setJustRegisteredUserId(uid: string): void {
+        this.justRegisteredUserId = uid;
     }
 
     /**
@@ -105,23 +114,25 @@ class _MatrixClientPeg {
      *
      * @returns {bool} True if user has just been registered
      */
-    currentUserIsJustRegistered() {
+    public currentUserIsJustRegistered(): boolean {
         return (
             this.matrixClient &&
-            this.matrixClient.credentials.userId === this._justRegisteredUserId
+            this.matrixClient.credentials.userId === this.justRegisteredUserId
         );
     }
 
-    /*
+    /**
      * Replace this MatrixClientPeg's client with a client instance that has
      * homeserver / identity server URLs and active credentials
+     *
+     * @param {ICredentials} creds The new credentials to use.
      */
-    replaceUsingCreds(creds: MatrixClientCreds) {
-        this._currentClientCreds = creds;
+    public replaceUsingCreds(creds: ICredentials): void {
+        this.currentClientCreds = creds;
         this._createClient(creds);
     }
 
-    async assign() {
+    public async assign(): Promise<any> {
         for (const dbType of ['indexeddb', 'memory']) {
             try {
                 const promise = this.matrixClient.store.startup();
@@ -132,7 +143,7 @@ class _MatrixClientPeg {
                 if (dbType === 'indexeddb') {
                     console.error('Error starting matrixclient store - falling back to memory store', err);
                     this.matrixClient.store = new MemoryStore({
-                        localStorage: global.localStorage,
+                        localStorage: localStorage,
                     });
                 } else {
                     console.error('Failed to start memory store!', err);
@@ -179,7 +190,7 @@ class _MatrixClientPeg {
         return opts;
     }
 
-    async start() {
+    public async start(): Promise<any> {
         const opts = await this.assign();
 
         console.log(`MatrixClientPeg: really starting MatrixClient`);
@@ -187,7 +198,7 @@ class _MatrixClientPeg {
         console.log(`MatrixClientPeg: MatrixClient started`);
     }
 
-    getCredentials(): MatrixClientCreds {
+    public getCredentials(): ICredentials {
         return {
             homeserverUrl: this.matrixClient.baseUrl,
             identityServerUrl: this.matrixClient.idBaseUrl,
@@ -198,12 +209,14 @@ class _MatrixClientPeg {
         };
     }
 
-    /*
+    /**
      * Return the server name of the user's homeserver
      * Throws an error if unable to deduce the homeserver name
      * (eg. if the user is not logged in)
+     *
+     * @returns {string} The homeserver name, if present.
      */
-    getHomeserverName() {
+    public getHomeserverName(): string {
         const matches = /^@.+:(.+)$/.exec(this.matrixClient.credentials.userId);
         if (matches === null || matches.length < 1) {
             throw new Error("Failed to derive homeserver name from user ID!");
@@ -211,7 +224,8 @@ class _MatrixClientPeg {
         return matches[1];
     }
 
-    _createClient(creds: MatrixClientCreds) {
+    private _createClient(creds: ICredentials): void {
+        // TODO: Make these opts typesafe with the js-sdk
         const opts = {
             baseUrl: creds.homeserverUrl,
             idBaseUrl: creds.identityServerUrl,
@@ -228,9 +242,9 @@ class _MatrixClientPeg {
             ],
             unstableClientRelationAggregation: true,
             identityServer: new IdentityAuthClient(),
+            cryptoCallbacks: {},
         };
 
-        opts.cryptoCallbacks = {};
         // These are always installed regardless of the labs flag so that
         // cross-signing features can toggle on without reloading and also be
         // accessed immediately after login.
@@ -253,8 +267,10 @@ class _MatrixClientPeg {
     }
 }
 
-if (!global.mxMatrixClientPeg) {
-    global.mxMatrixClientPeg = new _MatrixClientPeg();
+const anyGlobal = <any>global;
+
+if (!anyGlobal.mxMatrixClientPeg) {
+    anyGlobal.mxMatrixClientPeg = new _MatrixClientPeg();
 }
 
-export const MatrixClientPeg = global.mxMatrixClientPeg;
+export const MatrixClientPeg = <_MatrixClientPeg>anyGlobal.mxMatrixClientPeg;

From 0cec74cc2b436ec3b1f7e7fd6e0d05b650263fcc Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Mon, 25 May 2020 15:59:15 -0600
Subject: [PATCH 3/5] Appease the linter (and the project)

Also export the interface that the project expects to be able to import :|
---
 src/MatrixClientPeg.ts                     | 20 ++++++++++----------
 src/components/structures/LoggedInView.tsx |  4 ++--
 2 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/src/MatrixClientPeg.ts b/src/MatrixClientPeg.ts
index 2c35129734..2a89b05a39 100644
--- a/src/MatrixClientPeg.ts
+++ b/src/MatrixClientPeg.ts
@@ -34,7 +34,7 @@ import IdentityAuthClient from './IdentityAuthClient';
 import { crossSigningCallbacks } from './CrossSigningManager';
 import {SHOW_QR_CODE_METHOD} from "matrix-js-sdk/src/crypto/verification/QRCode";
 
-interface ICredentials {
+export interface IMatrixClientCreds {
     homeserverUrl: string,
     identityServerUrl: string,
     userId: string,
@@ -57,20 +57,20 @@ interface IOpts {
  * Matrix Client object is available easily.
  */
 class _MatrixClientPeg {
-    private matrixClient: MatrixClient;
-    private justRegisteredUserId: string;
-
     // These are the default options used when when the
     // client is started in 'start'. These can be altered
     // at any time up to after the 'will_start_client'
     // event is finished processing.
-    private opts: IOpts = {
+    public opts: IOpts = {
         initialSyncLimit: 20,
     };
 
+    private matrixClient: MatrixClient;
+    private justRegisteredUserId: string;
+
     // the credentials used to init the current client object.
     // used if we tear it down & recreate it with a different store
-    private currentClientCreds: ICredentials;
+    private currentClientCreds: IMatrixClientCreds;
 
     constructor() {
     }
@@ -125,9 +125,9 @@ class _MatrixClientPeg {
      * Replace this MatrixClientPeg's client with a client instance that has
      * homeserver / identity server URLs and active credentials
      *
-     * @param {ICredentials} creds The new credentials to use.
+     * @param {IMatrixClientCreds} creds The new credentials to use.
      */
-    public replaceUsingCreds(creds: ICredentials): void {
+    public replaceUsingCreds(creds: IMatrixClientCreds): void {
         this.currentClientCreds = creds;
         this._createClient(creds);
     }
@@ -198,7 +198,7 @@ class _MatrixClientPeg {
         console.log(`MatrixClientPeg: MatrixClient started`);
     }
 
-    public getCredentials(): ICredentials {
+    public getCredentials(): IMatrixClientCreds {
         return {
             homeserverUrl: this.matrixClient.baseUrl,
             identityServerUrl: this.matrixClient.idBaseUrl,
@@ -224,7 +224,7 @@ class _MatrixClientPeg {
         return matches[1];
     }
 
-    private _createClient(creds: ICredentials): void {
+    private _createClient(creds: IMatrixClientCreds): void {
         // TODO: Make these opts typesafe with the js-sdk
         const opts = {
             baseUrl: creds.homeserverUrl,
diff --git a/src/components/structures/LoggedInView.tsx b/src/components/structures/LoggedInView.tsx
index 148d10fe8d..f502b4da4b 100644
--- a/src/components/structures/LoggedInView.tsx
+++ b/src/components/structures/LoggedInView.tsx
@@ -29,7 +29,7 @@ import { fixupColorFonts } from '../../utils/FontManager';
 import * as sdk from '../../index';
 import dis from '../../dispatcher/dispatcher';
 import sessionStore from '../../stores/SessionStore';
-import {MatrixClientPeg, MatrixClientCreds} from '../../MatrixClientPeg';
+import {MatrixClientPeg, IMatrixClientCreds} from '../../MatrixClientPeg';
 import SettingsStore from "../../settings/SettingsStore";
 
 import TagOrderActions from '../../actions/TagOrderActions';
@@ -57,7 +57,7 @@ function canElementReceiveInput(el) {
 
 interface IProps {
     matrixClient: MatrixClient;
-    onRegistered: (credentials: MatrixClientCreds) => Promise<MatrixClient>;
+    onRegistered: (credentials: IMatrixClientCreds) => Promise<MatrixClient>;
     viaServers?: string[];
     hideToSRUsers: boolean;
     resizeNotifier: ResizeNotifier;

From e5c2d17015700ffae6ff676ea68360d6f02baf2f Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Mon, 25 May 2020 16:06:05 -0600
Subject: [PATCH 4/5] Move the instance definition to the Window

---
 src/@types/global.d.ts |   2 +
 src/MatrixClientPeg.ts | 101 ++++++++++++++++++++++++-----------------
 2 files changed, 62 insertions(+), 41 deletions(-)

diff --git a/src/@types/global.d.ts b/src/@types/global.d.ts
index e6e339d067..87e1e44341 100644
--- a/src/@types/global.d.ts
+++ b/src/@types/global.d.ts
@@ -15,10 +15,12 @@ limitations under the License.
 */
 
 import * as ModernizrStatic from "modernizr";
+import { IMatrixClientPeg } from "../MatrixClientPeg";
 
 declare global {
     interface Window {
         Modernizr: ModernizrStatic;
+        mxMatrixClientPeg: IMatrixClientPeg;
         Olm: {
             init: () => Promise<void>;
         };
diff --git a/src/MatrixClientPeg.ts b/src/MatrixClientPeg.ts
index 2a89b05a39..ab19295263 100644
--- a/src/MatrixClientPeg.ts
+++ b/src/MatrixClientPeg.ts
@@ -44,19 +44,74 @@ export interface IMatrixClientCreds {
 }
 
 // TODO: Move this to the js-sdk
-interface IOpts {
+export interface IOpts {
     initialSyncLimit?: number;
     pendingEventOrdering?: "detached" | "chronological";
     lazyLoadMembers?: boolean;
 }
 
+export interface IMatrixClientPeg {
+    opts: IOpts;
+
+    /**
+     * Sets the script href passed to the IndexedDB web worker
+     * If set, a separate web worker will be started to run the IndexedDB
+     * queries on.
+     *
+     * @param {string} script href to the script to be passed to the web worker
+     */
+    setIndexedDbWorkerScript(script: string): void;
+
+    /**
+     * Return the server name of the user's homeserver
+     * Throws an error if unable to deduce the homeserver name
+     * (eg. if the user is not logged in)
+     *
+     * @returns {string} The homeserver name, if present.
+     */
+    getHomeserverName(): string;
+
+    get(): MatrixClient;
+    unset(): void;
+    assign(): Promise<any>;
+    start(): Promise<any>;
+
+    getCredentials(): IMatrixClientCreds;
+
+    /**
+     * If we've registered a user ID we set this to the ID of the
+     * user we've just registered. If they then go & log in, we
+     * can send them to the welcome user (obviously this doesn't
+     * guarentee they'll get a chat with the welcome user).
+     *
+     * @param {string} uid The user ID of the user we've just registered
+     */
+    setJustRegisteredUserId(uid: string): void;
+
+    /**
+     * Returns true if the current user has just been registered by this
+     * client as determined by setJustRegisteredUserId()
+     *
+     * @returns {bool} True if user has just been registered
+     */
+    currentUserIsJustRegistered(): boolean;
+
+    /**
+     * Replace this MatrixClientPeg's client with a client instance that has
+     * homeserver / identity server URLs and active credentials
+     *
+     * @param {IMatrixClientCreds} creds The new credentials to use.
+     */
+    replaceUsingCreds(creds: IMatrixClientCreds): void;
+}
+
 /**
  * Wrapper object for handling the js-sdk Matrix Client object in the react-sdk
  * Handles the creation/initialisation of client objects.
  * This module provides a singleton instance of this class so the 'current'
  * Matrix Client object is available easily.
  */
-class _MatrixClientPeg {
+class _MatrixClientPeg implements IMatrixClientPeg {
     // These are the default options used when when the
     // client is started in 'start'. These can be altered
     // at any time up to after the 'will_start_client'
@@ -75,13 +130,6 @@ class _MatrixClientPeg {
     constructor() {
     }
 
-    /**
-     * Sets the script href passed to the IndexedDB web worker
-     * If set, a separate web worker will be started to run the IndexedDB
-     * queries on.
-     *
-     * @param {string} script href to the script to be passed to the web worker
-     */
     public setIndexedDbWorkerScript(script: string): void {
         createMatrixClient.indexedDbWorkerScript = script;
     }
@@ -96,24 +144,10 @@ class _MatrixClientPeg {
         MatrixActionCreators.stop();
     }
 
-    /**
-     * If we've registered a user ID we set this to the ID of the
-     * user we've just registered. If they then go & log in, we
-     * can send them to the welcome user (obviously this doesn't
-     * guarentee they'll get a chat with the welcome user).
-     *
-     * @param {string} uid The user ID of the user we've just registered
-     */
     public setJustRegisteredUserId(uid: string): void {
         this.justRegisteredUserId = uid;
     }
 
-    /**
-     * Returns true if the current user has just been registered by this
-     * client as determined by setJustRegisteredUserId()
-     *
-     * @returns {bool} True if user has just been registered
-     */
     public currentUserIsJustRegistered(): boolean {
         return (
             this.matrixClient &&
@@ -121,12 +155,6 @@ class _MatrixClientPeg {
         );
     }
 
-    /**
-     * Replace this MatrixClientPeg's client with a client instance that has
-     * homeserver / identity server URLs and active credentials
-     *
-     * @param {IMatrixClientCreds} creds The new credentials to use.
-     */
     public replaceUsingCreds(creds: IMatrixClientCreds): void {
         this.currentClientCreds = creds;
         this._createClient(creds);
@@ -209,13 +237,6 @@ class _MatrixClientPeg {
         };
     }
 
-    /**
-     * Return the server name of the user's homeserver
-     * Throws an error if unable to deduce the homeserver name
-     * (eg. if the user is not logged in)
-     *
-     * @returns {string} The homeserver name, if present.
-     */
     public getHomeserverName(): string {
         const matches = /^@.+:(.+)$/.exec(this.matrixClient.credentials.userId);
         if (matches === null || matches.length < 1) {
@@ -267,10 +288,8 @@ class _MatrixClientPeg {
     }
 }
 
-const anyGlobal = <any>global;
-
-if (!anyGlobal.mxMatrixClientPeg) {
-    anyGlobal.mxMatrixClientPeg = new _MatrixClientPeg();
+if (!window.mxMatrixClientPeg) {
+    window.mxMatrixClientPeg = new _MatrixClientPeg();
 }
 
-export const MatrixClientPeg = <_MatrixClientPeg>anyGlobal.mxMatrixClientPeg;
+export const MatrixClientPeg = window.mxMatrixClientPeg;

From 1c9b5eb42d99ddcc8ac04c9f8fed0ca1a5dd2a67 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Mon, 25 May 2020 16:14:51 -0600
Subject: [PATCH 5/5] Appease the tests

---
 src/MatrixClientPeg.ts | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/MatrixClientPeg.ts b/src/MatrixClientPeg.ts
index ab19295263..ff0750c501 100644
--- a/src/MatrixClientPeg.ts
+++ b/src/MatrixClientPeg.ts
@@ -120,7 +120,7 @@ class _MatrixClientPeg implements IMatrixClientPeg {
         initialSyncLimit: 20,
     };
 
-    private matrixClient: MatrixClient;
+    private matrixClient: MatrixClient = null;
     private justRegisteredUserId: string;
 
     // the credentials used to init the current client object.
@@ -157,7 +157,7 @@ class _MatrixClientPeg implements IMatrixClientPeg {
 
     public replaceUsingCreds(creds: IMatrixClientCreds): void {
         this.currentClientCreds = creds;
-        this._createClient(creds);
+        this.createClient(creds);
     }
 
     public async assign(): Promise<any> {
@@ -245,7 +245,7 @@ class _MatrixClientPeg implements IMatrixClientPeg {
         return matches[1];
     }
 
-    private _createClient(creds: IMatrixClientCreds): void {
+    private createClient(creds: IMatrixClientCreds): void {
         // TODO: Make these opts typesafe with the js-sdk
         const opts = {
             baseUrl: creds.homeserverUrl,