Skip to content

feat(desktop): scroll to first diff when opening file in diff viewer#623

Merged
Kitenite merged 1 commit intomainfrom
changes-scrollto
Jan 6, 2026
Merged

feat(desktop): scroll to first diff when opening file in diff viewer#623
Kitenite merged 1 commit intomainfrom
changes-scrollto

Conversation

@Kitenite
Copy link
Copy Markdown
Collaborator

@Kitenite Kitenite commented Jan 6, 2026

Summary

  • Automatically scroll to the first diff location when opening a file in the diff viewer, improving UX so users don't have to manually scroll to find changes
  • Uses Monaco DiffEditor's onDidUpdateDiff callback to detect when diff computation completes, then scrolls to the first change using revealLineInCenter

Summary by CodeRabbit

  • New Features
    • Added a public filePath prop to the diff viewer to ensure scrolling behavior resets when switching files.
  • Bug Fixes
    • Diff viewer now automatically and reliably scrolls to the first difference once when a file is opened, with improved handling when navigating between files.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 6, 2026

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

Adds tracking and lifecycle-managed listener to the DiffViewer that detects when Monaco diff computation finishes and automatically scrolls the diff editor to the first changed line, resetting behavior when the viewed file changes.

Changes

Cohort / File(s) Summary
DiffViewer enhancement
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx
Adds filePath prop to DiffViewerProps; introduces diffEditorRef, hasScrolledToFirstDiffRef, and diffUpdateListenerRef; attaches onDidUpdateDiff listener to trigger a one-time scroll to the first diff line; disposes previous listeners on remount/unmount and resets scroll flag when filePath changes.

Sequence Diagram(s)

(omitted — changes are localized to the component and do not introduce a multi-component sequential flow that meets diagram criteria)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 I hop along the diffing trail,
Listeners twitch when changes sail,
I scroll to the first bright line,
Keep things tidy, neat, and fine,
A little cleanup makes code prevail.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main feature: auto-scrolling to first diff when opening files in the diff viewer.
Description check ✅ Passed The description provides a clear summary and implementation details, but lacks several required template sections like Related Issues, Type of Change, Testing, and Additional Notes.

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 83e16ec and b5dc454.

📒 Files selected for processing (1)
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx (1)

79-84: Clarify the comment about deletion handling.

The comment suggests using originalStartLineNumber for deletions, but modifiedStartLineNumber > 0 doesn't actually detect deletions—it will be > 0 even for pure deletions (pointing to where the deletion occurred). The fallback to originalStartLineNumber would only trigger if modifiedStartLineNumber is somehow 0, which is edge-case behavior.

The code works correctly, but the comment is misleading.

🔎 Suggested comment clarification
-					// Use modifiedStartLineNumber for scrolling in the modified editor
-					// If it's a deletion (modifiedStartLineNumber > modifiedEndLineNumber), use originalStartLineNumber
+					// Use modifiedStartLineNumber for scrolling in the modified editor
+					// Fallback to originalStartLineNumber if modifiedStartLineNumber is unavailable
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d4318dd and 83e16ec.

📒 Files selected for processing (1)
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx
🧰 Additional context used
📓 Path-based instructions (6)
apps/desktop/**/*.{ts,tsx}

📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)

apps/desktop/**/*.{ts,tsx}: For Electron interprocess communication, ALWAYS use tRPC as defined in src/lib/trpc
Use alias as defined in tsconfig.json when possible
Prefer zustand for state management if it makes sense. Do not use effect unless absolutely necessary.
For tRPC subscriptions with trpc-electron, ALWAYS use the observable pattern from @trpc/server/observable instead of async generators, as the library explicitly checks isObservable(result) and throws an error otherwise

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Use object parameters for functions with 2+ parameters instead of positional arguments
Functions with 2+ parameters should accept a single params object with named properties for self-documentation and extensibility
Use prefixed console logging with context pattern: [domain/operation] message
Extract magic numbers and hardcoded values to named constants at module top
Use lookup objects/maps instead of repeated if (type === ...) conditionals
Avoid using any type - maintain type safety in TypeScript code
Never swallow errors silently - at minimum log them with context
Import from concrete files directly when possible - avoid barrel file abuse that creates circular dependencies
Avoid deep nesting (4+ levels) - use early returns, extract functions, and invert conditions
Use named properties in options objects instead of boolean parameters to avoid boolean blindness

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx
apps/desktop/src/renderer/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Never import Node.js modules (fs, path, os, net) in renderer process or shared code - they are externalized for browser compatibility

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx
**/*.tsx

📄 CodeRabbit inference engine (AGENTS.md)

One component per file - do not create multi-component files

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx
apps/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use Drizzle ORM for all database operations - never use raw SQL

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use Biome for formatting and linting - run at root level with bun run lint:fix or biome check --write

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx
🧬 Code graph analysis (1)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx (1)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/editor-actions.ts (1)
  • registerCopyPathLineAction (4-29)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build
🔇 Additional comments (4)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx (4)

32-34: LGTM!

The diff editor ref is properly typed and initialized.


40-47: LGTM!

Good use of a ref for tracking scroll state without triggering re-renders. The biome-ignore is properly justified—resetting only on file change is the correct behavior.


56-57: LGTM!

Follows the established pattern for disposable listener refs in this file.


98-104: LGTM!

Proper unmount cleanup for the diff update listener. This pairs well with the cleanup-before-create pattern in handleMount to handle both re-mounts and final unmount scenarios.

@Kitenite Kitenite merged commit f17dfe5 into main Jan 6, 2026
4 of 5 checks passed
@Kitenite Kitenite deleted the changes-scrollto branch January 6, 2026 19:30
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jan 6, 2026

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

  • ⚠️ Neon database branch
  • ⚠️ Electric Fly.io app

Thank you for your contribution! 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant