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:
parent
e3930fb8b0
commit
ad65b4e444
4 changed files with 37 additions and 30 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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}
|
||||||
|
|
|
@ -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 ||
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue