Skip to content

Commit b975405

Browse files
authored
Diff Editor v2: Iterates on collapsed unchanged code feature. (microsoft#185499)
1 parent b5bcc09 commit b975405

File tree

10 files changed

+423
-253
lines changed

10 files changed

+423
-253
lines changed

build/lib/stylelint/vscode-known-variables.json

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@
101101
"--vscode-diffEditor-removedTextBackground",
102102
"--vscode-diffEditor-removedTextBorder",
103103
"--vscode-diffEditor-unchangedRegionBackground",
104+
"--vscode-diffEditor-unchangedRegionForeground",
104105
"--vscode-diffEditorGutter-insertedLineBackground",
105106
"--vscode-diffEditorGutter-removedLineBackground",
106107
"--vscode-diffEditorOverview-insertedForeground",
@@ -295,6 +296,16 @@
295296
"--vscode-focusBorder",
296297
"--vscode-foreground",
297298
"--vscode-icon-foreground",
299+
"--vscode-inlineChat-background",
300+
"--vscode-inlineChat-border",
301+
"--vscode-inlineChat-regionHighlight",
302+
"--vscode-inlineChat-shadow",
303+
"--vscode-inlineChatDiff-inserted",
304+
"--vscode-inlineChatInput-background",
305+
"--vscode-inlineChatInput-border",
306+
"--vscode-inlineChatInput-focusBorder",
307+
"--vscode-inlineChatInput-placeholderForeground",
308+
"--vscode-inlineChatrDiff-removed",
298309
"--vscode-input-background",
299310
"--vscode-input-border",
300311
"--vscode-input-foreground",
@@ -312,16 +323,6 @@
312323
"--vscode-inputValidation-warningBackground",
313324
"--vscode-inputValidation-warningBorder",
314325
"--vscode-inputValidation-warningForeground",
315-
"--vscode-inlineChat-background",
316-
"--vscode-inlineChat-border",
317-
"--vscode-inlineChat-regionHighlight",
318-
"--vscode-inlineChat-shadow",
319-
"--vscode-inlineChatDiff-inserted",
320-
"--vscode-inlineChatDiff-removed",
321-
"--vscode-inlineChatInput-background",
322-
"--vscode-inlineChatInput-border",
323-
"--vscode-inlineChatInput-focusBorder",
324-
"--vscode-inlineChatInput-placeholderForeground",
325326
"--vscode-keybindingLabel-background",
326327
"--vscode-keybindingLabel-border",
327328
"--vscode-keybindingLabel-bottomBorder",
@@ -745,4 +746,4 @@
745746
"--z-index-run-button-container",
746747
"--zoom-factor"
747748
]
748-
}
749+
}

src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import { ViewZoneManager } from 'vs/editor/browser/widget/diffEditorWidget2/line
2525
import { MovedBlocksLinesPart } from 'vs/editor/browser/widget/diffEditorWidget2/movedBlocksLines';
2626
import { OverviewRulerPart } from 'vs/editor/browser/widget/diffEditorWidget2/overviewRulerPart';
2727
import { UnchangedRangesFeature } from 'vs/editor/browser/widget/diffEditorWidget2/unchangedRanges';
28-
import { ObservableElementSizeObserver, applyObservableDecorations, deepMerge } from 'vs/editor/browser/widget/diffEditorWidget2/utils';
28+
import { ObservableElementSizeObserver, applyObservableDecorations, deepMerge, readHotReloadableExport } from 'vs/editor/browser/widget/diffEditorWidget2/utils';
2929
import { WorkerBasedDocumentDiffProvider } from 'vs/editor/browser/widget/workerBasedDocumentDiffProvider';
3030
import { EditorOptions, IDiffEditorOptions, IEditorOptions, ValidDiffEditorBaseOptions, clampedFloat, clampedInt, boolean as validateBooleanOption, stringSet as validateStringSetOption } from 'vs/editor/common/config/editorOptions';
3131
import { IDimension } from 'vs/editor/common/core/dimension';
@@ -43,6 +43,7 @@ import { DiffMapping, DiffModel } from './diffModel';
4343
import { Range } from 'vs/editor/common/core/range';
4444
import { LineRangeMapping } from 'vs/editor/common/diff/linesDiffComputer';
4545
import { deepClone } from 'vs/base/common/objects';
46+
import { autorunWithStore2 } from 'vs/base/common/observableImpl/autorun';
4647

