1
+ use std:: time:: Duration ;
2
+
1
3
use editor:: Editor ;
2
4
use gpui:: {
3
- EventEmitter , IntoElement , ParentElement , Render , Styled , Subscription , View , ViewContext ,
5
+ EventEmitter , IntoElement , ParentElement , Render , Styled , Subscription , Task , View , ViewContext ,
4
6
WeakView ,
5
7
} ;
6
8
use language:: Diagnostic ;
@@ -14,7 +16,9 @@ pub struct DiagnosticIndicator {
14
16
active_editor : Option < WeakView < Editor > > ,
15
17
workspace : WeakView < Workspace > ,
16
18
current_diagnostic : Option < Diagnostic > ,
19
+ pending_diagnostic : Option < Diagnostic > ,
17
20
_observe_active_editor : Option < Subscription > ,
21
+ _diagnostic_update_task : Option < Task < ( ) > > ,
18
22
}
19
23
20
24
impl Render for DiagnosticIndicator {
@@ -125,7 +129,9 @@ impl DiagnosticIndicator {
125
129
active_editor : None ,
126
130
workspace : workspace. weak_handle ( ) ,
127
131
current_diagnostic : None ,
132
+ pending_diagnostic : None ,
128
133
_observe_active_editor : None ,
134
+ _diagnostic_update_task : None ,
129
135
}
130
136
}
131
137
@@ -148,11 +154,45 @@ impl DiagnosticIndicator {
148
154
. filter ( |entry| !entry. range . is_empty ( ) )
149
155
. min_by_key ( |entry| ( entry. diagnostic . severity , entry. range . len ( ) ) )
150
156
. map ( |entry| entry. diagnostic ) ;
151
- if new_diagnostic != self . current_diagnostic {
157
+ if new_diagnostic == self . current_diagnostic {
158
+ return ;
159
+ }
160
+
161
+ // if we have a diagnostic, we should update the current diagnostic immediately
162
+ // otherwise we should debounce the update to avoid flashing
163
+ if new_diagnostic. is_some ( ) {
152
164
self . current_diagnostic = new_diagnostic;
165
+ self . _diagnostic_update_task = None ;
153
166
cx. notify ( ) ;
167
+ } else {
168
+ self . pending_diagnostic = new_diagnostic;
169
+ self . _debounced_diagnostic_update ( cx) ;
154
170
}
155
171
}
172
+
173
+ fn _debounced_diagnostic_update ( & mut self , cx : & mut ViewContext < Self > ) {
174
+ // do not schedule another task if one is already running
175
+ if self . _diagnostic_update_task . is_some ( ) {
176
+ return ;
177
+ }
178
+
179
+ self . _diagnostic_update_task = Some ( cx. spawn ( |this, mut cx| async move {
180
+ cx. background_executor ( )
181
+ . timer ( Duration :: from_millis ( 50 ) )
182
+ . await ;
183
+
184
+ this. update ( & mut cx, |this, cx| {
185
+ // check if the background update has been aborted
186
+ if this. _diagnostic_update_task . is_none ( ) {
187
+ return ;
188
+ }
189
+ this. _diagnostic_update_task = None ;
190
+ this. current_diagnostic = this. pending_diagnostic . clone ( ) ;
191
+ cx. notify ( ) ;
192
+ } )
193
+ . ok ( ) ;
194
+ } ) ) ;
195
+ }
156
196
}
157
197
158
198
impl EventEmitter < ToolbarItemEvent > for DiagnosticIndicator { }
0 commit comments