@pubuduth-aplicy/chat-ui 2.1.40 → 2.1.41

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.40",
3
+ "version": "2.1.41",
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": "",
@@ -7,7 +7,7 @@ import useChatUIStore from "../../stores/Zustant";
7
7
  import { useInfiniteQuery } from "@tanstack/react-query";
8
8
  import { fetchMessages } from "../../service/messageService";
9
9
  import { useInView } from "react-intersection-observer";
10
- import Loader from "../loader";
10
+ import Loader from "../Loader";
11
11
 
12
12
  const Messages = () => {
13
13
  const { selectedConversation, setMessages, messages } = useChatUIStore();
@@ -16,68 +16,135 @@ const Messages = () => {
16
16
  const scrollContainerRef = useRef<HTMLDivElement>(null);
17
17
  const [isInitialLoad, setIsInitialLoad] = useState(true);
18
18
  const [isAutoScrolling, setIsAutoScrolling] = useState(false);
19
-
20
-
19
+ const [prevMessagesLength, setPrevMessagesLength] = useState(0);
20
+ const loadingRef = useRef(false);
21
21
  // const { data, isLoading, isError, error } = useMessages(selectedConversation?._id, userId);
22
22
 
23
23
  const lastMessageRef = useRef<HTMLDivElement>(null);
24
24
 
25
- // const { data, fetchNextPage, hasNextPage, isFetchingNextPage } =
26
- // useInfiniteQuery({
27
- // queryKey: ["messages", selectedConversation?._id, userId],
28
- // queryFn: ({ pageParam = 1 }) =>
29
- // fetchMessages(selectedConversation?._id, userId, pageParam),
30
- // initialPageParam: 1,
31
- // getNextPageParam: (lastPage, allPages) => {
32
- // return lastPage.messages.length ? allPages.length + 1: undefined;
33
- // },
34
- // });
35
-
36
-
37
- const {
38
- data,
39
- fetchNextPage,
40
- hasNextPage,
41
- isFetchingNextPage,
42
- isLoading,
43
- } = useInfiniteQuery({
25
+ const { data, fetchNextPage, hasNextPage, isFetchingNextPage } =
26
+ useInfiniteQuery({
44
27
  queryKey: ["messages", selectedConversation?._id, userId],
45
28
  queryFn: ({ pageParam = 1 }) =>
46
29
  fetchMessages(selectedConversation?._id, userId, pageParam),
47
- getNextPageParam: (lastPage) => lastPage.nextPage ?? undefined,
48
- onSuccess: (data) => {
49
- const allMessages = data.pages.flatMap(page => page.messages);
50
- setMessages(allMessages);
51
-
52
- // Scroll to bottom on initial load
53
- if (isInitialLoad && scrollContainerRef.current) {
54
- setTimeout(() => {
55
- scrollContainerRef.current?.scrollTo({
56
- top: scrollContainerRef.current.scrollHeight,
57
- behavior: 'auto'
58
- });
59
- setIsInitialLoad(false);
60
- }, 100);
61
- }
30
+ getNextPageParam: (lastPage) => {
31
+ return lastPage.nextPage; // Use the nextPage from API response
62
32
  },
33
+ initialPageParam: 1,
63
34
  });
64
35
 
65
- // Auto-scroll to bottom when new message arrives and user is near bottom
66
- useEffect(() => {
67
- if (!scrollContainerRef.current || isAutoScrolling) return;
68
-
69
- const container = scrollContainerRef.current;
70
- const isNearBottom = container.scrollHeight - container.scrollTop - container.clientHeight < 100;
71
-
72
- if (isNearBottom) {
73
- setIsAutoScrolling(true);
74
- container.scrollTo({
75
- top: container.scrollHeight,
76
- behavior: "smooth"
77
- });
78
- setTimeout(() => setIsAutoScrolling(false), 500);
79
- }
80
- }, [messages.length, isAutoScrolling]);
36
+ const [isLoadingMore, setIsLoadingMore] = useState(false);
37
+ const scrollHeightBeforeLoad = useRef(0);
38
+
39
+ const handleScroll = useCallback(() => {
40
+ if (!scrollContainerRef.current || isFetchingNextPage || !hasNextPage) return;
41
+
42
+ const { scrollTop, scrollHeight, clientHeight } = scrollContainerRef.current;
43
+
44
+ // Load more when scrolled near the top (100px threshold)
45
+ if (scrollTop < 100) {
46
+ // Save current scroll height before loading
47
+ scrollHeightBeforeLoad.current = scrollHeight;
48
+ setIsLoadingMore(true);
49
+ fetchNextPage().finally(() => setIsLoadingMore(false));
50
+ }
51
+ }, [fetchNextPage, isFetchingNextPage, hasNextPage]);
52
+
53
+ useEffect(() => {
54
+ if (isLoadingMore && scrollContainerRef.current && scrollHeightBeforeLoad.current) {
55
+ // After new messages are loaded, adjust scroll position to maintain the same view
56
+ const container = scrollContainerRef.current;
57
+ const newScrollHeight = container.scrollHeight;
58
+ container.scrollTop = newScrollHeight - scrollHeightBeforeLoad.current;
59
+ }
60
+ }, [messages.length, isLoadingMore]);
61
+
62
+ // Scroll to bottom for new messages
63
+ useEffect(() => {
64
+ if (messages.length > 0 && !isLoadingMore) {
65
+ setTimeout(() => {
66
+ lastMessageRef.current?.scrollIntoView({ behavior: "smooth" });
67
+ }, 100);
68
+ }
69
+ }, [messages.length, isLoadingMore]);
70
+
71
+
72
+ // const {
73
+ // data,
74
+ // fetchNextPage,
75
+ // hasNextPage,
76
+ // isFetchingNextPage,
77
+ // isLoading,
78
+ // } = useInfiniteQuery({
79
+ // queryKey: ["messages", selectedConversation?._id, userId],
80
+ // queryFn: ({ pageParam = 1 }) =>
81
+ // fetchMessages(selectedConversation?._id, userId, pageParam),
82
+ // getNextPageParam: (lastPage) => lastPage.nextPage ?? undefined,
83
+ // onSuccess: (data) => {
84
+ // const allMessages = data.pages.flatMap(page => page.messages);
85
+ // setMessages(allMessages);
86
+
87
+ // // Scroll to bottom on initial load
88
+ // if (isInitialLoad && scrollContainerRef.current) {
89
+ // setTimeout(() => {
90
+ // scrollContainerRef.current?.scrollTo({
91
+ // top: scrollContainerRef.current.scrollHeight,
92
+ // behavior: 'auto'
93
+ // });
94
+ // setIsInitialLoad(false);
95
+ // }, 100);
96
+ // }
97
+ // },
98
+ // });
99
+
100
+ // Maintain scroll position when loading older messages
101
+
102
+
103
+ // useEffect(() => {
104
+ // console.log('scrollContainerRef',scrollContainerRef.current);
105
+
106
+ // if (!scrollContainerRef.current || isInitialLoad) return;
107
+
108
+ // if (isFetchingNextPage) {
109
+ // // Store current scroll position before loading
110
+ // const container = scrollContainerRef.current;
111
+ // const scrollTopBefore = container.scrollTop;
112
+ // const scrollHeightBefore = container.scrollHeight;
113
+ // console.log(container,'scrollHeightBefore',scrollHeightBefore,'container',scrollTopBefore);
114
+
115
+ // loadingRef.current = true;
116
+
117
+ // return () => {
118
+ // // After messages are loaded, adjust scroll position
119
+ // requestAnimationFrame(() => {
120
+ // container.scrollTop = container.scrollHeight - scrollHeightBefore + scrollTopBefore;
121
+ // loadingRef.current = false;
122
+ // });
123
+ // };
124
+ // }
125
+ // }, [isFetchingNextPage, isInitialLoad]);
126
+
127
+ // Add this useEffect to handle new messages
128
+ // useEffect(() => {
129
+ // if (!scrollContainerRef.current || loadingRef.current) return;
130
+
131
+ // const container = scrollContainerRef.current;
132
+ // console.log("container",container);
133
+
134
+ // const isNearBottom = container.scrollHeight - container.scrollTop - container.clientHeight < 100;
135
+
136
+ // // Only auto-scroll if we're near bottom or it's a new message
137
+ // if (isNearBottom || messages.length > prevMessagesLength) {
138
+ // setIsAutoScrolling(true);
139
+ // container.scrollTo({
140
+ // top: container.scrollHeight,
141
+ // behavior: messages.length > prevMessagesLength ? 'smooth' : 'auto'
142
+ // });
143
+ // setTimeout(() => setIsAutoScrolling(false), 500);
144
+ // }
145
+
146
+ // setPrevMessagesLength(messages.length);
147
+ // }, [messages.length]);
81
148
 
82
149
  useEffect(() => {
83
150
  if (inView) {
@@ -95,7 +162,9 @@ const {
95
162
 
96
163
  useEffect(() => {
97
164
  if (data) {
98
- const allMessages = data.pages.flatMap(page => page.messages);
165
+ console.log('message fetching data',data);
166
+
167
+ const allMessages = data.pages.flatMap(page => page.messages).reverse();
99
168
  setMessages(allMessages);
100
169
  }
101
170
  }, [data]);
@@ -172,23 +241,23 @@ useEffect(() => {
172
241
  return () => observer.disconnect();
173
242
  }, [messages, socket]);
174
243
 
175
- const handleScroll = useCallback(() => {
176
- if (!scrollContainerRef.current || isFetchingNextPage || !hasNextPage) return;
244
+ // const handleScroll = useCallback(() => {
245
+ // if (!scrollContainerRef.current || isFetchingNextPage || !hasNextPage) return;
177
246
 
178
- const { scrollTop } = scrollContainerRef.current;
179
- // Load more when scrolled near the top (10% threshold)
180
- if (scrollTop < 100) {
181
- fetchNextPage();
182
- }
183
- }, [fetchNextPage, isFetchingNextPage, hasNextPage]);
247
+ // const { scrollTop } = scrollContainerRef.current;
248
+ // // Load more when scrolled near the top (10% threshold)
249
+ // if (scrollTop < 100) {
250
+ // fetchNextPage();
251
+ // }
252
+ // }, [fetchNextPage, isFetchingNextPage, hasNextPage]);
184
253
 
185
- useEffect(() => {
186
- const container = scrollContainerRef.current;
187
- if (container) {
188
- container.addEventListener('scroll', handleScroll);
189
- return () => container.removeEventListener('scroll', handleScroll);
190
- }
191
- }, [handleScroll]);
254
+ // useEffect(() => {
255
+ // const container = scrollContainerRef.current;
256
+ // if (container) {
257
+ // container.addEventListener('scroll', handleScroll);
258
+ // return () => container.removeEventListener('scroll', handleScroll);
259
+ // }
260
+ // }, [handleScroll]);
192
261
 
193
262
  // useEffect(() => {
194
263
  // const scrollContainer = scrollContainerRef.current;
@@ -197,28 +266,29 @@ useEffect(() => {
197
266
  // return () => scrollContainer.removeEventListener("scroll", handleScroll);
198
267
  // }
199
268
  // }, [handleScroll]);
200
- console.log("📩 Messages:", messages);
269
+
270
+
271
+ console.log("📩 Messages:", messages);
201
272
  console.log("📩 Messages Length:", messages?.length);
202
273
 
203
- if (isLoading && !messages.length) {
204
- return <Loader />;
205
- }
274
+
206
275
 
207
276
  return (
208
277
  <div className="chatMessages"
209
278
  ref={scrollContainerRef}
210
279
  style={{ overflowY: 'auto', height: '100%', position: 'relative' }}
211
280
  >
212
- {isFetchingNextPage && (
213
- <div className="loading-indicator">
214
- <Loader/>
215
- </div>
216
- )}
281
+
282
+ <div ref={ref} className="my-8">
283
+ {isFetchingNextPage ? <Loader /> : null}
284
+ </div>
217
285
  {messages?.length > 0 ? (
218
286
  messages?.map((message: any) =>
219
287
  // Check if the message object is valid and has an _id before rendering
220
288
  message ? (
221
- <div key={message._id} ref={lastMessageRef}>
289
+ <div key={message._id} ref={lastMessageRef}
290
+ style={{ flex: 1, minHeight: 0, overflowY: 'auto' }}
291
+ >
222
292
  <Message message={message} />
223
293
  </div>
224
294
  ) : null