4748
const diffEditorDefaultOptions: ValidDiffEditorBaseOptions = {
4849
enableSplitViewResizing: true,
@@ -88,6 +89,8 @@ export class DiffEditorWidget2 extends DelegatingEditor implements IDiffEditor {
8889
private readonly _boundarySashes = observableValue<IBoundarySashes | undefined>('boundarySashes', undefined);
8990
private readonly _renderOverviewRuler: IObservable<boolean>;
9091

92+
private unchangedRangesFeature!: UnchangedRangesFeature;
93+
9194
constructor(
9295
private readonly _domElement: HTMLElement,
9396
options: Readonly<IDiffEditorConstructionOptions>,
@@ -146,18 +149,20 @@ export class DiffEditorWidget2 extends DelegatingEditor implements IDiffEditor {
146149
});
147150
this._register(keepAlive(this._sash, true));
148151

149-
this._register(new UnchangedRangesFeature(
150-
this._originalEditor,
151-
this._modifiedEditor,
152-
this._diffModel
153-
));
152+
this._register(autorunWithStore2('unchangedRangesFeature', (reader, store) => {
153+
this.unchangedRangesFeature = store.add(new (readHotReloadableExport(UnchangedRangesFeature, reader))(
154+
this._originalEditor, this._modifiedEditor, this._diffModel, this._options.map(o => o.renderSideBySide)
155+
));
156+
}));
157+
154158
this._register(this._instantiationService.createInstance(
155159
ViewZoneManager,
156160
this._originalEditor,
157161
this._modifiedEditor,
158162
this._diffModel,
159163
this._options.map((o) => o.renderSideBySide),
160164
this,
165+
() => this.unchangedRangesFeature.isUpdatingViewZones,
161166
));
162167

163168
this._register(this._instantiationService.createInstance(OverviewRulerPart,

src/vs/editor/browser/widget/diffEditorWidget2/diffModel.ts

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import { RunOnceScheduler } from 'vs/base/common/async';
77
import { Disposable } from 'vs/base/common/lifecycle';
8-
import { IObservable, IReader, ITransaction, derived, observableSignal, observableSignalFromEvent, observableValue, transaction, waitForState } from 'vs/base/common/observable';
8+
import { IObservable, IReader, ISettableObservable, ITransaction, derived, observableSignal, observableSignalFromEvent, observableValue, transaction, waitForState } from 'vs/base/common/observable';
99
import { autorunWithStore2 } from 'vs/base/common/observableImpl/autorun';
1010
import { isDefined } from 'vs/base/common/types';
1111
import { LineRange } from 'vs/editor/common/core/lineRange';
@@ -279,10 +279,14 @@ export class UnchangedRegion {
279279
}
280280

281281
private readonly _visibleLineCountTop = observableValue<number>('visibleLineCountTop', 0);
282-
public readonly visibleLineCountTop: IObservable<number> = this._visibleLineCountTop;
282+
public readonly visibleLineCountTop: ISettableObservable<number> = this._visibleLineCountTop;
283283

284284
private readonly _visibleLineCountBottom = observableValue<number>('visibleLineCountBottom', 0);
285-
public readonly visibleLineCountBottom: IObservable<number> = this._visibleLineCountBottom;
285+
public readonly visibleLineCountBottom: ISettableObservable<number> = this._visibleLineCountBottom;
286+
287+
private readonly _shouldHideControls = derived('isVisible', reader => this.visibleLineCountTop.read(reader) + this.visibleLineCountBottom.read(reader) === this.lineCount && !this.isDragged.read(reader));
288+
289+
public readonly isDragged = observableValue<boolean>('isDragged', false);
286290

287291
constructor(
288292
public readonly originalLineNumber: number,
@@ -295,6 +299,10 @@ export class UnchangedRegion {
295299
this._visibleLineCountBottom.set(visibleLineCountBottom, undefined);
296300
}
297301

302+
public shouldHideControls(reader: IReader | undefined): boolean {
303+
return this._shouldHideControls.read(reader);
304+
}
305+
298306
public getHiddenOriginalRange(reader: IReader | undefined): LineRange {
299307
return LineRange.ofLength(
300308
this.originalLineNumber + this._visibleLineCountTop.read(reader),
@@ -309,14 +317,22 @@ export class UnchangedRegion {
309317
);
310318
}
311319

312-
public showMoreAbove(tx: ITransaction | undefined): void {
313-
const maxVisibleLineCountTop = this.lineCount - this._visibleLineCountBottom.get();
314-
this._visibleLineCountTop.set(Math.min(this._visibleLineCountTop.get() + 10, maxVisibleLineCountTop), tx);
320+
public getMaxVisibleLineCountTop() {
321+
return this.lineCount - this._visibleLineCountBottom.get();
322+
}
323+
324+
public getMaxVisibleLineCountBottom() {
325+
return this.lineCount - this._visibleLineCountTop.get();
326+
}
327+
328+
public showMoreAbove(count = 10, tx: ITransaction | undefined): void {
329+
const maxVisibleLineCountTop = this.getMaxVisibleLineCountTop();
330+
this._visibleLineCountTop.set(Math.min(this._visibleLineCountTop.get() + count, maxVisibleLineCountTop), tx);
315331
}
316332

317-
public showMoreBelow(tx: ITransaction | undefined): void {
333+
public showMoreBelow(count = 10, tx: ITransaction | undefined): void {
318334
const maxVisibleLineCountBottom = this.lineCount - this._visibleLineCountTop.get();
319-
this._visibleLineCountBottom.set(Math.min(this._visibleLineCountBottom.get() + 10, maxVisibleLineCountBottom), tx);
335+
this._visibleLineCountBottom.set(Math.min(this._visibleLineCountBottom.get() + count, maxVisibleLineCountBottom), tx);
320336
}
321337

322338
public showAll(tx: ITransaction | undefined): void {

src/vs/editor/browser/widget/diffEditorWidget2/lineAlignment.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ export class ViewZoneManager extends Disposable {
5353
private readonly _diffModel: IObservable<DiffModel | undefined>,
5454
private readonly _renderSideBySide: IObservable<boolean>,
5555
private readonly _diffEditorWidget: DiffEditorWidget2,
56+
private readonly _canIgnoreViewZoneUpdateEvent: () => boolean,
5657
@IClipboardService private readonly _clipboardService: IClipboardService,
5758
@IContextMenuService private readonly _contextMenuService: IContextMenuService,
5859
) {
@@ -62,11 +63,11 @@ export class ViewZoneManager extends Disposable {
6263

6364
const originalViewZonesChanged = observableSignalFromEvent(
6465
'origViewZonesChanged',
65-
e => this._originalEditor.onDidChangeViewZones((args) => { if (!isChangingViewZones) { e(args); } })
66+
e => this._originalEditor.onDidChangeViewZones((args) => { if (!isChangingViewZones && !this._canIgnoreViewZoneUpdateEvent()) { e(args); } })
6667
);
6768
const modifiedViewZonesChanged = observableSignalFromEvent(
6869
'modViewZonesChanged',
69-
e => this._modifiedEditor.onDidChangeViewZones((args) => { if (!isChangingViewZones) { e(args); } })
70+
e => this._modifiedEditor.onDidChangeViewZones((args) => { if (!isChangingViewZones && !this._canIgnoreViewZoneUpdateEvent()) { e(args); } })
7071
);
7172

7273
const originalModelTokenizationCompleted = this._diffModel.map(m =>
@@ -116,6 +117,7 @@ export class ViewZoneManager extends Disposable {
116117
afterLineNumber: 0,
117118
domNode: document.createElement('div'),
118119
heightInPx: modifiedTopPaddingVal,
120+
showInHiddenAreas: true,
119121
});
120122
}
121123
const originalTopPaddingVal = this._originalTopPadding.read(reader);
@@ -124,6 +126,7 @@ export class ViewZoneManager extends Disposable {
124126
afterLineNumber: 0,
125127
domNode: document.createElement('div'),
126128
heightInPx: originalTopPaddingVal,
129+
showInHiddenAreas: true,
127130
});
128131
}
129132

@@ -232,6 +235,7 @@ export class ViewZoneManager extends Disposable {
232235
domNode: createFakeLinesDiv(),
233236
heightInPx: a.modifiedHeightInPx,
234237
marginDomNode,
238+
showInHiddenAreas: true,
235239
});
236240
} else {
237241
const delta = a.modifiedHeightInPx - a.originalHeightInPx;
@@ -244,6 +248,7 @@ export class ViewZoneManager extends Disposable {
244248
afterLineNumber: a.originalRange.endLineNumberExclusive - 1,
245249
domNode: createFakeLinesDiv(),
246250
heightInPx: delta,
251+
showInHiddenAreas: true,
247252
});
248253
} else {
249254
if (syncedMovedText?.lineRangeMapping.modifiedRange.contains(a.modifiedRange.endLineNumberExclusive - 1)) {
@@ -266,6 +271,7 @@ export class ViewZoneManager extends Disposable {
266271
domNode: createFakeLinesDiv(),
267272
heightInPx: -delta,
268273
marginDomNode,
274+
showInHiddenAreas: true,
269275
});
270276
}
271277
}
@@ -329,6 +335,9 @@ export class ViewZoneManager extends Disposable {
329335
scrollState.restore(this._modifiedEditor);
330336
}));
331337

338+
this._register(this._originalEditor.onDidScrollChange(e => { this._modifiedEditor.setScrollLeft(e.scrollLeft); }));
339+
this._register(this._modifiedEditor.onDidScrollChange(e => { this._originalEditor.setScrollLeft(e.scrollLeft); }));
340+
332341
this._originalScrollTop = observableFromEvent(this._originalEditor.onDidScrollChange, () => this._originalEditor.getScrollTop());
333342
this._modifiedScrollTop = observableFromEvent(this._modifiedEditor.onDidScrollChange, () => this._modifiedEditor.getScrollTop());
334343

src/vs/editor/browser/widget/diffEditorWidget2/patternBottom.svg

Lines changed: 0 additions & 5 deletions
This file was deleted.

src/vs/editor/browser/widget/diffEditorWidget2/patternTop.svg

Lines changed: 0 additions & 5 deletions
This file was deleted.

src/vs/editor/browser/widget/diffEditorWidget2/style.css

Lines changed: 32 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,63 +3,57 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
.diff-hidden-lines.showTop {
7-
margin: -5px 0;
6+
.diff-hidden-lines-widget {
7+
width: 100%;
88
}
99

10-
.diff-hidden-lines.showTop .top {
11-
height: 7px;
12-
background-color: var(--vscode-diffEditor-unchangedRegionBackground);
13-
mask: url("./patternTop.svg") repeat 0px 0px;
14-
-webkit-mask: url("./patternTop.svg") repeat 0px 0px;
10+
.diff-hidden-lines {
11+
transform: translate(0px, -8px);
12+
font-size: 13px;
13+
line-height: 14px;
1514
}
1615

17-
.diff-hidden-lines.showBottom .bottom {
18-
height: 7px;
19-
background-color: var(--vscode-diffEditor-unchangedRegionBackground);
20-
mask: url("./patternBottom.svg") repeat 10px 0px;
21-
-webkit-mask: url("./patternBottom.svg") repeat 10px 0px;
16+
.diff-hidden-lines:not(.dragging) .top:hover, .diff-hidden-lines:not(.dragging) .bottom:hover, .diff-hidden-lines .top.dragging, .diff-hidden-lines .bottom.dragging {
17+
background-color: var(--vscode-focusBorder);
2218
}
2319

24-
.diff-hidden-lines .center {
25-
background: var(--vscode-diffEditor-unchangedRegionBackground);
26-
padding: 0px 3px;
27-
overflow: hidden;
28-
display: block;
29-
text-overflow: ellipsis;
30-
white-space: nowrap;
31-
32-
height: 20px;
20+
.diff-hidden-lines .top, .diff-hidden-lines .bottom {
21+
transition: background-color 0.1s ease-out;
22+
height: 4px;
23+
background-color: transparent;
24+
background-clip: padding-box;
25+
border-bottom: 2px solid transparent;
26+
border-top: 4px solid transparent;
27+
cursor: pointer;
3328
}
3429

35-
.diff-hidden-lines .center > span,
36-
.diff-hidden-lines .center > a {
37-
user-select: none;
38-
-webkit-user-select: none;
39-
white-space: nowrap;
30+
.diff-hidden-lines .top {
31+
transform: translate(0px, 4px);
4032
}
4133

42-
.diff-hidden-lines .center > a {
43-
text-decoration: none;
34+
.diff-hidden-lines .bottom {
35+
transform: translate(0px, -6px);
4436
}
4537

46-
.diff-hidden-lines .center > a:hover {
47-
cursor: pointer;
48-
color: var(--vscode-editorLink-activeForeground) !important;
49-
}
5038

51-
.diff-hidden-lines .center > a:hover .codicon {
52-
color: var(--vscode-editorLink-activeForeground) !important;
39+
.diff-hidden-lines .center {
40+
background: var(--vscode-diffEditor-unchangedRegionBackground);
41+
color: var(--vscode-diffEditor-unchangedRegionForeground);
42+
overflow: hidden;
43+
display: block;
44+
text-overflow: ellipsis;
45+
white-space: nowrap;
46+
47+
height: 24px;
5348
}
5449

55-
.diff-hidden-lines .center .codicon {
50+
.diff-hidden-lines .center span.codicon {
5651
vertical-align: middle;
57-
color: currentColor !important;
58-
color: var(--vscode-editorCodeLens-foreground);
5952
}
6053

61-
.merge-editor-conflict-actions > a:hover .codicon::before {
54+
.diff-hidden-lines .center a:hover .codicon {
6255
cursor: pointer;
56+
color: var(--vscode-editorLink-activeForeground) !important;
6357
}
6458

6559
.movedOriginal {

0 commit comments

Comments
 (0)