This commit is contained in:
Max Brunsfeld 2021-08-25 15:22:14 -07:00
parent 8f86fa1ccd
commit b923f65a63
8 changed files with 114 additions and 21 deletions

10
Cargo.lock generated
View file

@ -5142,6 +5142,15 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "time"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e0a10c9a9fb3a5dce8c2239ed670f1a2569fcf42da035f5face1b19860d52b0"
dependencies = [
"libc",
]
[[package]]
name = "time-macros"
version = "0.1.1"
@ -5832,6 +5841,7 @@ dependencies = [
"smol",
"surf",
"tempdir",
"time 0.3.2",
"tiny_http",
"toml 0.5.8",
"tree-sitter",

View file

@ -48,6 +48,7 @@ smallvec = { version = "1.6", features = ["union"] }
smol = "1.2.5"
surf = "2.2"
tempdir = { version = "0.3.7", optional = true }
time = { version = "0.3", features = ["local-offset"] }
tiny_http = "0.8"
toml = "0.5"
tree-sitter = "0.19.5"

View file

@ -22,8 +22,14 @@ color = "$text.2"
[workspace.active_sidebar_icon]
color = "$text.0"
[chat_panel]
padding = { top = 10.0, bottom = 10.0, left = 10.0, right = 10.0 }
[chat_panel.message]
body = "$text.0"
sender.margin.right = 10.0
sender.text = { color = "#ff0000", weight = "bold", italic = true }
timestamp.text = "$text.2"
[selector]
background = "$surface.2"

View file

@ -14,6 +14,7 @@ use std::{
ops::Range,
sync::Arc,
};
use time::OffsetDateTime;
use zrpc::{
proto::{self, ChannelMessageSent},
TypedEnvelope,
@ -47,6 +48,7 @@ pub struct Channel {
pub struct ChannelMessage {
pub id: u64,
pub body: String,
pub timestamp: OffsetDateTime,
pub sender: Arc<User>,
}
@ -261,14 +263,17 @@ impl Channel {
this.insert_message(
ChannelMessage {
id: response.message_id,
timestamp: OffsetDateTime::from_unix_timestamp(
response.timestamp as i64,
)?,
body,
sender,
},
cx,
);
}
});
Ok(())
Ok(())
})
}
.log_err()
})
@ -363,6 +368,7 @@ impl ChannelMessage {
Ok(ChannelMessage {
id: message.id,
body: message.body,
timestamp: OffsetDateTime::from_unix_timestamp(message.timestamp as i64)?,
sender,
})
}

View file

