Conversation
|
Warning Rate limit exceeded
Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 6 minutes and 26 seconds. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughAdds branch search/create TRPC endpoints and safer git branch commands; enriches blame tooltips with cached GitHub commit-author avatars; reworks terminal history suggestions with typing-preview and keyboard changes; introduces a compact changes-list UI and threads worktreePath through blame/editor components. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Blame as Blame Plugin
participant TRPC as TRPC Endpoint
participant GitHub as GitHub API
participant Cache as CommitAuthor Cache
User->>Blame: Open blame tooltip (missing avatar)
Blame->>TRPC: getGitHubCommitAuthor(worktreePath, commitHash)
TRPC->>Cache: lookup(worktreePath#commitHash)
alt cache hit
Cache-->>TRPC: cached author/null
else
TRPC->>GitHub: gh api repos/<owner>/<name>/commits/<sha>
GitHub-->>TRPC: response (author/login, avatar_url)
TRPC->>Cache: store result (TTL)
end
TRPC-->>Blame: GitHubCommitAuthor | null
Blame->>Blame: update tooltip avatar (image or initials)
sequenceDiagram
participant User
participant TerminalComp as Terminal Component
participant Suggestion as useTerminalSuggestion Hook
participant TRPC as TRPC getSuggestions
participant Preview as TerminalTypingPreview
participant Xterm as Xterm Instance
User->>TerminalComp: Press ↑
TerminalComp->>Suggestion: openHistorySuggestions()
Suggestion->>TRPC: getSuggestions(prefix)
TRPC-->>Suggestion: suggestions[]
Suggestion-->>TerminalComp: display suggestions
User->>Suggestion: select + Enter
Suggestion->>TerminalComp: onExecuteCommand(command, currentInput)
TerminalComp->>Preview: animate typing suffix (~200ms)
Preview->>Xterm: render preview at cursor
TerminalComp->>Xterm: write command + \r
TerminalComp->>Suggestion: clear/dismiss
sequenceDiagram
participant User
participant UI as Branch Create UI
participant TRPC as TRPC Endpoint
participant GitCmd as gitCreateBranch
participant Git as Git Process
participant DB as Worktree DB
User->>UI: submit new branch (name, startPoint)
UI->>TRPC: createBranch(worktreePath, branch, startPoint)
TRPC->>Git: check branch existence (local/remote)
alt branch exists
Git-->>TRPC: exists
TRPC-->>UI: { success: false }
else
TRPC->>GitCmd: gitCreateBranch(...)
GitCmd->>Git: git switch -c / fallback checkout -b
Git-->>GitCmd: switched/created
GitCmd-->>TRPC: verified current branch
TRPC->>DB: persist current branch (if registered)
TRPC->>TRPC: clear status cache, invalidate queries
TRPC-->>UI: { success: true, branch }
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (4)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/TerminalTypingPreview/TerminalTypingPreview.tsx (1)
10-27: Consider extractinggetCellDimensionsto a shared utility.This helper function is duplicated from
TerminalSuggestion.tsx. Extracting it to a shared location (e.g., autils.tsfile in the Terminal folder) would reduce duplication and centralize any future maintenance of xterm internal API access.♻️ Suggested extraction
Create a shared utility in the Terminal folder:
// utils.ts or xterm-utils.ts import type { Terminal as XTerm } from "@xterm/xterm"; export function getCellDimensions( xterm: XTerm, ): { width: number; height: number } | null { const dimensions = ( xterm as unknown as { _core?: { _renderService?: { dimensions?: { css: { cell: { width: number; height: number } } }; }; }; } )._core?._renderService?.dimensions; if (!dimensions?.css?.cell) return null; const { width, height } = dimensions.css.cell; if (width <= 0 || height <= 0) return null; return { width, height }; }Then import it in both
TerminalSuggestion.tsxandTerminalTypingPreview.tsx.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/TerminalTypingPreview/TerminalTypingPreview.tsx` around lines 10 - 27, The getCellDimensions function is duplicated between TerminalTypingPreview.tsx and TerminalSuggestion.tsx; extract it into a shared utility (e.g., Terminal/utils.ts or Terminal/xterm-utils.ts) as an exported function getCellDimensions(xterm: XTerm): { width: number; height: number } | null, move the implementation there, and update both TerminalTypingPreview.tsx and TerminalSuggestion.tsx to import and use that utility instead of their local copies; ensure the exported function keeps the same signature and behavior so callers (getCellDimensions) continue to work unchanged.apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx (1)
341-413: Animation logic is correct; considerrequestAnimationFramefor smoother visuals.The typing preview animation correctly calculates progress based on elapsed time and incrementally reveals characters. Using
setTimeout(..., 0)works but may produce inconsistent frame timing.♻️ Using requestAnimationFrame for smoother animation
- const tick = () => { - const elapsed = performance.now() - startTime; - const progress = Math.min(1, elapsed / durationMs); - const visibleLength = Math.max( - 1, - Math.min(totalSteps, Math.ceil(progress * totalSteps)), - ); - setTypingPreviewText(suffix.slice(0, visibleLength)); - - if (progress >= 1) { - finish(); - return; - } - - typingPreviewTimeoutRef.current = setTimeout(tick, 0); - }; - - setTypingPreviewText(suffix.slice(0, 1)); - typingPreviewTimeoutRef.current = setTimeout(tick, 0); + let rafId: number | null = null; + + const tick = () => { + const elapsed = performance.now() - startTime; + const progress = Math.min(1, elapsed / durationMs); + const visibleLength = Math.max( + 1, + Math.min(totalSteps, Math.ceil(progress * totalSteps)), + ); + setTypingPreviewText(suffix.slice(0, visibleLength)); + + if (progress >= 1) { + finish(); + return; + } + + rafId = requestAnimationFrame(tick); + }; + + setTypingPreviewText(suffix.slice(0, 1)); + rafId = requestAnimationFrame(tick);Note: You'd need to adjust the ref and cleanup logic to handle
cancelAnimationFrameinstead ofclearTimeout.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx` around lines 341 - 413, Replace the setTimeout-based animation in handleSuggestionExecute with requestAnimationFrame for smoother frames: change typingPreviewTimeoutRef to store an animation frame id (number), clear any existing frame via cancelAnimationFrame at the start, and use requestAnimationFrame inside tick instead of setTimeout; update finish to null the ref and ensure cancelAnimationFrame is used in any cleanup, and keep using startTime, duration (TYPING_PREVIEW_MAX_DURATION_MS), totalSteps, setTypingPreviewText, finish, and tick semantics otherwise so the reveal logic stays identical.apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/ChangesHeader/ChangesHeader.tsx (1)
759-765: Consider simplifying nested ternary.The four-level nested ternary is harder to scan. A lookup object or switch would improve readability.
💡 Alternative with object lookup
const modeRenderers = { default: renderDefaultList, create: renderCreateList, "create-from-ref": renderCreateFromRefList, "compare-base": renderCompareBaseList, } as const; // In JSX: {modeRenderers[mode]()}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/ChangesHeader/ChangesHeader.tsx` around lines 759 - 765, Replace the nested ternary expression that switches on mode with a clearer mapping or switch: create a lookup object (e.g., modeRenderers) that maps the mode values to the corresponding renderer functions renderDefaultList, renderCreateList, renderCreateFromRefList, and renderCompareBaseList, then invoke the selected renderer in JSX via modeRenderers[mode]() (or use a switch that returns the appropriate render function). Ensure the mapping keys cover "default", "create", "create-from-ref", and the compare case and handle unknown modes safely (fallback to renderDefaultList) to avoid runtime errors.apps/desktop/src/lib/trpc/routers/changes/branches.ts (1)
394-477: Consider logging suppressed errors for debuggability.The empty
catch {}blocks (lines 415, 452, 476) silently discard errors. While graceful degradation is appropriate here, consider adding debug-level logging to aid troubleshooting when ref enumeration unexpectedly returns partial results.💡 Example for debug logging
try { for (const localBranch of await getRefEntries(git, { refPath: "refs/heads/", dateField: "committerdate", authorField: "authorname", })) { // ... } - } catch {} + } catch (error) { + // Local branches unavailable, continue with partial results + console.debug("Failed to enumerate local branches:", error); + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/desktop/src/lib/trpc/routers/changes/branches.ts` around lines 394 - 477, The three empty catch blocks that swallow errors during ref enumeration (around the loops that call getRefEntries for refs/heads, refs/remotes/origin, and refs/tags) should capture the error and emit a debug-level log so partial failures are visible; replace each catch {} with catch (err) { /* use existing logger (e.g. processLogger.debug or console.debug) */ logger?.debug("enumerating refs failed in <loop context>:", err); } referencing getRefEntries, matchesSearch, and the refs push logic so you can see which enumeration (local, remote, tag) failed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@apps/desktop/src/renderer/screens/main/components/WorkspaceView/components/CodeEditor/createBlamePlugin.ts`:
- Around line 83-87: commitAuthorCache currently stores null on lookup failures
which permanently negative-caches transient errors; change caching so only
successful GitHubCommitAuthor results are stored (i.e., make commitAuthorCache a
Map<string, GitHubCommitAuthor> and never set null), and keep
commitAuthorInFlight as-is to coalesce requests; when a fetch fails, ensure you
reject/clear the in-flight entry and do not insert a null into commitAuthorCache
(or alternatively attach a short TTL to negative entries), updating the code
paths that set cache entries (the places that currently write null into
commitAuthorCache and where in-flight promises are resolved/rejected) to only
cache on success.
In
`@apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/ChangesHeader/ChangesHeader.tsx`:
- Around line 373-392: The sort comparator inside compareBaseBranches contains
dead checks against branchData?.defaultBranch even though that branch was
already removed by the filter; remove the two comparisons that check a ===
branchData?.defaultBranch and b === branchData?.defaultBranch from the
comparator in compareBaseBranches (or alternatively stop filtering out
branchData?.defaultBranch earlier if you intended to keep it) so the sort logic
only compares against effectiveBaseBranch and falls back to localeCompare.
---
Nitpick comments:
In `@apps/desktop/src/lib/trpc/routers/changes/branches.ts`:
- Around line 394-477: The three empty catch blocks that swallow errors during
ref enumeration (around the loops that call getRefEntries for refs/heads,
refs/remotes/origin, and refs/tags) should capture the error and emit a
debug-level log so partial failures are visible; replace each catch {} with
catch (err) { /* use existing logger (e.g. processLogger.debug or console.debug)
*/ logger?.debug("enumerating refs failed in <loop context>:", err); }
referencing getRefEntries, matchesSearch, and the refs push logic so you can see
which enumeration (local, remote, tag) failed.
In
`@apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx`:
- Around line 341-413: Replace the setTimeout-based animation in
handleSuggestionExecute with requestAnimationFrame for smoother frames: change
typingPreviewTimeoutRef to store an animation frame id (number), clear any
existing frame via cancelAnimationFrame at the start, and use
requestAnimationFrame inside tick instead of setTimeout; update finish to null
the ref and ensure cancelAnimationFrame is used in any cleanup, and keep using
startTime, duration (TYPING_PREVIEW_MAX_DURATION_MS), totalSteps,
setTypingPreviewText, finish, and tick semantics otherwise so the reveal logic
stays identical.
In
`@apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/TerminalTypingPreview/TerminalTypingPreview.tsx`:
- Around line 10-27: The getCellDimensions function is duplicated between
TerminalTypingPreview.tsx and TerminalSuggestion.tsx; extract it into a shared
utility (e.g., Terminal/utils.ts or Terminal/xterm-utils.ts) as an exported
function getCellDimensions(xterm: XTerm): { width: number; height: number } |
null, move the implementation there, and update both TerminalTypingPreview.tsx
and TerminalSuggestion.tsx to import and use that utility instead of their local
copies; ensure the exported function keeps the same signature and behavior so
callers (getCellDimensions) continue to work unchanged.
In
`@apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/ChangesHeader/ChangesHeader.tsx`:
- Around line 759-765: Replace the nested ternary expression that switches on
mode with a clearer mapping or switch: create a lookup object (e.g.,
modeRenderers) that maps the mode values to the corresponding renderer functions
renderDefaultList, renderCreateList, renderCreateFromRefList, and
renderCompareBaseList, then invoke the selected renderer in JSX via
modeRenderers[mode]() (or use a switch that returns the appropriate render
function). Ensure the mapping keys cover "default", "create", "create-from-ref",
and the compare case and handle unknown modes safely (fallback to
renderDefaultList) to avoid runtime errors.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: ba6db6dc-e412-4f1e-8410-8d455a4fdf00
📒 Files selected for processing (18)
apps/desktop/src/lib/trpc/routers/changes/branches.tsapps/desktop/src/lib/trpc/routers/changes/git-blame.tsapps/desktop/src/lib/trpc/routers/changes/security/git-commands.tsapps/desktop/src/lib/trpc/routers/workspaces/utils/github/cache.tsapps/desktop/src/main/lib/shell-history.tsapps/desktop/src/renderer/routes/_authenticated/settings/terminal/components/TerminalSettings/components/SuggestionsSetting/SuggestionsSetting.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/CodeMirrorDiffViewer/CodeMirrorDiffViewer.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileViewerContent/FileViewerContent.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/TerminalSuggestion/TerminalSuggestion.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/TerminalTypingPreview/TerminalTypingPreview.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/TerminalTypingPreview/index.tsapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/helpers.tsapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalLifecycle.tsapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalSuggestion.tsapps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/ChangesHeader/ChangesHeader.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/components/CodeEditor/CodeEditor.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/components/CodeEditor/createBlamePlugin.ts
💤 Files with no reviewable changes (1)
- apps/desktop/src/main/lib/shell-history.ts
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (4)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/TerminalSuggestion/TerminalSuggestion.tsx (3)
82-83: Potential stale refs when suggestions array shrinks.
itemTextRefs.currentis an array that grows as refs are assigned, but it's never trimmed whensuggestionsshrinks. This could leave stale references in the array, though it shouldn't cause issues since you only accessitemTextRefs.current[selectedIndex]which is bounded bysuggestions.length.♻️ Consider trimming refs array on render
+ // Trim refs array to match suggestions length + itemTextRefs.current.length = suggestions.length; + useEffect(() => { const selectedText = itemTextRefs.current[selectedIndex];🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/TerminalSuggestion/TerminalSuggestion.tsx` around lines 82 - 83, The itemTextRefs ref array can accumulate stale entries when suggestions shrinks; add logic to trim itemTextRefs.current to match suggestions.length (e.g. in an effect watching suggestions or before mapping) so that itemTextRefs.current = itemTextRefs.current.slice(0, suggestions.length) and ensure accesses like itemTextRefs.current[selectedIndex] remain bounded; update the ref-trimming logic around the existing itemTextRefs (useRef) and where suggestions and selectedIndex are used.
197-234: Consider guarding against prefix mismatch in suggestion display.If
suggestion.commanddoesn't start withprefix(which shouldn't happen normally, but could occur during rapid state updates),slice(prefix.length)would display incorrect text.🛡️ Proposed defensive rendering
- <span style={{ color: "#89b4fa" }}>{prefix}</span> - {suggestion.command.slice(prefix.length)} + {suggestion.command.startsWith(prefix) ? ( + <> + <span style={{ color: "#89b4fa" }}>{prefix}</span> + {suggestion.command.slice(prefix.length)} + </> + ) : ( + suggestion.command + )}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/TerminalSuggestion/TerminalSuggestion.tsx` around lines 197 - 234, In TerminalSuggestion (the suggestions.map rendering inside the TerminalSuggestion component), guard the substring operation on suggestion.command.slice(prefix.length) by first checking that suggestion.command actually starts with prefix (e.g., suggestion.command?.startsWith(prefix)); if it does not, fall back to rendering the full suggestion.command (or a safe truncated version) to avoid showing incorrect text during rapid state updates—update the span that currently renders prefix + suggestion.command.slice(prefix.length) to use this guarded logic and keep itemTextRefs/selectedIndex handling unchanged.
36-72: Consider handling edge case for future timestamps.If
lastRunAtis in the future (e.g., due to clock skew or corrupted history),diffMsbecomes negative, causing unexpected output like-1s ago. Consider adding a guard.🛡️ Proposed defensive check
function formatLastRunAgo(lastRunAt: number | null): string { if (!lastRunAt) return ""; const diffMs = Date.now() - lastRunAt; + if (diffMs < 0) return ""; + const minuteMs = 60_000;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/TerminalSuggestion/TerminalSuggestion.tsx` around lines 36 - 72, The function formatLastRunAgo currently computes diffMs = Date.now() - lastRunAt and can produce negative values when lastRunAt is in the future; update formatLastRunAgo to guard against future timestamps by clamping diffMs to 0 (or treating negatives as "just now") before the unit checks so you never return negative durations; change logic inside formatLastRunAgo to set diffMs = Math.max(0, Date.now() - lastRunAt) and then proceed with the existing minute/hour/day/week/month/year branches.apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/FileList/FileListCompact.tsx (1)
41-41: Consider memoizingsortedFilesfor consistency with the virtualized variant.
FileListCompactVirtualizedusesuseMemofor the sorted files, but this component re-sorts on every render. While the non-virtualized path is used for smaller lists (<200 files), memoization would maintain consistency and avoid unnecessary re-computation.♻️ Suggested change
+import { useMemo } from "react"; import type { ExternalApp } from "@superset/local-db"; import type { ChangeCategory, ChangedFile } from "shared/changes-types"; import { FileItem } from "../FileItem"; import { getDirectoryLabel, sortFilesForCompactView } from "./compact-view";}: FileListCompactProps) { - const sortedFiles = sortFilesForCompactView(files); + const sortedFiles = useMemo(() => sortFilesForCompactView(files), [files]);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/FileList/FileListCompact.tsx` at line 41, FileListCompact re-sorts on every render; wrap the call to sortFilesForCompactView(files) in a useMemo to match FileListCompactVirtualized and avoid unnecessary work. Replace the direct assignment to sortedFiles with a memoized value using React.useMemo(() => sortFilesForCompactView(files), [files]) (or import/useMemo) inside the FileListCompact component so sorting only runs when files changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/TerminalSuggestion/TerminalSuggestion.tsx`:
- Around line 94-104: The useEffect in TerminalSuggestion is over-specified:
remove unneeded dependencies `prefix` and `suggestions` from the dependency
array so it only depends on `selectedIndex` (and any refs you need); update the
effect that reads `itemTextRefs.current[selectedIndex]` and calls
`setIsSelectedTruncated(...)` to run only when `selectedIndex` changes (or, if
truncation should update when the selected item content changes, replace
`suggestions` with the specific value `suggestions[selectedIndex]?.command` in
the dependency array); modify the dependency array for the useEffect in
TerminalSuggestion.tsx accordingly.
In `@apps/desktop/src/renderer/stores/changes/store.ts`:
- Line 17: The store defines a broader FileListViewMode while sortFiles expects
a narrower one, causing unsafe passing of fileListViewMode into sortFiles; fix
by consolidating the type: export a single FileListViewMode from one module
(e.g., create or use the type in sortFiles.ts) and import that type into
store.ts so fileListViewMode uses the exact same union, or alternatively change
the store's usage to map/guard the "compact" value to a supported mode before
calling sortFiles (reference symbols: FileListViewMode, fileListViewMode,
sortFiles, sortFiles.ts).
---
Nitpick comments:
In
`@apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/TerminalSuggestion/TerminalSuggestion.tsx`:
- Around line 82-83: The itemTextRefs ref array can accumulate stale entries
when suggestions shrinks; add logic to trim itemTextRefs.current to match
suggestions.length (e.g. in an effect watching suggestions or before mapping) so
that itemTextRefs.current = itemTextRefs.current.slice(0, suggestions.length)
and ensure accesses like itemTextRefs.current[selectedIndex] remain bounded;
update the ref-trimming logic around the existing itemTextRefs (useRef) and
where suggestions and selectedIndex are used.
- Around line 197-234: In TerminalSuggestion (the suggestions.map rendering
inside the TerminalSuggestion component), guard the substring operation on
suggestion.command.slice(prefix.length) by first checking that
suggestion.command actually starts with prefix (e.g.,
suggestion.command?.startsWith(prefix)); if it does not, fall back to rendering
the full suggestion.command (or a safe truncated version) to avoid showing
incorrect text during rapid state updates—update the span that currently renders
prefix + suggestion.command.slice(prefix.length) to use this guarded logic and
keep itemTextRefs/selectedIndex handling unchanged.
- Around line 36-72: The function formatLastRunAgo currently computes diffMs =
Date.now() - lastRunAt and can produce negative values when lastRunAt is in the
future; update formatLastRunAgo to guard against future timestamps by clamping
diffMs to 0 (or treating negatives as "just now") before the unit checks so you
never return negative durations; change logic inside formatLastRunAgo to set
diffMs = Math.max(0, Date.now() - lastRunAt) and then proceed with the existing
minute/hour/day/week/month/year branches.
In
`@apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/FileList/FileListCompact.tsx`:
- Line 41: FileListCompact re-sorts on every render; wrap the call to
sortFilesForCompactView(files) in a useMemo to match FileListCompactVirtualized
and avoid unnecessary work. Replace the direct assignment to sortedFiles with a
memoized value using React.useMemo(() => sortFilesForCompactView(files),
[files]) (or import/useMemo) inside the FileListCompact component so sorting
only runs when files changes.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 1ca19d3c-aa68-468e-bbdf-01e1f8091fe9
📒 Files selected for processing (12)
apps/desktop/src/main/lib/shell-history.tsapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/TerminalSuggestion/TerminalSuggestion.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalSuggestion.tsapps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/FileItem/FileItem.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/FileList/FileList.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/FileList/FileListCompact.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/FileList/FileListCompactVirtualized.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/FileList/compact-view.tsapps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/FileList/index.tsapps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/ViewModeToggle/ViewModeToggle.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/types.tsapps/desktop/src/renderer/stores/changes/store.ts
✅ Files skipped from review due to trivial changes (1)
- apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/types.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalSuggestion.ts
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/TerminalSuggestion/TerminalSuggestion.tsx (1)
97-107:⚠️ Potential issue | 🟡 MinorRecompute truncation when the selected command changes.
This effect only depends on
selectedIndex. When a refresh swaps in a differentsuggestions[selectedIndex]while the index stays the same,isSelectedTruncatedis reused for the wrong command and the overflow tooltip can get stuck in the previous state.🔧 Suggested fix
- }, [selectedIndex]); + }, [selectedIndex, selectedCommand]);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/TerminalSuggestion/TerminalSuggestion.tsx` around lines 97 - 107, The effect that computes truncation for the selected item (using itemTextRefs.current[selectedIndex] and calling setIsSelectedTruncated) only lists selectedIndex as a dependency, so when the suggestion object at that index changes the truncation state is not recomputed; update the dependency array to include the suggestion value (e.g., suggestions or suggestions[selectedIndex]) so the useEffect reruns when the selected command changes, ensuring itemTextRefs, selectedIndex, suggestions, and setIsSelectedTruncated are considered when recalculating truncation.
🧹 Nitpick comments (2)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ChangesContent/utils/sortFiles.ts (1)
105-113: Handle"compact"explicitly insortFilesinstead of relying on fallback.Now that
FileListViewModeincludes"compact", the currenttree vs elsebranch makes compact behavior implicit. Please add an explicit"compact"branch (even if it currently aliases grouped sorting) so behavior stays intentional and future-safe.♻️ Suggested refactor
export function sortFiles( files: ChangedFile[], viewMode: FileListViewMode, ): ChangedFile[] { - return viewMode === "tree" - ? sortFilesTreeOrder(files) - : sortFilesGroupedOrder(files); + switch (viewMode) { + case "tree": + return sortFilesTreeOrder(files); + case "grouped": + return sortFilesGroupedOrder(files); + case "compact": + // Keep explicit even if behavior currently matches grouped. + return sortFilesGroupedOrder(files); + default: { + const exhaustiveCheck: never = viewMode; + return exhaustiveCheck; + } + } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/desktop/src/renderer/screens/main/components/WorkspaceView/ChangesContent/utils/sortFiles.ts` around lines 105 - 113, The sortFiles function currently uses a binary branch for viewMode which treats "compact" implicitly; update sortFiles to explicitly handle "compact" by adding a case for viewMode === "compact" (even if it simply returns sortFilesGroupedOrder(files)) so behavior is intentional and future-safe; modify the conditional in sortFiles to check viewMode === "tree", viewMode === "compact", and otherwise call sortFilesGroupedOrder(files), referencing the existing sortFilesTreeOrder and sortFilesGroupedOrder functions.apps/desktop/src/renderer/screens/main/components/WorkspaceView/components/CodeEditor/createBlamePlugin.ts (1)
30-36: Consider extracting locale to a shared constant or i18n configuration.The date formatter uses hardcoded
"ja-JP-u-hc-h24"locale. While consistent with the Japanese strings informatTimeAgo, centralizing locale configuration would ease future i18n changes.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/desktop/src/renderer/screens/main/components/WorkspaceView/components/CodeEditor/createBlamePlugin.ts` around lines 30 - 36, Extract the hardcoded locale string into a shared constant (e.g., BLAME_DATE_LOCALE or a value in the app i18n config) and use that constant when creating blameDateFormatter so locale changes are centralized; update the instantiation in createBlamePlugin (the blameDateFormatter declaration) to reference the shared locale constant and, if applicable, replace any other direct uses of "ja-JP-u-hc-h24" such as in formatTimeAgo to the same constant to ensure consistency across the codebase.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalSuggestion.ts`:
- Around line 67-77: The async fetchSuggestions race can repopulate
historySuggestions after dismiss/execute because those only enqueue state
updates; update dismiss and execute to immediately flip the open-guard ref
(isOpenRef.current = false) and/or increment a local request token before
triggering state updates so any outstanding fetchSuggestions checks (which
currently read isOpenRef.current) will bail out; ensure fetchSuggestions
verifies that token or isOpenRef.current right before calling
setHistorySuggestions and that dismiss clears fetchTimerRef and resets the token
to prevent late responses from resurrecting the panel (references: dismiss,
execute, fetchSuggestions, isOpenRef, fetchTimerRef, setHistorySuggestions,
lastPrefixRef).
- Around line 193-208: The accept() handler uses a stale prefix from
lastPrefixRef.current and skips on empty prompts; change it to read the live
input buffer (commandBufferRef.current) instead of lastPrefixRef.current, remove
the truthy check so acceptance works when the prompt is empty, compute suffix =
item.command.slice(currentInput.length) against that live prefix, call
onAcceptWriteRef.current(suffix) and update commandBufferRef.current and
lastPrefixRef.current to item.command as before, then clear suggestions with
setHistorySuggestions(EMPTY) and reset setSelectedIndex(0); keep references to
selectedIndexRef.current and historySuggestionsRef.current to locate the code.
---
Duplicate comments:
In
`@apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/TerminalSuggestion/TerminalSuggestion.tsx`:
- Around line 97-107: The effect that computes truncation for the selected item
(using itemTextRefs.current[selectedIndex] and calling setIsSelectedTruncated)
only lists selectedIndex as a dependency, so when the suggestion object at that
index changes the truncation state is not recomputed; update the dependency
array to include the suggestion value (e.g., suggestions or
suggestions[selectedIndex]) so the useEffect reruns when the selected command
changes, ensuring itemTextRefs, selectedIndex, suggestions, and
setIsSelectedTruncated are considered when recalculating truncation.
---
Nitpick comments:
In
`@apps/desktop/src/renderer/screens/main/components/WorkspaceView/ChangesContent/utils/sortFiles.ts`:
- Around line 105-113: The sortFiles function currently uses a binary branch for
viewMode which treats "compact" implicitly; update sortFiles to explicitly
handle "compact" by adding a case for viewMode === "compact" (even if it simply
returns sortFilesGroupedOrder(files)) so behavior is intentional and
future-safe; modify the conditional in sortFiles to check viewMode === "tree",
viewMode === "compact", and otherwise call sortFilesGroupedOrder(files),
referencing the existing sortFilesTreeOrder and sortFilesGroupedOrder functions.
In
`@apps/desktop/src/renderer/screens/main/components/WorkspaceView/components/CodeEditor/createBlamePlugin.ts`:
- Around line 30-36: Extract the hardcoded locale string into a shared constant
(e.g., BLAME_DATE_LOCALE or a value in the app i18n config) and use that
constant when creating blameDateFormatter so locale changes are centralized;
update the instantiation in createBlamePlugin (the blameDateFormatter
declaration) to reference the shared locale constant and, if applicable, replace
any other direct uses of "ja-JP-u-hc-h24" such as in formatTimeAgo to the same
constant to ensure consistency across the codebase.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 0a7ab418-8f5e-47e3-a3c9-14fc8c6ce789
📒 Files selected for processing (13)
apps/desktop/src/lib/trpc/routers/changes/file-contents.tsapps/desktop/src/lib/trpc/routers/changes/git-blame.tsapps/desktop/src/lib/trpc/routers/workspaces/utils/git-client.tsapps/desktop/src/renderer/screens/main/components/WorkspaceView/ChangesContent/utils/sortFiles.tsapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/CodeMirrorDiffViewer/CodeMirrorDiffViewer.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileViewerContent/FileViewerContent.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/TerminalSuggestion/TerminalSuggestion.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalSuggestion.tsapps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/FileList/index.tsapps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/ViewModeToggle/ViewModeToggle.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/components/CodeEditor/CodeEditor.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/components/CodeEditor/createBlamePlugin.ts
✅ Files skipped from review due to trivial changes (2)
- apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileViewerContent/FileViewerContent.tsx
- apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/FileList/index.ts
🚧 Files skipped from review as they are similar to previous changes (2)
- apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/CodeMirrorDiffViewer/CodeMirrorDiffViewer.tsx
- apps/desktop/src/lib/trpc/routers/changes/git-blame.ts
概要
Terminal の変更点
↑または↓を押した時だけ明示的に開くように変更Enterで実行、→は入力欄への補完のみ、EscとCtrl+Cでは panel を閉じるように変更テスト
Summary by CodeRabbit