Skip to content

Commit 606d586

Browse files
authored
🐛 When a user swipes and taps the chat box, the Dialog status should switch to "read". #1388
2 parents 6f301c4 + d155035 commit 606d586

File tree

5 files changed

+72
-3
lines changed

5 files changed

+72
-3
lines changed

frontend/app/[locale]/chat/internal/chatInterface.tsx

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import type React from "react";
44

5-
import { useState, useRef, useEffect } from "react";
5+
import { useState, useRef, useEffect, useCallback } from "react";
66
import { useRouter } from "next/navigation";
77
import { v4 as uuidv4 } from "uuid";
88
import { useTranslation } from "react-i18next";
@@ -208,6 +208,45 @@ export function ChatInterface() {
208208
setShowRightPanel(false);
209209
}, [conversationManagement.conversationId]);
210210

211+
// Helper function to clear completed conversation indicator
212+
const clearCompletedIndicator = useCallback(() => {
213+
if (
214+
conversationManagement.conversationId &&
215+
conversationManagement.conversationId !== -1
216+
) {
217+
setCompletedConversations((prev) => {
218+
// Use functional update to avoid dependency on completedConversations
219+
if (prev.has(conversationManagement.conversationId)) {
220+
const newSet = new Set(prev);
221+
newSet.delete(conversationManagement.conversationId);
222+
return newSet;
223+
}
224+
return prev;
225+
});
226+
}
227+
}, [conversationManagement.conversationId]);
228+
229+
// Add useEffect to clear completed conversation indicator when user is viewing the current conversation
230+
useEffect(() => {
231+
// If current conversation is in completedConversations, clear it when user is viewing it
232+
clearCompletedIndicator();
233+
}, [conversationManagement.conversationId, clearCompletedIndicator]);
234+
235+
// Add click event listener to clear completed conversation indicator when user clicks anywhere on the page
236+
useEffect(() => {
237+
const handlePageClick = (e: MouseEvent) => {
238+
// Clear completed indicator when user clicks anywhere on the page
239+
clearCompletedIndicator();
240+
};
241+
242+
// Add click event listener to the document
243+
document.addEventListener('click', handlePageClick, true);
244+
245+
return () => {
246+
document.removeEventListener('click', handlePageClick, true);
247+
};
248+
}, [clearCompletedIndicator]);
249+
211250

