From 803badba1bf0621774e36d5f48b69a859e56a041 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Fri, 11 Sep 2020 20:20:33 -0600 Subject: [PATCH] Show the user's 3PID invite after they've reloaded the page This is a step towards https://github.com/vector-im/element-web/issues/13430 Since we've stored the invite, we can send the user to it once they reload the page or revisit Element. We currently only support one invite at a time, but this should be fine for most cases. We only do this restoration if the next screen isn't set to avoid breaking the user out of an expected flow. As an added touch, this also ensures that the email address is pre-filled on the registration page if needed, just in case the user refreshes before getting to the submit button. --- src/Lifecycle.js | 11 +++++++++++ src/components/structures/MatrixChat.tsx | 11 ++++++++++- src/stores/ThreepidInviteStore.ts | 25 +++++++++++++++++------- 3 files changed, 39 insertions(+), 8 deletions(-) diff --git a/src/Lifecycle.js b/src/Lifecycle.js index d2de31eb80..dc5718b378 100644 --- a/src/Lifecycle.js +++ b/src/Lifecycle.js @@ -42,6 +42,7 @@ import {Mjolnir} from "./mjolnir/Mjolnir"; import DeviceListener from "./DeviceListener"; import {Jitsi} from "./widgets/Jitsi"; import {SSO_HOMESERVER_URL_KEY, SSO_ID_SERVER_URL_KEY} from "./BasePlatform"; +import ThreepidInviteStore from "./stores/ThreepidInviteStore"; const HOMESERVER_URL_KEY = "mx_hs_url"; const ID_SERVER_URL_KEY = "mx_is_url"; @@ -676,7 +677,17 @@ async function _clearStorage() { Analytics.disable(); if (window.localStorage) { + // try to save any 3pid invites from being obliterated + const pendingInvites = ThreepidInviteStore.instance.getWireInvites(); + window.localStorage.clear(); + + // now restore those invites + pendingInvites.forEach(i => { + const roomId = i.roomId; + delete i.roomId; // delete to avoid confusing the store + ThreepidInviteStore.instance.storeInvite(roomId, i); + }); } if (window.sessionStorage) { diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index 64524641e2..3a8a02c098 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -1214,6 +1214,14 @@ export default class MatrixChat extends React.PureComponent { // the homepage. dis.dispatch({action: 'view_home_page'}); } + } else if (ThreepidInviteStore.instance.pickBestInvite()) { + // The user has a 3pid invite pending - show them that + const threepidInvite = ThreepidInviteStore.instance.pickBestInvite(); + + // HACK: This is a pretty brutal way of threading the invite back through + // our systems, but it's the safest we have for now. + const params = ThreepidInviteStore.instance.translateToWireFormat(threepidInvite); + this.showScreen(`room/${threepidInvite.roomId}`, params) } else { // The user has just logged in after registering, // so show the homepage. @@ -2015,12 +2023,13 @@ export default class MatrixChat extends React.PureComponent { view = ; } else if (this.state.view === Views.REGISTER) { const Registration = sdk.getComponent('structures.auth.Registration'); + const email = ThreepidInviteStore.instance.pickBestInvite()?.toEmail; view = ( {roomId, ...wireInvite}; const id = this.generateIdOf(invite); localStorage.setItem(`${STORAGE_PREFIX}${id}`, JSON.stringify(invite)); return this.translateInvite(invite); } - public getInvites(): IThreepidInvite[] { - const result: IThreepidInvite[] = []; + public getWireInvites(): IPersistedThreepidInvite[] { + const results: IPersistedThreepidInvite[] = []; for (let i = 0; i < localStorage.length; i++) { const keyName = localStorage.key(i); if (!keyName.startsWith(STORAGE_PREFIX)) continue; - - const persisted = JSON.parse(localStorage.getItem(keyName)) as IPersistedThreepidInvite; - result.push(this.translateInvite(persisted)); + results.push(JSON.parse(localStorage.getItem(keyName)) as IPersistedThreepidInvite); } - return result; + return results; + } + + public getInvites(): IThreepidInvite[] { + return this.getWireInvites().map(i => this.translateInvite(i)); } // Currently Element can only handle one invite at a time, so handle that @@ -104,4 +105,14 @@ export default class ThreepidInviteStore extends EventEmitter { inviterName: persisted.inviter_name, }; } + + public translateToWireFormat(invite: IThreepidInvite): IThreepidInviteWireFormat { + return { + email: invite.toEmail, + signurl: invite.signUrl, + room_name: invite.roomName, + room_avatar_url: invite.roomAvatarUrl, + inviter_name: invite.inviterName, + }; + } }