Skip to content

Commit 7d87301

Browse files
author
pengyu
committed
adjust the bugs for sending getchatdetail twice
1 parent afb5868 commit 7d87301

File tree

4 files changed

+203
-144
lines changed

4 files changed

+203
-144
lines changed

frontend/src/components/chat/code-engine/code-engine.tsx

Lines changed: 37 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -71,39 +71,27 @@ export function CodeEngine({
7171
}
7272
}, [chatId]);
7373

74-
// Poll for project if needed using chatId
7574
useEffect(() => {
76-
// 如果项目已经完成,跳过轮询
77-
if (projectCompleted || isProjectLoadedRef.current) {
78-
return;
79-
}
80-
81-
if (!curProject && chatId && !projectLoading) {
82-
const loadProjectFromChat = async () => {
83-
try {
84-
setIsLoading(true);
85-
const project = await pollChatProject(chatId);
86-
if (project) {
87-
setLocalProject(project);
88-
// 如果成功加载项目,将状态设置为已完成
89-
if (project.projectPath) {
90-
setProjectCompleted(true);
91-
isProjectLoadedRef.current = true;
92-
}
93-
}
94-
} catch (error) {
95-
logger.error('Failed to load project from chat:', error);
96-
} finally {
97-
setIsLoading(false);
98-
}
99-
};
75+
// 如果全局轮询完毕,projectPath 可用了,就完成 loading bar
76+
if (
77+
curProject?.id === chatId &&
78+
curProject?.projectPath &&
79+
!projectCompleted &&
80+
!isProjectLoadedRef.current
81+
) {
82+
setProgress(100);
83+
setTimerActive(false);
84+
setIsCompleting(false);
85+
setProjectCompleted(true);
86+
isProjectLoadedRef.current = true;
10087

101-
loadProjectFromChat();
102-
} else {
103-
setIsLoading(projectLoading);
88+
try {
89+
localStorage.setItem(`project-completed-${chatId}`, 'true');
90+
} catch (e) {
91+
logger.error('Failed to save project completion status:', e);
92+
}
10493
}
105-
}, [chatId, curProject, projectLoading, pollChatProject, projectCompleted]);
106-
94+
}, [curProject?.projectPath, chatId, projectCompleted]);
10795
// Use either curProject from context or locally polled project
10896
const activeProject = curProject || localProject;
10997

