use parking_lot::Mutex;
use std::sync::Arc;
#[cfg(feature = "native")]
mod native;
#[cfg(not(feature = "native"))]
mod wasm_js;
pub type Callback = Box<dyn FnMut() + Send>;
#[derive(Default)]
pub(crate) struct Context {
pub(crate) callbacks: Arc<Mutex<Vec<Callback>>>,
}
#[derive(Clone)]
pub struct IdleManager {
context: Arc<Mutex<Context>>,
idle_timeout: u32,
#[cfg(not(feature = "native"))]
js_sender: Arc<Mutex<futures::channel::mpsc::Sender<wasm_js::JsMessage>>>,
#[cfg(feature = "native")]
running: Arc<std::sync::atomic::AtomicBool>,
#[cfg(feature = "native")]
event_sender: Arc<Mutex<futures::channel::mpsc::Sender<()>>>,
#[cfg(feature = "native")]
_drop_sender: Arc<Mutex<futures::channel::oneshot::Sender<()>>>,
}
impl IdleManager {
pub const DEFAULT_IDLE_TIMEOUT: u32 = 10 * 60 * 1000;
#[cfg(feature = "wasm-js")]
pub const DEFAULT_SCROLL_DEBOUNCE: u32 = 100;
pub fn new(options: Option<IdleManagerOptions>) -> Self {
#[cfg(feature = "native")]
{
Self::new_native(options)
}
#[cfg(not(feature = "native"))]
{
Self::new_wasm_js(options)
}
}
pub fn exit(&mut self) {
#[cfg(feature = "native")]
{
self.exit_native();
}
#[cfg(not(feature = "native"))]
{
self.exit_wasm_js();
}
}
pub fn reset_timer(&self) {
#[cfg(feature = "native")]
{
self.reset_timer_native();
}
#[cfg(not(feature = "native"))]
{
self.reset_timer_wasm_js();
}
}
pub fn register_callback<F>(&self, callback: F)
where
F: FnMut() + Send + 'static,
{
self.context
.lock()
.callbacks
.lock()
.push(Box::new(callback));
}
}
#[derive(Default, Clone, bon::Builder)]
pub struct IdleManagerOptions {
#[builder(field)]
pub on_idle: Arc<Mutex<Vec<Callback>>>,
pub idle_timeout: Option<u32>,
pub capture_scroll: Option<bool>,
pub scroll_debounce: Option<u32>,
}
impl std::fmt::Debug for IdleManagerOptions {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let callback_count = self.on_idle.lock().len();
f.debug_struct("IdleManagerOptions")
.field("on_idle", &format!("{} callbacks", callback_count))
.field("idle_timeout", &self.idle_timeout)
.field("capture_scroll", &self.capture_scroll)
.field("scroll_debounce", &self.scroll_debounce)
.finish()
}
}
#[allow(dead_code)]
impl<S: idle_manager_options_builder::State> IdleManagerOptionsBuilder<S> {
pub fn on_idle(self, value: fn()) -> Self {
self.on_idle
.lock()
.push(Box::new(value) as Box<dyn FnMut() + Send>);
self
}
}