raw img + background png convert
This commit is contained in:
@ -1,28 +1,27 @@
|
|||||||
use arboard::{Clipboard, ImageData};
|
use arboard::Clipboard;
|
||||||
use image::{ExtendedColorType, ImageEncoder, codecs::png::PngEncoder};
|
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::models::{ClipboardData, ClipboardEntry, Image};
|
use crate::models::{ClipboardData, ClipboardEntry, Image};
|
||||||
|
|
||||||
pub trait ImageDataExt {
|
// pub trait ImageDataExt {
|
||||||
fn to_png(&self) -> Result<Vec<u8>, Box<dyn Error>>;
|
// fn to_png(&self) -> Result<Vec<u8>, Box<dyn Error>>;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
impl ImageDataExt for ImageData<'_> {
|
// impl ImageDataExt for ImageData<'_> {
|
||||||
fn to_png(&self) -> Result<Vec<u8>, Box<dyn Error>> {
|
// fn to_png(&self) -> Result<Vec<u8>, Box<dyn Error>> {
|
||||||
let mut buffer = Vec::new();
|
// let mut buffer = Vec::new();
|
||||||
let encoder = PngEncoder::new(&mut buffer);
|
// let encoder = PngEncoder::new(&mut buffer);
|
||||||
encoder.write_image(
|
// encoder.write_image(
|
||||||
&self.bytes,
|
// &self.bytes,
|
||||||
self.width as u32,
|
// self.width as u32,
|
||||||
self.height as u32,
|
// self.height as u32,
|
||||||
ExtendedColorType::Rgba8,
|
// ExtendedColorType::Rgba8,
|
||||||
)?;
|
// )?;
|
||||||
Ok(buffer)
|
// Ok(buffer)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
impl ClipboardEntry {
|
impl ClipboardEntry {
|
||||||
pub fn new(clipboard: &mut Clipboard) -> Result<ClipboardEntry, Box<dyn Error>> {
|
pub fn new(clipboard: &mut Clipboard) -> Result<ClipboardEntry, Box<dyn Error>> {
|
||||||
@ -32,7 +31,9 @@ impl ClipboardEntry {
|
|||||||
Ok(image) => {
|
Ok(image) => {
|
||||||
let id = Uuid::new_v4();
|
let id = Uuid::new_v4();
|
||||||
Some(ClipboardData::Image(Image {
|
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,
|
id,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
use crate::models::{ClipboardData, ClipboardEntry, Image};
|
use crate::models::{ClipboardData, ClipboardEntry, Image};
|
||||||
|
use image::codecs::png::PngEncoder;
|
||||||
|
use image::{ExtendedColorType, ImageEncoder};
|
||||||
use rusqlite::Connection;
|
use rusqlite::Connection;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
@ -43,11 +45,17 @@ impl Database {
|
|||||||
let (entry_type, content) = match &entry.content {
|
let (entry_type, content) = match &entry.content {
|
||||||
ClipboardData::Text(text) => ("text", text.clone()),
|
ClipboardData::Text(text) => ("text", text.clone()),
|
||||||
ClipboardData::Image(img) => {
|
ClipboardData::Image(img) => {
|
||||||
if let Some(bytes) = &img.bytes {
|
if let Some(raw_pixels) = &img.raw_pixels {
|
||||||
let img_path = Path::new(&self.dir_path)
|
let img_path = img.file_path(&self.dir_path);
|
||||||
.join("images")
|
|
||||||
.join(format!("{}.png", img.id));
|
let file = fs::File::create(&img_path)?;
|
||||||
fs::write(&img_path, bytes)?;
|
let encoder = PngEncoder::new(file);
|
||||||
|
encoder.write_image(
|
||||||
|
raw_pixels,
|
||||||
|
img.width,
|
||||||
|
img.height,
|
||||||
|
ExtendedColorType::Rgba8,
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
("image", img.id.to_string())
|
("image", img.id.to_string())
|
||||||
}
|
}
|
||||||
@ -83,7 +91,12 @@ impl Database {
|
|||||||
ClipboardData::Text(content)
|
ClipboardData::Text(content)
|
||||||
} else {
|
} else {
|
||||||
let id = Uuid::parse_str(&content)?;
|
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 {
|
entries.push(ClipboardEntry {
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use crate::database::Database;
|
use crate::database::Database;
|
||||||
use arboard::Clipboard;
|
use arboard::Clipboard;
|
||||||
|
|
||||||
@ -9,12 +11,11 @@ mod ws;
|
|||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let clipboard = Clipboard::new()?;
|
let clipboard = Clipboard::new()?;
|
||||||
|
|
||||||
let dir_path = "clipboard";
|
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)?;
|
monitor::start(db, clipboard)?;
|
||||||
|
|
||||||
|
|||||||
@ -17,7 +17,9 @@ pub enum ClipboardData {
|
|||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Image {
|
pub struct Image {
|
||||||
pub bytes: Option<Vec<u8>>,
|
pub raw_pixels: Option<Vec<u8>>,
|
||||||
|
pub width: u32,
|
||||||
|
pub height: u32,
|
||||||
pub id: Uuid,
|
pub id: Uuid,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,9 +31,6 @@ impl Image {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_bytes(&self, dir_path: &str) -> io::Result<Vec<u8>> {
|
pub fn load_bytes(&self, dir_path: &str) -> io::Result<Vec<u8>> {
|
||||||
if let Some(b) = &self.bytes {
|
|
||||||
return Ok(b.clone());
|
|
||||||
}
|
|
||||||
fs::read(self.file_path(dir_path))
|
fs::read(self.file_path(dir_path))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,12 @@
|
|||||||
use crate::database::Database;
|
use crate::database::Database;
|
||||||
use arboard::Clipboard;
|
use arboard::Clipboard;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
#[cfg(feature = "x11")]
|
#[cfg(feature = "x11")]
|
||||||
use crate::ws;
|
use crate::ws;
|
||||||
#[cfg(feature = "x11")]
|
#[cfg(feature = "x11")]
|
||||||
pub fn start(db: Database, clipboard: Clipboard) -> Result<(), Box<dyn Error>> {
|
pub fn start(db: Arc<Mutex<Database>>, clipboard: Clipboard) -> Result<(), Box<dyn Error>> {
|
||||||
ws::x11::start(db, clipboard)?;
|
ws::x11::start(db, clipboard)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -13,12 +14,12 @@ pub fn start(db: Database, clipboard: Clipboard) -> Result<(), Box<dyn Error>> {
|
|||||||
#[cfg(feature = "wayland")]
|
#[cfg(feature = "wayland")]
|
||||||
use crate::ws;
|
use crate::ws;
|
||||||
#[cfg(feature = "wayland")]
|
#[cfg(feature = "wayland")]
|
||||||
pub fn start(db: Database, clipboard: Clipboard) -> Result<(), Box<dyn Error>> {
|
pub fn start(db: Arc<Mutex<Database>>, clipboard: Clipboard) -> Result<(), Box<dyn Error>> {
|
||||||
ws::wayland::start(db, clipboard)?;
|
ws::wayland::start(db, clipboard)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(any(feature = "x11", feature = "wayland")))]
|
#[cfg(not(any(feature = "x11", feature = "wayland")))]
|
||||||
pub fn start(_db: Database, _clipboard: Clipboard) -> Result<(), Box<dyn Error>> {
|
pub fn start(_db: Arc<Mutex<Database>>, _clipboard: Clipboard) -> Result<(), Box<dyn Error>> {
|
||||||
Err("No window system feature enabled".into())
|
Err("No window system feature enabled".into())
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,14 @@
|
|||||||
use crate::{database::Database, models::ClipboardEntry};
|
use crate::{database::Database, models::ClipboardEntry};
|
||||||
use arboard::Clipboard;
|
use arboard::Clipboard;
|
||||||
use std::time::Duration;
|
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};
|
use wayland_clipboard_listener::{WlClipboardPasteStream, WlListenType};
|
||||||
|
|
||||||
pub fn start(db: Database, mut clipboard: Clipboard) -> Result<(), Box<dyn Error>> {
|
pub fn start(db: Arc<Mutex<Database>>, mut clipboard: Clipboard) -> Result<(), Box<dyn Error>> {
|
||||||
let (tx, rx) = channel();
|
let (tx, rx) = channel();
|
||||||
|
|
||||||
std::thread::spawn(
|
std::thread::spawn(
|
||||||
@ -26,18 +30,24 @@ pub fn start(db: Database, mut clipboard: Clipboard) -> Result<(), Box<dyn Error
|
|||||||
|
|
||||||
for _ in rx {
|
for _ in rx {
|
||||||
println!("Clipboard update!");
|
println!("Clipboard update!");
|
||||||
// if let Ok(entry) = ClipboardEntry::new(&mut clipboard) {
|
if let Ok(entry) = ClipboardEntry::new(&mut clipboard) {
|
||||||
// if let Err(e) = db.append(entry) {
|
let db_clone = Arc::clone(&db);
|
||||||
// eprintln!("SQLite writing error: {}", e);
|
|
||||||
// } else {
|
std::thread::spawn(move || {
|
||||||
// println!("SQLite edited!");
|
let db_lock = db_clone.lock().unwrap();
|
||||||
// }
|
|
||||||
// }
|
if let Err(e) = db_lock.append(entry) {
|
||||||
//
|
eprintln!("SQLite writing error: {}", e);
|
||||||
match ClipboardEntry::new(&mut clipboard) {
|
} else {
|
||||||
Ok(entry) => db.append(entry)?,
|
println!("SQLite edited!");
|
||||||
Err(e) => eprintln!("{}", e),
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// match ClipboardEntry::new(&mut clipboard) {
|
||||||
|
// Ok(entry) => db.append(entry)?,
|
||||||
|
// Err(e) => eprintln!("{}", e),
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
|
use crate::{database::Database, models::ClipboardEntry};
|
||||||
use arboard::Clipboard;
|
use arboard::Clipboard;
|
||||||
use clipboard_master::{CallbackResult, ClipboardHandler, Master};
|
use clipboard_master::{CallbackResult, ClipboardHandler, Master};
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
use std::{
|
use std::{
|
||||||
error::Error,
|
error::Error,
|
||||||
sync::mpsc::{Sender, channel},
|
sync::mpsc::{Sender, channel},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{database::Database, models::ClipboardEntry};
|
|
||||||
|
|
||||||
pub struct Handler {
|
pub struct Handler {
|
||||||
pub clipboard_tx: Sender<()>,
|
pub clipboard_tx: Sender<()>,
|
||||||
}
|
}
|
||||||
@ -20,7 +20,7 @@ impl ClipboardHandler for Handler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start(db: Database, mut clipboard: Clipboard) -> Result<(), Box<dyn Error>> {
|
pub fn start(db: Arc<Mutex<Database>>, mut clipboard: Clipboard) -> Result<(), Box<dyn Error>> {
|
||||||
let (tx, rx) = channel();
|
let (tx, rx) = channel();
|
||||||
|
|
||||||
let mut master = Master::new(Handler { clipboard_tx: tx })?;
|
let mut master = Master::new(Handler { clipboard_tx: tx })?;
|
||||||
@ -33,11 +33,15 @@ pub fn start(db: Database, mut clipboard: Clipboard) -> Result<(), Box<dyn Error
|
|||||||
for _ in rx {
|
for _ in rx {
|
||||||
println!("Clipboard update!");
|
println!("Clipboard update!");
|
||||||
if let Ok(entry) = ClipboardEntry::new(&mut clipboard) {
|
if let Ok(entry) = ClipboardEntry::new(&mut clipboard) {
|
||||||
if let Err(e) = db.append(entry) {
|
let db_clone = Arc::clone(&db);
|
||||||
eprintln!("SQLite writing error: {}", e);
|
std::thread::spawn(move || {
|
||||||
} else {
|
let db_lock = db_clone.lock().unwrap();
|
||||||
// println!("SQLite edited!");
|
if let Err(e) = db_lock.append(entry) {
|
||||||
}
|
eprintln!("SQLite writing error: {}", e);
|
||||||
|
} else {
|
||||||
|
println!("SQLite edited!");
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user