@pubuduth-aplicy/chat-ui 2.1.38 → 2.1.39

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.38",
3
+ "version": "2.1.39",
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": "",
@@ -1,291 +1,74 @@
1
- // /* eslint-disable @typescript-eslint/no-explicit-any */
2
- // import { useCallback, useEffect, useRef } from "react";
3
- // import Message from "./Message";
4
- // import { useChatContext } from "../../providers/ChatProvider";
5
- // import { useMessages } from "../../hooks/queries/useChatApi";
6
- // import useChatUIStore from "../../stores/Zustant";
7
- // import { useInfiniteQuery } from "@tanstack/react-query";
8
- // import { fetchMessages } from "../../service/messageService";
9
- // import { useInView } from "react-intersection-observer";
10
-
11
- // const Messages = () => {
12
- // const { selectedConversation, setMessages, messages } = useChatUIStore();
13
- // const { userId, socket } = useChatContext();
14
- // const { ref, inView } = useInView();
15
- // const previousScrollHeight = useRef(0);
16
- // const scrollContainerRef = useRef<HTMLDivElement>(null);
17
-
18
- // // const { data, isLoading, isError, error } = useMessages(selectedConversation?._id, userId);
19
-
20
- // const lastMessageRef = useRef<HTMLDivElement>(null);
21
-
22
- // const { data, fetchNextPage, hasNextPage, isFetchingNextPage } =
23
- // useInfiniteQuery({
24
- // queryKey: ["messages", selectedConversation?._id, userId],
25
- // queryFn: ({ pageParam = 1 }) =>
26
- // fetchMessages(selectedConversation?._id, userId, pageParam),
27
- // initialPageParam: 1,
28
- // getNextPageParam: (lastPage, allPages) => {
29
- // return lastPage.messages.length ? allPages.length + 1: undefined;
30
- // },
31
- // });
32
-
33
- // useEffect(() => {
34
- // if (inView) {
35
- // fetchNextPage();
36
- // }
37
- // }, [fetchNextPage, inView]);
38
-
39
- // // useEffect(() => {
40
- // // if (data) {
41
- // // console.log(data,'message data');
42
-
43
- // // setMessages(data.messages);
44
- // // }
45
- // // }, [selectedConversation?._id, data]);
46
-
47
- // useEffect(() => {
48
- // if (data) {
49
- // const allMessages = data.pages.flatMap(page => page.messages);
50
- // setMessages(allMessages);
51
-
52
- // if (scrollContainerRef.current) {
53
- // const newScrollHeight = scrollContainerRef.current.scrollHeight;
54
- // scrollContainerRef.current.scrollTop = newScrollHeight - previousScrollHeight.current;
55
- // }
56
- // }
57
- // }, [data]);
58
-
59
- // // Listen for new messages from the server
60
- // useEffect(() => {
61
- // if (!socket || !selectedConversation?._id) return;
62
-
63
- // // const handleNewMessage = (newMessage: any) => {
64
- // // newMessage.shouldShake = true;
65
- // // console.log("📩 New message received:", newMessage);
66
- // // setMessages((prevMessages) => [...prevMessages, newMessage[1]]);
67
- // // };
68
-
69
- // const handleNewMessage = (newMessage: any) => {
70
- // newMessage.shouldShake = true;
71
- // console.log("📩 New message received:", newMessage);
72
- // setMessages((prevMessages) => {
73
- // const updatedMessages = [...prevMessages, newMessage];
74
- // return [...new Map(updatedMessages.map(m => [m._id, m])).values()]; // Prevent duplicates
75
- // });
76
- // };
77
-
78
-
79
- // const handleStatusUpdate = ({
80
- // messageId,
81
- // status,
82
- // }: {
83
- // messageId: string;
84
- // status: string;
85
- // }) => {
86
- // setMessages((prev) =>
87
- // prev.map((msg) => (msg._id === messageId ? { ...msg, status } : msg))
88
- // );
89
- // };
90
-
91
- // socket.on("newMessage", handleNewMessage);
92
- // socket.on("messageStatusUpdated", handleStatusUpdate);
93
-
94
- // return () => {
95
- // socket.off("newMessage", handleNewMessage);
96
- // socket.off("messageStatusUpdated", handleStatusUpdate);
97
- // };
98
- // }, [socket, setMessages, messages]);
99
-
100
- // // useEffect(() => {
101
- // // setTimeout(() => {
102
- // // lastMessageRef.current?.scrollIntoView({ behavior: "smooth" });
103
- // // }, 100);
104
- // // }, [messages]);
105
-
106
- // useEffect(() => {
107
- // if (!scrollContainerRef.current) return;
108
-
109
- // const { scrollTop, scrollHeight, clientHeight } = scrollContainerRef.current;
110
- // const isAtBottom = scrollHeight - scrollTop <= clientHeight + 100;
111
-
112
- // if (isAtBottom) {
113
- // setTimeout(() => {
114
- // lastMessageRef.current?.scrollIntoView({ behavior: "smooth" });
115
- // }, 100);
116
- // }
117
- // }, [messages]);
118
-
119
-
120
- // useEffect(() => {
121
- // if (!socket || !messages.length) return;
122
-
123
- // const observer = new IntersectionObserver(
124
- // (entries) => {
125
- // entries.forEach((entry) => {
126
- // if (entry.isIntersecting) {
127
- // const messageId = entry.target.getAttribute("data-message-id");
128
- // if (messageId) {
129
- // socket.emit("confirmDelivery", { messageId });
130
- // }
131
- // }
132
- // });
133
- // },
134
- // { threshold: 0.5 }
135
- // );
136
-
137
- // const messageElements = document.querySelectorAll("[data-message-id]");
138
- // messageElements.forEach((el) => observer.observe(el));
139
-
140
- // return () => observer.disconnect();
141
- // }, [messages, socket]);
142
-
143
- // const handleScroll = useCallback(() => {
144
- // if (!scrollContainerRef.current || isFetchingNextPage || !hasNextPage) return;
145
-
146
- // const { scrollTop } = scrollContainerRef.current;
147
-
148
- // if (scrollTop < 50) { // Fetch next page only if close to the top
149
- // fetchNextPage();
150
- // }
151
- // }, [fetchNextPage, isFetchingNextPage, hasNextPage]);
152
-
153
-
154
-
155
- // useEffect(() => {
156
- // const scrollContainer = scrollContainerRef.current;
157
- // if (scrollContainer) {
158
- // scrollContainer.addEventListener("scroll", handleScroll);
159
- // return () => scrollContainer.removeEventListener("scroll", handleScroll);
160
- // }
161
- // }, [handleScroll]);
162
-
163
- // console.log("📩 Messages:", messages);
164
- // console.log("📩 Messages Length:", messages?.length);
165
-
166
- // return (
167
- // <div className="chatMessages">
168
-
169
- // <div ref={ref} className="my-8">
170
- // {isFetchingNextPage ? '<Loading isLoading={isFetchingNextPage} /> ': null}
171
- // </div>
172
- // {messages?.length > 0 ? (
173
- // messages?.map((message: any) =>
174
- // // Check if the message object is valid and has an _id before rendering
175
- // message ? (
176
- // <div key={message._id} ref={lastMessageRef}>
177
- // <Message message={message} />
178
- // </div>
179
- // ) : null
180
- // )
181
- // ) : (
182
- // <p style={{ textAlign: "center" }}>
183
- // Send a message to start the conversation
184
- // </p>
185
- // )}
186
-
187
- // </div>
188
- // );
189
- // };
190
- // export default Messages;
191
-
192
-
193
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
194
- import { useCallback, useEffect, useRef, useState } from "react";
2
+ import { useCallback, useEffect, useRef } from "react";
195
3
  import Message from "./Message";
