@pubuduth-aplicy/chat-ui 2.1.25 → 2.1.27
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/package.json +1 -1
- package/src/components/messages/MessageInput.tsx +46 -27
- package/src/declarations.d.ts +10 -0
- package/src/providers/ChatProvider.tsx +38 -21
- package/src/style/style.css +44 -27
package/package.json
CHANGED
|
@@ -1,45 +1,64 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
import React, { useState } from
|
|
3
|
-
import { useMessageMutation } from
|
|
4
|
-
import { useChatContext } from
|
|
5
|
-
import useChatUIStore from
|
|
2
|
+
import React, { useCallback, useState } from "react";
|
|
3
|
+
import { useMessageMutation } from "../../hooks/mutations/useSendMessage";
|
|
4
|
+
import { useChatContext } from "../../providers/ChatProvider";
|
|
5
|
+
import useChatUIStore from "../../stores/Zustant";
|
|
6
|
+
import paperplane from "../../assets/icons8-send-50.png";
|
|
6
7
|
// import { PaperPlaneRight } from '@phosphor-icons/react'; // Assuming you're using icons from Phosphor Icons library
|
|
7
8
|
// import useSendMessage from '../../hooks/useSendMessage'; // Importing the useSendMessage hook
|
|
8
9
|
|
|
9
10
|
const MessageInput = () => {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
const { socket } = useChatContext();
|
|
12
|
+
const { userId } = useChatContext();
|
|
13
|
+
const { selectedConversation } = useChatUIStore();
|
|
13
14
|
const [message, setMessage] = useState(""); // State for storing the message input
|
|
14
15
|
const { mutate: sendMessage } = useMessageMutation();
|
|
15
16
|
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
17
|
+
const [isSending, setIsSending] = useState(false);
|
|
18
|
+
|
|
19
|
+
const handleSubmit = useCallback(
|
|
20
|
+
async (e: any) => {
|
|
21
|
+
e.preventDefault();
|
|
22
|
+
if (!message || isSending) return;
|
|
23
|
+
|
|
24
|
+
setIsSending(true);
|
|
25
|
+
try {
|
|
26
|
+
console.log("📤 Sending message:", message);
|
|
27
|
+
|
|
28
|
+
if (selectedConversation?._id) {
|
|
29
|
+
sendMessage({
|
|
30
|
+
chatId: selectedConversation.participantDetails._id,
|
|
31
|
+
senderId: userId,
|
|
32
|
+
message,
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
socket.emit("sendMessage", {
|
|
36
|
+
chatId: selectedConversation._id,
|
|
37
|
+
message,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
} catch (error) {
|
|
41
|
+
console.error("❌ Error sending message:", error);
|
|
42
|
+
} finally {
|
|
43
|
+
setIsSending(false);
|
|
44
|
+
setMessage("");
|
|
26
45
|
}
|
|
27
|
-
|
|
28
|
-
|
|
46
|
+
},
|
|
47
|
+
[message, selectedConversation, userId, isSending]
|
|
48
|
+
);
|
|
29
49
|
|
|
30
50
|
return (
|
|
31
|
-
<form className=
|
|
32
|
-
|
|
33
|
-
<div style={{width:"100%"}}>
|
|
51
|
+
<form className="chatMessageInputform" onSubmit={handleSubmit}>
|
|
52
|
+
<div className="chatMessageInputdiv">
|
|
34
53
|
<input
|
|
35
|
-
type=
|
|
36
|
-
className=
|
|
37
|
-
placeholder=
|
|
54
|
+
type="text"
|
|
55
|
+
className="chatMessageInput"
|
|
56
|
+
placeholder="Send a message"
|
|
38
57
|
value={message}
|
|
39
58
|
onChange={(e) => setMessage(e.target.value)} // Update message state as the user types
|
|
40
59
|
/>
|
|
41
|
-
<button type=
|
|
42
|
-
send
|
|
60
|
+
<button type="submit" className="chatMessageInputSubmit">
|
|
61
|
+
<img width={10} height={10} src={paperplane} alt="send" />
|
|
43
62
|
{/* {loading ? <div className='loading loading-spinner'></div> : <PaperPlaneRight />} Show loading spinner if loading */}
|
|
44
63
|
</button>
|
|
45
64
|
</div>
|
package/src/declarations.d.ts
CHANGED
|
@@ -3,4 +3,14 @@ declare module '*.css' {
|
|
|
3
3
|
const content: string;
|
|
4
4
|
export default content;
|
|
5
5
|
}
|
|
6
|
+
|
|
7
|
+
declare module '*.png' {
|
|
8
|
+
const content: string;
|
|
9
|
+
export default content;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
declare module '*.svg' {
|
|
13
|
+
const content: string;
|
|
14
|
+
export default content;
|
|
15
|
+
}
|
|
6
16
|
|
|
@@ -1,48 +1,65 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
|
|
1
|
+
import React, {
|
|
2
|
+
createContext,
|
|
3
|
+
useContext,
|
|
4
|
+
ReactNode,
|
|
5
|
+
useEffect,
|
|
6
|
+
useState,
|
|
7
|
+
useRef,
|
|
8
|
+
} from "react";
|
|
9
|
+
import { Socket, io } from "socket.io-client";
|
|
3
10
|
// import { apiClient } from '../lib/api/apiClient';
|
|
4
11
|
// import { S3Client } from '../lib/storage/s3Client';
|
|
5
12
|
// import { CryptoUtils } from '../lib/encryption/cryptoUtils';
|
|
6
13
|
|
|
7
14
|
interface ChatProviderProps {
|
|
8
|
-
// apiUrl: string;
|
|
9
|
-
// s3Config: {
|
|
10
|
-
// bucket: string;
|
|
11
|
-
// region: string;
|
|
12
|
-
// accessKeyId: string;
|
|
13
|
-
// secretAccessKey: string;
|
|
14
|
-
// };
|
|
15
|
+
// apiUrl: string;
|
|
16
|
+
// s3Config: {
|
|
17
|
+
// bucket: string;
|
|
18
|
+
// region: string;
|
|
19
|
+
// accessKeyId: string;
|
|
20
|
+
// secretAccessKey: string;
|
|
21
|
+
// };
|
|
15
22
|
userId: string; // User ID for identification
|
|
16
23
|
children: ReactNode;
|
|
17
24
|
}
|
|
18
25
|
|
|
19
26
|
interface ChatContextType {
|
|
20
|
-
// s3Client: S3Client;
|
|
27
|
+
// s3Client: S3Client;
|
|
21
28
|
socket: Socket;
|
|
22
|
-
// cryptoUtils: CryptoUtils;
|
|
29
|
+
// cryptoUtils: CryptoUtils;
|
|
23
30
|
userId: string;
|
|
24
31
|
}
|
|
25
32
|
|
|
26
33
|
const ChatContext = createContext<ChatContextType | null>(null);
|
|
27
34
|
|
|
28
|
-
export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
35
|
+
export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
36
|
+
userId,
|
|
37
|
+
children,
|
|
38
|
+
}) => {
|
|
39
|
+
const socketRef = useRef<Socket | null>(null);
|
|
29
40
|
const [socket, setSocket] = useState<Socket | null>(null);
|
|
30
|
-
const apiUrl=import.meta.env.VITE_APP_BACKEND_PORT
|
|
41
|
+
const apiUrl = import.meta.env.VITE_APP_BACKEND_PORT;
|
|
31
42
|
|
|
32
43
|
useEffect(() => {
|
|
33
|
-
|
|
34
|
-
|
|
44
|
+
if (!socketRef.current) {
|
|
45
|
+
console.log("🔌 Creating new socket connection...");
|
|
46
|
+
const socketInstance = io(apiUrl, { auth: { userId } });
|
|
47
|
+
socketRef.current = socketInstance;
|
|
48
|
+
setSocket(socketInstance);
|
|
49
|
+
}
|
|
35
50
|
|
|
36
51
|
return () => {
|
|
37
|
-
|
|
52
|
+
console.log("❌ Disconnecting socket...");
|
|
53
|
+
socketRef.current?.disconnect();
|
|
54
|
+
socketRef.current = null;
|
|
38
55
|
};
|
|
39
56
|
}, [apiUrl, userId]);
|
|
40
57
|
|
|
41
58
|
if (!socket) return null;
|
|
42
59
|
|
|
43
|
-
// const apiClient = new ApiClient(apiUrl);
|
|
44
|
-
// const s3Client = new S3Client(s3Config);
|
|
45
|
-
// const cryptoUtils = new CryptoUtils();
|
|
60
|
+
// const apiClient = new ApiClient(apiUrl);
|
|
61
|
+
// const s3Client = new S3Client(s3Config);
|
|
62
|
+
// const cryptoUtils = new CryptoUtils();
|
|
46
63
|
|
|
47
64
|
return (
|
|
48
65
|
<ChatContext.Provider value={{ socket, userId }}>
|
|
@@ -54,7 +71,7 @@ const apiUrl=import.meta.env.VITE_APP_BACKEND_PORT
|
|
|
54
71
|
export const useChatContext = () => {
|
|
55
72
|
const context = useContext(ChatContext);
|
|
56
73
|
if (!context) {
|
|
57
|
-
throw new Error(
|
|
74
|
+
throw new Error("useChatContext must be used within a ChatProvider");
|
|
58
75
|
}
|
|
59
76
|
return context;
|
|
60
|
-
};
|
|
77
|
+
};
|
package/src/style/style.css
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
grid-template-columns: repeat(1, minmax(0, 1fr));
|
|
5
5
|
border-radius: 0.5rem;
|
|
6
6
|
background-clip: padding-box;
|
|
7
|
-
background-color: #9CA3AF;
|
|
7
|
+
/* background-color: #9CA3AF; */
|
|
8
8
|
--bg-opacity: 0;
|
|
9
9
|
backdrop-blur: blur(16px);
|
|
10
10
|
}
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
.messageContainer {
|
|
20
20
|
grid-column: span 4;
|
|
21
|
-
border: 1px solid;
|
|
21
|
+
/* border: 1px solid; */
|
|
22
22
|
max-height: 100vh;
|
|
23
23
|
overflow-y: auto;
|
|
24
24
|
}
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
|
|
74
74
|
.chatSidebarInput {
|
|
75
75
|
outline-style: none;
|
|
76
|
-
width: 100%;
|
|
76
|
+
/* width: 100%; */
|
|
77
77
|
padding: 8px 4px;
|
|
78
78
|
font-size: 1rem;
|
|
79
79
|
border-radius: 4px;
|
|
@@ -94,7 +94,7 @@
|
|
|
94
94
|
.chatSidebarConversationMain {
|
|
95
95
|
display: inline-flex;
|
|
96
96
|
padding: 0.5rem;
|
|
97
|
-
margin-top: 0.875rem;
|
|
97
|
+
margin-top: 0.875rem;
|
|
98
98
|
/* padding-top: 0.75rem;
|
|
99
99
|
padding-bottom: 0.75rem; */
|
|
100
100
|
gap: 0.75rem;
|
|
@@ -202,7 +202,7 @@
|
|
|
202
202
|
}
|
|
203
203
|
|
|
204
204
|
.chatMessageContainerOutterDiv {
|
|
205
|
-
display: inline-flex;
|
|
205
|
+
/* display: inline-flex; */
|
|
206
206
|
justify-content: flex-start;
|
|
207
207
|
align-items: center;
|
|
208
208
|
align-self: stretch;
|
|
@@ -248,19 +248,21 @@
|
|
|
248
248
|
|
|
249
249
|
.chatMessagesBubble_me {
|
|
250
250
|
float: right;
|
|
251
|
-
background-color: #
|
|
251
|
+
background-color: #12bbb5;
|
|
252
|
+
color: white;
|
|
252
253
|
}
|
|
253
254
|
|
|
254
255
|
.chatMessagesBubble_Other {
|
|
255
256
|
float: left;
|
|
256
|
-
background-color: #
|
|
257
|
+
background-color: #f3f4f6;
|
|
258
|
+
color: #374151;
|
|
257
259
|
}
|
|
258
260
|
|
|
259
261
|
.chatMessage {
|
|
260
262
|
overflow-y: auto;
|
|
261
263
|
padding-left: 2rem;
|
|
262
|
-
padding-right: 2rem;
|
|
263
|
-
padding-top:
|
|
264
|
+
/* padding-right: 2rem; */
|
|
265
|
+
padding-top: 0.5rem;
|
|
264
266
|
flex-grow: 1;
|
|
265
267
|
max-height: 100vh;
|
|
266
268
|
text-align: left;
|
|
@@ -274,34 +276,42 @@
|
|
|
274
276
|
}
|
|
275
277
|
|
|
276
278
|
.chatMessagesBubble_inner {
|
|
277
|
-
|
|
279
|
+
max-width: 250px;
|
|
280
|
+
padding: 10px 15px;
|
|
281
|
+
border-radius: 15px;
|
|
278
282
|
position: relative;
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
border-radius: 0.375rem;
|
|
284
|
-
color: #ffffff;
|
|
283
|
+
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
|
284
|
+
font-size: 14px;
|
|
285
|
+
display: inline-block;
|
|
286
|
+
text-align: left;
|
|
285
287
|
word-break: break-all;
|
|
286
288
|
}
|
|
287
289
|
|
|
290
|
+
|
|
288
291
|
.chatMessagesBubble_Time {
|
|
289
|
-
display:
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
line-height: 1rem;
|
|
295
|
-
opacity: 0.5;
|
|
292
|
+
display: block;
|
|
293
|
+
text-align: right;
|
|
294
|
+
font-size: 10px;
|
|
295
|
+
color: #d1d1d1;
|
|
296
|
+
margin-top: 5px;
|
|
296
297
|
}
|
|
297
298
|
|
|
298
|
-
.
|
|
299
|
+
.chatMessageInputform {
|
|
299
300
|
position: sticky;
|
|
300
301
|
bottom: 0;
|
|
302
|
+
background: #dbdbdb;
|
|
301
303
|
padding-left: 1rem;
|
|
302
304
|
padding-right: 1rem;
|
|
305
|
+
padding-top: 0.25rem;
|
|
306
|
+
padding-bottom: 0.25rem;
|
|
303
307
|
margin-top: 0.75rem;
|
|
304
|
-
margin-bottom: 0.75rem;
|
|
308
|
+
/* margin-bottom: 0.75rem; */
|
|
309
|
+
}
|
|
310
|
+
.chatMessageInputdiv {
|
|
311
|
+
display: flex;
|
|
312
|
+
align-items: center;
|
|
313
|
+
border-top: 1px;
|
|
314
|
+
gap: 8px;
|
|
305
315
|
}
|
|
306
316
|
|
|
307
317
|
.chatMessageInput {
|
|
@@ -312,16 +322,23 @@
|
|
|
312
322
|
border-style: none;
|
|
313
323
|
outline-style: none;
|
|
314
324
|
width: 100%;
|
|
325
|
+
max-height: 11.76em;
|
|
326
|
+
min-height: 1.47em;
|
|
327
|
+
white-space: pre-wrap;
|
|
328
|
+
word-break: break-all;
|
|
315
329
|
font-size: 0.875rem;
|
|
316
330
|
line-height: 1.25rem;
|
|
317
331
|
}
|
|
318
332
|
|
|
319
333
|
.chatMessageInputSubmit {
|
|
320
|
-
display: flex;
|
|
334
|
+
/* display: flex;
|
|
321
335
|
position: absolute;
|
|
322
336
|
top: 0;
|
|
323
337
|
bottom: 0;
|
|
324
|
-
align-items: center;
|
|
338
|
+
align-items: center; */
|
|
339
|
+
padding: 8px;
|
|
340
|
+
border-radius: 100%;
|
|
341
|
+
background: #12bbb5;
|
|
325
342
|
}
|
|
326
343
|
|
|
327
344
|
@media (min-width: 640px) {
|