mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-24 17:28:40 +00:00
Highlight mentions in the Saved chat messages
This commit is contained in:
parent
44cb55fbe9
commit
6844bb6510
4 changed files with 82 additions and 27 deletions
|
@ -366,13 +366,26 @@ impl ChatPanel {
|
||||||
};
|
};
|
||||||
|
|
||||||
let is_pending = message.is_pending();
|
let is_pending = message.is_pending();
|
||||||
let text = self
|
let theme = theme::current(cx);
|
||||||
.markdown_data
|
let text = self.markdown_data.entry(message.id).or_insert_with(|| {
|
||||||
.entry(message.id)
|
let mut markdown =
|
||||||
.or_insert_with(|| rich_text::render_markdown(message.body, &self.languages, None));
|
rich_text::render_markdown(message.body.clone(), &self.languages, None);
|
||||||
|
let self_client_id = self.client.id();
|
||||||
|
for (mention_range, user_id) in message.mentions {
|
||||||
|
let is_current_user = self_client_id == user_id;
|
||||||
|
markdown
|
||||||
|
.add_mention(
|
||||||
|
mention_range,
|
||||||
|
is_current_user,
|
||||||
|
theme.chat_panel.mention_highlight.clone(),
|
||||||
|
)
|
||||||
|
.log_err();
|
||||||
|
}
|
||||||
|
markdown
|
||||||
|
});
|
||||||
|
|
||||||
let now = OffsetDateTime::now_utc();
|
let now = OffsetDateTime::now_utc();
|
||||||
let theme = theme::current(cx);
|
|
||||||
let style = if is_pending {
|
let style = if is_pending {
|
||||||
&theme.chat_panel.pending_message
|
&theme.chat_panel.pending_message
|
||||||
} else if is_continuation {
|
} else if is_continuation {
|
||||||
|
@ -400,6 +413,7 @@ impl ChatPanel {
|
||||||
theme.editor.syntax.clone(),
|
theme.editor.syntax.clone(),
|
||||||
style.body.clone(),
|
style.body.clone(),
|
||||||
theme.editor.document_highlight_read_background,
|
theme.editor.document_highlight_read_background,
|
||||||
|
theme.chat_panel.self_mention_background,
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
.flex(1., true),
|
.flex(1., true),
|
||||||
|
@ -456,6 +470,7 @@ impl ChatPanel {
|
||||||
theme.editor.syntax.clone(),
|
theme.editor.syntax.clone(),
|
||||||
style.body.clone(),
|
style.body.clone(),
|
||||||
theme.editor.document_highlight_read_background,
|
theme.editor.document_highlight_read_background,
|
||||||
|
theme.chat_panel.self_mention_background,
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
.flex(1., true),
|
.flex(1., true),
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use std::{ops::Range, sync::Arc};
|
use std::{ops::Range, sync::Arc};
|
||||||
|
|
||||||
|
use anyhow::bail;
|
||||||
use futures::FutureExt;
|
use futures::FutureExt;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
color::Color,
|
color::Color,
|
||||||
|
@ -25,9 +26,15 @@ pub struct RichText {
|
||||||
pub regions: Vec<RenderedRegion>,
|
pub regions: Vec<RenderedRegion>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
|
enum BackgroundKind {
|
||||||
|
Code,
|
||||||
|
Mention,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct RenderedRegion {
|
pub struct RenderedRegion {
|
||||||
code: bool,
|
background_kind: Option<BackgroundKind>,
|
||||||
link_url: Option<String>,
|
link_url: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,6 +44,7 @@ impl RichText {
|
||||||
syntax: Arc<SyntaxTheme>,
|
syntax: Arc<SyntaxTheme>,
|
||||||
style: TextStyle,
|
style: TextStyle,
|
||||||
code_span_background_color: Color,
|
code_span_background_color: Color,
|
||||||
|
self_mention_span_background_color: Color,
|
||||||
cx: &mut ViewContext<V>,
|
cx: &mut ViewContext<V>,
|
||||||
) -> AnyElement<V> {
|
) -> AnyElement<V> {
|
||||||
let mut region_id = 0;
|
let mut region_id = 0;
|
||||||
|
@ -73,18 +81,49 @@ impl RichText {
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if region.code {
|
if region.background_kind == Some(BackgroundKind::Code) {
|
||||||
cx.scene().push_quad(gpui::Quad {
|
cx.scene().push_quad(gpui::Quad {
|
||||||
bounds,
|
bounds,
|
||||||
background: Some(code_span_background_color),
|
background: Some(code_span_background_color),
|
||||||
border: Default::default(),
|
border: Default::default(),
|
||||||
corner_radii: (2.0).into(),
|
corner_radii: (2.0).into(),
|
||||||
});
|
});
|
||||||
|
} else if region.background_kind == Some(BackgroundKind::Mention) {
|
||||||
|
cx.scene().push_quad(gpui::Quad {
|
||||||
|
bounds,
|
||||||
|
background: Some(self_mention_span_background_color),
|
||||||
|
border: Default::default(),
|
||||||
|
corner_radii: (2.0).into(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.with_soft_wrap(true)
|
.with_soft_wrap(true)
|
||||||
.into_any()
|
.into_any()
|
||||||
}
|
}
|
||||||
|
pub fn add_mention(
|
||||||
|
&mut self,
|
||||||
|
range: Range<usize>,
|
||||||
|
is_current_user: bool,
|
||||||
|
mention_style: HighlightStyle,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
if range.end > self.text.len() {
|
||||||
|
bail!(
|
||||||
|
"Mention in range {range:?} is outside of bounds for a message of length {}",
|
||||||
|
self.text.len()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if is_current_user {
|
||||||
|
self.region_ranges.push(range.clone());
|
||||||
|
self.regions.push(RenderedRegion {
|
||||||
|
background_kind: Some(BackgroundKind::Mention),
|
||||||
|
link_url: None,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
self.highlights
|
||||||
|
.push((range, Highlight::Highlight(mention_style)));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_markdown_mut(
|
pub fn render_markdown_mut(
|
||||||
|
@ -101,7 +140,11 @@ pub fn render_markdown_mut(
|
||||||
let mut current_language = None;
|
let mut current_language = None;
|
||||||
let mut list_stack = Vec::new();
|
let mut list_stack = Vec::new();
|
||||||
|
|
||||||
for event in Parser::new_ext(&block, Options::all()) {
|
// Smart Punctuation is disabled as that messes with offsets within the message.
|
||||||
|
let mut options = Options::all();
|
||||||
|
options.remove(Options::ENABLE_SMART_PUNCTUATION);
|
||||||
|
|
||||||
|
for event in Parser::new_ext(&block, options) {
|
||||||
let prev_len = data.text.len();
|
let prev_len = data.text.len();
|
||||||
match event {
|
match event {
|
||||||
Event::Text(t) => {
|
Event::Text(t) => {
|
||||||
|
@ -121,7 +164,7 @@ pub fn render_markdown_mut(
|
||||||
data.region_ranges.push(prev_len..data.text.len());
|
data.region_ranges.push(prev_len..data.text.len());
|
||||||
data.regions.push(RenderedRegion {
|
data.regions.push(RenderedRegion {
|
||||||
link_url: Some(link_url),
|
link_url: Some(link_url),
|
||||||
code: false,
|
background_kind: None,
|
||||||
});
|
});
|
||||||
style.underline = Some(Underline {
|
style.underline = Some(Underline {
|
||||||
thickness: 1.0.into(),
|
thickness: 1.0.into(),
|
||||||
|
@ -162,7 +205,7 @@ pub fn render_markdown_mut(
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
data.regions.push(RenderedRegion {
|
data.regions.push(RenderedRegion {
|
||||||
code: true,
|
background_kind: Some(BackgroundKind::Code),
|
||||||
link_url: link_url.clone(),
|
link_url: link_url.clone(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -641,6 +641,7 @@ pub struct ChatPanel {
|
||||||
pub avatar_container: ContainerStyle,
|
pub avatar_container: ContainerStyle,
|
||||||
pub message: ChatMessage,
|
pub message: ChatMessage,
|
||||||
pub mention_highlight: HighlightStyle,
|
pub mention_highlight: HighlightStyle,
|
||||||
|
pub self_mention_background: Color,
|
||||||
pub continuation_message: ChatMessage,
|
pub continuation_message: ChatMessage,
|
||||||
pub last_message_bottom_spacing: f32,
|
pub last_message_bottom_spacing: f32,
|
||||||
pub pending_message: ChatMessage,
|
pub pending_message: ChatMessage,
|
||||||
|
|
|
@ -1,11 +1,8 @@
|
||||||
import {
|
import { background, border, text } from "./components"
|
||||||
background,
|
|
||||||
border,
|
|
||||||
text,
|
|
||||||
} from "./components"
|
|
||||||
import { icon_button } from "../component/icon_button"
|
import { icon_button } from "../component/icon_button"
|
||||||
import { useTheme } from "../theme"
|
import { useTheme } from "../theme"
|
||||||
import { interactive } from "../element"
|
import { interactive } from "../element"
|
||||||
|
import { Color } from "ayu/dist/color"
|
||||||
|
|
||||||
export default function chat_panel(): any {
|
export default function chat_panel(): any {
|
||||||
const theme = useTheme()
|
const theme = useTheme()
|
||||||
|
@ -41,15 +38,13 @@ export default function chat_panel(): any {
|
||||||
left: 2,
|
left: 2,
|
||||||
top: 2,
|
top: 2,
|
||||||
bottom: 2,
|
bottom: 2,
|
||||||
}
|
},
|
||||||
},
|
|
||||||
list: {
|
|
||||||
|
|
||||||
},
|
},
|
||||||
|
list: {},
|
||||||
channel_select: {
|
channel_select: {
|
||||||
header: {
|
header: {
|
||||||
...channel_name,
|
...channel_name,
|
||||||
border: border(layer, { bottom: true })
|
border: border(layer, { bottom: true }),
|
||||||
},
|
},
|
||||||
item: channel_name,
|
item: channel_name,
|
||||||
active_item: {
|
active_item: {
|
||||||
|
@ -62,8 +57,8 @@ export default function chat_panel(): any {
|
||||||
},
|
},
|
||||||
menu: {
|
menu: {
|
||||||
background: background(layer, "on"),
|
background: background(layer, "on"),
|
||||||
border: border(layer, { bottom: true })
|
border: border(layer, { bottom: true }),
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
icon_button: icon_button({
|
icon_button: icon_button({
|
||||||
variant: "ghost",
|
variant: "ghost",
|
||||||
|
@ -91,7 +86,8 @@ export default function chat_panel(): any {
|
||||||
top: 4,
|
top: 4,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mention_highlight: { weight: 'bold' },
|
mention_highlight: { weight: "bold" },
|
||||||
|
self_mention_background: background(layer, "active"),
|
||||||
message: {
|
message: {
|
||||||
...interactive({
|
...interactive({
|
||||||
base: {
|
base: {
|
||||||
|
@ -101,7 +97,7 @@ export default function chat_panel(): any {
|
||||||
bottom: 4,
|
bottom: 4,
|
||||||
left: SPACING / 2,
|
left: SPACING / 2,
|
||||||
right: SPACING / 3,
|
right: SPACING / 3,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
state: {
|
state: {
|
||||||
hovered: {
|
hovered: {
|
||||||
|
@ -135,7 +131,7 @@ export default function chat_panel(): any {
|
||||||
bottom: 4,
|
bottom: 4,
|
||||||
left: SPACING / 2,
|
left: SPACING / 2,
|
||||||
right: SPACING / 3,
|
right: SPACING / 3,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
state: {
|
state: {
|
||||||
hovered: {
|
hovered: {
|
||||||
|
@ -160,7 +156,7 @@ export default function chat_panel(): any {
|
||||||
bottom: 4,
|
bottom: 4,
|
||||||
left: SPACING / 2,
|
left: SPACING / 2,
|
||||||
right: SPACING / 3,
|
right: SPACING / 3,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
state: {
|
state: {
|
||||||
hovered: {
|
hovered: {
|
||||||
|
@ -171,6 +167,6 @@ export default function chat_panel(): any {
|
||||||
},
|
},
|
||||||
sign_in_prompt: {
|
sign_in_prompt: {
|
||||||
default: text(layer, "sans", "base"),
|
default: text(layer, "sans", "base"),
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue