diff --git a/crates/services/src/services/git_host/azure/cli.rs b/crates/services/src/services/git_host/azure/cli.rs index cb5ad420..4e4fda78 100644 --- a/crates/services/src/services/git_host/azure/cli.rs +++ b/crates/services/src/services/git_host/azure/cli.rs @@ -531,6 +531,7 @@ impl AzCli { url: None, path: path.clone(), line, + side: None, diff_hunk: None, }); } else { diff --git a/crates/services/src/services/git_host/github/mod.rs b/crates/services/src/services/git_host/github/mod.rs index ec75f227..867460c4 100644 --- a/crates/services/src/services/git_host/github/mod.rs +++ b/crates/services/src/services/git_host/github/mod.rs @@ -352,6 +352,7 @@ impl GitHostProvider for GitHubProvider { url: Some(c.html_url), path: c.path, line: c.line, + side: c.side, diff_hunk: Some(c.diff_hunk), }); } diff --git a/crates/services/src/services/git_host/types.rs b/crates/services/src/services/git_host/types.rs index a347e52d..52b5a393 100644 --- a/crates/services/src/services/git_host/types.rs +++ b/crates/services/src/services/git_host/types.rs @@ -119,6 +119,7 @@ pub enum UnifiedPrComment { url: Option, path: String, line: Option, + side: Option, diff_hunk: Option, }, } diff --git a/frontend/src/components/ui-new/containers/CommentWidgetLine.tsx b/frontend/src/components/ui-new/containers/CommentWidgetLine.tsx index f882d715..d8e24e7d 100644 --- a/frontend/src/components/ui-new/containers/CommentWidgetLine.tsx +++ b/frontend/src/components/ui-new/containers/CommentWidgetLine.tsx @@ -1,6 +1,7 @@ import { useState, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; import { PrimaryButton } from '../primitives/PrimaryButton'; +import { CommentCard } from '../primitives/CommentCard'; import WYSIWYGEditor from '@/components/ui/wysiwyg'; import { useReview, type ReviewDraft } from '@/contexts/ReviewProvider'; @@ -43,18 +44,10 @@ export function CommentWidgetLine({ }, [value, draft, setDraft, widgetKey, onSave, addComment]); return ( -
-
- -
+ {t('actions.cancel')} -
-
-
+ + } + > + + ); } diff --git a/frontend/src/components/ui-new/containers/DiffViewCardWithComments.tsx b/frontend/src/components/ui-new/containers/DiffViewCardWithComments.tsx index e62bdfb7..ab38d739 100644 --- a/frontend/src/components/ui-new/containers/DiffViewCardWithComments.tsx +++ b/frontend/src/components/ui-new/containers/DiffViewCardWithComments.tsx @@ -1,6 +1,10 @@ import { useMemo, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; -import { CaretDownIcon, ChatCircleIcon } from '@phosphor-icons/react'; +import { + CaretDownIcon, + ChatCircleIcon, + GithubLogoIcon, +} from '@phosphor-icons/react'; import { DiffView, DiffModeEnum, SplitSide } from '@git-diff-view/react'; import { generateDiffFile, type DiffFile } from '@git-diff-view/file'; import { cn } from '@/lib/utils'; @@ -15,8 +19,13 @@ import { type ReviewDraft, type ReviewComment, } from '@/contexts/ReviewProvider'; +import { + useWorkspaceContext, + type NormalizedGitHubComment, +} from '@/contexts/WorkspaceContext'; import { CommentWidgetLine } from './CommentWidgetLine'; import { ReviewCommentRenderer } from './ReviewCommentRenderer'; +import { GitHubCommentRenderer } from './GitHubCommentRenderer'; import type { ToolStatus, DiffChangeKind } from 'shared/types'; import { ToolStatusDot } from '../primitives/conversation/ToolStatusDot'; import { OpenInIdeButton } from '@/components/ide/OpenInIdeButton'; @@ -24,6 +33,11 @@ import { useOpenInEditor } from '@/hooks/useOpenInEditor'; import '@/styles/diff-style-overrides.css'; import { DisplayTruncatedPath } from '@/utils/TruncatePath'; +/** Discriminated union for comment data in extendData */ +type ExtendLineData = + | { type: 'review'; comment: ReviewComment } + | { type: 'github'; comment: NormalizedGitHubComment }; + // Discriminated union for input format flexibility export type DiffInput = | { @@ -172,6 +186,8 @@ export function DiffViewCardWithComments({ const { diffFile, additions, deletions, filePath, isValid } = useDiffData(input); const { comments, drafts, setDraft } = useReview(); + const { showGitHubComments, getGitHubCommentsForFile } = + useWorkspaceContext(); // Open in IDE functionality const openInEditor = useOpenInEditor(attemptId); @@ -212,17 +228,48 @@ export function DiffViewCardWithComments({ [comments, filePath] ); - // Transform comments to git-diff-view extendData format - const extendData = useMemo(() => { - const oldFileData: Record = {}; - const newFileData: Record = {}; + // Get GitHub comments for this file (only when enabled) + const githubCommentsForFile = useMemo(() => { + if (!showGitHubComments) return []; + return getGitHubCommentsForFile(filePath); + }, [showGitHubComments, getGitHubCommentsForFile, filePath]); + // Total comment count (user + GitHub) + const totalCommentCount = + commentsForFile.length + githubCommentsForFile.length; + + // Transform comments to git-diff-view extendData format + // The library expects { data: T } where T is the actual data + const extendData = useMemo(() => { + const oldFileData: Record = {}; + const newFileData: Record = {}; + + // Add user review comments first (higher priority) commentsForFile.forEach((comment) => { const lineKey = String(comment.lineNumber); + const entry: ExtendLineData = { type: 'review', comment }; if (comment.side === SplitSide.old) { - oldFileData[lineKey] = { data: comment }; + oldFileData[lineKey] = { data: entry }; } else { - newFileData[lineKey] = { data: comment }; + newFileData[lineKey] = { data: entry }; + } + }); + + // Add GitHub comments (only if no user comment on that line). + // User comments take priority - if you're adding your own comment on a line, + // you've likely addressed the GitHub feedback, so we hide the GitHub comment. + githubCommentsForFile.forEach((comment) => { + const lineKey = String(comment.lineNumber); + const entry: ExtendLineData = { type: 'github', comment }; + // Place comment on correct side based on GitHub's side field + if (comment.side === SplitSide.old) { + if (!oldFileData[lineKey]) { + oldFileData[lineKey] = { data: entry }; + } + } else { + if (!newFileData[lineKey]) { + newFileData[lineKey] = { data: entry }; + } } }); @@ -230,7 +277,7 @@ export function DiffViewCardWithComments({ oldFile: oldFileData, newFile: newFileData, }; - }, [commentsForFile]); + }, [commentsForFile, githubCommentsForFile]); // Handle click on "add widget" button in diff view const handleAddWidgetClick = useCallback( @@ -269,11 +316,21 @@ export function DiffViewCardWithComments({ [filePath, drafts, projectId] ); - // Render existing comments below lines + // Render existing comments below lines (handles both user and GitHub comments) + // The library wraps our data in { data: ExtendLineData } const renderExtendLine = useCallback( - (lineData: { data: ReviewComment }) => { + (lineData: { data: ExtendLineData }) => { + // Guard against undefined data (can happen when switching diff modes) + if (!lineData.data) return null; + + if (lineData.data.type === 'github') { + return ; + } return ( - + ); }, [projectId] @@ -332,10 +389,20 @@ export function DiffViewCardWithComments({ {deletions > 0 && -{deletions}} )} - {commentsForFile.length > 0 && ( - - - {commentsForFile.length} + {totalCommentCount > 0 && ( + + {commentsForFile.length > 0 && ( + + + {commentsForFile.length} + + )} + {githubCommentsForFile.length > 0 && ( + + + {githubCommentsForFile.length} + + )} )}
@@ -393,8 +460,8 @@ function DiffViewBodyWithComments({ theme: 'light' | 'dark'; diffMode: DiffModeEnum; extendData: { - oldFile: Record; - newFile: Record; + oldFile: Record; + newFile: Record; }; onAddWidgetClick: (lineNumber: number, side: SplitSide) => void; renderWidgetLine: (props: { @@ -402,7 +469,7 @@ function DiffViewBodyWithComments({ lineNumber: number; onClose: () => void; }) => React.ReactNode; - renderExtendLine: (lineData: { data: ReviewComment }) => React.ReactNode; + renderExtendLine: (lineData: { data: ExtendLineData }) => React.ReactNode; }) { const { t } = useTranslation('tasks'); if (!isValid || !diffFile) { diff --git a/frontend/src/components/ui-new/containers/FileTreeContainer.tsx b/frontend/src/components/ui-new/containers/FileTreeContainer.tsx index 6b09144f..211d1db9 100644 --- a/frontend/src/components/ui-new/containers/FileTreeContainer.tsx +++ b/frontend/src/components/ui-new/containers/FileTreeContainer.tsx @@ -7,6 +7,7 @@ import { getAllFolderPaths, } from '@/utils/fileTreeUtils'; import { usePersistedCollapsedPaths } from '@/stores/useUiPreferencesStore'; +import { useWorkspaceContext } from '@/contexts/WorkspaceContext'; import type { Diff } from 'shared/types'; interface FileTreeContainerProps { @@ -30,6 +31,14 @@ export function FileTreeContainer({ const [selectedPath, setSelectedPath] = useState(null); const nodeRefs = useRef>(new Map()); + // Get GitHub comments state from workspace context + const { + showGitHubComments, + setShowGitHubComments, + getGitHubCommentCountForFile, + isGitHubCommentsLoading, + } = useWorkspaceContext(); + // Sync selectedPath with external selectedFilePath prop and scroll into view useEffect(() => { if (selectedFilePath !== undefined) { @@ -129,6 +138,10 @@ export function FileTreeContainer({ isAllExpanded={isAllExpanded} onToggleExpandAll={handleToggleExpandAll} className={className} + showGitHubComments={showGitHubComments} + onToggleGitHubComments={setShowGitHubComments} + getGitHubCommentCountForFile={getGitHubCommentCountForFile} + isGitHubCommentsLoading={isGitHubCommentsLoading} /> ); } diff --git a/frontend/src/components/ui-new/containers/GitHubCommentRenderer.tsx b/frontend/src/components/ui-new/containers/GitHubCommentRenderer.tsx new file mode 100644 index 00000000..901356e8 --- /dev/null +++ b/frontend/src/components/ui-new/containers/GitHubCommentRenderer.tsx @@ -0,0 +1,41 @@ +import { GithubLogoIcon, ArrowSquareOutIcon } from '@phosphor-icons/react'; +import { CommentCard } from '../primitives/CommentCard'; +import { formatRelativeTime } from '@/utils/date'; +import type { NormalizedGitHubComment } from '@/contexts/WorkspaceContext'; + +interface GitHubCommentRendererProps { + comment: NormalizedGitHubComment; +} + +/** + * Read-only renderer for GitHub PR comments. + * Uses CommentCard primitive with 'github' variant for neutral styling. + */ +export function GitHubCommentRenderer({ comment }: GitHubCommentRendererProps) { + const header = ( +
+ + @{comment.author} + {formatRelativeTime(comment.createdAt)} + {comment.url && ( + e.stopPropagation()} + > + + + )} +
+ ); + + return ( + +
+ {comment.body} +
+
+ ); +} diff --git a/frontend/src/components/ui-new/containers/ReviewCommentRenderer.tsx b/frontend/src/components/ui-new/containers/ReviewCommentRenderer.tsx index 66ded606..98cead43 100644 --- a/frontend/src/components/ui-new/containers/ReviewCommentRenderer.tsx +++ b/frontend/src/components/ui-new/containers/ReviewCommentRenderer.tsx @@ -1,6 +1,7 @@ import { useState } from 'react'; import { useTranslation } from 'react-i18next'; import { PrimaryButton } from '../primitives/PrimaryButton'; +import { CommentCard } from '../primitives/CommentCard'; import WYSIWYGEditor from '@/components/ui/wysiwyg'; import { useReview, type ReviewComment } from '@/contexts/ReviewProvider'; @@ -41,18 +42,10 @@ export function ReviewCommentRenderer({ if (isEditing) { return ( -
-
- -
+ {t('actions.cancel')} -
-
-
+ + } + > + + ); } return ( -
-
- -
-
+ + + ); } diff --git a/frontend/src/components/ui-new/primitives/CommentCard.tsx b/frontend/src/components/ui-new/primitives/CommentCard.tsx new file mode 100644 index 00000000..52df2939 --- /dev/null +++ b/frontend/src/components/ui-new/primitives/CommentCard.tsx @@ -0,0 +1,51 @@ +import { ReactNode } from 'react'; +import { cn } from '@/lib/utils'; + +export type CommentCardVariant = 'user' | 'github' | 'input'; + +interface CommentCardProps { + /** Determines the visual styling */ + variant: CommentCardVariant; + /** Main content (editor, text, etc.) */ + children: ReactNode; + /** Optional header (author, timestamp) */ + header?: ReactNode; + /** Optional action buttons */ + actions?: ReactNode; + /** Additional className for the outer wrapper */ + className?: string; +} + +const variantStyles: Record = { + user: 'bg-brand/20 border-brand', + github: 'bg-secondary border-border', + input: 'bg-brand/20 border-brand', +}; + +/** + * Shared primitive for displaying comments in diff views. + * Used by ReviewCommentRenderer, GitHubCommentRenderer, and CommentWidgetLine. + */ +export function CommentCard({ + variant, + children, + header, + actions, + className, +}: CommentCardProps) { + return ( +
+
+ {header &&
{header}
} + {children} + {actions &&
{actions}
} +
+
+ ); +} diff --git a/frontend/src/components/ui-new/views/FileTree.tsx b/frontend/src/components/ui-new/views/FileTree.tsx index 0fa89eb3..9cc605a1 100644 --- a/frontend/src/components/ui-new/views/FileTree.tsx +++ b/frontend/src/components/ui-new/views/FileTree.tsx @@ -1,5 +1,7 @@ import { useTranslation } from 'react-i18next'; +import { GithubLogoIcon } from '@phosphor-icons/react'; import { cn } from '@/lib/utils'; +import { Tooltip } from '../primitives/Tooltip'; import { FileTreeSearchBar } from './FileTreeSearchBar'; import { FileTreeNode } from './FileTreeNode'; import type { TreeNode } from '../types/fileTree'; @@ -18,6 +20,14 @@ interface FileTreeProps { isAllExpanded: boolean; onToggleExpandAll: () => void; className?: string; + /** Whether to show GitHub comments */ + showGitHubComments?: boolean; + /** Callback to toggle GitHub comments visibility */ + onToggleGitHubComments?: (show: boolean) => void; + /** Function to get comment count for a file path (handles prefixed paths) */ + getGitHubCommentCountForFile?: (filePath: string) => number; + /** Whether GitHub comments are currently loading */ + isGitHubCommentsLoading?: boolean; } export function FileTree({ @@ -32,6 +42,10 @@ export function FileTree({ isAllExpanded, onToggleExpandAll, className, + showGitHubComments, + onToggleGitHubComments, + getGitHubCommentCountForFile, + isGitHubCommentsLoading, }: FileTreeProps) { const { t } = useTranslation(['tasks', 'common']); @@ -56,6 +70,8 @@ export function FileTree({ ? () => onSelectFile(node.path) : undefined } + commentCount={getGitHubCommentCountForFile?.(node.path)} + showCommentBadge={showGitHubComments} /> {node.type === 'folder' && node.children && @@ -73,12 +89,42 @@ export function FileTree({ contentClassName="flex flex-col flex-1 min-h-0" >
- +
+
+ +
+ {onToggleGitHubComments && ( + + + + )} +
{nodes.length > 0 ? ( diff --git a/frontend/src/components/ui-new/views/FileTreeNode.tsx b/frontend/src/components/ui-new/views/FileTreeNode.tsx index b266aeaf..a65a58d3 100644 --- a/frontend/src/components/ui-new/views/FileTreeNode.tsx +++ b/frontend/src/components/ui-new/views/FileTreeNode.tsx @@ -3,6 +3,7 @@ import { CaretDownIcon, CaretRightIcon, FolderSimpleIcon, + GithubLogoIcon, } from '@phosphor-icons/react'; import { cn } from '@/lib/utils'; import { getFileIcon } from '@/utils/fileTypeIcon'; @@ -17,11 +18,24 @@ interface FileTreeNodeProps { isSelected?: boolean; onToggle?: () => void; onSelect?: () => void; + /** GitHub comment count for this file */ + commentCount?: number; + /** Whether to show the comment badge */ + showCommentBadge?: boolean; } export const FileTreeNode = forwardRef( function FileTreeNode( - { node, depth, isExpanded = false, isSelected = false, onToggle, onSelect }, + { + node, + depth, + isExpanded = false, + isSelected = false, + onToggle, + onSelect, + commentCount, + showCommentBadge, + }, ref ) { const { theme } = useTheme(); @@ -128,6 +142,17 @@ export const FileTreeNode = forwardRef( )} )} + + {/* GitHub comment badge */} + {showCommentBadge && + node.type === 'file' && + commentCount != null && + commentCount > 0 && ( + + + {commentCount} + + )}
); diff --git a/frontend/src/contexts/WorkspaceContext.tsx b/frontend/src/contexts/WorkspaceContext.tsx index 129c0fa2..5117e140 100644 --- a/frontend/src/contexts/WorkspaceContext.tsx +++ b/frontend/src/contexts/WorkspaceContext.tsx @@ -15,13 +15,20 @@ import { import { useAttempt } from '@/hooks/useAttempt'; import { useAttemptRepo } from '@/hooks/useAttemptRepo'; import { useWorkspaceSessions } from '@/hooks/useWorkspaceSessions'; +import { + useGitHubComments, + type NormalizedGitHubComment, +} from '@/hooks/useGitHubComments'; import { attemptsApi } from '@/lib/api'; import type { Workspace as ApiWorkspace, Session, RepoWithTargetBranch, + UnifiedPrComment, } from 'shared/types'; +export type { NormalizedGitHubComment } from '@/hooks/useGitHubComments'; + interface WorkspaceContextValue { workspaceId: string | undefined; /** Real workspace data from API */ @@ -48,6 +55,13 @@ interface WorkspaceContextValue { /** Repos for the current workspace */ repos: RepoWithTargetBranch[]; isReposLoading: boolean; + /** GitHub PR Comments */ + gitHubComments: UnifiedPrComment[]; + isGitHubCommentsLoading: boolean; + showGitHubComments: boolean; + setShowGitHubComments: (show: boolean) => void; + getGitHubCommentsForFile: (filePath: string) => NormalizedGitHubComment[]; + getGitHubCommentCountForFile: (filePath: string) => number; } const WorkspaceContext = createContext(null); @@ -95,6 +109,24 @@ export function WorkspaceProvider({ children }: WorkspaceProviderProps) { enabled: !isCreateMode, }); + // Get first repo ID for PR comments. + // TODO: Support multiple repos - currently only fetches comments from the primary repo. + const primaryRepoId = repos[0]?.id; + + // GitHub comments hook (fetching, normalization, and helpers) + const { + gitHubComments, + isGitHubCommentsLoading, + showGitHubComments, + setShowGitHubComments, + getGitHubCommentsForFile, + getGitHubCommentCountForFile, + } = useGitHubComments({ + workspaceId, + repoId: primaryRepoId, + enabled: !isCreateMode, + }); + const isLoading = isLoadingList || isLoadingWorkspace; const selectWorkspace = useCallback( @@ -142,6 +174,12 @@ export function WorkspaceProvider({ children }: WorkspaceProviderProps) { startNewSession, repos, isReposLoading, + gitHubComments, + isGitHubCommentsLoading, + showGitHubComments, + setShowGitHubComments, + getGitHubCommentsForFile, + getGitHubCommentCountForFile, }), [ workspaceId, @@ -162,6 +200,12 @@ export function WorkspaceProvider({ children }: WorkspaceProviderProps) { startNewSession, repos, isReposLoading, + gitHubComments, + isGitHubCommentsLoading, + showGitHubComments, + setShowGitHubComments, + getGitHubCommentsForFile, + getGitHubCommentCountForFile, ] ); diff --git a/frontend/src/hooks/useGitHubComments.ts b/frontend/src/hooks/useGitHubComments.ts new file mode 100644 index 00000000..3ec942d8 --- /dev/null +++ b/frontend/src/hooks/useGitHubComments.ts @@ -0,0 +1,122 @@ +import { useMemo, useCallback } from 'react'; +import { SplitSide } from '@git-diff-view/react'; +import { usePrComments } from './usePrComments'; +import { + usePersistedExpanded, + PERSIST_KEYS, +} from '@/stores/useUiPreferencesStore'; +import type { UnifiedPrComment } from 'shared/types'; + +/** + * Normalized GitHub comment for diff view display + */ +export interface NormalizedGitHubComment { + id: string; + author: string; + body: string; + createdAt: string; + url: string | null; + filePath: string; + lineNumber: number; + side: SplitSide; + diffHunk: string | null; +} + +interface UseGitHubCommentsOptions { + workspaceId?: string; + repoId?: string; + enabled?: boolean; +} + +interface UseGitHubCommentsResult { + gitHubComments: UnifiedPrComment[]; + isGitHubCommentsLoading: boolean; + showGitHubComments: boolean; + setShowGitHubComments: (show: boolean) => void; + getGitHubCommentsForFile: (filePath: string) => NormalizedGitHubComment[]; + getGitHubCommentCountForFile: (filePath: string) => number; +} + +export function useGitHubComments({ + workspaceId, + repoId, + enabled = true, +}: UseGitHubCommentsOptions): UseGitHubCommentsResult { + // GitHub comments toggle state (persisted) + const [showGitHubComments, setShowGitHubComments] = usePersistedExpanded( + PERSIST_KEYS.showGitHubComments, + true // Default to shown + ); + + // Fetch PR comments for the current workspace + const { data: prCommentsData, isLoading: isGitHubCommentsLoading } = + usePrComments(workspaceId, repoId, { + enabled: enabled && !!repoId, + }); + + const gitHubComments = useMemo( + () => prCommentsData?.comments ?? [], + [prCommentsData?.comments] + ); + + // Normalize GitHub review comments for file matching + const normalizedComments = useMemo(() => { + const normalized: NormalizedGitHubComment[] = []; + for (const comment of gitHubComments) { + if (comment.comment_type !== 'review') continue; + if (comment.line === null) continue; // Skip file-level comments + + normalized.push({ + id: String(comment.id), + author: comment.author, + body: comment.body, + createdAt: comment.created_at, + url: comment.url, + filePath: comment.path, + lineNumber: Number(comment.line), + // Use side from API: "LEFT" = old/deleted side, "RIGHT" = new/added side (default) + side: comment.side === 'LEFT' ? SplitSide.old : SplitSide.new, + diffHunk: comment.diff_hunk, + }); + } + return normalized; + }, [gitHubComments]); + + // Helper to match paths - handles repo prefix in diff paths + // GitHub paths: "frontend/src/file.ts" + // Diff paths: "vibe-kanban/frontend/src/file.ts" (prefixed with repo name) + const pathMatches = useCallback( + (diffPath: string, githubPath: string): boolean => { + return diffPath === githubPath || diffPath.endsWith('/' + githubPath); + }, + [] + ); + + // Get comments for a specific file (handles prefixed paths) + const getGitHubCommentsForFile = useCallback( + (filePath: string): NormalizedGitHubComment[] => { + return normalizedComments.filter((c) => + pathMatches(filePath, c.filePath) + ); + }, + [normalizedComments, pathMatches] + ); + + // Get comment count for a specific file (handles prefixed paths) + const getGitHubCommentCountForFile = useCallback( + (filePath: string): number => { + return normalizedComments.filter((c) => pathMatches(filePath, c.filePath)) + .length; + }, + [normalizedComments, pathMatches] + ); + + return { + gitHubComments, + isGitHubCommentsLoading, + showGitHubComments, + setShowGitHubComments, + getGitHubCommentsForFile, + getGitHubCommentCountForFile, + }; +} diff --git a/frontend/src/i18n/locales/en/common.json b/frontend/src/i18n/locales/en/common.json index 6349d00e..4c61678f 100644 --- a/frontend/src/i18n/locales/en/common.json +++ b/frontend/src/i18n/locales/en/common.json @@ -143,7 +143,9 @@ "fileTree": { "searchPlaceholder": "Search files...", "noResults": "No matching files", - "title": "Files" + "title": "Files", + "showGitHubComments": "Show GitHub comments", + "hideGitHubComments": "Hide GitHub comments" }, "sections": { "changes": "Changes", diff --git a/frontend/src/i18n/locales/es/common.json b/frontend/src/i18n/locales/es/common.json index c559a9b9..d9b5c22d 100644 --- a/frontend/src/i18n/locales/es/common.json +++ b/frontend/src/i18n/locales/es/common.json @@ -143,7 +143,9 @@ "fileTree": { "searchPlaceholder": "Buscar archivos...", "noResults": "No hay archivos coincidentes", - "title": "Archivos" + "title": "Archivos", + "showGitHubComments": "Mostrar comentarios de GitHub", + "hideGitHubComments": "Ocultar comentarios de GitHub" }, "sections": { "changes": "Cambios", diff --git a/frontend/src/i18n/locales/ja/common.json b/frontend/src/i18n/locales/ja/common.json index 3932d811..67a790ed 100644 --- a/frontend/src/i18n/locales/ja/common.json +++ b/frontend/src/i18n/locales/ja/common.json @@ -143,7 +143,9 @@ "fileTree": { "searchPlaceholder": "ファイルを検索...", "noResults": "一致するファイルがありません", - "title": "ファイル" + "title": "ファイル", + "showGitHubComments": "GitHubコメントを表示", + "hideGitHubComments": "GitHubコメントを非表示" }, "sections": { "changes": "変更", diff --git a/frontend/src/i18n/locales/ko/common.json b/frontend/src/i18n/locales/ko/common.json index 18218b40..d5081b0b 100644 --- a/frontend/src/i18n/locales/ko/common.json +++ b/frontend/src/i18n/locales/ko/common.json @@ -143,7 +143,9 @@ "fileTree": { "searchPlaceholder": "파일 검색...", "noResults": "일치하는 파일 없음", - "title": "파일" + "title": "파일", + "showGitHubComments": "GitHub 댓글 표시", + "hideGitHubComments": "GitHub 댓글 숨기기" }, "sections": { "changes": "변경사항", diff --git a/frontend/src/i18n/locales/zh-Hans/common.json b/frontend/src/i18n/locales/zh-Hans/common.json index f77a740a..3a8c3421 100644 --- a/frontend/src/i18n/locales/zh-Hans/common.json +++ b/frontend/src/i18n/locales/zh-Hans/common.json @@ -143,7 +143,9 @@ "fileTree": { "searchPlaceholder": "搜索文件...", "noResults": "没有匹配的文件", - "title": "文件" + "title": "文件", + "showGitHubComments": "显示 GitHub 评论", + "hideGitHubComments": "隐藏 GitHub 评论" }, "sections": { "changes": "更改", diff --git a/frontend/src/i18n/locales/zh-Hant/common.json b/frontend/src/i18n/locales/zh-Hant/common.json index 4a2eaadf..b62612a0 100644 --- a/frontend/src/i18n/locales/zh-Hant/common.json +++ b/frontend/src/i18n/locales/zh-Hant/common.json @@ -143,7 +143,9 @@ "fileTree": { "searchPlaceholder": "搜尋檔案...", "noResults": "沒有匹配的檔案", - "title": "檔案" + "title": "檔案", + "showGitHubComments": "顯示 GitHub 評論", + "hideGitHubComments": "隱藏 GitHub 評論" }, "sections": { "changes": "變更", diff --git a/frontend/src/stores/useUiPreferencesStore.ts b/frontend/src/stores/useUiPreferencesStore.ts index 3b2a5e63..7d81a072 100644 --- a/frontend/src/stores/useUiPreferencesStore.ts +++ b/frontend/src/stores/useUiPreferencesStore.ts @@ -30,6 +30,8 @@ export const PERSIST_KEYS = { devServerSection: 'dev-server-section', // Context bar contextBarPosition: 'context-bar-position', + // GitHub comments toggle + showGitHubComments: 'show-github-comments', // Pane sizes sidebarWidth: 'workspaces-sidebar-width', gitPanelWidth: 'workspaces-git-panel-width', @@ -50,6 +52,7 @@ export type PersistKey = | typeof PERSIST_KEYS.processesSection | typeof PERSIST_KEYS.changesSection | typeof PERSIST_KEYS.devServerSection + | typeof PERSIST_KEYS.showGitHubComments | typeof PERSIST_KEYS.sidebarWidth | typeof PERSIST_KEYS.gitPanelWidth | typeof PERSIST_KEYS.changesPanelWidth diff --git a/shared/types.ts b/shared/types.ts index f328fb46..b254a9ef 100644 --- a/shared/types.ts +++ b/shared/types.ts @@ -300,7 +300,7 @@ export type GetPrCommentsError = { "type": "no_pr_attached" } | { "type": "cli_n export type GetPrCommentsQuery = { repo_id: string, }; -export type UnifiedPrComment = { "comment_type": "general", id: string, author: string, author_association: string | null, body: string, created_at: string, url: string | null, } | { "comment_type": "review", id: bigint, author: string, author_association: string | null, body: string, created_at: string, url: string | null, path: string, line: bigint | null, diff_hunk: string | null, }; +export type UnifiedPrComment = { "comment_type": "general", id: string, author: string, author_association: string | null, body: string, created_at: string, url: string | null, } | { "comment_type": "review", id: bigint, author: string, author_association: string | null, body: string, created_at: string, url: string | null, path: string, line: bigint | null, side: string | null, diff_hunk: string | null, }; export type ProviderKind = "git_hub" | "azure_dev_ops" | "unknown";