mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-25 01:34:02 +00:00
107 channel touch ups (#3087)
Release Notes: - Add user avatars to channel chat messages - Group messages by sender - Fix visual bugs in new chat and note buttons
This commit is contained in:
commit
b0e56b7c54
5 changed files with 154 additions and 49 deletions
|
@ -130,6 +130,7 @@ impl ChatPanel {
|
|||
fs,
|
||||
client,
|
||||
channel_store,
|
||||
|
||||
active_chat: Default::default(),
|
||||
pending_serialization: Task::ready(None),
|
||||
message_list,
|
||||
|
@ -328,12 +329,26 @@ impl ChatPanel {
|
|||
}
|
||||
|
||||
fn render_message(&self, ix: usize, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
|
||||
let message = self.active_chat.as_ref().unwrap().0.read(cx).message(ix);
|
||||
let (message, is_continuation, is_last) = {
|
||||
let active_chat = self.active_chat.as_ref().unwrap().0.read(cx);
|
||||
let last_message = active_chat.message(ix.saturating_sub(1));
|
||||
let this_message = active_chat.message(ix);
|
||||
let is_continuation = last_message.id != this_message.id
|
||||
&& this_message.sender.id == last_message.sender.id;
|
||||
|
||||
(
|
||||
active_chat.message(ix),
|
||||
is_continuation,
|
||||
active_chat.message_count() == ix + 1,
|
||||
)
|
||||
};
|
||||
|
||||
let now = OffsetDateTime::now_utc();
|
||||
let theme = theme::current(cx);
|
||||
let style = if message.is_pending() {
|
||||
&theme.chat_panel.pending_message
|
||||
} else if is_continuation {
|
||||
&theme.chat_panel.continuation_message
|
||||
} else {
|
||||
&theme.chat_panel.message
|
||||
};
|
||||
|
@ -349,49 +364,103 @@ impl ChatPanel {
|
|||
enum DeleteMessage {}
|
||||
|
||||
let body = message.body.clone();
|
||||
Flex::column()
|
||||
.with_child(
|
||||
Flex::row()
|
||||
.with_child(
|
||||
Label::new(
|
||||
message.sender.github_login.clone(),
|
||||
style.sender.text.clone(),
|
||||
if is_continuation {
|
||||
Flex::row()
|
||||
.with_child(Text::new(body, style.body.clone()))
|
||||
.with_children(message_id_to_remove.map(|id| {
|
||||
MouseEventHandler::new::<DeleteMessage, _>(id as usize, cx, |mouse_state, _| {
|
||||
let button_style = theme.chat_panel.icon_button.style_for(mouse_state);
|
||||
render_icon_button(button_style, "icons/x.svg")
|
||||
.aligned()
|
||||
.into_any()
|
||||
})
|
||||
.with_padding(Padding::uniform(2.))
|
||||
.with_cursor_style(CursorStyle::PointingHand)
|
||||
.on_click(MouseButton::Left, move |_, this, cx| {
|
||||
this.remove_message(id, cx);
|
||||
})
|
||||
.flex_float()
|
||||
}))
|
||||
.contained()
|
||||
.with_style(style.container)
|
||||
.with_margin_bottom(if is_last {
|
||||
theme.chat_panel.last_message_bottom_spacing
|
||||
} else {
|
||||
0.
|
||||
})
|
||||
.into_any()
|
||||
} else {
|
||||
Flex::column()
|
||||
.with_child(
|
||||
Flex::row()
|
||||
.with_child(
|
||||
message
|
||||
.sender
|
||||
.avatar
|
||||
.clone()
|
||||
.map(|avatar| {
|
||||
Image::from_data(avatar)
|
||||
.with_style(theme.collab_panel.channel_avatar)
|
||||
.into_any()
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
Empty::new()
|
||||
.constrained()
|
||||
.with_width(
|
||||
theme.collab_panel.channel_avatar.width.unwrap_or(12.),
|
||||
)
|
||||
.into_any()
|
||||
})
|
||||
.contained()
|
||||
.with_margin_right(4.),
|
||||
)
|
||||
.contained()
|
||||
.with_style(style.sender.container),
|
||||
)
|
||||
.with_child(
|
||||
Label::new(
|
||||
format_timestamp(message.timestamp, now, self.local_timezone),
|
||||
style.timestamp.text.clone(),
|
||||
.with_child(
|
||||
Label::new(
|
||||
message.sender.github_login.clone(),
|
||||
style.sender.text.clone(),
|
||||
)
|
||||
.contained()
|
||||
.with_style(style.sender.container),
|
||||
)
|
||||
.contained()
|
||||
.with_style(style.timestamp.container),
|
||||
)
|
||||
.with_children(message_id_to_remove.map(|id| {
|
||||
MouseEventHandler::new::<DeleteMessage, _>(
|
||||
id as usize,
|
||||
cx,
|
||||
|mouse_state, _| {
|
||||
let button_style =
|
||||
theme.chat_panel.icon_button.style_for(mouse_state);
|
||||
render_icon_button(button_style, "icons/x.svg")
|
||||
.aligned()
|
||||
.into_any()
|
||||
},
|
||||
.with_child(
|
||||
Label::new(
|
||||
format_timestamp(message.timestamp, now, self.local_timezone),
|
||||
style.timestamp.text.clone(),
|
||||
)
|
||||
.contained()
|
||||
.with_style(style.timestamp.container),
|
||||
)
|
||||
.with_padding(Padding::uniform(2.))
|
||||
.with_cursor_style(CursorStyle::PointingHand)
|
||||
.on_click(MouseButton::Left, move |_, this, cx| {
|
||||
this.remove_message(id, cx);
|
||||
})
|
||||
.flex_float()
|
||||
})),
|
||||
)
|
||||
.with_child(Text::new(body, style.body.clone()))
|
||||
.contained()
|
||||
.with_style(style.container)
|
||||
.into_any()
|
||||
.with_children(message_id_to_remove.map(|id| {
|
||||
MouseEventHandler::new::<DeleteMessage, _>(
|
||||
id as usize,
|
||||
cx,
|
||||
|mouse_state, _| {
|
||||
let button_style =
|
||||
theme.chat_panel.icon_button.style_for(mouse_state);
|
||||
render_icon_button(button_style, "icons/x.svg")
|
||||
.aligned()
|
||||
.into_any()
|
||||
},
|
||||
)
|
||||
.with_padding(Padding::uniform(2.))
|
||||
.with_cursor_style(CursorStyle::PointingHand)
|
||||
.on_click(MouseButton::Left, move |_, this, cx| {
|
||||
this.remove_message(id, cx);
|
||||
})
|
||||
.flex_float()
|
||||
}))
|
||||
.align_children_center(),
|
||||
)
|
||||
.with_child(Text::new(body, style.body.clone()))
|
||||
.contained()
|
||||
.with_style(style.container)
|
||||
.with_margin_bottom(if is_last {
|
||||
theme.chat_panel.last_message_bottom_spacing
|
||||
} else {
|
||||
0.
|
||||
})
|
||||
.into_any()
|
||||
}
|
||||
}
|
||||
|
||||
fn render_input_box(&self, theme: &Arc<Theme>, cx: &AppContext) -> AnyElement<Self> {
|
||||
|
|
|
@ -1937,6 +1937,8 @@ impl CollabPanel {
|
|||
is_dragged_over = true;
|
||||
}
|
||||
|
||||
let has_messages_notification = channel.unseen_message_id.is_some();
|
||||
|
||||
MouseEventHandler::new::<Channel, _>(ix, cx, |state, cx| {
|
||||
let row_hovered = state.hovered();
|
||||
|
||||
|
@ -2022,24 +2024,33 @@ impl CollabPanel {
|
|||
.flex(1., true)
|
||||
})
|
||||
.with_child(
|
||||
MouseEventHandler::new::<ChannelNote, _>(ix, cx, move |_, _| {
|
||||
MouseEventHandler::new::<ChannelNote, _>(ix, cx, move |mouse_state, _| {
|
||||
let container_style = collab_theme
|
||||
.disclosure
|
||||
.button
|
||||
.style_for(mouse_state)
|
||||
.container;
|
||||
|
||||
if channel.unseen_message_id.is_some() {
|
||||
Svg::new("icons/conversations.svg")
|
||||
.with_color(collab_theme.channel_note_active_color)
|
||||
.constrained()
|
||||
.with_width(collab_theme.channel_hash.width)
|
||||
.contained()
|
||||
.with_style(container_style)
|
||||
.with_uniform_padding(4.)
|
||||
.into_any()
|
||||
} else if row_hovered {
|
||||
Svg::new("icons/conversations.svg")
|
||||
.with_color(collab_theme.channel_hash.color)
|
||||
.constrained()
|
||||
.with_width(collab_theme.channel_hash.width)
|
||||
.contained()
|
||||
.with_style(container_style)
|
||||
.with_uniform_padding(4.)
|
||||
.into_any()
|
||||
} else {
|
||||
Empty::new()
|
||||
.constrained()
|
||||
.with_width(collab_theme.channel_hash.width)
|
||||
.into_any()
|
||||
Empty::new().into_any()
|
||||
}
|
||||
})
|
||||
.on_click(MouseButton::Left, move |_, this, cx| {
|
||||
|
@ -2056,7 +2067,12 @@ impl CollabPanel {
|
|||
.with_margin_right(4.),
|
||||
)
|
||||
.with_child(
|
||||
MouseEventHandler::new::<ChannelCall, _>(ix, cx, move |_, cx| {
|
||||
MouseEventHandler::new::<ChannelCall, _>(ix, cx, move |mouse_state, cx| {
|
||||
let container_style = collab_theme
|
||||
.disclosure
|
||||
.button
|
||||
.style_for(mouse_state)
|
||||
.container;
|
||||
if row_hovered || channel.unseen_note_version.is_some() {
|
||||
Svg::new("icons/file.svg")
|
||||
.with_color(if channel.unseen_note_version.is_some() {
|
||||
|
@ -2067,6 +2083,8 @@ impl CollabPanel {
|
|||
.constrained()
|
||||
.with_width(collab_theme.channel_hash.width)
|
||||
.contained()
|
||||
.with_style(container_style)
|
||||
.with_uniform_padding(4.)
|
||||
.with_margin_right(collab_theme.channel_hash.container.margin.left)
|
||||
.with_tooltip::<NotesTooltip>(
|
||||
ix as usize,
|
||||
|
@ -2076,13 +2094,16 @@ impl CollabPanel {
|
|||
cx,
|
||||
)
|
||||
.into_any()
|
||||
} else {
|
||||
} else if has_messages_notification {
|
||||
Empty::new()
|
||||
.constrained()
|
||||
.with_width(collab_theme.channel_hash.width)
|
||||
.contained()
|
||||
.with_uniform_padding(4.)
|
||||
.with_margin_right(collab_theme.channel_hash.container.margin.left)
|
||||
.into_any()
|
||||
} else {
|
||||
Empty::new().into_any()
|
||||
}
|
||||
})
|
||||
.on_click(MouseButton::Left, move |_, this, cx| {
|
||||
|
|
|
@ -635,6 +635,8 @@ pub struct ChatPanel {
|
|||
pub channel_select: ChannelSelect,
|
||||
pub input_editor: FieldEditor,
|
||||
pub message: ChatMessage,
|
||||
pub continuation_message: ChatMessage,
|
||||
pub last_message_bottom_spacing: f32,
|
||||
pub pending_message: ChatMessage,
|
||||
pub sign_in_prompt: Interactive<TextStyle>,
|
||||
pub icon_button: Interactive<IconButton>,
|
||||
|
|
|
@ -87,7 +87,19 @@ export default function chat_panel(): any {
|
|||
...text(layer, "sans", "base", { weight: "bold" }),
|
||||
},
|
||||
timestamp: text(layer, "sans", "base", "disabled"),
|
||||
margin: { bottom: SPACING }
|
||||
margin: { top: SPACING }
|
||||
},
|
||||
last_message_bottom_spacing: SPACING,
|
||||
continuation_message: {
|
||||
body: text(layer, "sans", "base"),
|
||||
sender: {
|
||||
margin: {
|
||||
right: 8,
|
||||
},
|
||||
...text(layer, "sans", "base", { weight: "bold" }),
|
||||
},
|
||||
timestamp: text(layer, "sans", "base", "disabled"),
|
||||
|
||||
},
|
||||
pending_message: {
|
||||
body: text(layer, "sans", "base"),
|
||||
|
|
|
@ -21,6 +21,7 @@ export default function contacts_panel(): any {
|
|||
...text(theme.lowest, "sans", "base"),
|
||||
button: icon_button({ variant: "ghost" }),
|
||||
spacing: 4,
|
||||
padding: 4,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue