@pubuduth-aplicy/chat-ui 2.1.48 → 2.1.50

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pubuduth-aplicy/chat-ui",
3
- "version": "2.1.48",
3
+ "version": "2.1.50",
4
4
  "description": "This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.",
5
5
  "license": "ISC",
6
6
  "author": "",
@@ -21,8 +21,8 @@ const Message = ({ message }: MessageProps) => {
21
21
 
22
22
  const { userId } = useChatContext();
23
23
  const fromMe = message.senderId === userId;
24
- const bubbleBgColor = fromMe ? "chatMessagesBubble_me" : "chatMessagesBubble_Other";
25
- const alignItems = fromMe ? "chatMessagesBubble_me" : "chatMessagesBubble_Other";
24
+ const timestamp = fromMe ? "timestamp_outgoing" : "timestamp_incomeing";
25
+ const alignItems = fromMe ? "outgoing" : "incoming";
26
26
 
27
27
  const date = new Date(message.createdAt);
28
28
  const hours = date.getUTCHours();
@@ -58,19 +58,17 @@ const getStatusIcon = () => {
58
58
  </div>
59
59
  </div> */}
60
60
 
61
- <div className='chatMessage'>
62
- <div className="chatMessagesContainer">
63
- <div style={{color:"#374151"}}>
64
- <div className={`chatMessagesBubble_inner ${alignItems} ${bubbleBgColor} `}>
65
- <p style={{fontSize:"14px"}}>{message.message}</p>
66
- <div className='chatMessagesBubble_Time'> {new Date(message.createdAt).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}</div>
67
- {getStatusIcon()}
68
- </div>
61
+ <div className="chat-container">
62
+ <div className={`message-row ${alignItems}`}>
63
+ <div className="bubble-container">
64
+ <div className="chat-bubble">{message.message}</div>
65
+ <div className={`${timestamp}`}>{new Date(message.createdAt).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}
66
+ <span className="status-icon">{getStatusIcon()}</span>
69
67
  </div>
70
-
71
- {/* <div className="clear-both flex text-gray-700" /> */}
72
- </div>
73
- </div>
68
+ </div>
69
+ </div>
70
+ </div>
71
+
74
72
 
75
73
  </>
76
74
  )
@@ -55,7 +55,7 @@ const MessageInput = () => {
55
55
  setTypingUser(userId);
56
56
  }
57
57
  };
