Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
### Changed

- 聊天面板(PR Agent)内部重构:2578 行的单文件 `ChatPane.tsx` 按「容器 / 领域组件 / hooks / 工具方法」分层拆分到 `components/chat/`,状态与生命周期、业务动作、时间线归并各自成 hook,展示组件与工具方法独立成文件。对外接口与界面行为保持不变,仅改善可维护性;token 用量 ↑/↓ 的绿红色值一并从内联样式收进设计令牌与样式类。
- 首启向导内部重构:`OnboardingWizard.tsx` 的四个步骤组件(欢迎 / 平台 / LLM / 完成)拆分到 `onboarding/steps/` 各自成文件,容器只留向导骨架(步骤指示 + 切换 + 导航)。对外接口与界面行为不变。
- 首启向导内部重构:`OnboardingWizard.tsx` 的四个步骤组件(欢迎 / 平台 / LLM / 完成)拆分到 `steps/` 各自成文件,容器只留向导骨架(步骤指示 + 切换 + 导航)。对外接口与界面行为不变。
- `components/` 目录按职责重组:扁平堆叠的组件归入三类——`common/`(基础公共 UI)、`layout/`(应用骨架)、`features/`(业务领域:pr / diff / comments / drafts / settings / chat / onboarding),顶层只剩这三个桶。纯文件位置调整 + import 路径改写,无逻辑 / 界面变更。

### Fixed

Expand Down
14 changes: 7 additions & 7 deletions apps/desktop/src/renderer/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@ import type {
UpdateCheckResult,
} from '@meebox/shared';
import { invoke, subscribe } from './api';
import { ChatPane, CHAT_MAX_WIDTH, CHAT_MIN_WIDTH } from './components/chat';
import { ChatPane, CHAT_MAX_WIDTH, CHAT_MIN_WIDTH } from './components/features/chat';
import { wireChatRunStore } from './stores/chat-run-store';
import { wireDraftsStore } from './stores/drafts-store';
import { wireRepoSyncStore } from './stores/repo-sync-store';
import { MainPane } from './components/MainPane';
import { OnboardingWizard, type OnboardingResult } from './components/onboarding/OnboardingWizard';
import { SettingsModal } from './components/SettingsModal';
import { Sidebar, SIDEBAR_MAX_WIDTH, SIDEBAR_MIN_WIDTH } from './components/Sidebar';
import { StatusBar } from './components/StatusBar';
import { TitleBar } from './components/TitleBar';
import { MainPane } from './components/layout/MainPane';
import { OnboardingWizard, type OnboardingResult } from './components/features/onboarding/OnboardingWizard';
import { SettingsModal } from './components/features/settings/SettingsModal';
import { Sidebar, SIDEBAR_MAX_WIDTH, SIDEBAR_MIN_WIDTH } from './components/layout/Sidebar';
import { StatusBar } from './components/layout/StatusBar';
import { TitleBar } from './components/layout/TitleBar';

interface BootstrapState {
info: AppInfo;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useEffect, useState } from 'react';
import { invoke } from '../api';
import { invoke } from '../../api';

interface AvatarProps {
connectionId: string;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useEffect, useState } from 'react';
import { createPortal } from 'react-dom';
import { useTranslation } from 'react-i18next';
import { invoke } from '../api';
import { invoke } from '../../api';

