Make more code conform to strict null checks (#10219
* Make more code conform to strict null checks * Fix types * Fix tests * Fix remaining test assertions * Iterate PR
This commit is contained in:
parent
4c79ecf141
commit
76b82b4b2b
130 changed files with 603 additions and 603 deletions
|
@ -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 { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||
import { Room } from "matrix-js-sdk/src/models/room";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
|
@ -79,13 +79,13 @@ export default class BridgeTile extends React.PureComponent<IProps> {
|
|||
`Bridge info event ${this.props.ev.getId()} does not provide a 'bridgebot' key which` +
|
||||
"is deprecated behaviour. Using sender for now.",
|
||||
);
|
||||
content.bridgebot = this.props.ev.getSender();
|
||||
content.bridgebot = this.props.ev.getSender()!;
|
||||
}
|
||||
const { channel, network, protocol } = content;
|
||||
const protocolName = protocol.displayname || protocol.id;
|
||||
const channelName = channel.displayname || channel.id;
|
||||
|
||||
let creator = null;
|
||||
let creator: JSX.Element | undefined;
|
||||
if (content.creator) {
|
||||
creator = (
|
||||
<li>
|
||||
|
@ -129,7 +129,7 @@ export default class BridgeTile extends React.PureComponent<IProps> {
|
|||
let networkIcon;
|
||||
|
||||
if (protocol.avatar_url) {
|
||||
const avatarUrl = mediaFromMxc(protocol.avatar_url).getSquareThumbnailHttp(64);
|
||||
const avatarUrl = mediaFromMxc(protocol.avatar_url).getSquareThumbnailHttp(64) ?? undefined;
|
||||
|
||||
networkIcon = (
|
||||
<BaseAvatar
|
||||
|
@ -145,7 +145,7 @@ export default class BridgeTile extends React.PureComponent<IProps> {
|
|||
} else {
|
||||
networkIcon = <div className="mx_RoomSettingsDialog_noProtocolIcon" />;
|
||||
}
|
||||
let networkItem = null;
|
||||
let networkItem: ReactNode | undefined;
|
||||
if (network) {
|
||||
const networkName = network.displayname || network.id;
|
||||
let networkLink = <span>{networkName}</span>;
|
||||
|
|
|
@ -24,8 +24,8 @@ export default class ChangeDisplayName extends React.Component {
|
|||
private getDisplayName = async (): Promise<string> => {
|
||||
const cli = MatrixClientPeg.get();
|
||||
try {
|
||||
const res = await cli.getProfileInfo(cli.getUserId());
|
||||
return res.displayname;
|
||||
const res = await cli.getProfileInfo(cli.getUserId()!);
|
||||
return res.displayname ?? "";
|
||||
} catch (e) {
|
||||
throw new Error("Failed to fetch display name");
|
||||
}
|
||||
|
|
|
@ -42,12 +42,12 @@ enum Phase {
|
|||
}
|
||||
|
||||
interface IProps {
|
||||
onFinished?: (outcome: {
|
||||
onFinished: (outcome: {
|
||||
didSetEmail?: boolean;
|
||||
/** Was one or more other devices logged out whilst changing the password */
|
||||
didLogoutOutOtherDevices: boolean;
|
||||
}) => void;
|
||||
onError?: (error: { error: string }) => void;
|
||||
onError: (error: { error: string }) => void;
|
||||
rowClassName?: string;
|
||||
buttonClassName?: string;
|
||||
buttonKind?: string;
|
||||
|
@ -68,9 +68,9 @@ interface IState {
|
|||
}
|
||||
|
||||
export default class ChangePassword extends React.Component<IProps, IState> {
|
||||
private [FIELD_OLD_PASSWORD]: Field;
|
||||
private [FIELD_NEW_PASSWORD]: Field;
|
||||
private [FIELD_NEW_PASSWORD_CONFIRM]: Field;
|
||||
private [FIELD_OLD_PASSWORD]: Field | null;
|
||||
private [FIELD_NEW_PASSWORD]: Field | null;
|
||||
private [FIELD_NEW_PASSWORD_CONFIRM]: Field | null;
|
||||
|
||||
public static defaultProps: Partial<IProps> = {
|
||||
onFinished() {},
|
||||
|
@ -154,7 +154,7 @@ export default class ChangePassword extends React.Component<IProps, IState> {
|
|||
},
|
||||
// TODO: Remove `user` once servers support proper UIA
|
||||
// See https://github.com/matrix-org/synapse/issues/5665
|
||||
user: cli.credentials.userId,
|
||||
user: cli.credentials.userId ?? undefined,
|
||||
password: oldPassword,
|
||||
};
|
||||
|
||||
|
@ -195,7 +195,7 @@ export default class ChangePassword extends React.Component<IProps, IState> {
|
|||
});
|
||||
}
|
||||
|
||||
private checkPassword(oldPass: string, newPass: string, confirmPass: string): { error: string } {
|
||||
private checkPassword(oldPass: string, newPass: string, confirmPass: string): { error: string } | undefined {
|
||||
if (newPass !== confirmPass) {
|
||||
return {
|
||||
error: _t("New passwords don't match"),
|
||||
|
@ -226,7 +226,7 @@ export default class ChangePassword extends React.Component<IProps, IState> {
|
|||
);
|
||||
};
|
||||
|
||||
private markFieldValid(fieldID: FieldType, valid: boolean): void {
|
||||
private markFieldValid(fieldID: FieldType, valid?: boolean): void {
|
||||
const { fieldValid } = this.state;
|
||||
fieldValid[fieldID] = valid;
|
||||
this.setState({
|
||||
|
@ -367,7 +367,7 @@ export default class ChangePassword extends React.Component<IProps, IState> {
|
|||
return Object.values(this.state.fieldValid).every(Boolean);
|
||||
}
|
||||
|
||||
private findFirstInvalidField(fieldIDs: FieldType[]): Field {
|
||||
private findFirstInvalidField(fieldIDs: FieldType[]): Field | null {
|
||||
for (const fieldID of fieldIDs) {
|
||||
if (!this.state.fieldValid[fieldID] && this[fieldID]) {
|
||||
return this[fieldID];
|
||||
|
|
|
@ -75,7 +75,7 @@ export default class CrossSigningPanel extends React.PureComponent<{}, IState> {
|
|||
|
||||
private onBootstrapClick = (): void => {
|
||||
if (this.state.crossSigningPrivateKeysInStorage) {
|
||||
Modal.createDialog(SetupEncryptionDialog, {}, null, /* priority = */ false, /* static = */ true);
|
||||
Modal.createDialog(SetupEncryptionDialog, {}, undefined, /* priority = */ false, /* static = */ true);
|
||||
} else {
|
||||
// Trigger the flow to set up secure backup, which is what this will do when in
|
||||
// the appropriate state.
|
||||
|
@ -90,8 +90,8 @@ export default class CrossSigningPanel extends React.PureComponent<{}, IState> {
|
|||
private async getUpdatedStatus(): Promise<void> {
|
||||
const cli = MatrixClientPeg.get();
|
||||
const pkCache = cli.getCrossSigningCacheCallbacks();
|
||||
const crossSigning = cli.crypto.crossSigningInfo;
|
||||
const secretStorage = cli.crypto.secretStorage;
|
||||
const crossSigning = cli.crypto!.crossSigningInfo;
|
||||
const secretStorage = cli.crypto!.secretStorage;
|
||||
const crossSigningPublicKeysOnDevice = Boolean(crossSigning.getId());
|
||||
const crossSigningPrivateKeysInStorage = Boolean(await crossSigning.isStoredInSecretStorage(secretStorage));
|
||||
const masterPrivateKeyCached = !!(pkCache && (await pkCache.getCrossSigningKeyCache("master")));
|
||||
|
@ -209,7 +209,7 @@ export default class CrossSigningPanel extends React.PureComponent<{}, IState> {
|
|||
selfSigningPrivateKeyCached &&
|
||||
userSigningPrivateKeyCached;
|
||||
|
||||
const actions = [];
|
||||
const actions: JSX.Element[] = [];
|
||||
|
||||
// TODO: determine how better to expose this to users in addition to prompts at login/toast
|
||||
if (!keysExistEverywhere && homeserverSupportsCrossSigning) {
|
||||
|
|
|
@ -64,7 +64,7 @@ export default class DevicesPanel extends React.Component<IProps, IState> {
|
|||
}
|
||||
|
||||
private onDevicesUpdated = (users: string[]): void => {
|
||||
if (!users.includes(this.context.getUserId())) return;
|
||||
if (!users.includes(this.context.getUserId()!)) return;
|
||||
this.loadDevices();
|
||||
};
|
||||
|
||||
|
@ -252,9 +252,9 @@ export default class DevicesPanel extends React.Component<IProps, IState> {
|
|||
const otherDevices = devices.filter((device) => device.device_id !== myDeviceId);
|
||||
otherDevices.sort(this.deviceCompare);
|
||||
|
||||
const verifiedDevices = [];
|
||||
const unverifiedDevices = [];
|
||||
const nonCryptoDevices = [];
|
||||
const verifiedDevices: IMyDevice[] = [];
|
||||
const unverifiedDevices: IMyDevice[] = [];
|
||||
const nonCryptoDevices: IMyDevice[] = [];
|
||||
for (const device of otherDevices) {
|
||||
const verified = this.isDeviceVerified(device);
|
||||
if (verified === true) {
|
||||
|
@ -271,7 +271,7 @@ export default class DevicesPanel extends React.Component<IProps, IState> {
|
|||
return <React.Fragment />;
|
||||
}
|
||||
|
||||
let selectButton: JSX.Element;
|
||||
let selectButton: JSX.Element | undefined;
|
||||
if (deviceList.length > 1) {
|
||||
const anySelected = deviceList.some((device) => this.state.selectedDevices.includes(device.device_id));
|
||||
const buttonAction = anySelected
|
||||
|
|
|
@ -103,7 +103,7 @@ export default class DevicesPanelEntry extends React.Component<IProps, IState> {
|
|||
});
|
||||
} else {
|
||||
const cli = MatrixClientPeg.get();
|
||||
const userId = cli.getUserId();
|
||||
const userId = cli.getUserId()!;
|
||||
const verificationRequestPromise = cli.requestVerification(userId, [this.props.device.device_id]);
|
||||
Modal.createDialog(VerificationRequestDialog, {
|
||||
verificationRequestPromise,
|
||||
|
@ -119,7 +119,7 @@ export default class DevicesPanelEntry extends React.Component<IProps, IState> {
|
|||
|
||||
public render(): React.ReactNode {
|
||||
let iconClass = "";
|
||||
let verifyButton: JSX.Element;
|
||||
let verifyButton: JSX.Element | undefined;
|
||||
if (this.props.verified !== null) {
|
||||
iconClass = this.props.verified ? "mx_E2EIcon_verified" : "mx_E2EIcon_warning";
|
||||
if (!this.props.verified && this.props.canBeVerified) {
|
||||
|
@ -131,7 +131,7 @@ export default class DevicesPanelEntry extends React.Component<IProps, IState> {
|
|||
}
|
||||
}
|
||||
|
||||
let signOutButton: JSX.Element;
|
||||
let signOutButton: JSX.Element | undefined;
|
||||
if (this.props.isOwnDevice) {
|
||||
signOutButton = (
|
||||
<AccessibleButton kind="danger_outline" onClick={this.onOwnDeviceSignOut}>
|
||||
|
|
|
@ -26,6 +26,7 @@ import EventIndexPeg from "../../../indexing/EventIndexPeg";
|
|||
import { SettingLevel } from "../../../settings/SettingLevel";
|
||||
import SeshatResetDialog from "../dialogs/SeshatResetDialog";
|
||||
import InlineSpinner from "../elements/InlineSpinner";
|
||||
import { IIndexStats } from "../../../indexing/BaseEventIndexManager";
|
||||
|
||||
interface IState {
|
||||
enabling: boolean;
|
||||
|
@ -48,10 +49,10 @@ export default class EventIndexPanel extends React.Component<{}, IState> {
|
|||
|
||||
public updateCurrentRoom = async (): Promise<void> => {
|
||||
const eventIndex = EventIndexPeg.get();
|
||||
let stats;
|
||||
let stats: IIndexStats | undefined;
|
||||
|
||||
try {
|
||||
stats = await eventIndex.getStats();
|
||||
stats = await eventIndex?.getStats();
|
||||
} catch {
|
||||
// This call may fail if sporadically, not a huge issue as we will
|
||||
// try later again and probably succeed.
|
||||
|
@ -126,8 +127,8 @@ export default class EventIndexPanel extends React.Component<{}, IState> {
|
|||
});
|
||||
|
||||
await EventIndexPeg.initEventIndex();
|
||||
await EventIndexPeg.get().addInitialCheckpoints();
|
||||
EventIndexPeg.get().startCrawler();
|
||||
await EventIndexPeg.get()?.addInitialCheckpoints();
|
||||
EventIndexPeg.get()?.startCrawler();
|
||||
await SettingsStore.setValue("enableEventIndexing", null, SettingLevel.DEVICE, true);
|
||||
await this.updateState();
|
||||
};
|
||||
|
@ -146,7 +147,7 @@ export default class EventIndexPanel extends React.Component<{}, IState> {
|
|||
};
|
||||
|
||||
public render(): React.ReactNode {
|
||||
let eventIndexingSettings = null;
|
||||
let eventIndexingSettings: JSX.Element | undefined;
|
||||
const brand = SdkConfig.get().brand;
|
||||
|
||||
if (EventIndexPeg.get() !== null) {
|
||||
|
|
|
@ -39,8 +39,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 FontScalingPanel extends React.Component<IProps, IState> {
|
||||
|
@ -55,16 +55,13 @@ export default class FontScalingPanel extends React.Component<IProps, IState> {
|
|||
fontSize: (SettingsStore.getValue("baseFontSize", null) + FontWatcher.SIZE_DIFF).toString(),
|
||||
useCustomFontSize: SettingsStore.getValue("useCustomFontSize"),
|
||||
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;
|
||||
|
||||
|
|
|
@ -74,14 +74,14 @@ const JoinRuleSettings: React.FC<IProps> = ({
|
|||
? content.allow?.filter((o) => o.type === RestrictedAllowType.RoomMembership).map((o) => o.room_id)
|
||||
: undefined;
|
||||
|
||||
const editRestrictedRoomIds = async (): Promise<string[] | undefined> => {
|
||||
const editRestrictedRoomIds = async (): Promise<string[]> => {
|
||||
let selected = restrictedAllowRoomIds;
|
||||
if (!selected?.length && SpaceStore.instance.activeSpaceRoom) {
|
||||
selected = [SpaceStore.instance.activeSpaceRoom.roomId];
|
||||
}
|
||||
|
||||
const matrixClient = MatrixClientPeg.get();
|
||||
const { finished } = Modal.createDialog(
|
||||
const { finished } = Modal.createDialog<[string[]]>(
|
||||
ManageRestrictedJoinRuleDialog,
|
||||
{
|
||||
matrixClient,
|
||||
|
@ -127,7 +127,7 @@ const JoinRuleSettings: React.FC<IProps> = ({
|
|||
const shownSpaces = restrictedAllowRoomIds
|
||||
.map((roomId) => cli.getRoom(roomId))
|
||||
.filter((room) => room?.isSpaceRoom())
|
||||
.slice(0, 4);
|
||||
.slice(0, 4) as Room[];
|
||||
|
||||
let moreText;
|
||||
if (shownSpaces.length < restrictedAllowRoomIds.length) {
|
||||
|
@ -234,7 +234,7 @@ const JoinRuleSettings: React.FC<IProps> = ({
|
|||
const onChange = async (joinRule: JoinRule): Promise<void> => {
|
||||
const beforeJoinRule = content.join_rule;
|
||||
|
||||
let restrictedAllowRoomIds: string[];
|
||||
let restrictedAllowRoomIds: string[] | undefined;
|
||||
if (joinRule === JoinRule.Restricted) {
|
||||
if (beforeJoinRule === JoinRule.Restricted || roomSupportsRestricted) {
|
||||
// Have the user pick which spaces to allow joins from
|
||||
|
@ -244,8 +244,8 @@ const JoinRuleSettings: React.FC<IProps> = ({
|
|||
// Block this action on a room upgrade otherwise it'd make their room unjoinable
|
||||
const targetVersion = preferredRestrictionVersion;
|
||||
|
||||
let warning: JSX.Element;
|
||||
const userId = cli.getUserId();
|
||||
let warning: JSX.Element | undefined;
|
||||
const userId = cli.getUserId()!;
|
||||
const unableToUpdateSomeParents = Array.from(SpaceStore.instance.getKnownParents(room.roomId)).some(
|
||||
(roomId) => !cli.getRoom(roomId)?.currentState.maySendStateEvent(EventType.SpaceChild, userId),
|
||||
);
|
||||
|
@ -332,7 +332,7 @@ const JoinRuleSettings: React.FC<IProps> = ({
|
|||
}
|
||||
|
||||
// when setting to 0 allowed rooms/spaces set to invite only instead as per the note
|
||||
if (!restrictedAllowRoomIds.length) {
|
||||
if (!restrictedAllowRoomIds?.length) {
|
||||
joinRule = JoinRule.Invite;
|
||||
}
|
||||
}
|
||||
|
@ -346,7 +346,7 @@ const JoinRuleSettings: React.FC<IProps> = ({
|
|||
|
||||
// pre-set the accepted spaces with the currently viewed one as per the microcopy
|
||||
if (joinRule === JoinRule.Restricted) {
|
||||
newContent.allow = restrictedAllowRoomIds.map((roomId) => ({
|
||||
newContent.allow = restrictedAllowRoomIds?.map((roomId) => ({
|
||||
type: RestrictedAllowType.RoomMembership,
|
||||
room_id: roomId,
|
||||
}));
|
||||
|
|
|
@ -328,7 +328,7 @@ export default class Notifications extends React.PureComponent<IProps, IState> {
|
|||
this.setState({ phase: Phase.Persisting });
|
||||
|
||||
try {
|
||||
const masterRule = this.state.masterPushRule;
|
||||
const masterRule = this.state.masterPushRule!;
|
||||
await MatrixClientPeg.get().setPushRuleEnabled("global", masterRule.kind, masterRule.rule_id, !checked);
|
||||
await this.refreshFromServer();
|
||||
} catch (e) {
|
||||
|
@ -396,8 +396,8 @@ export default class Notifications extends React.PureComponent<IProps, IState> {
|
|||
if (rule.ruleId === KEYWORD_RULE_ID) {
|
||||
// Update all the keywords
|
||||
for (const rule of this.state.vectorKeywordRuleInfo.rules) {
|
||||
let enabled: boolean;
|
||||
let actions: PushRuleAction[];
|
||||
let enabled: boolean | undefined;
|
||||
let actions: PushRuleAction[] | undefined;
|
||||
if (checkedState === VectorState.On) {
|
||||
if (rule.actions.length !== 1) {
|
||||
// XXX: Magic number
|
||||
|
|
|
@ -33,14 +33,14 @@ import { accessSecretStorage } from "../../../SecurityManager";
|
|||
|
||||
interface IState {
|
||||
loading: boolean;
|
||||
error: null;
|
||||
backupKeyStored: boolean;
|
||||
backupKeyCached: boolean;
|
||||
backupKeyWellFormed: boolean;
|
||||
secretStorageKeyInAccount: boolean;
|
||||
secretStorageReady: boolean;
|
||||
backupInfo: IKeyBackupInfo;
|
||||
backupSigStatus: TrustInfo;
|
||||
error: Error | null;
|
||||
backupKeyStored: boolean | null;
|
||||
backupKeyCached: boolean | null;
|
||||
backupKeyWellFormed: boolean | null;
|
||||
secretStorageKeyInAccount: boolean | null;
|
||||
secretStorageReady: boolean | null;
|
||||
backupInfo: IKeyBackupInfo | null;
|
||||
backupSigStatus: TrustInfo | null;
|
||||
sessionsRemaining: number;
|
||||
}
|
||||
|
||||
|
@ -144,10 +144,10 @@ export default class SecureBackupPanel extends React.PureComponent<{}, IState> {
|
|||
|
||||
private async getUpdatedDiagnostics(): Promise<void> {
|
||||
const cli = MatrixClientPeg.get();
|
||||
const secretStorage = cli.crypto.secretStorage;
|
||||
const secretStorage = cli.crypto!.secretStorage;
|
||||
|
||||
const backupKeyStored = !!(await cli.isKeyBackupKeyStored());
|
||||
const backupKeyFromCache = await cli.crypto.getSessionBackupPrivateKey();
|
||||
const backupKeyFromCache = await cli.crypto!.getSessionBackupPrivateKey();
|
||||
const backupKeyCached = !!backupKeyFromCache;
|
||||
const backupKeyWellFormed = backupKeyFromCache instanceof Uint8Array;
|
||||
const secretStorageKeyInAccount = await secretStorage.hasKey();
|
||||
|
@ -173,7 +173,7 @@ export default class SecureBackupPanel extends React.PureComponent<{}, IState> {
|
|||
this.loadBackupStatus();
|
||||
},
|
||||
},
|
||||
null,
|
||||
undefined,
|
||||
/* priority = */ false,
|
||||
/* static = */ true,
|
||||
);
|
||||
|
@ -200,7 +200,7 @@ export default class SecureBackupPanel extends React.PureComponent<{}, IState> {
|
|||
};
|
||||
|
||||
private restoreBackup = async (): Promise<void> => {
|
||||
Modal.createDialog(RestoreKeyBackupDialog, null, null, /* priority = */ false, /* static = */ true);
|
||||
Modal.createDialog(RestoreKeyBackupDialog, undefined, undefined, /* priority = */ false, /* static = */ true);
|
||||
};
|
||||
|
||||
private resetSecretStorage = async (): Promise<void> => {
|
||||
|
@ -233,7 +233,7 @@ export default class SecureBackupPanel extends React.PureComponent<{}, IState> {
|
|||
let statusDescription;
|
||||
let extraDetailsTableRows;
|
||||
let extraDetails;
|
||||
const actions = [];
|
||||
const actions: JSX.Element[] = [];
|
||||
if (error) {
|
||||
statusDescription = <div className="error">{_t("Unable to load key backup status")}</div>;
|
||||
} else if (loading) {
|
||||
|
|
|
@ -97,7 +97,6 @@ export default class SetIdServer extends React.Component<IProps, IState> {
|
|||
defaultIdServer,
|
||||
currentClientIdServer: MatrixClientPeg.get().getIdentityServerUrl(),
|
||||
idServer: "",
|
||||
error: null,
|
||||
busy: false,
|
||||
disconnectBusy: false,
|
||||
checking: false,
|
||||
|
|
|
@ -133,7 +133,7 @@ interface IProps {
|
|||
|
||||
interface IState {
|
||||
verifying: boolean;
|
||||
addTask: AddThreepid;
|
||||
addTask: AddThreepid | null;
|
||||
continueDisabled: boolean;
|
||||
newEmailAddress: string;
|
||||
}
|
||||
|
@ -201,7 +201,7 @@ export default class EmailAddresses extends React.Component<IProps, IState> {
|
|||
|
||||
this.setState({ continueDisabled: true });
|
||||
this.state.addTask
|
||||
.checkEmailLinkClicked()
|
||||
?.checkEmailLinkClicked()
|
||||
.then(([finished]) => {
|
||||
let newEmailAddress = this.state.newEmailAddress;
|
||||
if (finished) {
|
||||
|
|
|
@ -33,11 +33,11 @@ interface Props {
|
|||
device?: ExtendedDevice;
|
||||
isLoading: boolean;
|
||||
isSigningOut: boolean;
|
||||
localNotificationSettings?: LocalNotificationSettings | undefined;
|
||||
localNotificationSettings?: LocalNotificationSettings;
|
||||
// number of other sessions the user has
|
||||
// excludes current session
|
||||
otherSessionsCount: number;
|
||||
setPushNotifications?: (deviceId: string, enabled: boolean) => Promise<void> | undefined;
|
||||
setPushNotifications: (deviceId: string, enabled: boolean) => Promise<void>;
|
||||
onVerifyCurrentDevice: () => void;
|
||||
onSignOutCurrentDevice: () => void;
|
||||
signOutAllOtherSessions?: () => void;
|
||||
|
|
|
@ -32,7 +32,7 @@ const makeDeleteRequest =
|
|||
export const deleteDevicesWithInteractiveAuth = async (
|
||||
matrixClient: MatrixClient,
|
||||
deviceIds: string[],
|
||||
onFinished?: InteractiveAuthCallback,
|
||||
onFinished: InteractiveAuthCallback,
|
||||
): Promise<void> => {
|
||||
if (!deviceIds.length) {
|
||||
return;
|
||||
|
|
|
@ -48,9 +48,9 @@ interface IEmailAddressProps {
|
|||
|
||||
interface IEmailAddressState {
|
||||
verifying: boolean;
|
||||
addTask: any; // FIXME: When AddThreepid is TSfied
|
||||
addTask: AddThreepid | null;
|
||||
continueDisabled: boolean;
|
||||
bound: boolean;
|
||||
bound?: boolean;
|
||||
}
|
||||
|
||||
export class EmailAddress extends React.Component<IEmailAddressProps, IEmailAddressState> {
|
||||
|
@ -172,7 +172,7 @@ export class EmailAddress extends React.Component<IEmailAddressProps, IEmailAddr
|
|||
|
||||
this.setState({ continueDisabled: true });
|
||||
try {
|
||||
await this.state.addTask.checkEmailLinkClicked();
|
||||
await this.state.addTask?.checkEmailLinkClicked();
|
||||
this.setState({
|
||||
addTask: null,
|
||||
continueDisabled: false,
|
||||
|
|
|
@ -41,10 +41,10 @@ interface IPhoneNumberProps {
|
|||
interface IPhoneNumberState {
|
||||
verifying: boolean;
|
||||
verificationCode: string;
|
||||
addTask: any; // FIXME: When AddThreepid is TSfied
|
||||
addTask: AddThreepid | null;
|
||||
continueDisabled: boolean;
|
||||
bound: boolean;
|
||||
verifyError: string;
|
||||
bound?: boolean;
|
||||
verifyError: string | null;
|
||||
}
|
||||
|
||||
export class PhoneNumber extends React.Component<IPhoneNumberProps, IPhoneNumberState> {
|
||||
|
@ -89,6 +89,7 @@ export class PhoneNumber extends React.Component<IPhoneNumberProps, IPhoneNumber
|
|||
// a leading plus sign to a number in E.164 format (which the 3PID
|
||||
// address is), but this goes against the spec.
|
||||
// See https://github.com/matrix-org/matrix-doc/issues/2222
|
||||
// @ts-ignore
|
||||
await task.bindMsisdn(null, `+${address}`);
|
||||
this.setState({
|
||||
continueDisabled: false,
|
||||
|
@ -128,8 +129,10 @@ export class PhoneNumber extends React.Component<IPhoneNumberProps, IPhoneNumber
|
|||
// address is), but this goes against the spec.
|
||||
// See https://github.com/matrix-org/matrix-doc/issues/2222
|
||||
if (bind) {
|
||||
// @ts-ignore
|
||||
await task.bindMsisdn(null, `+${address}`);
|
||||
} else {
|
||||
// @ts-ignore
|
||||
await task.addMsisdn(null, `+${address}`);
|
||||
}
|
||||
this.setState({
|
||||
|
@ -183,7 +186,7 @@ export class PhoneNumber extends React.Component<IPhoneNumberProps, IPhoneNumber
|
|||
this.setState({ continueDisabled: true });
|
||||
const token = this.state.verificationCode;
|
||||
try {
|
||||
await this.state.addTask.haveMsisdnToken(token);
|
||||
await this.state.addTask?.haveMsisdnToken(token);
|
||||
this.setState({
|
||||
addTask: null,
|
||||
continueDisabled: false,
|
||||
|
|
|
@ -16,7 +16,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 { SERVICE_TYPES } from "matrix-js-sdk/src/service-types";
|
||||
import { IThreepid } from "matrix-js-sdk/src/@types/threepids";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
|
@ -64,20 +64,20 @@ interface IState {
|
|||
spellCheckEnabled: boolean;
|
||||
spellCheckLanguages: string[];
|
||||
haveIdServer: boolean;
|
||||
serverSupportsSeparateAddAndBind: boolean;
|
||||
serverSupportsSeparateAddAndBind?: boolean;
|
||||
idServerHasUnsignedTerms: boolean;
|
||||
requiredPolicyInfo: {
|
||||
// This object is passed along to a component for handling
|
||||
hasTerms: boolean;
|
||||
policiesAndServices: ServicePolicyPair[]; // From the startTermsFlow callback
|
||||
agreedUrls: string[]; // From the startTermsFlow callback
|
||||
resolve: (values: string[]) => void; // Promise resolve function for startTermsFlow callback
|
||||
policiesAndServices: ServicePolicyPair[] | null; // From the startTermsFlow callback
|
||||
agreedUrls: string[] | null; // From the startTermsFlow callback
|
||||
resolve: ((values: string[]) => void) | null; // Promise resolve function for startTermsFlow callback
|
||||
};
|
||||
emails: IThreepid[];
|
||||
msisdns: IThreepid[];
|
||||
loading3pids: boolean; // whether or not the emails and msisdns have been loaded
|
||||
canChangePassword: boolean;
|
||||
idServerName: string;
|
||||
idServerName?: string;
|
||||
externalAccountManagementUrl?: string;
|
||||
}
|
||||
|
||||
|
@ -92,7 +92,6 @@ export default class GeneralUserSettingsTab extends React.Component<IProps, ISta
|
|||
spellCheckEnabled: false,
|
||||
spellCheckLanguages: [],
|
||||
haveIdServer: Boolean(MatrixClientPeg.get().getIdentityServerUrl()),
|
||||
serverSupportsSeparateAddAndBind: null,
|
||||
idServerHasUnsignedTerms: false,
|
||||
requiredPolicyInfo: {
|
||||
// This object is passed along to a component for handling
|
||||
|
@ -105,8 +104,6 @@ export default class GeneralUserSettingsTab extends React.Component<IProps, ISta
|
|||
msisdns: [],
|
||||
loading3pids: true, // whether or not the emails and msisdns have been loaded
|
||||
canChangePassword: false,
|
||||
idServerName: null,
|
||||
externalAccountManagementUrl: undefined,
|
||||
};
|
||||
|
||||
this.dispatcherRef = dis.register(this.onAction);
|
||||
|
@ -118,8 +115,8 @@ export default class GeneralUserSettingsTab extends React.Component<IProps, ISta
|
|||
public async componentDidMount(): Promise<void> {
|
||||
const plat = PlatformPeg.get();
|
||||
const [spellCheckEnabled, spellCheckLanguages] = await Promise.all([
|
||||
plat.getSpellCheckEnabled(),
|
||||
plat.getSpellCheckLanguages(),
|
||||
plat?.getSpellCheckEnabled(),
|
||||
plat?.getSpellCheckLanguages(),
|
||||
]);
|
||||
|
||||
if (spellCheckLanguages) {
|
||||
|
@ -301,7 +298,7 @@ export default class GeneralUserSettingsTab extends React.Component<IProps, ISta
|
|||
}
|
||||
|
||||
private renderAccountSection(): JSX.Element {
|
||||
let passwordChangeForm = (
|
||||
let passwordChangeForm: ReactNode = (
|
||||
<ChangePassword
|
||||
className="mx_GeneralUserSettingsTab_changePassword"
|
||||
rowClassName=""
|
||||
|
@ -311,7 +308,7 @@ export default class GeneralUserSettingsTab extends React.Component<IProps, ISta
|
|||
/>
|
||||
);
|
||||
|
||||
let threepidSection = null;
|
||||
let threepidSection: ReactNode = null;
|
||||
|
||||
// For older homeservers without separate 3PID add and bind methods (MSC2290),
|
||||
// we use a combo add with bind option API which requires an identity server to
|
||||
|
@ -345,7 +342,7 @@ export default class GeneralUserSettingsTab extends React.Component<IProps, ISta
|
|||
threepidSection = <Spinner />;
|
||||
}
|
||||
|
||||
let passwordChangeText = _t("Set a new account password…");
|
||||
let passwordChangeText: ReactNode = _t("Set a new account password…");
|
||||
if (!this.state.canChangePassword) {
|
||||
// Just don't show anything if you can't do anything.
|
||||
passwordChangeText = null;
|
||||
|
@ -483,7 +480,7 @@ export default class GeneralUserSettingsTab extends React.Component<IProps, ISta
|
|||
);
|
||||
}
|
||||
|
||||
private renderIntegrationManagerSection(): JSX.Element {
|
||||
private renderIntegrationManagerSection(): ReactNode {
|
||||
if (!SettingsStore.getValue(UIFeature.Widgets)) return null;
|
||||
|
||||
return (
|
||||
|
@ -496,7 +493,7 @@ export default class GeneralUserSettingsTab extends React.Component<IProps, ISta
|
|||
|
||||
public render(): React.ReactNode {
|
||||
const plaf = PlatformPeg.get();
|
||||
const supportsMultiLanguageSpellCheck = plaf.supportsSpellCheckSettings();
|
||||
const supportsMultiLanguageSpellCheck = plaf?.supportsSpellCheckSettings();
|
||||
|
||||
const discoWarning = this.state.requiredPolicyInfo.hasTerms ? (
|
||||
<img
|
||||
|
@ -508,7 +505,7 @@ export default class GeneralUserSettingsTab extends React.Component<IProps, ISta
|
|||
/>
|
||||
) : null;
|
||||
|
||||
let accountManagementSection;
|
||||
let accountManagementSection: JSX.Element | undefined;
|
||||
if (SettingsStore.getValue(UIFeature.Deactivate)) {
|
||||
accountManagementSection = (
|
||||
<>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue