Convert AsyncWrapper to Typescript

This commit is contained in:
Michael Telatynski 2021-06-07 10:57:25 +01:00
parent 9315a87ebf
commit 3431ebb995

View file

@ -1,6 +1,5 @@
/* /*
Copyright 2015, 2016 OpenMarket Ltd Copyright 2015-2021 The Matrix.org Foundation C.I.C.
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -15,52 +14,63 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import React from "react"; import React, { ComponentType } from "react";
import * as sdk from './index';
import PropTypes from 'prop-types';
import { _t } from './languageHandler'; import { _t } from './languageHandler';
import { IDialogProps } from "./components/views/dialogs/IDialogProps";
import BaseDialog from "./components/views/dialogs/BaseDialog";
import DialogButtons from "./components/views/elements/DialogButtons";
import Spinner from "./components/views/elements/Spinner";
type AsyncImport<T> = { default: T };
interface IProps extends IDialogProps {
// A promise which resolves with the real component
prom: Promise<ComponentType | AsyncImport<ComponentType>>;
}
interface IState {
component?: ComponentType;
error?: Error;
}
/** /**
* Wrap an asynchronous loader function with a react component which shows a * Wrap an asynchronous loader function with a react component which shows a
* spinner until the real component loads. * spinner until the real component loads.
*/ */
export default class AsyncWrapper extends React.Component { export default class AsyncWrapper extends React.Component<IProps, IState> {
static propTypes = { private unmounted = false;
/** A promise which resolves with the real component
*/
prom: PropTypes.object.isRequired,
};
state = { public state = {
component: null, component: null,
error: null, error: null,
}; };
componentDidMount() { componentDidMount() {
this._unmounted = false;
// XXX: temporary logging to try to diagnose // XXX: temporary logging to try to diagnose
// https://github.com/vector-im/element-web/issues/3148 // https://github.com/vector-im/element-web/issues/3148
console.log('Starting load of AsyncWrapper for modal'); console.log('Starting load of AsyncWrapper for modal');
this.props.prom.then((result) => { this.props.prom.then((result) => {
if (this._unmounted) { if (this.unmounted) return;
return;
}
// Take the 'default' member if it's there, then we support // Take the 'default' member if it's there, then we support
// passing in just an import()ed module, since ES6 async import // passing in just an import()ed module, since ES6 async import
// always returns a module *namespace*. // always returns a module *namespace*.
const component = result.default ? result.default : result; const component = (result as AsyncImport<ComponentType>).default
this.setState({component}); ? (result as AsyncImport<ComponentType>).default
: result as ComponentType;
this.setState({ component });
}).catch((e) => { }).catch((e) => {
console.warn('AsyncWrapper promise failed', e); console.warn('AsyncWrapper promise failed', e);
this.setState({error: e}); this.setState({ error: e });
}); });
} }
componentWillUnmount() { componentWillUnmount() {
this._unmounted = true; this.unmounted = true;
} }
_onWrapperCancelClick = () => { private onWrapperCancelClick = () => {
this.props.onFinished(false); this.props.onFinished(false);
}; };
@ -69,20 +79,15 @@ export default class AsyncWrapper extends React.Component {
const Component = this.state.component; const Component = this.state.component;
return <Component {...this.props} />; return <Component {...this.props} />;
} else if (this.state.error) { } else if (this.state.error) {
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog'); return <BaseDialog onFinished={this.props.onFinished} title={_t("Error")}>
const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); { _t("Unable to load! Check your network connectivity and try again.") }
return <BaseDialog onFinished={this.props.onFinished}
title={_t("Error")}
>
{_t("Unable to load! Check your network connectivity and try again.")}
<DialogButtons primaryButton={_t("Dismiss")} <DialogButtons primaryButton={_t("Dismiss")}
onPrimaryButtonClick={this._onWrapperCancelClick} onPrimaryButtonClick={this.onWrapperCancelClick}
hasCancel={false} hasCancel={false}
/> />
</BaseDialog>; </BaseDialog>;
} else { } else {
// show a spinner until the component is loaded. // show a spinner until the component is loaded.
const Spinner = sdk.getComponent("elements.Spinner");
return <Spinner />; return <Spinner />;
} }
} }