move some actions to redux in hooks
parent
0e4d7ec21a
commit
23e9a6d31c
@ -0,0 +1,179 @@
|
||||
import React, { useCallback } from 'react';
|
||||
|
||||
import { AttachmentTypeWithPath } from '../../types/Attachment';
|
||||
import _ from 'lodash';
|
||||
import { animation, Item, Menu } from 'react-contexify';
|
||||
|
||||
import { MessageInteraction } from '../../interactions';
|
||||
import { getMessageById } from '../../data/data';
|
||||
import { deleteMessagesById, replyToMessage } from '../../interactions/conversationInteractions';
|
||||
import { showMessageDetailsView, toggleSelectedMessageId } from '../../state/ducks/conversations';
|
||||
import { saveAttachmentToDisk } from '../../util/attachmentsUtil';
|
||||
import {
|
||||
addSenderAsModerator,
|
||||
removeSenderFromModerator,
|
||||
} from '../../interactions/messageInteractions';
|
||||
import { MessageDeliveryStatus, MessageModelType } from '../../models/messageType';
|
||||
import { pushUnblockToSend } from '../../session/utils/Toast';
|
||||
|
||||
export type PropsForMessageContextMenu = {
|
||||
messageId: string;
|
||||
authorPhoneNumber: string;
|
||||
direction: MessageModelType;
|
||||
timestamp: number;
|
||||
serverTimestamp?: number;
|
||||
convoId: string;
|
||||
isPublic?: boolean;
|
||||
isBlocked: boolean;
|
||||
attachments?: Array<AttachmentTypeWithPath>;
|
||||
status?: MessageDeliveryStatus | null;
|
||||
isOpenGroupV2?: boolean;
|
||||
isDeletable: boolean;
|
||||
text: string | null;
|
||||
isAdmin?: boolean;
|
||||
weAreAdmin?: boolean;
|
||||
contextMenuId: string;
|
||||
};
|
||||
|
||||
export const MessageContextMenu = (props: PropsForMessageContextMenu) => {
|
||||
const {
|
||||
attachments,
|
||||
authorPhoneNumber,
|
||||
convoId,
|
||||
direction,
|
||||
status,
|
||||
isDeletable,
|
||||
messageId,
|
||||
contextMenuId,
|
||||
isPublic,
|
||||
isOpenGroupV2,
|
||||
weAreAdmin,
|
||||
isAdmin,
|
||||
text,
|
||||
serverTimestamp,
|
||||
timestamp,
|
||||
isBlocked,
|
||||
} = props;
|
||||
const showRetry = status === 'error' && direction === 'outgoing';
|
||||
const multipleAttachments = attachments && attachments.length > 1;
|
||||
|
||||
const onContextMenuShown = useCallback(() => {
|
||||
window.contextMenuShown = true;
|
||||
}, []);
|
||||
|
||||
const onContextMenuHidden = useCallback(() => {
|
||||
// This function will called before the click event
|
||||
// on the message would trigger (and I was unable to
|
||||
// prevent propagation in this case), so use a short timeout
|
||||
setTimeout(() => {
|
||||
window.contextMenuShown = false;
|
||||
}, 100);
|
||||
}, []);
|
||||
|
||||
const onShowDetail = async () => {
|
||||
const found = await getMessageById(messageId);
|
||||
if (found) {
|
||||
const messageDetailsProps = await found.getPropsForMessageDetail();
|
||||
window.inboxStore?.dispatch(showMessageDetailsView(messageDetailsProps));
|
||||
} else {
|
||||
window.log.warn(`Message ${messageId} not found in db`);
|
||||
}
|
||||
};
|
||||
|
||||
const selectMessageText = window.i18n('selectMessage');
|
||||
const deleteMessageText = window.i18n('deleteMessage');
|
||||
|
||||
const addModerator = useCallback(() => {
|
||||
void addSenderAsModerator(authorPhoneNumber, convoId);
|
||||
}, [authorPhoneNumber, convoId]);
|
||||
|
||||
const removeModerator = useCallback(() => {
|
||||
void removeSenderFromModerator(authorPhoneNumber, convoId);
|
||||
}, [authorPhoneNumber, convoId]);
|
||||
|
||||
const onReply = useCallback(() => {
|
||||
if (isBlocked) {
|
||||
pushUnblockToSend();
|
||||
return;
|
||||
}
|
||||
void replyToMessage(messageId);
|
||||
}, [isBlocked, messageId]);
|
||||
|
||||
const saveAttachment = useCallback(
|
||||
(e: any) => {
|
||||
e.stopPropagation();
|
||||
if (!attachments?.length) {
|
||||
return;
|
||||
}
|
||||
const messageTimestamp = timestamp || serverTimestamp || 0;
|
||||
void saveAttachmentToDisk({
|
||||
attachment: attachments[0],
|
||||
messageTimestamp,
|
||||
messageSender: authorPhoneNumber,
|
||||
conversationId: convoId,
|
||||
});
|
||||
},
|
||||
[convoId, authorPhoneNumber, timestamp, serverTimestamp, convoId, attachments]
|
||||
);
|
||||
|
||||
const copyText = useCallback(() => {
|
||||
MessageInteraction.copyBodyToClipboard(text);
|
||||
}, [text]);
|
||||
|
||||
const onRetry = useCallback(async () => {
|
||||
const found = await getMessageById(messageId);
|
||||
if (found) {
|
||||
await found.retrySend();
|
||||
}
|
||||
}, [messageId]);
|
||||
|
||||
const onBan = useCallback(() => {
|
||||
MessageInteraction.banUser(authorPhoneNumber, convoId);
|
||||
}, [authorPhoneNumber, convoId]);
|
||||
|
||||
const onUnban = useCallback(() => {
|
||||
MessageInteraction.unbanUser(authorPhoneNumber, convoId);
|
||||
}, [authorPhoneNumber, convoId]);
|
||||
|
||||
const onSelect = useCallback(() => {
|
||||
window.inboxStore?.dispatch(toggleSelectedMessageId(messageId));
|
||||
}, [messageId]);
|
||||
|
||||
const onDelete = useCallback(() => {
|
||||
void deleteMessagesById([messageId], convoId, false);
|
||||
}, [convoId, messageId]);
|
||||
|
||||
return (
|
||||
<Menu
|
||||
id={contextMenuId}
|
||||
onShown={onContextMenuShown}
|
||||
onHidden={onContextMenuHidden}
|
||||
animation={animation.fade}
|
||||
>
|
||||
{!multipleAttachments && attachments && attachments[0] ? (
|
||||
<Item onClick={saveAttachment}>{window.i18n('downloadAttachment')}</Item>
|
||||
) : null}
|
||||
|
||||
<Item onClick={copyText}>{window.i18n('copyMessage')}</Item>
|
||||
<Item onClick={onReply}>{window.i18n('replyToMessage')}</Item>
|
||||
<Item onClick={onShowDetail}>{window.i18n('moreInformation')}</Item>
|
||||
{showRetry ? <Item onClick={onRetry}>{window.i18n('resend')}</Item> : null}
|
||||
{isDeletable ? (
|
||||
<>
|
||||
<Item onClick={onSelect}>{selectMessageText}</Item>
|
||||
<Item onClick={onDelete}>{deleteMessageText}</Item>
|
||||
</>
|
||||
) : null}
|
||||
{weAreAdmin && isPublic ? <Item onClick={onBan}>{window.i18n('banUser')}</Item> : null}
|
||||
{weAreAdmin && isOpenGroupV2 ? (
|
||||
<Item onClick={onUnban}>{window.i18n('unbanUser')}</Item>
|
||||
) : null}
|
||||
{weAreAdmin && isPublic && !isAdmin ? (
|
||||
<Item onClick={addModerator}>{window.i18n('addAsModerator')}</Item>
|
||||
) : null}
|
||||
{weAreAdmin && isPublic && isAdmin ? (
|
||||
<Item onClick={removeModerator}>{window.i18n('removeFromModerators')}</Item>
|
||||
) : null}
|
||||
</Menu>
|
||||
);
|
||||
};
|
Loading…
Reference in New Issue