From 8cb8cd4eb1b06832ebc0930d50cebae8fde6b604 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Tue, 14 Mar 2023 11:09:35 +0000
Subject: [PATCH] Conform more code to `strictNullChecks` (#10368
* Conform more code to `strictNullChecks`
* Iterate
---
src/Modal.tsx | 13 +++-
src/components/structures/RoomView.tsx | 38 ++++++------
src/components/structures/SpaceHierarchy.tsx | 62 +++++++++----------
.../views/dialogs/BugReportDialog.tsx | 12 ++--
.../views/dialogs/CreateRoomDialog.tsx | 25 ++++----
.../views/dialogs/CreateSubspaceDialog.tsx | 6 +-
src/components/views/dialogs/ExportDialog.tsx | 4 +-
src/components/views/dialogs/LogoutDialog.tsx | 2 +-
.../views/dialogs/ModalWidgetDialog.tsx | 22 ++++---
.../views/dialogs/ReportEventDialog.tsx | 20 +++---
.../dialogs/RoomUpgradeWarningDialog.tsx | 30 ++++++---
.../dialogs/SlidingSyncOptionsDialog.tsx | 4 +-
.../views/dialogs/TextInputDialog.tsx | 17 ++---
.../views/dialogs/UploadConfirmDialog.tsx | 11 ++--
.../security/RestoreKeyBackupDialog.tsx | 16 ++---
.../dialogs/spotlight/SpotlightDialog.tsx | 2 +-
src/components/views/right_panel/UserInfo.tsx | 31 +++++-----
.../views/spaces/SpaceBasicSettings.tsx | 2 +-
src/customisations/ChatExport.ts | 2 +-
src/i18n/strings/en_EN.json | 2 +-
src/rageshake/submit-rageshake.ts | 2 +-
src/sentry.ts | 2 +-
src/utils/pillify.tsx | 4 +-
.../views/right_panel/UserInfo-test.tsx | 4 +-
24 files changed, 176 insertions(+), 157 deletions(-)
diff --git a/src/Modal.tsx b/src/Modal.tsx
index 54ae185ad1..b3887795b2 100644
--- a/src/Modal.tsx
+++ b/src/Modal.tsx
@@ -32,8 +32,19 @@ export type ComponentType = React.ComponentType<{
onFinished?(...args: any): void;
}>;
+type Defaultize
= P extends any
+ ? string extends keyof P
+ ? P
+ : Pick
> &
+ Partial>> &
+ Partial>>
+ : never;
+
// Generic type which returns the props of the Modal component with the onFinished being optional.
-export type ComponentProps = Omit, "onFinished"> &
+export type ComponentProps = Defaultize<
+ Omit, "onFinished">,
+ C["defaultProps"]
+> &
Partial, "onFinished">>;
export interface IModal {
diff --git a/src/components/structures/RoomView.tsx b/src/components/structures/RoomView.tsx
index 451e893b11..bc533a137f 100644
--- a/src/components/structures/RoomView.tsx
+++ b/src/components/structures/RoomView.tsx
@@ -1020,7 +1020,7 @@ export class RoomView extends React.Component {
});
};
- 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") {
@@ -1034,7 +1034,7 @@ export class RoomView extends React.Component {
const action = getKeyBindingsManager().getRoomAction(ev);
switch (action) {
case KeyBindingAction.DismissReadMarker:
- this.messagePanel.forgetReadMarker();
+ this.messagePanel?.forgetReadMarker();
this.jumpToLiveTimeline();
handled = true;
break;
@@ -1067,7 +1067,7 @@ export class RoomView extends React.Component {
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 => {
@@ -1087,7 +1087,7 @@ export class RoomView extends React.Component {
ContentMessages.sharedInstance().sendContentListToRoom(
[payload.file],
this.state.room.roomId,
- null,
+ undefined,
this.context.client,
);
break;
@@ -1117,7 +1117,7 @@ export class RoomView extends React.Component {
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
@@ -1137,7 +1137,7 @@ export class RoomView extends React.Component {
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());
@@ -1194,7 +1194,7 @@ export class RoomView extends React.Component {
private onRoomTimeline = (
ev: MatrixEvent,
- room: Room | null,
+ room: Room | undefined,
toStartOfTimeline: boolean,
removed: boolean,
data?: IRoomTimelineData,
@@ -1228,7 +1228,7 @@ export class RoomView extends React.Component {
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
@@ -1325,7 +1325,7 @@ export class RoomView extends React.Component {
};
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 {
@@ -1336,7 +1336,7 @@ export class RoomView extends React.Component {
private async loadMembersIfJoined(room: Room): Promise {
// lazy load members if enabled
- if (this.context.client.hasLazyLoadMembersEnabled()) {
+ if (this.context.client?.hasLazyLoadMembersEnabled()) {
if (room && room.getMyMembership() === "join") {
try {
await room.loadMembersIfNeeded();
@@ -1415,7 +1415,7 @@ export class RoomView extends React.Component {
};
private async updateE2EStatus(room: Room): Promise {
- 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
@@ -2093,7 +2093,7 @@ export class RoomView extends React.Component {
// 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();
@@ -2102,7 +2102,7 @@ export class RoomView extends React.Component {
}
}
- let statusBar;
+ let statusBar: JSX.Element | undefined;
let isStatusAreaExpanded = true;
if (ContentMessages.sharedInstance().getCurrentUploads().length > 0) {
@@ -2301,7 +2301,7 @@ export class RoomView extends React.Component {
/>
);
- 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 = (
@@ -2342,7 +2342,7 @@ export class RoomView extends React.Component {
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) {
@@ -2396,10 +2396,10 @@ export class RoomView extends React.Component {
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
diff --git a/src/components/structures/SpaceHierarchy.tsx b/src/components/structures/SpaceHierarchy.tsx
index a0558413dd..e0d124af0c 100644
--- a/src/components/structures/SpaceHierarchy.tsx
+++ b/src/components/structures/SpaceHierarchy.tsx
@@ -100,9 +100,9 @@ const Tile: React.FC = ({
children,
}) => {
const cli = useContext(MatrixClientContext);
- const [joinedRoom, setJoinedRoom] = useState(() => {
+ const [joinedRoom, setJoinedRoom] = useState(() => {
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 =
@@ -264,9 +264,9 @@ const Tile: React.FC = ({
);
- 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 = (
@@ -386,7 +386,7 @@ export const showRoom = (cli: MatrixClient, hierarchy: RoomHierarchy, roomId: st
});
};
-export const joinRoom = (cli: MatrixClient, hierarchy: RoomHierarchy, roomId: string): Promise => {
+export const joinRoom = async (cli: MatrixClient, hierarchy: RoomHierarchy, roomId: string): Promise => {
// 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()) {
@@ -394,24 +394,20 @@ export const joinRoom = (cli: MatrixClient, hierarchy: RoomHierarchy, roomId: st
return;
}
- const prom = cli.joinRoom(roomId, {
- viaServers: Array.from(hierarchy.viaMap.get(roomId) || []),
+ try {
+ await cli.joinRoom(roomId, {
+ viaServers: Array.from(hierarchy.viaMap.get(roomId) || []),
+ });
+ } catch (err) {
+ SdkContextClass.instance.roomViewStore.showJoinRoomError(err, roomId);
+ return;
+ }
+
+ defaultDispatcher.dispatch({
+ action: Action.JoinRoomReady,
+ roomId,
+ metricsTrigger: "SpaceHierarchy",
});
-
- prom.then(
- () => {
- defaultDispatcher.dispatch({
- action: Action.JoinRoomReady,
- roomId,
- metricsTrigger: "SpaceHierarchy",
- });
- },
- (err) => {
- SdkContextClass.instance.roomViewStore.showJoinRoomError(err, roomId);
- },
- );
-
- return prom;
};
interface IHierarchyLevelProps {
@@ -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];
@@ -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:
@@ -476,7 +472,7 @@ export const HierarchyLevel: React.FC = ({
}) => {
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);
@@ -579,7 +575,7 @@ export const useRoomHierarchy = (
const loadMore = useCallback(
async (pageSize?: number): Promise => {
- 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);
},
@@ -673,7 +669,7 @@ const ManageButtons: React.FC = ({ hierarchy, selected, set
onClick={async (): Promise => {
setRemoving(true);
try {
- const userId = cli.getUserId();
+ const userId = cli.getSafeUserId();
for (const [parentId, childId] of selectedRelations) {
await cli.sendStateEvent(parentId, EventType.SpaceChild, {}, childId);
@@ -759,7 +755,7 @@ const SpaceHierarchy: React.FC = ({ space, initialText = "", showRoom, a
const visited = new Set();
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)) {
@@ -797,7 +793,7 @@ const SpaceHierarchy: React.FC = ({ 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;
@@ -816,9 +812,9 @@ const SpaceHierarchy: React.FC = ({ 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 = (
<>
@@ -843,7 +839,7 @@ const SpaceHierarchy: React.FC = ({ space, initialText = "", showRoom, a
);
}
- let loader: JSX.Element;
+ let loader: JSX.Element | undefined;
if (hierarchy.canLoadMore) {
loader = (
diff --git a/src/components/views/dialogs/BugReportDialog.tsx b/src/components/views/dialogs/BugReportDialog.tsx
index 4074db6d3e..319f7db817 100644
--- a/src/components/views/dialogs/BugReportDialog.tsx
+++ b/src/components/views/dialogs/BugReportDialog.tsx
@@ -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
{
@@ -181,12 +181,12 @@ export default class BugReportDialog extends React.Component {
};
public render(): React.ReactNode {
- let error = null;
+ let error: JSX.Element | undefined;
if (this.state.err) {
error = {this.state.err}
;
}
- let progress = null;
+ let progress: JSX.Element | undefined;
if (this.state.busy) {
progress = (
@@ -196,7 +196,7 @@ export default class BugReportDialog extends React.Component
{
);
}
- let warning;
+ let warning: JSX.Element | undefined;
if (window.Modernizr && Object.values(window.Modernizr).some((support) => support === false)) {
warning = (
diff --git a/src/components/views/dialogs/CreateRoomDialog.tsx b/src/components/views/dialogs/CreateRoomDialog.tsx
index b15fb800d2..1d91330023 100644
--- a/src/components/views/dialogs/CreateRoomDialog.tsx
+++ b/src/components/views/dialogs/CreateRoomDialog.tsx
@@ -126,7 +126,7 @@ export default class CreateRoomDialog extends React.Component {
public componentDidMount(): void {
// move focus to first field when showing dialog
- this.nameField.current.focus();
+ this.nameField.current?.focus();
}
private onKeyDown = (event: KeyboardEvent): void => {
@@ -141,10 +141,9 @@ export default class CreateRoomDialog extends React.Component {
};
private onOk = async (): Promise => {
+ if (!this.nameField.current) return;
const activeElement = document.activeElement as HTMLElement;
- if (activeElement) {
- activeElement.blur();
- }
+ activeElement?.blur();
await this.nameField.current.validate({ allowEmpty: false });
if (this.aliasField.current) {
await this.aliasField.current.validate({ allowEmpty: false });
@@ -155,7 +154,7 @@ export default class CreateRoomDialog extends React.Component {
if (this.state.nameIsValid && (!this.aliasField.current || this.aliasField.current.isValid)) {
this.props.onFinished(true, this.roomCreateOptions());
} else {
- let field;
+ let field: RoomAliasField | Field | null = null;
if (!this.state.nameIsValid) {
field = this.nameField.current;
} else if (this.aliasField.current && !this.aliasField.current.isValid) {
@@ -163,7 +162,7 @@ export default class CreateRoomDialog extends React.Component {
}
if (field) {
field.focus();
- field.validate({ allowEmpty: false, focused: true });
+ await field.validate({ allowEmpty: false, focused: true });
}
}
};
@@ -202,7 +201,7 @@ export default class CreateRoomDialog extends React.Component {
private onNameValidate = async (fieldState: IFieldState): Promise => {
const result = await CreateRoomDialog.validateRoomName(fieldState);
- this.setState({ nameIsValid: result.valid });
+ this.setState({ nameIsValid: !!result.valid });
return result;
};
@@ -219,9 +218,9 @@ export default class CreateRoomDialog extends React.Component {
public render(): React.ReactNode {
const isVideoRoom = this.props.type === RoomType.ElementVideo;
- let aliasField: JSX.Element;
+ let aliasField: JSX.Element | undefined;
if (this.state.joinRule === JoinRule.Public) {
- const domain = MatrixClientPeg.get().getDomain();
+ const domain = MatrixClientPeg.get().getDomain()!;
aliasField = (
{
);
}
- let publicPrivateLabel: JSX.Element;
+ let publicPrivateLabel: JSX.Element | undefined;
if (this.state.joinRule === JoinRule.Restricted) {
publicPrivateLabel = (
@@ -242,7 +241,7 @@ export default class CreateRoomDialog extends React.Component {
"Everyone in will be able to find and join this room.",
{},
{
- SpaceName: () => {this.props.parentSpace.name},
+ SpaceName: () => {this.props.parentSpace?.name ?? _t("Unnamed Space")},
},
)}
@@ -256,7 +255,7 @@ export default class CreateRoomDialog extends React.Component {
"Anyone will be able to find and join this room, not just members of .",
{},
{
- SpaceName: () => {this.props.parentSpace.name},
+ SpaceName: () => {this.props.parentSpace?.name ?? _t("Unnamed Space")},
},
)}
@@ -281,7 +280,7 @@ export default class CreateRoomDialog extends React.Component {
);
}
- let e2eeSection: JSX.Element;
+ let e2eeSection: JSX.Element | undefined;
if (this.state.joinRule !== JoinRule.Public) {
let microcopy: string;
if (privateShouldBeEncrypted()) {
diff --git a/src/components/views/dialogs/CreateSubspaceDialog.tsx b/src/components/views/dialogs/CreateSubspaceDialog.tsx
index 5e01396daf..4c12587ade 100644
--- a/src/components/views/dialogs/CreateSubspaceDialog.tsx
+++ b/src/components/views/dialogs/CreateSubspaceDialog.tsx
@@ -44,7 +44,7 @@ const CreateSubspaceDialog: React.FC = ({ space, onAddExistingSpaceClick
const spaceNameField = useRef();
const [alias, setAlias] = useState("");
const spaceAliasField = useRef();
- const [avatar, setAvatar] = useState(null);
+ const [avatar, setAvatar] = useState();
const [topic, setTopic] = useState("");
const spaceJoinRule = space.getJoinRule();
@@ -56,7 +56,7 @@ const CreateSubspaceDialog: React.FC = ({ space, onAddExistingSpaceClick
const onCreateSubspaceClick = async (e: ButtonEvent): Promise => {
e.preventDefault();
- if (busy) return;
+ if (busy || !spaceNameField.current || !spaceAliasField.current) return;
setBusy(true);
// require & validate the space name field
@@ -83,7 +83,7 @@ const CreateSubspaceDialog: React.FC = ({ space, onAddExistingSpaceClick
}
};
- let joinRuleMicrocopy: JSX.Element;
+ let joinRuleMicrocopy: JSX.Element | undefined;
if (joinRule === JoinRule.Restricted) {
joinRuleMicrocopy = (
diff --git a/src/components/views/dialogs/ExportDialog.tsx b/src/components/views/dialogs/ExportDialog.tsx
index 84afb0a4cc..9ae9272a9b 100644
--- a/src/components/views/dialogs/ExportDialog.tsx
+++ b/src/components/views/dialogs/ExportDialog.tsx
@@ -73,7 +73,7 @@ const useExportFormState = (): ExportConfig => {
const [exportType, setExportType] = useState(config.range ?? ExportType.Timeline);
const [includeAttachments, setAttachments] = useState(config.includeAttachments ?? false);
const [numberOfMessages, setNumberOfMessages] = useState(config.numberOfMessages ?? 100);
- const [sizeLimit, setSizeLimit] = useState(config.sizeMb ?? 8);
+ const [sizeLimit, setSizeLimit] = useState(config.sizeMb ?? 8);
return {
exportFormat,
@@ -260,7 +260,7 @@ const ExportDialog: React.FC = ({ room, onFinished }) => {
);
});
- let messageCount = null;
+ let messageCount: JSX.Element | undefined;
if (exportType === ExportType.LastNMessages && setNumberOfMessages) {
messageCount = (
{
dis.dispatch({ action: "logout" });
}
// close dialog
- this.props.onFinished(confirmed);
+ this.props.onFinished(!!confirmed);
};
private onSetRecoveryMethodClick = (): void => {
diff --git a/src/components/views/dialogs/ModalWidgetDialog.tsx b/src/components/views/dialogs/ModalWidgetDialog.tsx
index e62e8b53f8..7a73d25d23 100644
--- a/src/components/views/dialogs/ModalWidgetDialog.tsx
+++ b/src/components/views/dialogs/ModalWidgetDialog.tsx
@@ -70,7 +70,7 @@ export default class ModalWidgetDialog extends React.PureComponent b.id);
@@ -78,21 +78,23 @@ export default class ModalWidgetDialog extends React.PureComponent {
- this.state.messaging.sendWidgetConfig(this.props.widgetDefinition);
+ this.state.messaging?.sendWidgetConfig(this.props.widgetDefinition);
};
private onLoad = (): void => {
+ if (!this.state.messaging) return;
this.state.messaging.once("ready", this.onReady);
this.state.messaging.on(`action:${WidgetApiFromWidgetAction.CloseModalWidget}`, this.onWidgetClose);
this.state.messaging.on(`action:${WidgetApiFromWidgetAction.SetModalButtonEnabled}`, this.onButtonEnableToggle);
@@ -106,7 +108,7 @@ export default class ModalWidgetDialog extends React.PureComponent {
- this.state.messaging.notifyModalWidgetButtonClicked(def.id);
+ this.state.messaging?.notifyModalWidgetButtonClicked(def.id);
};
const isDisabled = this.state.disabledButtonIds.includes(def.id);
@@ -201,7 +203,7 @@ export default class ModalWidgetDialog extends React.PureComponent