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

Commit

Permalink
Conform more code to strictNullChecks (#10368
Browse files Browse the repository at this point in the history
* Conform more code to `strictNullChecks`

* Iterate
  • Loading branch information
t3chguy authored Mar 14, 2023
1 parent 05e3fb0 commit 8cb8cd4
Show file tree
Hide file tree
Showing 24 changed files with 176 additions and 157 deletions.
13 changes: 12 additions & 1 deletion src/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,19 @@ export type ComponentType = React.ComponentType<{
onFinished?(...args: any): void;
}>;

type Defaultize<P, D> = P extends any
? string extends keyof P
? P
: Pick<P, Exclude<keyof P, keyof D>> &
Partial<Pick<P, Extract<keyof P, keyof D>>> &
Partial<Pick<D, Exclude<keyof D, keyof P>>>
: never;

// Generic type which returns the props of the Modal component with the onFinished being optional.
export type ComponentProps<C extends ComponentType> = Omit<React.ComponentProps<C>, "onFinished"> &
export type ComponentProps<C extends ComponentType> = Defaultize<
Omit<React.ComponentProps<C>, "onFinished">,
C["defaultProps"]
> &
Partial<Pick<React.ComponentProps<C>, "onFinished">>;

export interface IModal<C extends ComponentType> {
Expand Down
38 changes: 19 additions & 19 deletions src/components/structures/RoomView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1020,7 +1020,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
});
};

