Skip to main content

chamber_vault/
autolock_service.rs

1// In a new file: crates/vault/src/autolock_service.rs
2use crate::autolock::{ActivityTracker, AutoLockConfig};
3use async_trait::async_trait;
4use std::sync::Arc;
5use tokio::sync::RwLock;
6use tokio::time::{Duration as TokioDuration, sleep};
7use tracing::{debug, info, warn};
8
9#[async_trait]
10pub trait AutoLockCallback: Send + Sync {
11    async fn on_auto_lock(&self) -> Result<(), Box<dyn std::error::Error + Send + Sync>>;
12}
13
14pub struct AutoLockService {
15    pub activity_tracker: ActivityTracker,
16    callback: Arc<dyn AutoLockCallback>,
17    is_running: Arc<RwLock<bool>>,
18}
19
20impl AutoLockService {
21    pub fn new(config: AutoLockConfig, callback: Arc<dyn AutoLockCallback>) -> Self {
22        Self {
23            activity_tracker: ActivityTracker::new(config),
24            callback,
25            is_running: Arc::new(RwLock::new(false)),
26        }
27    }
28
29    pub async fn start(&self) -> tokio::task::JoinHandle<()> {
30        let activity_tracker = self.activity_tracker.clone();
31        let callback = Arc::clone(&self.callback);
32        let is_running = Arc::clone(&self.is_running);
33
34        *is_running.write().await = true;
35
36        tokio::spawn(async move {
37            let check_interval = TokioDuration::from_secs(activity_tracker.get_config().check_interval_seconds);
38
39            info!("Auto-lock service started");
40
41            while *is_running.read().await {
42                if activity_tracker.should_auto_lock().await {
43                    info!("Auto-lock triggered due to inactivity");
44
45                    match callback.on_auto_lock().await {
46                        Ok(()) => {
47                            debug!("Auto-lock callback executed successfully");
48                        }
49                        Err(e) => {
50                            warn!("Auto-lock callback failed: {}", e);
51                        }
52                    }
53
54                    // Reset activity after locking to prevent immediate re-triggering
55                    activity_tracker.update_activity().await;
56                }
57
58                sleep(check_interval).await;
59            }
60
61            info!("Auto-lock service stopped");
62        })
63    }
64
65    pub async fn stop(&self) {
66        *self.is_running.write().await = false;
67    }
68
69    pub async fn update_activity(&self) {
70        self.activity_tracker.update_activity().await;
71    }
72
73    pub async fn get_time_until_lock(&self) -> Option<chrono::Duration> {
74        self.activity_tracker.time_until_lock().await
75    }
76
77    #[must_use]
78    pub const fn is_enabled(&self) -> bool {
79        self.activity_tracker.get_config().enabled
80    }
81}