diff --git a/web/index.html b/web/index.html
index 4935edb..4fe2fb4 100644
--- a/web/index.html
+++ b/web/index.html
@@ -22,6 +22,11 @@
width: 100%;
}
+ .message .header table td {
+ border: 0;
+ padding: 0;
+ }
+
.message .headers {
position: relative;
width: 100%;
diff --git a/web/src/view/mod.rs b/web/src/view/mod.rs
index 4c1bb12..760bdd0 100644
--- a/web/src/view/mod.rs
+++ b/web/src/view/mod.rs
@@ -324,21 +324,6 @@ implement_email!(
ShowThreadQueryThreadMessagesFrom
);
-fn view_address(email: impl Email) -> Node {
- span![
- C!["tag", "is-black"],
- email.addr().as_ref().map(|a| attrs! {At::Title=>a}),
- email
- .name()
- .as_ref()
- .unwrap_or(&email.addr().unwrap_or("(UNKNOWN)"))
- ]
-}
-
-fn view_addresses(addrs: &[impl Email]) -> Vec> {
- addrs.into_iter().map(view_address).collect::>()
-}
-
fn raw_text_message(contents: &str) -> Node {
let (contents, truncated_msg) = if contents.len() > MAX_RAW_MESSAGE_SIZE {
(
@@ -355,21 +340,7 @@ fn has_unread(tags: &[String]) -> bool {
tags.contains(&String::from("unread"))
}
-fn message_render(msg: &ShowThreadQueryThreadMessages, open: bool) -> Node {
- let id = msg.id.clone();
- let expand_id = msg.id.clone();
- let is_unread = has_unread(&msg.tags);
- let avatar: Option = None;
- //let avatar: Option = Some(String::from("https://bulma.io/images/placeholders/64x64.png"));
- let from: String = match &msg.from {
- Some(ShowThreadQueryThreadMessagesFrom {
- name: Some(name), ..
- }) => name.to_string(),
- Some(ShowThreadQueryThreadMessagesFrom {
- addr: Some(addr), ..
- }) => addr.to_string(),
- _ => String::from("UNKNOWN"),
- };
+fn render_avatar(avatar: Option, from: &str) -> Node {
let initials: String = from
.to_lowercase()
.split(" ")
@@ -377,12 +348,12 @@ fn message_render(msg: &ShowThreadQueryThreadMessages, open: bool) -> Node
// Limit to 2 characters because more characters don't fit in the box
.take(2)
.collect();
- let img = if let Some(src) = avatar {
+ if let Some(src) = avatar {
img![attrs! {At::Src=>src}]
} else {
let w = 64;
let h = 64;
- let from_color = compute_color(&from);
+ let from_color = compute_color(from);
svg![
attrs! {At::ViewBox=>format!("0 0 {w} {h}") },
style! {
@@ -416,64 +387,200 @@ fn message_render(msg: &ShowThreadQueryThreadMessages, open: bool) -> Node
]
]
]
+ }
+}
+
+fn render_open_header(msg: &ShowThreadQueryThreadMessages) -> Node {
+ let (from, from_detail) = match &msg.from {
+ Some(ShowThreadQueryThreadMessagesFrom {
+ name: Some(name),
+ addr,
+ }) => (name.to_string(), addr.clone()),
+ Some(ShowThreadQueryThreadMessagesFrom {
+ addr: Some(addr), ..
+ }) => (addr.to_string(), None),
+ _ => (String::from("UNKNOWN"), None),
};
+ // TODO(wathiede): get this from server
+ let avatar: Option = None;
+ //let avatar: Option = Some(String::from("https://bulma.io/images/placeholders/64x64.png"));
+ let id = msg.id.clone();
+ let is_unread = has_unread(&msg.tags);
+ let img = render_avatar(avatar, &from);
+ article![
+ C!["media"],
+ figure![C!["media-left"], p![C!["image", "is-64x64"], img]],
+ div![
+ C!["media-content"],
+ div![
+ C!["content"],
+ p![
+ strong![from],
+ br![],
+ small![from_detail],
+ table![
+ IF!(!msg.to.is_empty() =>
+ msg.to.iter().enumerate().map(|(i, to)|
+ tr![
+ td![ if i==0 { "To" }else { "" } ],
+ td![
+ small![
+ match to {
+ ShowThreadQueryThreadMessagesTo {
+ name: Some(name),
+ addr:Some(addr),
+ } => format!("{name} <{addr}>"),
+ ShowThreadQueryThreadMessagesTo {
+ name: Some(name),
+ addr:None
+ } => format!("{name}"),
+ ShowThreadQueryThreadMessagesTo {
+ addr: Some(addr), ..
+ } => format!("<{addr}>"),
+ _ => String::from("UNKNOWN"),
+ }
+
+ ]
+ ]])),
+ IF!(!msg.cc.is_empty() =>
+ msg.cc.iter().enumerate().map(|(i, cc)|
+ tr![
+ td![ if i==0 { "CC" }else { "" } ],
+ td![
+ small![
+ match cc {
+ ShowThreadQueryThreadMessagesCc {
+ name: Some(name),
+ addr:Some(addr),
+ } => format!("{name} <{addr}>"),
+ ShowThreadQueryThreadMessagesCc {
+ name: Some(name),
+ addr:None
+ } => format!("{name}"),
+ ShowThreadQueryThreadMessagesCc {
+ addr: Some(addr), ..
+ } => format!("<{addr}>"),
+ _ => String::from("UNKNOWN"),
+ }
+
+ ]
+ ]])),
+ tr![
+ td!["Date"],
+ td![msg.timestamp.map(|ts| span![C!["header"], human_age(ts)])]
+ ]
+ ],
+ ],
+ ],
+ ],
+ div![
+ C!["media-right"],
+ span![
+ C!["read-status"],
+ i![
+ C![
+ "far",
+ if is_unread {
+ "fa-envelope"
+ } else {
+ "fa-envelope-open"
+ },
+ ],
+ ev(Ev::Click, move |e| {
+ e.stop_propagation();
+ Msg::SetUnread(format!("id:{id}"), !is_unread)
+ })
+ ]
+ ]
+ ]
+ ]
+}
+
+fn render_closed_header(msg: &ShowThreadQueryThreadMessages) -> Node {
+ let from: String = match &msg.from {
+ Some(ShowThreadQueryThreadMessagesFrom {
+ name: Some(name), ..
+ }) => name.to_string(),
+ Some(ShowThreadQueryThreadMessagesFrom {
+ addr: Some(addr), ..
+ }) => addr.to_string(),
+ _ => String::from("UNKNOWN"),
+ };
+ // TODO(wathiede): get this from server
+ let avatar: Option = None;
+ //let avatar: Option = Some(String::from("https://bulma.io/images/placeholders/64x64.png"));
+ let id = msg.id.clone();
+ let is_unread = has_unread(&msg.tags);
+ let img = render_avatar(avatar, &from);
+ article![
+ C!["media"],
+ figure![C!["media-left"], p![C!["image", "is-64x64"], img]],
+ div![
+ C!["media-content"],
+ div![
+ C!["content"],
+ p![
+ strong![from],
+ br![],
+ IF!(!msg.to.is_empty() =>
+ nodes![
+ small![" to "],
+ msg.to.iter().enumerate().map(|(i, to)| small![
+ if i > 0 { ", " } else { "" },
+ to.name()
+ .as_ref()
+ .unwrap_or(&to.addr().unwrap_or("(UNKNOWN)"))
+ ]).collect::>()
+ ]),
+ IF!(!msg.cc.is_empty() =>
+ nodes![
+ small![" cc "],
+ msg.cc.iter().enumerate().map(|(i, cc)| small![
+ if i > 0 { ", " } else { "" },
+ cc.name()
+ .as_ref()
+ .unwrap_or(&cc.addr().unwrap_or("(UNKNOWN)"))
+ ]).collect::>()
+ ]),
+ br![],
+ msg.timestamp.map(|ts| span![C!["header"], human_age(ts)]),
+ ],
+ ],
+ ],
+ div![
+ C!["media-right"],
+ span![
+ C!["read-status"],
+ i![
+ C![
+ "far",
+ if is_unread {
+ "fa-envelope"
+ } else {
+ "fa-envelope-open"
+ },
+ ],
+ ev(Ev::Click, move |e| {
+ e.stop_propagation();
+ Msg::SetUnread(format!("id:{id}"), !is_unread)
+ })
+ ]
+ ]
+ ]
+ ]
+}
+
+fn message_render(msg: &ShowThreadQueryThreadMessages, open: bool) -> Node {
+ let expand_id = msg.id.clone();
div![
C!["message"],
- article![
- C!["media"],
- figure![C!["media-left"], p![C!["image", "is-64x64"], img],],
- div![
- C!["media-content"],
- div![
- C!["content"],
- p![
- strong![from],
- br![],
- IF!(!msg.to.is_empty() =>
- nodes![
- small![" to "],
- msg.to.iter().enumerate().map(|(i, to)| small![
- if i > 0 { ", " } else { "" },
- to.name()
- .as_ref()
- .unwrap_or(&to.addr().unwrap_or("(UNKNOWN)"))
- ]).collect::>()
- ]),
- IF!(!msg.cc.is_empty() =>
- nodes![
- small![" cc "],
- msg.cc.iter().enumerate().map(|(i, cc)| small![
- if i > 0 { ", " } else { "" },
- cc.name()
- .as_ref()
- .unwrap_or(&cc.addr().unwrap_or("(UNKNOWN)"))
- ]).collect::>()
- ]),
- br![],
- msg.timestamp.map(|ts| span![C!["header"], human_age(ts)]),
- ],
- ],
- ],
- div![
- C!["media-right"],
- span![
- C!["read-status"],
- i![
- C![
- "far",
- if is_unread {
- "fa-envelope"
- } else {
- "fa-envelope-open"
- },
- ],
- ev(Ev::Click, move |e| {
- e.stop_propagation();
- Msg::SetUnread(format!("id:{id}"), !is_unread)
- }),
- ],
- ],
- ],
+ div![
+ C!["header"],
+ if open {
+ render_open_header(&msg)
+ } else {
+ render_closed_header(&msg)
+ },
ev(Ev::Click, move |e| {
e.stop_propagation();
if open {
@@ -481,7 +588,7 @@ fn message_render(msg: &ShowThreadQueryThreadMessages, open: bool) -> Node
} else {
Msg::MessageExpand(expand_id)
}
- }),
+ })
],
IF!(open =>
div![