1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
use std::time::Duration;
use wasm_bindgen::prelude::*;
use yew::prelude::*;
use yew::services::{Task, TimeoutService};
use crate::button::*;
use crate::form::*;
use crate::icon::*;
use crate::*;
#[derive(Clone, PartialEq, Properties)]
pub struct Props {
#[prop_or_default]
pub value: String,
#[prop_or_default]
pub readonly: bool,
}
pub enum Msg {
Copy,
Copied,
Reset,
}
const DEFAULT_MESSAGE: &'static str = "Copy to clipboard";
pub struct Clipboard {
props: Props,
link: ComponentLink<Self>,
message: &'static str,
task: Option<Box<dyn Task>>,
}
impl Component for Clipboard {
type Message = Msg;
type Properties = Props;
fn create(props: Self::Properties, link: ComponentLink<Self>) -> Self {
Self {
props,
link,
message: DEFAULT_MESSAGE,
task: None,
}
}
fn update(&mut self, msg: Self::Message) -> ShouldRender {
match msg {
Msg::Copy => self.do_copy(),
Msg::Copied => {
log::info!("Copied");
self.message = "Copied!";
self.task = Some(Box::new(TimeoutService::spawn(
Duration::from_secs(2),
self.link.callback(|_| Msg::Reset),
)));
}
Msg::Reset => {
self.message = DEFAULT_MESSAGE;
self.task.take();
}
}
true
}
fn change(&mut self, props: Self::Properties) -> ShouldRender {
if self.props != props {
self.props = props;
true
} else {
false
}
}
fn view(&self) -> Html {
html! {
<div class="pf-c-clipboard-copy">
<div class="pf-c-clipboard-copy__group">
<TextInput value=&self.props.value/>
<Tooltip text=self.message>
<Button variant=Variant::Control icon=Icon::Copy onclick=self.link.callback(|_|Msg::Copy)/>
</Tooltip>
</div>
</div>
}
}
}
impl Clipboard {
fn do_copy(&self) {
let s = self.props.value.clone();
let cb: Callback<()> = self.link.callback(|_| Msg::Copied);
wasm_bindgen_futures::spawn_local(async move {
match copy_to_clipboard(s).await {
Ok(_) => cb.emit(()),
Err(_) => {}
};
});
}
}
#[wasm_bindgen(inline_js="export function copy_to_clipboard(value) {return window.navigator.clipboard.writeText(value);}")]
#[rustfmt::skip]
extern "C" {
#[wasm_bindgen(catch)]
async fn copy_to_clipboard(value: String) -> Result<(), JsValue>;
}