58
-
58
+
59
59
  const handleStopTyping = ({ userId, chatId }: { userId: string; chatId: string }) => {
60
60
  if (chatId === selectedConversation._id) {
61
61
  setTypingUser((prev) => (prev === userId ? null : prev));
@@ -90,7 +90,7 @@ const MessageInput = () => {
90
90
  socket.emit("sendMessage", {
91
91
  chatId: selectedConversation?._id,
92
92
  message,
93
- messageId:data[1]._id,
93
+ messageId: data[1]._id,
94
94
  senderId: userId,
95
95
  receiverId: selectedConversation?.participantDetails._id,
96
96
  });
@@ -127,15 +127,15 @@ const MessageInput = () => {
127
127
  </div>
128
128
 
129
129
  {typingUser && typingUser !== userId && typingUser === selectedConversation?.participantDetails?._id && !isSending && (
130
- <div className="typingIndicator">
131
- <div className="loader">
132
- <div className="ball" />
133
- <div className="ball" />
134
- <div className="ball" />
135
- typing
136
- </div>
137
- </div>
138
- )}
130
+ <div className="typingIndicator">
131
+ <div className="loader">
132
+ <div className="ball" />
133
+ <div className="ball" />
134
+ <div className="ball" />
135
+ typing
136
+ </div>
137
+ </div>
138
+ )}
139
139
 
140
140
  </form>
141
141
  );
@@ -17,31 +17,31 @@ const Messages = () => {
17
17
  const lastMessageRef = useRef<HTMLDivElement>(null);
18
18
 
19
19
  const { data, fetchNextPage, isFetchingNextPage } =
20
- useInfiniteQuery({
21
- queryKey: ["messages", selectedConversation?._id, userId],
22
- queryFn: ({ pageParam = 1 }) =>
23
- fetchMessages(selectedConversation?._id, userId, pageParam),
24
- getNextPageParam: (lastPage) => {
25
- return lastPage.nextPage; // Use the nextPage from API response
26
- },
27
- initialPageParam: 1,
28
- })
29
-
30
-
31
- useEffect(() => {
32
- if (inView) {
33
- fetchNextPage();
34
- }
35
- }, [fetchNextPage, inView]);
36
-
37
-
38
- useEffect(() => {
39
- if (data) {
40
- console.log('message fetching data',data);
41
-
42
- const allMessages = data.pages.flatMap(page => page.messages).reverse();
43
- setMessages(allMessages);
44
- }
20
+ useInfiniteQuery({
21
+ queryKey: ["messages", selectedConversation?._id, userId],
22
+ queryFn: ({ pageParam = 1 }) =>
23
+ fetchMessages(selectedConversation?._id, userId, pageParam),
24
+ getNextPageParam: (lastPage) => {
25
+ return lastPage.nextPage; // Use the nextPage from API response
26
+ },
27
+ initialPageParam: 1,
28
+ })
29
+
30
+
31
+ useEffect(() => {
32
+ if (inView) {
33
+ fetchNextPage();
34
+ }
35
+ }, [fetchNextPage, inView]);
36
+
37
+
38
+ useEffect(() => {
39
+ if (data) {
40
+ console.log('message fetching data', data);
41
+
42
+ const allMessages = data.pages.flatMap(page => page.messages).reverse();
43
+ setMessages(allMessages);
44
+ }
45
45
  }, [data]);
46
46
 
47
47
  // Listen for new messages from the server
@@ -54,15 +54,15 @@ useEffect(() => {
54
54
  setMessages((prevMessages) => [...prevMessages, newMessage[1]]);
55
55
  };
56
56
 
57
- // const handleNewMessage = (newMessage: any) => {
58
- // newMessage.shouldShake = true;
59
- // console.log("📩 New message received:", newMessage);
60
- // setMessages((prevMessages) => {
61
- // const updatedMessages = [...prevMessages, newMessage];
62
- // return [...new Map(updatedMessages.map(m => [m._id, m])).values()]; // Prevent duplicates
63
- // });
64
- // };
65
-
57
+ // const handleNewMessage = (newMessage: any) => {
58
+ // newMessage.shouldShake = true;
59
+ // console.log("📩 New message received:", newMessage);
60
+ // setMessages((prevMessages) => {
61
+ // const updatedMessages = [...prevMessages, newMessage];
62
+ // return [...new Map(updatedMessages.map(m => [m._id, m])).values()]; // Prevent duplicates
63
+ // });
64
+ // };
65
+
66
66
 
67
67
  const handleStatusUpdate = ({
68
68
  messageId,
@@ -87,10 +87,10 @@ useEffect(() => {
87
87
 
88
88
  useEffect(() => {
89
89
  if (messages.length > 0) {
90
- setTimeout(() => {
91
- lastMessageRef.current?.scrollIntoView({ behavior: "smooth" });
92
- }, 100);
93
- }
90
+ setTimeout(() => {
91
+ lastMessageRef.current?.scrollIntoView({ behavior: "smooth" });
92
+ }, 100);
93
+ }
94
94
  }, [messages.length]);
95
95
 
96
96
  useEffect(() => {
@@ -134,27 +134,26 @@ useEffect(() => {
134
134
  // }
135
135
  // }, [handleScroll]);
136
136
 
137
- // useEffect(() => {
138
- // const scrollContainer = scrollContainerRef.current;
139
- // if (scrollContainer) {
140
- // scrollContainer.addEventListener("scroll", handleScroll);
141
- // return () => scrollContainer.removeEventListener("scroll", handleScroll);
142
- // }
143
- // }, [handleScroll]);
144
-
137
+ // useEffect(() => {
138
+ // const scrollContainer = scrollContainerRef.current;
139
+ // if (scrollContainer) {
140
+ // scrollContainer.addEventListener("scroll", handleScroll);
141
+ // return () => scrollContainer.removeEventListener("scroll", handleScroll);
142
+ // }
143
+ // }, [handleScroll]);
145
144
 
146
- console.log("📩 Messages:", messages);
145
+
146
+ console.log("📩 Messages:", messages);
147
147
  console.log("📩 Messages Length:", messages?.length);
148
148
 
149
149
 
150
150
 
151
151
  return (
152
152
  <div className="chatMessages"
153
+ style={{ overflowY: 'auto', height: '100%', position: 'relative' }}
154
+ >
153
155
 
154
- style={{ overflowY: 'auto', height: '100%', position: 'relative' }}
155
- >
156
-
157
- <div ref={ref} className="my-8">
156
+ <div ref={ref} className="my-8">
158
157
  {isFetchingNextPage ? <Loader /> : null}
159
158
  </div>
160
159
  {messages?.length > 0 ? (
@@ -162,8 +161,8 @@ console.log("📩 Messages:", messages);
162
161
  // Check if the message object is valid and has an _id before rendering
163
162
  message ? (
164
163
  <div key={message._id} ref={lastMessageRef}
165
- style={{ flex: 1, minHeight: 0, overflowY: 'auto' }}
166
- >
164
+ style={{ flex: 1, minHeight: 0, overflowY: 'auto' }}
165
+ >
167
166
  <Message message={message} />
168
167
  </div>
169
168
  ) : null
@@ -46,37 +46,34 @@ const Conversation = ({ conversation, lastIdx }: ConversationProps) => {
46
46
  onlineUsers?.includes(conversation.participantDetails._id);
47
47
  return (
48
48
  <>
49
- <div
50
- className={` chatSidebarConversationMain
51
- `}
52
- onClick={handleSelectConversation}
53
- >
54
- <img
55
- className="chatSidebarConversationImg"
56
- src={
57
- conversation.participantDetails?.profilePic ||
58
- conversation.participantDetails?.idpic
59
- }
60
- />
61
- <p className="text-sm text-[#12bbb5]">
62
- {isUserOnline ? "Online" : "Offline"}
63
- </p>
64
- <div className="chatSidebarConversationContainer">
65
- {/* <div className="chatSidebarConversationInnerDiv"> */}
66
- <p className="text-sm text-gray-500">
67
- {conversation.participantDetails?.firstname}
68
- </p>
69
- <p className="chatSidebarConversationOuterDiv">
70
- {conversation.lastMessage.message}
49
+ <div className="conversation-container" onClick={handleSelectConversation}>
50
+ <div className="conversation-avatar">
51
+ <img
52
+ className="conversation-img"
53
+ src={conversation.participantDetails?.profilePic || conversation.participantDetails?.idpic}
54
+ alt="User Avatar"
55
+ />
56
+ <span className={`chatSidebarStatusDot ${isUserOnline ? "online" : "offline"}`}></span>
57
+ </div>
58
+
59
+ <div className="conversation-info">
60
+ <div className="conversation-header">
61
+ <p className="conversation-name">
62
+ {conversation.participantDetails?.firstname}
63
+ </p>
64
+ <span className="conversation-time">
65
+ {new Date(conversation.lastMessage.createdAt).toLocaleTimeString([], {
66
+ hour: "2-digit",
67
+ minute: "2-digit",
68
+ })}
69
+ </span>
70
+ </div>
71
+ <p className="conversation-message">
72
+ {conversation.lastMessage.message.length > 50
73
+ ? conversation.lastMessage.message.slice(0, 50) + "..."
74
+ : conversation.lastMessage.message}
71
75
  </p>
72
- {/* </div> */}
73
76
  </div>
74
- <span className="text-xs text-gray-500">
75
- {new Date(conversation.lastMessage.createdAt).toLocaleTimeString([], {
76
- hour: "2-digit",
77
- minute: "2-digit",
78
- })}
79
- </span>
80
77
  </div>
81
78
 
82
79
  {!lastIdx && <div className="divider my-0 py-0 h-1" />}
@@ -1,14 +1,17 @@
1
+ // apiClient.ts
1
2
  import axios from "axios";
2
3
  import { getChatConfig } from "../../Chat.config";
3
4
 
4
- const { apiUrl } = getChatConfig();
5
- export const apiClient = axios.create({
5
+ export const getApiClient = () => {
6
+ const { apiUrl } = getChatConfig(); // ✅ safe: runs after init
7
+ return axios.create({
6
8
  baseURL: apiUrl,
7
9
  timeout: 5000,
8
- withCredentials:true,
10
+ withCredentials: true,
9
11
  headers: {
10
- 'Content-Type': 'application/json',
12
+ "Content-Type": "application/json",
11
13
  },
12
14
  });
13
-
15
+ };
16
+
14
17
 
@@ -1,5 +1,5 @@
1
1
  export const Path = {
2
- getconversation: "/chat/getConversation",
3
- getmessage: "/chat/getMessage",
4
- sendmessage:"/chat"
2
+ getconversation: "api/chat/getConversation",
3
+ getmessage: "api/chat/getMessage",
4
+ sendmessage:"api/chat"
5
5
  };
@@ -1,8 +1,9 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import { apiClient } from "../lib/api/apiClient";
2
+ import { getApiClient } from "../lib/api/apiClient";
3
3
  import { Path } from "../lib/api/endpoint";
4
4
 
5
5
  export const sendMessage = async ({ chatId,senderId, message }: { chatId: any; senderId:any; message: string }) => {
6
+ const apiClient = getApiClient();
6
7
  const response = await apiClient.post(`${Path.sendmessage}/${chatId}/${senderId}`, {
7
8
  message:message
8
9
  })
@@ -11,6 +12,7 @@ export const sendMessage = async ({ chatId,senderId, message }: { chatId: any; s
11
12
 
12
13
 
13
14
  export const fetchMessages = async (chatId: string|undefined, userid: string,pagenum:number) => {
15
+ const apiClient = getApiClient();
14
16
  try {
15
17
  const response = await apiClient.get(`${Path.getmessage}/${chatId}/${userid}`,{
16
18
  params: { pagenum, limit: 20 },
@@ -1,11 +1,12 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import { apiClient } from "../lib/api/apiClient";
2
+ import { getApiClient } from "../lib/api/apiClient";
3
3
  import { Path } from "../lib/api/endpoint";
4
4
  import { ApiResponse } from "../types/type";
5
5
 
6
6
 
7
7
  export const getAllConversationData = async (userid: string) => {
8
8
  try {
9
+ const apiClient = getApiClient();
9
10
  const res = await apiClient.get<ApiResponse>(`${Path.getconversation}/${userid}`);
10
11
  if (res.data) {
11
12
  console.log("API Response: ", res.data);