mirror of https://github.com/vector-im/riot-web
Add mobile registration and dispatch event for mobile postmessage dance
parent
eae9d9e248
commit
a6dec86374
|
@ -94,6 +94,7 @@
|
||||||
@import "./structures/auth/_ConfirmSessionLockTheftView.pcss";
|
@import "./structures/auth/_ConfirmSessionLockTheftView.pcss";
|
||||||
@import "./structures/auth/_Login.pcss";
|
@import "./structures/auth/_Login.pcss";
|
||||||
@import "./structures/auth/_LoginSplashView.pcss";
|
@import "./structures/auth/_LoginSplashView.pcss";
|
||||||
|
@import "./structures/auth/_MobileRegistration.pcss";
|
||||||
@import "./structures/auth/_Registration.pcss";
|
@import "./structures/auth/_Registration.pcss";
|
||||||
@import "./structures/auth/_SessionLockStolenView.pcss";
|
@import "./structures/auth/_SessionLockStolenView.pcss";
|
||||||
@import "./structures/auth/_SetupEncryptionBody.pcss";
|
@import "./structures/auth/_SetupEncryptionBody.pcss";
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
/*
|
||||||
|
Copyright 2024 New Vector Ltd.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
|
||||||
|
Please see LICENSE files in the repository root for full details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.mx_MobileRegister_body {
|
||||||
|
padding: 32px;
|
||||||
|
}
|
|
@ -140,7 +140,7 @@ import { cleanUpDraftsIfRequired } from "../../DraftCleaner";
|
||||||
// legacy export
|
// legacy export
|
||||||
export { default as Views } from "../../Views";
|
export { default as Views } from "../../Views";
|
||||||
|
|
||||||
const AUTH_SCREENS = ["register", "login", "forgot_password", "start_sso", "start_cas", "welcome"];
|
const AUTH_SCREENS = ["register", "mobile_register", "login", "forgot_password", "start_sso", "start_cas", "welcome"];
|
||||||
|
|
||||||
// Actions that are redirected through the onboarding process prior to being
|
// Actions that are redirected through the onboarding process prior to being
|
||||||
// re-dispatched. NOTE: some actions are non-trivial and would require
|
// re-dispatched. NOTE: some actions are non-trivial and would require
|
||||||
|
@ -189,6 +189,7 @@ interface IState {
|
||||||
register_session_id?: string;
|
register_session_id?: string;
|
||||||
// eslint-disable-next-line camelcase
|
// eslint-disable-next-line camelcase
|
||||||
register_id_sid?: string;
|
register_id_sid?: string;
|
||||||
|
isMobileRegistration?: boolean;
|
||||||
// When showing Modal dialogs we need to set aria-hidden on the root app element
|
// When showing Modal dialogs we need to set aria-hidden on the root app element
|
||||||
// and disable it when there are no dialogs
|
// and disable it when there are no dialogs
|
||||||
hideToSRUsers: boolean;
|
hideToSRUsers: boolean;
|
||||||
|
@ -243,6 +244,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||||
currentUserId: null,
|
currentUserId: null,
|
||||||
|
|
||||||
hideToSRUsers: false,
|
hideToSRUsers: false,
|
||||||
|
isMobileRegistration: false,
|
||||||
|
|
||||||
syncError: null, // If the current syncing status is ERROR, the error object, otherwise null.
|
syncError: null, // If the current syncing status is ERROR, the error object, otherwise null.
|
||||||
resizeNotifier: new ResizeNotifier(),
|
resizeNotifier: new ResizeNotifier(),
|
||||||
|
@ -650,6 +652,9 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||||
case "require_registration":
|
case "require_registration":
|
||||||
startAnyRegistrationFlow(payload as any);
|
startAnyRegistrationFlow(payload as any);
|
||||||
break;
|
break;
|
||||||
|
case "start_mobile_registration":
|
||||||
|
this.startRegistration(payload.params || {}, true);
|
||||||
|
break;
|
||||||
case "start_registration":
|
case "start_registration":
|
||||||
if (Lifecycle.isSoftLogout()) {
|
if (Lifecycle.isSoftLogout()) {
|
||||||
this.onSoftLogout();
|
this.onSoftLogout();
|
||||||
|
@ -946,7 +951,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private async startRegistration(params: { [key: string]: string }): Promise<void> {
|
private async startRegistration(params: { [key: string]: string }, isMobileRegistration?: boolean): Promise<void> {
|
||||||
if (!SettingsStore.getValue(UIFeature.Registration)) {
|
if (!SettingsStore.getValue(UIFeature.Registration)) {
|
||||||
this.showScreen("welcome");
|
this.showScreen("welcome");
|
||||||
return;
|
return;
|
||||||
|
@ -976,12 +981,15 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||||
newState.register_client_secret = params.client_secret;
|
newState.register_client_secret = params.client_secret;
|
||||||
newState.register_session_id = params.session_id;
|
newState.register_session_id = params.session_id;
|
||||||
newState.register_id_sid = params.sid;
|
newState.register_id_sid = params.sid;
|
||||||
|
newState.register_id_sid = params.sid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
newState.isMobileRegistration = isMobileRegistration; //&& SettingsStore.getValue("Registration.mobileRegistrationHelper");
|
||||||
|
|
||||||
this.setStateForNewView(newState);
|
this.setStateForNewView(newState);
|
||||||
ThemeController.isLogin = true;
|
ThemeController.isLogin = true;
|
||||||
this.themeWatcher.recheck();
|
this.themeWatcher.recheck();
|
||||||
this.notifyNewScreen("register");
|
this.notifyNewScreen(isMobileRegistration ? "mobile_register" : "register");
|
||||||
}
|
}
|
||||||
|
|
||||||
// switch view to the given room
|
// switch view to the given room
|
||||||
|
@ -1721,6 +1729,11 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||||
params: params,
|
params: params,
|
||||||
});
|
});
|
||||||
PerformanceMonitor.instance.start(PerformanceEntryNames.REGISTER);
|
PerformanceMonitor.instance.start(PerformanceEntryNames.REGISTER);
|
||||||
|
} else if (screen === "mobile_register") {
|
||||||
|
dis.dispatch({
|
||||||
|
action: "start_mobile_registration",
|
||||||
|
params: params,
|
||||||
|
});
|
||||||
} else if (screen === "login") {
|
} else if (screen === "login") {
|
||||||
dis.dispatch({
|
dis.dispatch({
|
||||||
action: "start_login",
|
action: "start_login",
|
||||||
|
@ -2080,6 +2093,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||||
onServerConfigChange={this.onServerConfigChange}
|
onServerConfigChange={this.onServerConfigChange}
|
||||||
defaultDeviceDisplayName={this.props.defaultDeviceDisplayName}
|
defaultDeviceDisplayName={this.props.defaultDeviceDisplayName}
|
||||||
fragmentAfterLogin={fragmentAfterLogin}
|
fragmentAfterLogin={fragmentAfterLogin}
|
||||||
|
mobileRegister={this.state.isMobileRegistration}
|
||||||
{...this.getServerProperties()}
|
{...this.getServerProperties()}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
|
@ -53,6 +53,13 @@ const debuglog = (...args: any[]): void => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export interface MobileRegistrationResponse {
|
||||||
|
user_id: string;
|
||||||
|
home_server: string;
|
||||||
|
access_token: string;
|
||||||
|
device_id: string;
|
||||||
|
}
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
serverConfig: ValidatedServerConfig;
|
serverConfig: ValidatedServerConfig;
|
||||||
defaultDeviceDisplayName?: string;
|
defaultDeviceDisplayName?: string;
|
||||||
|
@ -62,7 +69,7 @@ interface IProps {
|
||||||
sessionId?: string;
|
sessionId?: string;
|
||||||
idSid?: string;
|
idSid?: string;
|
||||||
fragmentAfterLogin?: string;
|
fragmentAfterLogin?: string;
|
||||||
|
mobileRegister?: boolean;
|
||||||
// Called when the user has logged in. Params:
|
// Called when the user has logged in. Params:
|
||||||
// - object with userId, deviceId, homeserverUrl, identityServerUrl, accessToken
|
// - object with userId, deviceId, homeserverUrl, identityServerUrl, accessToken
|
||||||
// - The user's password, if available and applicable (may be cached in memory
|
// - The user's password, if available and applicable (may be cached in memory
|
||||||
|
@ -410,18 +417,33 @@ export default class Registration extends React.Component<IProps, IState> {
|
||||||
debuglog("Registration: ui auth finished:", { hasEmail, hasAccessToken });
|
debuglog("Registration: ui auth finished:", { hasEmail, hasAccessToken });
|
||||||
// don’t log in if we found a session for a different user
|
// don’t log in if we found a session for a different user
|
||||||
if (hasAccessToken && !newState.differentLoggedInUserId) {
|
if (hasAccessToken && !newState.differentLoggedInUserId) {
|
||||||
await this.props.onLoggedIn(
|
if (this.props.mobileRegister) {
|
||||||
{
|
const mobileResponse: MobileRegistrationResponse = {
|
||||||
userId,
|
user_id: userId,
|
||||||
deviceId: (response as RegisterResponse).device_id!,
|
home_server: this.state.matrixClient.getHomeserverUrl(),
|
||||||
homeserverUrl: this.state.matrixClient.getHomeserverUrl(),
|
access_token: accessToken,
|
||||||
identityServerUrl: this.state.matrixClient.getIdentityServerUrl(),
|
device_id: (response as RegisterResponse).device_id!,
|
||||||
accessToken,
|
};
|
||||||
},
|
const event = new CustomEvent<MobileRegistrationResponse>("mobileregistrationresponse", {
|
||||||
this.state.formVals.password!,
|
detail: mobileResponse,
|
||||||
);
|
});
|
||||||
|
document.dispatchEvent(event);
|
||||||
|
newState.busy = false;
|
||||||
|
newState.completedNoSignin = true;
|
||||||
|
} else {
|
||||||
|
await this.props.onLoggedIn(
|
||||||
|
{
|
||||||
|
userId,
|
||||||
|
deviceId: (response as RegisterResponse).device_id!,
|
||||||
|
homeserverUrl: this.state.matrixClient.getHomeserverUrl(),
|
||||||
|
identityServerUrl: this.state.matrixClient.getIdentityServerUrl(),
|
||||||
|
accessToken,
|
||||||
|
},
|
||||||
|
this.state.formVals.password!,
|
||||||
|
);
|
||||||
|
|
||||||
this.setupPushers();
|
this.setupPushers();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
newState.busy = false;
|
newState.busy = false;
|
||||||
newState.completedNoSignin = true;
|
newState.completedNoSignin = true;
|
||||||
|
@ -558,7 +580,7 @@ export default class Registration extends React.Component<IProps, IState> {
|
||||||
);
|
);
|
||||||
} else if (this.state.matrixClient && this.state.flows.length) {
|
} else if (this.state.matrixClient && this.state.flows.length) {
|
||||||
let ssoSection: JSX.Element | undefined;
|
let ssoSection: JSX.Element | undefined;
|
||||||
if (this.state.ssoFlow) {
|
if (!this.props.mobileRegister && this.state.ssoFlow) {
|
||||||
let continueWithSection;
|
let continueWithSection;
|
||||||
const providers = this.state.ssoFlow.identity_providers || [];
|
const providers = this.state.ssoFlow.identity_providers || [];
|
||||||
// when there is only a single (or 0) providers we show a wide button with `Continue with X` text
|
// when there is only a single (or 0) providers we show a wide button with `Continue with X` text
|
||||||
|
@ -591,7 +613,6 @@ export default class Registration extends React.Component<IProps, IState> {
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
{ssoSection}
|
{ssoSection}
|
||||||
|
@ -660,7 +681,9 @@ export default class Registration extends React.Component<IProps, IState> {
|
||||||
let body;
|
let body;
|
||||||
if (this.state.completedNoSignin) {
|
if (this.state.completedNoSignin) {
|
||||||
let regDoneText;
|
let regDoneText;
|
||||||
if (this.state.differentLoggedInUserId) {
|
if (this.props.mobileRegister) {
|
||||||
|
regDoneText = undefined;
|
||||||
|
} else if (this.state.differentLoggedInUserId) {
|
||||||
regDoneText = (
|
regDoneText = (
|
||||||
<div>
|
<div>
|
||||||
<p>
|
<p>
|
||||||
|
@ -717,6 +740,8 @@ export default class Registration extends React.Component<IProps, IState> {
|
||||||
{regDoneText}
|
{regDoneText}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
} else if (this.props.mobileRegister) {
|
||||||
|
body = this.renderRegisterComponent();
|
||||||
} else {
|
} else {
|
||||||
body = (
|
body = (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
|
@ -746,7 +771,13 @@ export default class Registration extends React.Component<IProps, IState> {
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (this.props.mobileRegister) {
|
||||||
|
return (
|
||||||
|
<Fragment>
|
||||||
|
<div className="mx_MobileRegister_body">{body}</div>
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<AuthPage>
|
<AuthPage>
|
||||||
<AuthHeader />
|
<AuthHeader />
|
||||||
|
|
|
@ -876,6 +876,10 @@ export const SETTINGS: { [setting: string]: ISetting } = {
|
||||||
supportedLevels: LEVELS_ACCOUNT_SETTINGS,
|
supportedLevels: LEVELS_ACCOUNT_SETTINGS,
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
|
"Registration.mobileRegistrationHelper": {
|
||||||
|
supportedLevels: [SettingLevel.CONFIG],
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
"autocompleteDelay": {
|
"autocompleteDelay": {
|
||||||
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG,
|
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG,
|
||||||
default: 200,
|
default: 200,
|
||||||
|
|
Loading…
Reference in New Issue