Conform more code to strict null checking (#10169)
* Conform more code to strict null checking * delint * Iterate * delint * Fix bad test
This commit is contained in:
parent
5123d7e641
commit
e8b92b308b
85 changed files with 283 additions and 287 deletions
|
@ -68,7 +68,7 @@ interface IState {
|
|||
export default class LeftPanel extends React.Component<IProps, IState> {
|
||||
private listContainerRef = createRef<HTMLDivElement>();
|
||||
private roomListRef = createRef<RoomList>();
|
||||
private focusedElement: Element = null;
|
||||
private focusedElement: Element | null = null;
|
||||
private isDoingStickyHeaders = false;
|
||||
|
||||
public constructor(props: IProps) {
|
||||
|
|
|
@ -41,7 +41,7 @@ const KEY_FILE_MAX_SIZE = 128;
|
|||
const VALIDATION_THROTTLE_MS = 200;
|
||||
|
||||
interface IProps extends IDialogProps {
|
||||
keyInfo: ISecretStorageKeyInfo;
|
||||
keyInfo?: ISecretStorageKeyInfo;
|
||||
checkPrivateKey: (k: { passphrase?: string; recoveryKey?: string }) => boolean;
|
||||
}
|
||||
|
||||
|
@ -137,7 +137,7 @@ export default class AccessSecretStorageDialog extends React.PureComponent<IProp
|
|||
};
|
||||
|
||||
private onRecoveryKeyFileChange = async (ev: ChangeEvent<HTMLInputElement>): Promise<void> => {
|
||||
if (ev.target.files.length === 0) return;
|
||||
if (!ev.target.files?.length) return;
|
||||
|
||||
const f = ev.target.files[0];
|
||||
|
||||
|
@ -170,7 +170,7 @@ export default class AccessSecretStorageDialog extends React.PureComponent<IProp
|
|||
};
|
||||
|
||||
private onRecoveryKeyFileUploadClick = (): void => {
|
||||
this.fileUpload.current.click();
|
||||
this.fileUpload.current?.click();
|
||||
};
|
||||
|
||||
private onPassPhraseNext = async (ev: FormEvent<HTMLFormElement> | React.MouseEvent): Promise<void> => {
|
||||
|
@ -269,15 +269,11 @@ export default class AccessSecretStorageDialog extends React.PureComponent<IProp
|
|||
}
|
||||
|
||||
public render(): React.ReactNode {
|
||||
const hasPassphrase =
|
||||
this.props.keyInfo &&
|
||||
this.props.keyInfo.passphrase &&
|
||||
this.props.keyInfo.passphrase.salt &&
|
||||
this.props.keyInfo.passphrase.iterations;
|
||||
const hasPassphrase = this.props.keyInfo?.passphrase?.salt && this.props.keyInfo?.passphrase?.iterations;
|
||||
|
||||
const resetButton = (
|
||||
<div className="mx_AccessSecretStorageDialog_reset">
|
||||
{_t("Forgotten or lost all recovery methods? <a>Reset all</a>", null, {
|
||||
{_t("Forgotten or lost all recovery methods? <a>Reset all</a>", undefined, {
|
||||
a: (sub) => (
|
||||
<AccessibleButton
|
||||
kind="link_inline"
|
||||
|
@ -405,7 +401,7 @@ export default class AccessSecretStorageDialog extends React.PureComponent<IProp
|
|||
value={this.state.recoveryKey}
|
||||
onChange={this.onRecoveryKeyChange}
|
||||
autoFocus={true}
|
||||
forceValidity={this.state.recoveryKeyCorrect}
|
||||
forceValidity={this.state.recoveryKeyCorrect ?? undefined}
|
||||
autoComplete="off"
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -112,8 +112,8 @@ export interface INativeOnChangeInputProps extends IProps, InputHTMLAttributes<H
|
|||
type PropShapes = IInputProps | ISelectProps | ITextareaProps | INativeOnChangeInputProps;
|
||||
|
||||
interface IState {
|
||||
valid: boolean;
|
||||
feedback: React.ReactNode;
|
||||
valid?: boolean;
|
||||
feedback?: React.ReactNode;
|
||||
feedbackVisible: boolean;
|
||||
focused: boolean;
|
||||
}
|
||||
|
@ -148,8 +148,6 @@ export default class Field extends React.PureComponent<PropShapes, IState> {
|
|||
public constructor(props: PropShapes) {
|
||||
super(props);
|
||||
this.state = {
|
||||
valid: undefined,
|
||||
feedback: undefined,
|
||||
feedbackVisible: false,
|
||||
focused: false,
|
||||
};
|
||||
|
@ -199,7 +197,7 @@ export default class Field extends React.PureComponent<PropShapes, IState> {
|
|||
this.props.onBlur?.(ev);
|
||||
};
|
||||
|
||||
public async validate({ focused, allowEmpty = true }: IValidateOpts): Promise<boolean> {
|
||||
public async validate({ focused, allowEmpty = true }: IValidateOpts): Promise<boolean | undefined> {
|
||||
if (!this.props.onValidate) {
|
||||
return;
|
||||
}
|
||||
|
@ -268,11 +266,11 @@ export default class Field extends React.PureComponent<PropShapes, IState> {
|
|||
|
||||
const fieldInput = React.createElement(this.props.element, inputProps_, children);
|
||||
|
||||
let prefixContainer = null;
|
||||
let prefixContainer: JSX.Element | undefined;
|
||||
if (prefixComponent) {
|
||||
prefixContainer = <span className="mx_Field_prefix">{prefixComponent}</span>;
|
||||
}
|
||||
let postfixContainer = null;
|
||||
let postfixContainer: JSX.Element | undefined;
|
||||
if (postfixComponent) {
|
||||
postfixContainer = <span className="mx_Field_postfix">{postfixComponent}</span>;
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import React, { ReactNode } from "react";
|
||||
import { Room } from "matrix-js-sdk/src/models/room";
|
||||
|
||||
import { _t, _td } from "../../../languageHandler";
|
||||
|
@ -41,12 +41,12 @@ export default class UrlPreviewSettings extends React.Component<IProps> {
|
|||
dis.fire(Action.ViewUserSettings);
|
||||
};
|
||||
|
||||
public render(): React.ReactNode {
|
||||
public render(): ReactNode {
|
||||
const roomId = this.props.room.roomId;
|
||||
const isEncrypted = MatrixClientPeg.get().isRoomEncrypted(roomId);
|
||||
|
||||
let previewsForAccount = null;
|
||||
let previewsForRoom = null;
|
||||
let previewsForAccount: ReactNode | undefined;
|
||||
let previewsForRoom: ReactNode | undefined;
|
||||
|
||||
if (!isEncrypted) {
|
||||
// Only show account setting state and room state setting state in non-e2ee rooms where they apply
|
||||
|
|
|
@ -28,10 +28,10 @@ import { SettingLevel } from "../../../settings/SettingLevel";
|
|||
|
||||
interface IProps {
|
||||
userId?: string;
|
||||
displayName: string;
|
||||
avatarUrl: string;
|
||||
displayName?: string;
|
||||
avatarUrl?: string;
|
||||
messagePreviewText: string;
|
||||
onLayoutChanged?: (layout: Layout) => void;
|
||||
onLayoutChanged: (layout: Layout) => void;
|
||||
}
|
||||
|
||||
interface IState {
|
||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import React, { ReactNode } from "react";
|
||||
import { IAnnotatedPushRule, IPusher, PushRuleAction, PushRuleKind, RuleId } from "matrix-js-sdk/src/@types/PushRules";
|
||||
import { IThreepid, ThreepidMedium } from "matrix-js-sdk/src/@types/threepids";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
|
@ -152,7 +152,7 @@ export default class Notifications extends React.PureComponent<IProps, IState> {
|
|||
// the master rule is *enabled* it means all other rules are *disabled* (or
|
||||
// inhibited). Conversely, when the master rule is *disabled* then all other rules
|
||||
// are *enabled* (or operate fine).
|
||||
return this.state.masterPushRule?.enabled;
|
||||
return !!this.state.masterPushRule?.enabled;
|
||||
}
|
||||
|
||||
public componentDidMount(): void {
|
||||
|
@ -622,12 +622,12 @@ export default class Notifications extends React.PureComponent<IProps, IState> {
|
|||
);
|
||||
}
|
||||
|
||||
private renderCategory(category: RuleClass): JSX.Element {
|
||||
private renderCategory(category: RuleClass): ReactNode {
|
||||
if (category !== RuleClass.VectorOther && this.isInhibited) {
|
||||
return null; // nothing to show for the section
|
||||
}
|
||||
|
||||
let clearNotifsButton: JSX.Element;
|
||||
let clearNotifsButton: JSX.Element | undefined;
|
||||
if (
|
||||
category === RuleClass.VectorOther &&
|
||||
MatrixClientPeg.get()
|
||||
|
@ -660,7 +660,7 @@ export default class Notifications extends React.PureComponent<IProps, IState> {
|
|||
return null;
|
||||
}
|
||||
|
||||
let keywordComposer: JSX.Element;
|
||||
let keywordComposer: JSX.Element | undefined;
|
||||
if (category === RuleClass.VectorMentions) {
|
||||
keywordComposer = (
|
||||
<TagComposer
|
||||
|
@ -691,7 +691,7 @@ export default class Notifications extends React.PureComponent<IProps, IState> {
|
|||
/>
|
||||
);
|
||||
|
||||
const fieldsetRows = this.state.vectorPushRules[category].map((r) => (
|
||||
const fieldsetRows = this.state.vectorPushRules[category]?.map((r) => (
|
||||
<fieldset
|
||||
key={category + r.ruleId}
|
||||
data-testid={category + r.ruleId}
|
||||
|
@ -736,10 +736,10 @@ export default class Notifications extends React.PureComponent<IProps, IState> {
|
|||
);
|
||||
}
|
||||
|
||||
private renderTargets(): JSX.Element {
|
||||
private renderTargets(): ReactNode {
|
||||
if (this.isInhibited) return null; // no targets if there's no notifications
|
||||
|
||||
const rows = this.state.pushers.map((p) => (
|
||||
const rows = this.state.pushers?.map((p) => (
|
||||
<tr key={p.kind + p.pushkey}>
|
||||
<td>{p.app_display_name}</td>
|
||||
<td>{p.device_display_name}</td>
|
||||
|
|
|
@ -34,11 +34,11 @@ import PosthogTrackers from "../../../PosthogTrackers";
|
|||
|
||||
interface IState {
|
||||
userId?: string;
|
||||
originalDisplayName?: string;
|
||||
displayName?: string;
|
||||
originalAvatarUrl?: string;
|
||||
originalDisplayName: string;
|
||||
displayName: string;
|
||||
originalAvatarUrl: string | null;
|
||||
avatarUrl?: string | ArrayBuffer;
|
||||
avatarFile?: File;
|
||||
avatarFile?: File | null;
|
||||
enableProfileSave?: boolean;
|
||||
}
|
||||
|
||||
|
@ -52,25 +52,25 @@ export default class ProfileSettings extends React.Component<{}, IState> {
|
|||
let avatarUrl = OwnProfileStore.instance.avatarMxc;
|
||||
if (avatarUrl) avatarUrl = mediaFromMxc(avatarUrl).getSquareThumbnailHttp(96);
|
||||
this.state = {
|
||||
userId: client.getUserId(),
|
||||
originalDisplayName: OwnProfileStore.instance.displayName,
|
||||
displayName: OwnProfileStore.instance.displayName,
|
||||
userId: client.getUserId()!,
|
||||
originalDisplayName: OwnProfileStore.instance.displayName ?? "",
|
||||
displayName: OwnProfileStore.instance.displayName ?? "",
|
||||
originalAvatarUrl: avatarUrl,
|
||||
avatarUrl: avatarUrl,
|
||||
avatarUrl: avatarUrl ?? undefined,
|
||||
avatarFile: null,
|
||||
enableProfileSave: false,
|
||||
};
|
||||
}
|
||||
|
||||
private uploadAvatar = (): void => {
|
||||
this.avatarUpload.current.click();
|
||||
this.avatarUpload.current?.click();
|
||||
};
|
||||
|
||||
private removeAvatar = (): void => {
|
||||
// clear file upload field so same file can be selected
|
||||
this.avatarUpload.current.value = "";
|
||||
this.setState({
|
||||
avatarUrl: null,
|
||||
avatarUrl: undefined,
|
||||
avatarFile: null,
|
||||
enableProfileSave: true,
|
||||
});
|
||||
|
@ -84,7 +84,7 @@ export default class ProfileSettings extends React.Component<{}, IState> {
|
|||
this.setState({
|
||||
enableProfileSave: false,
|
||||
displayName: this.state.originalDisplayName,
|
||||
avatarUrl: this.state.originalAvatarUrl,
|
||||
avatarUrl: this.state.originalAvatarUrl ?? undefined,
|
||||
avatarFile: null,
|
||||
});
|
||||
};
|
||||
|
@ -97,7 +97,7 @@ export default class ProfileSettings extends React.Component<{}, IState> {
|
|||
this.setState({ enableProfileSave: false });
|
||||
|
||||
const client = MatrixClientPeg.get();
|
||||
const newState: IState = {};
|
||||
const newState: Partial<IState> = {};
|
||||
|
||||
const displayName = this.state.displayName.trim();
|
||||
try {
|
||||
|
@ -114,7 +114,7 @@ export default class ProfileSettings extends React.Component<{}, IState> {
|
|||
);
|
||||
const { content_uri: uri } = await client.uploadContent(this.state.avatarFile);
|
||||
await client.setAvatarUrl(uri);
|
||||
newState.avatarUrl = mediaFromMxc(uri).getSquareThumbnailHttp(96);
|
||||
newState.avatarUrl = mediaFromMxc(uri).getSquareThumbnailHttp(96) ?? undefined;
|
||||
newState.originalAvatarUrl = newState.avatarUrl;
|
||||
newState.avatarFile = null;
|
||||
} else if (this.state.originalAvatarUrl !== this.state.avatarUrl) {
|
||||
|
@ -128,7 +128,7 @@ export default class ProfileSettings extends React.Component<{}, IState> {
|
|||
});
|
||||
}
|
||||
|
||||
this.setState(newState);
|
||||
this.setState<any>(newState);
|
||||
};
|
||||
|
||||
private onDisplayNameChanged = (e: React.ChangeEvent<HTMLInputElement>): void => {
|
||||
|
@ -141,7 +141,7 @@ export default class ProfileSettings extends React.Component<{}, IState> {
|
|||
private onAvatarChanged = (e: React.ChangeEvent<HTMLInputElement>): void => {
|
||||
if (!e.target.files || !e.target.files.length) {
|
||||
this.setState({
|
||||
avatarUrl: this.state.originalAvatarUrl,
|
||||
avatarUrl: this.state.originalAvatarUrl ?? undefined,
|
||||
avatarFile: null,
|
||||
enableProfileSave: false,
|
||||
});
|
||||
|
@ -152,7 +152,7 @@ export default class ProfileSettings extends React.Component<{}, IState> {
|
|||
const reader = new FileReader();
|
||||
reader.onload = (ev) => {
|
||||
this.setState({
|
||||
avatarUrl: ev.target.result,
|
||||
avatarUrl: ev.target?.result,
|
||||
avatarFile: file,
|
||||
enableProfileSave: true,
|
||||
});
|
||||
|
@ -162,7 +162,7 @@ export default class ProfileSettings extends React.Component<{}, IState> {
|
|||
|
||||
public render(): React.ReactNode {
|
||||
const hostingSignupLink = getHostingLink("user-settings");
|
||||
let hostingSignup = null;
|
||||
let hostingSignup: JSX.Element | undefined;
|
||||
if (hostingSignupLink) {
|
||||
hostingSignup = (
|
||||
<span>
|
||||
|
|
|
@ -27,7 +27,7 @@ import ToggleSwitch from "../elements/ToggleSwitch";
|
|||
interface IProps {}
|
||||
|
||||
interface IState {
|
||||
currentManager: IntegrationManagerInstance;
|
||||
currentManager: IntegrationManagerInstance | null;
|
||||
provisioningEnabled: boolean;
|
||||
}
|
||||
|
||||
|
|
|
@ -162,7 +162,7 @@ export default class ThemeChoicePanel extends React.Component<IProps, IState> {
|
|||
this.setState({ customThemeUrl: e.target.value });
|
||||
};
|
||||
|
||||
private renderHighContrastCheckbox(): React.ReactElement<HTMLDivElement> {
|
||||
private renderHighContrastCheckbox(): React.ReactElement<HTMLDivElement> | undefined {
|
||||
if (
|
||||
!this.state.useSystemTheme &&
|
||||
(findHighContrastTheme(this.state.theme) || isHighContrastTheme(this.state.theme))
|
||||
|
@ -181,7 +181,7 @@ export default class ThemeChoicePanel extends React.Component<IProps, IState> {
|
|||
}
|
||||
|
||||
private highContrastThemeChanged(checked: boolean): void {
|
||||
let newTheme: string;
|
||||
let newTheme: string | undefined;
|
||||
if (checked) {
|
||||
newTheme = findHighContrastTheme(this.state.theme);
|
||||
} else {
|
||||
|
@ -194,7 +194,7 @@ export default class ThemeChoicePanel extends React.Component<IProps, IState> {
|
|||
|
||||
public render(): React.ReactElement<HTMLDivElement> {
|
||||
const themeWatcher = new ThemeWatcher();
|
||||
let systemThemeSection: JSX.Element;
|
||||
let systemThemeSection: JSX.Element | undefined;
|
||||
if (themeWatcher.isSystemThemeSupported()) {
|
||||
systemThemeSection = (
|
||||
<div>
|
||||
|
@ -208,9 +208,9 @@ export default class ThemeChoicePanel extends React.Component<IProps, IState> {
|
|||
);
|
||||
}
|
||||
|
||||
let customThemeForm: JSX.Element;
|
||||
let customThemeForm: JSX.Element | undefined;
|
||||
if (SettingsStore.getValue("feature_custom_themes")) {
|
||||
let messageElement = null;
|
||||
let messageElement: JSX.Element | undefined;
|
||||
if (this.state.customThemeMessage.text) {
|
||||
if (this.state.customThemeMessage.isError) {
|
||||
messageElement = <div className="text-error">{this.state.customThemeMessage.text}</div>;
|
||||
|
@ -268,7 +268,7 @@ export default class ThemeChoicePanel extends React.Component<IProps, IState> {
|
|||
);
|
||||
}
|
||||
|
||||
public apparentSelectedThemeId(): string {
|
||||
public apparentSelectedThemeId(): string | undefined {
|
||||
if (this.state.useSystemTheme) {
|
||||
return undefined;
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ import AccessibleButton from "../../../components/views/elements/AccessibleButto
|
|||
import { CheckUpdatesPayload } from "../../../dispatcher/payloads/CheckUpdatesPayload";
|
||||
|
||||
function installUpdate(): void {
|
||||
PlatformPeg.get().installUpdate();
|
||||
PlatformPeg.get()?.installUpdate();
|
||||
}
|
||||
|
||||
function getStatusText(status: UpdateCheckStatus, errorDetail?: string): ReactNode {
|
||||
|
@ -58,11 +58,11 @@ function getStatusText(status: UpdateCheckStatus, errorDetail?: string): ReactNo
|
|||
const doneStatuses = [UpdateCheckStatus.Ready, UpdateCheckStatus.Error, UpdateCheckStatus.NotAvailable];
|
||||
|
||||
const UpdateCheckButton: React.FC = () => {
|
||||
const [state, setState] = useState<CheckUpdatesPayload>(null);
|
||||
const [state, setState] = useState<CheckUpdatesPayload | null>(null);
|
||||
|
||||
const onCheckForUpdateClick = (): void => {
|
||||
setState(null);
|
||||
PlatformPeg.get().startUpdateCheck();
|
||||
PlatformPeg.get()?.startUpdateCheck();
|
||||
};
|
||||
|
||||
useDispatcher(dis, ({ action, ...params }) => {
|
||||
|
@ -71,9 +71,9 @@ const UpdateCheckButton: React.FC = () => {
|
|||
}
|
||||
});
|
||||
|
||||
const busy = state && !doneStatuses.includes(state.status);
|
||||
const busy = !!state && !doneStatuses.includes(state.status);
|
||||
|
||||
let suffix;
|
||||
let suffix: JSX.Element | undefined;
|
||||
if (state) {
|
||||
suffix = (
|
||||
<span className="mx_UpdateCheckButton_summary">
|
||||
|
|
|
@ -31,14 +31,14 @@ import { ExtendedDevice } from "./types";
|
|||
|
||||
interface Props {
|
||||
device: ExtendedDevice;
|
||||
pusher?: IPusher | undefined;
|
||||
localNotificationSettings?: LocalNotificationSettings | undefined;
|
||||
pusher?: IPusher;
|
||||
localNotificationSettings?: LocalNotificationSettings;
|
||||
isSigningOut: boolean;
|
||||
onVerifyDevice?: () => void;
|
||||
onSignOutDevice: () => void;
|
||||
saveDeviceName: (deviceName: string) => Promise<void>;
|
||||
setPushNotifications?: (deviceId: string, enabled: boolean) => Promise<void> | undefined;
|
||||
supportsMSC3881?: boolean | undefined;
|
||||
setPushNotifications?: (deviceId: string, enabled: boolean) => Promise<void>;
|
||||
supportsMSC3881?: boolean;
|
||||
className?: string;
|
||||
isCurrentDevice?: boolean;
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ import SettingsSubsection from "../shared/SettingsSubsection";
|
|||
|
||||
interface IProps {
|
||||
onShowQr: () => void;
|
||||
versions: IServerVersions;
|
||||
versions?: IServerVersions;
|
||||
}
|
||||
|
||||
export default class LoginWithQRSection extends React.Component<IProps> {
|
||||
|
|
|
@ -40,6 +40,7 @@ interface IRecommendedVersion {
|
|||
}
|
||||
|
||||
interface IState {
|
||||
// This is eventually set to the value of room.getRecommendedVersion()
|
||||
upgradeRecommendation?: IRecommendedVersion;
|
||||
oldRoomId?: string;
|
||||
oldEventId?: string;
|
||||
|
@ -52,14 +53,11 @@ export default class AdvancedRoomSettingsTab extends React.Component<IProps, ISt
|
|||
|
||||
const msc3946ProcessDynamicPredecessor = SettingsStore.getValue("feature_dynamic_room_predecessors");
|
||||
|
||||
this.state = {
|
||||
// This is eventually set to the value of room.getRecommendedVersion()
|
||||
upgradeRecommendation: null,
|
||||
};
|
||||
this.state = {};
|
||||
|
||||
// we handle lack of this object gracefully later, so don't worry about it failing here.
|
||||
const room = MatrixClientPeg.get().getRoom(this.props.roomId);
|
||||
room.getRecommendedVersion().then((v) => {
|
||||
room?.getRecommendedVersion().then((v) => {
|
||||
const tombstone = room.currentState.getStateEvents(EventType.RoomTombstone, "");
|
||||
|
||||
const additionalStateChanges: Partial<IState> = {};
|
||||
|
@ -99,11 +97,10 @@ export default class AdvancedRoomSettingsTab extends React.Component<IProps, ISt
|
|||
public render(): React.ReactNode {
|
||||
const client = MatrixClientPeg.get();
|
||||
const room = client.getRoom(this.props.roomId);
|
||||
const isSpace = room.isSpaceRoom();
|
||||
const isSpace = room?.isSpaceRoom();
|
||||
|
||||
let unfederatableSection;
|
||||
const createEvent = room.currentState.getStateEvents(EventType.RoomCreate, "");
|
||||
if (createEvent && createEvent.getContent()["m.federate"] === false) {
|
||||
let unfederatableSection: JSX.Element | undefined;
|
||||
if (room?.currentState.getStateEvents(EventType.RoomCreate, "")?.getContent()["m.federate"] === false) {
|
||||
unfederatableSection = <div>{_t("This room is not accessible by remote Matrix servers")}</div>;
|
||||
}
|
||||
|
||||
|
@ -132,13 +129,13 @@ export default class AdvancedRoomSettingsTab extends React.Component<IProps, ISt
|
|||
);
|
||||
}
|
||||
|
||||
let oldRoomLink;
|
||||
let oldRoomLink: JSX.Element | undefined;
|
||||
if (this.state.oldRoomId) {
|
||||
let copy: string;
|
||||
if (isSpace) {
|
||||
copy = _t("View older version of %(spaceName)s.", { spaceName: room.name });
|
||||
copy = _t("View older version of %(spaceName)s.", { spaceName: room?.name ?? this.state.oldRoomId });
|
||||
} else {
|
||||
copy = _t("View older messages in %(roomName)s.", { roomName: room.name });
|
||||
copy = _t("View older messages in %(roomName)s.", { roomName: room?.name ?? this.state.oldRoomId });
|
||||
}
|
||||
|
||||
oldRoomLink = (
|
||||
|
@ -165,7 +162,7 @@ export default class AdvancedRoomSettingsTab extends React.Component<IProps, ISt
|
|||
<span className="mx_SettingsTab_subheading">{_t("Room version")}</span>
|
||||
<div>
|
||||
<span>{_t("Room version:")}</span>
|
||||
{room.getVersion()}
|
||||
{room?.getVersion()}
|
||||
</div>
|
||||
{oldRoomLink}
|
||||
{roomUpgradeButton}
|
||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import React, { ReactNode } from "react";
|
||||
import { Room } from "matrix-js-sdk/src/models/room";
|
||||
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||
|
||||
|
@ -34,17 +34,16 @@ interface IProps {
|
|||
}
|
||||
|
||||
export default class BridgeSettingsTab extends React.Component<IProps> {
|
||||
private renderBridgeCard(event: MatrixEvent, room: Room): JSX.Element {
|
||||
private renderBridgeCard(event: MatrixEvent, room: Room | null): ReactNode {
|
||||
const content = event.getContent();
|
||||
if (!content || !content.channel || !content.protocol) {
|
||||
return null;
|
||||
}
|
||||
if (!room || !content?.channel || !content.protocol) return null;
|
||||
return <BridgeTile key={event.getId()} room={room} ev={event} />;
|
||||
}
|
||||
|
||||
public static getBridgeStateEvents(roomId: string): MatrixEvent[] {
|
||||
const client = MatrixClientPeg.get();
|
||||
const roomState = client.getRoom(roomId).currentState;
|
||||
const roomState = client.getRoom(roomId)?.currentState;
|
||||
if (!roomState) return [];
|
||||
|
||||
return BRIDGE_EVENT_TYPES.map((typeName) => roomState.getStateEvents(typeName)).flat(1);
|
||||
}
|
||||
|
|
|
@ -61,15 +61,14 @@ export default class GeneralRoomSettingsTab extends React.Component<IProps, ISta
|
|||
const room = client.getRoom(this.props.roomId);
|
||||
|
||||
const canSetAliases = true; // Previously, we arbitrarily only allowed admins to do this
|
||||
const canSetCanonical = room.currentState.mayClientSendStateEvent("m.room.canonical_alias", client);
|
||||
const canonicalAliasEv = room.currentState.getStateEvents("m.room.canonical_alias", "");
|
||||
const canSetCanonical = room?.currentState.mayClientSendStateEvent("m.room.canonical_alias", client);
|
||||
const canonicalAliasEv = room?.currentState.getStateEvents("m.room.canonical_alias", "") ?? undefined;
|
||||
|
||||
const urlPreviewSettings = SettingsStore.getValue(UIFeature.URLPreviews) ? (
|
||||
<UrlPreviewSettings room={room} />
|
||||
) : null;
|
||||
const urlPreviewSettings =
|
||||
room && SettingsStore.getValue(UIFeature.URLPreviews) ? <UrlPreviewSettings room={room} /> : null;
|
||||
|
||||
let leaveSection;
|
||||
if (room.getMyMembership() === "join") {
|
||||
if (room?.getMyMembership() === "join") {
|
||||
leaveSection = (
|
||||
<>
|
||||
<span className="mx_SettingsTab_subheading">{_t("Leave room")}</span>
|
||||
|
|
|
@ -40,7 +40,7 @@ interface IProps {
|
|||
|
||||
interface IState {
|
||||
currentSound: string;
|
||||
uploadedFile: File;
|
||||
uploadedFile: File | null;
|
||||
}
|
||||
|
||||
export default class NotificationsSettingsTab extends React.Component<IProps, IState> {
|
||||
|
@ -71,7 +71,7 @@ export default class NotificationsSettingsTab extends React.Component<IProps, IS
|
|||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
|
||||
this.soundUpload.current.click();
|
||||
this.soundUpload.current?.click();
|
||||
};
|
||||
|
||||
private onSoundUploadChanged = (e: React.ChangeEvent<HTMLInputElement>): void => {
|
||||
|
@ -156,7 +156,7 @@ export default class NotificationsSettingsTab extends React.Component<IProps, IS
|
|||
};
|
||||
|
||||
public render(): React.ReactNode {
|
||||
let currentUploadedFile = null;
|
||||
let currentUploadedFile: JSX.Element | undefined;
|
||||
if (this.state.uploadedFile) {
|
||||
currentUploadedFile = (
|
||||
<div>
|
||||
|
|
|
@ -239,13 +239,13 @@ export default class RolesRoomSettingsTab extends React.Component<IProps> {
|
|||
public render(): React.ReactNode {
|
||||
const client = MatrixClientPeg.get();
|
||||
const room = client.getRoom(this.props.roomId);
|
||||
const isSpaceRoom = room.isSpaceRoom();
|
||||
const isSpaceRoom = room?.isSpaceRoom();
|
||||
|
||||
const plEvent = room.currentState.getStateEvents(EventType.RoomPowerLevels, "");
|
||||
const plEvent = room?.currentState.getStateEvents(EventType.RoomPowerLevels, "");
|
||||
const plContent = plEvent ? plEvent.getContent() || {} : {};
|
||||
const canChangeLevels = room.currentState.mayClientSendStateEvent(EventType.RoomPowerLevels, client);
|
||||
const canChangeLevels = room?.currentState.mayClientSendStateEvent(EventType.RoomPowerLevels, client);
|
||||
|
||||
const plEventsToLabels: Record<EventType | string, string> = {
|
||||
const plEventsToLabels: Record<EventType | string, string | null> = {
|
||||
// These will be translated for us later.
|
||||
[EventType.RoomAvatar]: isSpaceRoom ? _td("Change space avatar") : _td("Change room avatar"),
|
||||
[EventType.RoomName]: isSpaceRoom ? _td("Change space name") : _td("Change room name"),
|
||||
|
@ -322,7 +322,7 @@ export default class RolesRoomSettingsTab extends React.Component<IProps> {
|
|||
powerLevelDescriptors.users_default.defaultValue,
|
||||
);
|
||||
|
||||
let currentUserLevel = userLevels[client.getUserId()];
|
||||
let currentUserLevel = userLevels[client.getUserId()!];
|
||||
if (currentUserLevel === undefined) {
|
||||
currentUserLevel = defaultUserLevel;
|
||||
}
|
||||
|
@ -391,16 +391,16 @@ export default class RolesRoomSettingsTab extends React.Component<IProps> {
|
|||
}
|
||||
}
|
||||
|
||||
const banned = room.getMembersWithMembership("ban");
|
||||
let bannedUsersSection;
|
||||
if (banned.length) {
|
||||
const banned = room?.getMembersWithMembership("ban");
|
||||
let bannedUsersSection: JSX.Element | undefined;
|
||||
if (banned?.length) {
|
||||
const canBanUsers = currentUserLevel >= banLevel;
|
||||
bannedUsersSection = (
|
||||
<SettingsFieldset legend={_t("Banned users")}>
|
||||
<ul>
|
||||
{banned.map((member) => {
|
||||
const banEvent = member.events.member.getContent();
|
||||
const sender = room.getMember(member.events.member.getSender());
|
||||
const banEvent = member.events.member?.getContent();
|
||||
const sender = room?.getMember(member.events.member.getSender());
|
||||
let bannedBy = member.events.member.getSender(); // start by falling back to mxid
|
||||
if (sender) bannedBy = sender.name;
|
||||
return (
|
||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import React, { ReactNode } from "react";
|
||||
import { GuestAccess, HistoryVisibility, JoinRule } from "matrix-js-sdk/src/@types/partials";
|
||||
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||
import { RoomStateEvent } from "matrix-js-sdk/src/models/room-state";
|
||||
|
@ -61,16 +61,16 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
|
|||
public constructor(props: IProps, context: React.ContextType<typeof MatrixClientContext>) {
|
||||
super(props, context);
|
||||
|
||||
const state = context.getRoom(this.props.roomId).currentState;
|
||||
const state = context.getRoom(this.props.roomId)?.currentState;
|
||||
|
||||
this.state = {
|
||||
guestAccess: this.pullContentPropertyFromEvent<GuestAccess>(
|
||||
state.getStateEvents(EventType.RoomGuestAccess, ""),
|
||||
state?.getStateEvents(EventType.RoomGuestAccess, ""),
|
||||
"guest_access",
|
||||
GuestAccess.Forbidden,
|
||||
),
|
||||
history: this.pullContentPropertyFromEvent<HistoryVisibility>(
|
||||
state.getStateEvents(EventType.RoomHistoryVisibility, ""),
|
||||
state?.getStateEvents(EventType.RoomHistoryVisibility, ""),
|
||||
"history_visibility",
|
||||
HistoryVisibility.Shared,
|
||||
),
|
||||
|
@ -85,7 +85,7 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
|
|||
this.hasAliases().then((hasAliases) => this.setState({ hasAliases }));
|
||||
}
|
||||
|
||||
private pullContentPropertyFromEvent<T>(event: MatrixEvent, key: string, defaultValue: T): T {
|
||||
private pullContentPropertyFromEvent<T>(event: MatrixEvent | null | undefined, key: string, defaultValue: T): T {
|
||||
return event?.getContent()[key] || defaultValue;
|
||||
}
|
||||
|
||||
|
@ -117,7 +117,7 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
|
|||
"You'll get none of the benefits of encryption, and you won't be able to turn it " +
|
||||
"off later. Encrypting messages in a public room will make receiving and sending " +
|
||||
"messages slower.",
|
||||
null,
|
||||
undefined,
|
||||
{ b: (sub) => <b>{sub}</b> },
|
||||
)}{" "}
|
||||
</p>
|
||||
|
@ -126,7 +126,7 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
|
|||
{_t(
|
||||
"To avoid these issues, create a <a>new encrypted room</a> for " +
|
||||
"the conversation you plan to have.",
|
||||
null,
|
||||
undefined,
|
||||
{
|
||||
a: (sub) => (
|
||||
<AccessibleButton
|
||||
|
@ -236,7 +236,7 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
|
|||
};
|
||||
|
||||
private updateBlacklistDevicesFlag = (checked: boolean): void => {
|
||||
this.context.getRoom(this.props.roomId).setBlacklistUnverifiedDevices(checked);
|
||||
this.context.getRoom(this.props.roomId)?.setBlacklistUnverifiedDevices(checked);
|
||||
};
|
||||
|
||||
private async hasAliases(): Promise<boolean> {
|
||||
|
@ -250,8 +250,8 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
|
|||
const client = this.context;
|
||||
const room = client.getRoom(this.props.roomId);
|
||||
|
||||
let aliasWarning = null;
|
||||
if (room.getJoinRule() === JoinRule.Public && !this.state.hasAliases) {
|
||||
let aliasWarning: JSX.Element | undefined;
|
||||
if (room?.getJoinRule() === JoinRule.Public && !this.state.hasAliases) {
|
||||
aliasWarning = (
|
||||
<div className="mx_SecurityRoomSettingsTab_warning">
|
||||
<WarningIcon width={15} height={15} />
|
||||
|
@ -297,7 +297,7 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
|
|||
"It will mean anyone can find and join the room, so anyone can read messages. " +
|
||||
"You'll get none of the benefits of encryption. Encrypting messages in a public " +
|
||||
"room will make receiving and sending messages slower.",
|
||||
null,
|
||||
undefined,
|
||||
{ b: (sub) => <b>{sub}</b> },
|
||||
)}{" "}
|
||||
</p>
|
||||
|
@ -306,7 +306,7 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
|
|||
{_t(
|
||||
"To avoid these issues, create a <a>new public room</a> for the conversation " +
|
||||
"you plan to have.",
|
||||
null,
|
||||
undefined,
|
||||
{
|
||||
a: (sub) => (
|
||||
<AccessibleButton
|
||||
|
@ -335,15 +335,15 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
|
|||
return true;
|
||||
};
|
||||
|
||||
private renderHistory(): JSX.Element {
|
||||
private renderHistory(): ReactNode {
|
||||
if (!SettingsStore.getValue(UIFeature.RoomHistorySettings)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const client = this.context;
|
||||
const history = this.state.history;
|
||||
const state = client.getRoom(this.props.roomId).currentState;
|
||||
const canChangeHistory = state.mayClientSendStateEvent(EventType.RoomHistoryVisibility, client);
|
||||
const state = client.getRoom(this.props.roomId)?.currentState;
|
||||
const canChangeHistory = state?.mayClientSendStateEvent(EventType.RoomHistoryVisibility, client);
|
||||
|
||||
const options = [
|
||||
{
|
||||
|
@ -393,8 +393,8 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
|
|||
private renderAdvanced(): JSX.Element {
|
||||
const client = this.context;
|
||||
const guestAccess = this.state.guestAccess;
|
||||
const state = client.getRoom(this.props.roomId).currentState;
|
||||
const canSetGuestAccess = state.mayClientSendStateEvent(EventType.RoomGuestAccess, client);
|
||||
const state = client.getRoom(this.props.roomId)?.currentState;
|
||||
const canSetGuestAccess = state?.mayClientSendStateEvent(EventType.RoomGuestAccess, client);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -418,10 +418,10 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
|
|||
const client = this.context;
|
||||
const room = client.getRoom(this.props.roomId);
|
||||
const isEncrypted = this.state.encrypted;
|
||||
const hasEncryptionPermission = room.currentState.mayClientSendStateEvent(EventType.RoomEncryption, client);
|
||||
const hasEncryptionPermission = room?.currentState.mayClientSendStateEvent(EventType.RoomEncryption, client);
|
||||
const canEnableEncryption = !isEncrypted && hasEncryptionPermission;
|
||||
|
||||
let encryptionSettings = null;
|
||||
let encryptionSettings: JSX.Element | undefined;
|
||||
if (isEncrypted && SettingsStore.isEnabled("blacklistUnverifiedDevices")) {
|
||||
encryptionSettings = (
|
||||
<SettingsFlag
|
||||
|
@ -435,8 +435,8 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
|
|||
|
||||
const historySection = this.renderHistory();
|
||||
|
||||
let advanced;
|
||||
if (room.getJoinRule() === JoinRule.Public) {
|
||||
let advanced: JSX.Element | undefined;
|
||||
if (room?.getJoinRule() === JoinRule.Public) {
|
||||
advanced = (
|
||||
<div className="mx_SettingsTab_section">
|
||||
<AccessibleButton
|
||||
|
|
|
@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React, { ChangeEvent } from "react";
|
||||
import React, { ChangeEvent, ReactNode } from "react";
|
||||
|
||||
import { _t } from "../../../../../languageHandler";
|
||||
import SdkConfig from "../../../../../SdkConfig";
|
||||
|
@ -41,8 +41,8 @@ interface IState {
|
|||
layout: Layout;
|
||||
// User profile data for the message preview
|
||||
userId?: string;
|
||||
displayName: string;
|
||||
avatarUrl: string;
|
||||
displayName?: string;
|
||||
avatarUrl?: string;
|
||||
}
|
||||
|
||||
export default class AppearanceUserSettingsTab extends React.Component<IProps, IState> {
|
||||
|
@ -58,16 +58,13 @@ export default class AppearanceUserSettingsTab extends React.Component<IProps, I
|
|||
systemFont: SettingsStore.getValue("systemFont"),
|
||||
showAdvanced: false,
|
||||
layout: SettingsStore.getValue("layout"),
|
||||
userId: null,
|
||||
displayName: null,
|
||||
avatarUrl: null,
|
||||
};
|
||||
}
|
||||
|
||||
public async componentDidMount(): Promise<void> {
|
||||
// Fetch the current user profile for the message preview
|
||||
const client = MatrixClientPeg.get();
|
||||
const userId = client.getUserId();
|
||||
const userId = client.getUserId()!;
|
||||
const profileInfo = await client.getProfileInfo(userId);
|
||||
if (this.unmounted) return;
|
||||
|
||||
|
@ -86,7 +83,7 @@ export default class AppearanceUserSettingsTab extends React.Component<IProps, I
|
|||
this.setState({ layout: layout });
|
||||
};
|
||||
|
||||
private renderAdvancedSection(): JSX.Element {
|
||||
private renderAdvancedSection(): ReactNode {
|
||||
if (!SettingsStore.getValue(UIFeature.AdvancedSettings)) return null;
|
||||
|
||||
const brand = SdkConfig.get().brand;
|
||||
|
@ -115,7 +112,7 @@ export default class AppearanceUserSettingsTab extends React.Component<IProps, I
|
|||
/>
|
||||
<Field
|
||||
className="mx_AppearanceUserSettingsTab_systemFont"
|
||||
label={SettingsStore.getDisplayName("systemFont")}
|
||||
label={SettingsStore.getDisplayName("systemFont")!}
|
||||
onChange={(value: ChangeEvent<HTMLInputElement>) => {
|
||||
this.setState({
|
||||
systemFont: value.target.value,
|
||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import React, { ReactNode } from "react";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
|
||||
import AccessibleButton from "../../../elements/AccessibleButton";
|
||||
|
@ -37,7 +37,7 @@ interface IProps {
|
|||
}
|
||||
|
||||
interface IState {
|
||||
appVersion: string;
|
||||
appVersion: string | null;
|
||||
canUpdate: boolean;
|
||||
}
|
||||
|
||||
|
@ -53,13 +53,13 @@ export default class HelpUserSettingsTab extends React.Component<IProps, IState>
|
|||
|
||||
public componentDidMount(): void {
|
||||
PlatformPeg.get()
|
||||
.getAppVersion()
|
||||
?.getAppVersion()
|
||||
.then((ver) => this.setState({ appVersion: ver }))
|
||||
.catch((e) => {
|
||||
logger.error("Error getting vector version: ", e);
|
||||
});
|
||||
PlatformPeg.get()
|
||||
.canSelfUpdate()
|
||||
?.canSelfUpdate()
|
||||
.then((v) => this.setState({ canUpdate: v }))
|
||||
.catch((e) => {
|
||||
logger.error("Error getting self updatability: ", e);
|
||||
|
@ -90,7 +90,7 @@ export default class HelpUserSettingsTab extends React.Component<IProps, IState>
|
|||
MatrixClientPeg.get()
|
||||
.store.deleteAllData()
|
||||
.then(() => {
|
||||
PlatformPeg.get().reload();
|
||||
PlatformPeg.get()?.reload();
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -106,11 +106,11 @@ export default class HelpUserSettingsTab extends React.Component<IProps, IState>
|
|||
});
|
||||
};
|
||||
|
||||
private renderLegal(): JSX.Element {
|
||||
private renderLegal(): ReactNode {
|
||||
const tocLinks = SdkConfig.get().terms_and_conditions_links;
|
||||
if (!tocLinks) return null;
|
||||
|
||||
const legalLinks = [];
|
||||
const legalLinks: JSX.Element[] = [];
|
||||
for (const tocEntry of tocLinks) {
|
||||
legalLinks.push(
|
||||
<div key={tocEntry.url}>
|
||||
|
@ -248,7 +248,7 @@ export default class HelpUserSettingsTab extends React.Component<IProps, IState>
|
|||
);
|
||||
}
|
||||
|
||||
let updateButton = null;
|
||||
let updateButton: JSX.Element | undefined;
|
||||
if (this.state.canUpdate) {
|
||||
updateButton = <UpdateCheckButton />;
|
||||
}
|
||||
|
|
|
@ -105,7 +105,7 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
|
|||
this.setState({ busy: true });
|
||||
try {
|
||||
const list = Mjolnir.sharedInstance().getPersonalList();
|
||||
await list.unbanEntity(rule.kind, rule.entity);
|
||||
await list!.unbanEntity(rule.kind, rule.entity);
|
||||
} catch (e) {
|
||||
logger.error(e);
|
||||
|
||||
|
@ -142,7 +142,7 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
|
|||
const renderRules = (rules: ListRule[]): JSX.Element => {
|
||||
if (rules.length === 0) return <i>{_t("None")}</i>;
|
||||
|
||||
const tiles = [];
|
||||
const tiles: JSX.Element[] = [];
|
||||
for (const rule of rules) {
|
||||
tiles.push(
|
||||
<li key={rule.kind + rule.entity}>
|
||||
|
@ -173,7 +173,7 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
|
|||
const rules = list ? [...list.userRules, ...list.serverRules] : [];
|
||||
if (!list || rules.length <= 0) return <i>{_t("You have not ignored anyone.")}</i>;
|
||||
|
||||
const tiles = [];
|
||||
const tiles: JSX.Element[] = [];
|
||||
for (const rule of rules) {
|
||||
tiles.push(
|
||||
<li key={rule.entity} className="mx_MjolnirUserSettingsTab_listItem">
|
||||
|
@ -205,7 +205,7 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
|
|||
});
|
||||
if (!lists || lists.length <= 0) return <i>{_t("You are not subscribed to any lists")}</i>;
|
||||
|
||||
const tiles = [];
|
||||
const tiles: JSX.Element[] = [];
|
||||
for (const list of lists) {
|
||||
const room = MatrixClientPeg.get().getRoom(list.roomId);
|
||||
const name = room ? (
|
||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import React, { ReactNode } from "react";
|
||||
import { sleep } from "matrix-js-sdk/src/utils";
|
||||
import { Room, RoomEvent } from "matrix-js-sdk/src/models/room";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
|
@ -169,7 +169,7 @@ export default class SecurityUserSettingsTab extends React.Component<IProps, ISt
|
|||
return MatrixClientPeg.get()
|
||||
.getRooms()
|
||||
.filter((r) => {
|
||||
return r.hasMembershipState(MatrixClientPeg.get().getUserId(), "invite");
|
||||
return r.hasMembershipState(MatrixClientPeg.get().getUserId()!, "invite");
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -247,7 +247,7 @@ export default class SecurityUserSettingsTab extends React.Component<IProps, ISt
|
|||
);
|
||||
}
|
||||
|
||||
private renderManageInvites(): JSX.Element {
|
||||
private renderManageInvites(): ReactNode {
|
||||
const { invitedRoomIds } = this.state;
|
||||
|
||||
if (invitedRoomIds.size === 0) {
|
||||
|
|
|
@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import React, { ReactNode } from "react";
|
||||
|
||||
import { _t } from "../../../../../languageHandler";
|
||||
import MediaDeviceHandler, { IMediaDevices, MediaDeviceKindEnum } from "../../../../../MediaDeviceHandler";
|
||||
|
@ -28,10 +28,10 @@ import LabelledToggleSwitch from "../../../elements/LabelledToggleSwitch";
|
|||
import { requestMediaPermissions } from "../../../../../utils/media/requestMediaPermissions";
|
||||
|
||||
interface IState {
|
||||
mediaDevices: IMediaDevices;
|
||||
[MediaDeviceKindEnum.AudioOutput]: string;
|
||||
[MediaDeviceKindEnum.AudioInput]: string;
|
||||
[MediaDeviceKindEnum.VideoInput]: string;
|
||||
mediaDevices: IMediaDevices | null;
|
||||
[MediaDeviceKindEnum.AudioOutput]: string | null;
|
||||
[MediaDeviceKindEnum.AudioInput]: string | null;
|
||||
[MediaDeviceKindEnum.VideoInput]: string | null;
|
||||
audioAutoGainControl: boolean;
|
||||
audioEchoCancellation: boolean;
|
||||
audioNoiseSuppression: boolean;
|
||||
|
@ -104,7 +104,7 @@ export default class VoiceUserSettingsTab extends React.Component<{}, IState> {
|
|||
});
|
||||
}
|
||||
|
||||
private renderDropdown(kind: MediaDeviceKindEnum, label: string): JSX.Element {
|
||||
private renderDropdown(kind: MediaDeviceKindEnum, label: string): ReactNode {
|
||||
const devices = this.state.mediaDevices[kind].slice(0);
|
||||
if (devices.length === 0) return null;
|
||||
|
||||
|
@ -121,11 +121,11 @@ export default class VoiceUserSettingsTab extends React.Component<{}, IState> {
|
|||
);
|
||||
}
|
||||
|
||||
public render(): React.ReactNode {
|
||||
let requestButton = null;
|
||||
let speakerDropdown = null;
|
||||
let microphoneDropdown = null;
|
||||
let webcamDropdown = null;
|
||||
public render(): ReactNode {
|
||||
let requestButton: ReactNode | undefined;
|
||||
let speakerDropdown: ReactNode | undefined;
|
||||
let microphoneDropdown: ReactNode | undefined;
|
||||
let webcamDropdown: ReactNode | undefined;
|
||||
if (!this.state.mediaDevices) {
|
||||
requestButton = (
|
||||
<div className="mx_VoiceUserSettingsTab_missingMediaPermissions">
|
||||
|
|
|
@ -46,8 +46,8 @@ const QuickSettingsButton: React.FC<{
|
|||
const { [MetaSpace.Favourites]: favouritesEnabled, [MetaSpace.People]: peopleEnabled } =
|
||||
useSettingValue<Record<MetaSpace, boolean>>("Spaces.enabledMetaSpaces");
|
||||
|
||||
let contextMenu: JSX.Element;
|
||||
if (menuDisplayed) {
|
||||
let contextMenu: JSX.Element | undefined;
|
||||
if (menuDisplayed && handle.current) {
|
||||
contextMenu = (
|
||||
<ContextMenu
|
||||
{...alwaysAboveRightOf(handle.current.getBoundingClientRect(), ChevronFace.None, 16)}
|
||||
|
|
|
@ -38,9 +38,9 @@ const SpaceSettingsGeneralTab: React.FC<IProps> = ({ matrixClient: cli, space, o
|
|||
const [busy, setBusy] = useState(false);
|
||||
const [error, setError] = useState("");
|
||||
|
||||
const userId = cli.getUserId();
|
||||
const userId = cli.getUserId()!;
|
||||
|
||||
const [newAvatar, setNewAvatar] = useState<File>(null); // undefined means to remove avatar
|
||||
const [newAvatar, setNewAvatar] = useState<File | null | undefined>(null); // undefined means to remove avatar
|
||||
const canSetAvatar = space.currentState.maySendStateEvent(EventType.RoomAvatar, userId);
|
||||
const avatarChanged = newAvatar !== null;
|
||||
|
||||
|
@ -48,8 +48,8 @@ const SpaceSettingsGeneralTab: React.FC<IProps> = ({ matrixClient: cli, space, o
|
|||
const canSetName = space.currentState.maySendStateEvent(EventType.RoomName, userId);
|
||||
const nameChanged = name !== space.name;
|
||||
|
||||
const currentTopic = getTopic(space)?.text;
|
||||
const [topic, setTopic] = useState<string>(currentTopic);
|
||||
const currentTopic = getTopic(space)?.text ?? "";
|
||||
const [topic, setTopic] = useState(currentTopic);
|
||||
const canSetTopic = space.currentState.maySendStateEvent(EventType.RoomTopic, userId);
|
||||
const topicChanged = topic !== currentTopic;
|
||||
|
||||
|
@ -104,7 +104,7 @@ const SpaceSettingsGeneralTab: React.FC<IProps> = ({ matrixClient: cli, space, o
|
|||
|
||||
<div className="mx_SettingsTab_section">
|
||||
<SpaceBasicSettings
|
||||
avatarUrl={avatarUrlForRoom(space, 80, 80, "crop")}
|
||||
avatarUrl={avatarUrlForRoom(space, 80, 80, "crop") ?? undefined}
|
||||
avatarDisabled={busy || !canSetAvatar}
|
||||
setAvatar={setNewAvatar}
|
||||
name={name}
|
||||
|
|
|
@ -47,7 +47,7 @@ const SpaceSettingsVisibilityTab: React.FC<IProps> = ({ matrixClient: cli, space
|
|||
false,
|
||||
);
|
||||
|
||||
const userId = cli.getUserId();
|
||||
const userId = cli.getUserId()!;
|
||||
|
||||
const joinRule = useRoomState(space, (state) => state.getJoinRule());
|
||||
const [guestAccessEnabled, setGuestAccessEnabled] = useLocalEcho<boolean>(
|
||||
|
@ -120,7 +120,7 @@ const SpaceSettingsVisibilityTab: React.FC<IProps> = ({ matrixClient: cli, space
|
|||
);
|
||||
}
|
||||
|
||||
let addressesSection;
|
||||
let addressesSection: JSX.Element | undefined;
|
||||
if (space.getJoinRule() === JoinRule.Public) {
|
||||
addressesSection = (
|
||||
<>
|
||||
|
@ -129,7 +129,7 @@ const SpaceSettingsVisibilityTab: React.FC<IProps> = ({ matrixClient: cli, space
|
|||
roomId={space.roomId}
|
||||
canSetCanonicalAlias={canSetCanonical}
|
||||
canSetAliases={true}
|
||||
canonicalAliasEvent={canonicalAliasEv}
|
||||
canonicalAliasEvent={canonicalAliasEv ?? undefined}
|
||||
hidePublishSetting={!serverSupportsExploringSpaces}
|
||||
/>
|
||||
</>
|
||||
|
|
|
@ -83,7 +83,7 @@ export default class InlineTermsAgreement extends React.Component<IProps, IState
|
|||
};
|
||||
|
||||
private renderCheckboxes(): React.ReactNode[] {
|
||||
const rendered = [];
|
||||
const rendered: JSX.Element[] = [];
|
||||
for (let i = 0; i < this.state.policies.length; i++) {
|
||||
const policy = this.state.policies[i];
|
||||
const introText = _t(
|
||||
|
|
|
@ -77,7 +77,7 @@ export default class VerificationRequestToast extends React.PureComponent<IProps
|
|||
const device = await cli.getDevice(request.channel.deviceId);
|
||||
const ip = device.last_seen_ip;
|
||||
this.setState({
|
||||
device: cli.getStoredDevice(cli.getUserId(), request.channel.deviceId),
|
||||
device: cli.getStoredDevice(cli.getUserId()!, request.channel.deviceId),
|
||||
ip,
|
||||
});
|
||||
}
|
||||
|
@ -137,7 +137,7 @@ export default class VerificationRequestToast extends React.PureComponent<IProps
|
|||
request.cancel();
|
||||
},
|
||||
},
|
||||
null,
|
||||
undefined,
|
||||
/* priority = */ false,
|
||||
/* static = */ true,
|
||||
);
|
||||
|
|
|
@ -39,7 +39,7 @@ export function UserOnboardingButton({ selected, minimized }: Props): JSX.Elemen
|
|||
const visible = useSettingValue<boolean>("FTUE.userOnboardingButton");
|
||||
|
||||
if (!visible || minimized || !showUserOnboardingPage(useCase)) {
|
||||
return null;
|
||||
return <></>;
|
||||
}
|
||||
|
||||
return <UserOnboardingButtonInternal selected={selected} minimized={minimized} />;
|
||||
|
|
|
@ -26,7 +26,7 @@ import { shouldShowFeedback } from "../../../utils/Feedback";
|
|||
|
||||
export function UserOnboardingFeedback(): JSX.Element {
|
||||
if (!shouldShowFeedback()) {
|
||||
return null;
|
||||
return <></>;
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
|
@ -57,7 +57,7 @@ export function UserOnboardingTask({ task, completed = false }: Props): JSX.Elem
|
|||
kind="primary_outline"
|
||||
href={task.action.href}
|
||||
target="_blank"
|
||||
onClick={task.action.onClick}
|
||||
onClick={task.action.onClick ?? null}
|
||||
>
|
||||
{task.action.label}
|
||||
</AccessibleButton>
|
||||
|
|
|
@ -150,7 +150,7 @@ export const Lobby: FC<LobbyProps> = ({ room, joinCallButtonDisabledTooltip, con
|
|||
}, [videoMuted, setVideoMuted]);
|
||||
|
||||
const [videoStream, audioInputs, videoInputs] = useAsyncMemo(
|
||||
async (): Promise<[MediaStream, MediaDeviceInfo[], MediaDeviceInfo[]]> => {
|
||||
async (): Promise<[MediaStream | null, MediaDeviceInfo[], MediaDeviceInfo[]]> => {
|
||||
let devices = await MediaDeviceHandler.getDevices();
|
||||
|
||||
// We get the preview stream before requesting devices: this is because
|
||||
|
@ -335,7 +335,7 @@ const StartCallView: FC<StartCallViewProps> = ({ room, resizing, call, setStarti
|
|||
<AppTile
|
||||
app={call.widget}
|
||||
room={room}
|
||||
userId={cli.credentials.userId}
|
||||
userId={cli.credentials.userId!}
|
||||
creatorUserId={call.widget.creatorUserId}
|
||||
waitForIframeLoad={call.widget.waitForIframeLoad}
|
||||
showMenubar={false}
|
||||
|
@ -402,7 +402,7 @@ const JoinCallView: FC<JoinCallViewProps> = ({ room, resizing, call }) => {
|
|||
<AppTile
|
||||
app={call.widget}
|
||||
room={room}
|
||||
userId={cli.credentials.userId}
|
||||
userId={cli.credentials.userId!}
|
||||
creatorUserId={call.widget.creatorUserId}
|
||||
waitForIframeLoad={call.widget.waitForIframeLoad}
|
||||
showMenubar={false}
|
||||
|
|
|
@ -180,7 +180,7 @@ export default class LegacyCallView extends React.Component<IProps, IState> {
|
|||
}
|
||||
};
|
||||
|
||||
private updateCallListeners(oldCall: MatrixCall, newCall: MatrixCall): void {
|
||||
private updateCallListeners(oldCall: MatrixCall, newCall: MatrixCall | null): void {
|
||||
if (oldCall === newCall) return;
|
||||
|
||||
if (oldCall) {
|
||||
|
@ -430,7 +430,7 @@ export default class LegacyCallView extends React.Component<IProps, IState> {
|
|||
const { pipMode, call, onResize } = this.props;
|
||||
const { isLocalOnHold, isRemoteOnHold, sidebarShown, primaryFeed, secondaryFeed, sidebarFeeds } = this.state;
|
||||
|
||||
const callRoom = MatrixClientPeg.get().getRoom(call.roomId);
|
||||
const callRoom = MatrixClientPeg.get().getRoom(call.roomId) ?? undefined;
|
||||
const avatarSize = pipMode ? 76 : 160;
|
||||
const transfereeCall = LegacyCallHandler.instance.getTransfereeForCallId(call.callId);
|
||||
const isOnHold = isLocalOnHold || isRemoteOnHold;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue