Debounce diagnostics status bar updates (#21463)

Kirill Bulatov created

Closes https://github.com/zed-industries/zed/pull/20797

Release Notes:

- Fixed diagnostics status bar flashing when typing

Change summary

crates/diagnostics/src/items.rs | 21 +++++++++++++++++----
1 file changed, 17 insertions(+), 4 deletions(-)

Detailed changes

crates/diagnostics/src/items.rs 🔗

@@ -1,7 +1,9 @@
+use std::time::Duration;
+
 use editor::Editor;
 use gpui::{
-    EventEmitter, IntoElement, ParentElement, Render, Styled, Subscription, View, ViewContext,
-    WeakView,
+    EventEmitter, IntoElement, ParentElement, Render, Styled, Subscription, Task, View,
+    ViewContext, WeakView,
 };
 use language::Diagnostic;
 use ui::{h_flex, prelude::*, Button, ButtonLike, Color, Icon, IconName, Label, Tooltip};
@@ -15,6 +17,7 @@ pub struct DiagnosticIndicator {
     workspace: WeakView<Workspace>,
     current_diagnostic: Option<Diagnostic>,
     _observe_active_editor: Option<Subscription>,
+    diagnostics_update: Task<()>,
 }
 
 impl Render for DiagnosticIndicator {
@@ -126,6 +129,7 @@ impl DiagnosticIndicator {
             workspace: workspace.weak_handle(),
             current_diagnostic: None,
             _observe_active_editor: None,
+            diagnostics_update: Task::ready(()),
         }
     }
 
@@ -149,8 +153,17 @@ impl DiagnosticIndicator {
             .min_by_key(|entry| (entry.diagnostic.severity, entry.range.len()))
             .map(|entry| entry.diagnostic);
         if new_diagnostic != self.current_diagnostic {
-            self.current_diagnostic = new_diagnostic;
-            cx.notify();
+            self.diagnostics_update = cx.spawn(|diagnostics_indicator, mut cx| async move {
+                cx.background_executor()
+                    .timer(Duration::from_millis(50))
+                    .await;
+                diagnostics_indicator
+                    .update(&mut cx, |diagnostics_indicator, cx| {
+                        diagnostics_indicator.current_diagnostic = new_diagnostic;
+                        cx.notify();
+                    })
+                    .ok();
+            });
         }
     }
 }