1
+ import { match } from 'ts-pattern' ;
1
2
import { useCallback } from 'react' ;
2
3
import { useGroupChannelMessages } from '@sendbird/uikit-tools' ;
3
4
import { MessageMetaArray } from '@sendbird/chat/message' ;
@@ -19,9 +20,10 @@ import {
19
20
VOICE_MESSAGE_FILE_NAME ,
20
21
VOICE_MESSAGE_MIME_TYPE ,
21
22
} from '../../../../utils/consts' ;
22
- import type { SendableMessageType } from '../../../../utils' ;
23
+ import type { SendableMessageType , CoreMessageType } from '../../../../utils' ;
23
24
import type { ReplyType } from '../../../../types' ;
24
- import type { GroupChannelProviderProps } from '../GroupChannelProvider' ;
25
+ import type { GroupChannelProviderProps , OnBeforeHandler } from '../GroupChannelProvider' ;
26
+ import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext' ;
25
27
26
28
type MessageListDataSource = ReturnType < typeof useGroupChannelMessages > ;
27
29
type MessageActions = {
@@ -39,6 +41,13 @@ interface Params extends GroupChannelProviderProps, MessageListDataSource {
39
41
}
40
42
41
43
const pass = < T > ( value : T ) => value ;
44
+ type MessageParamsByType = {
45
+ user : UserMessageCreateParams ;
46
+ file : FileMessageCreateParams ;
47
+ multipleFiles : MultipleFilesMessageCreateParams ;
48
+ voice : FileMessageCreateParams ;
49
+ update : UserMessageUpdateParams ;
50
+ } ;
42
51
43
52
/**
44
53
* @description This hook controls common processes related to message sending, updating.
@@ -60,7 +69,7 @@ export function useMessageActions(params: Params): MessageActions {
60
69
quoteMessage,
61
70
replyType,
62
71
} = params ;
63
-
72
+ const { eventHandlers } = useSendbirdStateContext ( ) ;
64
73
const buildInternalMessageParams = useCallback (
65
74
< T extends BaseMessageCreateParams > ( basicParams : T ) : T => {
66
75
const messageParams = { ...basicParams } as T ;
@@ -84,33 +93,71 @@ export function useMessageActions(params: Params): MessageActions {
84
93
[ ] ,
85
94
) ;
86
95
96
+ const processParams = useCallback ( async < T extends keyof MessageParamsByType > (
97
+ handler : OnBeforeHandler < MessageParamsByType [ T ] > ,
98
+ params : ReturnType < typeof buildInternalMessageParams > ,
99
+ type : keyof MessageParamsByType ,
100
+ ) : Promise < MessageParamsByType [ T ] > => {
101
+ try {
102
+ const result = await handler ( params as MessageParamsByType [ T ] ) ;
103
+ return ( result === undefined ? params : result ) as MessageParamsByType [ T ] ;
104
+ } catch ( error ) {
105
+ if ( typeof eventHandlers ?. message === 'object' ) {
106
+ match ( type )
107
+ . with ( 'file' , 'voice' , ( ) => {
108
+ if ( ( params as any ) . file ) {
109
+ eventHandlers . message . onFileUploadFailed ?.( error ) ;
110
+ }
111
+ eventHandlers . message . onSendMessageFailed ?.( params as CoreMessageType , error ) ;
112
+ } )
113
+ . with ( 'multipleFiles' , ( ) => {
114
+ if ( ( params as MultipleFilesMessageCreateParams ) . fileInfoList ) {
115
+ eventHandlers . message . onFileUploadFailed ?.( error ) ;
116
+ }
117
+ eventHandlers . message . onSendMessageFailed ?.( params as CoreMessageType , error ) ;
118
+ } )
119
+ . with ( 'user' , ( ) => {
120
+ eventHandlers . message . onSendMessageFailed ?.(
121
+ params as CoreMessageType ,
122
+ error ,
123
+ ) ;
124
+ } )
125
+ . with ( 'update' , ( ) => {
126
+ eventHandlers . message . onUpdateMessageFailed ?.(
127
+ params as CoreMessageType ,
128
+ error ,
129
+ ) ;
130
+ } )
131
+ . exhaustive ( ) ;
132
+ }
133
+ throw error ;
134
+ }
135
+ } , [ eventHandlers ] ) ;
136
+
87
137
return {
88
138
sendUserMessage : useCallback (
89
139
async ( params ) => {
90
140
const internalParams = buildInternalMessageParams < UserMessageCreateParams > ( params ) ;
91
- const processedParams = await onBeforeSendUserMessage ( internalParams ) ;
92
-
141
+ const processedParams = await processParams ( onBeforeSendUserMessage , internalParams , 'user' ) as UserMessageCreateParams ;
93
142
return sendUserMessage ( processedParams , asyncScrollToBottom ) ;
94
143
} ,
95
- [ buildInternalMessageParams , sendUserMessage , scrollToBottom ] ,
144
+ [ buildInternalMessageParams , sendUserMessage , scrollToBottom , processParams ] ,
96
145
) ,
97
146
sendFileMessage : useCallback (
98
147
async ( params ) => {
99
148
const internalParams = buildInternalMessageParams < FileMessageCreateParams > ( params ) ;
100
- const processedParams = await onBeforeSendFileMessage ( internalParams ) ;
101
-
149
+ const processedParams = await processParams ( onBeforeSendFileMessage , internalParams , 'file' ) as FileMessageCreateParams ;
102
150
return sendFileMessage ( processedParams , asyncScrollToBottom ) ;
103
151
} ,
104
- [ buildInternalMessageParams , sendFileMessage , scrollToBottom ] ,
152
+ [ buildInternalMessageParams , sendFileMessage , scrollToBottom , processParams ] ,
105
153
) ,
106
154
sendMultipleFilesMessage : useCallback (
107
155
async ( params ) => {
108
156
const internalParams = buildInternalMessageParams < MultipleFilesMessageCreateParams > ( params ) ;
109
- const processedParams = await onBeforeSendMultipleFilesMessage ( internalParams ) ;
110
-
157
+ const processedParams = await processParams ( onBeforeSendMultipleFilesMessage , internalParams , 'multipleFiles' ) as MultipleFilesMessageCreateParams ;
111
158
return sendMultipleFilesMessage ( processedParams , asyncScrollToBottom ) ;
112
159
} ,
113
- [ buildInternalMessageParams , sendMultipleFilesMessage , scrollToBottom ] ,
160
+ [ buildInternalMessageParams , sendMultipleFilesMessage , scrollToBottom , processParams ] ,
114
161
) ,
115
162
sendVoiceMessage : useCallback (
116
163
async ( params : FileMessageCreateParams , duration : number ) => {
@@ -129,20 +176,18 @@ export function useMessageActions(params: Params): MessageActions {
129
176
} ) ,
130
177
] ,
131
178
} ) ;
132
- const processedParams = await onBeforeSendVoiceMessage ( internalParams ) ;
133
-
179
+ const processedParams = await processParams ( onBeforeSendVoiceMessage , internalParams , 'voice' ) ;
134
180
return sendFileMessage ( processedParams , asyncScrollToBottom ) ;
135
181
} ,
136
- [ buildInternalMessageParams , sendFileMessage , scrollToBottom ] ,
182
+ [ buildInternalMessageParams , sendFileMessage , scrollToBottom , processParams ] ,
137
183
) ,
138
184
updateUserMessage : useCallback (
139
185
async ( messageId : number , params : UserMessageUpdateParams ) => {
140
186
const internalParams = buildInternalMessageParams < UserMessageUpdateParams > ( params ) ;
141
- const processedParams = await onBeforeUpdateUserMessage ( internalParams ) ;
142
-
187
+ const processedParams = await processParams ( onBeforeUpdateUserMessage , internalParams , 'update' ) ;
143
188
return updateUserMessage ( messageId , processedParams ) ;
144
189
} ,
145
- [ buildInternalMessageParams , updateUserMessage ] ,
190
+ [ buildInternalMessageParams , updateUserMessage , processParams ] ,
146
191
) ,
147
192
} ;
148
193
}
0 commit comments