added conver to png for every image

This commit is contained in:
pandadev 2024-07-17 00:27:57 +02:00
parent c67ed49c3d
commit 4e2dcc9df3
No known key found for this signature in database
GPG key ID: C39629DACB8E762F

View file

@ -1,20 +1,18 @@
use arboard::Clipboard;
use base64::engine::general_purpose::STANDARD; use base64::engine::general_purpose::STANDARD;
use base64::Engine; use base64::Engine;
use rand::distributions::Alphanumeric; use rand::distributions::Alphanumeric;
use rand::{thread_rng, Rng}; use rand::{thread_rng, Rng};
use rdev::{listen, simulate, EventType, Key}; use rdev::{simulate, EventType, Key};
use sqlx::SqlitePool; use sqlx::SqlitePool;
use std::sync::mpsc;
use std::thread; use std::thread;
use std::time::Duration; use std::time::Duration;
use tauri::Manager; use tauri::Manager;
use tokio::runtime::Runtime; use tokio::runtime::Runtime;
use url::Url; use url::Url;
use reqwest::Client; use reqwest::Client;
use arboard::Clipboard;
use regex::Regex; use regex::Regex;
use image::ImageFormat; use image::ImageFormat;
use image::DynamicImage;
use std::io::Cursor; use std::io::Cursor;
#[tauri::command] #[tauri::command]
@ -35,60 +33,69 @@ pub fn simulate_paste() {
} }
pub fn setup(app_handle: tauri::AppHandle) { pub fn setup(app_handle: tauri::AppHandle) {
let (tx, rx) = mpsc::channel();
let is_processing = std::sync::Arc::new(std::sync::Mutex::new(false)); let is_processing = std::sync::Arc::new(std::sync::Mutex::new(false));
std::thread::spawn({ std::thread::spawn({
let is_processing = std::sync::Arc::clone(&is_processing); let is_processing = std::sync::Arc::clone(&is_processing);
move || { move || {
listen(move |event| match event.event_type { let mut clipboard = Clipboard::new().unwrap();
EventType::KeyPress(Key::ControlLeft | Key::ControlRight) => { let mut last_text = String::new();
let _ = tx.send(true); let mut last_image = Vec::new();
}
EventType::KeyRelease(Key::KeyC) => { loop {
let mut is_processing = is_processing.lock().unwrap(); let mut is_processing = is_processing.lock().unwrap();
if rx.try_recv().is_ok() && !*is_processing { if !*is_processing {
*is_processing = true; *is_processing = true;
let pool = app_handle.state::<SqlitePool>(); let pool = app_handle.state::<SqlitePool>();
let rt = app_handle.state::<Runtime>(); let rt = app_handle.state::<Runtime>();
let mut clipboard = Clipboard::new().unwrap();
if let Ok(content) = clipboard.get_text() { if let Ok(content) = clipboard.get_text() {
if content != last_text {
last_text = content.clone();
rt.block_on(async { rt.block_on(async {
insert_content_if_not_exists(&pool, "text", content).await; insert_content_if_not_exists(&pool, "text", content, None).await;
}); });
} }
}
if let Ok(image) = clipboard.get_image() { if let Ok(image) = clipboard.get_image() {
let image_bytes = image.bytes.to_vec();
if image_bytes != last_image {
last_image = image_bytes.clone();
rt.block_on(async { rt.block_on(async {
let png_image = convert_to_png(image.bytes.to_vec()); match convert_to_png(image_bytes) {
Ok((png_image, image_name)) => {
let base64_image = STANDARD.encode(&png_image); let base64_image = STANDARD.encode(&png_image);
insert_content_if_not_exists(&pool, "image", base64_image).await; insert_content_if_not_exists(&pool, "image", base64_image, Some(image_name)).await;
}
Err(e) => {
println!("Failed to convert image to PNG: {}", e);
}
}
}); });
} }
}
*is_processing = false; *is_processing = false;
} }
thread::sleep(Duration::from_millis(100));
} }
EventType::KeyRelease(Key::ControlLeft | Key::ControlRight) => {
let mut is_processing = is_processing.lock().unwrap();
*is_processing = false;
}
_ => {}
})
.unwrap();
} }
}); });
} }
fn convert_to_png(image_bytes: Vec<u8>) -> Vec<u8> { fn convert_to_png(image_bytes: Vec<u8>) -> Result<(Vec<u8>, String), image::ImageError> {
let img = image::load_from_memory(&image_bytes).unwrap(); match image::guess_format(&image_bytes) {
Ok(format) => println!("Image format: {:?}", format),
Err(e) => println!("Failed to guess image format: {}", e),
}
let img = image::load_from_memory(&image_bytes)?;
let mut png_bytes: Vec<u8> = Vec::new(); let mut png_bytes: Vec<u8> = Vec::new();
img.write_to(&mut Cursor::new(&mut png_bytes), ImageFormat::Png).unwrap(); img.write_to(&mut Cursor::new(&mut png_bytes), ImageFormat::Png)?;
png_bytes let image_name = format!("{}.png", thread_rng().sample_iter(&Alphanumeric).take(10).map(char::from).collect::<String>());
Ok((png_bytes, image_name))
} }
async fn insert_content_if_not_exists(pool: &SqlitePool, content_type: &str, content: String) { async fn insert_content_if_not_exists(pool: &SqlitePool, content_type: &str, content: String, name: Option<String>) {
let last_content: Option<String> = sqlx::query_scalar( let last_content: Option<String> = sqlx::query_scalar(
"SELECT content FROM history WHERE content_type = ? ORDER BY timestamp DESC LIMIT 1", "SELECT content FROM history WHERE content_type = ? ORDER BY timestamp DESC LIMIT 1",
) )
@ -137,11 +144,12 @@ async fn insert_content_if_not_exists(pool: &SqlitePool, content_type: &str, con
None None
}; };
let _ = sqlx::query("INSERT INTO history (id, content_type, content, favicon) VALUES (?, ?, ?, ?)") let _ = sqlx::query("INSERT INTO history (id, content_type, content, favicon, name) VALUES (?, ?, ?, ?, ?)")
.bind(id) .bind(id)
.bind(content_type) .bind(content_type)
.bind(content) .bind(content)
.bind(favicon_base64) .bind(favicon_base64)
.bind(name)
.execute(pool) .execute(pool)
.await; .await;
} }