diff --git a/.project-docs/30-worklog/tasks/20261013-trial-sidebar-update-8e37a2c1.md b/.project-docs/30-worklog/tasks/20261013-trial-sidebar-update-8e37a2c1.md new file mode 100644 index 00000000..1f22a31b --- /dev/null +++ b/.project-docs/30-worklog/tasks/20261013-trial-sidebar-update-8e37a2c1.md @@ -0,0 +1,57 @@ +# Task: Enable requested Code sidebar changes in current temporary app + +## Identity + +- Task ID: 20261013-trial-sidebar-update-8e37a2c1 +- Mode: Feature +- Branch: codex/20261013-trial-sidebar-update-8e37a2c1-trial-sidebar-update +- Worktree: /Users/chillishark/Makelore 麦洛/.codex-worktrees/makelore/20261013-trial-sidebar-update-8e37a2c1 +- Base commit: 16b10c44f1b846f33dbf28c0050f15a68fdae53b +- Owner: codex +- Status: In Progress + +## Scope + +- Enable the requested Coding前端-页面修改2 thread's latest Code sidebar correction in the current temporary app alongside the delivered TOOL/SKILL and left-card knowledge upload correction. Preserve earlier address-bar/refresh-icon/Work-tab introduction layout changes already included in the baseline. + +## Intent And Constraints + +- User explicitly requested updating the current temporary app with this thread's work. Apply only committed Renderer/UI/test/README changes from 20e2e5996079fea29296c604f96acc268f8c65ce; do not merge or push main, clean worktrees, deploy cloud patches, restart Main, save/apply live Agent configuration, mutate user conversations, record audio or call models. Preserve current login, saved configuration, draft/input and ongoing work; refresh only after actual native saved/idle evidence. + +## Project Context Loaded + +- Task ID/mode/branch/worktree/base: Identity above exactly matches official check/start/status. New managed feature worktree from the previous task's docs-only delivery commit16b10c4, with effective Renderer ad223603 and actual Main020b366/PID12660/Host58003. +- Other active local tasks: all50 exact peer owner/task-record paths were read only by delegated audit. Source sidebar task ready; recent Agent selectors, knowledge layout, channel, composer and consolidation tasks are compatible. An old child-language placeholder has unknown scope but no concrete dependency here. No peer or canonical edits. +- Read: AGENTS, entry/read-before-planning, memory-index, own record, positioning, historical integrated current-state, decision-index, relevant system-overview, community-collaboration, project conversations/archive domain rules, success criteria, evidence/reflection/commitment indexes and source sidebar record. Read requested thread's latest14 turns, distinguishing source user directions from screenshots and old deployment instructions. +- Project goal/current focus: creative Electron client with project-scoped Code state and Main-owned auth/runtime/API. Shared integrated docs are historical; current runtime pointer plus immutable snapshot identify the actual temporary baseline. +- Scope/constraints/decisions: sidebar hierarchy is already user-approved; archive remains recoverable and task/conversation identity stays Main-owned. TOOL/SKILL and left upload remain as just explicitly corrected. No API/schema, provider, runtime, account or cloud deployment change is needed. +- Evidence/reflection/commitments: source79 units and two focused Electron scenarios passed; historical broad navigation/titlebar assertions failed before this source and are not a delivery proof. Feature-mode docs are task-scoped; source records remain read only. Real provider/cloud deployment acceptance remains separate. +- Likely files: Sidebar.tsx, MainLayout.tsx, sidebar-peek.ts, CodingProjectConversations.tsx, classroom-workspace.css plus exact source README/test hunks. All five source product files in20e2e59^ are byte-identical to this task base, so the source patch needs no product conflict resolution. d12d214 Work-tab intro fix and d787267 address-bar fix are already ancestors. +- Unknowns/conflicts: broad historical test failures retained as limits; none blocks the targeted change. Planning Gate: Passed before implementation. + +## Plan + +1. Apply the exact source feature hunks excluding its peer task record; verify no Main/shared/resources/package/lock/build-config delta and preserve current corrections. +2. Run focused source unit/UI scenarios, current Agent regression assertions, typecheck, lint and default full build; review resulting immutable source. +3. Prepare a file-only Renderer overlay over identical current Main bytes. Check live native UI saved/idle state, activate files, refresh through CUA, verify Code sidebar and retained Agent controls; finalize runtime metadata only after actual observation. + +## Outcome + +- Applied exact source20e2e59 product/README/test hunks, excluding its peer task record. New conversation is labeled and left aligned; project-card overflow owns archived/recent lists and project settings, while per-conversation rename/recoverable archive/restore and task state remain unchanged. Open project menus retain sidebar preview through the independent menu peek source. +- Independent combined-tree review passed: five changed product files exactly match source; all three TOOL/SKILL/knowledge product files stay identical toad223603; Main/shared/resources/package/lock/build config delta versus actual Main020b366 is empty. Prior Work-tab welcome hiding, address bar placement and icon refresh remain included. +- Default compiled build is ready; immutable snapshot and saved/idle native refresh/verification remain to deliver before runtime metadata finalization. + +## Verification + +- Typecheck, changed-file ESLint, default full build:vite with NIANCODE_RENDERER_ONLY unset, git diff --check and task-aware document drift passed. +- 136 unit cases passed (source79 plus existing Agent configuration/knowledge57); ten test files. The two focused isolated Electron scenarios both passed (3.4s and3.9s, total8.3s): conversation rename/archive/restore without selecting/stopping target; project-targeting, peek-menu behavior, keyboard access and 128/171/256px left alignment/full label/no overflow. +- Logs: /tmp/makelore-sidebar8e37-{type,lint,unit,build,electron}.log; Electron screenshots/artifacts: /tmp/makelore-sidebar8e37-electron. Tests use isolated temporary state and synthetic host, not real user projects/model/cloud mutations. +- Source's broader historical titlebar/equal-height assertions are unrelated existing mismatches and were not rerun or counted as passed. No full-suite or real-provider claim. + +## Follow-ups + +- None recorded. + +## Promotion Candidates + +- None recorded. diff --git a/README.md b/README.md index 1a6fc37b..a5a34e1c 100644 --- a/README.md +++ b/README.md @@ -150,7 +150,7 @@ Pi 正式包必须继续运行 `pnpm run verify:artifact:pi`、`pnpm run smoke:p ### 项目智能体与对话 -- 对话行的“…”菜单支持重命名和归档,项目下的归档入口可查看并恢复原对话。归档保留历史、附件和 Pi Session,不中止正在执行的任务;已归档对话仍可查看、处理审批或中止,恢复后才能继续发送或创建分支。全部归档后显示空列表,不自动创建空对话。 +- 项目下仅保留与项目卡片左边框对齐的“+ 新对话”;项目卡片右侧的“…”菜单提供“已归档对话”和“项目设置”。对话行的“…”菜单支持重命名和归档,归档列表可查看并恢复原对话,也可返回最近对话;新建或恢复后回到最近对话列表。归档保留历史、附件和 Pi Session,不中止正在执行的任务;已归档对话仍可查看、处理审批或中止,恢复后才能继续发送或创建分支。全部归档后显示空列表,不自动创建空对话。 - 新对话使用第一条实际用户消息的首行作为标题,合并空白并截取最多 32 个字符;纯图片消息使用“附件对话”,命令和空消息不参与命名。不额外调用模型,不随后续消息改名。历史标题保持原样,手动重命名优先,标题最多 200 个字符;仅改标题不改变最近对话排序。Main 在本地元数据落盘后通过独立的 metadata-changed 事件通知列表,事件重连也会刷新列表。 - 新项目自动建立一个内部默认编程智能体,`defaultAgentId` 固定其身份;创建项目不再要求创建或选择智能体。有可用的全局默认模型时复制精确账号与模型,没有时保留待选择状态。旧项目优先保留原默认或置顶/首个可用智能体,保留所有历史绑定;全部停用时新增默认配置,不复活旧配置。 diff --git a/src/components/layout/MainLayout.tsx b/src/components/layout/MainLayout.tsx index 7d1a5def..6e34ad2e 100644 --- a/src/components/layout/MainLayout.tsx +++ b/src/components/layout/MainLayout.tsx @@ -25,6 +25,7 @@ export function MainLayout() { focus: false, sidebar: false, titlebar: false, + menu: false, }); const activeModule = getAiModuleForPath(location.pathname); const isPaintingModule = activeModule === 'painting'; @@ -60,7 +61,7 @@ export function MainLayout() { }, [sidebarCollapsed, isCloudAgents]); useEffect(() => { - sidebarPeekSourcesRef.current = { toggle: false, focus: false, sidebar: false, titlebar: false }; + sidebarPeekSourcesRef.current = { toggle: false, focus: false, sidebar: false, titlebar: false, menu: false }; // This transient state mirrors the external persisted sidebar preference; // reset it on preference changes and both edges of the Agents boundary so // a previous module's preview or timer cannot reopen the manual-only sidebar. diff --git a/src/components/layout/Sidebar.tsx b/src/components/layout/Sidebar.tsx index 84f86bf1..d1963cd4 100644 --- a/src/components/layout/Sidebar.tsx +++ b/src/components/layout/Sidebar.tsx @@ -4,14 +4,17 @@ import { useCallback, useEffect, useRef, useState } from 'react'; import { createPortal } from 'react-dom'; import { useTranslation } from 'react-i18next'; import { useLocation, useNavigate } from 'react-router-dom'; +import * as DropdownMenu from '@radix-ui/react-dropdown-menu'; import { + Archive, Bot, BotMessageSquare, Cpu, - ChevronRight, FolderKanban, Gamepad2, LogOut, + MessageSquare, + MoreHorizontal, Plus, Settings as SettingsIcon, UserCircle2, @@ -51,7 +54,7 @@ import { getAccountInitial } from '@/components/profile/user-avatar-utils'; import { UserProfileDialog } from '@/components/profile/UserProfileDialog'; import { useSettingsStore } from '@/stores/settings'; import { useAuthStore } from '@/stores/auth'; -import { useCodingWorkspaceStore } from '@/stores/coding-workspace'; +import { codingWorkspaceStore, useCodingWorkspaceStore } from '@/stores/coding-workspace'; import { useProviderStore } from '@/stores/providers'; import type { CodingProjectSummary } from '@/types/coding-project'; import { useProjectConfigStore } from '@/stores/project-config'; @@ -114,6 +117,8 @@ export function Sidebar({ } = useCurrentUserProfile(); const refreshProviderSnapshot = useProviderStore((state) => state.refreshProviderSnapshot); const [projectsOpen, setProjectsOpen] = useState(true); + const [archivedProjectId, setArchivedProjectId] = useState(null); + const [projectMenuOpen, setProjectMenuOpen] = useState(false); const [accountMenuOpen, setAccountMenuOpen] = useState(false); const [profileDialogOpen, setProfileDialogOpen] = useState(false); const [createDialogOpen, setCreateDialogOpen] = useState(false); @@ -339,6 +344,24 @@ export function Sidebar({ await readAndEnterProject(project); }, [readAndEnterProject]); + const openProjectAction = async (project: CodingProjectSummary, action: 'settings' | 'archived' | 'recent') => { + const opening = openProject(project); + const intent = projectEntryIntentRef.current; + await opening; + if (intent !== projectEntryIntentRef.current) return; + if (codingWorkspaceStore.getState().activeProjectId !== project.id) return; + if (action === 'settings') { + navigate('/project-config'); + } else { + setArchivedProjectId(action === 'archived' ? project.id : null); + } + }; + + useEffect(() => { + onSidebarPeekChange?.(projectMenuOpen, 'menu'); + return () => onSidebarPeekChange?.(false, 'menu'); + }, [projectMenuOpen, onSidebarPeekChange]); + useEffect(() => { if (!isProgrammingModule) return undefined; return subscribeCodingProjectOpenRequest((projectId) => { @@ -476,26 +499,71 @@ export function Sidebar({ {visibleProjects.map((project) => { const active = activeProject?.id === project.id; + const archived = active && archivedProjectId === project.id; return ( -
+ + + + + + + void openProjectAction(project, archived ? 'recent' : 'archived')} + > + {archived ? + void openProjectAction(project, 'settings')} + > + + + + +
+ {active && ( + setArchivedProjectId(value ? project.id : null)} + /> )} - > - {workspaceLayout ? sum + char.charCodeAt(0), 0) % 3]}> : } - {project.name} -