Conform more of the codebase to strictNullChecks (#10358

* Conform more of the codebase to `strictNullChecks`

* Fix types

* Iterate

* Iterate
This commit is contained in:
Michael Telatynski 2023-03-13 15:07:20 +00:00 committed by GitHub
parent 41d88ad6ae
commit 503df62191
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
76 changed files with 323 additions and 327 deletions

View file

@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { ComponentProps, createRef } from "react";
import React, { ComponentProps, createRef, ReactNode } from "react";
import { Blurhash } from "react-blurhash";
import classNames from "classnames";
import { CSSTransition, SwitchTransition } from "react-transition-group";
@ -47,8 +47,8 @@ enum Placeholder {
}
interface IState {
contentUrl?: string;
thumbUrl?: string;
contentUrl: string | null;
thumbUrl: string | null;
isAnimated?: boolean;
error?: Error;
imgError: boolean;
@ -78,6 +78,8 @@ export default class MImageBody extends React.Component<IBodyProps, IState> {
this.reconnectedListener = createReconnectedListener(this.clearError);
this.state = {
contentUrl: null,
thumbUrl: null,
imgError: false,
imgLoaded: false,
hover: false,
@ -126,7 +128,7 @@ export default class MImageBody extends React.Component<IBodyProps, IState> {
};
}
Modal.createDialog(ImageView, params, "mx_Dialog_lightbox", null, true);
Modal.createDialog(ImageView, params, "mx_Dialog_lightbox", undefined, true);
}
};
@ -177,7 +179,7 @@ export default class MImageBody extends React.Component<IBodyProps, IState> {
this.setState({ imgLoaded: true, loadedImageDimensions });
};
private getContentUrl(): string {
private getContentUrl(): string | null {
// During export, the content url will point to the MSC, which will later point to a local url
if (this.props.forExport) return this.media.srcMxc;
return this.media.srcHttp;
@ -187,7 +189,7 @@ export default class MImageBody extends React.Component<IBodyProps, IState> {
return mediaFromContent(this.props.mxEvent.getContent());
}
private getThumbUrl(): string {
private getThumbUrl(): string | null {
// FIXME: we let images grow as wide as you like, rather than capped to 800x600.
// So either we need to support custom timeline widths here, or reimpose the cap, otherwise the
// thumbnail resolution will be unnecessarily reduced.
@ -242,8 +244,8 @@ export default class MImageBody extends React.Component<IBodyProps, IState> {
private async downloadImage(): Promise<void> {
if (this.state.contentUrl) return; // already downloaded
let thumbUrl: string;
let contentUrl: string;
let thumbUrl: string | null;
let contentUrl: string | null;
if (this.props.mediaEventHelper.media.isEncrypted) {
try {
[contentUrl, thumbUrl] = await Promise.all([
@ -276,7 +278,7 @@ export default class MImageBody extends React.Component<IBodyProps, IState> {
// If there is no included non-animated thumbnail then we will generate our own, we can't depend on the server
// because 1. encryption and 2. we can't ask the server specifically for a non-animated thumbnail.
if (isAnimated && !SettingsStore.getValue("autoplayGifs")) {
if (!thumbUrl || !content?.info.thumbnail_info || mayBeAnimated(content.info.thumbnail_info.mimetype)) {
if (!thumbUrl || !content?.info?.thumbnail_info || mayBeAnimated(content.info.thumbnail_info.mimetype)) {
const img = document.createElement("img");
const loadPromise = new Promise((resolve, reject) => {
img.onload = resolve;
@ -364,7 +366,7 @@ export default class MImageBody extends React.Component<IBodyProps, IState> {
}
}
protected getBanner(content: IMediaEventContent): JSX.Element {
protected getBanner(content: IMediaEventContent): ReactNode {
// Hide it for the threads list & the file panel where we show it as text anyway.
if (
[TimelineRenderingType.ThreadsList, TimelineRenderingType.File].includes(this.context.timelineRenderingType)
@ -429,9 +431,9 @@ export default class MImageBody extends React.Component<IBodyProps, IState> {
forcedHeight ?? this.props.maxImageHeight,
);
let img: JSX.Element;
let placeholder: JSX.Element;
let gifLabel: JSX.Element;
let img: JSX.Element | undefined;
let placeholder: JSX.Element | undefined;
let gifLabel: JSX.Element | undefined;
if (!this.props.forExport && !this.state.imgLoaded) {
const classes = classNames("mx_MImageBody_placeholder", {
@ -471,7 +473,7 @@ export default class MImageBody extends React.Component<IBodyProps, IState> {
gifLabel = <p className="mx_MImageBody_gifLabel">GIF</p>;
}
let banner: JSX.Element;
let banner: ReactNode | undefined;
if (this.state.showImage && this.state.hover) {
banner = this.getBanner(content);
}
@ -526,7 +528,7 @@ export default class MImageBody extends React.Component<IBodyProps, IState> {
}
// Overridden by MStickerBody
protected getPlaceholder(width: number, height: number): JSX.Element {
protected getPlaceholder(width: number, height: number): ReactNode {
const blurhash = this.props.mxEvent.getContent().info?.[BLURHASH_FIELD];
if (blurhash) {
@ -540,12 +542,12 @@ export default class MImageBody extends React.Component<IBodyProps, IState> {
}
// Overridden by MStickerBody
protected getTooltip(): JSX.Element {
protected getTooltip(): ReactNode {
return null;
}
// Overridden by MStickerBody
protected getFileBody(): string | JSX.Element {
protected getFileBody(): ReactNode {
if (this.props.forExport) return null;
/*
* In the room timeline or the thread context we don't need the download
@ -577,7 +579,7 @@ export default class MImageBody extends React.Component<IBodyProps, IState> {
}
let contentUrl = this.state.contentUrl;
let thumbUrl: string;
let thumbUrl: string | undefined;
if (this.props.forExport) {
contentUrl = this.props.mxEvent.getContent().url ?? this.props.mxEvent.getContent().file?.url;
thumbUrl = contentUrl;