Commit Graph
5 Commits
Author SHA1 Message Date
7418andClaude Opus 4.6 27bf396cd3 refactor: migrate all Lucide icons to Phosphor + remove lucide-react (PR4)
Unified icon library:
- Create src/components/ui/icon.tsx as centralized icon re-export + size constants
- Migrate all 20+ files from lucide-react to @phosphor-icons/react
- Remove lucide-react from package.json dependencies
- Upgrade ESLint lucide-react rule from warn → error

Icon mappings applied:
  CheckIcon → Check, ChevronDown → CaretDown, ChevronUp → CaretUp,
  ChevronRight → CaretRight, X → X, Search → MagnifyingGlass,
  Loader2 → SpinnerGap, CornerDownLeft → ArrowElbowDownLeft,
  Image → Image, Brain → Brain, Terminal → Terminal, Book → Book,
  Dot → DotOutline, Circle → Circle

Files migrated: ui/ (6), ai-elements/ (11), layout/ (3)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 21:51:38 +08:00
7418andClaude Opus 4.6 18a77dc915 fix: file tree attachment on Electron + model selection follows session
File tree "+" button (Bug 1):
- Replace fragile fetch/blob attachment bridge with @filepath text insertion
- Works identically on web and Electron (pure text, no /api/files/raw fetch)
- Remove unused mimeFromFilename helper

Model selection follows session (Bug 2):
- page.tsx: include model/provider_id in session creation request
- [id]/page.tsx: add sessionInfoLoaded gate — ChatView only mounts after
  session metadata is fetched, preventing stale localStorage fallback
- SplitColumn.tsx: same sessionInfoLoaded gate for split-pane mode
- ChatView.tsx: useEffect sync only overrides model/provider when props
  are non-empty; empty = genuinely no model saved (old/imported sessions)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 11:46:34 +08:00
7418andClaude Opus 4.6 789b453e92 fix: onboarding stability, invalid JSON from hooks, file tree race conditions
Issue 1 — Onboarding re-triggering after completion:
- ChatView.tsx: fence regex now tolerates CRLF, trailing whitespace, leading
  whitespace before closing fence; JSON.parse input trimmed
- ChatView.tsx: hookTriggeredSessionId only cleared when backend returns ok
- assistant-workspace.ts: saveState uses atomic write (tmp + rename)

Issue 2 — "CLI output was not valid JSON" during document reads:
- claude-client.ts: remove all SDK hooks (Notification + PostToolUse) to
  eliminate hook_callback control_request transport that corrupts stdout
- claude-client.ts: TodoWrite sync moved to message stream — tool_use records
  pending input, tool_result emits task_update only on success
- claude-client.ts: notifications derived from system/task_notification and
  result/is_error messages; Telegram forwarding preserved via notifyGeneric

Issue 3 — File tree not updating on project switch:
- FileTree.tsx: AbortController cancels in-flight requests on directory change;
  abort fires before empty-directory early return to prevent stale overwrites;
  error state distinguishes empty dir from load failure; loading always reset
- page.tsx: clear workingDirectory immediately on session switch
- SplitColumn.tsx: clear workingDirectory when active column has no directory

Tests: 9 new tests for fence parsing, atomic write, corrupted state fallback.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 21:27:54 +08:00
7418andClaude Opus 4.6 4da188bfe5 feat: theme family system with 12 color palettes + NavRail redesign
Theme system:
- Two-layer architecture: mode (light/dark/system via next-themes) + theme family (color palette via CSS variables)
- 12 theme families: Default, GitHub, Rosé Pine, Tokyo Night, Everforest, Nord, Kanagawa, Night Owl, Poimandres, Vesper, Horizon, SynthWave '84
- Per-family code block highlighting for Prism, HLJS, and Shiki (no more generic oneLight/oneDark fallback)
- Anti-FOUC: synchronous script in <head> reads localStorage and sets data-theme-family before paint
- Theme JSON files in themes/ directory, auto-discovered by server-side loader
- OKLCH color space for all values; CSS specificity html[data-theme-family] beats :root

UI changes:
- NavRail: moved Settings to bottom (replacing theme toggle), removed light/dark toggle button
- Settings: merged General controls into one card with dividers; Appearance section with live Shiki code preview
- Replaced hardcoded blue-500/blue-600 with primary/primary-foreground across 19 components
- Appearance settings: pill mode selector (light/dark/system), theme family dropdown, live code preview

New files:
- src/lib/theme/{types,loader,render-css,context,code-themes}.ts — core theme infrastructure
- src/components/layout/ThemeFamilyProvider.tsx — client context provider
- src/components/settings/AppearanceSection.tsx — appearance settings UI
- src/hooks/useAppTheme.ts — combined theme hook
- themes/*.json — 12 theme family definitions
- docs/handover/theme-system.md — handover documentation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 11:15:01 +08:00
7418andClaude Opus 4.6 4f4ba5f8eb feat: 聊天分屏功能 — 支持多会话并排查看
新增聊天分屏功能,允许同时查看和操作多个聊天会话:

新增文件:
- src/hooks/useSplit.ts: SplitContext 和 useSplit hook,管理分屏会话列表、
  活跃列、添加/移除/退出分屏等操作,状态通过 localStorage 持久化
- src/components/layout/SplitColumn.tsx: 单个分屏列组件,独立加载会话元数据
  和消息,渲染紧凑标题栏 + ChatView,活跃列蓝色描边并同步 PanelContext
- src/components/layout/SplitChatContainer.tsx: 分屏容器,并排渲染多个
  SplitColumn,列间以 1px 分隔线分隔

修改文件:
- AppShell.tsx: 新增分屏状态管理(splitSessions/activeColumnId),包裹
  SplitContext.Provider,分屏激活时渲染 SplitChatContainer 替代路由页面,
  URL 与活跃列同步,离开聊天路由自动退出分屏
- ChatListPanel.tsx: 聊天卡片 hover 交互重构 — 移除模式徽章(Code/Plan),
  左侧 indent 区域 hover 显示分屏图标(点击将该会话加入分屏),右侧时间区域
  hover 切换为删除图标;分屏激活时列表顶部显示灰色描边分屏组卡片,分屏中的
  会话从常规列表过滤掉;所有元素始终存在于 DOM 中通过 opacity 切换,避免
  hover 时布局跳动
- en.ts / zh.ts: 新增 split.splitScreen、split.closeSplit、
  split.splitGroup、chatList.splitScreen 翻译

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 01:13:19 +08:00