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

Commit 605ef08

Browse files
authored
Conform more of the codebase to strictNullChecks (#10573)
* Conform more of the codebase to `strictNullChecks` * Iterate
1 parent b4d7f6b commit 605ef08

34 files changed

+119
-104
lines changed

src/ImageUtils.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,16 @@ limitations under the License.
2828
* consume in the timeline, when performing scroll offset calculations
2929
* (e.g. scroll locking)
3030
*/
31+
export function thumbHeight(fullWidth: number, fullHeight: number, thumbWidth: number, thumbHeight: number): number;
3132
export function thumbHeight(
32-
fullWidth: number,
33-
fullHeight: number,
33+
fullWidth: number | undefined,
34+
fullHeight: number | undefined,
35+
thumbWidth: number,
36+
thumbHeight: number,
37+
): null;
38+
export function thumbHeight(
39+
fullWidth: number | undefined,
40+
fullHeight: number | undefined,
3441
thumbWidth: number,
3542
thumbHeight: number,
3643
): number | null {

src/components/structures/AutoHideScrollbar.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ type DynamicHtmlElementProps<T extends keyof JSX.IntrinsicElements> =
2323
type DynamicElementProps<T extends keyof JSX.IntrinsicElements> = Partial<Omit<JSX.IntrinsicElements[T], "ref">>;
2424

2525
export type IProps<T extends keyof JSX.IntrinsicElements> = Omit<DynamicHtmlElementProps<T>, "onScroll"> & {
26-
element?: T;
26+
element: T;
2727
className?: string;
2828
onScroll?: (event: Event) => void;
2929
onWheel?: (event: WheelEvent) => void;

src/components/structures/IndicatorScrollbar.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ import React, { createRef } from "react";
1919
import AutoHideScrollbar, { IProps as AutoHideScrollbarProps } from "./AutoHideScrollbar";
2020
import UIStore, { UI_EVENTS } from "../../stores/UIStore";
2121

22-
export type IProps<T extends keyof JSX.IntrinsicElements> = Omit<AutoHideScrollbarProps<T>, "onWheel"> & {
22+
export type IProps<T extends keyof JSX.IntrinsicElements> = Omit<AutoHideScrollbarProps<T>, "onWheel" | "element"> & {
23+
element?: T;
2324
// If true, the scrollbar will append mx_IndicatorScrollbar_leftOverflowIndicator
2425
// and mx_IndicatorScrollbar_rightOverflowIndicator elements to the list for positioning
2526
// by the parent element.

src/components/structures/LeftPanel.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,13 @@ export default class LeftPanel extends React.Component<IProps, IState> {
9090
}
9191

9292
public componentDidMount(): void {
93-
UIStore.instance.trackElementDimensions("ListContainer", this.listContainerRef.current);
93+
if (this.listContainerRef.current) {
94+
UIStore.instance.trackElementDimensions("ListContainer", this.listContainerRef.current);
95+
// Using the passive option to not block the main thread
96+
// https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#improving_scrolling_performance_with_passive_listeners
97+
this.listContainerRef.current.addEventListener("scroll", this.onScroll, { passive: true });
98+
}
9499
UIStore.instance.on("ListContainer", this.refreshStickyHeaders);
95-
// Using the passive option to not block the main thread
96-
// https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#improving_scrolling_performance_with_passive_listeners
97-
this.listContainerRef.current?.addEventListener("scroll", this.onScroll, { passive: true });
98100
}
99101

100102
public componentWillUnmount(): void {

src/components/structures/LegacyCallEventGrouper.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,9 +177,9 @@ export default class LegacyCallEventGrouper extends EventEmitter {
177177
}
178178

179179
private setState = (): void => {
180-
if (CONNECTING_STATES.includes(this.call?.state)) {
180+
if (this.call && CONNECTING_STATES.includes(this.call.state)) {
181181
this.state = CallState.Connecting;
182-
} else if (SUPPORTED_STATES.includes(this.call?.state)) {
182+
} else if (this.call && SUPPORTED_STATES.includes(this.call.state)) {
183183
this.state = this.call.state;
184184
} else {
185185
if (this.callWasMissed) this.state = CustomCallState.Missed;

src/components/structures/MatrixChat.tsx

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -471,11 +471,9 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
471471
);
472472
}, 1000);
473473

474-
private getFallbackHsUrl(): string | null {
474+
private getFallbackHsUrl(): string | undefined {
475475
if (this.props.serverConfig?.isDefault) {
476-
return this.props.config.fallback_hs_url ?? null;
477-
} else {
478-
return null;
476+
return this.props.config.fallback_hs_url;
479477
}
480478
}
481479

@@ -577,7 +575,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
577575
if (payload.event_type === "m.identity_server") {
578576
const fullUrl = payload.event_content ? payload.event_content["base_url"] : null;
579577
if (!fullUrl) {
580-
MatrixClientPeg.get().setIdentityServerUrl(null);
578+
MatrixClientPeg.get().setIdentityServerUrl(undefined);
581579
localStorage.removeItem("mx_is_access_token");
582580
localStorage.removeItem("mx_is_url");
583581
} else {
@@ -1229,6 +1227,10 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
12291227
* @returns {string} The room ID of the new room, or null if no room was created
12301228
*/
12311229
private async startWelcomeUserChat(): Promise<string | null> {
1230+
const snakedConfig = new SnakedObject<IConfigOptions>(this.props.config);
1231+
const welcomeUserId = snakedConfig.get("welcome_user_id");
1232+
if (!welcomeUserId) return null;
1233+
12321234
// We can end up with multiple tabs post-registration where the user
12331235
// might then end up with a session and we don't want them all making
12341236
// a chat with the welcome user: try to de-dupe.
@@ -1242,8 +1244,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
12421244
}
12431245
await waitFor;
12441246

1245-
const snakedConfig = new SnakedObject<IConfigOptions>(this.props.config);
1246-
const welcomeUserRooms = DMRoomMap.shared().getDMRoomsForUserId(snakedConfig.get("welcome_user_id"));
1247+
const welcomeUserRooms = DMRoomMap.shared().getDMRoomsForUserId(welcomeUserId);
12471248
if (welcomeUserRooms.length === 0) {
12481249
const roomId = await createRoom({
12491250
dmUserId: snakedConfig.get("welcome_user_id"),
@@ -1260,7 +1261,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
12601261
// user room (it doesn't wait for new data from the server, just
12611262
// the saved sync to be loaded).
12621263
const saveWelcomeUser = (ev: MatrixEvent): void => {
1263-
if (ev.getType() === EventType.Direct && ev.getContent()[snakedConfig.get("welcome_user_id")]) {
1264+
if (ev.getType() === EventType.Direct && ev.getContent()[welcomeUserId]) {
12641265
MatrixClientPeg.get().store.save(true);
12651266
MatrixClientPeg.get().removeListener(ClientEvent.AccountData, saveWelcomeUser);
12661267
}

src/components/structures/MessagePanel.tsx

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -869,7 +869,7 @@ export default class MessagePanel extends React.Component<IProps, IState> {
869869
const receiptsByEvent: Map<string, IReadReceiptProps[]> = new Map();
870870
const receiptsByUserId: Map<string, IReadReceiptForUser> = new Map();
871871

872-
let lastShownEventId: string;
872+
let lastShownEventId: string | undefined;
873873
for (const event of this.props.events) {
874874
if (this.shouldShowEvent(event)) {
875875
lastShownEventId = event.getId();
@@ -1018,11 +1018,7 @@ export default class MessagePanel extends React.Component<IProps, IState> {
10181018
let ircResizer: JSX.Element | undefined;
10191019
if (this.props.layout == Layout.IRC) {
10201020
ircResizer = (
1021-
<IRCTimelineProfileResizer
1022-
minWidth={20}
1023-
maxWidth={600}
1024-
roomId={this.props.room ? this.props.room.roomId : null}
1025-
/>
1021+
<IRCTimelineProfileResizer minWidth={20} maxWidth={600} roomId={this.props.room?.roomId ?? null} />
10261022
);
10271023
}
10281024

@@ -1206,7 +1202,7 @@ class CreationGrouper extends BaseGrouper {
12061202
let summaryText: string;
12071203
const roomId = ev.getRoomId();
12081204
const creator = ev.sender?.name ?? ev.getSender();
1209-
if (DMRoomMap.shared().getUserIdForRoomId(roomId)) {
1205+
if (roomId && DMRoomMap.shared().getUserIdForRoomId(roomId)) {
12101206
summaryText = _t("%(creator)s created this DM.", { creator });
12111207
} else {
12121208
summaryText = _t("%(creator)s created and configured the room.", { creator });

src/components/structures/RightPanel.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ export default class RightPanel extends React.Component<IProps, IState> {
141141
// When the user clicks close on the encryption panel cancel the pending request first if any
142142
this.state.cardState.verificationRequest.cancel();
143143
} else {
144-
RightPanelStore.instance.togglePanel(this.props.room?.roomId);
144+
RightPanelStore.instance.togglePanel(this.props.room?.roomId ?? null);
145145
}
146146
};
147147

src/components/structures/RoomView.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1597,6 +1597,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
15971597
};
15981598

15991599
private injectSticker(url: string, info: object, text: string, threadId: string | null): void {
1600+
if (!this.context.client) return;
16001601
if (this.context.client.isGuest()) {
16011602
dis.dispatch({ action: "require_registration" });
16021603
return;

src/components/structures/ScrollPanel.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ export default class ScrollPanel extends React.Component<IProps> {
189189
// Is that next fill request scheduled because of a props update?
190190
private pendingFillDueToPropsUpdate: boolean;
191191
private scrollState: IScrollState;
192-
private preventShrinkingState: IPreventShrinkingState;
192+
private preventShrinkingState: IPreventShrinkingState | null;
193193
private unfillDebouncer: number | null;
194194
private bottomGrowth: number;
195195
private minListHeight: number;
@@ -676,7 +676,7 @@ export default class ScrollPanel extends React.Component<IProps> {
676676
debuglog("unable to save scroll state: found no children in the viewport");
677677
return;
678678
}
679-
const scrollToken = node!.dataset.scrollTokens.split(",")[0];
679+
const scrollToken = node!.dataset.scrollTokens?.split(",")[0];
680680
debuglog("saving anchored scroll state to message", scrollToken);
681681
const bottomOffset = this.topFromBottom(node);
682682
this.scrollState = {

src/components/structures/auth/Registration.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ const debuglog = (...args: any[]): void => {
5050

5151
interface IProps {
5252
serverConfig: ValidatedServerConfig;
53-
defaultDeviceDisplayName: string;
53+
defaultDeviceDisplayName?: string;
5454
email?: string;
5555
brand?: string;
5656
clientSecret?: string;

src/components/views/dialogs/ConfirmSpaceUserActionDialog.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ const ConfirmSpaceUserActionDialog: React.FC<IProps> = ({
5353
const [roomsToLeave, setRoomsToLeave] = useState<Room[]>([]);
5454
const selectedRooms = useMemo(() => new Set(roomsToLeave), [roomsToLeave]);
5555

56-
let warning: JSX.Element;
56+
let warning: JSX.Element | undefined;
5757
if (warningMessage) {
5858
warning = <div className="mx_ConfirmSpaceUserActionDialog_warning">{warningMessage}</div>;
5959
}

src/components/views/dialogs/CreateSubspaceDialog.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
import React, { useRef, useState } from "react";
17+
import React, { RefObject, useRef, useState } from "react";
1818
import { Room } from "matrix-js-sdk/src/models/room";
1919
import { JoinRule } from "matrix-js-sdk/src/@types/partials";
2020
import { logger } from "matrix-js-sdk/src/logger";
@@ -41,9 +41,9 @@ const CreateSubspaceDialog: React.FC<IProps> = ({ space, onAddExistingSpaceClick
4141

4242
const [busy, setBusy] = useState<boolean>(false);
4343
const [name, setName] = useState("");
44-
const spaceNameField = useRef<Field>();
44+
const spaceNameField = useRef() as RefObject<Field>;
4545
const [alias, setAlias] = useState("");
46-
const spaceAliasField = useRef<RoomAliasField>();
46+
const spaceAliasField = useRef() as RefObject<RoomAliasField>;
4747
const [avatar, setAvatar] = useState<File | undefined>();
4848
const [topic, setTopic] = useState<string>("");
4949

src/components/views/dialogs/ManageRestrictedJoinRuleDialog.tsx

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import AccessibleButton from "../elements/AccessibleButton";
2626
import AutoHideScrollbar from "../../structures/AutoHideScrollbar";
2727
import StyledCheckbox from "../elements/StyledCheckbox";
2828
import MatrixClientContext from "../../../contexts/MatrixClientContext";
29+
import { filterBoolean } from "../../../utils/arrays";
2930

3031
interface IProps {
3132
room: Room;
@@ -65,7 +66,7 @@ const Entry: React.FC<{
6566
)}
6667
</div>
6768
<StyledCheckbox
68-
onChange={onChange ? (e) => onChange(e.target.checked) : null}
69+
onChange={onChange ? (e) => onChange(e.target.checked) : undefined}
6970
checked={checked}
7071
disabled={!onChange}
7172
/>
@@ -80,7 +81,7 @@ const addAllParents = (set: Set<Room>, room: Room): void => {
8081
);
8182

8283
parents.forEach((parent) => {
83-
if (set.has(parent)) return;
84+
if (!parent || set.has(parent)) return;
8485
set.add(parent);
8586
addAllParents(set, parent);
8687
});
@@ -97,17 +98,17 @@ const ManageRestrictedJoinRuleDialog: React.FC<IProps> = ({ room, selected = [],
9798
addAllParents(parents, room);
9899
return [
99100
Array.from(parents),
100-
selected
101-
.map((roomId) => {
101+
filterBoolean(
102+
selected.map((roomId) => {
102103
const room = cli.getRoom(roomId);
103104
if (!room) {
104105
return { roomId, name: roomId } as Room;
105106
}
106107
if (room.getMyMembership() !== "join" || !room.isSpaceRoom()) {
107108
return room;
108109
}
109-
})
110-
.filter(Boolean),
110+
}),
111+
),
111112
];
112113
}, [cli, selected, room]);
113114

src/components/views/dialogs/RegistrationEmailPromptDialog.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ limitations under the License.
1515
*/
1616

1717
import * as React from "react";
18-
import { SyntheticEvent, useRef, useState } from "react";
18+
import { RefObject, SyntheticEvent, useRef, useState } from "react";
1919

2020
import { _t, _td } from "../../../languageHandler";
2121
import Field from "../elements/Field";
@@ -30,7 +30,7 @@ interface IProps {
3030

3131
const RegistrationEmailPromptDialog: React.FC<IProps> = ({ onFinished }) => {
3232
const [email, setEmail] = useState("");
33-
const fieldRef = useRef<Field>();
33+
const fieldRef = useRef() as RefObject<Field>;
3434

3535
const onSubmit = async (e: SyntheticEvent): Promise<void> => {
3636
e.preventDefault();

src/components/views/dialogs/spotlight/SpotlightDialog.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -288,8 +288,8 @@ interface IDirectoryOpts {
288288
}
289289

290290
const SpotlightDialog: React.FC<IProps> = ({ initialText = "", initialFilter = null, onFinished }) => {
291-
const inputRef = useRef<HTMLInputElement>();
292-
const scrollContainerRef = useRef<HTMLDivElement>();
291+
const inputRef = useRef() as RefObject<HTMLInputElement>;
292+
const scrollContainerRef = useRef() as RefObject<HTMLDivElement>;
293293
const cli = MatrixClientPeg.get();
294294
const rovingContext = useContext(RovingTabIndexContext);
295295
const [query, _setQuery] = useState(initialText);

src/components/views/elements/GenericEventListSummary.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ interface IProps {
3838
// The text to show as the summary of this event list
3939
"summaryText"?: ReactNode;
4040
// An array of EventTiles to render when expanded
41-
"children": ReactNode[];
41+
"children": ReactNode[] | null;
4242
// Called when the event list expansion is toggled
4343
onToggle?(): void;
4444
// The layout currently used

src/components/views/rooms/AppsDrawer.tsx

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,11 @@ interface IProps {
4545
}
4646

4747
interface IState {
48-
apps: Partial<{ [id in Container]: IApp[] }>;
48+
apps: {
49+
[Container.Top]: IApp[];
50+
[Container.Center]: IApp[];
51+
[Container.Right]?: IApp[];
52+
};
4953
resizingVertical: boolean; // true when changing the height of the apps drawer
5054
resizingHorizontal: boolean; // true when changing the distribution of the width between widgets
5155
resizing: boolean;
@@ -203,12 +207,10 @@ export default class AppsDrawer extends React.Component<IProps, IState> {
203207
}
204208
};
205209

206-
private getApps = (): Partial<{ [id in Container]: IApp[] }> => {
207-
const appsDict: Partial<{ [id in Container]: IApp[] }> = {};
208-
appsDict[Container.Top] = WidgetLayoutStore.instance.getContainerWidgets(this.props.room, Container.Top);
209-
appsDict[Container.Center] = WidgetLayoutStore.instance.getContainerWidgets(this.props.room, Container.Center);
210-
return appsDict;
211-
};
210+
private getApps = (): IState["apps"] => ({
211+
[Container.Top]: WidgetLayoutStore.instance.getContainerWidgets(this.props.room, Container.Top),
212+
[Container.Center]: WidgetLayoutStore.instance.getContainerWidgets(this.props.room, Container.Center),
213+
});
212214
private topApps = (): IApp[] => this.state.apps[Container.Top];
213215
private centerApps = (): IApp[] => this.state.apps[Container.Center];
214216

@@ -348,7 +350,7 @@ const PersistentVResizer: React.FC<IPersistentResizerProps> = ({
348350
resizeNotifier.notifyTimelineHeightChanged();
349351
}}
350352
onResizeStop={(e, dir, ref, d) => {
351-
let newHeight = defaultHeight + d.height;
353+
let newHeight = defaultHeight! + d.height;
352354
newHeight = percentageOf(newHeight, minHeight, maxHeight) * 100;
353355

354356
WidgetLayoutStore.instance.setContainerHeight(room, Container.Top, newHeight);

0 commit comments

Comments
 (0)