@@ -148,6 +136,9 @@ export function CodeEngine({
148136
!isFileStructureLoading;
149137

150138
if (shouldFetchFiles) {
139+
setIsLoading(false);
140+
setProjectCompleted(true);
141+
isProjectLoadedRef.current = true;
151142
fetchFiles();
152143
}
153144
}, [
@@ -451,12 +442,22 @@ export function CodeEngine({
451442
)}
452443

453444
<div className="w-64 flex flex-col items-center">
454-
<p className="text-sm text-muted-foreground mb-2">
455-
{progress === 100
456-
? 'Project ready!'
457-
: projectLoading
458-
? 'Loading project...'
459-
: `Initializing project (${progress}%)`}
445+
<p className="text-sm text-muted-foreground mb-2 text-center flex flex-col items-center">
446+
{progress === 100 ? (
447+
<span>Project ready!</span>
448+
) : (
449+
<>
450+
{estimateTime > 0 ? (
451+
<span className="text-xs text-muted-foreground">
452+
Preparing your project (about 5-6 minutes)…
453+
</span>
454+
) : (
455+
<span className="text-xs text-orange-500">
456+
Still working on it... thanks for your patience 🙏
457+
</span>
458+
)}
459+
</>
460+
)}
460461
</p>
461462

462463
<div className="w-full bg-gray-200 dark:bg-gray-700 rounded-full h-2.5 mb-1">

frontend/src/components/global-toast-listener.tsx

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,28 @@ import { ProjectContext } from './chat/code-engine/project-context';
66
import { logger } from '@/app/log/logger';
77
import { ProjectReadyToast } from './project-ready-toast';
88

9+
const COMPLETED_CACHE_KEY = 'completedChatIds';
10+
11+
const getCompletedFromLocalStorage = (): Set<string> => {
12+
try {
13+
const raw = localStorage.getItem(COMPLETED_CACHE_KEY);
14+
if (raw) {
15+
return new Set(JSON.parse(raw));
16+
}
17+
} catch (e) {
18+
logger.warn('Failed to read completedChatIds from localStorage');
19+
}
20+
return new Set();
21+
};
22+
23+
const saveCompletedToLocalStorage = (set: Set<string>) => {
24+
try {
25+
localStorage.setItem(COMPLETED_CACHE_KEY, JSON.stringify(Array.from(set)));
26+
} catch (e) {
27+
logger.warn('Failed to save completedChatIds to localStorage');
28+
}
29+
};
30+
931
const GlobalToastListener = () => {
1032
const {
1133
recentlyCompletedProjectId,
@@ -15,53 +37,52 @@ const GlobalToastListener = () => {
1537
} = useContext(ProjectContext);
1638
const router = useRouter();
1739
const intervalRef = useRef<NodeJS.Timeout | null>(null);
40+
const completedIdsRef = useRef<Set<string>>(getCompletedFromLocalStorage());
1841

19-
// optional: if you use this in your logic
20-
const setCurrentChatid = (id: string) => {}; // or import your actual setter
42+
const setCurrentChatid = (id: string) => {};
2143

2244
useEffect(() => {
23-
if (!recentlyCompletedProjectId) return;
45+
const chatId = recentlyCompletedProjectId;
2446

25-
const checkProjectReady = async () => {
47+
if (!chatId || completedIdsRef.current.has(chatId)) return;
48+
49+
intervalRef.current = setInterval(async () => {
2650
try {
27-
const project = await pollChatProject(recentlyCompletedProjectId);
51+
const project = await pollChatProject(chatId);
2852

2953
if (project?.projectPath) {
3054
toast.custom(
3155
(t) => (
3256
<ProjectReadyToast
33-
chatId={recentlyCompletedProjectId}
57+
chatId={chatId}
3458
close={() => toast.dismiss(t)}
3559
router={router}
3660
setCurrentChatid={setCurrentChatid}
3761
setChatId={setChatId}
3862
/>
3963
),
40-
{
41-
duration: 30000,
42-
}
64+
{ duration: 10000 }
4365
);
4466

67+
completedIdsRef.current.add(chatId);
68+
saveCompletedToLocalStorage(completedIdsRef.current);
69+
4570
setRecentlyCompletedProjectId(null);
4671

4772
if (intervalRef.current) {
4873
clearInterval(intervalRef.current);
4974
intervalRef.current = null;
5075
}
5176
} else {
52-
logger.debug('Project not ready yet, will retry...');
77+
logger.debug(`Chat ${chatId} not ready yet...`);
5378
}
54-
} catch (err) {
55-
logger.error('Error polling project status:', err);
79+
} catch (e) {
80+
logger.error('pollChatProject error:', e);
5681
}
57-
};
58-
59-
intervalRef.current = setInterval(checkProjectReady, 5000);
82+
}, 6000);
6083

6184
return () => {
62-
if (intervalRef.current) {
63-
clearInterval(intervalRef.current);
64-
}
85+
if (intervalRef.current) clearInterval(intervalRef.current);
6586
};
6687
}, [recentlyCompletedProjectId]);
6788

frontend/src/components/project-ready-toast.tsx

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,36 +21,58 @@ export const ProjectReadyToast = ({
2121
}: ProjectReadyToastProps) => {
2222
return (
2323
<motion.div
24-
className="w-[360px] p-4 rounded-xl bg-green-50 dark:bg-green-900 text-green-800 dark:text-green-100 shadow-lg flex flex-col gap-2 relative"
25-
initial={{ opacity: 0, y: 30, scale: 0.95 }}
24+
initial={{ opacity: 0, y: 40, scale: 0.95 }}
2625
animate={{ opacity: 1, y: 0, scale: 1 }}
27-
exit={{ opacity: 0, y: 30, scale: 0.95 }}
28-
transition={{ type: 'spring', stiffness: 260, damping: 20 }}
26+
exit={{ opacity: 0, y: 40, scale: 0.95 }}
27+
transition={{
28+
type: 'spring',
29+
stiffness: 260,
30+
damping: 20,
31+
duration: 0.4,
32+
}}
33+
className="fixed bottom-24 right-6 z-[9999] w-[360px] px-5 py-4
34+
bg-white dark:bg-zinc-900 text-gray-800 dark:text-gray-100
35+
border border-gray-200 dark:border-zinc-700
36+
rounded-lg shadow-2xl flex items-center justify-between gap-4"
2937
>
30-
{/* Close button */}
31-
<button
32-
onClick={close}
33-
className="absolute top-2 right-2 text-green-500 hover:text-green-700 dark:hover:text-green-300"
34-
>
35-
<X size={18} />
36-
</button>
37-
38-
{/* Title */}
39-
<p className="text-base font-semibold text-center mt-2">
40-
🎉 Project is ready!
41-
</p>
38+
{/* Left: Icon + Text */}
39+
<div className="flex items-center gap-2">
40+
<div className="bg-green-100 dark:bg-green-800 text-green-600 dark:text-green-300 rounded-full p-1">
41+
<svg
42+
xmlns="http://www.w3.org/2000/svg"
43+
className="w-4 h-4"
44+
fill="none"
45+
viewBox="0 0 24 24"
46+
stroke="currentColor"
47+
>
48+
<path
49+
strokeLinecap="round"
50+
strokeLinejoin="round"
51+
strokeWidth={2}
52+
d="M5 13l4 4L19 7"
53+
/>
54+
</svg>
55+
</div>
56+
<span className="text-sm font-medium">Project is ready!</span>
57+
</div>
4258

43-
{/* Centered Button */}
44-
<div className="flex justify-center mt-2">
59+
{/* Right: Open Chat + Close */}
60+
<div className="flex items-center gap-2">
4561
<button
4662
onClick={() => {
4763
redirectChatPage(chatId, setCurrentChatid, setChatId, router);
4864
close();
4965
}}
50-
className="bg-green-600 hover:bg-green-700 text-white px-4 py-2 rounded-md text-sm font-medium transition-all"
66+
className="text-sm px-3 py-1.5 rounded-md bg-green-600 hover:bg-green-700 text-white transition"
5167
>
5268
Open Chat
5369
</button>
70+
<button
71+
onClick={close}
72+
className="text-gray-400 hover:text-gray-600 dark:hover:text-gray-300"
73+
>
74+
<X size={16} />
75+
</button>
5476
</div>
5577
</motion.div>
5678
);

0 commit comments

Comments
 (0)