1+ use  std:: time:: Duration ; 
2+ 
13use  editor:: Editor ; 
24use  gpui:: { 
3-     EventEmitter ,  IntoElement ,  ParentElement ,  Render ,  Styled ,  Subscription ,  View ,  ViewContext , 
5+     EventEmitter ,  IntoElement ,  ParentElement ,  Render ,  Styled ,  Subscription ,  Task ,   View ,  ViewContext , 
46    WeakView , 
57} ; 
68use  language:: Diagnostic ; 
@@ -14,7 +16,9 @@ pub struct DiagnosticIndicator {
1416    active_editor :  Option < WeakView < Editor > > , 
1517    workspace :  WeakView < Workspace > , 
1618    current_diagnostic :  Option < Diagnostic > , 
19+     pending_diagnostic :  Option < Diagnostic > , 
1720    _observe_active_editor :  Option < Subscription > , 
21+     _diagnostic_update_task :  Option < Task < ( ) > > , 
1822} 
1923
2024impl  Render  for  DiagnosticIndicator  { 
@@ -125,7 +129,9 @@ impl DiagnosticIndicator {
125129            active_editor :  None , 
126130            workspace :  workspace. weak_handle ( ) , 
127131            current_diagnostic :  None , 
132+             pending_diagnostic :  None , 
128133            _observe_active_editor :  None , 
134+             _diagnostic_update_task :  None , 
129135        } 
130136    } 
131137
@@ -148,11 +154,45 @@ impl DiagnosticIndicator {
148154            . filter ( |entry| !entry. range . is_empty ( ) ) 
149155            . min_by_key ( |entry| ( entry. diagnostic . severity ,  entry. range . len ( ) ) ) 
150156            . 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 ( )  { 
152164            self . current_diagnostic  = new_diagnostic; 
165+             self . _diagnostic_update_task  = None ; 
153166            cx. notify ( ) ; 
167+         }  else  { 
168+             self . pending_diagnostic  = new_diagnostic; 
169+             self . _debounced_diagnostic_update ( cx) ; 
154170        } 
155171    } 
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+     } 
156196} 
157197
158198impl  EventEmitter < ToolbarItemEvent >  for  DiagnosticIndicator  { } 
0 commit comments