From dcc863c4514ac1d1f773fd35d3783097d3e1add6 Mon Sep 17 00:00:00 2001 From: zeefaad Date: Sun, 8 Mar 2026 18:57:28 +0100 Subject: [PATCH] uds ipc working --- rklipd/src/ipc.rs | 29 ++++++- src/app.rs | 23 +++++- src/ipc.rs | 14 ++++ src/main.rs | 196 +++++++++++++++++++++++++--------------------- src/ui.rs | 7 +- 5 files changed, 174 insertions(+), 95 deletions(-) diff --git a/rklipd/src/ipc.rs b/rklipd/src/ipc.rs index 57f6f4d..d0dc095 100644 --- a/rklipd/src/ipc.rs +++ b/rklipd/src/ipc.rs @@ -7,10 +7,10 @@ use std::os::unix::net::UnixListener; use std::path::Path; use std::sync::{Arc, Mutex}; -// --- LE CONTRAT (Protocole) --- #[derive(Serialize, Deserialize, Debug)] pub enum IpcRequest { GetHistory { limit: usize }, + SetClipboard { content: String }, } #[derive(Serialize, Deserialize, Debug)] @@ -63,6 +63,33 @@ pub fn start_server(db: Arc>, socket_path: &Path) { let response_json = serde_json::to_string(&response).unwrap(); let _ = stream.write_all(response_json.as_bytes()); } + IpcRequest::SetClipboard { content } => { + if let Ok(mut clipboard) = arboard::Clipboard::new() { + if content.ends_with(".jpg") || content.ends_with(".png") { + if let Some(proj_dirs) = directories::ProjectDirs::from( + "com", "zefad", "rklipd", + ) { + let img_path = proj_dirs + .data_dir() + .join("images") + .join(&content); + if let Ok(img) = image::open(&img_path) { + let rgba = img.into_rgba8(); + let img_data = arboard::ImageData { + width: rgba.width() as usize, + height: rgba.height() as usize, + bytes: std::borrow::Cow::Borrowed( + rgba.as_raw(), + ), + }; + let _ = clipboard.set_image(img_data); + } + } + } else { + let _ = clipboard.set_text(content); + } + } + } } } } diff --git a/src/app.rs b/src/app.rs index 9f6fa4b..274b13a 100644 --- a/src/app.rs +++ b/src/app.rs @@ -28,8 +28,14 @@ impl App { let mut list_state = ListState::default(); list_state.select(Some(0)); - let items = ipc::fetch_history(100) - .unwrap_or_else(|| vec!["rklipd deamon unaccessible".to_string()]); + let items = ipc::fetch_history(100).unwrap_or_default(); + + let mut list_state = ListState::default(); + if items.is_empty() { + list_state.select(None); + } else { + list_state.select(Some(0)); + } let picker = Picker::from_query_stdio().unwrap_or_else(|_| Picker::halfblocks()); @@ -175,6 +181,17 @@ impl App { } pub fn get_selected_item(&self) -> Option<&String> { - self.list_state.selected().map(|i| &self.filtered_items[i]) + self.list_state + .selected() + .and_then(|i| self.filtered_items.get(i)) + } + + pub fn sync_with_daemon(&mut self) { + if let Some(new_history) = crate::ipc::fetch_history(100) { + if self.all_items != new_history { + self.all_items = new_history; + self.update_search(); + } + } } } diff --git a/src/ipc.rs b/src/ipc.rs index e9a59e3..be0d8f5 100644 --- a/src/ipc.rs +++ b/src/ipc.rs @@ -5,6 +5,7 @@ use std::os::unix::net::UnixStream; #[derive(Serialize, Deserialize, Debug)] pub enum IpcRequest { GetHistory { limit: usize }, + SetClipboard { content: String }, } #[derive(Serialize, Deserialize, Debug)] @@ -35,3 +36,16 @@ pub fn fetch_history(limit: usize) -> Option> { None } + +pub fn set_clipboard(content: String) { + if let Some(base_dir) = directories::ProjectDirs::from("com", "zefad", "rklipd") { + let socket_path = base_dir.data_dir().join("rklip.sock"); + if let Ok(mut stream) = UnixStream::connect(&socket_path) { + let req = IpcRequest::SetClipboard { content }; + if let Ok(req_json) = serde_json::to_string(&req) { + let _ = stream.write_all(req_json.as_bytes()); + let _ = stream.shutdown(std::net::Shutdown::Write); + } + } + } +} diff --git a/src/main.rs b/src/main.rs index 79d6e5e..0f3e517 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,6 +11,7 @@ use crossterm::{ }; use ratatui::{Terminal, backend::CrosstermBackend}; use std::io; +use std::time::Duration; fn main() -> Result<(), Box> { enable_raw_mode()?; @@ -39,105 +40,120 @@ fn run_app(terminal: &mut Terminal>, app: &mut App) loop { terminal.draw(|f| ui::render(f, app))?; - if let Event::Key(key) = event::read()? { - match app.mode { - Mode::Normal => match key.code { - KeyCode::Char('j') => { - app.next(); - last_key_was_d = false; - } - KeyCode::Char('k') => { - app.previous(); - last_key_was_d = false; - } - KeyCode::Char('d') => { - if last_key_was_d { - app.delete_selected(); - last_key_was_d = false; - } else { - last_key_was_d = true; + if event::poll(Duration::from_millis(500))? { + if let Event::Key(key) = event::read()? { + match app.mode { + Mode::Normal => match key.code { + KeyCode::Enter => { + if let Some(selected) = app.get_selected_item() { + crate::ipc::set_clipboard(selected.clone()); + app.should_quit = true; + } } - last_key_was_g = false; - } - KeyCode::Char('u') => { - app.undo_delete(); - last_key_was_d = false; - } - KeyCode::Char('g') => { - if last_key_was_g { - if !app.filtered_items.is_empty() { - app.list_state.select(Some(0)); + KeyCode::Char('j') => { + app.next(); + last_key_was_d = false; + } + KeyCode::Char('k') => { + app.previous(); + last_key_was_d = false; + } + KeyCode::Char('d') => { + if last_key_was_d { + app.delete_selected(); + last_key_was_d = false; + } else { + last_key_was_d = true; } last_key_was_g = false; - } else { - last_key_was_g = true; } - last_key_was_d = false; - } - KeyCode::Char('G') => { - if !app.filtered_items.is_empty() { - app.list_state.select(Some(app.filtered_items.len() - 1)); + KeyCode::Char('u') => { + app.undo_delete(); + last_key_was_d = false; } - last_key_was_d = false; - } - KeyCode::Char(':') => { - app.mode = Mode::Command; - app.input_buffer.clear(); - last_key_was_d = false; - } - KeyCode::Char('/') => { - app.mode = Mode::Search; - app.input_buffer.clear(); - app.update_search(); - last_key_was_d = false; - } - KeyCode::Char('q') => { - app.should_quit = true; - } - _ => { - last_key_was_d = false; - } - }, - - Mode::Command => match key.code { - KeyCode::Esc => { - app.mode = Mode::Normal; - app.input_buffer.clear(); - app.update_search(); - } - KeyCode::Char(c) => app.input_buffer.push(c), - KeyCode::Backspace => { - app.input_buffer.pop(); - } - KeyCode::Enter => { - if app.input_buffer == "q" { + KeyCode::Char('g') => { + if last_key_was_g { + if !app.filtered_items.is_empty() { + app.list_state.select(Some(0)); + } + last_key_was_g = false; + } else { + last_key_was_g = true; + } + last_key_was_d = false; + } + KeyCode::Char('G') => { + if !app.filtered_items.is_empty() { + app.list_state.select(Some(app.filtered_items.len() - 1)); + } + last_key_was_d = false; + } + KeyCode::Char(':') => { + app.mode = Mode::Command; + app.input_buffer.clear(); + last_key_was_d = false; + } + KeyCode::Char('/') => { + app.mode = Mode::Search; + app.input_buffer.clear(); + app.update_search(); + last_key_was_d = false; + } + KeyCode::Char('q') => { app.should_quit = true; } - app.mode = Mode::Normal; - app.input_buffer.clear(); - app.update_search(); - } - _ => {} - }, + _ => { + last_key_was_d = false; + } + }, - Mode::Search => match key.code { - // ... ton code de recherche ... - KeyCode::Esc | KeyCode::Enter => { - app.mode = Mode::Normal; - app.input_buffer.clear(); - app.update_search(); - } - KeyCode::Char(c) => { - app.input_buffer.push(c); - app.update_search(); - } - KeyCode::Backspace => { - app.input_buffer.pop(); - app.update_search(); - } - _ => {} - }, + Mode::Command => match key.code { + KeyCode::Esc => { + app.mode = Mode::Normal; + app.input_buffer.clear(); + app.update_search(); + } + KeyCode::Char(c) => app.input_buffer.push(c), + KeyCode::Backspace => { + app.input_buffer.pop(); + } + KeyCode::Enter => { + if app.input_buffer == "q" { + app.should_quit = true; + } + app.mode = Mode::Normal; + app.input_buffer.clear(); + app.update_search(); + } + _ => {} + }, + + Mode::Search => match key.code { + KeyCode::Esc => { + app.mode = Mode::Normal; + app.input_buffer.clear(); + app.update_search(); + } + KeyCode::Enter => { + if let Some(selected) = app.get_selected_item() { + crate::ipc::set_clipboard(selected.clone()); + app.should_quit = true; + } + } + KeyCode::Char(c) => { + app.input_buffer.push(c); + app.update_search(); + } + KeyCode::Backspace => { + app.input_buffer.pop(); + app.update_search(); + } + _ => {} + }, + } } + } else { + app.sync_with_daemon(); } if app.should_quit { diff --git a/src/ui.rs b/src/ui.rs index 660ee45..ece3a40 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -1,4 +1,9 @@ -use crate::app::{App, Mode}; +use std::{io::Write, os::unix::net::UnixStream}; + +use crate::{ + app::{App, Mode}, + ipc::IpcRequest, +}; use ratatui::{ Frame, layout::{Constraint, Direction, Layout},