Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
Apply strictNullChecks to src/components/views/settings (#10724)
Browse files Browse the repository at this point in the history
  • Loading branch information
Kerry authored May 5, 2023
1 parent a4f0b80 commit 1f4d857
Show file tree
Hide file tree
Showing 11 changed files with 772 additions and 48 deletions.
7 changes: 6 additions & 1 deletion src/components/views/elements/Tag.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,12 @@ export const Tag: React.FC<IProps> = ({ icon, label, onDeleteClick, disabled = f
{icon?.()}
{label}
{onDeleteClick && (
<AccessibleButton className="mx_Tag_delete" onClick={onDeleteClick} disabled={disabled}>
<AccessibleButton
aria-label="Remove"
className="mx_Tag_delete"
onClick={onDeleteClick}
disabled={disabled}
>
<CancelRounded />
</AccessibleButton>
)}
Expand Down
16 changes: 11 additions & 5 deletions src/components/views/settings/JoinRuleSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import { Action } from "../../../dispatcher/actions";
import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
import { doesRoomVersionSupport, PreferredRoomVersions } from "../../../utils/PreferredRoomVersions";

interface IProps {
export interface JoinRuleSettingsProps {
room: Room;
promptUpgrade?: boolean;
closeSettingsFn(): void;
Expand All @@ -45,7 +45,7 @@ interface IProps {
aliasWarning?: ReactNode;
}

const JoinRuleSettings: React.FC<IProps> = ({
const JoinRuleSettings: React.FC<JoinRuleSettingsProps> = ({
room,
promptUpgrade,
aliasWarning,
Expand Down Expand Up @@ -287,7 +287,10 @@ const JoinRuleSettings: React.FC<IProps> = ({
fn(_t("Upgrading room"), 0, total);
} else if (!progress.roomSynced) {
fn(_t("Loading new room"), 1, total);
} else if (progress.inviteUsersProgress < progress.inviteUsersTotal) {
} else if (
progress.inviteUsersProgress !== undefined &&
progress.inviteUsersProgress < progress.inviteUsersTotal
) {
fn(
_t("Sending invites... (%(progress)s out of %(count)s)", {
progress: progress.inviteUsersProgress,
Expand All @@ -296,13 +299,16 @@ const JoinRuleSettings: React.FC<IProps> = ({
2 + progress.inviteUsersProgress,
total,
);
} else if (progress.updateSpacesProgress < progress.updateSpacesTotal) {
} else if (
progress.updateSpacesProgress !== undefined &&
progress.updateSpacesProgress < progress.updateSpacesTotal
) {
fn(
_t("Updating spaces... (%(progress)s out of %(count)s)", {
progress: progress.updateSpacesProgress,
count: progress.updateSpacesTotal,
}),
2 + progress.inviteUsersProgress + progress.updateSpacesProgress,
2 + (progress.inviteUsersProgress ?? 0) + progress.updateSpacesProgress,
total,
);
}
Expand Down
56 changes: 35 additions & 21 deletions src/components/views/settings/Notifications.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ const maximumVectorState = (
if (!definition.syncedRuleIds?.length) {
return undefined;
}
const vectorState = definition.syncedRuleIds.reduce<VectorState | undefined>((maxVectorState, ruleId) => {
const vectorState = definition.syncedRuleIds.reduce<VectorState>((maxVectorState, ruleId) => {
// already set to maximum
if (maxVectorState === VectorState.Loud) {
return maxVectorState;
Expand All @@ -177,12 +177,15 @@ const maximumVectorState = (
const syncedRuleVectorState = definition.ruleToVectorState(syncedRule);
// if syncedRule is 'louder' than current maximum
// set maximum to louder vectorState
if (OrderedVectorStates.indexOf(syncedRuleVectorState) > OrderedVectorStates.indexOf(maxVectorState)) {
if (
syncedRuleVectorState &&
OrderedVectorStates.indexOf(syncedRuleVectorState) > OrderedVectorStates.indexOf(maxVectorState)
) {
return syncedRuleVectorState;
}
}
return maxVectorState;
}, definition.ruleToVectorState(rule));
}, definition.ruleToVectorState(rule)!);

return vectorState;
};
Expand Down Expand Up @@ -281,7 +284,7 @@ export default class Notifications extends React.PureComponent<IProps, IState> {
}

private async refreshRules(): Promise<Partial<IState>> {
const ruleSets = await MatrixClientPeg.get().getPushRules();
const ruleSets = await MatrixClientPeg.get().getPushRules()!;
const categories: Record<string, RuleClass> = {
[RuleId.Master]: RuleClass.Master,

Expand Down Expand Up @@ -316,7 +319,7 @@ export default class Notifications extends React.PureComponent<IProps, IState> {
// noinspection JSUnfilteredForInLoop
const kind = k as PushRuleKind;

for (const r of ruleSets.global[kind]) {
for (const r of ruleSets.global[kind]!) {
const rule: IAnnotatedPushRule = Object.assign(r, { kind });
const category = categories[rule.rule_id] ?? RuleClass.Other;

Expand Down Expand Up @@ -344,7 +347,7 @@ export default class Notifications extends React.PureComponent<IProps, IState> {
preparedNewState.vectorPushRules[category] = [];
for (const rule of defaultRules[category]) {
const definition: VectorPushRuleDefinition = VectorPushRulesDefinitions[rule.rule_id];
const vectorState = definition.ruleToVectorState(rule);
const vectorState = definition.ruleToVectorState(rule)!;
preparedNewState.vectorPushRules[category]!.push({
ruleId: rule.rule_id,
rule,
Expand Down Expand Up @@ -441,8 +444,7 @@ export default class Notifications extends React.PureComponent<IProps, IState> {
} else {
const pusher = this.state.pushers?.find((p) => p.kind === "email" && p.pushkey === email);
if (pusher) {
pusher.kind = null; // flag for delete
await MatrixClientPeg.get().setPusher(pusher);
await MatrixClientPeg.get().removePusher(pusher.pushkey, pusher.app_id);
}
}

Expand Down Expand Up @@ -539,34 +541,37 @@ export default class Notifications extends React.PureComponent<IProps, IState> {
}
};

private async setKeywords(keywords: string[], originalRules: IAnnotatedPushRule[]): Promise<void> {
private async setKeywords(
unsafeKeywords: (string | undefined)[],
originalRules: IAnnotatedPushRule[],
): Promise<void> {
try {
// De-duplicate and remove empties
keywords = filterBoolean(Array.from(new Set(keywords)));
const oldKeywords = filterBoolean(Array.from(new Set(originalRules.map((r) => r.pattern))));
const keywords = filterBoolean<string>(Array.from(new Set(unsafeKeywords)));
const oldKeywords = filterBoolean<string>(Array.from(new Set(originalRules.map((r) => r.pattern))));

// Note: Technically because of the UI interaction (at the time of writing), the diff
// will only ever be +/-1 so we don't really have to worry about efficiently handling
// tons of keyword changes.

const diff = arrayDiff(oldKeywords, keywords);
const diff = arrayDiff<string>(oldKeywords, keywords);

for (const word of diff.removed) {
for (const rule of originalRules.filter((r) => r.pattern === word)) {
await MatrixClientPeg.get().deletePushRule("global", rule.kind, rule.rule_id);
}
}

let ruleVectorState = this.state.vectorKeywordRuleInfo?.vectorState;
let ruleVectorState = this.state.vectorKeywordRuleInfo!.vectorState;
if (ruleVectorState === VectorState.Off) {
// When the current global keywords rule is OFF, we need to look at
// the flavor of existing rules to apply the same actions
// when creating the new rule.
if (originalRules.length) {
ruleVectorState = PushRuleVectorState.contentRuleVectorStateKind(originalRules[0]) ?? undefined;
} else {
ruleVectorState = VectorState.On; // default
}
const existingRuleVectorState = originalRules.length
? PushRuleVectorState.contentRuleVectorStateKind(originalRules[0])
: undefined;
// set to same state as existing rule, or default to On
ruleVectorState = existingRuleVectorState ?? VectorState.On; //default
}
const kind = PushRuleKind.ContentSpecific;
for (const word of diff.added) {
Expand All @@ -588,6 +593,10 @@ export default class Notifications extends React.PureComponent<IProps, IState> {
}

private onKeywordAdd = (keyword: string): void => {
// should not encounter this
if (!this.state.vectorKeywordRuleInfo) {
throw new Error("Notification data is incomplete.");
}
const originalRules = objectClone(this.state.vectorKeywordRuleInfo.rules);

// We add the keyword immediately as a sort of local echo effect
Expand All @@ -606,14 +615,18 @@ export default class Notifications extends React.PureComponent<IProps, IState> {
},
async (): Promise<void> => {
await this.setKeywords(
this.state.vectorKeywordRuleInfo.rules.map((r) => r.pattern),
this.state.vectorKeywordRuleInfo!.rules.map((r) => r.pattern),
originalRules,
);
},
);
};

private onKeywordRemove = (keyword: string): void => {
// should not encounter this
if (!this.state.vectorKeywordRuleInfo) {
throw new Error("Notification data is incomplete.");
}
const originalRules = objectClone(this.state.vectorKeywordRuleInfo.rules);

// We remove the keyword immediately as a sort of local echo effect
Expand All @@ -627,7 +640,7 @@ export default class Notifications extends React.PureComponent<IProps, IState> {
},
async (): Promise<void> => {
await this.setKeywords(
this.state.vectorKeywordRuleInfo.rules.map((r) => r.pattern),
this.state.vectorKeywordRuleInfo!.rules.map((r) => r.pattern),
originalRules,
);
},
Expand Down Expand Up @@ -749,9 +762,10 @@ export default class Notifications extends React.PureComponent<IProps, IState> {

let keywordComposer: JSX.Element | undefined;
if (category === RuleClass.VectorMentions) {
const tags = filterBoolean<string>(this.state.vectorKeywordRuleInfo?.rules.map((r) => r.pattern) || []);
keywordComposer = (
<TagComposer
tags={this.state.vectorKeywordRuleInfo?.rules.map((r) => r.pattern)}
tags={tags}
onAdd={this.onKeywordAdd}
onRemove={this.onKeywordRemove}
disabled={this.state.phase === Phase.Persisting}
Expand Down
4 changes: 3 additions & 1 deletion src/components/views/settings/ProfileSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ export default class ProfileSettings extends React.Component<{}, IState> {

private removeAvatar = (): void => {
// clear file upload field so same file can be selected
this.avatarUpload.current.value = "";
if (this.avatarUpload.current) {
this.avatarUpload.current.value = "";
}
this.setState({
avatarUrl: undefined,
avatarFile: null,
Expand Down
16 changes: 8 additions & 8 deletions src/components/views/settings/SecureBackupPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,12 @@ export default class SecureBackupPanel extends React.PureComponent<{}, IState> {
private async checkKeyBackupStatus(): Promise<void> {
this.getUpdatedDiagnostics();
try {
const { backupInfo, trustInfo } = await MatrixClientPeg.get().checkKeyBackup();
const keyBackupResult = await MatrixClientPeg.get().checkKeyBackup();
this.setState({
loading: false,
error: null,
backupInfo,
backupSigStatus: trustInfo,
backupInfo: keyBackupResult?.backupInfo ?? null,
backupSigStatus: keyBackupResult?.trustInfo ?? null,
});
} catch (e) {
logger.log("Unable to fetch check backup status", e);
Expand All @@ -123,7 +123,7 @@ export default class SecureBackupPanel extends React.PureComponent<{}, IState> {
this.getUpdatedDiagnostics();
try {
const backupInfo = await MatrixClientPeg.get().getKeyBackupVersion();
const backupSigStatus = await MatrixClientPeg.get().isKeyBackupTrusted(backupInfo!);
const backupSigStatus = backupInfo ? await MatrixClientPeg.get().isKeyBackupTrusted(backupInfo) : null;
if (this.unmounted) return;
this.setState({
loading: false,
Expand Down Expand Up @@ -192,7 +192,7 @@ export default class SecureBackupPanel extends React.PureComponent<{}, IState> {
if (!proceed) return;
this.setState({ loading: true });
MatrixClientPeg.get()
.deleteKeyBackupVersion(this.state.backupInfo.version)
.deleteKeyBackupVersion(this.state.backupInfo!.version!)
.then(() => {
this.loadBackupStatus();
});
Expand Down Expand Up @@ -285,7 +285,7 @@ export default class SecureBackupPanel extends React.PureComponent<{}, IState> {
);
}

let backupSigStatuses: React.ReactNode = backupSigStatus?.sigs.map((sig, i) => {
let backupSigStatuses: React.ReactNode | undefined = backupSigStatus?.sigs?.map((sig, i) => {
const deviceName = sig.device ? sig.device.getDisplayName() || sig.device.deviceId : null;
const validity = (sub: string): JSX.Element => (
<span className={sig.valid ? "mx_SecureBackupPanel_sigValid" : "mx_SecureBackupPanel_sigInvalid"}>
Expand Down Expand Up @@ -354,7 +354,7 @@ export default class SecureBackupPanel extends React.PureComponent<{}, IState> {
{},
{ validity, verify, device },
);
} else if (sig.valid && !sig.deviceTrust.isVerified()) {
} else if (sig.valid && !sig.deviceTrust?.isVerified()) {
sigStatus = _t(
"Backup has a <validity>valid</validity> signature from " +
"<verify>unverified</verify> session <device></device>",
Expand All @@ -368,7 +368,7 @@ export default class SecureBackupPanel extends React.PureComponent<{}, IState> {
{},
{ validity, verify, device },
);
} else if (!sig.valid && !sig.deviceTrust.isVerified()) {
} else if (!sig.valid && !sig.deviceTrust?.isVerified()) {
sigStatus = _t(
"Backup has an <validity>invalid</validity> signature from " +
"<verify>unverified</verify> session <device></device>",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export default class VoiceUserSettingsTab extends React.Component<{}, IState> {

private setDevice = (deviceId: string, kind: MediaDeviceKindEnum): void => {
MediaDeviceHandler.instance.setDevice(deviceId, kind);
this.setState<null>({ [kind]: deviceId });
this.setState<any>({ [kind]: deviceId });
};

private changeWebRtcMethod = (p2p: boolean): void => {
Expand Down
Loading

0 comments on commit 1f4d857

Please sign in to comment.