Skip to content

Commit f264bf0

Browse files
authored
fix: add copy and flag message action handler to actionHandlers (#2573)
* fix: add copy and flag message action handler to actionHandlers * add unpinMessage action handler * improve default handlers * feat: add threadReply action handler
1 parent 004d7b4 commit f264bf0

File tree

5 files changed

+96
-75
lines changed

5 files changed

+96
-75
lines changed

package/src/components/Message/Message.tsx

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ export type MessageTouchableHandlerPayload<
101101
/**
102102
* Set of action handler functions for various message actions. You can use these functions to perform any action when give interaction occurs.
103103
*/
104-
actionHandlers?: MessageActionHandlers;
104+
actionHandlers?: MessageActionHandlers<StreamChatGenerics>;
105105
/**
106106
* Additional message touchable handler info.
107107
*/
@@ -112,16 +112,22 @@ export type MessageTouchableHandlerPayload<
112112
message?: MessageType<StreamChatGenerics>;
113113
};
114114

115-
export type MessageActionHandlers = {
116-
deleteMessage: () => Promise<void>;
115+
export type MessageActionHandlers<
116+
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
117+
> = {
118+
copyMessage: () => void;
119+
deleteMessage: () => void;
117120
editMessage: () => void;
121+
flagMessage: () => void;
118122
pinMessage: () => Promise<void>;
119123
quotedReply: () => void;
120124
resendMessage: () => Promise<void>;
121125
showMessageOverlay: () => void;
122126
toggleBanUser: () => Promise<void>;
123127
toggleMuteUser: () => Promise<void>;
124128
toggleReaction: (reactionType: string) => Promise<void>;
129+
unpinMessage: () => Promise<void>;
130+
threadReply?: (message: MessageType<StreamChatGenerics>) => Promise<void>;
125131
};
126132

127133
export type MessagePropsWithContext<
@@ -476,8 +482,10 @@ const MessageWithContext = <
476482
const ownCapabilities = useOwnCapabilitiesContext();
477483

478484
const {
485+
handleCopyMessage,
479486
handleDeleteMessage,
480487
handleEditMessage,
488+
handleFlagMessage,
481489
handleQuotedReplyMessage,
482490
handleResendMessage,
483491
handleToggleBanUser,
@@ -602,16 +610,20 @@ const MessageWithContext = <
602610
setOverlay('message');
603611
};
604612

605-
const actionHandlers: MessageActionHandlers = {
613+
const actionHandlers: MessageActionHandlers<StreamChatGenerics> = {
614+
copyMessage: handleCopyMessage,
606615
deleteMessage: handleDeleteMessage,
607616
editMessage: handleEditMessage,
617+
flagMessage: handleFlagMessage,
608618
pinMessage: handleTogglePinMessage,
609619
quotedReply: handleQuotedReplyMessage,
610620
resendMessage: handleResendMessage,
611621
showMessageOverlay,
622+
threadReply: handleThreadReply,
612623
toggleBanUser: handleToggleBanUser,
613624
toggleMuteUser: handleToggleMuteUser,
614625
toggleReaction: handleToggleReaction,
626+
unpinMessage: handleTogglePinMessage,
615627
};
616628

617629
const onLongPressMessage =
@@ -655,8 +667,10 @@ const MessageWithContext = <
655667
goToMessage,
656668
groupStyles,
657669
handleAction,
670+
handleCopyMessage,
658671
handleDeleteMessage,
659672
handleEditMessage,
673+
handleFlagMessage,
660674
handleQuotedReplyMessage,
661675
handleResendMessage,
662676
handleToggleBanUser,

package/src/components/Message/hooks/useCreateMessageContext.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@ export const useCreateMessageContext = <
1515
goToMessage,
1616
groupStyles,
1717
handleAction,
18+
handleCopyMessage,
1819
handleDeleteMessage,
1920
handleEditMessage,
21+
handleFlagMessage,
2022
handleQuotedReplyMessage,
2123
handleResendMessage,
2224
handleToggleBanUser,
@@ -66,8 +68,10 @@ export const useCreateMessageContext = <
6668
goToMessage,
6769
groupStyles,
6870
handleAction,
71+
handleCopyMessage,
6972
handleDeleteMessage,
7073
handleEditMessage,
74+
handleFlagMessage,
7175
handleQuotedReplyMessage,
7276
handleResendMessage,
7377
handleToggleBanUser,

package/src/components/Message/hooks/useMessageActionHandlers.ts

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1+
import { Alert } from 'react-native';
2+
13
import type { MessageResponse } from 'stream-chat';
24

35
import type { ChannelContextValue } from '../../../contexts/channelContext/ChannelContext';
46
import type { ChatContextValue } from '../../../contexts/chatContext/ChatContext';
57
import type { MessageContextValue } from '../../../contexts/messageContext/MessageContext';
68
import type { MessagesContextValue } from '../../../contexts/messagesContext/MessagesContext';
79

10+
import { useTranslationContext } from '../../../contexts/translationContext/TranslationContext';
11+
import { setClipboardString } from '../../../native';
812
import type { DefaultStreamChatGenerics } from '../../../types/types';
913

1014
export const useMessageActionHandlers = <
@@ -32,6 +36,7 @@ export const useMessageActionHandlers = <
3236
Pick<ChannelContextValue<StreamChatGenerics>, 'channel' | 'enforceUniqueReaction'> &
3337
Pick<ChatContextValue<StreamChatGenerics>, 'client'> &
3438
Pick<MessageContextValue<StreamChatGenerics>, 'message'>) => {
39+
const { t } = useTranslationContext();
3540
const handleResendMessage = () => retrySendMessage(message);
3641

3742
const handleQuotedReplyMessage = () => {
@@ -42,8 +47,28 @@ export const useMessageActionHandlers = <
4247
(mute) => mute.user.id === client.userID && mute.target.id === message.user?.id,
4348
);
4449

45-
const handleDeleteMessage = async () => {
46-
await deleteMessage(message as MessageResponse<StreamChatGenerics>);
50+
const handleCopyMessage = () => {
51+
setClipboardString(message.text || '');
52+
};
53+
54+
const handleDeleteMessage = () => {
55+
if (message.id) {
56+
Alert.alert(
57+
t('Delete Message'),
58+
t('Are you sure you want to permanently delete this message?'),
59+
[
60+
{ style: 'cancel', text: t('Cancel') },
61+
{
62+
onPress: async () => {
63+
await deleteMessage(message as MessageResponse<StreamChatGenerics>);
64+
},
65+
style: 'destructive',
66+
text: t('Delete'),
67+
},
68+
],
69+
{ cancelable: false },
70+
);
71+
}
4772
};
4873

4974
const handleToggleMuteUser = async () => {
@@ -84,6 +109,36 @@ export const useMessageActionHandlers = <
84109
setEditingState(message);
85110
};
86111

112+
const handleFlagMessage = () => {
113+
try {
114+
if (message.id) {
115+
Alert.alert(
116+
t('Flag Message'),
117+
t('Do you want to send a copy of this message to a moderator for further investigation?'),
118+
[
119+
{ style: 'cancel', text: t('Cancel') },
120+
{
121+
onPress: async () => {
122+
await client.flagMessage(message.id);
123+
Alert.alert(
124+
t('Message flagged'),
125+
t('The message has been reported to a moderator.'),
126+
);
127+
},
128+
text: t('Flag'),
129+
},
130+
],
131+
{ cancelable: false },
132+
);
133+
}
134+
} catch (_) {
135+
Alert.alert(
136+
t('Cannot Flag Message'),
137+
t('Flag action failed either due to a network issue or the message is already flagged'),
138+
);
139+
}
140+
};
141+
87142
const handleToggleReaction = async (reactionType: string) => {
88143
const messageId = message.id;
89144
const own_reactions = message.own_reactions ?? [];
@@ -114,8 +169,10 @@ export const useMessageActionHandlers = <
114169
};
115170

116171
return {
172+
handleCopyMessage,
117173
handleDeleteMessage,
118174
handleEditMessage,
175+
handleFlagMessage,
119176
handleQuotedReplyMessage,
120177
handleResendMessage,
121178
handleToggleBanUser,

package/src/components/Message/hooks/useMessageActions.tsx

Lines changed: 12 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import React from 'react';
2-
import { Alert } from 'react-native';
32

43
import { useMessageActionHandlers } from './useMessageActionHandlers';
54

@@ -100,8 +99,10 @@ export const useMessageActions = <
10099
},
101100
} = useTheme();
102101
const {
102+
handleCopyMessage,
103103
handleDeleteMessage,
104104
handleEditMessage,
105+
handleFlagMessage,
105106
handleQuotedReplyMessage,
106107
handleResendMessage,
107108
handleToggleBanUser,
@@ -161,7 +162,7 @@ export const useMessageActions = <
161162
if (handleCopy) {
162163
handleCopy(message);
163164
}
164-
setClipboardString(message.text || '');
165+
handleCopyMessage();
165166
},
166167
actionType: 'copyMessage',
167168
icon: <Copy pathFill={grey} />,
@@ -171,29 +172,11 @@ export const useMessageActions = <
171172

172173
const deleteMessage: MessageActionType = {
173174
action: () => {
174-
setOverlay('alert');
175-
if (message.id) {
176-
Alert.alert(
177-
t('Delete Message'),
178-
t('Are you sure you want to permanently delete this message?'),
179-
[
180-
{ onPress: () => setOverlay('none'), text: t('Cancel') },
181-
{
182-
onPress: async () => {
183-
setOverlay('none');
184-
if (handleDelete) {
185-
handleDelete(message);
186-
}
187-
188-
await handleDeleteMessage();
189-
},
190-
style: 'destructive',
191-
text: t('Delete'),
192-
},
193-
],
194-
{ cancelable: false },
195-
);
175+
setOverlay('none');
176+
if (handleDelete) {
177+
handleDelete(message);
196178
}
179+
handleDeleteMessage();
197180
},
198181
actionType: 'deleteMessage',
199182
icon: <Delete fill={accent_red} size={32} />,
@@ -242,51 +225,12 @@ export const useMessageActions = <
242225

243226
const flagMessage: MessageActionType = {
244227
action: () => {
245-
setOverlay('alert');
246-
if (message.id) {
247-
Alert.alert(
248-
t('Flag Message'),
249-
t('Do you want to send a copy of this message to a moderator for further investigation?'),
250-
[
251-
{ onPress: () => setOverlay('none'), text: t('Cancel') },
252-
{
253-
onPress: async () => {
254-
try {
255-
if (handleFlag) {
256-
handleFlag(message);
257-
}
258-
await client.flagMessage(message.id);
259-
Alert.alert(
260-
t('Message flagged'),
261-
t('The message has been reported to a moderator.'),
262-
[
263-
{
264-
onPress: () => setOverlay('none'),
265-
text: t('Ok'),
266-
},
267-
],
268-
);
269-
} catch (_) {
270-
Alert.alert(
271-
t('Cannot Flag Message'),
272-
t(
273-
'Flag action failed either due to a network issue or the message is already flagged',
274-
),
275-
[
276-
{
277-
onPress: () => setOverlay('none'),
278-
text: t('Ok'),
279-
},
280-
],
281-
);
282-
}
283-
},
284-
text: t('Flag'),
285-
},
286-
],
287-
{ cancelable: false },
288-
);
228+
setOverlay('none');
229+
if (handleFlag) {
230+
handleFlag(message);
289231
}
232+
233+
handleFlagMessage();
290234
},
291235
actionType: 'flagMessage',
292236
icon: <MessageFlag pathFill={grey} />,

package/src/contexts/messageContext/MessageContext.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,10 @@ export type MessageContextValue<
3838
groupStyles: GroupType[];
3939
/** Handler for actions. Actions in combination with attachments can be used to build [commands](https://getstream.io/chat/docs/#channel_commands). */
4040
handleAction: ActionHandler;
41-
handleDeleteMessage: () => Promise<void>;
41+
handleCopyMessage: () => void;
42+
handleDeleteMessage: () => void;
4243
handleEditMessage: () => void;
44+
handleFlagMessage: () => void;
4345
handleQuotedReplyMessage: () => void;
4446
handleResendMessage: () => Promise<void>;
4547
handleToggleBanUser: () => Promise<void>;

0 commit comments

Comments
 (0)