diff --git a/rklipd/src/clipboard.rs b/rklipd/src/clipboard.rs index 121da97..1b99602 100644 --- a/rklipd/src/clipboard.rs +++ b/rklipd/src/clipboard.rs @@ -1,28 +1,27 @@ -use arboard::{Clipboard, ImageData}; -use image::{ExtendedColorType, ImageEncoder, codecs::png::PngEncoder}; +use arboard::Clipboard; use std::error::Error; use std::time::SystemTime; use uuid::Uuid; use crate::models::{ClipboardData, ClipboardEntry, Image}; -pub trait ImageDataExt { - fn to_png(&self) -> Result, Box>; -} - -impl ImageDataExt for ImageData<'_> { - fn to_png(&self) -> Result, Box> { - let mut buffer = Vec::new(); - let encoder = PngEncoder::new(&mut buffer); - encoder.write_image( - &self.bytes, - self.width as u32, - self.height as u32, - ExtendedColorType::Rgba8, - )?; - Ok(buffer) - } -} +// pub trait ImageDataExt { +// fn to_png(&self) -> Result, Box>; +// } +// +// impl ImageDataExt for ImageData<'_> { +// fn to_png(&self) -> Result, Box> { +// let mut buffer = Vec::new(); +// let encoder = PngEncoder::new(&mut buffer); +// encoder.write_image( +// &self.bytes, +// self.width as u32, +// self.height as u32, +// ExtendedColorType::Rgba8, +// )?; +// Ok(buffer) +// } +// } impl ClipboardEntry { pub fn new(clipboard: &mut Clipboard) -> Result> { @@ -32,7 +31,9 @@ impl ClipboardEntry { Ok(image) => { let id = Uuid::new_v4(); Some(ClipboardData::Image(Image { - bytes: Some(image.to_png()?), + raw_pixels: Some(image.bytes.into_owned()), + width: image.width as u32, + height: image.height as u32, id, })) } diff --git a/rklipd/src/database.rs b/rklipd/src/database.rs index 52496dd..5e97ba8 100644 --- a/rklipd/src/database.rs +++ b/rklipd/src/database.rs @@ -1,4 +1,6 @@ use crate::models::{ClipboardData, ClipboardEntry, Image}; +use image::codecs::png::PngEncoder; +use image::{ExtendedColorType, ImageEncoder}; use rusqlite::Connection; use std::error::Error; use std::fs; @@ -43,11 +45,17 @@ impl Database { let (entry_type, content) = match &entry.content { ClipboardData::Text(text) => ("text", text.clone()), ClipboardData::Image(img) => { - if let Some(bytes) = &img.bytes { - let img_path = Path::new(&self.dir_path) - .join("images") - .join(format!("{}.png", img.id)); - fs::write(&img_path, bytes)?; + if let Some(raw_pixels) = &img.raw_pixels { + let img_path = img.file_path(&self.dir_path); + + let file = fs::File::create(&img_path)?; + let encoder = PngEncoder::new(file); + encoder.write_image( + raw_pixels, + img.width, + img.height, + ExtendedColorType::Rgba8, + )?; } ("image", img.id.to_string()) } @@ -83,7 +91,12 @@ impl Database { ClipboardData::Text(content) } else { let id = Uuid::parse_str(&content)?; - ClipboardData::Image(Image { id, bytes: None }) + ClipboardData::Image(Image { + id, + raw_pixels: None, + width: 0, + height: 0, + }) }; entries.push(ClipboardEntry { diff --git a/rklipd/src/main.rs b/rklipd/src/main.rs index d57ef35..c5d7eac 100644 --- a/rklipd/src/main.rs +++ b/rklipd/src/main.rs @@ -1,3 +1,5 @@ +use std::sync::{Arc, Mutex}; + use crate::database::Database; use arboard::Clipboard; @@ -9,12 +11,11 @@ mod ws; fn main() -> Result<(), Box> { let clipboard = Clipboard::new()?; - let dir_path = "clipboard"; - let db = Database::init(dir_path)?; + let db = Arc::new(Mutex::new(Database::init(dir_path)?)); - // println!("{:#?}", db.read_history()); + // println!("{:#?}", db.lock().unwrap().read_history()); monitor::start(db, clipboard)?; diff --git a/rklipd/src/models.rs b/rklipd/src/models.rs index 037094b..bbfa4d0 100644 --- a/rklipd/src/models.rs +++ b/rklipd/src/models.rs @@ -17,7 +17,9 @@ pub enum ClipboardData { #[derive(Debug, Clone)] pub struct Image { - pub bytes: Option>, + pub raw_pixels: Option>, + pub width: u32, + pub height: u32, pub id: Uuid, } @@ -29,9 +31,6 @@ impl Image { } pub fn load_bytes(&self, dir_path: &str) -> io::Result> { - if let Some(b) = &self.bytes { - return Ok(b.clone()); - } fs::read(self.file_path(dir_path)) } } diff --git a/rklipd/src/monitor.rs b/rklipd/src/monitor.rs index 8bd973f..dc772e9 100644 --- a/rklipd/src/monitor.rs +++ b/rklipd/src/monitor.rs @@ -1,11 +1,12 @@ use crate::database::Database; use arboard::Clipboard; use std::error::Error; +use std::sync::{Arc, Mutex}; #[cfg(feature = "x11")] use crate::ws; #[cfg(feature = "x11")] -pub fn start(db: Database, clipboard: Clipboard) -> Result<(), Box> { +pub fn start(db: Arc>, clipboard: Clipboard) -> Result<(), Box> { ws::x11::start(db, clipboard)?; Ok(()) } @@ -13,12 +14,12 @@ pub fn start(db: Database, clipboard: Clipboard) -> Result<(), Box> { #[cfg(feature = "wayland")] use crate::ws; #[cfg(feature = "wayland")] -pub fn start(db: Database, clipboard: Clipboard) -> Result<(), Box> { +pub fn start(db: Arc>, clipboard: Clipboard) -> Result<(), Box> { ws::wayland::start(db, clipboard)?; Ok(()) } #[cfg(not(any(feature = "x11", feature = "wayland")))] -pub fn start(_db: Database, _clipboard: Clipboard) -> Result<(), Box> { +pub fn start(_db: Arc>, _clipboard: Clipboard) -> Result<(), Box> { Err("No window system feature enabled".into()) } diff --git a/rklipd/src/ws/wayland.rs b/rklipd/src/ws/wayland.rs index 58488d8..422e595 100644 --- a/rklipd/src/ws/wayland.rs +++ b/rklipd/src/ws/wayland.rs @@ -1,10 +1,14 @@ use crate::{database::Database, models::ClipboardEntry}; use arboard::Clipboard; use std::time::Duration; -use std::{error::Error, sync::mpsc::channel}; +use std::{ + error::Error, + sync::mpsc::channel, + sync::{Arc, Mutex}, +}; use wayland_clipboard_listener::{WlClipboardPasteStream, WlListenType}; -pub fn start(db: Database, mut clipboard: Clipboard) -> Result<(), Box> { +pub fn start(db: Arc>, mut clipboard: Clipboard) -> Result<(), Box> { let (tx, rx) = channel(); std::thread::spawn( @@ -26,18 +30,24 @@ pub fn start(db: Database, mut clipboard: Clipboard) -> Result<(), Box db.append(entry)?, - Err(e) => eprintln!("{}", e), + if let Ok(entry) = ClipboardEntry::new(&mut clipboard) { + let db_clone = Arc::clone(&db); + + std::thread::spawn(move || { + let db_lock = db_clone.lock().unwrap(); + + if let Err(e) = db_lock.append(entry) { + eprintln!("SQLite writing error: {}", e); + } else { + println!("SQLite edited!"); + } + }); } + + // match ClipboardEntry::new(&mut clipboard) { + // Ok(entry) => db.append(entry)?, + // Err(e) => eprintln!("{}", e), + // } } Ok(()) diff --git a/rklipd/src/ws/x11.rs b/rklipd/src/ws/x11.rs index 8db4a21..436cf37 100644 --- a/rklipd/src/ws/x11.rs +++ b/rklipd/src/ws/x11.rs @@ -1,12 +1,12 @@ +use crate::{database::Database, models::ClipboardEntry}; use arboard::Clipboard; use clipboard_master::{CallbackResult, ClipboardHandler, Master}; +use std::sync::{Arc, Mutex}; use std::{ error::Error, sync::mpsc::{Sender, channel}, }; -use crate::{database::Database, models::ClipboardEntry}; - pub struct Handler { pub clipboard_tx: Sender<()>, } @@ -20,7 +20,7 @@ impl ClipboardHandler for Handler { } } -pub fn start(db: Database, mut clipboard: Clipboard) -> Result<(), Box> { +pub fn start(db: Arc>, mut clipboard: Clipboard) -> Result<(), Box> { let (tx, rx) = channel(); let mut master = Master::new(Handler { clipboard_tx: tx })?; @@ -33,11 +33,15 @@ pub fn start(db: Database, mut clipboard: Clipboard) -> Result<(), Box