Add copy to clipboard links to from/to/cc addresses

This commit is contained in:
Bill Thiede 2024-07-22 16:04:25 -07:00
parent 831466ddda
commit ad8fb77857
4 changed files with 85 additions and 31 deletions

4
web/.cargo/config.toml Normal file
View File

@ -0,0 +1,4 @@
[build]
rustflags = [ "--cfg=web_sys_unstable_apis" ]

View File

@ -36,6 +36,8 @@ wasm-opt = ['-Os']
[dependencies.web-sys] [dependencies.web-sys]
version = "0.3.58" version = "0.3.58"
features = [ features = [
"Clipboard",
"MediaQueryList", "MediaQueryList",
"Navigator",
"Window" "Window"
] ]

View File

@ -452,6 +452,17 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
} }
} }
Msg::MultiMsg(msgs) => msgs.into_iter().for_each(|msg| update(msg, model, orders)), Msg::MultiMsg(msgs) => msgs.into_iter().for_each(|msg| update(msg, model, orders)),
Msg::CopyToClipboard(text) => {
let clipboard = seed::window()
.navigator()
.clipboard()
.expect("couldn't get clipboard");
orders.perform_cmd(async move {
wasm_bindgen_futures::JsFuture::from(clipboard.write_text(&text))
.await
.expect("failed to copy to clipboard");
});
}
} }
} }
// `Model` describes our app state. // `Model` describes our app state.
@ -551,4 +562,6 @@ pub enum Msg {
MessageCollapse(String), MessageCollapse(String),
MessageExpand(String), MessageExpand(String),
MultiMsg(Vec<Msg>), MultiMsg(Vec<Msg>),
CopyToClipboard(String),
} }

View File

@ -6,7 +6,7 @@ use std::{
use chrono::{DateTime, Datelike, Duration, Local, Utc}; use chrono::{DateTime, Datelike, Duration, Local, Utc};
use human_format::{Formatter, Scales}; use human_format::{Formatter, Scales};
use itertools::Itertools; use itertools::Itertools;
use log::error; use log::{error, info};
use seed::{prelude::*, *}; use seed::{prelude::*, *};
use seed_hooks::{state_access::CloneState, topo, use_state}; use seed_hooks::{state_access::CloneState, topo, use_state};
@ -122,14 +122,16 @@ fn pretty_authors(authors: &str) -> impl Iterator<Item = Node<Msg>> + '_ {
if one_person { if one_person {
return Some(span![ return Some(span![
attrs! { attrs! {
At::Title => author.trim()}, At::Title => author.trim()
},
author author
]); ]);
} }
author.split_whitespace().nth(0).map(|first| { author.split_whitespace().nth(0).map(|first| {
span![ span![
attrs! { attrs! {
At::Title => author.trim()}, At::Title => author.trim()
},
first first
] ]
}) })
@ -516,7 +518,17 @@ fn render_open_header(msg: &ShowThreadQueryThreadMessages) -> Node<Msg> {
p![ p![
strong![from], strong![from],
br![], br![],
small![from_detail], small![
&from_detail,
" ",
from_detail.map(|detail| span![
i![C!["far", "fa-copy"]],
ev(Ev::Click, move |e| {
e.stop_propagation();
Msg::CopyToClipboard(detail.to_string())
})
])
],
table![ table![
IF!(!msg.to.is_empty() => IF!(!msg.to.is_empty() =>
tr![ tr![
@ -526,19 +538,31 @@ fn render_open_header(msg: &ShowThreadQueryThreadMessages) -> Node<Msg> {
msg.to.iter().enumerate().map(|(i, to)| msg.to.iter().enumerate().map(|(i, to)|
small![ small![
if i>0 { ", " }else { "" }, if i>0 { ", " }else { "" },
match to { {
ShowThreadQueryThreadMessagesTo { let to = match to {
name: Some(name), ShowThreadQueryThreadMessagesTo {
addr:Some(addr), name: Some(name),
} => format!("{name} <{addr}>"), addr:Some(addr),
ShowThreadQueryThreadMessagesTo { } => format!("{name} <{addr}>"),
name: Some(name), ShowThreadQueryThreadMessagesTo {
addr:None name: Some(name),
} => format!("{name}"), addr:None
ShowThreadQueryThreadMessagesTo { } => format!("{name}"),
addr: Some(addr), .. ShowThreadQueryThreadMessagesTo {
} => format!("{addr}"), addr: Some(addr), ..
_ => String::from("UNKNOWN"), } => format!("{addr}"),
_ => String::from("UNKNOWN"),
};
span![
&to, " ",
span![
i![C!["far", "fa-copy"]],
ev(Ev::Click, move |e| {
e.stop_propagation();
Msg::CopyToClipboard(to)
})
]
]
} }
]) ])
@ -551,21 +575,32 @@ fn render_open_header(msg: &ShowThreadQueryThreadMessages) -> Node<Msg> {
msg.cc.iter().enumerate().map(|(i, cc)| msg.cc.iter().enumerate().map(|(i, cc)|
small![ small![
if i>0 { ", " }else { "" }, if i>0 { ", " }else { "" },
match cc { {
ShowThreadQueryThreadMessagesCc { let cc = match cc {
name: Some(name), ShowThreadQueryThreadMessagesCc {
addr:Some(addr), name: Some(name),
} => format!("{name} <{addr}>"), addr:Some(addr),
ShowThreadQueryThreadMessagesCc { } => format!("{name} <{addr}>"),
name: Some(name), ShowThreadQueryThreadMessagesCc {
addr:None name: Some(name),
} => format!("{name}"), addr:None
ShowThreadQueryThreadMessagesCc { } => format!("{name}"),
addr: Some(addr), .. ShowThreadQueryThreadMessagesCc {
} => format!("<{addr}>"), addr: Some(addr), ..
_ => String::from("UNKNOWN"), } => format!("<{addr}>"),
_ => String::from("UNKNOWN"),
};
span![
&cc, " ",
span![
i![C!["far", "fa-copy"]],
ev(Ev::Click, move |e| {
e.stop_propagation();
Msg::CopyToClipboard(cc)
})
]
]
} }
]) ])
] ]
]), ]),