196
4
  import { useChatContext } from "../../providers/ChatProvider";
197
5
  import { useMessages } from "../../hooks/queries/useChatApi";
198
6
  import useChatUIStore from "../../stores/Zustant";
199
7
  import { useInfiniteQuery } from "@tanstack/react-query";
200
- import { fetchMessages } from "../../service/messageService";// Assuming you have a loading spinner component
8
+ import { fetchMessages } from "../../service/messageService";
9
+ import { useInView } from "react-intersection-observer";
201
10
 
202
11
  const Messages = () => {
203
12
  const { selectedConversation, setMessages, messages } = useChatUIStore();
204
13
  const { userId, socket } = useChatContext();
14
+ const { ref, inView } = useInView();
205
15
  const scrollContainerRef = useRef<HTMLDivElement>(null);
206
- const [isAutoScrolling, setIsAutoScrolling] = useState(false);
207
- const [initialLoad, setInitialLoad] = useState(true);
208
-
209
- const {
210
- data,
211
- fetchNextPage,
212
- hasNextPage,
213
- isFetchingNextPage,
214
- isLoading,
215
- } = useInfiniteQuery({
216
- queryKey: ["messages", selectedConversation?._id, userId],
217
- queryFn: ({ pageParam = 1 }) =>
218
- fetchMessages(selectedConversation?._id, userId, pageParam),
219
- initialPageParam: 1,
220
- getNextPageParam: (lastPage, allPages) => {
221
- return lastPage.messages.length ? allPages.length + 1 : undefined;
222
- },
223
- });
224
-
225
- // Handle merging paginated data with messages
226
- useEffect(() => {
227
- if (data) {
228
- const allMessages = data.pages.flatMap(page => page.messages);
229
- setMessages(allMessages);
230
- }
231
- }, [data, setMessages]);
232
16
 
233
- // Handle scroll position when new messages are loaded
234
- useEffect(() => {
235
- if (!scrollContainerRef.current || initialLoad) return;
17
+ // const { data, isLoading, isError, error } = useMessages(selectedConversation?._id, userId);
236
18
 
237
- const container = scrollContainerRef.current;
238
- if (isFetchingNextPage) {
239
- // Store current scroll position before loading more messages
240
- const scrollTopBefore = container.scrollTop;
241
- const scrollHeightBefore = container.scrollHeight;
242
-
243
- // After messages are loaded, adjust scroll position to maintain view
244
- requestAnimationFrame(() => {
245
- container.scrollTop = container.scrollHeight - scrollHeightBefore + scrollTopBefore;
246
- });
247
- }
248
- }, [isFetchingNextPage, initialLoad]);
19
+ const lastMessageRef = useRef<HTMLDivElement>(null);
249
20
 
250
- // Handle initial scroll to bottom
251
- useEffect(() => {
252
- if (scrollContainerRef.current && messages.length > 0 && initialLoad) {
253
- scrollContainerRef.current.scrollTop = scrollContainerRef.current.scrollHeight;
254
- setInitialLoad(false);
255
- }
256
- }, [messages.length, initialLoad]);
21
+ const { data, fetchNextPage, hasNextPage, isFetchingNextPage } =
22
+ useInfiniteQuery({
23
+ queryKey: ["messages", selectedConversation?._id, userId],
24
+ queryFn: ({ pageParam = 1 }) =>
25
+ fetchMessages(selectedConversation?._id, userId, pageParam),
26
+ initialPageParam: 1,
27
+ getNextPageParam: (lastPage, allPages) => {
28
+ return lastPage.messages.length ? allPages.length + 1: undefined;
29
+ },
30
+ });
257
31
 
258
- // Auto-scroll to bottom when new message arrives and user is near bottom
259
- useEffect(() => {
260
- if (!scrollContainerRef.current || isAutoScrolling) return;
32
+ useEffect(() => {
33
+ if (inView) {
34
+ fetchNextPage();
35
+ }
36
+ }, [fetchNextPage, inView]);
261
37
 
262
- const container = scrollContainerRef.current;
263
- const isNearBottom = container.scrollHeight - container.scrollTop - container.clientHeight < 100;
38
+ // useEffect(() => {
39
+ // if (data) {
40
+ // console.log(data,'message data');
41
+
42
+ // setMessages(data.messages);
43
+ // }
44
+ // }, [selectedConversation?._id, data]);
264
45
 
265
- if (isNearBottom) {
266
- setIsAutoScrolling(true);
267
- container.scrollTo({
268
- top: container.scrollHeight,
269
- behavior: "smooth"
270
- });
271
- setTimeout(() => setIsAutoScrolling(false), 500);
272
- }
273
- }, [messages.length, isAutoScrolling]);
46
+ useEffect(() => {
47
+ if (data) {
48
+ const allMessages = data.pages.flatMap(page => page.messages);
49
+ setMessages(allMessages);
50
+ }
51
+ }, [data]);
274
52
 
275
- // Socket event handlers
53
+ // Listen for new messages from the server
276
54
  useEffect(() => {
277
55
  if (!socket || !selectedConversation?._id) return;
278
56
 
279
- const handleNewMessage = (newMessage: any) => {
280
- newMessage.shouldShake = true;
281
- setMessages((prevMessages) => {
282
- // Prevent duplicates
283
- if (prevMessages.some(msg => msg._id === newMessage._id)) {
284
- return prevMessages;
285
- }
286
- return [...prevMessages, newMessage];
287
- });
288
- };
57
+ // const handleNewMessage = (newMessage: any) => {
58
+ // newMessage.shouldShake = true;
59
+ // console.log("📩 New message received:", newMessage);
60
+ // setMessages((prevMessages) => [...prevMessages, newMessage[1]]);
61
+ // };
62
+
63
+ const handleNewMessage = (newMessage: any) => {
64
+ newMessage.shouldShake = true;
65
+ console.log("📩 New message received:", newMessage);
66
+ setMessages((prevMessages) => {
67
+ const updatedMessages = [...prevMessages, newMessage];
68
+ return [...new Map(updatedMessages.map(m => [m._id, m])).values()]; // Prevent duplicates
69
+ });
70
+ };
71
+
289
72
 
290
73
  const handleStatusUpdate = ({
291
74
  messageId,
@@ -306,9 +89,16 @@ const Messages = () => {
306
89
  socket.off("newMessage", handleNewMessage);
307
90
  socket.off("messageStatusUpdated", handleStatusUpdate);
308
91
  };
309
- }, [socket, setMessages, selectedConversation?._id]);
92
+ }, [socket, setMessages, messages]);
93
+
94
+ useEffect(() => {
95
+ if (messages.length > 0) {
96
+ setTimeout(() => {
97
+ lastMessageRef.current?.scrollIntoView({ behavior: "smooth" });
98
+ }, 100);
99
+ }
100
+ }, [messages.length]);
310
101
 
311
- // Delivery confirmation observer
312
102
  useEffect(() => {
313
103
  if (!socket || !messages.length) return;
314
104
 
@@ -332,62 +122,48 @@ const Messages = () => {
332
122
  return () => observer.disconnect();
333
123
  }, [messages, socket]);
334
124
 
335
- // Scroll handler for infinite loading
336
125
  const handleScroll = useCallback(() => {
337
126
  if (!scrollContainerRef.current || isFetchingNextPage || !hasNextPage) return;
338
-
339
- const container = scrollContainerRef.current;
340
- const scrollTop = container.scrollTop;
341
127
 
342
- // Load more messages when scrolled near the top
343
- if (scrollTop < 100 && !isFetchingNextPage) {
128
+ const { scrollTop } = scrollContainerRef.current;
129
+
130
+ if (scrollTop < 100) {
344
131
  fetchNextPage();
345
132
  }
346
133
  }, [fetchNextPage, isFetchingNextPage, hasNextPage]);
347
134
 
348
- useEffect(() => {
349
- const scrollContainer = scrollContainerRef.current;
350
- if (scrollContainer) {
351
- scrollContainer.addEventListener("scroll", handleScroll);
352
- return () => scrollContainer.removeEventListener("scroll", handleScroll);
353
- }
354
- }, [handleScroll]);
355
-
356
- if (isLoading && !messages.length) {
357
- return <LoadingSpinner />;
358
- }
135
+ // useEffect(() => {
136
+ // const scrollContainer = scrollContainerRef.current;
137
+ // if (scrollContainer) {
138
+ // scrollContainer.addEventListener("scroll", handleScroll);
139
+ // return () => scrollContainer.removeEventListener("scroll", handleScroll);
140
+ // }
141
+ // }, [handleScroll]);
142
+ console.log("📩 Messages:", messages);
143
+ console.log("📩 Messages Length:", messages?.length);
359
144
 
360
145
  return (
361
- <div
362
- ref={scrollContainerRef}
363
- className="chatMessages"
364
- style={{ overflowY: "auto", height: "100%", position: "relative" }}
365
- >
366
- {isFetchingNextPage && (
367
- <div className="loading-indicator">
368
- loading
369
- </div>
370
- )}
371
-
146
+ <div className="chatMessages">
147
+
148
+ <div ref={ref} className="my-8">
149
+ {isFetchingNextPage ? '<Loading isLoading={isFetchingNextPage} /> ': null}
150
+ </div>
372
151
  {messages?.length > 0 ? (
373
- messages.map((message: any) => (
374
- message && (
375
- <div
376
- key={message._id}
377
- data-message-id={message._id}
378
- ref={messages.indexOf(message) === messages.length - 1 ? lastMessageRef : null}
379
- >
152
+ messages?.map((message: any) =>
153
+ // Check if the message object is valid and has an _id before rendering
154
+ message ? (
155
+ <div key={message._id} ref={lastMessageRef}>
380
156
  <Message message={message} />
381
157
  </div>
382
- )
383
- ))
158
+ ) : null
159
+ )
384
160
  ) : (
385
161
  <p style={{ textAlign: "center" }}>
386
162
  Send a message to start the conversation
387
163
  </p>
388
164
  )}
165
+
389
166
  </div>
390
167
  );
391
168
  };
392
-
393
- export default Messages;
169
+ export default Messages;