diff --git a/ts/components/conversation/message/message-content/MessageContextMenu.tsx b/ts/components/conversation/message/message-content/MessageContextMenu.tsx
index 112ccd187..909bcda1a 100644
--- a/ts/components/conversation/message/message-content/MessageContextMenu.tsx
+++ b/ts/components/conversation/message/message-content/MessageContextMenu.tsx
@@ -11,7 +11,6 @@ import { Data } from '../../../../data/data';
import { MessageInteraction } from '../../../../interactions';
import { replyToMessage } from '../../../../interactions/conversationInteractions';
-import { deleteMessagesForX } from '../../../../interactions/conversations/unsendingInteractions';
import {
addSenderAsModerator,
removeSenderFromModerator,
@@ -29,7 +28,6 @@ import {
useMessageBody,
useMessageDirection,
useMessageIsDeletable,
- useMessageIsDeletableForEveryone,
useMessageSender,
useMessageSenderIsAdmin,
useMessageServerTimestamp,
@@ -53,6 +51,9 @@ import { CopyAccountIdMenuItem } from '../../../menu/items/CopyAccountId/CopyAcc
import { Localizer } from '../../../basic/Localizer';
import { ItemWithDataTestId } from '../../../menu/items/MenuItemWithDataTestId';
import { getMenuAnimation } from '../../../menu/MenuAnimation';
+import { WithMessageId } from '../../../../session/types/with';
+import { DeleteItem } from '../../../menu/items/DeleteMessage/DeleteMessageMenuItem';
+import { RetryItem } from '../../../menu/items/RetrySend/RetrySendMenuItem';
export type MessageContextMenuSelectorProps = Pick<
MessageRenderingProps,
@@ -91,32 +92,7 @@ const StyledEmojiPanelContainer = styled.div<{ x: number; y: number }>`
}
`;
-const DeleteItem = ({ messageId }: { messageId: string }) => {
- const convoId = useSelectedConversationKey();
- const isPublic = useSelectedIsPublic();
-
- const isDeletable = useMessageIsDeletable(messageId);
- const isDeletableForEveryone = useMessageIsDeletableForEveryone(messageId);
- const messageStatus = useMessageStatus(messageId);
-
- const enforceDeleteServerSide = isPublic && messageStatus !== 'error';
-
- const onDelete = useCallback(() => {
- if (convoId) {
- void deleteMessagesForX([messageId], convoId, enforceDeleteServerSide);
- }
- }, [convoId, enforceDeleteServerSide, messageId]);
-
- if (!convoId || (isPublic && !isDeletableForEveryone) || (!isPublic && !isDeletable)) {
- return null;
- }
-
- return {window.i18n('delete')};
-};
-
-type MessageId = { messageId: string };
-
-const AdminActionItems = ({ messageId }: MessageId) => {
+const AdminActionItems = ({ messageId }: WithMessageId) => {
const convoId = useSelectedConversationKey();
const isPublic = useSelectedIsPublic();
const weAreModerator = useSelectedWeAreModerator();
@@ -163,24 +139,6 @@ const AdminActionItems = ({ messageId }: MessageId) => {
) : null;
};
-const RetryItem = ({ messageId }: MessageId) => {
- const direction = useMessageDirection(messageId);
-
- const status = useMessageStatus(messageId);
- const isOutgoing = direction === 'outgoing';
-
- const showRetry = status === 'error' && isOutgoing;
- const onRetry = useCallback(async () => {
- const found = await Data.getMessageById(messageId);
- if (found) {
- await found.retrySend();
- }
- }, [messageId]);
- return showRetry ? (
- {window.i18n('resend')}
- ) : null;
-};
-
export const showMessageInfoOverlay = async ({
messageId,
dispatch,
@@ -355,6 +313,7 @@ export const MessageContextMenu = (props: Props) => {
if (!convoId) {
return null;
}
+
return (
{enableReactions && showEmojiPanel && (
diff --git a/ts/components/menu/items/DeleteMessage/DeleteMessageMenuItem.tsx b/ts/components/menu/items/DeleteMessage/DeleteMessageMenuItem.tsx
new file mode 100644
index 000000000..45173dad8
--- /dev/null
+++ b/ts/components/menu/items/DeleteMessage/DeleteMessageMenuItem.tsx
@@ -0,0 +1,35 @@
+import { useCallback } from 'react';
+import { deleteMessagesForX } from '../../../../interactions/conversations/unsendingInteractions';
+import {
+ useMessageIsDeletable,
+ useMessageIsDeletableForEveryone,
+ useMessageStatus,
+} from '../../../../state/selectors';
+import {
+ useSelectedConversationKey,
+ useSelectedIsPublic,
+} from '../../../../state/selectors/selectedConversation';
+import { ItemWithDataTestId } from '../MenuItemWithDataTestId';
+
+export const DeleteItem = ({ messageId }: { messageId: string }) => {
+ const convoId = useSelectedConversationKey();
+ const isPublic = useSelectedIsPublic();
+
+ const isDeletable = useMessageIsDeletable(messageId);
+ const isDeletableForEveryone = useMessageIsDeletableForEveryone(messageId);
+ const messageStatus = useMessageStatus(messageId);
+
+ const enforceDeleteServerSide = isPublic && messageStatus !== 'error';
+
+ const onDelete = useCallback(() => {
+ if (convoId) {
+ void deleteMessagesForX([messageId], convoId, enforceDeleteServerSide);
+ }
+ }, [convoId, enforceDeleteServerSide, messageId]);
+
+ if (!convoId || (isPublic && !isDeletableForEveryone) || (!isPublic && !isDeletable)) {
+ return null;
+ }
+
+ return {window.i18n('delete')};
+};
diff --git a/ts/components/menu/items/RetrySend/RetrySendMenuItem.tsx b/ts/components/menu/items/RetrySend/RetrySendMenuItem.tsx
new file mode 100644
index 000000000..e571fb90b
--- /dev/null
+++ b/ts/components/menu/items/RetrySend/RetrySendMenuItem.tsx
@@ -0,0 +1,25 @@
+import { useCallback } from 'react';
+import { WithMessageId } from '../../../../session/types/with';
+import { useMessageDirection, useMessageStatus } from '../../../../state/selectors';
+import { ItemWithDataTestId } from '../MenuItemWithDataTestId';
+import { Data } from '../../../../data/data';
+
+export const RetryItem = ({ messageId }: WithMessageId) => {
+ const direction = useMessageDirection(messageId);
+
+ const status = useMessageStatus(messageId);
+ const isOutgoing = direction === 'outgoing';
+
+ const showRetry = status === 'error' && isOutgoing;
+ const onRetry = useCallback(async () => {
+ const found = await Data.getMessageById(messageId);
+ if (found) {
+ await found.retrySend();
+ }
+ }, [messageId]);
+
+ return showRetry ? (
+ // eslint-disable-next-line @typescript-eslint/no-misused-promises
+ {window.i18n('resend')}
+ ) : null;
+};