Merge branch 'develop' into gsouqet/ts-migration-1

This commit is contained in:
Germain Souquet 2021-07-20 18:43:08 +02:00
commit efce2d16f1
313 changed files with 4352 additions and 2957 deletions

View file

@ -26,7 +26,7 @@ export default class AuthPage extends React.PureComponent {
return (
<div className="mx_AuthPage">
<div className="mx_AuthPage_modal">
{this.props.children}
{ this.props.children }
</div>
<AuthFooter />
</div>

View file

@ -21,59 +21,68 @@ import { replaceableComponent } from "../../../utils/replaceableComponent";
const DIV_ID = 'mx_recaptcha';
interface IProps {
sitePublicKey?: string;
interface ICaptchaFormProps {
sitePublicKey: string;
onCaptchaResponse: (response: string) => void;
}
interface IState {
errorText: string;
interface ICaptchaFormState {
errorText?: string;
}
/**
* A pure UI component which displays a captcha form.
*/
@replaceableComponent("views.auth.CaptchaForm")
export default class CaptchaForm extends React.Component<IProps, IState> {
private captchaWidgetId: string;
private recaptchaContainer = createRef<HTMLDivElement>();
export default class CaptchaForm extends React.Component<ICaptchaFormProps, ICaptchaFormState> {
static defaultProps = {
onCaptchaResponse: () => {},
};
constructor(props) {
private captchaWidgetId?: string;
private recaptchaContainer = createRef<HTMLDivElement>();
constructor(props: ICaptchaFormProps) {
super(props);
this.state = {
errorText: null,
errorText: undefined,
};
CountlyAnalytics.instance.track("onboarding_grecaptcha_begin");
}
public componentDidMount(): void {
componentDidMount() {
// Just putting a script tag into the returned jsx doesn't work, annoyingly,
// so we do this instead.
if (window.grecaptcha) { // TODO: Properly find the type of `grecaptcha`
if (this.isRecaptchaReady()) {
// already loaded
this.onCaptchaLoaded();
} else {
console.log("Loading recaptcha script...");
window.mx_on_recaptcha_loaded = () => {this.onCaptchaLoaded();};
window.mxOnRecaptchaLoaded = () => { this.onCaptchaLoaded(); };
const scriptTag = document.createElement('script');
scriptTag.setAttribute(
'src', `https://www.recaptcha.net/recaptcha/api.js?onload=mx_on_recaptcha_loaded&render=explicit`,
'src', `https://www.recaptcha.net/recaptcha/api.js?onload=mxOnRecaptchaLoaded&render=explicit`,
);
this.recaptchaContainer.current.appendChild(scriptTag);
}
}
public componentWillUnmount(): void {
componentWillUnmount() {
this.resetRecaptcha();
}
private renderRecaptcha(divId): void {
if (!window.grecaptcha) {
// Borrowed directly from: https://github.com/codeep/react-recaptcha-google/commit/e118fa5670fa268426969323b2e7fe77698376ba
private isRecaptchaReady(): boolean {
return typeof window !== "undefined" &&
typeof global.grecaptcha !== "undefined" &&
typeof global.grecaptcha.render === 'function';
}
private renderRecaptcha(divId: string) {
if (!this.isRecaptchaReady()) {
console.error("grecaptcha not loaded!");
throw new Error("Recaptcha did not load successfully");
}
@ -83,23 +92,23 @@ export default class CaptchaForm extends React.Component<IProps, IState> {
console.error("No public key for recaptcha!");
throw new Error(
"This server has not supplied enough information for Recaptcha "
+ "authentication");
+ "authentication");
}
console.info("Rendering to %s", divId);
this.captchaWidgetId = window.grecaptcha.render(divId, {
this.captchaWidgetId = global.grecaptcha.render(divId, {
sitekey: publicKey,
callback: this.props.onCaptchaResponse,
});
}
private resetRecaptcha(): void {
private resetRecaptcha() {
if (this.captchaWidgetId !== null) {
window.grecaptcha.reset(this.captchaWidgetId);
global.grecaptcha.reset(this.captchaWidgetId);
}
}
private onCaptchaLoaded(): void {
private onCaptchaLoaded() {
console.log("Loaded recaptcha script.");
try {
this.renderRecaptcha(DIV_ID);
@ -116,7 +125,7 @@ export default class CaptchaForm extends React.Component<IProps, IState> {
}
}
public render(): React.ReactNode {
render() {
let error = null;
if (this.state.errorText) {
error = (
@ -128,9 +137,9 @@ export default class CaptchaForm extends React.Component<IProps, IState> {
return (
<div ref={this.recaptchaContainer}>
<p>{_t(
<p>{ _t(
"This homeserver would like to make sure you are not a robot.",
)}</p>
) }</p>
<div id={DIV_ID} />
{ error }
</div>

View file

@ -417,12 +417,12 @@ export class TermsAuthEntry extends React.Component<ITermsAuthEntryProps, ITerms
if (this.props.showContinue !== false) {
// XXX: button classes
submitButton = <button className="mx_InteractiveAuthEntryComponents_termsSubmit mx_GeneralButton"
onClick={this.trySubmit} disabled={!allChecked}>{_t("Accept")}</button>;
onClick={this.trySubmit} disabled={!allChecked}>{ _t("Accept") }</button>;
}
return (
<div>
<p>{_t("Please review and accept the policies of this homeserver:")}</p>
<p>{ _t("Please review and accept the policies of this homeserver:") }</p>
{ checkboxes }
{ errorSection }
{ submitButton }
@ -613,7 +613,7 @@ export class MsisdnAuthEntry extends React.Component<IMsisdnAuthEntryProps, IMsi
className="mx_InteractiveAuthEntryComponents_msisdnEntry"
value={this.state.token}
onChange={this.onTokenChange}
aria-label={ _t("Code")}
aria-label={_t("Code")}
/>
<br />
<input type="submit" value={_t("Submit")}
@ -621,7 +621,7 @@ export class MsisdnAuthEntry extends React.Component<IMsisdnAuthEntryProps, IMsi
disabled={!enableSubmit}
/>
</form>
{errorSection}
{ errorSection }
</div>
</div>
);
@ -717,21 +717,21 @@ export class SSOAuthEntry extends React.Component<ISSOAuthEntryProps, ISSOAuthEn
<AccessibleButton
onClick={this.props.onCancel}
kind={this.props.continueKind ? (this.props.continueKind + '_outline') : 'primary_outline'}
>{_t("Cancel")}</AccessibleButton>
>{ _t("Cancel") }</AccessibleButton>
);
if (this.state.phase === SSOAuthEntry.PHASE_PREAUTH) {
continueButton = (
<AccessibleButton
onClick={this.onStartAuthClick}
kind={this.props.continueKind || 'primary'}
>{this.props.continueText || _t("Single Sign On")}</AccessibleButton>
>{ this.props.continueText || _t("Single Sign On") }</AccessibleButton>
);
} else {
continueButton = (
<AccessibleButton
onClick={this.onConfirmClick}
kind={this.props.continueKind || 'primary'}
>{this.props.continueText || _t("Confirm")}</AccessibleButton>
>{ this.props.continueText || _t("Confirm") }</AccessibleButton>
);
}
@ -753,8 +753,8 @@ export class SSOAuthEntry extends React.Component<ISSOAuthEntryProps, ISSOAuthEn
return <React.Fragment>
{ errorSection }
<div className="mx_InteractiveAuthEntryComponents_sso_buttons">
{cancelButton}
{continueButton}
{ cancelButton }
{ continueButton }
</div>
</React.Fragment>;
}
@ -825,7 +825,7 @@ export class FallbackAuthEntry extends React.Component<IAuthEntryProps> {
<a href="" ref={this.fallbackButton} onClick={this.onShowFallbackClick}>{
_t("Start authentication")
}</a>
{errorSection}
{ errorSection }
</div>
);
}

View file

@ -416,7 +416,7 @@ export default class PasswordLogin extends React.PureComponent<IProps, IState> {
kind="link"
onClick={this.onForgotPasswordClick}
>
{_t("Forgot password?")}
{ _t("Forgot password?") }
</AccessibleButton>;
}
@ -441,16 +441,16 @@ export default class PasswordLogin extends React.PureComponent<IProps, IState> {
disabled={this.props.disableSubmit}
>
<option key={LoginField.MatrixId} value={LoginField.MatrixId}>
{_t('Username')}
{ _t('Username') }
</option>
<option
key={LoginField.Email}
value={LoginField.Email}
>
{_t('Email address')}
{ _t('Email address') }
</option>
<option key={LoginField.Password} value={LoginField.Password}>
{_t('Phone')}
{ _t('Phone') }
</option>
</Field>
</div>
@ -460,8 +460,8 @@ export default class PasswordLogin extends React.PureComponent<IProps, IState> {
return (
<div>
<form onSubmit={this.onSubmitForm}>
{loginType}
{loginField}
{ loginType }
{ loginField }
<Field
className={pwFieldClass}
type="password"
@ -474,7 +474,7 @@ export default class PasswordLogin extends React.PureComponent<IProps, IState> {
onValidate={this.onPasswordValidate}
ref={field => this[LoginField.Password] = field}
/>
{forgotPasswordJsx}
{ forgotPasswordJsx }
{ !this.props.busy && <input className="mx_Login_submit"
type="submit"
value={_t('Sign in')}

View file

@ -537,15 +537,15 @@ export default class RegistrationForm extends React.PureComponent<IProps, IState
<div>
<form onSubmit={this.onSubmit}>
<div className="mx_AuthBody_fieldRow">
{this.renderUsername()}
{ this.renderUsername() }
</div>
<div className="mx_AuthBody_fieldRow">
{this.renderPassword()}
{this.renderPasswordConfirm()}
{ this.renderPassword() }
{ this.renderPasswordConfirm() }
</div>
<div className="mx_AuthBody_fieldRow">
{this.renderEmail()}
{this.renderPhoneNumber()}
{ this.renderEmail() }
{ this.renderPhoneNumber() }
</div>
{ emailHelperText }
{ registerButton }