Apply strictNullChecks to src/components/views/avatars/* (#10254)
This commit is contained in:
parent
eca28ac2f3
commit
ae5725b24c
7 changed files with 41 additions and 31 deletions
|
@ -139,14 +139,18 @@ export function getInitialLetter(name: string): string | undefined {
|
|||
|
||||
export function avatarUrlForRoom(
|
||||
room: Room | null,
|
||||
width: number,
|
||||
height: number,
|
||||
width?: number,
|
||||
height?: number,
|
||||
resizeMethod?: ResizeMethod,
|
||||
): string | null {
|
||||
if (!room) return null; // null-guard
|
||||
|
||||
if (room.getMxcAvatarUrl()) {
|
||||
return mediaFromMxc(room.getMxcAvatarUrl() || undefined).getThumbnailOfSourceHttp(width, height, resizeMethod);
|
||||
const media = mediaFromMxc(room.getMxcAvatarUrl() ?? undefined);
|
||||
if (width !== undefined && height !== undefined) {
|
||||
return media.getThumbnailOfSourceHttp(width, height, resizeMethod);
|
||||
}
|
||||
return media.srcHttp;
|
||||
}
|
||||
|
||||
// space rooms cannot be DMs so skip the rest
|
||||
|
@ -160,7 +164,11 @@ export function avatarUrlForRoom(
|
|||
// If there are only two members in the DM use the avatar of the other member
|
||||
const otherMember = room.getAvatarFallbackMember();
|
||||
if (otherMember?.getMxcAvatarUrl()) {
|
||||
return mediaFromMxc(otherMember.getMxcAvatarUrl()).getThumbnailOfSourceHttp(width, height, resizeMethod);
|
||||
const media = mediaFromMxc(otherMember.getMxcAvatarUrl());
|
||||
if (width !== undefined && height !== undefined) {
|
||||
return media.getThumbnailOfSourceHttp(width, height, resizeMethod);
|
||||
}
|
||||
return media.srcHttp;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -35,10 +35,10 @@ interface IProps {
|
|||
name?: string; // The name (first initial used as default)
|
||||
idName?: string; // ID for generating hash colours
|
||||
title?: string; // onHover title text
|
||||
url?: string; // highest priority of them all, shortcut to set in urls[0]
|
||||
url?: string | null; // highest priority of them all, shortcut to set in urls[0]
|
||||
urls?: string[]; // [highest_priority, ... , lowest_priority]
|
||||
width?: number;
|
||||
height?: number;
|
||||
width: number;
|
||||
height: number;
|
||||
// XXX: resizeMethod not actually used.
|
||||
resizeMethod?: ResizeMethod;
|
||||
defaultToInitialLetter?: boolean; // true to add default url
|
||||
|
@ -48,7 +48,7 @@ interface IProps {
|
|||
tabIndex?: number;
|
||||
}
|
||||
|
||||
const calculateUrls = (url?: string, urls?: string[], lowBandwidth = false): string[] => {
|
||||
const calculateUrls = (url?: string | null, urls?: string[], lowBandwidth = false): string[] => {
|
||||
// work out the full set of urls to try to load. This is formed like so:
|
||||
// imageUrls: [ props.url, ...props.urls ]
|
||||
|
||||
|
@ -66,7 +66,7 @@ const calculateUrls = (url?: string, urls?: string[], lowBandwidth = false): str
|
|||
return Array.from(new Set(_urls));
|
||||
};
|
||||
|
||||
const useImageUrl = ({ url, urls }: { url?: string; urls?: string[] }): [string, () => void] => {
|
||||
const useImageUrl = ({ url, urls }: { url?: string | null; urls?: string[] }): [string, () => void] => {
|
||||
// Since this is a hot code path and the settings store can be slow, we
|
||||
// use the cached lowBandwidth value from the room context if it exists
|
||||
const roomContext = useContext(RoomContext);
|
||||
|
|
|
@ -62,7 +62,7 @@ enum Icon {
|
|||
PresenceBusy = "BUSY",
|
||||
}
|
||||
|
||||
function tooltipText(variant: Icon): string {
|
||||
function tooltipText(variant: Icon): string | undefined {
|
||||
switch (variant) {
|
||||
case Icon.Globe:
|
||||
return _t("This room is public");
|
||||
|
@ -78,7 +78,7 @@ function tooltipText(variant: Icon): string {
|
|||
}
|
||||
|
||||
export default class DecoratedRoomAvatar extends React.PureComponent<IProps, IState> {
|
||||
private _dmUser: User;
|
||||
private _dmUser: User | null;
|
||||
private isUnmounted = false;
|
||||
private isWatchingTimeline = false;
|
||||
|
||||
|
@ -103,11 +103,11 @@ export default class DecoratedRoomAvatar extends React.PureComponent<IProps, ISt
|
|||
return joinRule === JoinRule.Public;
|
||||
}
|
||||
|
||||
private get dmUser(): User {
|
||||
private get dmUser(): User | null {
|
||||
return this._dmUser;
|
||||
}
|
||||
|
||||
private set dmUser(val: User) {
|
||||
private set dmUser(val: User | null) {
|
||||
const oldUser = this._dmUser;
|
||||
this._dmUser = val;
|
||||
if (oldUser && oldUser !== this._dmUser) {
|
||||
|
@ -120,7 +120,7 @@ export default class DecoratedRoomAvatar extends React.PureComponent<IProps, ISt
|
|||
}
|
||||
}
|
||||
|
||||
private onRoomTimeline = (ev: MatrixEvent, room: Room | null): void => {
|
||||
private onRoomTimeline = (ev: MatrixEvent, room?: Room): void => {
|
||||
if (this.isUnmounted) return;
|
||||
if (this.props.room.roomId !== room?.roomId) return;
|
||||
|
||||
|
@ -182,7 +182,7 @@ export default class DecoratedRoomAvatar extends React.PureComponent<IProps, ISt
|
|||
|
||||
public render(): React.ReactNode {
|
||||
let badge: React.ReactNode;
|
||||
if (this.props.displayBadge) {
|
||||
if (this.props.displayBadge && this.state.notificationState) {
|
||||
badge = (
|
||||
<NotificationBadge
|
||||
notification={this.state.notificationState}
|
||||
|
@ -192,7 +192,7 @@ export default class DecoratedRoomAvatar extends React.PureComponent<IProps, ISt
|
|||
);
|
||||
}
|
||||
|
||||
let icon;
|
||||
let icon: JSX.Element | undefined;
|
||||
if (this.state.icon !== Icon.None) {
|
||||
icon = (
|
||||
<TextWithTooltip
|
||||
|
|
|
@ -65,7 +65,7 @@ export default function MemberAvatar({
|
|||
|
||||
const name = member?.name ?? fallbackUserId;
|
||||
let title: string | undefined = props.title;
|
||||
let imageUrl: string | undefined;
|
||||
let imageUrl: string | null | undefined;
|
||||
if (member?.name) {
|
||||
if (member.getMxcAvatarUrl()) {
|
||||
imageUrl = mediaFromMxc(member.getMxcAvatarUrl() ?? "").getThumbnailOfSourceHttp(
|
||||
|
|
|
@ -30,13 +30,14 @@ import DMRoomMap from "../../../utils/DMRoomMap";
|
|||
import { mediaFromMxc } from "../../../customisations/Media";
|
||||
import { IOOBData } from "../../../stores/ThreepidInviteStore";
|
||||
import { LocalRoom } from "../../../models/LocalRoom";
|
||||
import { filterBoolean } from "../../../utils/arrays";
|
||||
|
||||
interface IProps extends Omit<ComponentProps<typeof BaseAvatar>, "name" | "idName" | "url" | "onClick"> {
|
||||
// Room may be left unset here, but if it is,
|
||||
// oobData.avatarUrl should be set (else there
|
||||
// would be nowhere to get the avatar from)
|
||||
room?: Room;
|
||||
oobData?: IOOBData & {
|
||||
oobData: IOOBData & {
|
||||
roomId?: string;
|
||||
};
|
||||
viewAvatarOnClick?: boolean;
|
||||
|
@ -86,7 +87,7 @@ export default class RoomAvatar extends React.Component<IProps, IState> {
|
|||
};
|
||||
|
||||
private static getImageUrls(props: IProps): string[] {
|
||||
let oobAvatar = null;
|
||||
let oobAvatar: string | null = null;
|
||||
if (props.oobData.avatarUrl) {
|
||||
oobAvatar = mediaFromMxc(props.oobData.avatarUrl).getThumbnailOfSourceHttp(
|
||||
props.width,
|
||||
|
@ -94,28 +95,27 @@ export default class RoomAvatar extends React.Component<IProps, IState> {
|
|||
props.resizeMethod,
|
||||
);
|
||||
}
|
||||
return [
|
||||
|
||||
return filterBoolean([
|
||||
oobAvatar, // highest priority
|
||||
RoomAvatar.getRoomAvatarUrl(props),
|
||||
].filter(function (url) {
|
||||
return url !== null && url !== "";
|
||||
});
|
||||
]);
|
||||
}
|
||||
|
||||
private static getRoomAvatarUrl(props: IProps): string {
|
||||
private static getRoomAvatarUrl(props: IProps): string | null {
|
||||
if (!props.room) return null;
|
||||
|
||||
return Avatar.avatarUrlForRoom(props.room, props.width, props.height, props.resizeMethod);
|
||||
}
|
||||
|
||||
private onRoomAvatarClick = (): void => {
|
||||
const avatarUrl = Avatar.avatarUrlForRoom(this.props.room, null, null, null);
|
||||
const avatarUrl = Avatar.avatarUrlForRoom(this.props.room ?? null, undefined, undefined, undefined);
|
||||
const params = {
|
||||
src: avatarUrl,
|
||||
name: this.props.room.name,
|
||||
name: this.props.room?.name,
|
||||
};
|
||||
|
||||
Modal.createDialog(ImageView, params, "mx_Dialog_lightbox", null, true);
|
||||
Modal.createDialog(ImageView, params, "mx_Dialog_lightbox", undefined, true);
|
||||
};
|
||||
|
||||
private get roomIdName(): string | undefined {
|
||||
|
@ -137,7 +137,7 @@ export default class RoomAvatar extends React.Component<IProps, IState> {
|
|||
|
||||
public render(): React.ReactNode {
|
||||
const { room, oobData, viewAvatarOnClick, onClick, className, ...otherProps } = this.props;
|
||||
const roomName = room?.name ?? oobData.name;
|
||||
const roomName = room?.name ?? oobData.name ?? "?";
|
||||
|
||||
return (
|
||||
<BaseAvatar
|
||||
|
|
|
@ -21,8 +21,10 @@ import { IApp } from "../../../stores/WidgetStore";
|
|||
import BaseAvatar, { BaseAvatarType } from "./BaseAvatar";
|
||||
import { mediaFromMxc } from "../../../customisations/Media";
|
||||
|
||||
interface IProps extends Omit<ComponentProps<BaseAvatarType>, "name" | "url" | "urls"> {
|
||||
interface IProps extends Omit<ComponentProps<BaseAvatarType>, "name" | "url" | "urls" | "height" | "width"> {
|
||||
app: IApp;
|
||||
height?: number;
|
||||
width?: number;
|
||||
}
|
||||
|
||||
const WidgetAvatar: React.FC<IProps> = ({ app, className, width = 20, height = 20, ...props }) => {
|
||||
|
@ -44,7 +46,7 @@ const WidgetAvatar: React.FC<IProps> = ({ app, className, width = 20, height = 2
|
|||
name={app.id}
|
||||
className={classNames("mx_WidgetAvatar", className)}
|
||||
// MSC2765
|
||||
url={app.avatar_url ? mediaFromMxc(app.avatar_url).getSquareThumbnailHttp(20) : undefined}
|
||||
url={app.avatar_url ? mediaFromMxc(app.avatar_url).getSquareThumbnailHttp(20) : null}
|
||||
urls={iconUrls}
|
||||
width={width}
|
||||
height={height}
|
||||
|
|
|
@ -31,7 +31,7 @@ function getDisplayUserIdentifier(
|
|||
// them all as optional. This allows customisers to only define and export the
|
||||
// customisations they need while still maintaining type safety.
|
||||
export interface IUserIdentifierCustomisations {
|
||||
getDisplayUserIdentifier?: typeof getDisplayUserIdentifier;
|
||||
getDisplayUserIdentifier: typeof getDisplayUserIdentifier;
|
||||
}
|
||||
|
||||
// A real customisation module will define and export one or more of the
|
||||
|
|
Loading…
Reference in a new issue