/**
* react-markdown 默认 url sanitize 只允许 http/https/mailto/tel 协议,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import type { LocalPrStatus, PrAgentStatus, StoredPullRequest } from '@meebox/shared';
import { ChatIcon, TrashIcon } from '../icons';
import { ConfirmModal } from '../ConfirmModal';
import { PaneLoading } from '../Loading';
import { useChatRunStore } from '../../stores/chat-run-store';
import { useDraftsForPr } from '../../stores/drafts-store';
import { ChatIcon, TrashIcon } from '../../common/icons';
import { ConfirmModal } from '../../common/ConfirmModal';
import { PaneLoading } from '../../common/Loading';
import { useChatRunStore } from '../../../stores/chat-run-store';
import { useDraftsForPr } from '../../../stores/drafts-store';
import { CHAT_MAX_WIDTH, CHAT_MIN_WIDTH } from './constants';
import { useChatSession } from './hooks/useChatSession';
import { useChatActions } from './hooks/useChatActions';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import type { AgentStep } from '@meebox/shared';
import { RobotIcon } from '../../icons';
import { RobotIcon } from '../../../common/icons';
import { formatElapsed, formatTokens } from '../utils/format';
import { Spinner } from './shared';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useTranslation } from 'react-i18next';
import type { PrAgentStatus, StoredPullRequest } from '@meebox/shared';
import { ChatIcon } from '../../icons';
import { ChatIcon } from '../../../common/icons';
import { Bullet } from './shared';

export function ChatEmpty({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useEffect, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import type { LocalPrStatus, PrAgentStatus, ReviewRunTool, StoredPullRequest } from '@meebox/shared';
import { AutoReviewIcon, SendIcon, StopIcon } from '../../icons';
import { AutoReviewIcon, SendIcon, StopIcon } from '../../../common/icons';
import { COMMANDS, type CommandSpec } from '../commands';
import { loadChatHistory, pushChatHistory } from '../utils/chat-history';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useTranslation } from 'react-i18next';
import type { AgentMessage } from '@meebox/shared';
import { ChatIcon } from '../../icons';
import { ChatIcon } from '../../../common/icons';
import { VERDICT_LABEL_KEY } from '../constants';
import { Md } from './shared';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import ReactMarkdown from 'react-markdown';
import remarkBreaks from 'remark-breaks';
import remarkGfm from 'remark-gfm';
import type { Finding, PrDocSectionKey, ReviewDraft } from '@meebox/shared';
import { ChevronIcon } from '../../icons';
import { mermaidComponents, walkthroughMdComponents } from '../../markdownMermaid';
import { REMOTE_REHYPE_PLUGINS } from '../../../markdown';
import { translatePrAgentLabels } from '../../../utils/translate-pr-agent';
import { ChevronIcon } from '../../../common/icons';
import { mermaidComponents, walkthroughMdComponents } from '../../../common/markdownMermaid';
import { REMOTE_REHYPE_PLUGINS } from '../../../../markdown';
import { translatePrAgentLabels } from '../../../../utils/translate-pr-agent';
import {
pillStyle,
sectionLabel,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import type { ReviewRunTool } from '@meebox/shared';
import { CloseIcon } from '../../icons';
import { CloseIcon } from '../../../common/icons';
import { AskQuestion } from './shared';

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { useTranslation } from 'react-i18next';
import ReactMarkdown from 'react-markdown';
import remarkBreaks from 'remark-breaks';
import remarkGfm from 'remark-gfm';
import { mermaidComponents } from '../../markdownMermaid';
import { REMOTE_REHYPE_PLUGINS } from '../../../markdown';
import { mermaidComponents } from '../../../common/markdownMermaid';
import { REMOTE_REHYPE_PLUGINS } from '../../../../markdown';
import type { MatchedRule } from '../types';

export function RulePreviewModal({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import type { Finding, ReviewDraft, ReviewRun } from '@meebox/shared';
import { RetryIcon } from '../../icons';
import { RetryIcon } from '../../../common/icons';
import { orderFindings } from '../utils/findings';
import { formatStartTime, formatTokens, runStatusLabel } from '../utils/format';
import { extractTokenUsage, type TokenUsage } from '../utils/tokens';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import { useTranslation } from 'react-i18next';
import ReactMarkdown from 'react-markdown';
import remarkBreaks from 'remark-breaks';
import remarkGfm from 'remark-gfm';
import { QuestionIcon } from '../../icons';
import { mermaidComponents } from '../../markdownMermaid';
import { REMOTE_REHYPE_PLUGINS } from '../../../markdown';
import { parseAnsi, segmentStyle } from '../../../utils/ansi';
import { QuestionIcon } from '../../../common/icons';
import { mermaidComponents } from '../../../common/markdownMermaid';
import { REMOTE_REHYPE_PLUGINS } from '../../../../markdown';
import { parseAnsi, segmentStyle } from '../../../../utils/ansi';

export function Spinner() {
return <span className="spinner" aria-hidden="true" />;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import type {
ReviewRunTool,
StoredPullRequest,
} from '@meebox/shared';
import { invoke } from '../../../api';
import { invoke } from '../../../../api';
import { htmlInlineToMarkdown, stripFindingMarker } from '../utils/findings';

interface UseChatActionsParams {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useEffect, useRef, useState, type MutableRefObject } from 'react';
import type { AgentMessage, AgentStep, ReviewRun } from '@meebox/shared';
import { invoke, subscribe } from '../../../api';
import { invoke, subscribe } from '../../../../api';
import { RUNS_PAGE_SIZE } from '../constants';
import type { MatchedRule } from '../types';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useEffect, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { invoke } from '../api';
import { invoke } from '../../../api';

interface CommentEditEditorProps {
prLocalId: string;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useEffect, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { invoke } from '../api';
import { invoke } from '../../../api';

interface CommentReplyEditorProps {
prLocalId: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ import ReactMarkdown from 'react-markdown';
import remarkBreaks from 'remark-breaks';
import remarkGfm from 'remark-gfm';
import type { PlatformCapabilities, PrComment, StoredPullRequest } from '@meebox/shared';
import { invoke, subscribe } from '../api';
import i18n from '../i18n';
import { formatBackendError, type FormattedError } from '../errors';
import { REMOTE_REHYPE_PLUGINS } from '../markdown';
import { Avatar } from './Avatar';
import { makeBitbucketImageFor, transformBitbucketUrl } from './BitbucketImage';
import { invoke, subscribe } from '../../../api';
import i18n from '../../../i18n';
import { formatBackendError, type FormattedError } from '../../../errors';
import { REMOTE_REHYPE_PLUGINS } from '../../../markdown';
import { Avatar } from '../../common/Avatar';
import { makeBitbucketImageFor, transformBitbucketUrl } from '../../common/BitbucketImage';
import { CommentEditEditor } from './CommentEditEditor';
import { CommentReplyEditor } from './CommentReplyEditor';
import { ConfirmModal } from './ConfirmModal';
import { mermaidComponents } from './markdownMermaid';
import { ConfirmModal } from '../../common/ConfirmModal';
import { mermaidComponents } from '../../common/markdownMermaid';
// 行内代码上下文用 Monaco,懒加载随 DiffView 同一套 Monaco chunk 按需拉取,不进入口包。
const InlineCodeContext = lazy(() =>
import('./InlineCodeContext').then((m) => ({ default: m.InlineCodeContext })),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
// 必须在用到 @monaco-editor/react 之前执行(见 DiffView 同款说明)。本文件经
// React.lazy 动态加载 → Monaco 随本 chunk 按需拉取,不进入口包。
import '../monaco-setup';
import '../../../monaco-setup';
import { Editor, type Monaco } from '@monaco-editor/react';
import type { editor } from 'monaco-editor';
import { memo, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import type { PrCommentAnchor, StoredPullRequest } from '@meebox/shared';
import { invoke } from '../api';
import { editorFontSize } from '../editor-font';
import { languageFor } from '../utils/language';
import { invoke } from '../../../api';
import { editorFontSize } from '../../../editor-font';
import { languageFor } from '../../../utils/language';

interface InlineCodeContextProps {
pr: StoredPullRequest;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { useTranslation } from 'react-i18next';
import type { TFunction } from 'i18next';
import { editor as MonacoEditorNs } from 'monaco-editor';
import type { DiffChangedFile } from '@meebox/shared';
import { invoke } from '../api';
import { languageFor } from '../utils/language';
import { invoke } from '../../../api';
import { languageFor } from '../../../utils/language';

/**
* 搜索 PR diff 全部变更文件内容。仿 Bitbucket "Search code" 入口的行为:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// 必须在用到 @monaco-editor/react 之前执行(loader.config 指向本地 monaco)。
// 本文件经 React.lazy 动态加载,故 Monaco 随本 chunk 按需拉取,不进入口包。
import '../monaco-setup';
import '../../../monaco-setup';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { createRoot, type Root } from 'react-dom/client';
Expand All @@ -21,23 +21,23 @@ import type {
SyncProgressEvent,
} from '@meebox/shared';
import { policyForPlatform } from '@meebox/shared';
import { invoke, subscribe } from '../api';
import { editorFontSize } from '../editor-font';
import { formatBackendError, type FormattedError } from '../errors';
import { REMOTE_REHYPE_PLUGINS } from '../markdown';
import { useDraftsForPr } from '../stores/drafts-store';
import { Avatar } from './Avatar';
import { DraftZone } from './DraftZone';
import { ErrorBoundary } from './ErrorBoundary';
import { makeBitbucketImageFor, transformBitbucketUrl } from './BitbucketImage';
import { CommentEditEditor } from './CommentEditEditor';
import { CommentReplyEditor } from './CommentReplyEditor';
import { ConfirmModal } from './ConfirmModal';
import { invoke, subscribe } from '../../../api';
import { editorFontSize } from '../../../editor-font';
import { formatBackendError, type FormattedError } from '../../../errors';
import { REMOTE_REHYPE_PLUGINS } from '../../../markdown';
import { useDraftsForPr } from '../../../stores/drafts-store';
import { Avatar } from '../../common/Avatar';
import { DraftZone } from '../drafts/DraftZone';
import { ErrorBoundary } from '../../common/ErrorBoundary';
import { makeBitbucketImageFor, transformBitbucketUrl } from '../../common/BitbucketImage';
import { CommentEditEditor } from '../comments/CommentEditEditor';
import { CommentReplyEditor } from '../comments/CommentReplyEditor';
import { ConfirmModal } from '../../common/ConfirmModal';
import { DiffSearchPanel } from './DiffSearchPanel';
import { FileTree } from './FileTree';
import { PaneLoading } from './Loading';
import { FileTreeIcon, SearchIcon } from './icons';
import { languageFor } from '../utils/language';
import { PaneLoading } from '../../common/Loading';
import { FileTreeIcon, SearchIcon } from '../../common/icons';
import { languageFor } from '../../../utils/language';

interface DiffViewProps {
pr: StoredPullRequest;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next';
import type { TFunction } from 'i18next';
import { Icon } from '@iconify/react';
import type { DiffChangedFile } from '@meebox/shared';
import { ChevronIcon } from './icons';
import { ChevronIcon } from '../../common/icons';

interface FileTreeProps {
files: DiffChangedFile[];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import ReactMarkdown from 'react-markdown';
import remarkBreaks from 'remark-breaks';
import remarkGfm from 'remark-gfm';
import type { ReviewDraft } from '@meebox/shared';
import { ConfirmModal } from './ConfirmModal';
import { TrashIcon } from './icons';
import { ConfirmModal } from '../../common/ConfirmModal';
import { TrashIcon } from '../../common/icons';

interface DraftZoneProps {
draft: ReviewDraft;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import ReactMarkdown from 'react-markdown';
import remarkBreaks from 'remark-breaks';
import remarkGfm from 'remark-gfm';
import type { PlatformCapabilities, ReviewDraft, StoredPullRequest } from '@meebox/shared';
import { invoke } from '../api';
import { useDraftsForPr } from '../stores/drafts-store';
import { ConfirmModal } from './ConfirmModal';
import { invoke } from '../../../api';
import { useDraftsForPr } from '../../../stores/drafts-store';
import { ConfirmModal } from '../../common/ConfirmModal';

// posted 已不存在 (发布成功即删本地),筛选项只保留 publishable / all / rejected
type Filter = 'all' | 'publishable' | 'rejected';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import type { ReviewDraft } from '@meebox/shared';
import { invoke } from '../api';
import { invoke } from '../../../api';

/**
* 批量发布草稿到 Bitbucket 的确认 modal。M4 发布闭环最后一公里。
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { LANGUAGE_OPTIONS, type LlmProfile, type SupportedLanguage } from '@meebox/shared';
import { invoke } from '../../api';
import i18n, { persistLanguage, resolveUiLanguage } from '../../i18n';
import { invoke } from '../../../api';
import i18n, { persistLanguage, resolveUiLanguage } from '../../../i18n';
import {
connDraftCanSave,
fromConnDraft,
type ConnDraft,
type ConnEntry,
} from '../ConnectionForm';
import { newProfileId } from '../LlmProfileForm';
} from '../settings/ConnectionForm';
import { newProfileId } from '../settings/LlmProfileForm';
import { WelcomeStep } from './steps/WelcomeStep';
import { PlatformStep } from './steps/PlatformStep';
import { LlmStep } from './steps/LlmStep';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useTranslation } from 'react-i18next';
import { SuccessBadgeIcon } from '../../icons';
import { SuccessBadgeIcon } from '../../../common/icons';

export function DoneStep({ submitting, error }: { submitting: boolean; error: string | null }) {
const { t } = useTranslation();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import type { LlmProfile } from '@meebox/shared';
import { LLM_PROVIDERS, LlmProfileForm } from '../../LlmProfileForm';
import { LlmProviderIcon } from '../../LlmProviderIcon';
import { LLM_PROVIDERS, LlmProfileForm } from '../../settings/LlmProfileForm';
import { LlmProviderIcon } from '../../../common/LlmProviderIcon';

export function LlmStep({
draft,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { useTranslation } from 'react-i18next';
import { invoke } from '../../../api';
import { ConnectionForm, type ConnDraft } from '../../ConnectionForm';
import { PLATFORM_META } from '../../PlatformIcon';
import { FolderIcon } from '../../icons';
import { invoke } from '../../../../api';
import { ConnectionForm, type ConnDraft } from '../../settings/ConnectionForm';
import { PLATFORM_META } from '../../../common/PlatformIcon';
import { FolderIcon } from '../../../common/icons';

export function PlatformStep({
connDraft,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useRef } from 'react';
import { useTranslation } from 'react-i18next';
import { invoke } from '../../../api';
import { PullRequestIcon } from '../../icons';
import { invoke } from '../../../../api';
import { PullRequestIcon } from '../../../common/icons';

export function WelcomeStep({ onStart }: { onStart: () => void }) {
const { t } = useTranslation();
Expand Down
Loading
Loading