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.
This commit is contained in:
381
src-tauri/Cargo.lock
generated
381
src-tauri/Cargo.lock
generated
@@ -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"
|
||||
|
@@ -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"] }
|
||||
|
@@ -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};
|
||||
|
@@ -1,5 +1,4 @@
|
||||
pub mod agents;
|
||||
pub mod claude;
|
||||
pub mod mcp;
|
||||
pub mod screenshot;
|
||||
pub mod usage;
|
||||
|
@@ -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<String, String>` - 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<String>,
|
||||
full_page: bool,
|
||||
) -> Result<String, String> {
|
||||
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<String>,
|
||||
full_page: bool,
|
||||
) -> Result<String, String> {
|
||||
// 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 <body> 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 <body> 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<usize, String>` - The number of files deleted, or an error message
|
||||
#[tauri::command]
|
||||
pub async fn cleanup_screenshot_temp_files(
|
||||
older_than_minutes: Option<u64>,
|
||||
) -> Result<usize, String> {
|
||||
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::<chrono::Utc>::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)
|
||||
}
|
@@ -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");
|
||||
|
@@ -792,17 +792,7 @@ export const ClaudeCodeSession: React.FC<ClaudeCodeSessionProps> = ({
|
||||
// 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<ClaudeCodeSessionProps> = ({
|
||||
<WebviewPreview
|
||||
initialUrl={previewUrl}
|
||||
onClose={handleClosePreview}
|
||||
onScreenshot={handlePreviewScreenshot}
|
||||
isMaximized={isPreviewMaximized}
|
||||
onToggleMaximize={handleTogglePreviewMaximize}
|
||||
onUrlChange={handlePreviewUrlChange}
|
||||
@@ -1101,7 +1090,6 @@ export const ClaudeCodeSession: React.FC<ClaudeCodeSessionProps> = ({
|
||||
<WebviewPreview
|
||||
initialUrl={previewUrl}
|
||||
onClose={handleClosePreview}
|
||||
onScreenshot={handlePreviewScreenshot}
|
||||
isMaximized={isPreviewMaximized}
|
||||
onToggleMaximize={handleTogglePreviewMaximize}
|
||||
onUrlChange={handlePreviewUrlChange}
|
||||
|
@@ -7,7 +7,6 @@ import {
|
||||
X,
|
||||
Minimize2,
|
||||
Maximize2,
|
||||
Camera,
|
||||
Loader2,
|
||||
AlertCircle,
|
||||
Globe,
|
||||
@@ -17,7 +16,6 @@ import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { api } from "@/lib/api";
|
||||
// TODO: These imports will be used when implementing actual Tauri webview
|
||||
// import { getCurrentWebviewWindow } from "@tauri-apps/api/webviewWindow";
|
||||
// import { WebviewWindow } from "@tauri-apps/api/webviewWindow";
|
||||
@@ -31,10 +29,6 @@ interface WebviewPreviewProps {
|
||||
* Callback when close is clicked
|
||||
*/
|
||||
onClose: () => void;
|
||||
/**
|
||||
* Callback when screenshot is requested
|
||||
*/
|
||||
onScreenshot?: (imagePath: string) => void;
|
||||
/**
|
||||
* Whether the webview is maximized
|
||||
*/
|
||||
@@ -60,13 +54,11 @@ interface WebviewPreviewProps {
|
||||
* <WebviewPreview
|
||||
* initialUrl="http://localhost:3000"
|
||||
* onClose={() => setShowPreview(false)}
|
||||
* onScreenshot={(path) => attachImage(path)}
|
||||
* />
|
||||
*/
|
||||
const WebviewPreviewComponent: React.FC<WebviewPreviewProps> = ({
|
||||
initialUrl,
|
||||
onClose,
|
||||
onScreenshot,
|
||||
isMaximized = false,
|
||||
onToggleMaximize,
|
||||
onUrlChange,
|
||||
@@ -80,8 +72,6 @@ const WebviewPreviewComponent: React.FC<WebviewPreviewProps> = ({
|
||||
// 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<WebviewWindow | null>(null);
|
||||
@@ -181,39 +171,6 @@ const WebviewPreviewComponent: React.FC<WebviewPreviewProps> = ({
|
||||
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 (
|
||||
<div
|
||||
ref={containerRef}
|
||||
@@ -330,49 +287,11 @@ const WebviewPreviewComponent: React.FC<WebviewPreviewProps> = ({
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Screenshot Button */}
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={handleScreenshot}
|
||||
disabled={isCapturing || hasError}
|
||||
className="gap-2"
|
||||
>
|
||||
{isCapturing ? (
|
||||
<Loader2 className="h-4 w-4 animate-spin" />
|
||||
) : (
|
||||
<Camera className="h-4 w-4" />
|
||||
)}
|
||||
Send to Claude
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Webview Content */}
|
||||
<div className="flex-1 relative bg-background" ref={contentRef}>
|
||||
{/* Shutter Animation */}
|
||||
<AnimatePresence>
|
||||
{showShutterAnimation && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
transition={{ duration: 0.2 }}
|
||||
className="absolute inset-0 z-20 pointer-events-none"
|
||||
>
|
||||
<motion.div
|
||||
initial={{ borderWidth: 0 }}
|
||||
animate={{ borderWidth: 8 }}
|
||||
exit={{ borderWidth: 0 }}
|
||||
transition={{ duration: 0.3 }}
|
||||
className="absolute inset-0 border-white shadow-lg"
|
||||
style={{ boxShadow: 'inset 0 0 20px rgba(255, 255, 255, 0.8)' }}
|
||||
/>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
|
||||
{/* Loading Overlay */}
|
||||
<AnimatePresence>
|
||||
{isLoading && (
|
||||
|
@@ -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<string> {
|
||||
return await invoke<string>("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<number> {
|
||||
try {
|
||||
return await invoke<number>("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
|
||||
|
Reference in New Issue
Block a user