Skip to content

Commit a90bd64

Browse files
committed
Fix animation hook to support dynamic default chat name
1 parent 3bf0c2c commit a90bd64

4 files changed

Lines changed: 23 additions & 37 deletions

File tree

packages/react-ui/src/app/features/ai/assistant/assistant-ui-chat.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ const AssistantUiChat = ({
9191
return title;
9292
}, [chatId, chats, title]);
9393

94+
const isTitleDefault = currentChatTitle === title;
95+
9496
const onChatSelected = useCallback(
9597
(id: string) => {
9698
onChatIdChange(id);
@@ -139,7 +141,7 @@ const AssistantUiChat = ({
139141
runtime={runtime}
140142
onNewChat={onNewChatClick}
141143
title={currentChatTitle}
142-
defaultTitle={title}
144+
isTitleDefault={isTitleDefault}
143145
availableModels={availableModels}
144146
onModelSelected={onModelSelected}
145147
isModelSelectorLoading={isModelSelectorLoading}

packages/ui-components/src/components/assistant-ui/assistant-top-bar.tsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ type AssistantTopBarProps = {
1111
onClose: () => void;
1212
onNewChat: () => void;
1313
title?: string;
14-
defaultTitle?: string;
14+
isTitleDefault?: boolean;
1515
onHistoryOpenChange?: (open: boolean) => void;
1616
isHistoryOpen?: boolean;
1717
historyContent?: ReactNode;
@@ -28,15 +28,14 @@ const AssistantTopBar = ({
2828
historyContent,
2929
children,
3030
chatId,
31-
defaultTitle,
31+
isTitleDefault,
3232
}: AssistantTopBarProps) => {
33-
const baseTitle = defaultTitle ?? t('OpenOps Assistant');
33+
const baseTitle = t('OpenOps Assistant');
3434
const animatedTitle = useTypingAnimation({
3535
text: title || baseTitle,
3636
speed: 50,
37-
fromText: baseTitle,
38-
defaultText: baseTitle,
3937
chatId: chatId,
38+
isDefault: isTitleDefault,
4039
});
4140

4241
return (

packages/ui-components/src/components/assistant-ui/assistant-ui-chat-container.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ type AssistantUiChatContainerProps = {
1414
runtime: AssistantRuntime;
1515
toolComponents?: Record<string, ReactNode>;
1616
handleInject?: (codeContent: string | SourceCode) => void;
17+
isTitleDefault?: boolean;
1718
} & ConnectionStatusProps &
1819
AssistantTopBarProps &
1920
ThreadProps;
@@ -36,7 +37,7 @@ const AssistantUiChatContainer = ({
3637
isShowingSlowWarning,
3738
connectionError,
3839
chatId,
39-
defaultTitle,
40+
isTitleDefault,
4041
}: AssistantUiChatContainerProps) => {
4142
const codeVariation = useMemo(() => {
4243
return handleInject
@@ -54,7 +55,7 @@ const AssistantUiChatContainer = ({
5455
isHistoryOpen={isHistoryOpen}
5556
historyContent={children}
5657
chatId={chatId}
57-
defaultTitle={defaultTitle}
58+
isTitleDefault={isTitleDefault}
5859
>
5960
{null}
6061
</AssistantTopBar>

packages/ui-components/src/hooks/use-typing-animation.ts

Lines changed: 13 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,62 +3,46 @@ import { useEffect, useRef, useState } from 'react';
33
type UseTypingAnimationOptions = {
44
text: string;
55
speed?: number;
6-
fromText?: string;
76
chatId?: string | null;
8-
defaultText?: string;
7+
isDefault?: boolean;
98
};
109

1110
export function useTypingAnimation({
1211
text,
1312
speed = 50,
14-
fromText,
1513
chatId,
16-
defaultText,
14+
isDefault,
1715
}: UseTypingAnimationOptions): string {
1816
const [displayedText, setDisplayedText] = useState(text);
19-
const prevTextRef = useRef(text);
20-
const prevChatIdRef = useRef<string | null | undefined>(chatId);
17+
const prevChatIdRef = useRef(chatId);
18+
const prevIsDefaultRef = useRef(isDefault);
2119

2220
useEffect(() => {
23-
let shouldAnimate = false;
24-
let interval: NodeJS.Timeout | undefined;
25-
26-
if (fromText !== undefined && defaultText !== undefined) {
27-
const isSameChat = prevChatIdRef.current === chatId;
28-
const wasDefault =
29-
prevTextRef.current === defaultText || prevTextRef.current === fromText;
30-
const nowHasName = text !== defaultText && text !== fromText;
31-
32-
shouldAnimate = isSameChat && wasDefault && nowHasName;
33-
} else if (fromText !== undefined) {
34-
shouldAnimate = prevTextRef.current === fromText && text !== fromText;
35-
}
21+
const shouldAnimate =
22+
prevChatIdRef.current === chatId &&
23+
prevIsDefaultRef.current === true &&
24+
isDefault === false;
3625

3726
if (shouldAnimate && text.length > 0) {
3827
setDisplayedText('');
3928
let currentIndex = 0;
40-
41-
interval = setInterval(() => {
29+
const interval = setInterval(() => {
4230
if (currentIndex < text.length) {
4331
setDisplayedText(text.slice(0, currentIndex + 1));
4432
currentIndex++;
4533
} else {
4634
clearInterval(interval);
4735
}
4836
}, speed);
37+
38+
return () => clearInterval(interval);
4939
} else {
5040
setDisplayedText(text);
5141
}
5242

53-
prevTextRef.current = text;
5443
prevChatIdRef.current = chatId;
55-
56-
return () => {
57-
if (interval) {
58-
clearInterval(interval);
59-
}
60-
};
61-
}, [text, speed, fromText, chatId, defaultText]);
44+
prevIsDefaultRef.current = isDefault;
45+
}, [text, speed, chatId, isDefault]);
6246

6347
return displayedText;
6448
}

0 commit comments

Comments
 (0)