6
6
import './media/chatEditorController.css' ;
7
7
import { addStandardDisposableListener , getTotalWidth } from '../../../../base/browser/dom.js' ;
8
8
import { Disposable , DisposableStore , dispose , toDisposable } from '../../../../base/common/lifecycle.js' ;
9
- import { autorun , autorunWithStore , derived , IObservable , observableFromEvent , observableValue } from '../../../../base/common/observable.js' ;
9
+ import { autorun , autorunWithStore , derived , IObservable , observableFromEvent , observableValue , transaction } from '../../../../base/common/observable.js' ;
10
10
import { themeColorFromId } from '../../../../base/common/themables.js' ;
11
11
import { ICodeEditor , IOverlayWidget , IOverlayWidgetPosition , IOverlayWidgetPositionCoordinates , IViewZone , MouseTargetType } from '../../../../editor/browser/editorBrowser.js' ;
12
12
import { LineSource , renderLines , RenderOptions } from '../../../../editor/browser/widget/diffEditor/components/diffEditorViewZones/renderLines.js' ;
@@ -55,8 +55,11 @@ export class ChatEditorController extends Disposable implements IEditorContribut
55
55
return controller ;
56
56
}
57
57
58
- private readonly _currentChange = observableValue < Position | undefined > ( this , undefined ) ;
59
- readonly currentChange : IObservable < Position | undefined > = this . _currentChange ;
58
+ private readonly _currentEntryIndex = observableValue < number | undefined > ( this , undefined ) ;
59
+ readonly currentEntryIndex : IObservable < number | undefined > = this . _currentEntryIndex ;
60
+
61
+ private readonly _currentChangeIndex = observableValue < number | undefined > ( this , undefined ) ;
62
+ readonly currentChangeIndex : IObservable < number | undefined > = this . _currentChangeIndex ;
60
63
61
64
private _scrollLock : boolean = false ;
62
65
@@ -76,20 +79,28 @@ export class ChatEditorController extends Disposable implements IEditorContribut
76
79
const lineHeightObs = observableCodeEditor ( this . _editor ) . getOption ( EditorOption . lineHeight ) ;
77
80
const modelObs = observableCodeEditor ( this . _editor ) . model ;
78
81
79
- // scroll along unless "another" scroll happens
80
- let ignoreScrollEvent = false ;
81
- this . _store . add ( this . _editor . onDidScrollChange ( e => {
82
- if ( e . scrollTopChanged && ! ignoreScrollEvent ) {
83
- // this._scrollLock = true;
84
- }
85
- } ) ) ;
86
82
87
83
this . _store . add ( autorun ( r => {
88
84
const session = this . _chatEditingService . currentEditingSessionObs . read ( r ) ;
89
85
this . _ctxRequestInProgress . set ( session ?. state . read ( r ) === ChatEditingSessionState . StreamingEdits ) ;
90
86
} ) ) ;
91
87
92
- let didReveal = false ;
88
+
89
+ const entryForEditor = derived ( r => {
90
+ const model = modelObs . read ( r ) ;
91
+ const session = this . _chatEditingService . currentEditingSessionObs . read ( r ) ;
92
+ if ( ! session ) {
93
+ return undefined ;
94
+ }
95
+ const entry = model ?. uri ? session . readEntry ( model . uri , r ) : undefined ;
96
+ if ( ! entry || entry . state . read ( r ) !== WorkingSetEntryState . Modified ) {
97
+ return undefined ;
98
+ }
99
+ return { session, entry } ;
100
+ } ) ;
101
+
102
+
103
+ let didReval = false ;
93
104
94
105
this . _register ( autorunWithStore ( ( r , store ) => {
95
106
@@ -98,55 +109,48 @@ export class ChatEditorController extends Disposable implements IEditorContribut
98
109
return ;
99
110
}
100
111
101
- fontInfoObs . read ( r ) ;
102
- lineHeightObs . read ( r ) ;
103
-
104
- const model = modelObs . read ( r ) ;
112
+ const currentEditorEntry = entryForEditor . read ( r ) ;
105
113
106
- const session = this . _chatEditingService . currentEditingSessionObs . read ( r ) ;
107
- const entry = model ?. uri ? session ?. readEntry ( model . uri , r ) : undefined ;
108
-
109
- if ( ! entry || entry . state . read ( r ) !== WorkingSetEntryState . Modified ) {
114
+ if ( ! currentEditorEntry ) {
110
115
this . _clearRendering ( ) ;
111
- didReveal = false ;
116
+ didReval = false ;
112
117
return ;
113
118
}
114
119
120
+ const { session, entry } = currentEditorEntry ;
121
+
122
+ const entryIndex = session . entries . read ( r ) . indexOf ( entry ) ;
123
+ this . _currentEntryIndex . set ( entryIndex , undefined ) ;
124
+
115
125
if ( entry . isCurrentlyBeingModified . read ( r ) ) {
126
+ // while modified: scroll along unless locked
127
+ if ( ! this . _scrollLock ) {
128
+ const maxLineNumber = entry . maxLineNumber . read ( r ) ;
129
+ this . _editor . revealLineNearTop ( maxLineNumber , ScrollType . Smooth ) ;
130
+ }
116
131
const domNode = this . _editor . getDomNode ( ) ;
117
132
if ( domNode ) {
118
133
store . add ( addStandardDisposableListener ( domNode , 'wheel' , ( ) => {
119
134
this . _scrollLock = true ;
120
135
} ) ) ;
121
136
}
122
- }
137
+ } else {
138
+ // done: render diff
139
+ fontInfoObs . read ( r ) ;
140
+ lineHeightObs . read ( r ) ;
123
141
124
- try {
125
- ignoreScrollEvent = true ;
126
- if ( ! this . _scrollLock && ! didReveal ) {
127
- const maxLineNumber = entry . maxLineNumber . read ( r ) ;
128
- this . _editor . revealLineNearTop ( maxLineNumber , ScrollType . Smooth ) ;
129
- }
130
142
const diff = entry ?. diffInfo . read ( r ) ;
131
143
this . _updateWithDiff ( entry , diff ) ;
132
- if ( ! entry . isCurrentlyBeingModified . read ( r ) ) {
133
- this . initNavigation ( ) ;
134
-
135
- if ( ! this . _scrollLock && ! didReveal ) {
136
- const currentPosition = this . _currentChange . read ( r ) ;
137
- if ( currentPosition ) {
138
- this . _editor . revealLine ( currentPosition . lineNumber , ScrollType . Smooth ) ;
139
- didReveal = true ;
140
- } else {
141
- didReveal = this . revealNext ( ) ;
142
- }
143
- }
144
+
145
+ if ( ! didReval && ! diff . identical ) {
146
+ didReval = true ;
147
+ this . revealNext ( ) ;
144
148
}
145
- } finally {
146
- ignoreScrollEvent = false ;
147
149
}
148
150
} ) ) ;
149
151
152
+ // ---- readonly while streaming
153
+
150
154
const shouldBeReadOnly = derived ( this , r => {
151
155
const value = this . _chatEditingService . currentEditingSessionObs . read ( r ) ;
152
156
if ( ! value || value . state . read ( r ) !== ChatEditingSessionState . StreamingEdits ) {
@@ -200,7 +204,10 @@ export class ChatEditorController extends Disposable implements IEditorContribut
200
204
this . _diffVisualDecorations . clear ( ) ;
201
205
this . _diffLineDecorations . clear ( ) ;
202
206
this . _ctxHasEditorModification . reset ( ) ;
203
- this . _currentChange . set ( undefined , undefined ) ;
207
+ transaction ( tx => {
208
+ this . _currentEntryIndex . set ( undefined , tx ) ;
209
+ this . _currentChangeIndex . set ( undefined , tx ) ;
210
+ } ) ;
204
211
this . _scrollLock = false ;
205
212
}
206
213
@@ -423,10 +430,8 @@ export class ChatEditorController extends Disposable implements IEditorContribut
423
430
424
431
initNavigation ( ) : void {
425
432
const position = this . _editor . getPosition ( ) ;
426
- const range = position && this . _diffLineDecorations . getRanges ( ) . find ( r => r . containsPosition ( position ) ) ;
427
- if ( range ) {
428
- this . _currentChange . set ( position , undefined ) ;
429
- }
433
+ const target = position ? this . _diffLineDecorations . getRanges ( ) . findIndex ( r => r . containsPosition ( position ) ) : - 1 ;
434
+ this . _currentChangeIndex . set ( target >= 0 ? target : undefined , undefined ) ;
430
435
}
431
436
432
437
revealNext ( strict = false ) : boolean {
@@ -440,6 +445,7 @@ export class ChatEditorController extends Disposable implements IEditorContribut
440
445
private _reveal ( next : boolean , strict : boolean ) : boolean {
441
446
const position = this . _editor . getPosition ( ) ;
442
447
if ( ! position ) {
448
+ this . _currentChangeIndex . set ( undefined , undefined ) ;
443
449
return false ;
444
450
}
445
451
@@ -448,6 +454,7 @@ export class ChatEditorController extends Disposable implements IEditorContribut
448
454
. sort ( ( a , b ) => Range . compareRangesUsingStarts ( a , b ) ) ;
449
455
450
456
if ( decorations . length === 0 ) {
457
+ this . _currentChangeIndex . set ( undefined , undefined ) ;
451
458
return false ;
452
459
}
453
460
@@ -464,18 +471,19 @@ export class ChatEditorController extends Disposable implements IEditorContribut
464
471
}
465
472
466
473
if ( strict && ( target < 0 || target >= decorations . length ) ) {
474
+ this . _currentChangeIndex . set ( undefined , undefined ) ;
467
475
return false ;
468
476
}
469
477
470
478
target = ( target + decorations . length ) % decorations . length ;
471
479
472
- const targetPosition = next ? decorations [ target ] . getStartPosition ( ) : decorations [ target ] . getEndPosition ( ) ;
473
-
474
- this . _currentChange . set ( targetPosition , undefined ) ;
480
+ this . _currentChangeIndex . set ( target , undefined ) ;
475
481
482
+ const targetPosition = next ? decorations [ target ] . getStartPosition ( ) : decorations [ target ] . getEndPosition ( ) ;
476
483
this . _editor . setPosition ( targetPosition ) ;
477
484
this . _editor . revealPositionInCenter ( targetPosition , ScrollType . Smooth ) ;
478
485
this . _editor . focus ( ) ;
486
+
479
487
return true ;
480
488
}
481
489
0 commit comments