Adjust channel rendering to group related messages
This commit is contained in:
parent
5074bccae4
commit
73e78a2257
3 changed files with 126 additions and 68 deletions
|
@ -2,7 +2,7 @@ use crate::{channel_view::ChannelView, ChatPanelSettings};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use call::ActiveCall;
|
use call::ActiveCall;
|
||||||
use channel::{ChannelChat, ChannelChatEvent, ChannelMessageId, ChannelStore};
|
use channel::{ChannelChat, ChannelChatEvent, ChannelMessageId, ChannelStore};
|
||||||
use client::{Client, UserStore};
|
use client::Client;
|
||||||
use db::kvp::KEY_VALUE_STORE;
|
use db::kvp::KEY_VALUE_STORE;
|
||||||
use editor::Editor;
|
use editor::Editor;
|
||||||
use feature_flags::{ChannelsAlpha, FeatureFlagAppExt};
|
use feature_flags::{ChannelsAlpha, FeatureFlagAppExt};
|
||||||
|
@ -35,7 +35,6 @@ const CHAT_PANEL_KEY: &'static str = "ChatPanel";
|
||||||
pub struct ChatPanel {
|
pub struct ChatPanel {
|
||||||
client: Arc<Client>,
|
client: Arc<Client>,
|
||||||
channel_store: ModelHandle<ChannelStore>,
|
channel_store: ModelHandle<ChannelStore>,
|
||||||
user_store: ModelHandle<UserStore>,
|
|
||||||
active_chat: Option<(ModelHandle<ChannelChat>, Subscription)>,
|
active_chat: Option<(ModelHandle<ChannelChat>, Subscription)>,
|
||||||
message_list: ListState<ChatPanel>,
|
message_list: ListState<ChatPanel>,
|
||||||
input_editor: ViewHandle<Editor>,
|
input_editor: ViewHandle<Editor>,
|
||||||
|
@ -79,7 +78,6 @@ impl ChatPanel {
|
||||||
let fs = workspace.app_state().fs.clone();
|
let fs = workspace.app_state().fs.clone();
|
||||||
let client = workspace.app_state().client.clone();
|
let client = workspace.app_state().client.clone();
|
||||||
let channel_store = workspace.app_state().channel_store.clone();
|
let channel_store = workspace.app_state().channel_store.clone();
|
||||||
let user_store = workspace.app_state().user_store.clone();
|
|
||||||
|
|
||||||
let input_editor = cx.add_view(|cx| {
|
let input_editor = cx.add_view(|cx| {
|
||||||
let mut editor = Editor::auto_height(
|
let mut editor = Editor::auto_height(
|
||||||
|
@ -132,7 +130,7 @@ impl ChatPanel {
|
||||||
fs,
|
fs,
|
||||||
client,
|
client,
|
||||||
channel_store,
|
channel_store,
|
||||||
user_store,
|
|
||||||
active_chat: Default::default(),
|
active_chat: Default::default(),
|
||||||
pending_serialization: Task::ready(None),
|
pending_serialization: Task::ready(None),
|
||||||
message_list,
|
message_list,
|
||||||
|
@ -331,12 +329,26 @@ impl ChatPanel {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_message(&self, ix: usize, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
|
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 now = OffsetDateTime::now_utc();
|
||||||
let theme = theme::current(cx);
|
let theme = theme::current(cx);
|
||||||
let style = if message.is_pending() {
|
let style = if message.is_pending() {
|
||||||
&theme.chat_panel.pending_message
|
&theme.chat_panel.pending_message
|
||||||
|
} else if is_continuation {
|
||||||
|
&theme.chat_panel.continuation_message
|
||||||
} else {
|
} else {
|
||||||
&theme.chat_panel.message
|
&theme.chat_panel.message
|
||||||
};
|
};
|
||||||
|
@ -352,6 +364,32 @@ impl ChatPanel {
|
||||||
enum DeleteMessage {}
|
enum DeleteMessage {}
|
||||||
|
|
||||||
let body = message.body.clone();
|
let body = message.body.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()
|
Flex::column()
|
||||||
.with_child(
|
.with_child(
|
||||||
Flex::row()
|
Flex::row()
|
||||||
|
@ -416,8 +454,14 @@ impl ChatPanel {
|
||||||
.with_child(Text::new(body, style.body.clone()))
|
.with_child(Text::new(body, style.body.clone()))
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
|
.with_margin_bottom(if is_last {
|
||||||
|
theme.chat_panel.last_message_bottom_spacing
|
||||||
|
} else {
|
||||||
|
0.
|
||||||
|
})
|
||||||
.into_any()
|
.into_any()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn render_input_box(&self, theme: &Arc<Theme>, cx: &AppContext) -> AnyElement<Self> {
|
fn render_input_box(&self, theme: &Arc<Theme>, cx: &AppContext) -> AnyElement<Self> {
|
||||||
ChildView::new(&self.input_editor, cx)
|
ChildView::new(&self.input_editor, cx)
|
||||||
|
|
|
@ -635,6 +635,8 @@ pub struct ChatPanel {
|
||||||
pub channel_select: ChannelSelect,
|
pub channel_select: ChannelSelect,
|
||||||
pub input_editor: FieldEditor,
|
pub input_editor: FieldEditor,
|
||||||
pub message: ChatMessage,
|
pub message: ChatMessage,
|
||||||
|
pub continuation_message: ChatMessage,
|
||||||
|
pub last_message_bottom_spacing: f32,
|
||||||
pub pending_message: ChatMessage,
|
pub pending_message: ChatMessage,
|
||||||
pub sign_in_prompt: Interactive<TextStyle>,
|
pub sign_in_prompt: Interactive<TextStyle>,
|
||||||
pub icon_button: Interactive<IconButton>,
|
pub icon_button: Interactive<IconButton>,
|
||||||
|
|
|
@ -87,7 +87,19 @@ export default function chat_panel(): any {
|
||||||
...text(layer, "sans", "base", { weight: "bold" }),
|
...text(layer, "sans", "base", { weight: "bold" }),
|
||||||
},
|
},
|
||||||
timestamp: text(layer, "sans", "base", "disabled"),
|
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: {
|
pending_message: {
|
||||||
body: text(layer, "sans", "base"),
|
body: text(layer, "sans", "base"),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue