merge: integrate coding default page

# Conflicts:
#	src/components/layout/Sidebar.tsx
#	tests/unit/coding-chat-panel.test.tsx
This commit is contained in:
inman
2026-09-07 10:10:34 +08:00
12 changed files with 487 additions and 36 deletions

View File

@@ -31,6 +31,10 @@ import {
import { getAiModuleForPath } from '@/lib/ai-modules';
import { invokeIpc } from '@/lib/api-client';
import { getAuthUserDisplayName } from '@/lib/auth-user-display';
import {
subscribeCodingProjectCreationRequest,
subscribeCodingProjectOpenRequest,
} from '@/lib/coding-project-entry';
import { WORKS_SQUARE_TOKEN_USAGE_STALE_EVENT } from '@/lib/works-square-usage-events';
import { fetchWorksTokenUsage, type WorksTokenUsage } from '@/lib/works-square';
import { isWorksTokenUsageExhausted } from '@/lib/works-square-token-usage';
@@ -385,13 +389,18 @@ export function Sidebar({ workspaceLayout = false, sidebarPeekOpen = false, onSi
}, [authUser, refreshTokenUsage]);
const openCreateProject = () => {
const openCreateProject = useCallback(() => {
setNewProjectName('');
setNewProjectSelectedPath('');
setNewProjectDirectoryMode('use-selected-directory');
setCreateProjectError(null);
setCreateDialogOpen(true);
};
}, []);
useEffect(() => {
if (!isProgrammingModule) return undefined;
return subscribeCodingProjectCreationRequest(openCreateProject);
}, [isProgrammingModule, openCreateProject]);
const closeCreateProject = () => {
if (creatingProject) return;
@@ -411,11 +420,11 @@ export function Sidebar({ workspaceLayout = false, sidebarPeekOpen = false, onSi
setCreateProjectError(null);
};
const showProjectEntryError = (project: CodingProjectSummary, message: string) => {
const showProjectEntryError = useCallback((project: CodingProjectSummary, message: string) => {
setProjectEntryError({ project, message });
};
}, []);
const enterProject = async (project: CodingProjectSummary) => {
const enterProject = useCallback(async (project: CodingProjectSummary) => {
const result = await loadProjectConfig(project.id);
if (result.status !== 'valid' || !result.config) {
showProjectEntryError(project, result.status === 'missing' ? '项目缺少必要的配置文件' : result.error ?? '项目配置无效');
@@ -423,16 +432,16 @@ export function Sidebar({ workspaceLayout = false, sidebarPeekOpen = false, onSi
}
await setActiveProject(project.id);
navigate('/chat');
};
}, [loadProjectConfig, navigate, setActiveProject, showProjectEntryError]);
const readAndEnterProject = async (project: CodingProjectSummary) => {
const readAndEnterProject = useCallback(async (project: CodingProjectSummary) => {
setProjectEntryError(null);
try {
await enterProject(project);
} catch (error) {
showProjectEntryError(project, error instanceof Error ? error.message : String(error));
}
};
}, [enterProject, showProjectEntryError]);
const confirmCreateProject = async () => {
@@ -465,9 +474,17 @@ export function Sidebar({ workspaceLayout = false, sidebarPeekOpen = false, onSi
}
};
const openProject = async (project: CodingProjectSummary) => {
const openProject = useCallback(async (project: CodingProjectSummary) => {
await readAndEnterProject(project);
};
}, [readAndEnterProject]);
useEffect(() => {
if (!isProgrammingModule) return undefined;
return subscribeCodingProjectOpenRequest((projectId) => {
const project = visibleProjects.find((candidate) => candidate.id === projectId);
if (project) void openProject(project);
});
}, [isProgrammingModule, openProject, visibleProjects]);
const requestRemoveUnavailableProject = () => {
if (!projectEntryError) return;