212251
// Clear all timers and requests when component unmounts
213252
useEffect(() => {
@@ -1635,6 +1674,8 @@ export function ChatInterface() {
16351674
shouldScrollToBottom={shouldScrollToBottom}
16361675
selectedAgentId={selectedAgentId}
16371676
onAgentSelect={setSelectedAgentId}
1677+
onCitationHover={clearCompletedIndicator}
1678+
onScroll={clearCompletedIndicator}
16381679
/>
16391680
</div>
16401681

frontend/app/[locale]/chat/streaming/chatStreamFinalMessage.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ interface FinalMessageProps {
3232
hideButtons?: boolean;
3333
index?: number;
3434
currentConversationId?: number;
35+
onCitationHover?: () => void;
3536
}
3637

3738
// TTS playback status
@@ -48,6 +49,7 @@ export function ChatStreamFinalMessage({
4849
hideButtons = false,
4950
index,
5051
currentConversationId,
52+
onCitationHover,
5153
}: FinalMessageProps) {
5254
const { t } = useTranslation("common");
5355

@@ -269,6 +271,7 @@ export function ChatStreamFinalMessage({
269271
<MarkdownRenderer
270272
content={message.finalAnswer || message.content || ""}
271273
searchResults={message?.searchResults}
274+
onCitationHover={onCitationHover}
272275
/>
273276

274277
{/* Button group - only show when hideButtons is false and message is complete */}
@@ -287,6 +290,11 @@ export function ChatStreamFinalMessage({
287290
isSelected ? "bg-gray-100" : ""
288291
}`}
289292
onClick={handleMessageSelect}
293+
onMouseEnter={() => {
294+
if (onCitationHover) {
295+
onCitationHover();
296+
}
297+
}}
290298
>
291299
<span>
292300
{searchResultsCount > 0 &&

frontend/app/[locale]/chat/streaming/chatStreamMain.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ export function ChatStreamMain({
3737
shouldScrollToBottom,
3838
selectedAgentId,
3939
onAgentSelect,
40+
onCitationHover,
41+
onScroll,
4042
}: ChatStreamMainProps) {
4143
const { t } = useTranslation();
4244
// Animation variants for ChatInput
@@ -325,6 +327,11 @@ export function ChatStreamMain({
325327
setAutoScroll(false);
326328
}
327329
}
330+
331+
// Clear completed conversation indicator when scrolling
332+
if (onScroll) {
333+
onScroll();
334+
}
328335
};
329336

330337
// Add scroll event listener
@@ -336,7 +343,7 @@ export function ChatStreamMain({
336343
return () => {
337344
scrollAreaElement.removeEventListener("scroll", handleScroll);
338345
};
339-
}, [shouldScrollToBottom]);
346+
}, [shouldScrollToBottom, onScroll]);
340347

341348
// Scroll to bottom function
342349
const scrollToBottom = (smooth = false) => {
@@ -544,6 +551,7 @@ export function ChatStreamMain({
544551
onOpinionChange={onOpinionChange}
545552
index={index}
546553
currentConversationId={currentConversationId}
554+
onCitationHover={onCitationHover}
547555
/>
548556
{message.role === "user" &&
549557
processedMessages.conversationGroups.has(message.id!) && (

frontend/components/ui/markdownRenderer.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ interface MarkdownRendererProps {
2828
className?: string;
2929
searchResults?: SearchResult[];
3030
showDiagramToggle?: boolean;
31+
onCitationHover?: () => void;
3132
}
3233

3334
// Get background color for different tool signs
@@ -87,9 +88,11 @@ const CitationBadge = ({
8788
const HoverableText = ({
8889
text,
8990
searchResults,
91+
onCitationHover,
9092
}: {
9193
text: string;
9294
searchResults?: SearchResult[];
95+
onCitationHover?: () => void;
9396
}) => {
9497
const [isOpen, setIsOpen] = React.useState(false);
9598
const containerRef = React.useRef<HTMLSpanElement>(null);
@@ -141,6 +144,11 @@ const HoverableText = ({
141144
clearTimeout(timeoutId);
142145
}
143146

147+
// Clear completed conversation indicator when hovering over citation
148+
if (onCitationHover) {
149+
onCitationHover();
150+
}
151+
144152
// Delay before showing tooltip to avoid quick hover triggers
145153
timeoutId = setTimeout(() => {
146154
setIsOpen(true);
@@ -226,7 +234,7 @@ const HoverableText = ({
226234
container.removeEventListener("mouseenter", handleMouseEnter);
227235
container.removeEventListener("mouseleave", handleMouseLeave);
228236
};
229-
}, [isOpen]);
237+
}, [isOpen, onCitationHover]);
230238

231239
return (
232240
<TooltipProvider>
@@ -355,6 +363,7 @@ export const MarkdownRenderer: React.FC<MarkdownRendererProps> = ({
355363
className,
356364
searchResults = [],
357365
showDiagramToggle = true,
366+
onCitationHover,
358367
}) => {
359368
const { t } = useTranslation("common");
360369

@@ -424,6 +433,7 @@ export const MarkdownRenderer: React.FC<MarkdownRendererProps> = ({
424433
key={index}
425434
text={innerText}
426435
searchResults={searchResults}
436+
onCitationHover={onCitationHover}
427437
/>
428438
);
429439
} else {

frontend/types/chat.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,8 @@ export interface ChatStreamMainProps {
169169
shouldScrollToBottom?: boolean;
170170
selectedAgentId?: number | null;
171171
onAgentSelect?: (agentId: number | null) => void;
172+
onCitationHover?: () => void;
173+
onScroll?: () => void;
172174
}
173175

174176
// Card item type for task window

0 commit comments

Comments
 (0)