@ -9,6 +9,7 @@ use gpui::{
Subscription, View, ViewContext, ViewHandle,
};
use postage::watch;
use time::{OffsetDateTime, UtcOffset};
pub struct ChatPanel {
channel_list: ModelHandle<ChannelList>,
@ -75,12 +76,13 @@ impl ChatPanel {
fn set_active_channel(&mut self, channel: ModelHandle<Channel>, cx: &mut ViewContext<Self>) {
if self.active_channel.as_ref().map(|e| &e.0) != Some(&channel) {
let subscription = cx.subscribe(&channel, Self::channel_did_change);
let now = OffsetDateTime::now_utc();
self.messages = ListState::new(
channel
.read(cx)
.messages()
.cursor::<(), ()>()
.map(|m| self.render_message(m))
.map(|m| self.render_message(m, now))
.collect(),
Orientation::Bottom,
);
@ -99,12 +101,13 @@ impl ChatPanel {
old_range,
new_count,
} => {
let now = OffsetDateTime::now_utc();
self.messages.splice(
old_range.clone(),
channel
.read(cx)
.messages_in_range(old_range.start..(old_range.start + new_count))
.map(|message| self.render_message(message)),
.map(|message| self.render_message(message, now)),
);
}
}
@ -115,15 +118,50 @@ impl ChatPanel {
Expanded::new(1., List::new(self.messages.clone()).boxed()).boxed()
}
fn render_message(&self, message: &ChannelMessage) -> ElementBox {
fn render_message(&self, message: &ChannelMessage, now: OffsetDateTime) -> ElementBox {
let settings = self.settings.borrow();
Text::new(
message.body.clone(),
settings.ui_font_family,
settings.ui_font_size,
)
.with_style(&settings.theme.chat_panel.message.body)
.boxed()
let theme = &settings.theme.chat_panel.message;
Flex::column()
.with_child(
Flex::row()
.with_child(
Container::new(
Label::new(
message.sender.github_login.clone(),
settings.ui_font_family,
settings.ui_font_size,
)
.with_style(&theme.sender.label)
.boxed(),
)
.with_style(&theme.sender.container)
.boxed(),
)
.with_child(
Container::new(
Label::new(
format_timestamp(message.timestamp, now),
settings.ui_font_family,
settings.ui_font_size,
)
.with_style(&theme.timestamp.label)
.boxed(),
)
.with_style(&theme.timestamp.container)
.boxed(),
)
.boxed(),
)
.with_child(
Text::new(
message.body.clone(),
settings.ui_font_family,
settings.ui_font_size,
)
.with_style(&theme.body)
.boxed(),
)
.boxed()
}
fn render_input_box(&self) -> ElementBox {
@ -157,9 +195,36 @@ impl View for ChatPanel {
}
fn render(&self, _: &RenderContext<Self>) -> ElementBox {
Flex::column()
.with_child(self.render_active_channel_messages())
.with_child(self.render_input_box())
.boxed()
let theme = &self.settings.borrow().theme;
Container::new(
Flex::column()
.with_child(self.render_active_channel_messages())
.with_child(self.render_input_box())
.boxed(),
)
.with_style(&theme.chat_panel.container)
.boxed()
}
}
fn format_timestamp(mut timestamp: OffsetDateTime, mut now: OffsetDateTime) -> String {
let local_offset = UtcOffset::current_local_offset().unwrap_or(UtcOffset::UTC);
timestamp = timestamp.to_offset(local_offset);
now = now.to_offset(local_offset);
let today = now.date();
let date = timestamp.date();
let mut hour = timestamp.hour();
let mut part = "am";
if hour > 12 {
hour -= 12;
part = "pm";
}
if date == today {
format!("{}:{}{}", hour, timestamp.minute(), part)
} else if date.next_day() == Some(today) {
format!("yesterday at {}:{}{}", hour, timestamp.minute(), part)
} else {
format!("{}/{}/{}", date.month(), date.day(), date.year())
}
}

View file

@ -55,12 +55,16 @@ pub struct SidebarIcon {
#[derive(Debug, Default, Deserialize)]
pub struct ChatPanel {
#[serde(flatten)]
pub container: ContainerStyle,
pub message: ChatMessage,
}
#[derive(Debug, Default, Deserialize)]
pub struct ChatMessage {
pub body: TextStyle,
pub sender: ContainedLabel,
pub timestamp: ContainedLabel,
}
#[derive(Debug, Default, Deserialize)]
@ -70,12 +74,12 @@ pub struct Selector {
#[serde(flatten)]
pub label: LabelStyle,
pub item: SelectorItem,
pub active_item: SelectorItem,
pub item: ContainedLabel,
pub active_item: ContainedLabel,
}
#[derive(Debug, Default, Deserialize)]
pub struct SelectorItem {
pub struct ContainedLabel {
#[serde(flatten)]
pub container: ContainerStyle,
#[serde(flatten)]

View file

@ -99,6 +99,7 @@ impl ThemeSelector {
Ok(theme) => {
cx.notify_all();
action.0.settings_tx.lock().borrow_mut().theme = theme;
log::info!("reloaded theme {}", current_theme_name);
}
Err(error) => {
log::error!("failed to load theme {}: {:?}", current_theme_name, error)

View file

@ -958,7 +958,7 @@ impl View for Workspace {
if let Some(panel) = self.left_sidebar.active_item() {
content.add_child(
ConstrainedBox::new(ChildView::new(panel.id()).boxed())
.with_width(200.0)
.with_width(300.0)
.named("left panel"),
);
}
@ -966,7 +966,7 @@ impl View for Workspace {
if let Some(panel) = self.right_sidebar.active_item() {
content.add_child(
ConstrainedBox::new(ChildView::new(panel.id()).boxed())
.with_width(200.0)
.with_width(300.0)
.named("right panel"),
);
}