Conform more of the codebase with strictNullChecks
(#10703)
This commit is contained in:
parent
db40479910
commit
619a9e8542
24 changed files with 108 additions and 77 deletions
|
@ -69,7 +69,7 @@ export default class CountryDropdown extends React.Component<IProps, IState> {
|
|||
const locale = new Intl.Locale(navigator.language ?? navigator.languages[0]);
|
||||
const code = locale.region ?? locale.language ?? locale.baseName;
|
||||
const displayNames = new Intl.DisplayNames(["en"], { type: "region" });
|
||||
const displayName = displayNames.of(code).toUpperCase();
|
||||
const displayName = displayNames.of(code)?.toUpperCase();
|
||||
defaultCountry = COUNTRIES.find(
|
||||
(c) => c.iso2 === code.toUpperCase() || c.name.toUpperCase() === displayName,
|
||||
);
|
||||
|
|
|
@ -49,7 +49,7 @@ export default class ServerPickerDialog extends React.PureComponent<IProps, ISta
|
|||
super(props);
|
||||
|
||||
const config = SdkConfig.get();
|
||||
this.defaultServer = config["validated_server_config"];
|
||||
this.defaultServer = config["validated_server_config"]!;
|
||||
const { serverConfig } = this.props;
|
||||
|
||||
let otherHomeserver = "";
|
||||
|
@ -152,11 +152,11 @@ export default class ServerPickerDialog extends React.PureComponent<IProps, ISta
|
|||
private onSubmit = async (ev: SyntheticEvent): Promise<void> => {
|
||||
ev.preventDefault();
|
||||
|
||||
const valid = await this.fieldRef.current.validate({ allowEmpty: false });
|
||||
const valid = await this.fieldRef.current?.validate({ allowEmpty: false });
|
||||
|
||||
if (!valid && !this.state.defaultChosen) {
|
||||
this.fieldRef.current.focus();
|
||||
this.fieldRef.current.validate({ allowEmpty: false, focused: true });
|
||||
this.fieldRef.current?.focus();
|
||||
this.fieldRef.current?.validate({ allowEmpty: false, focused: true });
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -1089,7 +1089,7 @@ const SpotlightDialog: React.FC<IProps> = ({ initialText = "", initialFilter = n
|
|||
ev.stopPropagation();
|
||||
ev.preventDefault();
|
||||
|
||||
if (rovingContext.state.refs.length > 0) {
|
||||
if (rovingContext.state.activeRef && rovingContext.state.refs.length > 0) {
|
||||
let refs = rovingContext.state.refs;
|
||||
if (!query && !filter !== null) {
|
||||
// If the current selection is not in the recently viewed row then only include the
|
||||
|
@ -1112,6 +1112,7 @@ const SpotlightDialog: React.FC<IProps> = ({ initialText = "", initialFilter = n
|
|||
if (
|
||||
!query &&
|
||||
!filter !== null &&
|
||||
rovingContext.state.activeRef &&
|
||||
rovingContext.state.refs.length > 0 &&
|
||||
refIsForRecentlyViewed(rovingContext.state.activeRef)
|
||||
) {
|
||||
|
|
|
@ -25,7 +25,7 @@ import AccessibleTooltipButton from "./AccessibleTooltipButton";
|
|||
|
||||
interface IProps {
|
||||
children?: React.ReactNode;
|
||||
getTextToCopy: () => string;
|
||||
getTextToCopy: () => string | null;
|
||||
border?: boolean;
|
||||
className?: string;
|
||||
}
|
||||
|
@ -35,7 +35,8 @@ const CopyableText: React.FC<IProps> = ({ children, getTextToCopy, border = true
|
|||
|
||||
const onCopyClickInternal = async (e: ButtonEvent): Promise<void> => {
|
||||
e.preventDefault();
|
||||
const successful = await copyPlaintext(getTextToCopy());
|
||||
const text = getTextToCopy();
|
||||
const successful = !!text && (await copyPlaintext(text));
|
||||
setTooltip(successful ? _t("Copied!") : _t("Failed to copy"));
|
||||
};
|
||||
|
||||
|
|
|
@ -162,9 +162,9 @@ class EmojiPicker extends React.Component<IProps, IState> {
|
|||
};
|
||||
|
||||
private keyboardNavigation(ev: React.KeyboardEvent, state: RovingState, dispatch: Dispatch<RovingAction>): void {
|
||||
const node = state.activeRef.current;
|
||||
const parent = node.parentElement;
|
||||
if (!parent) return;
|
||||
const node = state.activeRef?.current;
|
||||
const parent = node?.parentElement;
|
||||
if (!parent || !state.activeRef) return;
|
||||
const rowIndex = Array.from(parent.children).indexOf(node);
|
||||
const refIndex = state.refs.indexOf(state.activeRef);
|
||||
|
||||
|
@ -173,12 +173,12 @@ class EmojiPicker extends React.Component<IProps, IState> {
|
|||
switch (ev.key) {
|
||||
case Key.ARROW_LEFT:
|
||||
focusRef = state.refs[refIndex - 1];
|
||||
newParent = focusRef?.current?.parentElement;
|
||||
newParent = focusRef?.current?.parentElement ?? undefined;
|
||||
break;
|
||||
|
||||
case Key.ARROW_RIGHT:
|
||||
focusRef = state.refs[refIndex + 1];
|
||||
newParent = focusRef?.current?.parentElement;
|
||||
newParent = focusRef?.current?.parentElement ?? undefined;
|
||||
break;
|
||||
|
||||
case Key.ARROW_UP:
|
||||
|
@ -188,7 +188,7 @@ class EmojiPicker extends React.Component<IProps, IState> {
|
|||
ev.key === Key.ARROW_UP
|
||||
? state.refs[refIndex - rowIndex - 1]
|
||||
: state.refs[refIndex - rowIndex + EMOJIS_PER_ROW];
|
||||
newParent = ref?.current?.parentElement;
|
||||
newParent = ref?.current?.parentElement ?? undefined;
|
||||
const newTarget = newParent?.children[clamp(rowIndex, 0, newParent.children.length - 1)];
|
||||
focusRef = state.refs.find((r) => r.current === newTarget);
|
||||
break;
|
||||
|
|
|
@ -386,8 +386,8 @@ class EditMessageComposer extends React.Component<IEditMessageComposerProps, ISt
|
|||
// in case we're currently editing a pending event
|
||||
const sel = document.getSelection()!;
|
||||
let caret: DocumentOffset | undefined;
|
||||
if (sel.focusNode) {
|
||||
caret = getCaretOffsetAndText(this.editorRef.current?.editorRef.current, sel).caret;
|
||||
if (sel.focusNode && this.editorRef.current?.editorRef.current) {
|
||||
caret = getCaretOffsetAndText(this.editorRef.current.editorRef.current, sel).caret;
|
||||
}
|
||||
const parts = this.model.serializeParts();
|
||||
// if caret is undefined because for some reason there isn't a valid selection,
|
||||
|
@ -458,12 +458,15 @@ class EditMessageComposer extends React.Component<IEditMessageComposerProps, ISt
|
|||
};
|
||||
|
||||
public render(): React.ReactNode {
|
||||
const room = this.getRoom();
|
||||
if (!room) return null;
|
||||
|
||||
return (
|
||||
<div className={classNames("mx_EditMessageComposer", this.props.className)} onKeyDown={this.onKeyDown}>
|
||||
<BasicMessageComposer
|
||||
ref={this.editorRef}
|
||||
model={this.model}
|
||||
room={this.getRoom()}
|
||||
room={room}
|
||||
threadId={this.props.editState?.getEvent()?.getThread()?.id}
|
||||
initialCaret={this.props.editState.getCaret() ?? undefined}
|
||||
label={_t("Edit message")}
|
||||
|
|
|
@ -16,7 +16,7 @@ limitations under the License.
|
|||
|
||||
import { EventType, RoomType } from "matrix-js-sdk/src/@types/event";
|
||||
import { Room } from "matrix-js-sdk/src/models/room";
|
||||
import React, { ComponentType, createRef, ReactComponentElement, RefObject, SyntheticEvent } from "react";
|
||||
import React, { ComponentType, createRef, ReactComponentElement, SyntheticEvent } from "react";
|
||||
|
||||
import { IState as IRovingTabIndexState, RovingTabIndexProvider } from "../../../accessibility/RovingTabIndex";
|
||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||
|
@ -106,8 +106,8 @@ type TagAestheticsMap = Partial<{
|
|||
[tagId in TagID]: ITagAesthetics;
|
||||
}>;
|
||||
|
||||
const auxButtonContextMenuPosition = (handle: RefObject<HTMLDivElement>): MenuProps => {
|
||||
const rect = handle.current.getBoundingClientRect();
|
||||
const auxButtonContextMenuPosition = (handle: HTMLDivElement): MenuProps => {
|
||||
const rect = handle.getBoundingClientRect();
|
||||
return {
|
||||
chevronFace: ChevronFace.None,
|
||||
left: rect.left - 7,
|
||||
|
@ -126,11 +126,11 @@ const DmAuxButton: React.FC<IAuxButtonProps> = ({ tabIndex, dispatcher = default
|
|||
|
||||
if (activeSpace && (showCreateRooms || showInviteUsers)) {
|
||||
let contextMenu: JSX.Element | undefined;
|
||||
if (menuDisplayed) {
|
||||
if (menuDisplayed && handle.current) {
|
||||
const canInvite = shouldShowSpaceInvite(activeSpace);
|
||||
|
||||
contextMenu = (
|
||||
<IconizedContextMenu {...auxButtonContextMenuPosition(handle)} onFinished={closeMenu} compact>
|
||||
<IconizedContextMenu {...auxButtonContextMenuPosition(handle.current)} onFinished={closeMenu} compact>
|
||||
<IconizedContextMenuOptionList first>
|
||||
{showCreateRooms && (
|
||||
<IconizedContextMenuOption
|
||||
|
@ -357,9 +357,9 @@ const UntaggedAuxButton: React.FC<IAuxButtonProps> = ({ tabIndex }) => {
|
|||
}
|
||||
|
||||
let contextMenu: JSX.Element | null = null;
|
||||
if (menuDisplayed) {
|
||||
if (menuDisplayed && handle.current) {
|
||||
contextMenu = (
|
||||
<IconizedContextMenu {...auxButtonContextMenuPosition(handle)} onFinished={closeMenu} compact>
|
||||
<IconizedContextMenu {...auxButtonContextMenuPosition(handle.current)} onFinished={closeMenu} compact>
|
||||
{contextMenuContent}
|
||||
</IconizedContextMenu>
|
||||
);
|
||||
|
@ -491,6 +491,7 @@ export default class RoomList extends React.PureComponent<IProps, IState> {
|
|||
if (payload.action === Action.ViewRoomDelta) {
|
||||
const viewRoomDeltaPayload = payload as ViewRoomDeltaPayload;
|
||||
const currentRoomId = SdkContextClass.instance.roomViewStore.getRoomId();
|
||||
if (!currentRoomId) return;
|
||||
const room = this.getRoomDelta(currentRoomId, viewRoomDeltaPayload.delta, viewRoomDeltaPayload.unread);
|
||||
if (room) {
|
||||
defaultDispatcher.dispatch<ViewRoomPayload>({
|
||||
|
|
|
@ -207,7 +207,8 @@ export class RoomTile extends React.PureComponent<ClassProps, State> {
|
|||
return;
|
||||
}
|
||||
|
||||
const messagePreview = await MessagePreviewStore.instance.getPreviewForRoom(this.props.room, this.props.tag);
|
||||
const messagePreview =
|
||||
(await MessagePreviewStore.instance.getPreviewForRoom(this.props.room, this.props.tag)) ?? undefined;
|
||||
this.setState({ messagePreview });
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ export function usePlainTextListeners(
|
|||
onChange?: (content: string) => void,
|
||||
onSend?: () => void,
|
||||
): {
|
||||
ref: RefObject<HTMLDivElement | null>;
|
||||
ref: RefObject<HTMLDivElement>;
|
||||
content?: string;
|
||||
onInput(event: SyntheticEvent<HTMLDivElement, InputEvent | ClipboardEvent>): void;
|
||||
onPaste(event: SyntheticEvent<HTMLDivElement, InputEvent | ClipboardEvent>): void;
|
||||
|
|
|
@ -295,7 +295,7 @@ export default class SecureBackupPanel extends React.PureComponent<{}, IState> {
|
|||
const verify = (sub: string): JSX.Element => (
|
||||
<span
|
||||
className={
|
||||
sig.device && sig.deviceTrust.isVerified()
|
||||
sig.device && sig.deviceTrust?.isVerified()
|
||||
? "mx_SecureBackupPanel_deviceVerified"
|
||||
: "mx_SecureBackupPanel_deviceNotVerified"
|
||||
}
|
||||
|
@ -347,7 +347,7 @@ export default class SecureBackupPanel extends React.PureComponent<{}, IState> {
|
|||
{},
|
||||
{ validity },
|
||||
);
|
||||
} 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>verified</verify> session <device></device>",
|
||||
|
@ -361,7 +361,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>verified</verify> session <device></device>",
|
||||
|
|
|
@ -67,7 +67,7 @@ export default class LabsUserSettingsTab extends React.Component<{}> {
|
|||
const groups = new EnhancedMap<LabGroup, JSX.Element[]>();
|
||||
this.labs.forEach((f) => {
|
||||
groups
|
||||
.getOrCreate(SettingsStore.getLabGroup(f), [])
|
||||
.getOrCreate(SettingsStore.getLabGroup(f)!, [])
|
||||
.push(<SettingsFlag level={SettingLevel.DEVICE} name={f} key={f} />);
|
||||
});
|
||||
|
||||
|
|
|
@ -68,14 +68,14 @@ const QuickSettingsButton: React.FC<{
|
|||
{_t("All settings")}
|
||||
</AccessibleButton>
|
||||
|
||||
{SettingsStore.getValue("developerMode") && (
|
||||
{SettingsStore.getValue("developerMode") && SdkContextClass.instance.roomViewStore.getRoomId() && (
|
||||
<AccessibleButton
|
||||
onClick={() => {
|
||||
closeMenu();
|
||||
Modal.createDialog(
|
||||
DevtoolsDialog,
|
||||
{
|
||||
roomId: SdkContextClass.instance.roomViewStore.getRoomId(),
|
||||
roomId: SdkContextClass.instance.roomViewStore.getRoomId()!,
|
||||
},
|
||||
"mx_DevtoolsDialog_wrapper",
|
||||
);
|
||||
|
|
|
@ -122,7 +122,7 @@ export const SpaceButton = forwardRef<HTMLElement, IButtonProps>(
|
|||
}
|
||||
|
||||
let contextMenu: JSX.Element | undefined;
|
||||
if (menuDisplayed && handle.current && ContextMenuComponent) {
|
||||
if (space && menuDisplayed && handle.current && ContextMenuComponent) {
|
||||
contextMenu = (
|
||||
<ContextMenuComponent
|
||||
{...toRightOf(handle.current.getBoundingClientRect(), 0)}
|
||||
|
|
|
@ -74,10 +74,12 @@ export default class VerificationRequestToast extends React.PureComponent<IProps
|
|||
|
||||
if (request.isSelfVerification) {
|
||||
const cli = MatrixClientPeg.get();
|
||||
const device = await cli.getDevice(request.channel.deviceId);
|
||||
const ip = device.last_seen_ip;
|
||||
const device = request.channel.deviceId ? await cli.getDevice(request.channel.deviceId) : null;
|
||||
const ip = device?.last_seen_ip;
|
||||
this.setState({
|
||||
device: cli.getStoredDevice(cli.getUserId()!, request.channel.deviceId) ?? undefined,
|
||||
device:
|
||||
(request.channel.deviceId && cli.getStoredDevice(cli.getSafeUserId(), request.channel.deviceId)) ||
|
||||
undefined,
|
||||
ip,
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue