Apply strictNullChecks to src/components/views/room_settings/* (#10366

* Apply `strictNullChecks` to `src/components/views/room_settings/*`

* Restore tsconfig.json
This commit is contained in:
Michael Telatynski 2023-03-15 08:39:02 +00:00 committed by GitHub
parent e3930fb8b0
commit ad65b4e444
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 37 additions and 30 deletions

View file

@ -21,7 +21,7 @@ import Field from "./Field";
import AccessibleButton, { ButtonEvent } from "./AccessibleButton"; import AccessibleButton, { ButtonEvent } from "./AccessibleButton";
interface IItemProps { interface IItemProps {
index?: number; index: number;
value?: string; value?: string;
onRemove?(index: number): void; onRemove?(index: number): void;
} }
@ -99,7 +99,7 @@ interface IProps {
canEdit?: boolean; canEdit?: boolean;
canRemove?: boolean; canRemove?: boolean;
suggestionsListId?: string; suggestionsListId?: string;
onItemAdded?(item: string): void; onItemAdded?(item?: string): void;
onItemRemoved?(index: number): void; onItemRemoved?(index: number): void;
onNewItemChanged?(item: string): void; onNewItemChanged?(item: string): void;
} }

View file

@ -41,6 +41,8 @@ class EditableAliasesList extends EditableItemList<IEditableAliasesListProps> {
private onAliasAdded = async (ev: SyntheticEvent): Promise<void> => { private onAliasAdded = async (ev: SyntheticEvent): Promise<void> => {
ev.preventDefault(); ev.preventDefault();
if (!this.aliasField.current) return;
await this.aliasField.current.validate({ allowEmpty: false }); await this.aliasField.current.validate({ allowEmpty: false });
if (this.aliasField.current.isValid) { if (this.aliasField.current.isValid) {
@ -85,9 +87,12 @@ interface IProps {
} }
interface IState { interface IState {
// [ #alias:domain.tld, ... ]
altAliases: string[]; altAliases: string[];
// [ #alias:my-hs.tld, ... ]
localAliases: string[]; localAliases: string[];
canonicalAlias?: string; // #canonical:domain.tld
canonicalAlias: string | null;
updatingCanonicalAlias: boolean; updatingCanonicalAlias: boolean;
localAliasesLoading: boolean; localAliasesLoading: boolean;
detailsOpen: boolean; detailsOpen: boolean;
@ -108,9 +113,9 @@ export default class AliasSettings extends React.Component<IProps, IState> {
super(props, context); super(props, context);
const state: IState = { const state: IState = {
altAliases: [], // [ #alias:domain.tld, ... ] altAliases: [],
localAliases: [], // [ #alias:my-hs.tld, ... ] localAliases: [],
canonicalAlias: null, // #canonical:domain.tld canonicalAlias: null,
updatingCanonicalAlias: false, updatingCanonicalAlias: false,
localAliasesLoading: false, localAliasesLoading: false,
detailsOpen: false, detailsOpen: false,
@ -156,7 +161,7 @@ export default class AliasSettings extends React.Component<IProps, IState> {
} }
} }
private changeCanonicalAlias(alias: string): void { private changeCanonicalAlias(alias: string | null): void {
if (!this.props.canSetCanonicalAlias) return; if (!this.props.canSetCanonicalAlias) return;
const oldAlias = this.state.canonicalAlias; const oldAlias = this.state.canonicalAlias;
@ -232,7 +237,7 @@ export default class AliasSettings extends React.Component<IProps, IState> {
this.setState({ newAlias: value }); this.setState({ newAlias: value });
}; };
private onLocalAliasAdded = (alias: string): void => { private onLocalAliasAdded = (alias?: string): void => {
if (!alias || alias.length === 0) return; // ignore attempts to create blank aliases if (!alias || alias.length === 0) return; // ignore attempts to create blank aliases
const localDomain = this.context.getDomain(); const localDomain = this.context.getDomain();
@ -242,11 +247,11 @@ export default class AliasSettings extends React.Component<IProps, IState> {
.createAlias(alias, this.props.roomId) .createAlias(alias, this.props.roomId)
.then(() => { .then(() => {
this.setState({ this.setState({
localAliases: this.state.localAliases.concat(alias), localAliases: this.state.localAliases.concat(alias!),
newAlias: null, newAlias: undefined,
}); });
if (!this.state.canonicalAlias) { if (!this.state.canonicalAlias) {
this.changeCanonicalAlias(alias); this.changeCanonicalAlias(alias!);
} }
}) })
.catch((err) => { .catch((err) => {
@ -338,7 +343,7 @@ export default class AliasSettings extends React.Component<IProps, IState> {
public render(): React.ReactNode { public render(): React.ReactNode {
const mxClient = this.context; const mxClient = this.context;
const localDomain = mxClient.getDomain(); const localDomain = mxClient.getDomain()!;
const isSpaceRoom = mxClient.getRoom(this.props.roomId)?.isSpaceRoom(); const isSpaceRoom = mxClient.getRoom(this.props.roomId)?.isSpaceRoom();
let found = false; let found = false;

View file

@ -16,6 +16,7 @@ limitations under the License.
import React, { createRef } from "react"; import React, { createRef } from "react";
import classNames from "classnames"; import classNames from "classnames";
import { EventType } from "matrix-js-sdk/src/matrix";
import { _t } from "../../../languageHandler"; import { _t } from "../../../languageHandler";
import { MatrixClientPeg } from "../../../MatrixClientPeg"; import { MatrixClientPeg } from "../../../MatrixClientPeg";
@ -33,9 +34,9 @@ interface IProps {
interface IState { interface IState {
originalDisplayName: string; originalDisplayName: string;
displayName: string; displayName: string;
originalAvatarUrl: string; originalAvatarUrl: string | null;
avatarUrl: string; avatarUrl: string | null;
avatarFile: File; avatarFile: File | null;
originalTopic: string; originalTopic: string;
topic: string; topic: string;
profileFieldsTouched: Record<string, boolean>; profileFieldsTouched: Record<string, boolean>;
@ -55,16 +56,17 @@ export default class RoomProfileSettings extends React.Component<IProps, IState>
const room = client.getRoom(props.roomId); const room = client.getRoom(props.roomId);
if (!room) throw new Error(`Expected a room for ID: ${props.roomId}`); if (!room) throw new Error(`Expected a room for ID: ${props.roomId}`);
const avatarEvent = room.currentState.getStateEvents("m.room.avatar", ""); const avatarEvent = room.currentState.getStateEvents(EventType.RoomAvatar, "");
let avatarUrl = avatarEvent && avatarEvent.getContent() ? avatarEvent.getContent()["url"] : null; let avatarUrl = avatarEvent?.getContent()["url"] ?? null;
if (avatarUrl) avatarUrl = mediaFromMxc(avatarUrl).getSquareThumbnailHttp(96); if (avatarUrl) avatarUrl = mediaFromMxc(avatarUrl).getSquareThumbnailHttp(96);
const topicEvent = room.currentState.getStateEvents("m.room.topic", ""); const topicEvent = room.currentState.getStateEvents(EventType.RoomTopic, "");
const topic = topicEvent && topicEvent.getContent() ? topicEvent.getContent()["topic"] : ""; const topic = topicEvent && topicEvent.getContent() ? topicEvent.getContent()["topic"] : "";
const nameEvent = room.currentState.getStateEvents("m.room.name", ""); const nameEvent = room.currentState.getStateEvents(EventType.RoomName, "");
const name = nameEvent && nameEvent.getContent() ? nameEvent.getContent()["name"] : ""; const name = nameEvent && nameEvent.getContent() ? nameEvent.getContent()["name"] : "";
const userId = client.getSafeUserId();
this.state = { this.state = {
originalDisplayName: name, originalDisplayName: name,
displayName: name, displayName: name,
@ -74,19 +76,19 @@ export default class RoomProfileSettings extends React.Component<IProps, IState>
originalTopic: topic, originalTopic: topic,
topic: topic, topic: topic,
profileFieldsTouched: {}, profileFieldsTouched: {},
canSetName: room.currentState.maySendStateEvent("m.room.name", client.getUserId()), canSetName: room.currentState.maySendStateEvent(EventType.RoomName, userId),
canSetTopic: room.currentState.maySendStateEvent("m.room.topic", client.getUserId()), canSetTopic: room.currentState.maySendStateEvent(EventType.RoomTopic, userId),
canSetAvatar: room.currentState.maySendStateEvent("m.room.avatar", client.getUserId()), canSetAvatar: room.currentState.maySendStateEvent(EventType.RoomAvatar, userId),
}; };
} }
private uploadAvatar = (): void => { private uploadAvatar = (): void => {
this.avatarUpload.current.click(); this.avatarUpload.current?.click();
}; };
private removeAvatar = (): void => { private removeAvatar = (): void => {
// clear file upload field so same file can be selected // clear file upload field so same file can be selected
this.avatarUpload.current.value = ""; if (this.avatarUpload.current) this.avatarUpload.current.value = "";
this.setState({ this.setState({
avatarUrl: null, avatarUrl: null,
avatarFile: null, avatarFile: null,
@ -135,12 +137,12 @@ export default class RoomProfileSettings extends React.Component<IProps, IState>
if (this.state.avatarFile) { if (this.state.avatarFile) {
const { content_uri: uri } = await client.uploadContent(this.state.avatarFile); const { content_uri: uri } = await client.uploadContent(this.state.avatarFile);
await client.sendStateEvent(this.props.roomId, "m.room.avatar", { url: uri }, ""); await client.sendStateEvent(this.props.roomId, EventType.RoomAvatar, { url: uri }, "");
newState.avatarUrl = mediaFromMxc(uri).getSquareThumbnailHttp(96); newState.avatarUrl = mediaFromMxc(uri).getSquareThumbnailHttp(96);
newState.originalAvatarUrl = newState.avatarUrl; newState.originalAvatarUrl = newState.avatarUrl;
newState.avatarFile = null; newState.avatarFile = null;
} else if (this.state.originalAvatarUrl !== this.state.avatarUrl) { } else if (this.state.originalAvatarUrl !== this.state.avatarUrl) {
await client.sendStateEvent(this.props.roomId, "m.room.avatar", {}, ""); await client.sendStateEvent(this.props.roomId, EventType.RoomAvatar, {}, "");
} }
if (this.state.originalTopic !== this.state.topic) { if (this.state.originalTopic !== this.state.topic) {
@ -207,7 +209,7 @@ export default class RoomProfileSettings extends React.Component<IProps, IState>
const reader = new FileReader(); const reader = new FileReader();
reader.onload = (ev) => { reader.onload = (ev) => {
this.setState({ this.setState({
avatarUrl: String(ev.target.result), avatarUrl: String(ev.target?.result),
avatarFile: file, avatarFile: file,
profileFieldsTouched: { profileFieldsTouched: {
...this.state.profileFieldsTouched, ...this.state.profileFieldsTouched,
@ -269,7 +271,7 @@ export default class RoomProfileSettings extends React.Component<IProps, IState>
/> />
</div> </div>
<AvatarSetting <AvatarSetting
avatarUrl={this.state.avatarUrl} avatarUrl={this.state.avatarUrl ?? undefined}
avatarName={this.state.displayName || this.props.roomId} avatarName={this.state.displayName || this.props.roomId}
avatarAltText={_t("Room avatar")} avatarAltText={_t("Room avatar")}
uploadAvatar={this.state.canSetAvatar ? this.uploadAvatar : undefined} uploadAvatar={this.state.canSetAvatar ? this.uploadAvatar : undefined}

View file

@ -15,7 +15,7 @@ limitations under the License.
*/ */
import React from "react"; import React from "react";
import { Visibility } from "matrix-js-sdk/src/@types/partials"; import { JoinRule, Visibility } from "matrix-js-sdk/src/@types/partials";
import LabelledToggleSwitch from "../elements/LabelledToggleSwitch"; import LabelledToggleSwitch from "../elements/LabelledToggleSwitch";
import { _t } from "../../../languageHandler"; import { _t } from "../../../languageHandler";
@ -66,7 +66,7 @@ export default class RoomPublishSetting extends React.PureComponent<IProps, ISta
const client = MatrixClientPeg.get(); const client = MatrixClientPeg.get();
const room = client.getRoom(this.props.roomId); const room = client.getRoom(this.props.roomId);
const isRoomPublishable = room.getJoinRule() !== "invite"; const isRoomPublishable = room && room.getJoinRule() !== JoinRule.Invite;
const enabled = const enabled =
(DirectoryCustomisations.requireCanonicalAliasAccessToPublish?.() === false || (DirectoryCustomisations.requireCanonicalAliasAccessToPublish?.() === false ||