feat(screenshot): implement area screenshot functionality and integrate with shortcut management
This commit is contained in:
5
frontend/src-tauri/Cargo.lock
generated
5
frontend/src-tauri/Cargo.lock
generated
@ -1,12 +1,13 @@
|
|||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 4
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "Haystack"
|
name = "Haystack"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.21.7",
|
"base64 0.21.7",
|
||||||
|
"chrono",
|
||||||
"cocoa",
|
"cocoa",
|
||||||
"notify",
|
"notify",
|
||||||
"serde",
|
"serde",
|
||||||
@ -536,8 +537,10 @@ checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"android-tzdata",
|
"android-tzdata",
|
||||||
"iana-time-zone",
|
"iana-time-zone",
|
||||||
|
"js-sys",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"serde",
|
"serde",
|
||||||
|
"wasm-bindgen",
|
||||||
"windows-link",
|
"windows-link",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ base64 = "0.21.7"
|
|||||||
tokio = { version = "1.36.0", features = ["full"] }
|
tokio = { version = "1.36.0", features = ["full"] }
|
||||||
tauri-plugin-store = "2.0.0-beta.12"
|
tauri-plugin-store = "2.0.0-beta.12"
|
||||||
tauri-plugin-http = "2.0.0-beta.12"
|
tauri-plugin-http = "2.0.0-beta.12"
|
||||||
|
chrono = "0.4"
|
||||||
|
|
||||||
[target."cfg(target_os = \"macos\")".dependencies]
|
[target."cfg(target_os = \"macos\")".dependencies]
|
||||||
cocoa = "0.26"
|
cocoa = "0.26"
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
mod commands;
|
mod commands;
|
||||||
mod shortcut;
|
pub mod screenshot;
|
||||||
|
pub mod shortcut;
|
||||||
mod state;
|
mod state;
|
||||||
mod utils;
|
pub mod utils;
|
||||||
mod window;
|
mod window;
|
||||||
|
|
||||||
use state::new_shared_watcher_state;
|
use state::new_shared_watcher_state;
|
||||||
|
53
frontend/src-tauri/src/screenshot.rs
Normal file
53
frontend/src-tauri/src/screenshot.rs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
use base64::{engine::general_purpose::STANDARD as BASE64, Engine as _};
|
||||||
|
use std::fs;
|
||||||
|
use std::process::Command;
|
||||||
|
use tauri::{AppHandle, Runtime};
|
||||||
|
|
||||||
|
/// Takes a screenshot of a selected area and returns the image data as base64
|
||||||
|
pub fn take_area_screenshot<R: Runtime>(app: &AppHandle<R>) -> Result<String, String> {
|
||||||
|
// Create a temporary file path
|
||||||
|
let temp_dir = std::env::temp_dir();
|
||||||
|
let timestamp = chrono::Local::now().format("%Y%m%d_%H%M%S");
|
||||||
|
let temp_file = temp_dir.join(format!("haystack_screenshot_{}.png", timestamp));
|
||||||
|
|
||||||
|
// Use screencapture command with -i flag for interactive selection
|
||||||
|
let output = Command::new("screencapture")
|
||||||
|
.arg("-i") // interactive selection
|
||||||
|
.arg("-x") // don't play sound
|
||||||
|
.arg("-o") // don't show cursor
|
||||||
|
.arg("-r") // don't add shadow
|
||||||
|
.arg(temp_file.to_str().unwrap())
|
||||||
|
.output()
|
||||||
|
.map_err(|e| format!("Failed to execute screencapture: {}", e))?;
|
||||||
|
|
||||||
|
if !output.status.success() {
|
||||||
|
return Err(format!(
|
||||||
|
"screencapture failed: {}",
|
||||||
|
String::from_utf8_lossy(&output.stderr)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the captured image
|
||||||
|
let contents =
|
||||||
|
fs::read(&temp_file).map_err(|e| format!("Failed to read screenshot file: {}", e))?;
|
||||||
|
|
||||||
|
// Convert to base64
|
||||||
|
let base64_string = BASE64.encode(&contents);
|
||||||
|
|
||||||
|
// Clean up the temporary file
|
||||||
|
if let Err(e) = fs::remove_file(&temp_file) {
|
||||||
|
println!("Warning: Failed to remove temporary screenshot file: {}", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log the base64 string (truncated for readability)
|
||||||
|
if base64_string.len() > 100 {
|
||||||
|
println!(
|
||||||
|
"Screenshot base64 (truncated): {}...",
|
||||||
|
&base64_string[..100]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
println!("Screenshot base64: {}", base64_string);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(base64_string)
|
||||||
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
use crate::screenshot::take_area_screenshot;
|
||||||
use tauri::App;
|
use tauri::App;
|
||||||
use tauri::AppHandle;
|
use tauri::AppHandle;
|
||||||
use tauri::Emitter;
|
use tauri::Emitter;
|
||||||
@ -200,6 +201,9 @@ fn register_shortcut_upon_start(
|
|||||||
// TODO: Implement screenshot functionality
|
// TODO: Implement screenshot functionality
|
||||||
println!("Screenshot shortcut pressed");
|
println!("Screenshot shortcut pressed");
|
||||||
}
|
}
|
||||||
|
if let Err(e) = take_area_screenshot(app) {
|
||||||
|
println!("Failed to take screenshot: {}", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.build(),
|
.build(),
|
||||||
@ -268,11 +272,12 @@ pub fn change_screenshot_shortcut<R: Runtime>(
|
|||||||
|
|
||||||
fn register_screenshot_shortcut<R: Runtime>(app: &AppHandle<R>, shortcut: Shortcut) {
|
fn register_screenshot_shortcut<R: Runtime>(app: &AppHandle<R>, shortcut: Shortcut) {
|
||||||
app.global_shortcut()
|
app.global_shortcut()
|
||||||
.on_shortcut(shortcut, move |_app, scut, event| {
|
.on_shortcut(shortcut, move |app, scut, event| {
|
||||||
if scut == &shortcut {
|
if scut == &shortcut {
|
||||||
if let ShortcutState::Pressed = event.state() {
|
if let ShortcutState::Pressed = event.state() {
|
||||||
// TODO: Implement screenshot functionality
|
if let Err(e) = take_area_screenshot(app) {
|
||||||
println!("Screenshot shortcut pressed");
|
println!("Failed to take screenshot: {}", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
Reference in New Issue
Block a user