private onPageUnload = (event: BeforeUnloadEvent): string => {
private onPageUnload = (event: BeforeUnloadEvent): string | undefined => {
if (ContentMessages.sharedInstance().getCurrentUploads().length > 0) {
return (event.returnValue = _t("You seem to be uploading files, are you sure you want to quit?"));
} else if (this.getCallForRoom() && this.state.callState !== "ended") {
Expand All @@ -1034,7 +1034,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
const action = getKeyBindingsManager().getRoomAction(ev);
switch (action) {
case KeyBindingAction.DismissReadMarker:
this.messagePanel.forgetReadMarker();
this.messagePanel?.forgetReadMarker();
this.jumpToLiveTimeline();
handled = true;
break;
Expand Down Expand Up @@ -1067,7 +1067,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {

if (!roomId) return;
const call = this.getCallForRoom();
this.setState({ callState: call ? call.state : null });
this.setState({ callState: call?.state });
};

private onAction = async (payload: ActionPayload): Promise<void> => {
Expand All @@ -1087,7 +1087,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
ContentMessages.sharedInstance().sendContentListToRoom(
[payload.file],
this.state.room.roomId,
null,
undefined,
this.context.client,
);
break;
Expand Down Expand Up @@ -1117,7 +1117,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
if (!this.state.matrixClientIsReady) {
this.setState(
{
matrixClientIsReady: this.context.client?.isInitialSyncComplete(),
matrixClientIsReady: !!this.context.client?.isInitialSyncComplete(),
},
() => {
// send another "initial" RVS update to trigger peeking if needed
Expand All @@ -1137,7 +1137,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
case Action.EditEvent: {
// Quit early if we're trying to edit events in wrong rendering context
if (payload.timelineRenderingType !== this.state.timelineRenderingType) return;
const editState = payload.event ? new EditorStateTransfer(payload.event) : null;
const editState = payload.event ? new EditorStateTransfer(payload.event) : undefined;
this.setState({ editState }, () => {
if (payload.event) {
this.messagePanel?.scrollToEventIfNeeded(payload.event.getId());
Expand Down Expand Up @@ -1194,7 +1194,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {

private onRoomTimeline = (
ev: MatrixEvent,
room: Room | null,
room: Room | undefined,
toStartOfTimeline: boolean,
removed: boolean,
data?: IRoomTimelineData,
Expand Down Expand Up @@ -1228,7 +1228,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
this.handleEffects(ev);
}

if (ev.getSender() !== this.context.client.credentials.userId) {
if (ev.getSender() !== this.context.client.getSafeUserId()) {
// update unread count when scrolled up
if (!this.state.search && this.state.atEndOfLiveTimeline) {
// no change
Expand Down Expand Up @@ -1325,7 +1325,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
};

private getRoomTombstone(room = this.state.room): MatrixEvent | undefined {
return room?.currentState.getStateEvents(EventType.RoomTombstone, "");
return room?.currentState.getStateEvents(EventType.RoomTombstone, "") ?? undefined;
}

private async calculateRecommendedVersion(room: Room): Promise<void> {
Expand All @@ -1336,7 +1336,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {

private async loadMembersIfJoined(room: Room): Promise<void> {
// lazy load members if enabled
if (this.context.client.hasLazyLoadMembersEnabled()) {
if (this.context.client?.hasLazyLoadMembersEnabled()) {
if (room && room.getMyMembership() === "join") {
try {
await room.loadMembersIfNeeded();
Expand Down Expand Up @@ -1415,7 +1415,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
};

private async updateE2EStatus(room: Room): Promise<void> {
if (!this.context.client.isRoomEncrypted(room.roomId)) return;
if (!this.context.client?.isRoomEncrypted(room.roomId)) return;

// If crypto is not currently enabled, we aren't tracking devices at all,
// so we don't know what the answer is. Let's error on the safe side and show
Expand Down Expand Up @@ -2093,7 +2093,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
// We have successfully loaded this room, and are not previewing.
// Display the "normal" room view.

let activeCall = null;
let activeCall: MatrixCall | null = null;
{
// New block because this variable doesn't need to hang around for the rest of the function
const call = this.getCallForRoom();
Expand All @@ -2102,7 +2102,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
}
}

let statusBar;
let statusBar: JSX.Element | undefined;
let isStatusAreaExpanded = true;

if (ContentMessages.sharedInstance().getCurrentUploads().length > 0) {
Expand Down Expand Up @@ -2301,7 +2301,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
/>
);

let topUnreadMessagesBar = null;
let topUnreadMessagesBar: JSX.Element | undefined;
// Do not show TopUnreadMessagesBar if we have search results showing, it makes no sense
if (this.state.showTopUnreadMessagesBar && !this.state.search) {
topUnreadMessagesBar = (
Expand Down Expand Up @@ -2342,7 +2342,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {

const showChatEffects = SettingsStore.getValue("showChatEffects");

let mainSplitBody: React.ReactFragment;
let mainSplitBody: JSX.Element | undefined;
let mainSplitContentClassName: string;
// Decide what to show in the main split
switch (this.state.mainSplitContentType) {
Expand Down Expand Up @@ -2396,10 +2396,10 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
const mainSplitContentClasses = classNames("mx_RoomView_body", mainSplitContentClassName);

let excludedRightPanelPhaseButtons = [RightPanelPhases.Timeline];
let onAppsClick = this.onAppsClick;
let onForgetClick = this.onForgetClick;
let onSearchClick = this.onSearchClick;
let onInviteClick = null;
let onAppsClick: (() => void) | null = this.onAppsClick;
let onForgetClick: (() => void) | null = this.onForgetClick;
let onSearchClick: (() => void) | null = this.onSearchClick;
let onInviteClick: (() => void) | null = null;
let viewingCall = false;

// Simplify the header for other main split types
Expand Down
62 changes: 29 additions & 33 deletions src/components/structures/SpaceHierarchy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,9 @@ const Tile: React.FC<ITileProps> = ({
children,
}) => {
const cli = useContext(MatrixClientContext);
const [joinedRoom, setJoinedRoom] = useState<Room>(() => {
const [joinedRoom, setJoinedRoom] = useState<Room | undefined>(() => {
const cliRoom = cli.getRoom(room.room_id);
return cliRoom?.getMyMembership() === "join" ? cliRoom : null;
return cliRoom?.getMyMembership() === "join" ? cliRoom : undefined;
});
const joinedRoomName = useTypedEventEmitterState(joinedRoom, RoomEvent.Name, (room) => room?.name);
const name =
Expand Down Expand Up @@ -264,9 +264,9 @@ const Tile: React.FC<ITileProps> = ({
</React.Fragment>
);

let childToggle: JSX.Element;
let childSection: JSX.Element;
let onKeyDown: KeyboardEventHandler;
let childToggle: JSX.Element | undefined;
let childSection: JSX.Element | undefined;
let onKeyDown: KeyboardEventHandler | undefined;
if (children) {
// the chevron is purposefully a div rather than a button as it should be ignored for a11y
childToggle = (
Expand Down Expand Up @@ -386,32 +386,28 @@ export const showRoom = (cli: MatrixClient, hierarchy: RoomHierarchy, roomId: st
});
};

export const joinRoom = (cli: MatrixClient, hierarchy: RoomHierarchy, roomId: string): Promise<unknown> => {
export const joinRoom = async (cli: MatrixClient, hierarchy: RoomHierarchy, roomId: string): Promise<unknown> => {
// Don't let the user view a room they won't be able to either peek or join:
// fail earlier so they don't have to click back to the directory.
if (cli.isGuest()) {
defaultDispatcher.dispatch({ action: "require_registration" });
return;
}

const prom = cli.joinRoom(roomId, {
viaServers: Array.from(hierarchy.viaMap.get(roomId) || []),
});

prom.then(
() => {
defaultDispatcher.dispatch<JoinRoomReadyPayload>({
action: Action.JoinRoomReady,
roomId,
metricsTrigger: "SpaceHierarchy",
});
},
(err) => {
SdkContextClass.instance.roomViewStore.showJoinRoomError(err, roomId);
},
);
try {
await cli.joinRoom(roomId, {
viaServers: Array.from(hierarchy.viaMap.get(roomId) || []),
});
} catch (err) {
SdkContextClass.instance.roomViewStore.showJoinRoomError(err, roomId);
return;
}

return prom;
defaultDispatcher.dispatch<JoinRoomReadyPayload>({
action: Action.JoinRoomReady,
roomId,
metricsTrigger: "SpaceHierarchy",
});
};

interface IHierarchyLevelProps {
Expand All @@ -433,7 +429,7 @@ export const toLocalRoom = (cli: MatrixClient, room: IHierarchyRoom, hierarchy:
);

// Pick latest room that is actually part of the hierarchy
let cliRoom = null;
let cliRoom: Room | null = null;
for (let idx = history.length - 1; idx >= 0; --idx) {
if (hierarchy.roomMap.get(history[idx].roomId)) {
cliRoom = history[idx];
Expand All @@ -448,7 +444,7 @@ export const toLocalRoom = (cli: MatrixClient, room: IHierarchyRoom, hierarchy:
room_type: cliRoom.getType(),
name: cliRoom.name,
topic: cliRoom.currentState.getStateEvents(EventType.RoomTopic, "")?.getContent().topic,
avatar_url: cliRoom.getMxcAvatarUrl(),
avatar_url: cliRoom.getMxcAvatarUrl() ?? undefined,
canonical_alias: cliRoom.getCanonicalAlias() ?? undefined,
aliases: cliRoom.getAltAliases(),
world_readable:
Expand Down Expand Up @@ -476,7 +472,7 @@ export const HierarchyLevel: React.FC<IHierarchyLevelProps> = ({
}) => {
const cli = useContext(MatrixClientContext);
const space = cli.getRoom(root.room_id);
const hasPermissions = space?.currentState.maySendStateEvent(EventType.SpaceChild, cli.getUserId());
const hasPermissions = space?.currentState.maySendStateEvent(EventType.SpaceChild, cli.getSafeUserId());

const sortedChildren = sortBy(root.children_state, (ev) => {
return getChildOrder(ev.content.order, ev.origin_server_ts, ev.state_key);
Expand Down Expand Up @@ -579,7 +575,7 @@ export const useRoomHierarchy = (

const loadMore = useCallback(
async (pageSize?: number): Promise<void> => {
if (hierarchy.loading || !hierarchy.canLoadMore || hierarchy.noSupport || error) return;
if (!hierarchy || hierarchy.loading || !hierarchy.canLoadMore || hierarchy.noSupport || error) return;
await hierarchy.load(pageSize).catch(setError);
setRooms(hierarchy.rooms);
},
Expand Down Expand Up @@ -673,7 +669,7 @@ const ManageButtons: React.FC<IManageButtonsProps> = ({ hierarchy, selected, set
onClick={async (): Promise<void> => {
setRemoving(true);
try {
const userId = cli.getUserId();
const userId = cli.getSafeUserId();
for (const [parentId, childId] of selectedRelations) {
await cli.sendStateEvent(parentId, EventType.SpaceChild, {}, childId);

Expand Down Expand Up @@ -759,7 +755,7 @@ const SpaceHierarchy: React.FC<IProps> = ({ space, initialText = "", showRoom, a
const visited = new Set<string>();
const queue = [...directMatches.map((r) => r.room_id)];
while (queue.length) {
const roomId = queue.pop();
const roomId = queue.pop()!;
visited.add(roomId);
hierarchy.backRefs.get(roomId)?.forEach((parentId) => {
if (!visited.has(parentId)) {
Expand Down Expand Up @@ -797,7 +793,7 @@ const SpaceHierarchy: React.FC<IProps> = ({ space, initialText = "", showRoom, a
return;
}

const parentSet = selected.get(parentId);
const parentSet = selected.get(parentId)!;
if (!parentSet.has(childId)) {
setSelected(new Map(selected.set(parentId, new Set([...parentSet, childId]))));
return;
Expand All @@ -816,9 +812,9 @@ const SpaceHierarchy: React.FC<IProps> = ({ space, initialText = "", showRoom, a
} else {
const hasPermissions =
space?.getMyMembership() === "join" &&
space.currentState.maySendStateEvent(EventType.SpaceChild, cli.getUserId());
space.currentState.maySendStateEvent(EventType.SpaceChild, cli.getSafeUserId());

let results: JSX.Element;
let results: JSX.Element | undefined;
if (filteredRoomSet.size) {
results = (
<>
Expand All @@ -843,7 +839,7 @@ const SpaceHierarchy: React.FC<IProps> = ({ space, initialText = "", showRoom, a
);
}

let loader: JSX.Element;
let loader: JSX.Element | undefined;
if (hierarchy.canLoadMore) {
loader = (
<div ref={loaderRef}>
Expand Down
12 changes: 6 additions & 6 deletions src/components/views/dialogs/BugReportDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ interface IProps {
interface IState {
sendLogs: boolean;
busy: boolean;
err: string;
err: string | null;
issueUrl: string;
text: string;
progress: string;
progress: string | null;
downloadBusy: boolean;
downloadProgress: string;
downloadProgress: string | null;
}

export default class BugReportDialog extends React.Component<IProps, IState> {
Expand Down Expand Up @@ -181,12 +181,12 @@ export default class BugReportDialog extends React.Component<IProps, IState> {
};

public render(): React.ReactNode {
let error = null;
let error: JSX.Element | undefined;
if (this.state.err) {
error = <div className="error">{this.state.err}</div>;
}

let progress = null;
let progress: JSX.Element | undefined;
if (this.state.busy) {
progress = (
<div className="progress">
Expand All @@ -196,7 +196,7 @@ export default class BugReportDialog extends React.Component<IProps, IState> {
);
}

let warning;
let warning: JSX.Element | undefined;
if (window.Modernizr && Object.values(window.Modernizr).some((support) => support === false)) {
warning = (
<p>
Expand Down
Loading

0 comments on commit 8cb8cd4

Please sign in to comment.