use crate::bind::{Bind, MaybeSend};
#[must_use = "You should call .show() on this widget to render it"]
pub struct RefreshButton<'a, T, E> {
bind: &'a mut Bind<T, E>,
interval_secs: f64,
debounce_factor: f64,
text: String,
}
impl<'a, T, E> RefreshButton<'a, T, E> {
pub fn new(bind: &'a mut Bind<T, E>) -> Self {
Self {
bind,
interval_secs: 60.0,
debounce_factor: 4.0,
text: "🔄".to_string(),
}
}
pub const fn interval_secs(mut self, secs: f64) -> Self {
self.interval_secs = secs;
self
}
pub fn show<Fut>(self, ui: &mut egui::Ui, f: impl FnOnce() -> Fut) -> egui::Response
where
Fut: Future<Output = Result<T, E>> + MaybeSend + 'static,
T: MaybeSend + 'static,
E: MaybeSend + 'static,
{
let is_pending = self.bind.is_pending();
let resp = ui.add_enabled(!is_pending, egui::Button::new(self.text));
let diff = if self.bind.since_completed() > self.interval_secs / self.debounce_factor
&& resp.clicked()
&& !is_pending
{
self.bind.refresh(f());
-1.0
} else {
self.bind.request_every_sec(f, self.interval_secs)
};
let hover_text = if is_pending {
"Refreshing...".to_string()
} else if diff < 0.0 {
"Refreshing now!".to_string()
} else {
format!("Refreshing automatically in {diff:.0}s...")
};
resp.on_hover_text(hover_text)
}
}