use crate::models::StickyNote; use crate::state::MemoryState; use arboard::Clipboard; use std::sync::Arc; use tokio::time::{Duration, sleep}; pub fn spawn_watcher(state: Arc) { tokio::spawn(async move { let mut last_text = String::new(); loop { sleep(Duration::from_millis(1000)).await; let is_enabled = { let watch = state.clipboard_watch_mode.read().await; *watch }; if !is_enabled { continue; } if let Ok(mut clipboard) = Clipboard::new() && let Ok(text) = clipboard.get_text() && text != last_text && !text.trim().is_empty() { last_text = text.clone(); let note = StickyNote { timestamp: std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .unwrap() .as_secs(), content: text.clone(), expires_at: None, }; state.code.sticky.modify(|notes| { notes.push(note.clone()); }); state.record_activity( "clipboard", "Auto-ingested clipboard content into sticky notes", Some(&text), ); // We use rebuild_index to index the new sticky note state.rebuild_index().await; } } }); } #[cfg(test)] mod tests { use super::*; use tempfile::tempdir; #[tokio::test] async fn test_spawn_watcher_lifecycle() { let dir = tempdir().unwrap(); let state = Arc::new(MemoryState::new(dir.path().to_str().unwrap())); // Set watch mode to disabled first *state.clipboard_watch_mode.write().await = false; spawn_watcher(state.clone()); tokio::time::sleep(Duration::from_millis(50)).await; // Enable watch mode *state.clipboard_watch_mode.write().await = true; tokio::time::sleep(Duration::from_millis(150)).await; } }