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.
This commit is contained in:
parent
a5d7b24805
commit
803badba1b
3 changed files with 39 additions and 8 deletions
|
@ -42,6 +42,7 @@ import {Mjolnir} from "./mjolnir/Mjolnir";
|
||||||
import DeviceListener from "./DeviceListener";
|
import DeviceListener from "./DeviceListener";
|
||||||
import {Jitsi} from "./widgets/Jitsi";
|
import {Jitsi} from "./widgets/Jitsi";
|
||||||
import {SSO_HOMESERVER_URL_KEY, SSO_ID_SERVER_URL_KEY} from "./BasePlatform";
|
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 HOMESERVER_URL_KEY = "mx_hs_url";
|
||||||
const ID_SERVER_URL_KEY = "mx_is_url";
|
const ID_SERVER_URL_KEY = "mx_is_url";
|
||||||
|
@ -676,7 +677,17 @@ async function _clearStorage() {
|
||||||
Analytics.disable();
|
Analytics.disable();
|
||||||
|
|
||||||
if (window.localStorage) {
|
if (window.localStorage) {
|
||||||
|
// try to save any 3pid invites from being obliterated
|
||||||
|
const pendingInvites = ThreepidInviteStore.instance.getWireInvites();
|
||||||
|
|
||||||
window.localStorage.clear();
|
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) {
|
if (window.sessionStorage) {
|
||||||
|
|
|
@ -1214,6 +1214,14 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||||
// the homepage.
|
// the homepage.
|
||||||
dis.dispatch({action: 'view_home_page'});
|
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 {
|
} else {
|
||||||
// The user has just logged in after registering,
|
// The user has just logged in after registering,
|
||||||
// so show the homepage.
|
// so show the homepage.
|
||||||
|
@ -2015,12 +2023,13 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||||
view = <Welcome />;
|
view = <Welcome />;
|
||||||
} else if (this.state.view === Views.REGISTER) {
|
} else if (this.state.view === Views.REGISTER) {
|
||||||
const Registration = sdk.getComponent('structures.auth.Registration');
|
const Registration = sdk.getComponent('structures.auth.Registration');
|
||||||
|
const email = ThreepidInviteStore.instance.pickBestInvite()?.toEmail;
|
||||||
view = (
|
view = (
|
||||||
<Registration
|
<Registration
|
||||||
clientSecret={this.state.register_client_secret}
|
clientSecret={this.state.register_client_secret}
|
||||||
sessionId={this.state.register_session_id}
|
sessionId={this.state.register_session_id}
|
||||||
idSid={this.state.register_id_sid}
|
idSid={this.state.register_id_sid}
|
||||||
email={this.props.startingFragmentQueryParams.email}
|
email={email}
|
||||||
brand={this.props.config.brand}
|
brand={this.props.config.brand}
|
||||||
makeRegistrationUrl={this.makeRegistrationUrl}
|
makeRegistrationUrl={this.makeRegistrationUrl}
|
||||||
onLoggedIn={this.onRegisterFlowComplete}
|
onLoggedIn={this.onRegisterFlowComplete}
|
||||||
|
|
|
@ -60,23 +60,24 @@ export default class ThreepidInviteStore extends EventEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
public storeInvite(roomId: string, wireInvite: IThreepidInviteWireFormat): IThreepidInvite {
|
public storeInvite(roomId: string, wireInvite: IThreepidInviteWireFormat): IThreepidInvite {
|
||||||
console.log("Storing invite: ", {roomId, ...wireInvite});
|
|
||||||
const invite = <IPersistedThreepidInvite>{roomId, ...wireInvite};
|
const invite = <IPersistedThreepidInvite>{roomId, ...wireInvite};
|
||||||
const id = this.generateIdOf(invite);
|
const id = this.generateIdOf(invite);
|
||||||
localStorage.setItem(`${STORAGE_PREFIX}${id}`, JSON.stringify(invite));
|
localStorage.setItem(`${STORAGE_PREFIX}${id}`, JSON.stringify(invite));
|
||||||
return this.translateInvite(invite);
|
return this.translateInvite(invite);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getInvites(): IThreepidInvite[] {
|
public getWireInvites(): IPersistedThreepidInvite[] {
|
||||||
const result: IThreepidInvite[] = [];
|
const results: IPersistedThreepidInvite[] = [];
|
||||||
for (let i = 0; i < localStorage.length; i++) {
|
for (let i = 0; i < localStorage.length; i++) {
|
||||||
const keyName = localStorage.key(i);
|
const keyName = localStorage.key(i);
|
||||||
if (!keyName.startsWith(STORAGE_PREFIX)) continue;
|
if (!keyName.startsWith(STORAGE_PREFIX)) continue;
|
||||||
|
results.push(JSON.parse(localStorage.getItem(keyName)) as IPersistedThreepidInvite);
|
||||||
const persisted = JSON.parse(localStorage.getItem(keyName)) as IPersistedThreepidInvite;
|
|
||||||
result.push(this.translateInvite(persisted));
|
|
||||||
}
|
}
|
||||||
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
|
// 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,
|
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,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue