Skip to content

Commit 0747dc6

Browse files
committed
Fix status bar diagnostics flashing
1 parent 89a5696 commit 0747dc6

File tree

1 file changed

+42
-2
lines changed

1 file changed

+42
-2
lines changed

crates/diagnostics/src/items.rs

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
use std::time::Duration;
2+
13
use editor::Editor;
24
use gpui::{
3-
EventEmitter, IntoElement, ParentElement, Render, Styled, Subscription, View, ViewContext,
5+
EventEmitter, IntoElement, ParentElement, Render, Styled, Subscription, Task, View, ViewContext,
46
WeakView,
57
};
68
use 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

2024
impl 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

158198
impl EventEmitter<ToolbarItemEvent> for DiagnosticIndicator {}

0 commit comments

Comments
 (0)