feat: update Makelore modules and conversations
Some checks failed
Electron E2E / Electron E2E (macos-latest) (push) Has been cancelled
Electron E2E / Electron E2E (ubuntu-latest) (push) Has been cancelled
Electron E2E / Electron E2E (windows-latest) (push) Has been cancelled

This commit is contained in:
inman
2026-07-31 10:08:41 +08:00
parent b8ca3f8eea
commit 80e8386fa6
175 changed files with 8036 additions and 10581 deletions

View File

@@ -3,7 +3,7 @@
* TitleBar at top, then sidebar + content below.
*/
import { Outlet, useLocation, useNavigate } from 'react-router-dom';
import { useEffect } from 'react';
import { useCallback, useEffect, useRef, useState } from 'react';
import { LockKeyhole, Settings2 } from 'lucide-react';
import { Sidebar } from './Sidebar';
import { TitleBar } from './TitleBar';
@@ -11,16 +11,51 @@ import { Button } from '@/components/ui/button';
import { getAiModuleForPath } from '@/lib/ai-modules';
import { useOpencodeStore } from '@/stores/opencode';
import { useProjectConfigStore } from '@/stores/project-config';
import { useSettingsStore } from '@/stores/settings';
export function MainLayout() {
const activeProject = useOpencodeStore((state) => state.activeProject);
const sidebarCollapsed = useSettingsStore((state) => state.sidebarCollapsed);
const config = useProjectConfigStore((state) => activeProject ? state.configsByProjectId[activeProject.id] : undefined);
const load = useProjectConfigStore((state) => state.load);
const location = useLocation();
const navigate = useNavigate();
const [sidebarPeekOpen, setSidebarPeekOpen] = useState(false);
const sidebarPeekCloseTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
const isPaintingModule = getAiModuleForPath(location.pathname) === 'painting';
const isInitializationSafeRoute = location.pathname === '/project-config' || isPaintingModule;
const handleSidebarPeekChange = useCallback((open: boolean) => {
if (!sidebarCollapsed) return;
if (sidebarPeekCloseTimerRef.current) {
clearTimeout(sidebarPeekCloseTimerRef.current);
sidebarPeekCloseTimerRef.current = null;
}
if (open) {
setSidebarPeekOpen(true);
return;
}
sidebarPeekCloseTimerRef.current = setTimeout(() => {
setSidebarPeekOpen(false);
sidebarPeekCloseTimerRef.current = null;
}, 120);
}, [sidebarCollapsed]);
useEffect(() => {
setSidebarPeekOpen(false);
if (sidebarPeekCloseTimerRef.current) {
clearTimeout(sidebarPeekCloseTimerRef.current);
sidebarPeekCloseTimerRef.current = null;
}
}, [sidebarCollapsed]);
useEffect(() => () => {
if (sidebarPeekCloseTimerRef.current) clearTimeout(sidebarPeekCloseTimerRef.current);
}, []);
useEffect(() => {
if (activeProject && !isPaintingModule) void load(activeProject.id).catch(() => undefined);
}, [activeProject, isPaintingModule, load]);
@@ -29,20 +64,20 @@ export function MainLayout() {
return (
<div data-testid="main-layout" className="flex h-screen flex-col overflow-hidden bg-background">
{/* Title bar: drag region on macOS, icon + controls on Windows */}
<TitleBar integrated />
<TitleBar integrated sidebarPeekOpen={sidebarPeekOpen} onSidebarPeekChange={handleSidebarPeekChange} />
{/* Below the title bar: sidebar + content */}
<div className="flex min-h-0 flex-1 overflow-hidden">
<Sidebar />
<main data-testid="main-content" className="relative min-h-0 flex-1 overflow-auto p-6">
<div className="relative flex min-h-0 flex-1 overflow-hidden">
<Sidebar sidebarPeekOpen={sidebarPeekOpen} onSidebarPeekChange={handleSidebarPeekChange} />
<main data-testid="main-content" className="relative min-h-0 flex-1 overflow-auto bg-background p-5 sm:p-6">
<Outlet />
{initializationBlocked ? (
<div data-testid="project-initialization-gate" className="absolute inset-0 z-50 flex items-center justify-center bg-white/95 p-6">
<div className="max-w-md rounded-2xl border-2 border-[#26384D] bg-[#FFFFFF] p-8 text-center shadow-[8px_8px_0_#26384D]">
<div data-testid="project-initialization-gate" className="glass-surface absolute inset-0 z-50 flex items-center justify-center bg-background/90 p-6">
<div className="surface-card max-w-md rounded-2xl border border-border/80 bg-background p-8 text-center shadow-float">
<LockKeyhole className="mx-auto h-10 w-10" />
<h1 className="mt-4 text-2xl font-black">项目尚未初始化</h1>
<p className="mt-3 text-sm font-bold text-[#68788B]">完成模板 Agent 名称确认后,聊天、任务和其他项目功能才会启用。</p>
<Button onClick={() => navigate('/project-config')} className="mt-6 border-2 border-[#26384D] bg-[#3A5578] font-black text-white shadow-[4px_4px_0_#26384D]"><Settings2 className="mr-2 h-4 w-4" />打开项目配置</Button>
<h1 className="mt-4 text-2xl font-semibold">项目尚未初始化</h1>
<p className="mt-3 text-sm font-medium text-muted-foreground">请先在项目配置中完成至少一个手动 Agent 的名称、模型和职责设置。</p>
<Button onClick={() => navigate('/project-config')} className="mt-6 border border-brand/20 bg-brand font-semibold text-primary-foreground"><Settings2 className="mr-2 h-4 w-4" />打开项目配置</Button>
</div>
</div>
) : null}