mirror of https://github.com/vector-im/riot-web
Apply `strictNullChecks` to `src/components/views/context_menus/*` (#10367)
parent
4c2b5df1f2
commit
7c2511a592
|
@ -54,7 +54,7 @@ const DeviceContextMenuSection: React.FC<IDeviceContextMenuSectionProps> = ({ de
|
|||
|
||||
useEffect(() => {
|
||||
const getDevices = async (): Promise<void> => {
|
||||
return setDevices((await MediaDeviceHandler.getDevices())[deviceKind]);
|
||||
return setDevices((await MediaDeviceHandler.getDevices())?.[deviceKind] ?? []);
|
||||
};
|
||||
getDevices();
|
||||
}, [deviceKind]);
|
||||
|
|
|
@ -48,7 +48,7 @@ export const KebabContextMenu: React.FC<KebabContextMenuProps> = ({ options, tit
|
|||
compact
|
||||
rightAligned
|
||||
closeOnInteraction
|
||||
{...contextMenuBelow(button.current.getBoundingClientRect())}
|
||||
{...contextMenuBelow(button.current!.getBoundingClientRect())}
|
||||
>
|
||||
<IconizedContextMenuOptionList>{options}</IconizedContextMenuOptionList>
|
||||
</IconizedContextMenu>
|
||||
|
|
|
@ -73,7 +73,7 @@ const ReplyInThreadButton: React.FC<IReplyInThreadButton> = ({ mxEvent, closeMen
|
|||
if (mxEvent.getThread() && !mxEvent.isThreadRoot) {
|
||||
dis.dispatch<ShowThreadPayload>({
|
||||
action: Action.ShowThread,
|
||||
rootEvent: mxEvent.getThread().rootEvent,
|
||||
rootEvent: mxEvent.getThread()!.rootEvent!,
|
||||
initialEvent: mxEvent,
|
||||
scroll_into_view: true,
|
||||
highlighted: true,
|
||||
|
@ -163,12 +163,12 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
|
|||
// to obliterate the room - https://github.com/matrix-org/synapse/issues/4042
|
||||
// Similarly for encryption events, since redacting them "breaks everything"
|
||||
const canRedact =
|
||||
room.currentState.maySendRedactionForEvent(this.props.mxEvent, cli.credentials.userId) &&
|
||||
!!room?.currentState.maySendRedactionForEvent(this.props.mxEvent, cli.getSafeUserId()) &&
|
||||
this.props.mxEvent.getType() !== EventType.RoomServerAcl &&
|
||||
this.props.mxEvent.getType() !== EventType.RoomEncryption;
|
||||
|
||||
let canPin =
|
||||
room.currentState.mayClientSendStateEvent(EventType.RoomPinnedEvents, cli) &&
|
||||
!!room?.currentState.mayClientSendStateEvent(EventType.RoomPinnedEvents, cli) &&
|
||||
canPinEvent(this.props.mxEvent);
|
||||
|
||||
// HACK: Intentionally say we can't pin if the user doesn't want to use the functionality
|
||||
|
@ -249,9 +249,10 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
|
|||
private onPinClick = (): void => {
|
||||
const cli = MatrixClientPeg.get();
|
||||
const room = cli.getRoom(this.props.mxEvent.getRoomId());
|
||||
if (!room) return;
|
||||
const eventId = this.props.mxEvent.getId();
|
||||
|
||||
const pinnedIds = room?.currentState?.getStateEvents(EventType.RoomPinnedEvents, "")?.getContent().pinned || [];
|
||||
const pinnedIds = room.currentState?.getStateEvents(EventType.RoomPinnedEvents, "")?.getContent().pinned || [];
|
||||
|
||||
if (pinnedIds.includes(eventId)) {
|
||||
pinnedIds.splice(pinnedIds.indexOf(eventId), 1);
|
||||
|
@ -261,7 +262,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
|
|||
event_ids: [...(room.getAccountData(ReadPinsEventId)?.getContent()?.event_ids || []), eventId],
|
||||
});
|
||||
}
|
||||
cli.sendStateEvent(this.props.mxEvent.getRoomId(), EventType.RoomPinnedEvents, { pinned: pinnedIds }, "");
|
||||
cli.sendStateEvent(room.roomId, EventType.RoomPinnedEvents, { pinned: pinnedIds }, "");
|
||||
this.closeMenu();
|
||||
};
|
||||
|
||||
|
@ -294,12 +295,13 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
|
|||
|
||||
private onCopyLinkClick = (e: ButtonEvent): void => {
|
||||
e.preventDefault(); // So that we don't open the permalink
|
||||
if (!this.props.link) return;
|
||||
copyPlaintext(this.props.link);
|
||||
this.closeMenu();
|
||||
};
|
||||
|
||||
private onCollapseReplyChainClick = (): void => {
|
||||
this.props.collapseReplyChain();
|
||||
this.props.collapseReplyChain?.();
|
||||
this.closeMenu();
|
||||
};
|
||||
|
||||
|
@ -349,10 +351,12 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
|
|||
const cli = MatrixClientPeg.get();
|
||||
const room = cli.getRoom(this.props.mxEvent.getRoomId());
|
||||
const eventId = this.props.mxEvent.getId();
|
||||
return room.getPendingEvents().filter((e) => {
|
||||
const relation = e.getRelation();
|
||||
return relation?.rel_type === RelationType.Annotation && relation.event_id === eventId && filter(e);
|
||||
});
|
||||
return (
|
||||
room?.getPendingEvents().filter((e) => {
|
||||
const relation = e.getRelation();
|
||||
return relation?.rel_type === RelationType.Annotation && relation.event_id === eventId && filter(e);
|
||||
}) ?? []
|
||||
);
|
||||
}
|
||||
|
||||
private getUnsentReactions(): MatrixEvent[] {
|
||||
|
@ -380,7 +384,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
|
|||
const eventStatus = mxEvent.status;
|
||||
const unsentReactionsCount = this.getUnsentReactions().length;
|
||||
const contentActionable = isContentActionable(mxEvent);
|
||||
const permalink = this.props.permalinkCreator?.forEvent(this.props.mxEvent.getId());
|
||||
const permalink = this.props.permalinkCreator?.forEvent(this.props.mxEvent.getId()!);
|
||||
// status is SENT before remote-echo, null after
|
||||
const isSent = !eventStatus || eventStatus === EventStatus.SENT;
|
||||
const { timelineRenderingType, canReact, canSendMessages } = this.context;
|
||||
|
|
|
@ -399,7 +399,7 @@ const RoomContextMenu: React.FC<IProps> = ({ room, onFinished, ...props }) => {
|
|||
Modal.createDialog(
|
||||
DevtoolsDialog,
|
||||
{
|
||||
roomId: SdkContextClass.instance.roomViewStore.getRoomId(),
|
||||
roomId: room.roomId,
|
||||
},
|
||||
"mx_DevtoolsDialog_wrapper",
|
||||
);
|
||||
|
|
|
@ -72,7 +72,7 @@ const ThreadListContextMenu: React.FC<ThreadListContextMenuProps> = ({
|
|||
if (permalinkCreator) {
|
||||
evt?.preventDefault();
|
||||
evt?.stopPropagation();
|
||||
const matrixToUrl = permalinkCreator.forEvent(mxEvent.getId());
|
||||
const matrixToUrl = permalinkCreator.forEvent(mxEvent.getId()!);
|
||||
await copyPlaintext(matrixToUrl);
|
||||
closeThreadOptions();
|
||||
}
|
||||
|
@ -84,9 +84,8 @@ const ThreadListContextMenu: React.FC<ThreadListContextMenuProps> = ({
|
|||
onMenuToggle?.(menuDisplayed);
|
||||
}, [menuDisplayed, onMenuToggle]);
|
||||
|
||||
const isMainSplitTimelineShown = !WidgetLayoutStore.instance.hasMaximisedWidget(
|
||||
MatrixClientPeg.get().getRoom(mxEvent.getRoomId()),
|
||||
);
|
||||
const room = MatrixClientPeg.get().getRoom(mxEvent.getRoomId());
|
||||
const isMainSplitTimelineShown = !!room && !WidgetLayoutStore.instance.hasMaximisedWidget(room);
|
||||
return (
|
||||
<React.Fragment>
|
||||
<ContextMenuTooltipButton
|
||||
|
@ -104,7 +103,7 @@ const ThreadListContextMenu: React.FC<ThreadListContextMenuProps> = ({
|
|||
className="mx_RoomTile_contextMenu"
|
||||
compact
|
||||
rightAligned
|
||||
{...contextMenuBelow(button.current.getBoundingClientRect())}
|
||||
{...contextMenuBelow(button.current!.getBoundingClientRect())}
|
||||
>
|
||||
<IconizedContextMenuOptionList>
|
||||
{isMainSplitTimelineShown && (
|
||||
|
|
|
@ -63,8 +63,8 @@ export const WidgetContextMenu: React.FC<IProps> = ({
|
|||
const widgetMessaging = WidgetMessagingStore.instance.getMessagingForUid(WidgetUtils.getWidgetUid(app));
|
||||
const canModify = userWidget || WidgetUtils.canUserModifyWidgets(roomId);
|
||||
|
||||
let streamAudioStreamButton;
|
||||
if (getConfigLivestreamUrl() && WidgetType.JITSI.matches(app.type)) {
|
||||
let streamAudioStreamButton: JSX.Element | undefined;
|
||||
if (roomId && getConfigLivestreamUrl() && WidgetType.JITSI.matches(app.type)) {
|
||||
const onStreamAudioClick = async (): Promise<void> => {
|
||||
try {
|
||||
await startJitsiAudioLivestream(widgetMessaging!, roomId);
|
||||
|
@ -87,12 +87,12 @@ export const WidgetContextMenu: React.FC<IProps> = ({
|
|||
const pinnedWidgets = room ? WidgetLayoutStore.instance.getContainerWidgets(room, Container.Top) : [];
|
||||
const widgetIndex = pinnedWidgets.findIndex((widget) => widget.id === app.id);
|
||||
|
||||
let editButton;
|
||||
let editButton: JSX.Element | undefined;
|
||||
if (canModify && WidgetUtils.isManagedByManager(app)) {
|
||||
const _onEditClick = (): void => {
|
||||
if (onEditClick) {
|
||||
onEditClick();
|
||||
} else {
|
||||
} else if (room) {
|
||||
WidgetUtils.editWidget(room, app);
|
||||
}
|
||||
onFinished();
|
||||
|
@ -101,7 +101,7 @@ export const WidgetContextMenu: React.FC<IProps> = ({
|
|||
editButton = <IconizedContextMenuOption onClick={_onEditClick} label={_t("Edit")} />;
|
||||
}
|
||||
|
||||
let snapshotButton;
|
||||
let snapshotButton: JSX.Element | undefined;
|
||||
const screenshotsEnabled = SettingsStore.getValue("enableWidgetScreenshots");
|
||||
if (screenshotsEnabled && widgetMessaging?.hasCapability(MatrixCapabilities.Screenshots)) {
|
||||
const onSnapshotClick = (): void => {
|
||||
|
@ -122,12 +122,12 @@ export const WidgetContextMenu: React.FC<IProps> = ({
|
|||
snapshotButton = <IconizedContextMenuOption onClick={onSnapshotClick} label={_t("Take a picture")} />;
|
||||
}
|
||||
|
||||
let deleteButton;
|
||||
let deleteButton: JSX.Element | undefined;
|
||||
if (onDeleteClick || canModify) {
|
||||
const _onDeleteClick = (): void => {
|
||||
if (onDeleteClick) {
|
||||
onDeleteClick();
|
||||
} else {
|
||||
} else if (roomId) {
|
||||
// Show delete confirmation dialog
|
||||
Modal.createDialog(QuestionDialog, {
|
||||
title: _t("Delete Widget"),
|
||||
|
@ -159,7 +159,7 @@ export const WidgetContextMenu: React.FC<IProps> = ({
|
|||
app.creatorUserId === cli.getUserId();
|
||||
|
||||
const isLocalWidget = WidgetType.JITSI.matches(app.type);
|
||||
let revokeButton;
|
||||
let revokeButton: JSX.Element | undefined;
|
||||
if (!userWidget && !isLocalWidget && isAllowedWidget) {
|
||||
const opts: ApprovalOpts = { approved: undefined };
|
||||
ModuleRunner.instance.invoke(WidgetLifecycle.PreLoadRequest, opts, new ElementWidget(app));
|
||||
|
@ -182,7 +182,7 @@ export const WidgetContextMenu: React.FC<IProps> = ({
|
|||
}
|
||||
}
|
||||
|
||||
let moveLeftButton;
|
||||
let moveLeftButton: JSX.Element | undefined;
|
||||
if (showUnpin && widgetIndex > 0) {
|
||||
const onClick = (): void => {
|
||||
if (!room) throw new Error("room must be defined");
|
||||
|
@ -193,7 +193,7 @@ export const WidgetContextMenu: React.FC<IProps> = ({
|
|||
moveLeftButton = <IconizedContextMenuOption onClick={onClick} label={_t("Move left")} />;
|
||||
}
|
||||
|
||||
let moveRightButton;
|
||||
let moveRightButton: JSX.Element | undefined;
|
||||
if (showUnpin && widgetIndex < pinnedWidgets.length - 1) {
|
||||
const onClick = (): void => {
|
||||
if (!room) throw new Error("room must be defined");
|
||||
|
|
Loading…
Reference in New Issue