//! Clipboard copy button, shared by the join-code and watch-link actions. use std::cell::RefCell; use std::rc::Rc; use sycamore::prelude::*; /// A button that copies `text` to the clipboard and shows "Copied!" for a /// moment. `label` is the idle caption. #[component(inline_props)] pub fn CopyButton(text: String, label: String) -> View { let copied = create_signal(false); // Held so the reset timer is cancelled if the button is rebuilt (e.g. // another player joins) while the "Copied!" feedback is showing: // firing it afterwards would set a disposed signal and panic. let reset_timer: Rc>> = Rc::new(RefCell::new(None)); on_cleanup({ let reset_timer = reset_timer.clone(); move || { reset_timer.borrow_mut().take(); } }); let on_click = { let text = text.clone(); move |_| { if let Some(win) = web_sys::window() { let _ = win.navigator().clipboard().write_text(&text); } copied.set(true); *reset_timer.borrow_mut() = Some(gloo_timers::callback::Timeout::new( 1500, move || { copied.set(false); }, )); } }; view! { button(class="btn btn-outline-light", on:click=on_click) { (move || if copied.get() { "Copied!".to_string() } else { label.clone() }) } } }