@vserifsaglam/chat-react-client 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +674 -0
- package/dist/api/chatApi.d.ts +143 -0
- package/dist/connection/ConnectionManager.d.ts +68 -0
- package/dist/connection/ConnectionManager.test.d.ts +1 -0
- package/dist/context/ChatContext.d.ts +20 -0
- package/dist/context/ConnectionContext.d.ts +28 -0
- package/dist/context/ConnectionContext.test.d.ts +1 -0
- package/dist/hooks/useBans.d.ts +14 -0
- package/dist/hooks/useClientProfile.d.ts +10 -0
- package/dist/hooks/useConnection.d.ts +14 -0
- package/dist/hooks/useConversationDetails.d.ts +15 -0
- package/dist/hooks/useConversationManagements.d.ts +12 -0
- package/dist/hooks/useConversations.d.ts +17 -0
- package/dist/hooks/useCustomEvents.d.ts +14 -0
- package/dist/hooks/useFiles.d.ts +10 -0
- package/dist/hooks/useLogging.d.ts +9 -0
- package/dist/hooks/useMessageManagements.d.ts +19 -0
- package/dist/hooks/useMessages.d.ts +23 -0
- package/dist/hooks/useQueue.d.ts +12 -0
- package/dist/hooks/useRealtime.d.ts +56 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.js +3075 -0
- package/dist/index.js.map +1 -0
- package/dist/index.modern.js +3057 -0
- package/dist/index.modern.js.map +1 -0
- package/dist/index.test.d.ts +1 -0
- package/dist/types.d.ts +248 -0
- package/dist/utils/Logger.d.ts +37 -0
- package/package.json +68 -0
package/README.md
ADDED
|
@@ -0,0 +1,674 @@
|
|
|
1
|
+
# Chat React Client
|
|
2
|
+
|
|
3
|
+
> A React library for integratin with the Chat Backend API
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/chat-react-client) [](https://standardjs.com)
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- 🔒 Secure authentication with JWT tokens
|
|
10
|
+
- 🔄 Real-time chat functionality with WebSocket
|
|
11
|
+
- 📁 File uploads and attachments
|
|
12
|
+
- 📱 Responsive design
|
|
13
|
+
- 🧩 Modular architecture with React hooks
|
|
14
|
+
- 📝 TypeScript support
|
|
15
|
+
- 🔁 Automatic reconnection and fallback mechanisms
|
|
16
|
+
- 📋 Message queue for handling failed sends
|
|
17
|
+
- 📄 Pagination support for message history
|
|
18
|
+
- 🔔 Unread message indicators
|
|
19
|
+
- 🔄 Conversation and message management hooks for simplified integration
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install --save chat-react-client
|
|
25
|
+
# or
|
|
26
|
+
yarn add chat-react-client
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Quick Start
|
|
30
|
+
|
|
31
|
+
Wrap your application with the `ChatClient` component to provide authentication and API access:
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
import React from 'react';
|
|
35
|
+
import { ChatClient, ConnectionType } from 'chat-react-client';
|
|
36
|
+
|
|
37
|
+
const App = () => {
|
|
38
|
+
return (
|
|
39
|
+
<ChatClient
|
|
40
|
+
token="your_jwt_token"
|
|
41
|
+
baseUrl="https://api.example.com"
|
|
42
|
+
connectionOptions={{
|
|
43
|
+
connectionType: ConnectionType.WebSocket,
|
|
44
|
+
autoReconnect: true
|
|
45
|
+
}}
|
|
46
|
+
>
|
|
47
|
+
<YourChatComponent />
|
|
48
|
+
</ChatClient>
|
|
49
|
+
);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
// Example with long polling only
|
|
53
|
+
const AppWithLongPolling = () => {
|
|
54
|
+
return (
|
|
55
|
+
<ChatClient
|
|
56
|
+
token="your_jwt_token"
|
|
57
|
+
baseUrl="https://api.example.com"
|
|
58
|
+
connectionOptions={{
|
|
59
|
+
connectionType: ConnectionType.LongPolling,
|
|
60
|
+
onlyLongpolling: true,
|
|
61
|
+
autoReconnect: true
|
|
62
|
+
}}
|
|
63
|
+
>
|
|
64
|
+
<YourChatComponent />
|
|
65
|
+
</ChatClient>
|
|
66
|
+
);
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export default App;
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
The `connectionOptions` prop allows you to configure the realtime connection:
|
|
73
|
+
|
|
74
|
+
- `connectionType`: Select the connection type (WebSocket or LongPolling)
|
|
75
|
+
- `autoReconnect`: Automatically reconnect if the connection is lost
|
|
76
|
+
- `onlyLongpolling`: Force the connection to use long polling only (no WebSocket)
|
|
77
|
+
|
|
78
|
+
## Hooks
|
|
79
|
+
|
|
80
|
+
### useConversationManagement
|
|
81
|
+
|
|
82
|
+
A higher-level hook for managing conversations, including conversation selection and state management:
|
|
83
|
+
|
|
84
|
+
```tsx
|
|
85
|
+
import React from 'react';
|
|
86
|
+
import { useConversationManagement } from 'chat-react-client';
|
|
87
|
+
|
|
88
|
+
const ConversationsManager = () => {
|
|
89
|
+
const {
|
|
90
|
+
conversations,
|
|
91
|
+
conversationsLoading,
|
|
92
|
+
selectedConversationId,
|
|
93
|
+
selectedConversation,
|
|
94
|
+
handleSelectConversation,
|
|
95
|
+
getConversations
|
|
96
|
+
} = useConversationManagement();
|
|
97
|
+
|
|
98
|
+
if (conversationsLoading) return <div>Loading conversations...</div>;
|
|
99
|
+
|
|
100
|
+
return (
|
|
101
|
+
<div className="chat-container">
|
|
102
|
+
<div className="conversations-list">
|
|
103
|
+
{conversations.map(conversation => (
|
|
104
|
+
<div
|
|
105
|
+
key={conversation.id}
|
|
106
|
+
className={`conversation ${selectedConversationId === conversation.id ? 'selected' : ''}`}
|
|
107
|
+
onClick={() => handleSelectConversation(conversation)}
|
|
108
|
+
>
|
|
109
|
+
<h3>{conversation.user.name}</h3>
|
|
110
|
+
<p>{conversation.lastMessage?.content}</p>
|
|
111
|
+
{conversation.unreadCount > 0 && (
|
|
112
|
+
<span className="unread-badge">{conversation.unreadCount}</span>
|
|
113
|
+
)}
|
|
114
|
+
</div>
|
|
115
|
+
))}
|
|
116
|
+
</div>
|
|
117
|
+
|
|
118
|
+
{selectedConversation && (
|
|
119
|
+
<div className="conversation-details">
|
|
120
|
+
<h2>Chat with {selectedConversation.user.name}</h2>
|
|
121
|
+
<MessagePanel conversationId={selectedConversationId} />
|
|
122
|
+
</div>
|
|
123
|
+
)}
|
|
124
|
+
</div>
|
|
125
|
+
);
|
|
126
|
+
};
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### useMessageManagement
|
|
130
|
+
|
|
131
|
+
A higher-level hook for managing messages in a conversation, including pagination, file uploads, and real-time updates:
|
|
132
|
+
|
|
133
|
+
```tsx
|
|
134
|
+
import React, { useState, useRef } from 'react';
|
|
135
|
+
import { useMessageManagement } from 'chat-react-client';
|
|
136
|
+
|
|
137
|
+
const MessagePanel = ({ conversationId, receiverId }) => {
|
|
138
|
+
const [messageText, setMessageText] = useState('');
|
|
139
|
+
const [file, setFile] = useState(null);
|
|
140
|
+
const messagesEndRef = useRef(null);
|
|
141
|
+
|
|
142
|
+
const {
|
|
143
|
+
messages,
|
|
144
|
+
messagesLoading,
|
|
145
|
+
fileLoading,
|
|
146
|
+
uploadProgress,
|
|
147
|
+
uploadFile,
|
|
148
|
+
handleSendMessage,
|
|
149
|
+
handleSendFileMessage,
|
|
150
|
+
loadMoreMessages,
|
|
151
|
+
hasMore
|
|
152
|
+
} = useMessageManagement(conversationId);
|
|
153
|
+
|
|
154
|
+
const handleSend = async () => {
|
|
155
|
+
if (!messageText.trim()) return;
|
|
156
|
+
|
|
157
|
+
const success = await handleSendMessage(messageText, receiverId);
|
|
158
|
+
if (success) {
|
|
159
|
+
setMessageText('');
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
const handleFileUpload = async (e) => {
|
|
164
|
+
const selectedFile = e.target.files[0];
|
|
165
|
+
if (!selectedFile) return;
|
|
166
|
+
|
|
167
|
+
setFile(selectedFile);
|
|
168
|
+
const fileId = await uploadFile(selectedFile);
|
|
169
|
+
|
|
170
|
+
if (fileId) {
|
|
171
|
+
await handleSendFileMessage(`Sent a file: ${selectedFile.name}`, fileId, receiverId);
|
|
172
|
+
setFile(null);
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
return (
|
|
177
|
+
<div className="message-panel">
|
|
178
|
+
{hasMore && (
|
|
179
|
+
<button
|
|
180
|
+
onClick={loadMoreMessages}
|
|
181
|
+
disabled={messagesLoading}
|
|
182
|
+
className="load-more-button"
|
|
183
|
+
>
|
|
184
|
+
{messagesLoading ? 'Loading...' : 'Load Previous Messages'}
|
|
185
|
+
</button>
|
|
186
|
+
)}
|
|
187
|
+
|
|
188
|
+
<div className="messages-container">
|
|
189
|
+
{messages.map(message => (
|
|
190
|
+
<div key={message.id} className={`message ${message.is_mine ? 'mine' : 'theirs'}`}>
|
|
191
|
+
<p>{message.content}</p>
|
|
192
|
+
{message.attachments?.length > 0 && (
|
|
193
|
+
<div className="attachments">
|
|
194
|
+
{message.attachments.map(attachment => (
|
|
195
|
+
<a key={attachment.id} href={attachment.url} target="_blank" rel="noopener noreferrer">
|
|
196
|
+
{attachment.filename}
|
|
197
|
+
</a>
|
|
198
|
+
))}
|
|
199
|
+
</div>
|
|
200
|
+
)}
|
|
201
|
+
<small>{new Date(message.timestamp).toLocaleString()}</small>
|
|
202
|
+
</div>
|
|
203
|
+
))}
|
|
204
|
+
<div ref={messagesEndRef} />
|
|
205
|
+
</div>
|
|
206
|
+
|
|
207
|
+
<div className="message-input">
|
|
208
|
+
{fileLoading && (
|
|
209
|
+
<div className="upload-progress">
|
|
210
|
+
<div className="progress-bar" style={{ width: `${uploadProgress}%` }}></div>
|
|
211
|
+
<span>{uploadProgress}%</span>
|
|
212
|
+
</div>
|
|
213
|
+
)}
|
|
214
|
+
|
|
215
|
+
<input
|
|
216
|
+
type="text"
|
|
217
|
+
value={messageText}
|
|
218
|
+
onChange={e => setMessageText(e.target.value)}
|
|
219
|
+
placeholder="Type a message..."
|
|
220
|
+
/>
|
|
221
|
+
<input type="file" onChange={handleFileUpload} />
|
|
222
|
+
<button onClick={handleSend} disabled={messagesLoading || fileLoading}>Send</button>
|
|
223
|
+
</div>
|
|
224
|
+
</div>
|
|
225
|
+
);
|
|
226
|
+
};
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### useConversations
|
|
230
|
+
|
|
231
|
+
Access and manage conversations:
|
|
232
|
+
|
|
233
|
+
```tsx
|
|
234
|
+
import React, { useEffect } from 'react';
|
|
235
|
+
import { useConversations } from 'chat-react-client';
|
|
236
|
+
|
|
237
|
+
const ConversationsList = () => {
|
|
238
|
+
const {
|
|
239
|
+
conversations,
|
|
240
|
+
loading,
|
|
241
|
+
error,
|
|
242
|
+
getConversations,
|
|
243
|
+
archiveConversation,
|
|
244
|
+
unarchiveConversation,
|
|
245
|
+
deleteConversation
|
|
246
|
+
} = useConversations();
|
|
247
|
+
|
|
248
|
+
useEffect(() => {
|
|
249
|
+
getConversations();
|
|
250
|
+
}, [getConversations]);
|
|
251
|
+
|
|
252
|
+
if (loading) return <div>Loading...</div>;
|
|
253
|
+
if (error) return <div>Error: {error.message}</div>;
|
|
254
|
+
|
|
255
|
+
return (
|
|
256
|
+
<div>
|
|
257
|
+
{conversations.map(conversation => (
|
|
258
|
+
<div key={conversation.id}>
|
|
259
|
+
<h3>{conversation.user.name}</h3>
|
|
260
|
+
<p>{conversation.lastMessage?.content}</p>
|
|
261
|
+
<button onClick={() => archiveConversation(conversation.id)}>
|
|
262
|
+
Archive
|
|
263
|
+
</button>
|
|
264
|
+
</div>
|
|
265
|
+
))}
|
|
266
|
+
</div>
|
|
267
|
+
);
|
|
268
|
+
};
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### useMessages
|
|
272
|
+
|
|
273
|
+
Send and receive messages:
|
|
274
|
+
|
|
275
|
+
```tsx
|
|
276
|
+
import React, { useState, useEffect } from 'react';
|
|
277
|
+
import { useMessages } from 'chat-react-client';
|
|
278
|
+
|
|
279
|
+
const ChatMessages = ({ conversationId }) => {
|
|
280
|
+
const [messageText, setMessageText] = useState('');
|
|
281
|
+
const {
|
|
282
|
+
messages,
|
|
283
|
+
loading,
|
|
284
|
+
sendMessage,
|
|
285
|
+
getMessages,
|
|
286
|
+
markConversationAsRead
|
|
287
|
+
} = useMessages(conversationId);
|
|
288
|
+
|
|
289
|
+
useEffect(() => {
|
|
290
|
+
if (conversationId) {
|
|
291
|
+
getMessages();
|
|
292
|
+
markConversationAsRead();
|
|
293
|
+
}
|
|
294
|
+
}, [conversationId, getMessages, markConversationAsRead]);
|
|
295
|
+
|
|
296
|
+
const handleSend = async () => {
|
|
297
|
+
if (!messageText.trim()) return;
|
|
298
|
+
|
|
299
|
+
await sendMessage({
|
|
300
|
+
receiver_client_id: 'recipient_id',
|
|
301
|
+
content: messageText
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
setMessageText('');
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
return (
|
|
308
|
+
<div>
|
|
309
|
+
<div className="messages-container">
|
|
310
|
+
{messages.map(message => (
|
|
311
|
+
<div key={message.id} className="message">
|
|
312
|
+
<p>{message.content}</p>
|
|
313
|
+
<small>{new Date(message.timestamp).toLocaleString()}</small>
|
|
314
|
+
</div>
|
|
315
|
+
))}
|
|
316
|
+
</div>
|
|
317
|
+
|
|
318
|
+
<div className="message-input">
|
|
319
|
+
<input
|
|
320
|
+
type="text"
|
|
321
|
+
value={messageText}
|
|
322
|
+
onChange={e => setMessageText(e.target.value)}
|
|
323
|
+
placeholder="Type a message..."
|
|
324
|
+
/>
|
|
325
|
+
<button onClick={handleSend} disabled={loading}>Send</button>
|
|
326
|
+
</div>
|
|
327
|
+
</div>
|
|
328
|
+
);
|
|
329
|
+
};
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### useFiles
|
|
333
|
+
|
|
334
|
+
Upload files and attachments:
|
|
335
|
+
|
|
336
|
+
```tsx
|
|
337
|
+
import React, { useState } from 'react';
|
|
338
|
+
import { useFiles, useMessages } from 'chat-react-client';
|
|
339
|
+
|
|
340
|
+
const FileUploader = ({ conversationId }) => {
|
|
341
|
+
const { uploadFile, uploadProgress, loading } = useFiles();
|
|
342
|
+
const { sendMessage } = useMessages(conversationId);
|
|
343
|
+
const [file, setFile] = useState(null);
|
|
344
|
+
|
|
345
|
+
const handleFileChange = (e) => {
|
|
346
|
+
setFile(e.target.files[0]);
|
|
347
|
+
};
|
|
348
|
+
|
|
349
|
+
const handleUpload = async () => {
|
|
350
|
+
if (!file) return;
|
|
351
|
+
|
|
352
|
+
const response = await uploadFile(file);
|
|
353
|
+
|
|
354
|
+
if (response) {
|
|
355
|
+
// Send a message with the file attachment
|
|
356
|
+
await sendMessage({
|
|
357
|
+
receiver_client_id: 'recipient_id',
|
|
358
|
+
content: 'I sent you a file',
|
|
359
|
+
attachments: [response.file_id]
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
|
|
364
|
+
return (
|
|
365
|
+
<div>
|
|
366
|
+
<input type="file" onChange={handleFileChange} />
|
|
367
|
+
|
|
368
|
+
{file && (
|
|
369
|
+
<>
|
|
370
|
+
<div className="progress-bar">
|
|
371
|
+
<div
|
|
372
|
+
className="progress"
|
|
373
|
+
style={{ width: `${uploadProgress}%` }}
|
|
374
|
+
></div>
|
|
375
|
+
</div>
|
|
376
|
+
<button onClick={handleUpload} disabled={loading}>
|
|
377
|
+
Upload and Send
|
|
378
|
+
</button>
|
|
379
|
+
</>
|
|
380
|
+
)}
|
|
381
|
+
</div>
|
|
382
|
+
);
|
|
383
|
+
};
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
## API Reference
|
|
387
|
+
|
|
388
|
+
### ChatClient
|
|
389
|
+
|
|
390
|
+
The main component that provides authentication and API access.
|
|
391
|
+
|
|
392
|
+
Props:
|
|
393
|
+
- `token` (string): JWT token for authentication
|
|
394
|
+
- `baseUrl` (string): Base URL of the Chat API
|
|
395
|
+
- `connectionOptions` (ConnectionOptions): Options for the realtime connection
|
|
396
|
+
- `children` (ReactNode): Child components
|
|
397
|
+
|
|
398
|
+
### ConnectionOptions
|
|
399
|
+
|
|
400
|
+
Options for configuring the realtime connection:
|
|
401
|
+
|
|
402
|
+
- `connectionType` (ConnectionType): The type of connection to use (WebSocket or LongPolling)
|
|
403
|
+
- `autoReconnect` (boolean): Whether to automatically reconnect if the connection is lost
|
|
404
|
+
- `reconnectAttempts` (number): Maximum number of reconnection attempts
|
|
405
|
+
- `reconnectDelay` (number): Delay between reconnection attempts in milliseconds
|
|
406
|
+
- `onlyLongpolling` (boolean): Force the connection to use long polling only (no WebSocket)
|
|
407
|
+
|
|
408
|
+
### User
|
|
409
|
+
|
|
410
|
+
Interface representing a user in the chat system:
|
|
411
|
+
|
|
412
|
+
- `id` (string): Unique identifier for the user
|
|
413
|
+
- `name` (string): Display name of the user
|
|
414
|
+
- `avatar` (string): URL to the user's avatar image
|
|
415
|
+
- `is_admin` (boolean): Whether the user is an admin
|
|
416
|
+
- `attributes` (Record<string, any>): Additional attributes for the user
|
|
417
|
+
- `file_storage_provider` (string): The storage provider for the user's files
|
|
418
|
+
- `owner_client_id` (string): The client ID of the user's owner
|
|
419
|
+
|
|
420
|
+
### Conversation
|
|
421
|
+
|
|
422
|
+
Interface representing a conversation:
|
|
423
|
+
|
|
424
|
+
- `id` (string): Unique identifier for the conversation
|
|
425
|
+
- `status` (string): Status of the conversation (e.g., "answered")
|
|
426
|
+
- `user` (User): The user participating in the conversation
|
|
427
|
+
- `lastMessage` (LastMessage): The last message in the conversation
|
|
428
|
+
- `unreadCount` (number): Number of unread messages in the conversation
|
|
429
|
+
|
|
430
|
+
### ConversationDetails
|
|
431
|
+
|
|
432
|
+
Interface representing detailed information about a conversation:
|
|
433
|
+
|
|
434
|
+
- `conversation_uid` (string): Unique identifier for the conversation
|
|
435
|
+
- `user_message_count` (number): Number of messages sent by the user
|
|
436
|
+
- `user_attachment_count` (number): Number of attachments sent by the user
|
|
437
|
+
- `user_attachments` (Attachment[]): List of attachments sent by the user
|
|
438
|
+
- `participants` (User[]): List of participants in the conversation
|
|
439
|
+
|
|
440
|
+
### useConversations
|
|
441
|
+
|
|
442
|
+
Hook for managing conversations.
|
|
443
|
+
|
|
444
|
+
Returns:
|
|
445
|
+
- `conversations` (Conversation[]): List of conversations
|
|
446
|
+
- `loading` (boolean): Loading state
|
|
447
|
+
- `error` (Error | null): Error state
|
|
448
|
+
- `getConversations(archived?: boolean, clientId?: string)`: Get conversations
|
|
449
|
+
- `deleteConversation(conversationUid: string)`: Delete a conversation
|
|
450
|
+
- `archiveConversation(conversationUid: string)`: Archive a conversation
|
|
451
|
+
- `unarchiveConversation(conversationUid: string)`: Unarchive a conversation
|
|
452
|
+
- `getConversationDetails(conversationUid: string)`: Get conversation details
|
|
453
|
+
- `searchConversation(conversationUid: string, term: string)`: Search messages in a conversation
|
|
454
|
+
|
|
455
|
+
### useMessages
|
|
456
|
+
|
|
457
|
+
Hook for managing messages.
|
|
458
|
+
|
|
459
|
+
Parameters:
|
|
460
|
+
- `conversationUid` (string, optional): ID of the conversation
|
|
461
|
+
|
|
462
|
+
Returns:
|
|
463
|
+
- `messages` (Message[]): List of messages
|
|
464
|
+
- `pagination` (MessagesPagination): Pagination information
|
|
465
|
+
- `loading` (boolean): Loading state
|
|
466
|
+
- `error` (Error | null): Error state
|
|
467
|
+
- `getMessages(conversationId?: string, page?: number, pageSize?: number)`: Get messages
|
|
468
|
+
- `markMessageAsRead(messageId: number)`: Mark a message as read
|
|
469
|
+
- `sendMessage(message: SendMessageRequest)`: Send a message
|
|
470
|
+
- `markConversationAsRead(conversationId?: string)`: Mark all messages in a conversation as read
|
|
471
|
+
- `updateMessage(messageId: number, update: UpdateMessageRequest)`: Update a message
|
|
472
|
+
- `deleteMessage(messageId: number)`: Delete a message
|
|
473
|
+
|
|
474
|
+
### useFiles
|
|
475
|
+
|
|
476
|
+
Hook for managing file uploads.
|
|
477
|
+
|
|
478
|
+
Returns:
|
|
479
|
+
- `loading` (boolean): Loading state
|
|
480
|
+
- `error` (Error | null): Error state
|
|
481
|
+
- `uploadProgress` (number): Upload progress (0-100)
|
|
482
|
+
- `uploadFile(file: File)`: Upload a file
|
|
483
|
+
|
|
484
|
+
### useConnection
|
|
485
|
+
|
|
486
|
+
Hook for managing the realtime connection.
|
|
487
|
+
|
|
488
|
+
Returns:
|
|
489
|
+
- `status` (ConnectionStatus): Current connection status
|
|
490
|
+
- `isConnected` (boolean): Whether the connection is active
|
|
491
|
+
- `isConnecting` (boolean): Whether the connection is in progress
|
|
492
|
+
- `hasError` (boolean): Whether the connection has an error
|
|
493
|
+
- `connect()`: Connect to the server
|
|
494
|
+
- `disconnect()`: Disconnect from the server
|
|
495
|
+
- `sendMessage(message: SendMessageRequest, maxAttempts?: number)`: Send a message with retry support
|
|
496
|
+
|
|
497
|
+
### useRealtime
|
|
498
|
+
|
|
499
|
+
Hook for subscribing to realtime events.
|
|
500
|
+
|
|
501
|
+
Parameters:
|
|
502
|
+
- `eventType` (EventType): The event type to subscribe to
|
|
503
|
+
|
|
504
|
+
Returns:
|
|
505
|
+
- `event` (RealtimeEvent | null): The latest event
|
|
506
|
+
- `clearEvent()`: Clear the current event
|
|
507
|
+
|
|
508
|
+
### useMessageSentEvents
|
|
509
|
+
|
|
510
|
+
Hook for subscribing to message sent events.
|
|
511
|
+
|
|
512
|
+
Returns:
|
|
513
|
+
- `event` (RealtimeEvent<MessageSentEvent> | null): The latest message sent event
|
|
514
|
+
- `clearEvent()`: Clear the current event
|
|
515
|
+
|
|
516
|
+
### useMessageEditedEvents
|
|
517
|
+
|
|
518
|
+
Hook for subscribing to message edited events.
|
|
519
|
+
|
|
520
|
+
Returns:
|
|
521
|
+
- `event` (RealtimeEvent<MessageEditedEvent> | null): The latest message edited event
|
|
522
|
+
- `clearEvent()`: Clear the current event
|
|
523
|
+
|
|
524
|
+
### useMessageDeletedEvents
|
|
525
|
+
|
|
526
|
+
Hook for subscribing to message deleted events.
|
|
527
|
+
|
|
528
|
+
Returns:
|
|
529
|
+
- `event` (RealtimeEvent<MessageDeletedEvent> | null): The latest message deleted event
|
|
530
|
+
- `clearEvent()`: Clear the current event
|
|
531
|
+
|
|
532
|
+
### useConversationManagement
|
|
533
|
+
|
|
534
|
+
Hook for managing conversations with selection state.
|
|
535
|
+
|
|
536
|
+
Returns:
|
|
537
|
+
- `conversations` (Conversation[]): List of conversations
|
|
538
|
+
- `conversationsLoading` (boolean): Loading state for conversations
|
|
539
|
+
- `selectedConversationId` (string): ID of the currently selected conversation
|
|
540
|
+
- `selectedConversation` (Conversation | undefined): The currently selected conversation object
|
|
541
|
+
- `handleSelectConversation(conversation: Conversation)`: Function to select a conversation
|
|
542
|
+
- `getConversations()`: Function to load conversations
|
|
543
|
+
|
|
544
|
+
### useMessageManagement
|
|
545
|
+
|
|
546
|
+
Hook for managing messages in a conversation with pagination and file handling.
|
|
547
|
+
|
|
548
|
+
Parameters:
|
|
549
|
+
- `selectedConversationId` (string): ID of the conversation to manage messages for
|
|
550
|
+
|
|
551
|
+
Returns:
|
|
552
|
+
- `messages` (Message[]): List of messages in the conversation
|
|
553
|
+
- `messagesLoading` (boolean): Loading state for messages
|
|
554
|
+
- `fileLoading` (boolean): Loading state for file uploads
|
|
555
|
+
- `uploadProgress` (number): Upload progress percentage (0-100)
|
|
556
|
+
- `uploadFile(file: File)`: Function to upload a file
|
|
557
|
+
- `handleSendMessage(content: string, receiverId: string)`: Function to send a text message
|
|
558
|
+
- `handleSendFileMessage(content: string, fileId: number, receiverId: string)`: Function to send a message with a file attachment
|
|
559
|
+
- `getMessages(conversationId?: string, page?: number)`: Function to get messages for a conversation
|
|
560
|
+
- `loadMoreMessages()`: Function to load more messages (pagination)
|
|
561
|
+
- `hasMore` (boolean): Whether there are more messages to load
|
|
562
|
+
|
|
563
|
+
### useAllMessageEvents
|
|
564
|
+
|
|
565
|
+
Hook for subscribing to all message events.
|
|
566
|
+
|
|
567
|
+
Returns:
|
|
568
|
+
- `messageSent` (RealtimeEvent<MessageSentEvent> | null): The latest message sent event
|
|
569
|
+
- `messageEdited` (RealtimeEvent<MessageEditedEvent> | null): The latest message edited event
|
|
570
|
+
- `messageDeleted` (RealtimeEvent<MessageDeletedEvent> | null): The latest message deleted event
|
|
571
|
+
- `clearEvents()`: Clear all events
|
|
572
|
+
|
|
573
|
+
## Realtime Examples
|
|
574
|
+
|
|
575
|
+
### Connection Management
|
|
576
|
+
|
|
577
|
+
```tsx
|
|
578
|
+
import React, { useEffect } from 'react';
|
|
579
|
+
import { useConnection, ConnectionStatus } from 'chat-react-client';
|
|
580
|
+
|
|
581
|
+
const ConnectionStatusComponent = () => {
|
|
582
|
+
const { status, isConnected, connect, disconnect } = useConnection();
|
|
583
|
+
|
|
584
|
+
useEffect(() => {
|
|
585
|
+
// Connect when the component mounts
|
|
586
|
+
connect();
|
|
587
|
+
|
|
588
|
+
// Disconnect when the component unmounts
|
|
589
|
+
return () => {
|
|
590
|
+
disconnect();
|
|
591
|
+
};
|
|
592
|
+
}, [connect, disconnect]);
|
|
593
|
+
|
|
594
|
+
return (
|
|
595
|
+
<div>
|
|
596
|
+
<div>Connection Status: {status}</div>
|
|
597
|
+
<button onClick={connect} disabled={isConnected}>
|
|
598
|
+
Connect
|
|
599
|
+
</button>
|
|
600
|
+
<button onClick={disconnect} disabled={!isConnected}>
|
|
601
|
+
Disconnect
|
|
602
|
+
</button>
|
|
603
|
+
</div>
|
|
604
|
+
);
|
|
605
|
+
};
|
|
606
|
+
|
|
607
|
+
### Event Listening
|
|
608
|
+
|
|
609
|
+
```tsx
|
|
610
|
+
import React, { useEffect, useState } from 'react';
|
|
611
|
+
import { useAllMessageEvents } from 'chat-react-client';
|
|
612
|
+
|
|
613
|
+
const MessageEventListener = () => {
|
|
614
|
+
const [messages, setMessages] = useState([]);
|
|
615
|
+
const {
|
|
616
|
+
messageSent,
|
|
617
|
+
messageEdited,
|
|
618
|
+
messageDeleted,
|
|
619
|
+
clearEvents
|
|
620
|
+
} = useAllMessageEvents();
|
|
621
|
+
|
|
622
|
+
// Handle new message
|
|
623
|
+
useEffect(() => {
|
|
624
|
+
if (messageSent) {
|
|
625
|
+
setMessages(prevMessages => [...prevMessages, messageSent.data]);
|
|
626
|
+
clearEvents();
|
|
627
|
+
}
|
|
628
|
+
}, [messageSent, clearEvents]);
|
|
629
|
+
|
|
630
|
+
// Handle edited message
|
|
631
|
+
useEffect(() => {
|
|
632
|
+
if (messageEdited) {
|
|
633
|
+
setMessages(prevMessages =>
|
|
634
|
+
prevMessages.map(msg =>
|
|
635
|
+
msg.id === messageEdited.data.msg_id
|
|
636
|
+
? { ...msg, content: messageEdited.data.new_content }
|
|
637
|
+
: msg
|
|
638
|
+
)
|
|
639
|
+
);
|
|
640
|
+
clearEvents();
|
|
641
|
+
}
|
|
642
|
+
}, [messageEdited, clearEvents]);
|
|
643
|
+
|
|
644
|
+
// Handle deleted message
|
|
645
|
+
useEffect(() => {
|
|
646
|
+
if (messageDeleted) {
|
|
647
|
+
setMessages(prevMessages =>
|
|
648
|
+
prevMessages.filter(msg => msg.id !== messageDeleted.data.msg_id)
|
|
649
|
+
);
|
|
650
|
+
clearEvents();
|
|
651
|
+
}
|
|
652
|
+
}, [messageDeleted, clearEvents]);
|
|
653
|
+
|
|
654
|
+
return (
|
|
655
|
+
<div>
|
|
656
|
+
<h3>Messages</h3>
|
|
657
|
+
<ul>
|
|
658
|
+
{messages.map(msg => (
|
|
659
|
+
<li key={msg.id}>{msg.content}</li>
|
|
660
|
+
))}
|
|
661
|
+
</ul>
|
|
662
|
+
</div>
|
|
663
|
+
);
|
|
664
|
+
};
|
|
665
|
+
```
|
|
666
|
+
|
|
667
|
+
|
|
668
|
+
## Complete Example
|
|
669
|
+
|
|
670
|
+
For a complete example of how to use the library, see the [example](https://github.com/vahit/chat-react-client/tree/master/example) directory.
|
|
671
|
+
|
|
672
|
+
## License
|
|
673
|
+
|
|
674
|
+
MIT © [vahit](https://github.com/vahit)
|