From 2d73a38222e0e68b9e5bc0c4a8038f4a4d0643d3 Mon Sep 17 00:00:00 2001 From: Mufeed VH Date: Wed, 2 Jul 2025 20:29:38 +0530 Subject: [PATCH] refactor: remove screenshot functionality and headless_chrome dependency Remove the screenshot capture system and associated UI components to simplify the codebase. - Remove screenshot.rs command module and related functionality - Remove headless_chrome dependency from Cargo.toml - Update Cargo.lock to reflect dependency changes - Remove screenshot handlers and UI from WebviewPreview component - Clean up screenshot-related API calls and imports - Remove camera icon and capture controls from preview interface This reduces bundle size and eliminates an underutilized feature. --- src-tauri/Cargo.lock | 381 +-------------------------- src-tauri/Cargo.toml | 1 - src-tauri/src/commands/agents.rs | 1 - src-tauri/src/commands/mod.rs | 1 - src-tauri/src/commands/screenshot.rs | 269 ------------------- src-tauri/src/main.rs | 6 +- src/components/ClaudeCodeSession.tsx | 14 +- src/components/WebviewPreview.tsx | 81 ------ src/lib/api.ts | 31 --- 9 files changed, 6 insertions(+), 779 deletions(-) delete mode 100644 src-tauri/src/commands/screenshot.rs diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index f51e4a3..41820dc 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -17,17 +17,6 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" -[[package]] -name = "aes" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures", -] - [[package]] name = "ahash" version = "0.8.12" @@ -345,20 +334,6 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" -[[package]] -name = "auto_generate_cdp" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6e1961a0d5d77969057eba90d448e610d3c439024d135d9dbd98e33ec973520" -dependencies = [ - "convert_case", - "proc-macro2", - "quote", - "serde", - "serde_json", - "ureq 2.12.1", -] - [[package]] name = "autocfg" version = "1.4.0" @@ -507,25 +482,6 @@ dependencies = [ "serde", ] -[[package]] -name = "bzip2" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49ecfb22d906f800d4fe833b6282cf4dc1c298f5057ca0b5445e5c209735ca47" -dependencies = [ - "bzip2-sys", -] - -[[package]] -name = "bzip2-sys" -version = "0.1.13+1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225bff33b2141874fe80d71e07d6eec4f85c5c216453dd96388240f96e1acc14" -dependencies = [ - "cc", - "pkg-config", -] - [[package]] name = "cairo-rs" version = "0.18.5" @@ -658,16 +614,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "cipher" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" -dependencies = [ - "crypto-common", - "inout", -] - [[package]] name = "claudia" version = "0.1.0" @@ -681,7 +627,6 @@ dependencies = [ "env_logger", "futures", "glob", - "headless_chrome", "libc", "log", "objc", @@ -773,12 +718,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "constant_time_eq" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" - [[package]] name = "convert_case" version = "0.4.0" @@ -873,21 +812,6 @@ dependencies = [ "libc", ] -[[package]] -name = "crc" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675" -dependencies = [ - "crc-catalog", -] - -[[package]] -name = "crc-catalog" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" - [[package]] name = "crc32fast" version = "1.4.2" @@ -994,24 +918,12 @@ dependencies = [ "syn 2.0.101", ] -[[package]] -name = "data-encoding" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" - [[package]] name = "data-url" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c297a1c74b71ae29df00c3e22dd9534821d60eb9af5a0192823fa2acea70c2a" -[[package]] -name = "deflate64" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da692b8d1080ea3045efaab14434d40468c3d8657e42abddfffca87b428f4c1b" - [[package]] name = "deranged" version = "0.4.0" @@ -1033,37 +945,6 @@ dependencies = [ "syn 2.0.101", ] -[[package]] -name = "derive_builder" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" -dependencies = [ - "derive_builder_macro", -] - -[[package]] -name = "derive_builder_core" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn 2.0.101", -] - -[[package]] -name = "derive_builder_macro" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" -dependencies = [ - "derive_builder_core", - "syn 2.0.101", -] - [[package]] name = "derive_more" version = "0.99.20" @@ -1085,16 +966,6 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "crypto-common", - "subtle", -] - -[[package]] -name = "directories" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16f5094c54661b38d03bd7e50df373292118db60b585c08a411c6d840017fe7d" -dependencies = [ - "dirs-sys 0.5.0", ] [[package]] @@ -2017,33 +1888,6 @@ dependencies = [ "hashbrown 0.14.5", ] -[[package]] -name = "headless_chrome" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c268ea01c2902b2acb382c1fae26818113dd661e0dba036a893f0ba40f00cdd8" -dependencies = [ - "anyhow", - "auto_generate_cdp", - "base64 0.22.1", - "derive_builder", - "directories", - "log", - "rand 0.9.1", - "regex", - "serde", - "serde_json", - "tempfile", - "thiserror 2.0.12", - "tungstenite", - "ureq 3.0.12", - "url", - "walkdir", - "which", - "winreg", - "zip 2.4.2", -] - [[package]] name = "heck" version = "0.4.1" @@ -2068,15 +1912,6 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest", -] - [[package]] name = "html5ever" version = "0.26.0" @@ -2171,7 +2006,7 @@ dependencies = [ "tokio", "tokio-rustls", "tower-service", - "webpki-roots 1.0.1", + "webpki-roots", ] [[package]] @@ -2407,15 +2242,6 @@ dependencies = [ "cfb", ] -[[package]] -name = "inout" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" -dependencies = [ - "generic-array", -] - [[package]] name = "ipnet" version = "2.11.0" @@ -2724,27 +2550,6 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" -[[package]] -name = "lzma-rs" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "297e814c836ae64db86b36cf2a557ba54368d03f6afcd7d947c266692f71115e" -dependencies = [ - "byteorder", - "crc", -] - -[[package]] -name = "lzma-sys" -version = "0.1.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fda04ab3764e6cde78b9974eec4f779acaba7c4e84b36eca3cf77c581b85d27" -dependencies = [ - "cc", - "libc", - "pkg-config", -] - [[package]] name = "mac" version = "0.1.1" @@ -3411,16 +3216,6 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" -[[package]] -name = "pbkdf2" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" -dependencies = [ - "digest", - "hmac", -] - [[package]] name = "percent-encoding" version = "2.3.1" @@ -4079,7 +3874,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", - "webpki-roots 1.0.1", + "webpki-roots", ] [[package]] @@ -4188,7 +3983,6 @@ version = "0.23.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7160e3e10bf4535308537f3c4e1641468cd0e485175d6163087c0393c7d46643" dependencies = [ - "log", "once_cell", "ring", "rustls-pki-types", @@ -4197,15 +3991,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "rustls-pemfile" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" -dependencies = [ - "rustls-pki-types", -] - [[package]] name = "rustls-pki-types" version = "1.12.0" @@ -4490,17 +4275,6 @@ dependencies = [ "stable_deref_trait", ] -[[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - [[package]] name = "sha2" version = "0.10.9" @@ -4580,17 +4354,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "socks" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0c3dbbd9ae980613c6dd8e28a9407b50509d3803b57624d5dfe8315218cd58b" -dependencies = [ - "byteorder", - "libc", - "winapi", -] - [[package]] name = "softbuffer" version = "0.4.6" @@ -5148,7 +4911,7 @@ dependencies = [ "tokio", "url", "windows-sys 0.60.2", - "zip 4.2.0", + "zip", ] [[package]] @@ -5641,23 +5404,6 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" -[[package]] -name = "tungstenite" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4793cb5e56680ecbb1d843515b23b6de9a75eb04b66643e256a396d43be33c13" -dependencies = [ - "bytes", - "data-encoding", - "http", - "httparse", - "log", - "rand 0.9.1", - "sha1", - "thiserror 2.0.12", - "utf-8", -] - [[package]] name = "typeid" version = "1.0.3" @@ -5740,53 +5486,6 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" -[[package]] -name = "ureq" -version = "2.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02d1a66277ed75f640d608235660df48c8e3c19f3b4edb6a263315626cc3c01d" -dependencies = [ - "base64 0.22.1", - "flate2", - "log", - "once_cell", - "rustls", - "rustls-pki-types", - "socks", - "url", - "webpki-roots 0.26.11", -] - -[[package]] -name = "ureq" -version = "3.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f0fde9bc91026e381155f8c67cb354bcd35260b2f4a29bcc84639f762760c39" -dependencies = [ - "base64 0.22.1", - "flate2", - "log", - "percent-encoding", - "rustls", - "rustls-pemfile", - "rustls-pki-types", - "ureq-proto", - "utf-8", - "webpki-roots 0.26.11", -] - -[[package]] -name = "ureq-proto" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59db78ad1923f2b1be62b6da81fe80b173605ca0d57f85da2e005382adf693f7" -dependencies = [ - "base64 0.22.1", - "http", - "httparse", - "log", -] - [[package]] name = "url" version = "2.5.4" @@ -6137,15 +5836,6 @@ dependencies = [ "system-deps", ] -[[package]] -name = "webpki-roots" -version = "0.26.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" -dependencies = [ - "webpki-roots 1.0.1", -] - [[package]] name = "webpki-roots" version = "1.0.1" @@ -6839,15 +6529,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" -[[package]] -name = "xz2" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388c44dc09d76f1536602ead6d325eb532f5c122f17782bd57fb47baeeb767e2" -dependencies = [ - "lzma-sys", -] - [[package]] name = "yoke" version = "0.8.0" @@ -6979,20 +6660,6 @@ name = "zeroize" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", -] [[package]] name = "zerotrie" @@ -7027,36 +6694,6 @@ dependencies = [ "syn 2.0.101", ] -[[package]] -name = "zip" -version = "2.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fabe6324e908f85a1c52063ce7aa26b68dcb7eb6dbc83a2d148403c9bc3eba50" -dependencies = [ - "aes", - "arbitrary", - "bzip2", - "constant_time_eq", - "crc32fast", - "crossbeam-utils", - "deflate64", - "displaydoc", - "flate2", - "getrandom 0.3.3", - "hmac", - "indexmap 2.9.0", - "lzma-rs", - "memchr", - "pbkdf2", - "sha1", - "thiserror 2.0.12", - "time", - "xz2", - "zeroize", - "zopfli", - "zstd", -] - [[package]] name = "zip" version = "4.2.0" @@ -7069,18 +6706,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "zopfli" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edfc5ee405f504cd4984ecc6f14d02d55cfda60fa4b689434ef4102aae150cd7" -dependencies = [ - "bumpalo", - "crc32fast", - "log", - "simd-adler32", -] - [[package]] name = "zstd" version = "0.13.3" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 0e5a058..7934db3 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -43,7 +43,6 @@ futures = "0.3" async-trait = "0.1" tempfile = "3" which = "7" -headless_chrome = { version = "1.0", features = ["fetch"] } sha2 = "0.10" zstd = "0.13" uuid = { version = "1.6", features = ["v4", "serde"] } diff --git a/src-tauri/src/commands/agents.rs b/src-tauri/src/commands/agents.rs index d4a60be..39e9b93 100644 --- a/src-tauri/src/commands/agents.rs +++ b/src-tauri/src/commands/agents.rs @@ -5,7 +5,6 @@ use reqwest; use rusqlite::{params, Connection, Result as SqliteResult}; use serde::{Deserialize, Serialize}; use serde_json::Value as JsonValue; -use std::path::PathBuf; use std::process::Stdio; use std::sync::Mutex; use tauri::{AppHandle, Emitter, Manager, State}; diff --git a/src-tauri/src/commands/mod.rs b/src-tauri/src/commands/mod.rs index aa947a5..2ee8365 100644 --- a/src-tauri/src/commands/mod.rs +++ b/src-tauri/src/commands/mod.rs @@ -1,5 +1,4 @@ pub mod agents; pub mod claude; pub mod mcp; -pub mod screenshot; pub mod usage; diff --git a/src-tauri/src/commands/screenshot.rs b/src-tauri/src/commands/screenshot.rs deleted file mode 100644 index 8fb6c53..0000000 --- a/src-tauri/src/commands/screenshot.rs +++ /dev/null @@ -1,269 +0,0 @@ -use headless_chrome::protocol::cdp::Page; -use headless_chrome::{Browser, LaunchOptions}; -use std::fs; -use std::time::Duration; -use tauri::AppHandle; - -/// Captures a screenshot of a URL using headless Chrome -/// -/// This function launches a headless Chrome browser, navigates to the specified URL, -/// and captures a screenshot of either the entire page or a specific element. -/// -/// # Arguments -/// * `app` - The Tauri application handle -/// * `url` - The URL to capture -/// * `selector` - Optional CSS selector for a specific element to capture -/// * `full_page` - Whether to capture the entire page or just the viewport -/// -/// # Returns -/// * `Result` - The path to the saved screenshot file, or an error message -#[tauri::command] -pub async fn capture_url_screenshot( - _app: AppHandle, - url: String, - selector: Option, - full_page: bool, -) -> Result { - log::info!( - "Capturing screenshot of URL: {}, selector: {:?}, full_page: {}", - url, - selector, - full_page - ); - - // Run the browser operations in a blocking task since headless_chrome is not async - let result = - tokio::task::spawn_blocking(move || capture_screenshot_sync(url, selector, full_page)) - .await - .map_err(|e| format!("Failed to spawn blocking task: {}", e))?; - - // Log the result of the headless Chrome capture before returning - match &result { - Ok(path) => log::info!("capture_url_screenshot returning path: {}", path), - Err(err) => log::error!("capture_url_screenshot encountered error: {}", err), - } - - result -} - -/// Synchronous helper function to capture screenshots using headless Chrome -fn capture_screenshot_sync( - url: String, - selector: Option, - full_page: bool, -) -> Result { - // Configure browser launch options - let launch_options = LaunchOptions { - headless: true, - window_size: Some((1920, 1080)), - ..Default::default() - }; - - // Launch the browser - let browser = - Browser::new(launch_options).map_err(|e| format!("Failed to launch browser: {}", e))?; - - // Create a new tab - let tab = browser - .new_tab() - .map_err(|e| format!("Failed to create new tab: {}", e))?; - - // Set a reasonable timeout for page navigation - tab.set_default_timeout(Duration::from_secs(30)); - - // Navigate to the URL - tab.navigate_to(&url) - .map_err(|e| format!("Failed to navigate to URL: {}", e))?; - - // Wait for the page to load - // Try to wait for network idle, but don't fail if it times out - let _ = tab.wait_until_navigated(); - - // Additional wait to ensure dynamic content loads - std::thread::sleep(Duration::from_millis(500)); - - // Wait explicitly for the element to exist – this often prevents - // "Unable to capture screenshot" CDP errors on some pages - if let Err(e) = tab.wait_for_element("body") { - log::warn!( - "Timed out waiting for element: {} – continuing anyway", - e - ); - } - - // Capture the screenshot - let screenshot_data = if let Some(selector) = selector { - // Wait for the element and capture it - log::info!("Waiting for element with selector: {}", selector); - - let element = tab - .wait_for_element(&selector) - .map_err(|e| format!("Failed to find element '{}': {}", selector, e))?; - - element - .capture_screenshot(Page::CaptureScreenshotFormatOption::Png) - .map_err(|e| format!("Failed to capture element screenshot: {}", e))? - } else { - // Capture the entire page or viewport - log::info!( - "Capturing {} screenshot", - if full_page { "full page" } else { "viewport" } - ); - - // Get the page dimensions for full page screenshot - let clip = if full_page { - // Execute JavaScript to get the full page dimensions - let dimensions = tab - .evaluate( - r#" - ({ - width: Math.max( - document.body.scrollWidth, - document.documentElement.scrollWidth, - document.body.offsetWidth, - document.documentElement.offsetWidth, - document.documentElement.clientWidth - ), - height: Math.max( - document.body.scrollHeight, - document.documentElement.scrollHeight, - document.body.offsetHeight, - document.documentElement.offsetHeight, - document.documentElement.clientHeight - ) - }) - "#, - false, - ) - .map_err(|e| format!("Failed to get page dimensions: {}", e))?; - - // Extract dimensions from the result - let width = dimensions - .value - .as_ref() - .and_then(|v| v.as_object()) - .and_then(|obj| obj.get("width")) - .and_then(|v| v.as_f64()) - .unwrap_or(1920.0); - - let height = dimensions - .value - .as_ref() - .and_then(|v| v.as_object()) - .and_then(|obj| obj.get("height")) - .and_then(|v| v.as_f64()) - .unwrap_or(1080.0); - - Some(Page::Viewport { - x: 0.0, - y: 0.0, - width, - height, - scale: 1.0, - }) - } else { - None - }; - - let capture_result = tab.capture_screenshot( - Page::CaptureScreenshotFormatOption::Png, - None, - clip.clone(), - full_page, // capture_beyond_viewport only makes sense for full page - ); - - match capture_result { - Ok(data) => data, - Err(err) => { - // Retry once with capture_beyond_viewport=true which works around some Chromium bugs - log::warn!( - "Initial screenshot attempt failed: {}. Retrying with capture_beyond_viewport=true", - err - ); - - tab.capture_screenshot(Page::CaptureScreenshotFormatOption::Png, None, clip, true) - .map_err(|e| format!("Failed to capture screenshot after retry: {}", e))? - } - } - }; - - // Save to temporary file - let temp_dir = std::env::temp_dir(); - let timestamp = chrono::Utc::now().timestamp_millis(); - let filename = format!("claudia_screenshot_{}.png", timestamp); - let file_path = temp_dir.join(filename); - - fs::write(&file_path, screenshot_data) - .map_err(|e| format!("Failed to save screenshot: {}", e))?; - - // Log the screenshot path prominently - println!("═══════════════════════════════════════════════════════════════"); - println!("📸 SCREENSHOT SAVED SUCCESSFULLY!"); - println!("📁 Location: {}", file_path.display()); - println!("═══════════════════════════════════════════════════════════════"); - - log::info!("Screenshot saved to: {:?}", file_path); - - Ok(file_path.to_string_lossy().to_string()) -} - -/// Cleans up old screenshot files from the temporary directory -/// -/// This function removes screenshot files older than the specified number of minutes -/// to prevent accumulation of temporary files. -/// -/// # Arguments -/// * `older_than_minutes` - Remove files older than this many minutes (default: 60) -/// -/// # Returns -/// * `Result` - The number of files deleted, or an error message -#[tauri::command] -pub async fn cleanup_screenshot_temp_files( - older_than_minutes: Option, -) -> Result { - let minutes = older_than_minutes.unwrap_or(60); - log::info!( - "Cleaning up screenshot files older than {} minutes", - minutes - ); - - let temp_dir = std::env::temp_dir(); - let cutoff_time = chrono::Utc::now() - chrono::Duration::minutes(minutes as i64); - let mut deleted_count = 0; - - // Read directory entries - let entries = - fs::read_dir(&temp_dir).map_err(|e| format!("Failed to read temp directory: {}", e))?; - - for entry in entries { - if let Ok(entry) = entry { - let path = entry.path(); - - // Check if it's a claudia screenshot file - if let Some(filename) = path.file_name() { - if let Some(filename_str) = filename.to_str() { - if filename_str.starts_with("claudia_screenshot_") - && filename_str.ends_with(".png") - { - // Check file age - if let Ok(metadata) = fs::metadata(&path) { - if let Ok(modified) = metadata.modified() { - let modified_time = chrono::DateTime::::from(modified); - if modified_time < cutoff_time { - // Delete the file - if fs::remove_file(&path).is_ok() { - deleted_count += 1; - log::debug!("Deleted old screenshot: {:?}", path); - } - } - } - } - } - } - } - } - } - - log::info!("Cleaned up {} old screenshot files", deleted_count); - Ok(deleted_count) -} diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 9151f1b..5b330e3 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -33,7 +33,7 @@ use commands::mcp::{ mcp_read_project_config, mcp_remove, mcp_reset_project_choices, mcp_save_project_config, mcp_serve, mcp_test_connection, }; -use commands::screenshot::{capture_url_screenshot, cleanup_screenshot_temp_files}; + use commands::usage::{ get_session_stats, get_usage_by_date_range, get_usage_details, get_usage_stats, }; @@ -160,9 +160,7 @@ fn main() { mcp_reset_project_choices, mcp_get_server_status, mcp_read_project_config, - mcp_save_project_config, - capture_url_screenshot, - cleanup_screenshot_temp_files + mcp_save_project_config ]) .run(tauri::generate_context!()) .expect("error while running tauri application"); diff --git a/src/components/ClaudeCodeSession.tsx b/src/components/ClaudeCodeSession.tsx index 89f554c..c00c5d4 100644 --- a/src/components/ClaudeCodeSession.tsx +++ b/src/components/ClaudeCodeSession.tsx @@ -792,17 +792,7 @@ export const ClaudeCodeSession: React.FC = ({ // Keep the previewUrl so it can be restored when reopening }; - const handlePreviewScreenshot = async (imagePath: string) => { - console.log("Screenshot captured:", imagePath); - - // Add the screenshot to the floating prompt input - if (floatingPromptRef.current) { - floatingPromptRef.current.addImage(imagePath); - - // Show a subtle animation/feedback that the image was added - // You could add a toast notification here if desired - } - }; + const handlePreviewUrlChange = (url: string) => { console.log('[ClaudeCodeSession] Preview URL changed to:', url); @@ -951,7 +941,6 @@ export const ClaudeCodeSession: React.FC = ({ = ({ void; - /** - * Callback when screenshot is requested - */ - onScreenshot?: (imagePath: string) => void; /** * Whether the webview is maximized */ @@ -60,13 +54,11 @@ interface WebviewPreviewProps { * setShowPreview(false)} - * onScreenshot={(path) => attachImage(path)} * /> */ const WebviewPreviewComponent: React.FC = ({ initialUrl, onClose, - onScreenshot, isMaximized = false, onToggleMaximize, onUrlChange, @@ -80,8 +72,6 @@ const WebviewPreviewComponent: React.FC = ({ // TODO: These will be implemented with actual webview navigation // const [canGoBack, setCanGoBack] = useState(false); // const [canGoForward, setCanGoForward] = useState(false); - const [isCapturing, setIsCapturing] = useState(false); - const [showShutterAnimation, setShowShutterAnimation] = useState(false); // TODO: These will be used for actual Tauri webview implementation // const webviewRef = useRef(null); @@ -181,39 +171,6 @@ const WebviewPreviewComponent: React.FC = ({ navigate(initialUrl); }; - const handleScreenshot = async () => { - if (isCapturing || !currentUrl) return; - - try { - setIsCapturing(true); - setShowShutterAnimation(true); - - // Wait for shutter animation to start - await new Promise(resolve => setTimeout(resolve, 100)); - - // Capture the current URL using headless Chrome - const filePath = await api.captureUrlScreenshot( - currentUrl, - null, // No specific selector - capture the whole viewport - false // Not full page, just viewport - ); - - console.log("Screenshot captured and saved to:", filePath); - - // Continue shutter animation - await new Promise(resolve => setTimeout(resolve, 200)); - setShowShutterAnimation(false); - - // Trigger callback with animation - onScreenshot?.(filePath); - } catch (err) { - console.error("Failed to capture screenshot:", err); - setShowShutterAnimation(false); - } finally { - setIsCapturing(false); - } - }; - return (
= ({ )}
- - {/* Screenshot Button */} - {/* Webview Content */}
- {/* Shutter Animation */} - - {showShutterAnimation && ( - - - - )} - - {/* Loading Overlay */} {isLoading && ( diff --git a/src/lib/api.ts b/src/lib/api.ts index 56a1e87..a74256b 100644 --- a/src/lib/api.ts +++ b/src/lib/api.ts @@ -1481,38 +1481,7 @@ export const api = { } }, - /** - * Captures a screenshot of a specific region in the window - * @param url - The URL to capture - * @param selector - Optional selector to capture - * @param fullPage - Whether to capture the full page - * @returns Promise resolving to the path of the saved screenshot - */ - async captureUrlScreenshot( - url: string, - selector?: string | null, - fullPage: boolean = false - ): Promise { - return await invoke("capture_url_screenshot", { - url, - selector, - fullPage, - }); - }, - /** - * Cleans up old screenshot files from the temporary directory - * @param olderThanMinutes - Remove files older than this many minutes (default: 60) - * @returns Promise resolving to the number of files deleted - */ - async cleanupScreenshotTempFiles(olderThanMinutes?: number): Promise { - try { - return await invoke("cleanup_screenshot_temp_files", { olderThanMinutes }); - } catch (error) { - console.error("Failed to cleanup screenshot files:", error); - throw error; - } - }, /** * List all available Claude installations on the system