Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit e4776e0

Browse files
Merge pull request #1 from utkuakyuz/feature/minimap-improvements
Feature/minimap improvements applied
2 parents 735018b + 9c1e60e commit e4776e0

File tree

4 files changed

+121
-32
lines changed

4 files changed

+121
-32
lines changed

‎src/components/DiffViewer/components/DiffMinimap.tsx‎

Lines changed: 89 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import React, { useRef, useEffect, useCallback, useMemo } from "react";
22
import { DiffMinimapProps, DiffRowOrCollapsed } from "../types";
33

4-
const MINIMAP_WIDTH = 100;
54
const ROW_HEIGHT = 20;
65
const SEARCH_HIGHLIGHT_COLOR = "#ffd700";
76
const CURRENT_MATCH_COLOR = "#ff4500";
@@ -10,11 +9,18 @@ const ADD_LINE_COLOR = "#4CAF50";
109
const REMOVE_LINE_COLOR = "#F44336";
1110
const MODIFY_LINE_COLOR = "#FFC107";
1211

12+
// const MINIMAP_HOVER_SCROLL_COLOR = "#2196f3cc";
13+
// const MINIMAP_SCROLL_COLOR = "#2196f380";
14+
15+
const MINIMAP_HOVER_SCROLL_COLOR = "#7B7B7Bcc";
16+
const MINIMAP_SCROLL_COLOR = "#7B7B7B80";
17+
1318
export const DiffMinimap: React.FC<DiffMinimapProps> = ({
1419
leftDiff,
1520
rightDiff,
1621
height,
1722
onScroll,
23+
miniMapWidth = 20,
1824
currentScrollTop,
1925
searchResults = [],
2026
currentMatchIndex = -1,
@@ -59,47 +65,60 @@ export const DiffMinimap: React.FC<DiffMinimapProps> = ({
5965
ctx.fillRect(x, y, width, ROW_HEIGHT);
6066
}, []);
6167

62-
const drawMinimap = useCallback(() => {
63-
const canvas = canvasRef.current;
64-
if (!canvas) return;
65-
66-
const ctx = canvas.getContext("2d");
67-
if (!ctx) return;
68-
69-
ctx.clearRect(0, 0, canvas.width, canvas.height);
70-
71-
const totalLines = Math.max(leftDiff.length, rightDiff.length);
68+
// Draw the differences -> This will be called in drawScrollBox method
69+
const drawDifferencesInMinimap = (ctx: CanvasRenderingContext2D) => {
7270
const scale = height / totalLines;
7371

72+
if (currentMatchIndex >= 0 && searchResults[currentMatchIndex] !== undefined) {
73+
const y = searchResults[currentMatchIndex] * scale;
74+
const lineHeight = Math.max(1, scale);
75+
ctx.fillStyle = CURRENT_MATCH_COLOR;
76+
ctx.fillRect(0, y, miniMapWidth, lineHeight);
77+
}
78+
7479
leftDiff.forEach((line, index) => {
7580
const y = index * scale;
76-
drawLine(ctx, line, y, 0, MINIMAP_WIDTH / 2);
81+
drawLine(ctx, line, y, 0, miniMapWidth / 2);
7782
});
7883

7984
rightDiff.forEach((line, index) => {
8085
const y = index * scale;
81-
drawLine(ctx, line, y, MINIMAP_WIDTH / 2, MINIMAP_WIDTH / 2);
86+
drawLine(ctx, line, y, miniMapWidth / 2, miniMapWidth / 2);
8287
});
8388

8489
searchResults.forEach((index) => {
8590
const y = index * scale;
8691
const lineHeight = Math.max(1, scale);
8792
ctx.fillStyle = SEARCH_HIGHLIGHT_COLOR;
88-
ctx.fillRect(0, y, MINIMAP_WIDTH, lineHeight);
93+
ctx.fillRect(0, y, miniMapWidth, lineHeight);
8994
});
95+
};
9096

91-
if (currentMatchIndex >= 0 && searchResults[currentMatchIndex] !== undefined) {
92-
const y = searchResults[currentMatchIndex] * scale;
93-
const lineHeight = Math.max(1, scale);
94-
ctx.fillStyle = CURRENT_MATCH_COLOR;
95-
ctx.fillRect(0, y, MINIMAP_WIDTH, lineHeight);
96-
}
97-
97+
// Draw the scroll box and also differences in minimapo
98+
const drawScrollBox = (ctx: CanvasRenderingContext2D, color: string) => {
9899
const totalContentHeight = totalLines * ROW_HEIGHT;
99100
const viewportTop = (currentScrollTop / totalContentHeight) * height;
100-
ctx.strokeStyle = "#2196F3";
101-
ctx.lineWidth = 2;
102-
ctx.strokeRect(0, viewportTop, MINIMAP_WIDTH, viewportHeight);
101+
102+
drawDifferencesInMinimap(ctx);
103+
104+
ctx.fillStyle = color;
105+
ctx.fillRect(0, viewportTop, miniMapWidth, viewportHeight);
106+
};
107+
108+
const drawMinimap = useCallback(() => {
109+
const canvas = canvasRef.current;
110+
if (!canvas) return;
111+
112+
const ctx = canvas.getContext("2d");
113+
if (!ctx) return;
114+
115+
ctx.clearRect(0, 0, canvas.width, canvas.height);
116+
117+
if (!isDragging.current) {
118+
drawScrollBox(ctx, MINIMAP_SCROLL_COLOR);
119+
} else {
120+
drawScrollBox(ctx, MINIMAP_HOVER_SCROLL_COLOR);
121+
}
103122
}, [leftDiff, rightDiff, height, currentScrollTop, searchResults, currentMatchIndex, drawLine, viewportHeight]);
104123

105124
useEffect(() => {
@@ -116,6 +135,13 @@ export const DiffMinimap: React.FC<DiffMinimapProps> = ({
116135

117136
if (height <= 0 || totalLines <= 0) return;
118137

138+
const canvas = canvasRef.current;
139+
if (!canvas) return;
140+
141+
const ctx = canvas.getContext("2d");
142+
if (!ctx) return;
143+
drawScrollBox(ctx, "rgba(33, 150, 243, 0.8)");
144+
119145
const viewportCenter = relativeY - viewportHeight / 2;
120146
const scrollTop = (viewportCenter / height) * totalLines * ROW_HEIGHT;
121147

@@ -128,15 +154,33 @@ export const DiffMinimap: React.FC<DiffMinimapProps> = ({
128154

129155
const handleMouseMove = useCallback(
130156
(e: React.MouseEvent) => {
131-
if (!isDragging.current || !containerRef.current) return;
132-
157+
if (!containerRef.current) return;
133158
const rect = containerRef.current.getBoundingClientRect();
134-
const relativeY = e.clientY - rect.top;
159+
const relativeY = e.clientY - rect.top; // e.client y - rect top (120)
160+
const viewportCenter = relativeY - viewportHeight / 2; // 0 when mouse is at the center of the drag square
161+
const scrollTop = (viewportCenter / height) * totalLines * ROW_HEIGHT;
135162

136-
if (height <= 0 || totalLines <= 0) return;
163+
const totalContentHeight = totalLines * ROW_HEIGHT;
164+
const scrollSquareTop = (currentScrollTop / totalContentHeight) * height;
137165

138-
const viewportCenter = relativeY - viewportHeight / 2;
139-
const scrollTop = (viewportCenter / height) * totalLines * ROW_HEIGHT;
166+
const isHovering = relativeY > scrollSquareTop && relativeY < scrollSquareTop + viewportHeight;
167+
168+
const canvas = canvasRef.current;
169+
170+
drawMinimap();
171+
172+
if (canvas) {
173+
const ctx = canvas.getContext("2d");
174+
if (!ctx) return;
175+
if (isHovering) {
176+
// This is active when box is hovered
177+
drawScrollBox(ctx, MINIMAP_HOVER_SCROLL_COLOR);
178+
}
179+
}
180+
181+
if (!isDragging.current) return;
182+
183+
if (height <= 0 || totalLines <= 0) return;
140184

141185
if (isNaN(scrollTop) || !isFinite(scrollTop)) return;
142186

@@ -160,6 +204,18 @@ export const DiffMinimap: React.FC<DiffMinimapProps> = ({
160204
isDragging.current = false;
161205
}, []);
162206

207+
const handleMouseLeave = () => {
208+
const canvas = canvasRef.current;
209+
if (!canvas) return;
210+
const ctx = canvas.getContext("2d");
211+
if (!ctx) return;
212+
213+
if (isDragging.current) {
214+
isDragging.current = false;
215+
}
216+
drawMinimap(); // resets full state
217+
};
218+
163219
useEffect(() => {
164220
window.addEventListener("mouseup", handleMouseUp);
165221
return () => window.removeEventListener("mouseup", handleMouseUp);
@@ -169,17 +225,18 @@ export const DiffMinimap: React.FC<DiffMinimapProps> = ({
169225
<div
170226
ref={containerRef}
171227
style={{
172-
width: MINIMAP_WIDTH,
228+
width: miniMapWidth,
173229
height,
174230
position: "relative",
175231
cursor: "pointer",
176232
}}
177233
onMouseDown={handleMouseDown}
178234
onMouseMove={handleMouseMove}
235+
onMouseLeave={handleMouseLeave}
179236
>
180237
<canvas
181238
ref={canvasRef}
182-
width={MINIMAP_WIDTH}
239+
width={miniMapWidth}
183240
height={height}
184241
style={{
185242
width: "100%",

‎src/components/DiffViewer/components/VirtualizedDiffViewer.tsx‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ export const VirtualizedDiffViewer: React.FC<VirtualizedDiffViewerProps> = ({
6969
onSearchMatch,
7070
differOptions,
7171
className,
72+
miniMapWidth,
7273
}) => {
7374
const listRef = useRef<List>(null);
7475
const searchTimeoutRef = useRef<NodeJS.Timeout>();
@@ -310,6 +311,7 @@ export const VirtualizedDiffViewer: React.FC<VirtualizedDiffViewerProps> = ({
310311
listRef.current?.scrollTo(scrollTop);
311312
}}
312313
currentScrollTop={scrollTop}
314+
miniMapWidth={miniMapWidth}
313315
searchResults={searchState.results}
314316
currentMatchIndex={searchState.currentIndex}
315317
/>

‎src/components/DiffViewer/styles/JsonDiffCustomTheme.css‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,34 @@
55
padding-bottom: 12px;
66
}
77

8+
.virtual-json-diff-list-container {
9+
--sb-track-color: #232E33;
10+
--sb-thumb-color: #4560f8;
11+
--sb-size: 6px;
12+
}
13+
14+
.virtual-json-diff-list-container::-webkit-scrollbar {
15+
width: var(--sb-size)
16+
}
17+
18+
.virtual-json-diff-list-container::-webkit-scrollbar-track {
19+
background: var(--sb-track-color);
20+
border-radius: 3px;
21+
}
22+
23+
.virtual-json-diff-list-container::-webkit-scrollbar-thumb {
24+
background: var(--sb-thumb-color);
25+
border-radius: 3px;
26+
27+
}
28+
29+
@supports not selector(::-webkit-scrollbar) {
30+
.virtual-json-diff-list-container {
31+
scrollbar-color: var(--sb-thumb-color)
32+
var(--sb-track-color);
33+
}
34+
}
35+
836

937
.diff-viewer-container {
1038
button {

‎src/components/DiffViewer/types/index.ts‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ export interface VirtualizedDiffViewerProps {
4343
onSearchMatch?: (index: number) => void;
4444
differOptions?: DifferOptions;
4545
className?: string;
46+
miniMapWidth?: number;
4647
}
4748

4849
export interface DiffMinimapProps {
@@ -53,4 +54,5 @@ export interface DiffMinimapProps {
5354
currentScrollTop: number;
5455
searchResults?: number[];
5556
currentMatchIndex?: number;
57+
miniMapWidth?: number;
5658
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /