From 1c39471156e4230d8efe110fd8695176cf80ae3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=B2=A8=E9=B1=BC=E8=BE=A3=E6=A4=92?= Date: Wed, 14 Oct 2026 11:14:43 +0800 Subject: [PATCH] Expand left sidebar on home module entry --- .../20261014-home-sidebar-default-31a87f9c.md | 41 +++++++++++++++++ README.md | 2 +- src/pages/ModuleSelection/index.tsx | 3 ++ tests/unit/module-navigation.test.tsx | 44 ++++++++++++++++++- 4 files changed, 88 insertions(+), 2 deletions(-) create mode 100644 .project-docs/30-worklog/tasks/20261014-home-sidebar-default-31a87f9c.md diff --git a/.project-docs/30-worklog/tasks/20261014-home-sidebar-default-31a87f9c.md b/.project-docs/30-worklog/tasks/20261014-home-sidebar-default-31a87f9c.md new file mode 100644 index 00000000..03959c6c --- /dev/null +++ b/.project-docs/30-worklog/tasks/20261014-home-sidebar-default-31a87f9c.md @@ -0,0 +1,41 @@ +# Task: Expand module sidebars when entering from home + +## Identity + +- Task ID: 20261014-home-sidebar-default-31a87f9c +- Mode: Feature +- Branch: codex/20261014-home-sidebar-default-31a87f9c-home-sidebar-default +- Worktree: /Users/chillishark/Makelore 麦洛/.codex-worktrees/makelore/20261014-home-sidebar-default-31a87f9c +- Base commit: b7f50be87bac49bb321c28264279c7a9c379aee4 +- Owner: codex +- Status: In Progress + +## Scope + +- Expand the shared left sidebar before an authorized homepage module-card navigation for Code, Agents, and Canvas. Cover prior-collapse/re-entry and preserve manual toggling. + +## Intent And Constraints + +- Scope is homepage entry behavior only; retain module access/auth guards, Agent view=mine entry, manual collapse, and accepted gallery placement. No new API or content values. Preserve current combined trial Main and inherited feature bytes during Renderer update. + +## Outcome + +- Implemented guarded homepage-entry expansion through the existing shared sidebar setter; already-expanded entries avoid redundant preference writes. Agent entry remains `?view=mine`; auth/module policy guards remain before changes. Manual toggling and Canvas desktop/compact rules are unchanged. +- README current behavior updated. Source review found no actionable issue. +- Combined-trial Renderer update and focused Electron verification pending. + +## Verification + +- Planning gate passed after official task identity/status and all 63 peer records (189 sections) were checked read-only; no blocking semantic conflict. +- Typecheck and targeted ESLint passed. +- 37 focused tests passed across module-navigation, cloud-agent-entry-navigation, main-layout-sidebar-peek, and image-workspace-sidebar. +- Default full `build:vite` passed with Renderer-only mode unset; existing Browserslist/chunk warnings only. +- Focused Electron and actual trial checks pending. + +## Follow-ups + +- None recorded. + +## Promotion Candidates + +- None recorded. diff --git a/README.md b/README.md index 9b57fc0a..d7feb64d 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Code 会话保存的模型被下架后,会提示重新选择可用模型;用户可在原会话中切换,恢复时使用新选择并保留会话与历史消息。切换不会自动重发消息或自动选择替代模型。 -Makelore 是一个面向软件、视觉创作、智能机器人与个人云智能体的 AI 桌面工作台。当前版本为 `2.0.0`,首页展示 Agents、Code、Canvas 三个模块入口,Robot 入口隐藏;云智能体需配套配置 WS/Yuxi 服务。桌面采用左侧问候与标题、右侧三个横向插画卡片竖排的布局,Code 入口中心与“今天,想创作什么?”标题中心对齐,三个入口等高、间距均匀;标题组在桌面向右偏移约 1.5cm,小窗口将标题放在卡片上方;Agents 标语为“打造你想象中的AI助手”。各页左下角账户按钮统一沿用 Code 的白色圆角卡片、头像、字号和右箭头,展开时跟随 Code 侧栏宽度偏好,首页和设置页与 Code 保持相同的左侧与底部边距;展开菜单保持原尺寸,可查看本人词元点数与预占、打开词元点数与充值、个人资料、设置和退出登录;沿用侧栏的账号、钱包和资料规则。设置使用独立页面,不显示编程项目栏、项目标题或工作栏收起按钮;“返回”回到打开设置前的页面(保留查询参数),直接打开设置时回模块首页,未保存设置先保存或还原。工作区左上角入口点击后返回模块入口页: +Makelore 是一个面向软件、视觉创作、智能机器人与个人云智能体的 AI 桌面工作台。当前版本为 `2.0.0`,首页展示 Agents、Code、Canvas 三个模块入口,Robot 入口隐藏;云智能体需配套配置 WS/Yuxi 服务。桌面采用左侧问候与标题、右侧三个横向插画卡片竖排的布局,Code 入口中心与“今天,想创作什么?”标题中心对齐,三个入口等高、间距均匀;标题组在桌面向右偏移约 1.5cm,小窗口将标题放在卡片上方;Agents 标语为“打造你想象中的AI助手”。各页左下角账户按钮统一沿用 Code 的白色圆角卡片、头像、字号和右箭头,展开时跟随 Code 侧栏宽度偏好,首页和设置页与 Code 保持相同的左侧与底部边距;展开菜单保持原尺寸,可查看本人词元点数与预占、打开词元点数与充值、个人资料、设置和退出登录;沿用侧栏的账号、钱包和资料规则。设置使用独立页面,不显示编程项目栏、项目标题或工作栏收起按钮;“返回”回到打开设置前的页面(保留查询参数),直接打开设置时回模块首页,未保存设置先保存或还原。每次从首页进入 Code、Agents 或 Canvas 时,默认展开左侧工作栏;进入后沿用各模块现有的手动收起与紧凑布局规则。工作区左上角入口点击后返回模块入口页: - `Makelore Code|AI 编程`:管理本地项目、项目智能体、对话、文件上下文、代码变更和运行时。 会话工作台采用浅蓝项目栏,侧栏入口与项目列表采用 Agent 式的彩色图标徽章+文字,选中项目保留浅色反馈;中间对话/作品使用圆角标签,作品预览的后退、前进、刷新与网址输入统一放在标签右侧;只在作品页显示,窄窗口自动换行。右侧智能体咨询使用奶油色标题区。沿用真实项目和会话入口、侧栏伸缩与账户菜单,样式只作用于 Code 会话工作台。可编辑的空对话在输入区上方的可用区域中央显示童趣欢迎语;欢迎区的麦洛标识、星装饰和「作品广场」组成同一个可鼠标或键盘操作的广场入口,保留原有主标题与说明,输入框上方不再显示两句广场邀请。老师介绍以固定宽度浮在右上角,不占用中间布局;欢迎语和底部输入区始终相对项目栏右侧的整个内容区域居中;小窗口的欢迎内容独立滚动;发送首条消息后收起欢迎区。侧栏的「作品广场」固定在底部、紧邻账户按钮上方,保持与上方入口相同的横向对齐;只有点击后才在系统浏览器打开公共广场,不请求、摘取或内嵌展示广场作品。打开广场保留当前项目、对话、草稿和附件,不自动发送消息;老师求助按钮保留临时应用的最新文案「帮我整体看🧠」。 diff --git a/src/pages/ModuleSelection/index.tsx b/src/pages/ModuleSelection/index.tsx index 1efc7209..6ac9fd46 100644 --- a/src/pages/ModuleSelection/index.tsx +++ b/src/pages/ModuleSelection/index.tsx @@ -12,6 +12,7 @@ import { aiModules, isAiModuleAllowed, type AiModuleId } from '@/lib/ai-modules' import { getAuthUserDisplayName } from '@/lib/auth-user-display'; import { cn } from '@/lib/utils'; import { useAuthStore } from '@/stores/auth'; +import { useSettingsStore } from '@/stores/settings'; import { getUserProfileDisplayName } from '@/stores/user-profile'; const moduleSelectionContent: Record = { @@ -23,6 +24,7 @@ const moduleSelectionContent: Record state.setSidebarCollapsed); const authUser = useAuthStore((state) => state.user); const moduleAccess = useAuthStore((state) => state.moduleAccess); const authenticated = useAuthStore((state) => state.isAuthenticated()); @@ -46,6 +48,7 @@ export function ModuleSelection({ authRequired = true }: { authRequired?: boolea navigate('/login'); return; } + if (useSettingsStore.getState().sidebarCollapsed) setSidebarCollapsed(false); navigate(route === '/cloud-agents' ? `${route}?view=mine` : route); }; diff --git a/tests/unit/module-navigation.test.tsx b/tests/unit/module-navigation.test.tsx index 3128e9b2..433ca5a4 100644 --- a/tests/unit/module-navigation.test.tsx +++ b/tests/unit/module-navigation.test.tsx @@ -1,11 +1,12 @@ import { fireEvent, render, screen, waitFor } from '@testing-library/react'; import { beforeEach, describe, expect, it } from 'vitest'; -import { MemoryRouter, Route, Routes, useLocation } from 'react-router-dom'; +import { MemoryRouter, Route, Routes, useLocation, useNavigate } from 'react-router-dom'; import { ModuleSwitcher } from '@/components/layout/ModuleSwitcher'; import { ModuleSelection } from '@/pages/ModuleSelection'; import { useAuthStore } from '@/stores/auth'; import { codingWorkspaceStore } from '@/stores/coding-workspace'; import { useUserProfileStore } from '@/stores/user-profile'; +import { useSettingsStore } from '@/stores/settings'; const { hostApiFetchMock } = vi.hoisted(() => ({ hostApiFetchMock: vi.fn(), @@ -20,9 +21,22 @@ function LocationProbe() { return {location.pathname}; } +function SidebarEntryProbe() { + const collapsed = useSettingsStore((state) => state.sidebarCollapsed); + const setCollapsed = useSettingsStore((state) => state.setSidebarCollapsed); + const navigate = useNavigate(); + return <> + + {collapsed ? 'collapsed' : 'expanded'} + + + ; +} + describe('AI module navigation', () => { beforeEach(() => { vi.clearAllMocks(); + useSettingsStore.setState({ sidebarCollapsed: true }); useAuthStore.setState({ initialized: true, loading: false, @@ -52,6 +66,32 @@ describe('AI module navigation', () => { }); }); + it.each([ + ['programming', '/chat'], + ['cloud_agents', '/cloud-agents'], + ['painting', '/image-canvas'], + ])('expands %s on every home entry while allowing manual collapse', async (moduleId, route) => { + render( + + + } /> + } /> + + , + ); + + fireEvent.click(screen.getByTestId(`ai-module-option-${moduleId}`)); + expect(await screen.findByTestId('location-path')).toHaveTextContent(route); + expect(screen.getByTestId('sidebar-state')).toHaveTextContent('expanded'); + fireEvent.click(screen.getByRole('button', { name: 'Toggle sidebar' })); + expect(screen.getByTestId('sidebar-state')).toHaveTextContent('collapsed'); + + fireEvent.click(screen.getByRole('button', { name: 'Home', exact: true })); + expect(useSettingsStore.getState().sidebarCollapsed).toBe(true); + fireEvent.click(screen.getByTestId(`ai-module-option-${moduleId}`)); + expect(await screen.findByTestId('sidebar-state')).toHaveTextContent('expanded'); + }); + it('shows Agents, Code and Canvas on the home page and routes Canvas from the chooser', async () => { render( @@ -144,6 +184,7 @@ describe('AI module navigation', () => { fireEvent.click(canvasOption); expect(screen.getByTestId('ai-module-selection-page')).toBeInTheDocument(); expect(screen.queryByTestId('location-path')).not.toBeInTheDocument(); + expect(useSettingsStore.getState().sidebarCollapsed).toBe(true); }); it('routes AI programming from the chooser to the project conversation entry', async () => { @@ -184,6 +225,7 @@ describe('AI module navigation', () => { fireEvent.click(screen.getByTestId('ai-module-option-programming')); expect(await screen.findByTestId('location-path')).toHaveTextContent('/login'); + expect(useSettingsStore.getState().sidebarCollapsed).toBe(true); }); it('returns to the module chooser from the Sidebar entry', async () => {