use crate::hooks::use_signal::use_signal;
use std::cell::RefCell;
use std::time::{Duration, Instant};
thread_local! {
static LAST_ACTIVITY: RefCell<Instant> = RefCell::new(Instant::now());
}
pub fn record_activity() {
LAST_ACTIVITY.with(|last| {
*last.borrow_mut() = Instant::now();
});
}
pub fn idle_duration() -> Duration {
LAST_ACTIVITY.with(|last| last.borrow().elapsed())
}
pub fn is_idle(threshold: Duration) -> bool {
idle_duration() >= threshold
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct IdleState {
pub is_idle: bool,
pub idle_seconds: u64,
}
impl IdleState {
pub fn new(threshold: Duration) -> Self {
let duration = idle_duration();
Self {
is_idle: duration >= threshold,
idle_seconds: duration.as_secs(),
}
}
}
pub fn use_idle(threshold: Duration) -> bool {
let idle = use_signal(move || is_idle(threshold));
idle.get()
}
pub fn use_idle_state(threshold: Duration) -> IdleState {
let state = use_signal(move || IdleState::new(threshold));
state.get()
}
pub fn use_idle_seconds() -> u64 {
let seconds = use_signal(|| idle_duration().as_secs());
seconds.get()
}
#[derive(Debug, Clone)]
pub struct IdleConfig {
pub threshold: Duration,
pub repeat: bool,
pub repeat_interval: Duration,
}
impl Default for IdleConfig {
fn default() -> Self {
Self {
threshold: Duration::from_secs(60),
repeat: false,
repeat_interval: Duration::from_secs(10),
}
}
}
impl IdleConfig {
pub fn new(threshold: Duration) -> Self {
Self {
threshold,
..Default::default()
}
}
pub fn threshold(mut self, threshold: Duration) -> Self {
self.threshold = threshold;
self
}
pub fn repeat(mut self, repeat: bool) -> Self {
self.repeat = repeat;
self
}
pub fn repeat_interval(mut self, interval: Duration) -> Self {
self.repeat_interval = interval;
self
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_record_activity() {
record_activity();
let duration = idle_duration();
assert!(duration < Duration::from_secs(1));
}
#[test]
fn test_idle_duration() {
record_activity();
let duration = idle_duration();
assert!(duration.as_millis() < 100);
}
#[test]
fn test_is_idle() {
record_activity();
assert!(!is_idle(Duration::from_secs(1)));
}
#[test]
fn test_idle_state() {
record_activity();
let state = IdleState::new(Duration::from_secs(60));
assert!(!state.is_idle);
}
#[test]
fn test_idle_state_default() {
let state = IdleState::default();
assert!(!state.is_idle);
assert_eq!(state.idle_seconds, 0);
}
#[test]
fn test_idle_config() {
let config = IdleConfig::new(Duration::from_secs(30))
.repeat(true)
.repeat_interval(Duration::from_secs(5));
assert_eq!(config.threshold, Duration::from_secs(30));
assert!(config.repeat);
assert_eq!(config.repeat_interval, Duration::from_secs(5));
}
#[test]
fn test_use_idle_compiles() {
fn _test() {
let _ = use_idle(Duration::from_secs(30));
}
}
#[test]
fn test_use_idle_state_compiles() {
fn _test() {
let _ = use_idle_state(Duration::from_secs(30));
}
}
#[test]
fn test_use_idle_seconds_compiles() {
fn _test() {
let _ = use_idle_seconds();
}
}
}