Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion frontend/src/app/(main)/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ export default function HomePage() {
if (!message.trim()) return;

try {
await createProjectFromPrompt(message, isPublic, model);
const chatId = await createProjectFromPrompt(message, isPublic, model);
promptFormRef.current.clearMessage();
router.push(`/chat?id=${chatId}`);
} catch (error) {
logger.error('Error creating project:', error);
}
Expand Down
14 changes: 3 additions & 11 deletions frontend/src/components/chat/code-engine/project-context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export interface ProjectContextType {
setProjects: React.Dispatch<React.SetStateAction<Project[]>>;
curProject: Project | undefined;
setCurProject: React.Dispatch<React.SetStateAction<Project | undefined>>;
projectLoading: boolean; // 新增字段
projectLoading: boolean;
filePath: string | null;
setFilePath: React.Dispatch<React.SetStateAction<string | null>>;
createNewProject: (projectName: string, description: string) => Promise<void>;
Expand Down Expand Up @@ -404,15 +404,6 @@ export function ProjectProvider({ children }: { children: ReactNode }) {
const [createProject] = useMutation(CREATE_PROJECT, {
onCompleted: (data) => {
if (!isMounted.current) return;

// Navigate to chat page after project creation
if (data?.createProject?.id) {
toast.success('Project created successfully!');
router.push(`/chat?id=${data.createProject.id}`);

// Refresh the projects list
refreshProjects();
}
},
onError: (error) => {
if (isMounted.current) {
Expand Down Expand Up @@ -723,8 +714,9 @@ export function ProjectProvider({ children }: { children: ReactNode }) {
},
},
});
console.log('creatae a project result:', result);

return !!result.data?.createProject;
return result.data.id;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Update function return type in interface definition

The function now returns result.data.id (a string) instead of a boolean, but the interface definition on line 39 still declares the return type as Promise<boolean>. This mismatch should be fixed to maintain type safety.

Apply this change to the interface definition:

  createProjectFromPrompt: (
    prompt: string,
    isPublic: boolean,
    model?: string
-  ) => Promise<boolean>;
+  ) => Promise<string>;

Additionally, the error case on line 725 should be updated to either:

- return false;
+ throw new Error('Failed to create project from prompt');

or

- return false;
+ return '';  // Return empty string for error case
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return result.data.id;
// ----- Interface Definition (around line 39) -----
interface IProjectContext {
createProjectFromPrompt: (
prompt: string,
isPublic: boolean,
model?: string
) => Promise<string>;
// ... other methods
}
// ----- Function Implementation (relevant portions) -----
async function createProjectFromPrompt(prompt: string, isPublic: boolean, model?: string): Promise<string> {
// ... function logic before error handling
// When an error is detected (previously returning a boolean false)
if (/* error condition */) {
- return false;
+ throw new Error('Failed to create project from prompt');
}
// Function now correctly returns a string ID
return result.data.id;
}

} catch (error) {
logger.error('Error creating project:', error);
if (isMounted.current) {
Expand Down
6 changes: 2 additions & 4 deletions frontend/src/components/sidebar-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ function SideBarItemComponent({
}: SideBarItemProps) {
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
const [isDialogOpen, setIsDialogOpen] = useState(false);
const router = useRouter();

const isSelected = currentChatId === id;
const variant = isSelected ? 'secondary' : 'ghost';
Expand All @@ -49,7 +50,7 @@ function SideBarItemComponent({
onCompleted: () => {
toast.success('Chat deleted successfully');
if (isSelected) {
window.history.replaceState({}, '', '/');
router.push('/');
const event = new Event(EventEnum.NEW_CHAT);
window.dispatchEvent(event);
}
Expand Down Expand Up @@ -77,9 +78,6 @@ function SideBarItemComponent({

const handleChatClick = (e: React.MouseEvent) => {
if (!(e.target as HTMLElement).closest('.dropdown-trigger')) {
window.history.replaceState({}, '', `/chat?id=${id}`);
const event = new Event(EventEnum.CHAT);
window.dispatchEvent(event);
onSelect(id);
}
};
Expand Down
53 changes: 30 additions & 23 deletions frontend/src/components/sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
'use client';

import { Button } from '@/components/ui/button';
import Image from 'next/image';
import { memo, useCallback, useContext, useState } from 'react';
Expand All @@ -9,7 +8,7 @@ import { SideBarItem } from './sidebar-item';
import { Chat } from '@/graphql/type';
import { EventEnum } from '../const/EventEnum';
import { useRouter } from 'next/navigation';
import { FixedSizeList } from 'react-window';
import { FixedSizeList, ListChildComponentProps } from 'react-window';

import {
SidebarContent,
Expand All @@ -36,37 +35,41 @@ interface SidebarProps {
setChatListUpdated: (value: boolean) => void;
chats: Chat[];
loading: boolean;
error: any;
error: unknown;
onRefetch: () => void;
}

interface ChatRowData {
chats: Chat[];
currentChatId: string;
onSelect: (chatId: string) => void;
onRefetch: () => void;
}

interface ChatRowProps extends ListChildComponentProps {
data: ChatRowData;
}

// Row renderer for react-window
const ChatRow = memo(
({ index, style, data }: any) => {
const { chats, currentChatId, setCurProject, pollChatProject } = data;
({ index, style, data }: ChatRowProps) => {
const { onSelect, chats, currentChatId, onRefetch } = data;
const chat = chats[index];

const handleSelect = useCallback(() => {
setCurProject(null);
pollChatProject(chat.id).then((p) => {
setCurProject(p);
});
}, [chat.id, setCurProject, pollChatProject]);

return (
<div style={style}>
<SideBarItem
key={chat.id}
id={chat.id}
currentChatId={currentChatId}
title={chat.title}
onSelect={handleSelect}
refetchChats={data.onRefetch}
onSelect={() => onSelect(chat.id)}
refetchChats={onRefetch}
/>
</div>
);
},
(prevProps, nextProps) => {
(prevProps: ChatRowProps, nextProps: ChatRowProps) => {
return (
prevProps.data.chats[prevProps.index].id ===
nextProps.data.chats[nextProps.index].id &&
Expand All @@ -91,18 +94,24 @@ function ChatSideBarComponent({
const { setCurProject, pollChatProject } = useContext(ProjectContext);

const handleNewChat = useCallback(() => {
window.history.replaceState({}, '', '/');
router.push('/');
setCurrentChatid('');
const event = new Event(EventEnum.NEW_CHAT);
window.dispatchEvent(event);
}, []);
}, [router]);

const handleChatSelect = useCallback(
(chatId: string) => {
router.push(`/chat?id=${chatId}`);
setCurrentChatid(chatId);
router.push(`/chat?id=${chatId}`);
setCurProject(null);
pollChatProject(chatId).then((p) => {
setCurProject(p);
});
const event = new Event(EventEnum.CHAT);
window.dispatchEvent(event);
},
[router]
[router, setCurProject, pollChatProject]
);

if (loading) return <SidebarSkeleton />;
Expand Down Expand Up @@ -215,10 +224,8 @@ function ChatSideBarComponent({
itemData={{
chats,
currentChatId: currentChatid,
setCurProject,
pollChatProject,
onRefetch,
onSelect: handleChatSelect,
onRefetch,
}}
>
{ChatRow}
Expand Down Expand Up @@ -247,7 +254,7 @@ function ChatSideBarComponent({
// Optimized memo comparison
export const ChatSideBar = memo(
ChatSideBarComponent,
(prevProps, nextProps) => {
(prevProps: SidebarProps, nextProps: SidebarProps) => {
if (prevProps.isCollapsed !== nextProps.isCollapsed) return false;
if (prevProps.loading !== nextProps.loading) return false;
if (prevProps.error !== nextProps.error) return false;
Expand Down
Loading