mirror of
https://github.com/0PandaDEV/Qopy.git
synced 2025-04-21 21:24:05 +02:00
finally image support
This commit is contained in:
parent
bae359f1cf
commit
c67ed49c3d
9 changed files with 98 additions and 100 deletions
33
src-tauri/Cargo.lock
generated
33
src-tauri/Cargo.lock
generated
|
@ -2605,15 +2605,6 @@ dependencies = [
|
|||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_threads"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc"
|
||||
version = "0.2.7"
|
||||
|
@ -3224,14 +3215,12 @@ dependencies = [
|
|||
"arboard",
|
||||
"base64 0.22.1",
|
||||
"image 0.25.1",
|
||||
"log",
|
||||
"rand 0.8.5",
|
||||
"rdev",
|
||||
"regex",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"simplelog",
|
||||
"sqlx",
|
||||
"tauri",
|
||||
"tauri-build",
|
||||
|
@ -4010,17 +3999,6 @@ dependencies = [
|
|||
"quote",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simplelog"
|
||||
version = "0.12.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "16257adbfaef1ee58b1363bdc0664c9b8e1e30aed86049635fb5f147d065a9c0"
|
||||
dependencies = [
|
||||
"log",
|
||||
"termcolor",
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "0.3.11"
|
||||
|
@ -4854,15 +4832,6 @@ dependencies = [
|
|||
"utf-8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thin-slice"
|
||||
version = "0.1.1"
|
||||
|
@ -4918,9 +4887,7 @@ checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885"
|
|||
dependencies = [
|
||||
"deranged",
|
||||
"itoa 1.0.11",
|
||||
"libc",
|
||||
"num-conv",
|
||||
"num_threads",
|
||||
"powerfmt",
|
||||
"serde",
|
||||
"time-core",
|
||||
|
|
|
@ -10,7 +10,7 @@ rust-version = "1.70"
|
|||
tauri-build = { version = "2.0.0-beta.18", features = [] }
|
||||
|
||||
[dependencies]
|
||||
tauri = { version = "2.0.0-beta.23", features = ["unstable", "tray-icon", "image-png"] }
|
||||
tauri = { version = "2.0.0-beta.23", features = ["tray-icon", "image-png"] }
|
||||
tauri-plugin-sql = {version = "2.0.0-beta.8", features = ["sqlite"] }
|
||||
tauri-plugin-clipboard-manager = "2.1.0-beta.5"
|
||||
tauri-plugin-global-shortcut = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
|
||||
|
@ -27,6 +27,4 @@ arboard = "3.4.0"
|
|||
image = "0.25.1"
|
||||
reqwest = { version = "0.12.5", features = ["blocking"] }
|
||||
url = "2.5.2"
|
||||
log = "0.4"
|
||||
simplelog = "0.12.2"
|
||||
regex = "1"
|
|
@ -13,6 +13,9 @@ use url::Url;
|
|||
use reqwest::Client;
|
||||
use arboard::Clipboard;
|
||||
use regex::Regex;
|
||||
use image::ImageFormat;
|
||||
use image::DynamicImage;
|
||||
use std::io::Cursor;
|
||||
|
||||
#[tauri::command]
|
||||
pub fn simulate_paste() {
|
||||
|
@ -33,45 +36,58 @@ pub fn simulate_paste() {
|
|||
|
||||
pub fn setup(app_handle: tauri::AppHandle) {
|
||||
let (tx, rx) = mpsc::channel();
|
||||
let mut is_processing = false;
|
||||
let is_processing = std::sync::Arc::new(std::sync::Mutex::new(false));
|
||||
|
||||
std::thread::spawn(move || {
|
||||
listen(move |event| match event.event_type {
|
||||
EventType::KeyPress(Key::ControlLeft | Key::ControlRight) => {
|
||||
let _ = tx.send(true);
|
||||
}
|
||||
EventType::KeyRelease(Key::KeyC) => {
|
||||
if rx.try_recv().is_ok() && !is_processing {
|
||||
is_processing = true;
|
||||
let pool = app_handle.state::<SqlitePool>();
|
||||
let rt = app_handle.state::<Runtime>();
|
||||
|
||||
let mut clipboard = Clipboard::new().unwrap();
|
||||
|
||||
if let Ok(content) = clipboard.get_text() {
|
||||
rt.block_on(async {
|
||||
insert_content_if_not_exists(&pool, "text", content).await;
|
||||
});
|
||||
}
|
||||
|
||||
if let Ok(image) = clipboard.get_image() {
|
||||
rt.block_on(async {
|
||||
let base64_image = STANDARD.encode(&image.bytes);
|
||||
insert_content_if_not_exists(&pool, "image", base64_image).await;
|
||||
});
|
||||
}
|
||||
is_processing = false;
|
||||
std::thread::spawn({
|
||||
let is_processing = std::sync::Arc::clone(&is_processing);
|
||||
move || {
|
||||
listen(move |event| match event.event_type {
|
||||
EventType::KeyPress(Key::ControlLeft | Key::ControlRight) => {
|
||||
let _ = tx.send(true);
|
||||
}
|
||||
}
|
||||
EventType::KeyRelease(Key::ControlLeft | Key::ControlRight) => {
|
||||
is_processing = false;
|
||||
}
|
||||
_ => {}
|
||||
})
|
||||
.unwrap();
|
||||
EventType::KeyRelease(Key::KeyC) => {
|
||||
let mut is_processing = is_processing.lock().unwrap();
|
||||
if rx.try_recv().is_ok() && !*is_processing {
|
||||
*is_processing = true;
|
||||
let pool = app_handle.state::<SqlitePool>();
|
||||
let rt = app_handle.state::<Runtime>();
|
||||
|
||||
let mut clipboard = Clipboard::new().unwrap();
|
||||
|
||||
if let Ok(content) = clipboard.get_text() {
|
||||
rt.block_on(async {
|
||||
insert_content_if_not_exists(&pool, "text", content).await;
|
||||
});
|
||||
}
|
||||
|
||||
if let Ok(image) = clipboard.get_image() {
|
||||
rt.block_on(async {
|
||||
let png_image = convert_to_png(image.bytes.to_vec());
|
||||
let base64_image = STANDARD.encode(&png_image);
|
||||
insert_content_if_not_exists(&pool, "image", base64_image).await;
|
||||
});
|
||||
}
|
||||
*is_processing = false;
|
||||
}
|
||||
}
|
||||
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> {
|
||||
let img = image::load_from_memory(&image_bytes).unwrap();
|
||||
let mut png_bytes: Vec<u8> = Vec::new();
|
||||
img.write_to(&mut Cursor::new(&mut png_bytes), ImageFormat::Png).unwrap();
|
||||
png_bytes
|
||||
}
|
||||
|
||||
async fn insert_content_if_not_exists(pool: &SqlitePool, content_type: &str, content: String) {
|
||||
let last_content: Option<String> = sqlx::query_scalar(
|
||||
"SELECT content FROM history WHERE content_type = ? ORDER BY timestamp DESC LIMIT 1",
|
||||
|
|
|
@ -40,6 +40,13 @@ pub fn setup(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>> {
|
|||
.await
|
||||
.expect("Failed to create table");
|
||||
|
||||
sqlx::query(
|
||||
"CREATE INDEX IF NOT EXISTS idx_timestamp ON history (timestamp)"
|
||||
)
|
||||
.execute(&pool)
|
||||
.await
|
||||
.expect("Failed to create index");
|
||||
|
||||
if is_new_db {
|
||||
let id: String = thread_rng()
|
||||
.sample_iter(&Alphanumeric)
|
||||
|
|
|
@ -29,7 +29,7 @@ pub fn setup(app_handle: tauri::AppHandle) {
|
|||
println!("V key pressed");
|
||||
if meta_pressed {
|
||||
println!("Meta+V detected");
|
||||
let window = app_handle.get_window("main").unwrap();
|
||||
let window = app_handle.get_webview_window("main").unwrap();
|
||||
let is_visible = window.is_visible().unwrap();
|
||||
if is_visible {
|
||||
println!("Hiding window");
|
||||
|
|
|
@ -12,7 +12,7 @@ use tauri::Manager;
|
|||
use tauri::PhysicalPosition;
|
||||
use tauri_plugin_autostart::MacosLauncher;
|
||||
|
||||
fn center_window_on_current_monitor(window: &tauri::Window) {
|
||||
fn center_window_on_current_monitor(window: &tauri::WebviewWindow) {
|
||||
if let Some(monitor) = window.current_monitor().unwrap() {
|
||||
let monitor_size = monitor.size();
|
||||
let window_size = window.outer_size().unwrap();
|
||||
|
@ -43,9 +43,9 @@ fn main() {
|
|||
hotkeys::setup(app_handle.clone());
|
||||
tray::setup(app)?;
|
||||
database::setup(app)?;
|
||||
clipboard::setup(app_handle);
|
||||
clipboard::setup(app_handle.clone());
|
||||
|
||||
if let Some(window) = app.get_window("main") {
|
||||
if let Some(window) = app.get_webview_window("main") {
|
||||
center_window_on_current_monitor(&window);
|
||||
window.hide().unwrap();
|
||||
}
|
||||
|
@ -60,15 +60,12 @@ fn main() {
|
|||
Ok(())
|
||||
})
|
||||
.on_window_event(|app, event| match event {
|
||||
#[cfg(not(dev))]
|
||||
tauri::WindowEvent::Focused(false) => {
|
||||
println!("Window lost focus");
|
||||
if let Some(window) = app.get_window("main") {
|
||||
if let Some(window) = app.get_webview_window("main") {
|
||||
window.hide().unwrap();
|
||||
}
|
||||
}
|
||||
tauri::WindowEvent::Focused(true) => {
|
||||
println!("Window gained focus");
|
||||
}
|
||||
_ => {}
|
||||
})
|
||||
.invoke_handler(tauri::generate_handler![clipboard::simulate_paste])
|
||||
|
|
|
@ -5,7 +5,7 @@ use tauri::{
|
|||
};
|
||||
|
||||
pub fn setup(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let window = app.get_window("main").unwrap();
|
||||
let window = app.get_webview_window("main").unwrap();
|
||||
let window_clone_for_tray = window.clone();
|
||||
let window_clone_for_click = window.clone();
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue