+
);
}
}
@@ -814,9 +912,11 @@ export interface IStageComponentProps extends IAuthEntryProps {
showContinue?: boolean;
continueText?: string;
continueKind?: string;
+ serverPicker?: ReactNode;
fail?(e: Error): void;
setEmailSid?(sid: string): void;
onCancel?(): void;
+ requestEmailToken?(): Promise;
}
export interface IStageComponent extends React.ComponentClass> {
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json
index 15df64eeec8..c8c6ecfe5c6 100644
--- a/src/i18n/strings/en_EN.json
+++ b/src/i18n/strings/en_EN.json
@@ -2976,8 +2976,11 @@
"Missing captcha public key in homeserver configuration. Please report this to your homeserver administrator.": "Missing captcha public key in homeserver configuration. Please report this to your homeserver administrator.",
"Please review and accept all of the homeserver's policies": "Please review and accept all of the homeserver's policies",
"Please review and accept the policies of this homeserver:": "Please review and accept the policies of this homeserver:",
- "A confirmation email has been sent to %(emailAddress)s": "A confirmation email has been sent to %(emailAddress)s",
- "Open the link in the email to continue registration.": "Open the link in the email to continue registration.",
+ "Check your email to continue": "Check your email to continue",
+ "Unread email icon": "Unread email icon",
+ "To create your account, open the link in the email we just sent to %(emailAddress)s.": "To create your account, open the link in the email we just sent to %(emailAddress)s.",
+ "Did not receive it? Resend it": "Did not receive it? Resend it",
+ "Did not receive it? Requested": "Did not receive it? Requested",
"Token incorrect": "Token incorrect",
"A text message has been sent to %(msisdn)s": "A text message has been sent to %(msisdn)s",
"Please enter the code it contains:": "Please enter the code it contains:",
From efafb0db3eaa87a5224aa41bc84b6c3b03426866 Mon Sep 17 00:00:00 2001
From: Janne Mareike Koschinski
Date: Wed, 11 May 2022 14:10:54 +0200
Subject: [PATCH 02/16] fix: add copyright header
---
res/css/structures/auth/_Registration.scss | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/res/css/structures/auth/_Registration.scss b/res/css/structures/auth/_Registration.scss
index 9f37ec0180e..b415e78f107 100644
--- a/res/css/structures/auth/_Registration.scss
+++ b/res/css/structures/auth/_Registration.scss
@@ -1,3 +1,19 @@
+/*
+Copyright 2022 The Matrix.org Foundation C.I.C.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
.mx_Register_mainContent {
display: flex;
flex-direction: column;
From 799f050b7d6629a4a8760d0f45bbb43ff1f0bd2b Mon Sep 17 00:00:00 2001
From: Janne Mareike Koschinski
Date: Wed, 11 May 2022 14:33:40 +0200
Subject: [PATCH 03/16] fix: remove unneeded vestigial code for serverPicker
passthrough
---
src/components/structures/InteractiveAuth.tsx | 4 +-
.../auth/InteractiveAuthEntryComponents.tsx | 158 +++++++-----------
2 files changed, 65 insertions(+), 97 deletions(-)
diff --git a/src/components/structures/InteractiveAuth.tsx b/src/components/structures/InteractiveAuth.tsx
index 0c1b326a802..b42e65d57fb 100644
--- a/src/components/structures/InteractiveAuth.tsx
+++ b/src/components/structures/InteractiveAuth.tsx
@@ -23,7 +23,7 @@ import {
IStageStatus,
} from "matrix-js-sdk/src/interactive-auth";
import { MatrixClient } from "matrix-js-sdk/src/client";
-import React, { createRef, ReactNode } from 'react';
+import React, { createRef } from 'react';
import { logger } from "matrix-js-sdk/src/logger";
import getEntryComponentForLoginType, { IStageComponent } from '../views/auth/InteractiveAuthEntryComponents';
@@ -52,7 +52,6 @@ interface IProps {
// continueText and continueKind are passed straight through to the AuthEntryComponent.
continueText?: string;
continueKind?: string;
- serverPicker?: ReactNode;
// callback
makeRequest(auth: IAuthData): Promise;
// callback called when the auth process has finished,
@@ -274,7 +273,6 @@ export default class InteractiveAuthComponent extends React.Component
);
}
diff --git a/src/components/views/auth/InteractiveAuthEntryComponents.tsx b/src/components/views/auth/InteractiveAuthEntryComponents.tsx
index 0e7b4538ea4..492b1348e3c 100644
--- a/src/components/views/auth/InteractiveAuthEntryComponents.tsx
+++ b/src/components/views/auth/InteractiveAuthEntryComponents.tsx
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import React, { ChangeEvent, createRef, FormEvent, Fragment, MouseEvent, ReactNode } from 'react';
+import React, { ChangeEvent, createRef, FormEvent, Fragment, MouseEvent } from 'react';
import classNames from 'classnames';
import { MatrixClient } from "matrix-js-sdk/src/client";
import { AuthType, IAuthDict, IInputs, IStageStatus } from 'matrix-js-sdk/src/interactive-auth';
@@ -47,9 +47,6 @@ import EmailPromptIcon from '../../../../res/img/element-icons/email-prompt.svg'
* stageParams: params from the server for the stage being attempted
* errorText: error message from a previous attempt to authenticate
* submitAuthDict: a function which will be called with the new auth dict
- * serverPicker: the UI element allowing you to choose which server to
- * authenticate against. In certain stages of the flow, it may
- * make sense to avoid showing it.
* busy: a boolean indicating whether the auth logic is doing something
* the user needs to wait for.
* inputs: Object of inputs provided by the user, as in js-sdk
@@ -87,7 +84,6 @@ interface IAuthEntryProps {
authSessionId: string;
errorText?: string;
errorCode?: string;
- serverPicker?: ReactNode;
// Is the auth logic currently waiting for something to happen?
busy?: boolean;
onPhaseChange: (phase: number) => void;
@@ -166,27 +162,24 @@ export class PasswordAuthEntry extends React.Component
- { this.props.serverPicker }
-
-
{ _t("Confirm your identity by entering your account password below.") }
-
-
-
+
+
{ _t("Confirm your identity by entering your account password below.") }
;
}
From 06f8854e8ccb47cc5b1cfb2f361a7600edebbdb6 Mon Sep 17 00:00:00 2001
From: Janne Mareike Koschinski
Date: Wed, 11 May 2022 14:53:08 +0200
Subject: [PATCH 06/16] fix: cleanly split reducer and context
---
.../structures/auth/AuthHeaderContext.tsx | 107 ------------------
.../structures/auth/Registration.tsx | 3 +-
.../auth/header/AuthHeaderContext.tsx | 26 +++++
.../auth/header/AuthHeaderDisplay.tsx | 41 +++++++
.../auth/header/AuthHeaderModifier.tsx | 39 +++++++
.../auth/header/AuthHeaderProvider.tsx | 52 +++++++++
.../auth/InteractiveAuthEntryComponents.tsx | 4 +-
7 files changed, 162 insertions(+), 110 deletions(-)
delete mode 100644 src/components/structures/auth/AuthHeaderContext.tsx
create mode 100644 src/components/structures/auth/header/AuthHeaderContext.tsx
create mode 100644 src/components/structures/auth/header/AuthHeaderDisplay.tsx
create mode 100644 src/components/structures/auth/header/AuthHeaderModifier.tsx
create mode 100644 src/components/structures/auth/header/AuthHeaderProvider.tsx
diff --git a/src/components/structures/auth/AuthHeaderContext.tsx b/src/components/structures/auth/AuthHeaderContext.tsx
deleted file mode 100644
index ac034ee170c..00000000000
--- a/src/components/structures/auth/AuthHeaderContext.tsx
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
-Copyright 2022 The Matrix.org Foundation C.I.C.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-import { isEqual } from "lodash";
-import React, {
- createContext, Dispatch,
- Fragment,
- PropsWithChildren,
- ReactNode,
- Reducer,
- ReducerState,
- useContext,
- useEffect,
- useReducer,
-} from "react";
-
-interface AuthHeaderContextValue {
- title: ReactNode;
- icon?: ReactNode;
- hideServerPicker?: boolean;
-}
-
-enum AuthHeaderContextActionType {
- ADD,
- REMOVE
-}
-
-interface AuthHeaderContextAction {
- type: AuthHeaderContextActionType;
- value: AuthHeaderContextValue;
-}
-
-type AuthContextReducer = Reducer;
-
-interface AuthHeaderContextType {
- state: ReducerState;
- dispatch: Dispatch;
-}
-
-const AuthHeaderContext = createContext(undefined);
-
-export function AuthHeader(content: AuthHeaderContextValue) {
- const context = useContext(AuthHeaderContext);
- const dispatch = context ? context.dispatch : null;
- useEffect(() => {
- if (!dispatch) {
- return;
- }
- dispatch({ type: AuthHeaderContextActionType.ADD, value: content });
- return () => dispatch({ type: AuthHeaderContextActionType.REMOVE, value: content });
- }, [content, dispatch]);
- return null;
-}
-
-interface Props {
- title: ReactNode;
- icon?: ReactNode;
- serverPicker: ReactNode;
-}
-
-export function AuthHeaderDisplay({ title, icon, serverPicker, children }: PropsWithChildren) {
- const context = useContext(AuthHeaderContext);
- if (!context) {
- return null;
- }
- const current = context.state.length ? context.state[0] : null;
- return (
-
- { current?.icon ?? icon }
-
{ current?.title ?? title }
- { children }
- { current?.hideServerPicker !== true && serverPicker }
-
- );
-}
-
-export function AuthHeaderProvider({ children }: PropsWithChildren<{}>) {
- const [state, dispatch] = useReducer(
- (state: AuthHeaderContextValue[], action: AuthHeaderContextAction) => {
- switch (action.type) {
- case AuthHeaderContextActionType.ADD:
- return [action.value, ...state];
- case AuthHeaderContextActionType.REMOVE:
- return (state.length && isEqual(state[0], action.value)) ? state.slice(1) : state;
- }
- },
- [] as AuthHeaderContextValue[],
- );
- return (
-
- { children }
-
- );
-}
diff --git a/src/components/structures/auth/Registration.tsx b/src/components/structures/auth/Registration.tsx
index c9af766150e..7515a4f0d90 100644
--- a/src/components/structures/auth/Registration.tsx
+++ b/src/components/structures/auth/Registration.tsx
@@ -25,7 +25,6 @@ import { messageForResourceLimitError } from '../../../utils/ErrorUtils';
import AutoDiscoveryUtils, { ValidatedServerConfig } from "../../../utils/AutoDiscoveryUtils";
import * as Lifecycle from '../../../Lifecycle';
import { IMatrixClientCreds, MatrixClientPeg } from "../../../MatrixClientPeg";
-import { AuthHeaderDisplay, AuthHeaderProvider } from "./AuthHeaderContext";
import AuthPage from "../../views/auth/AuthPage";
import Login, { ISSOFlow } from "../../../Login";
import dis from "../../../dispatcher/dispatcher";
@@ -37,6 +36,8 @@ import AuthBody from "../../views/auth/AuthBody";
import AuthHeader from "../../views/auth/AuthHeader";
import InteractiveAuth from "../InteractiveAuth";
import Spinner from "../../views/elements/Spinner";
+import { AuthHeaderDisplay } from './header/AuthHeaderDisplay';
+import { AuthHeaderProvider } from './header/AuthHeaderProvider';
interface IProps {
serverConfig: ValidatedServerConfig;
diff --git a/src/components/structures/auth/header/AuthHeaderContext.tsx b/src/components/structures/auth/header/AuthHeaderContext.tsx
new file mode 100644
index 00000000000..347b26252dd
--- /dev/null
+++ b/src/components/structures/auth/header/AuthHeaderContext.tsx
@@ -0,0 +1,26 @@
+/*
+Copyright 2022 The Matrix.org Foundation C.I.C.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+import { createContext, Dispatch, ReducerAction, ReducerState } from "react";
+
+import type { AuthHeaderReducer } from "./AuthHeaderProvider";
+
+interface AuthHeaderContextType {
+ state: ReducerState;
+ dispatch: Dispatch>;
+}
+
+export const AuthHeaderContext = createContext(undefined);
diff --git a/src/components/structures/auth/header/AuthHeaderDisplay.tsx b/src/components/structures/auth/header/AuthHeaderDisplay.tsx
new file mode 100644
index 00000000000..fd5b65a1ebd
--- /dev/null
+++ b/src/components/structures/auth/header/AuthHeaderDisplay.tsx
@@ -0,0 +1,41 @@
+/*
+Copyright 2022 The Matrix.org Foundation C.I.C.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+import React, { Fragment, PropsWithChildren, ReactNode, useContext } from "react";
+
+import { AuthHeaderContext } from "./AuthHeaderContext";
+
+interface Props {
+ title: ReactNode;
+ icon?: ReactNode;
+ serverPicker: ReactNode;
+}
+
+export function AuthHeaderDisplay({ title, icon, serverPicker, children }: PropsWithChildren) {
+ const context = useContext(AuthHeaderContext);
+ if (!context) {
+ return null;
+ }
+ const current = context.state.length ? context.state[0] : null;
+ return (
+
+ { current?.icon ?? icon }
+
{ current?.title ?? title }
+ { children }
+ { current?.hideServerPicker !== true && serverPicker }
+
+ );
+}
diff --git a/src/components/structures/auth/header/AuthHeaderModifier.tsx b/src/components/structures/auth/header/AuthHeaderModifier.tsx
new file mode 100644
index 00000000000..a1289a9c705
--- /dev/null
+++ b/src/components/structures/auth/header/AuthHeaderModifier.tsx
@@ -0,0 +1,39 @@
+/*
+Copyright 2022 The Matrix.org Foundation C.I.C.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+import { ReactNode, useContext, useEffect } from "react";
+
+import { AuthHeaderContext } from "./AuthHeaderContext";
+import { AuthHeaderActionType } from "./AuthHeaderProvider";
+
+interface Props {
+ title: ReactNode;
+ icon?: ReactNode;
+ hideServerPicker?: boolean;
+}
+
+export function AuthHeaderModifier(content: Props) {
+ const context = useContext(AuthHeaderContext);
+ const dispatch = context ? context.dispatch : null;
+ useEffect(() => {
+ if (!dispatch) {
+ return;
+ }
+ dispatch({ type: AuthHeaderActionType.Add, value: content });
+ return () => dispatch({ type: AuthHeaderActionType.Remove, value: content });
+ }, [content, dispatch]);
+ return null;
+}
diff --git a/src/components/structures/auth/header/AuthHeaderProvider.tsx b/src/components/structures/auth/header/AuthHeaderProvider.tsx
new file mode 100644
index 00000000000..6c2bc5a7509
--- /dev/null
+++ b/src/components/structures/auth/header/AuthHeaderProvider.tsx
@@ -0,0 +1,52 @@
+/*
+Copyright 2022 The Matrix.org Foundation C.I.C.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+import { isEqual } from "lodash";
+import React, { ComponentProps, PropsWithChildren, Reducer, useReducer } from "react";
+
+import { AuthHeaderContext } from "./AuthHeaderContext";
+import { AuthHeaderModifier } from "./AuthHeaderModifier";
+
+export enum AuthHeaderActionType {
+ Add,
+ Remove
+}
+
+interface AuthHeaderAction {
+ type: AuthHeaderActionType;
+ value: ComponentProps;
+}
+
+export type AuthHeaderReducer = Reducer[], AuthHeaderAction>;
+
+export function AuthHeaderProvider({ children }: PropsWithChildren<{}>) {
+ const [state, dispatch] = useReducer(
+ (state: ComponentProps[], action: AuthHeaderAction) => {
+ switch (action.type) {
+ case AuthHeaderActionType.Add:
+ return [action.value, ...state];
+ case AuthHeaderActionType.Remove:
+ return (state.length && isEqual(state[0], action.value)) ? state.slice(1) : state;
+ }
+ },
+ [] as ComponentProps[],
+ );
+ return (
+
+ { children }
+
+ );
+}
diff --git a/src/components/views/auth/InteractiveAuthEntryComponents.tsx b/src/components/views/auth/InteractiveAuthEntryComponents.tsx
index ee3796adb00..9ce0177e8ae 100644
--- a/src/components/views/auth/InteractiveAuthEntryComponents.tsx
+++ b/src/components/views/auth/InteractiveAuthEntryComponents.tsx
@@ -22,7 +22,7 @@ import { logger } from "matrix-js-sdk/src/logger";
import { _t } from '../../../languageHandler';
import SettingsStore from "../../../settings/SettingsStore";
-import { AuthHeader } from "../../structures/auth/AuthHeaderContext";
+import { AuthHeaderModifier } from "../../structures/auth/header/AuthHeaderModifier";
import AccessibleButton from "../elements/AccessibleButton";
import Spinner from "../elements/Spinner";
import { LocalisedPolicy, Policies } from '../../../Terms';
@@ -462,7 +462,7 @@ export class EmailIdentityAuthEntry extends
} else {
return (
);
From 6d7eef787fa8ae3b3db27091ea4e276024e7007a Mon Sep 17 00:00:00 2001
From: Janne Mareike Koschinski
Date: Fri, 13 May 2022 16:03:04 +0200
Subject: [PATCH 16/16] fix: add comments to spinner overrides
---
res/css/views/auth/_InteractiveAuthEntryComponents.scss | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/res/css/views/auth/_InteractiveAuthEntryComponents.scss b/res/css/views/auth/_InteractiveAuthEntryComponents.scss
index d839c12fa95..43e0062eb3d 100644
--- a/res/css/views/auth/_InteractiveAuthEntryComponents.scss
+++ b/res/css/views/auth/_InteractiveAuthEntryComponents.scss
@@ -76,12 +76,18 @@ limitations under the License.
}
.mx_InteractiveAuthEntryComponents_emailWrapper {
+ // "Resend" button/link
.mx_AccessibleButton_kind_link_inline {
+ // We need this to be an inline-block so positioning works correctly
display: inline-block !important;
+ // Spinner as end adornment of the "resend" button/link
.mx_Spinner {
+ // Spinners are usually block elements, but we need it as inline element
display: inline-flex !important;
+ // Spinners by default fill all available width, but we don't want that
width: auto !important;
+ // We need to center the spinner relative to the button/link
vertical-align: middle !important;
}
}