mirror of
https://github.com/zed-industries/zed.git
synced 2024-09-20 02:47:34 +03:00
Improve lsp notifications (#10220)
1. They now will not go off-screen 2. You can scroll long messages. 3. Only one notification per language server is shown at a time 4. The title/text are now distinguished visually 5. You can copy the error message to the clipboard Fixes: #10217 Fixes: #10190 Fixes: #10090 Release Notes: - Fixed language server notifications being too large ([#10090](https://github.com/zed-industries/zed/issues/10090)).
This commit is contained in:
parent
3aa242e076
commit
0325bda89a
@ -1,13 +1,14 @@
|
|||||||
use crate::{Toast, Workspace};
|
use crate::{Toast, Workspace};
|
||||||
use collections::HashMap;
|
use collections::HashMap;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
svg, AnyView, AppContext, AsyncWindowContext, DismissEvent, Entity, EntityId, EventEmitter,
|
svg, AnyView, AppContext, AsyncWindowContext, ClipboardItem, DismissEvent, Entity, EntityId,
|
||||||
Global, PromptLevel, Render, Task, View, ViewContext, VisualContext, WindowContext,
|
EventEmitter, Global, PromptLevel, Render, ScrollHandle, Task, View, ViewContext,
|
||||||
|
VisualContext, WindowContext,
|
||||||
};
|
};
|
||||||
use language::DiagnosticSeverity;
|
use language::DiagnosticSeverity;
|
||||||
|
|
||||||
use std::{any::TypeId, ops::DerefMut};
|
use std::{any::TypeId, ops::DerefMut};
|
||||||
use ui::prelude::*;
|
use ui::{prelude::*, Tooltip};
|
||||||
use util::ResultExt;
|
use util::ResultExt;
|
||||||
|
|
||||||
pub fn init(cx: &mut AppContext) {
|
pub fn init(cx: &mut AppContext) {
|
||||||
@ -100,22 +101,16 @@ impl Workspace {
|
|||||||
build_notification: impl FnOnce(&mut ViewContext<Self>) -> View<V>,
|
build_notification: impl FnOnce(&mut ViewContext<Self>) -> View<V>,
|
||||||
) {
|
) {
|
||||||
let type_id = TypeId::of::<V>();
|
let type_id = TypeId::of::<V>();
|
||||||
if self
|
self.dismiss_notification_internal(type_id, id, cx);
|
||||||
.notifications
|
|
||||||
.iter()
|
let notification = build_notification(cx);
|
||||||
.all(|(existing_type_id, existing_id, _)| {
|
cx.subscribe(¬ification, move |this, _, _: &DismissEvent, cx| {
|
||||||
(*existing_type_id, *existing_id) != (type_id, id)
|
this.dismiss_notification_internal(type_id, id, cx);
|
||||||
})
|
})
|
||||||
{
|
.detach();
|
||||||
let notification = build_notification(cx);
|
self.notifications
|
||||||
cx.subscribe(¬ification, move |this, _, _: &DismissEvent, cx| {
|
.push((type_id, id, Box::new(notification)));
|
||||||
this.dismiss_notification_internal(type_id, id, cx);
|
cx.notify();
|
||||||
})
|
|
||||||
.detach();
|
|
||||||
self.notifications
|
|
||||||
.push((type_id, id, Box::new(notification)));
|
|
||||||
cx.notify();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn show_error<E>(&mut self, err: &E, cx: &mut ViewContext<Self>)
|
pub fn show_error<E>(&mut self, err: &E, cx: &mut ViewContext<Self>)
|
||||||
@ -174,12 +169,14 @@ impl Workspace {
|
|||||||
|
|
||||||
pub struct LanguageServerPrompt {
|
pub struct LanguageServerPrompt {
|
||||||
request: Option<project::LanguageServerPromptRequest>,
|
request: Option<project::LanguageServerPromptRequest>,
|
||||||
|
scroll_handle: ScrollHandle,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LanguageServerPrompt {
|
impl LanguageServerPrompt {
|
||||||
pub fn new(request: project::LanguageServerPromptRequest) -> Self {
|
pub fn new(request: project::LanguageServerPromptRequest) -> Self {
|
||||||
Self {
|
Self {
|
||||||
request: Some(request),
|
request: Some(request),
|
||||||
|
scroll_handle: ScrollHandle::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,45 +208,88 @@ impl Render for LanguageServerPrompt {
|
|||||||
|
|
||||||
h_flex()
|
h_flex()
|
||||||
.id("language_server_prompt_notification")
|
.id("language_server_prompt_notification")
|
||||||
|
.occlude()
|
||||||
.elevation_3(cx)
|
.elevation_3(cx)
|
||||||
.items_start()
|
.items_start()
|
||||||
.justify_between()
|
.justify_between()
|
||||||
.p_2()
|
.p_2()
|
||||||
.gap_2()
|
.gap_2()
|
||||||
.w_full()
|
.w_full()
|
||||||
|
.max_h(vh(0.8, cx))
|
||||||
|
.overflow_y_scroll()
|
||||||
|
.track_scroll(&self.scroll_handle)
|
||||||
|
.group("")
|
||||||
.child(
|
.child(
|
||||||
v_flex()
|
v_flex()
|
||||||
|
.w_full()
|
||||||
.overflow_hidden()
|
.overflow_hidden()
|
||||||
.child(
|
.child(
|
||||||
h_flex()
|
h_flex()
|
||||||
.children(
|
.w_full()
|
||||||
match request.level {
|
.justify_between()
|
||||||
PromptLevel::Info => None,
|
.child(
|
||||||
PromptLevel::Warning => Some(DiagnosticSeverity::WARNING),
|
h_flex()
|
||||||
PromptLevel::Critical => Some(DiagnosticSeverity::ERROR),
|
.flex_grow()
|
||||||
}
|
.children(
|
||||||
.map(|severity| {
|
match request.level {
|
||||||
svg()
|
PromptLevel::Info => None,
|
||||||
.size(cx.text_style().font_size)
|
PromptLevel::Warning => {
|
||||||
.flex_none()
|
Some(DiagnosticSeverity::WARNING)
|
||||||
.mr_1()
|
|
||||||
.map(|icon| {
|
|
||||||
if severity == DiagnosticSeverity::ERROR {
|
|
||||||
icon.path(IconName::ExclamationTriangle.path())
|
|
||||||
.text_color(Color::Error.color(cx))
|
|
||||||
} else {
|
|
||||||
icon.path(IconName::ExclamationTriangle.path())
|
|
||||||
.text_color(Color::Warning.color(cx))
|
|
||||||
}
|
}
|
||||||
})
|
PromptLevel::Critical => {
|
||||||
}),
|
Some(DiagnosticSeverity::ERROR)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.map(|severity| {
|
||||||
|
svg()
|
||||||
|
.size(cx.text_style().font_size)
|
||||||
|
.flex_none()
|
||||||
|
.mr_1()
|
||||||
|
.mt(px(-2.0))
|
||||||
|
.map(|icon| {
|
||||||
|
if severity == DiagnosticSeverity::ERROR {
|
||||||
|
icon.path(
|
||||||
|
IconName::ExclamationTriangle.path(),
|
||||||
|
)
|
||||||
|
.text_color(Color::Error.color(cx))
|
||||||
|
} else {
|
||||||
|
icon.path(
|
||||||
|
IconName::ExclamationTriangle.path(),
|
||||||
|
)
|
||||||
|
.text_color(Color::Warning.color(cx))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
Label::new(request.lsp_name.clone())
|
||||||
|
.size(LabelSize::Default),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
Label::new(format!("{}:", request.lsp_name))
|
ui::IconButton::new("close", ui::IconName::Close)
|
||||||
.size(LabelSize::Default),
|
.on_click(cx.listener(|_, _, cx| cx.emit(gpui::DismissEvent))),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.child(Label::new(request.message.to_string()))
|
.child(
|
||||||
|
v_flex()
|
||||||
|
.child(
|
||||||
|
h_flex().absolute().right_0().rounded_md().child(
|
||||||
|
ui::IconButton::new("copy", ui::IconName::Copy)
|
||||||
|
.on_click({
|
||||||
|
let message = request.message.clone();
|
||||||
|
move |_, cx| {
|
||||||
|
cx.write_to_clipboard(ClipboardItem::new(
|
||||||
|
message.clone(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.tooltip(|cx| Tooltip::text("Copy", cx))
|
||||||
|
.visible_on_hover(""),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.child(Label::new(request.message.to_string()).size(LabelSize::Small)),
|
||||||
|
)
|
||||||
.children(request.actions.iter().enumerate().map(|(ix, action)| {
|
.children(request.actions.iter().enumerate().map(|(ix, action)| {
|
||||||
let this_handle = cx.view().clone();
|
let this_handle = cx.view().clone();
|
||||||
ui::Button::new(ix, action.title.clone())
|
ui::Button::new(ix, action.title.clone())
|
||||||
@ -263,10 +303,6 @@ impl Render for LanguageServerPrompt {
|
|||||||
})
|
})
|
||||||
})),
|
})),
|
||||||
)
|
)
|
||||||
.child(
|
|
||||||
ui::IconButton::new("close", ui::IconName::Close)
|
|
||||||
.on_click(cx.listener(|_, _, cx| cx.emit(gpui::DismissEvent))),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -638,7 +638,7 @@ impl Workspace {
|
|||||||
|
|
||||||
project::Event::LanguageServerPrompt(request) => {
|
project::Event::LanguageServerPrompt(request) => {
|
||||||
let mut hasher = DefaultHasher::new();
|
let mut hasher = DefaultHasher::new();
|
||||||
request.message.as_str().hash(&mut hasher);
|
request.lsp_name.as_str().hash(&mut hasher);
|
||||||
let id = hasher.finish();
|
let id = hasher.finish();
|
||||||
|
|
||||||
this.show_notification(id as usize, cx, |cx| {
|
this.show_notification(id as usize, cx, |cx| {
|
||||||
|
Loading…
Reference in New Issue
Block a user