Conform more of the codebase to strictNullChecks (#10672)

* Conform more of the codebase to `strictNullChecks`

* Iterate

* Iterate

* Iterate

* Iterate

* Conform more of the codebase to `strictNullChecks`

* Iterate

* Update record key
This commit is contained in:
Michael Telatynski 2023-04-21 11:50:42 +01:00 committed by GitHub
parent 792a39a39b
commit be5928cb64
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
34 changed files with 143 additions and 115 deletions

View file

@ -169,8 +169,8 @@ const RoomContextMenu: React.FC<IProps> = ({ room, onFinished, ...props }) => {
);
const echoChamber = EchoChamber.forRoom(room);
let notificationLabel: string;
let iconClassName: string;
let notificationLabel: string | undefined;
let iconClassName: string | undefined;
switch (echoChamber.notificationVolume) {
case RoomNotifState.AllMessages:
notificationLabel = _t("Default");
@ -337,7 +337,7 @@ const RoomContextMenu: React.FC<IProps> = ({ room, onFinished, ...props }) => {
const isApplied = RoomListStore.instance.getTagsForRoom(room).includes(tagId);
const removeTag = isApplied ? tagId : inverseTag;
const addTag = isApplied ? null : tagId;
dis.dispatch(RoomListActions.tagRoom(cli, room, removeTag, addTag, undefined, 0));
dis.dispatch(RoomListActions.tagRoom(cli, room, removeTag, addTag, 0));
} else {
logger.warn(`Unexpected tag ${tagId} applied to ${room.roomId}`);
}

View file

@ -100,7 +100,7 @@ export const RoomGeneralContextMenu: React.FC<RoomGeneralContextMenuProps> = ({
const isApplied = RoomListStore.instance.getTagsForRoom(room).includes(tagId);
const removeTag = isApplied ? tagId : inverseTag;
const addTag = isApplied ? null : tagId;
dis.dispatch(RoomListActions.tagRoom(cli, room, removeTag, addTag, undefined, 0));
dis.dispatch(RoomListActions.tagRoom(cli, room, removeTag, addTag, 0));
} else {
logger.warn(`Unexpected tag ${tagId} applied to ${room.roomId}`);
}

View file

@ -260,7 +260,7 @@ export default class ReportEventDialog extends React.Component<IProps, IState> {
// if the user should also be ignored, do that
if (this.state.ignoreUserToo) {
await client.setIgnoredUsers([...client.getIgnoredUsers(), ev.getSender()]);
await client.setIgnoredUsers([...client.getIgnoredUsers(), ev.getSender()!]);
}
this.props.onFinished(true);
@ -309,8 +309,8 @@ export default class ReportEventDialog extends React.Component<IProps, IState> {
// Display report-to-moderator dialog.
// We let the user pick a nature.
const client = MatrixClientPeg.get();
const homeServerName = SdkConfig.get("validated_server_config").hsName;
let subtitle;
const homeServerName = SdkConfig.get("validated_server_config")!.hsName;
let subtitle: string;
switch (this.state.nature) {
case Nature.Disagreement:
subtitle = _t(

View file

@ -130,7 +130,7 @@ export default class AccessSecretStorageDialog extends React.PureComponent<IProp
// also clear the file upload control so that the user can upload the same file
// the did before (otherwise the onchange wouldn't fire)
if (this.fileUpload.current) this.fileUpload.current.value = null;
if (this.fileUpload.current) this.fileUpload.current.value = "";
// We don't use Field's validation here because a) we want it in a separate place rather
// than in a tooltip and b) we want it to display feedback based on the uploaded file

View file

@ -324,7 +324,10 @@ export default class RestoreKeyBackupDialog extends React.PureComponent<IProps,
details = _t("Fetching keys from server…");
} else if (this.state.progress.stage === ProgressState.LoadKeys) {
const { total, successes, failures } = this.state.progress;
details = _t("%(completed)s of %(total)s keys restored", { total, completed: successes + failures });
details = _t("%(completed)s of %(total)s keys restored", {
total,
completed: (successes ?? 0) + (failures ?? 0),
});
} else if (this.state.progress.stage === ProgressState.PreFetch) {
details = _t("Fetching keys from server…");
}

View file

@ -65,11 +65,11 @@ export const OverflowMenuContext = createContext<OverflowMenuCloser | null>(null
const MessageComposerButtons: React.FC<IProps> = (props: IProps) => {
const matrixClient = useContext(MatrixClientContext);
const { room, roomId, narrow } = useContext(RoomContext);
const { room, narrow } = useContext(RoomContext);
const isWysiwygLabEnabled = useSettingValue<boolean>("feature_wysiwyg_composer");
if (props.haveRecording) {
if (!matrixClient || !room || props.haveRecording) {
return null;
}
@ -93,7 +93,7 @@ const MessageComposerButtons: React.FC<IProps> = (props: IProps) => {
voiceRecordingButton(props, narrow),
startVoiceBroadcastButton(props),
props.showPollsButton ? pollButton(room, props.relation) : null,
showLocationButton(props, room, roomId, matrixClient),
showLocationButton(props, room, matrixClient),
];
} else {
mainButtons = [
@ -113,7 +113,7 @@ const MessageComposerButtons: React.FC<IProps> = (props: IProps) => {
voiceRecordingButton(props, narrow),
startVoiceBroadcastButton(props),
props.showPollsButton ? pollButton(room, props.relation) : null,
showLocationButton(props, room, roomId, matrixClient),
showLocationButton(props, room, matrixClient),
];
}
@ -127,7 +127,7 @@ const MessageComposerButtons: React.FC<IProps> = (props: IProps) => {
});
return (
<UploadButtonContextProvider roomId={roomId} relation={props.relation}>
<UploadButtonContextProvider roomId={room.roomId} relation={props.relation}>
{mainButtons}
{moreButtons.length > 0 && (
<AccessibleTooltipButton
@ -346,18 +346,13 @@ class PollButton extends React.PureComponent<IPollButtonProps> {
}
}
function showLocationButton(
props: IProps,
room: Room,
roomId: string,
matrixClient: MatrixClient,
): ReactElement | null {
const sender = room.getMember(matrixClient.getUserId()!);
function showLocationButton(props: IProps, room: Room, matrixClient: MatrixClient): ReactElement | null {
const sender = room.getMember(matrixClient.getSafeUserId());
return props.showLocationButton && sender ? (
<LocationButton
key="location"
roomId={roomId}
roomId={room.roomId}
relation={props.relation}
sender={sender}
menuPosition={props.menuPosition}

View file

@ -151,7 +151,7 @@ export default class RoomPreviewBar extends React.Component<IProps, IState> {
const result = await MatrixClientPeg.get().lookupThreePid(
"email",
this.props.invitedEmail,
identityAccessToken,
identityAccessToken!,
);
this.setState({ invitedEmailMxid: result.mxid });
} catch (err) {
@ -243,8 +243,8 @@ export default class RoomPreviewBar extends React.Component<IProps, IState> {
if (!inviteEvent) {
return null;
}
const inviterUserId = inviteEvent.events.member.getSender();
return room.currentState.getMember(inviterUserId);
const inviterUserId = inviteEvent.events.member?.getSender();
return inviterUserId ? room.currentState.getMember(inviterUserId) : null;
}
private isDMInvite(): boolean {
@ -252,8 +252,8 @@ export default class RoomPreviewBar extends React.Component<IProps, IState> {
if (!myMember) {
return false;
}
const memberContent = myMember.events.member.getContent();
return memberContent.membership === "invite" && memberContent.is_direct;
const memberContent = myMember.events.member?.getContent();
return memberContent?.membership === "invite" && memberContent.is_direct;
}
private makeScreenAfterLogin(): { screen: string; params: Record<string, any> } {

View file

@ -64,7 +64,7 @@ export default class SearchResultTile extends React.Component<IProps> {
const eventId = resultEvent.getId();
const ts1 = resultEvent.getTs();
const ret = [<DateSeparator key={ts1 + "-search"} roomId={resultEvent.getRoomId()} ts={ts1} />];
const ret = [<DateSeparator key={ts1 + "-search"} roomId={resultEvent.getRoomId()!} ts={ts1} />];
const layout = SettingsStore.getValue("layout");
const isTwelveHour = SettingsStore.getValue("showTwelveHourTimestamps");
const alwaysShowTimestamps = SettingsStore.getValue("alwaysShowTimestamps");

View file

@ -372,7 +372,10 @@ export class SendMessageComposer extends React.Component<ISendMessageComposerPro
return false;
}
this.currentlyComposedEditorState = this.model.serializeParts();
} else if (this.sendHistoryManager.currentIndex + delta === this.sendHistoryManager.history.length) {
} else if (
this.currentlyComposedEditorState &&
this.sendHistoryManager.currentIndex + delta === this.sendHistoryManager.history.length
) {
// True when we return to the message being composed currently
this.model.reset(this.currentlyComposedEditorState);
this.sendHistoryManager.currentIndex = this.sendHistoryManager.history.length;
@ -393,6 +396,7 @@ export class SendMessageComposer extends React.Component<ISendMessageComposerPro
private sendQuickReaction(): void {
const timeline = this.context.liveTimeline;
if (!timeline) return;
const events = timeline.getEvents();
const reaction = this.model.parts[1].text;
for (let i = events.length - 1; i >= 0; i--) {
@ -443,8 +447,8 @@ export class SendMessageComposer extends React.Component<ISendMessageComposerPro
isReply: !!this.props.replyToEvent,
inThread: this.props.relation?.rel_type === THREAD_RELATION_TYPE.name,
};
if (posthogEvent.inThread) {
const threadRoot = this.props.room.findEventById(this.props.relation.event_id);
if (posthogEvent.inThread && this.props.relation!.event_id) {
const threadRoot = this.props.room.findEventById(this.props.relation!.event_id);
posthogEvent.startsThread = threadRoot?.getThread()?.events.length === 1;
}
PosthogAnalytics.instance.trackEvent<ComposerEvent>(posthogEvent);
@ -480,7 +484,7 @@ export class SendMessageComposer extends React.Component<ISendMessageComposerPro
return; // errored
}
if (cmd.category === CommandCategories.messages || cmd.category === CommandCategories.effects) {
if (content && [CommandCategories.messages, CommandCategories.effects].includes(cmd.category)) {
// Attach any mentions which might be contained in the command content.
attachMentions(this.props.mxClient.getSafeUserId(), content, model, replyToEvent);
attachRelation(content, this.props.relation);

View file

@ -86,7 +86,7 @@ export default class AdvancedRoomSettingsTab extends React.Component<IProps, ISt
private upgradeRoom = (): void => {
const room = MatrixClientPeg.get().getRoom(this.props.roomId);
Modal.createDialog(RoomUpgradeDialog, { room });
if (room) Modal.createDialog(RoomUpgradeDialog, { room });
};
private onOldRoomClicked = (e: ButtonEvent): void => {

View file

@ -66,13 +66,20 @@ interface IState {
haveIdServer: boolean;
serverSupportsSeparateAddAndBind?: boolean;
idServerHasUnsignedTerms: boolean;
requiredPolicyInfo: {
// This object is passed along to a component for handling
hasTerms: boolean;
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
};
requiredPolicyInfo:
| {
// This object is passed along to a component for handling
hasTerms: false;
policiesAndServices: null; // From the startTermsFlow callback
agreedUrls: null; // From the startTermsFlow callback
resolve: null; // Promise resolve function for startTermsFlow callback
}
| {
hasTerms: boolean;
policiesAndServices: ServicePolicyPair[];
agreedUrls: string[];
resolve: (values: string[]) => void;
};
emails: IThreepid[];
msisdns: IThreepid[];
loading3pids: boolean; // whether or not the emails and msisdns have been loaded
@ -191,19 +198,19 @@ export default class GeneralUserSettingsTab extends React.Component<IProps, ISta
}
private async checkTerms(): Promise<void> {
if (!this.state.haveIdServer) {
// By starting the terms flow we get the logic for checking which terms the user has signed
// for free. So we might as well use that for our own purposes.
const idServerUrl = MatrixClientPeg.get().getIdentityServerUrl();
if (!this.state.haveIdServer || !idServerUrl) {
this.setState({ idServerHasUnsignedTerms: false });
return;
}
// By starting the terms flow we get the logic for checking which terms the user has signed
// for free. So we might as well use that for our own purposes.
const idServerUrl = MatrixClientPeg.get().getIdentityServerUrl();
const authClient = new IdentityAuthClient();
try {
const idAccessToken = await authClient.getAccessToken({ check: false });
await startTermsFlow(
[new Service(SERVICE_TYPES.IS, idServerUrl, idAccessToken)],
[new Service(SERVICE_TYPES.IS, idServerUrl, idAccessToken!)],
(policiesAndServices, agreedUrls, extraClassNames) => {
return new Promise((resolve, reject) => {
this.setState({

View file

@ -62,7 +62,7 @@ export default class AudioFeed extends React.Component<IProps, IState> {
// it fails.
// It seems reliable if you set the sink ID after setting the srcObject and then set the sink ID
// back to the default after the call is over - Dave
element.setSinkId(audioOutput);
element!.setSinkId(audioOutput);
} catch (e) {
logger.error("Couldn't set requested audio output device: using default", e);
logger.warn("Couldn't set requested audio output device: using default", e);
@ -103,7 +103,7 @@ export default class AudioFeed extends React.Component<IProps, IState> {
if (!element) return;
element.pause();
element.src = null;
element.removeAttribute("src");
// As per comment in componentDidMount, setting the sink ID back to the
// default once the call is over makes setSinkId work reliably. - Dave

View file

@ -339,16 +339,17 @@ export default class LegacyCallView extends React.Component<IProps, IState> {
private onCallResumeClick = (): void => {
const userFacingRoomId = LegacyCallHandler.instance.roomIdForCall(this.props.call);
LegacyCallHandler.instance.setActiveCallRoomId(userFacingRoomId);
if (userFacingRoomId) LegacyCallHandler.instance.setActiveCallRoomId(userFacingRoomId);
};
private onTransferClick = (): void => {
const transfereeCall = LegacyCallHandler.instance.getTransfereeForCallId(this.props.call.callId);
this.props.call.transferToCall(transfereeCall);
if (transfereeCall) this.props.call.transferToCall(transfereeCall);
};
private onHangupClick = (): void => {
LegacyCallHandler.instance.hangupOrReject(LegacyCallHandler.instance.roomIdForCall(this.props.call));
const roomId = LegacyCallHandler.instance.roomIdForCall(this.props.call);
if (roomId) LegacyCallHandler.instance.hangupOrReject(roomId);
};
private onToggleSidebar = (): void => {
@ -451,13 +452,12 @@ export default class LegacyCallView extends React.Component<IProps, IState> {
let holdTransferContent: React.ReactNode;
if (transfereeCall) {
const transferTargetRoom = MatrixClientPeg.get().getRoom(
LegacyCallHandler.instance.roomIdForCall(call),
);
const cli = MatrixClientPeg.get();
const callRoomId = LegacyCallHandler.instance.roomIdForCall(call);
const transferTargetRoom = callRoomId ? cli.getRoom(callRoomId) : null;
const transferTargetName = transferTargetRoom ? transferTargetRoom.name : _t("unknown person");
const transfereeRoom = MatrixClientPeg.get().getRoom(
LegacyCallHandler.instance.roomIdForCall(transfereeCall),
);
const transfereeCallRoomId = LegacyCallHandler.instance.roomIdForCall(transfereeCall);
const transfereeRoom = transfereeCallRoomId ? cli.getRoom(transfereeCallRoomId) : null;
const transfereeName = transfereeRoom ? transfereeRoom.name : _t("unknown person");
holdTransferContent = (
@ -579,6 +579,8 @@ export default class LegacyCallView extends React.Component<IProps, IState> {
const callRoomId = LegacyCallHandler.instance.roomIdForCall(call);
const secondaryCallRoomId = LegacyCallHandler.instance.roomIdForCall(secondaryCall);
const callRoom = callRoomId ? client.getRoom(callRoomId) : null;
if (!callRoom) return null;
const secCallRoom = secondaryCallRoomId ? client.getRoom(secondaryCallRoomId) : null;
const callViewClasses = classNames({

View file

@ -150,7 +150,7 @@ export default class VideoFeed extends React.PureComponent<IProps, IState> {
if (!element) return;
element.pause();
element.src = null;
element.removeAttribute("src");
// As per comment in componentDidMount, setting the sink ID back to the
// default once the call is over makes setSinkId work reliably. - Dave