diff --git a/Cargo.lock b/Cargo.lock index 34a48f2..7f2b269 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,97 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "ab_glyph" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01c0457472c38ea5bd1c3b5ada5e368271cb550be7a4ca4a0b4634e9913f6cc2" +dependencies = [ + "ab_glyph_rasterizer", + "owned_ttf_parser", +] + +[[package]] +name = "ab_glyph_rasterizer" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "366ffbaa4442f4684d91e2cd7c5ea7c4ed8add41959a31447066e279e432b618" + +[[package]] +name = "accesskit" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74a4b14f3d99c1255dcba8f45621ab1a2e7540a0009652d33989005a4d0bfc6b" +dependencies = [ + "enumn", + "serde", +] + +[[package]] +name = "accesskit_consumer" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c17cca53c09fbd7288667b22a201274b9becaa27f0b91bf52a526db95de45e6" +dependencies = [ + "accesskit", +] + +[[package]] +name = "accesskit_macos" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd3b6ae1eabbfbced10e840fd3fce8a93ae84f174b3e4ba892ab7bcb42e477a7" +dependencies = [ + "accesskit", + "accesskit_consumer", + "objc2 0.3.0-beta.3.patch-leaks.3", + "once_cell", +] + +[[package]] +name = "accesskit_unix" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09f46c18d99ba61ad7123dd13eeb0c104436ab6af1df6a1cd8c11054ed394a08" +dependencies = [ + "accesskit", + "accesskit_consumer", + "async-channel 2.5.0", + "async-once-cell", + "atspi", + "futures-lite 1.13.0", + "once_cell", + "serde", + "zbus", +] + +[[package]] +name = "accesskit_windows" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afcae27ec0974fc7c3b0b318783be89fd1b2e66dd702179fe600166a38ff4a0b" +dependencies = [ + "accesskit", + "accesskit_consumer", + "once_cell", + "paste", + "static_assertions", + "windows 0.48.0", +] + +[[package]] +name = "accesskit_winit" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5284218aca17d9e150164428a0ebc7b955f70e3a9a78b4c20894513aabf98a67" +dependencies = [ + "accesskit", + "accesskit_macos", + "accesskit_unix", + "accesskit_windows", + "winit", +] + [[package]] name = "adler2" version = "2.0.1" @@ -26,7 +117,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ "cfg-if", + "getrandom 0.3.4", "once_cell", + "serde", "version_check", "zerocopy", ] @@ -41,19 +134,49 @@ dependencies = [ ] [[package]] -name = "alloc-no-stdlib" -version = "2.0.4" +name = "aligned" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" +checksum = "ee4508988c62edf04abd8d92897fca0c2995d907ce1dfeaf369dac3716a40685" +dependencies = [ + "as-slice", +] [[package]] -name = "alloc-stdlib" +name = "aligned-vec" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b" +dependencies = [ + "equator", +] + +[[package]] +name = "android-activity" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee91c0c2905bae44f84bfa4e044536541df26b7703fd0888deeb9060fcc44289" +dependencies = [ + "android-properties", + "bitflags 2.13.0", + "cc", + "cesu8", + "jni 0.21.1", + "jni-sys 0.3.1", + "libc", + "log", + "ndk", + "ndk-context", + "ndk-sys", + "num_enum", + "thiserror 1.0.69", +] + +[[package]] +name = "android-properties" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" -dependencies = [ - "alloc-no-stdlib", -] +checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" [[package]] name = "android_system_properties" @@ -70,6 +193,76 @@ version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" +[[package]] +name = "arbitrary" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" + +[[package]] +name = "arboard" +version = "3.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0348a1c054491f4bfe6ab86a7b6ab1e44e45d899005de92f58b3df180b36ddaf" +dependencies = [ + "clipboard-win", + "log", + "objc2 0.6.4", + "objc2-app-kit 0.3.2", + "objc2-foundation 0.3.2", + "parking_lot", + "percent-encoding", + "windows-sys 0.60.2", + "x11rb", +] + +[[package]] +name = "arg_enum_proc_macro" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "as-raw-xcb-connection" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b" + +[[package]] +name = "as-slice" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "ash" +version = "0.37.3+1.3.251" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39e9c3835d686b0a6084ab4234fcd1b07dbf6e4767dce60874b12356a25ecd4a" +dependencies = [ + "libloading 0.7.4", +] + [[package]] name = "async-broadcast" version = "0.5.1" @@ -214,6 +407,12 @@ dependencies = [ "url", ] +[[package]] +name = "async-once-cell" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288f83726785267c6f2ef073a3d83dc3f9b81464e9f99898240cced85fce35a" + [[package]] name = "async-process" version = "1.8.1" @@ -303,35 +502,60 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "atk" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241b621213072e993be4f6f3a9e4b45f65b7e6faad43001be957184b7bb1824b" -dependencies = [ - "atk-sys", - "glib", - "libc", -] - -[[package]] -name = "atk-sys" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5e48b684b0ca77d2bbadeef17424c2ea3c897d44d566a1617e7e8f30614d086" -dependencies = [ - "glib-sys", - "gobject-sys", - "libc", - "system-deps", -] - [[package]] name = "atomic-waker" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" +[[package]] +name = "atspi" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6059f350ab6f593ea00727b334265c4dfc7fd442ee32d264794bd9bdc68e87ca" +dependencies = [ + "atspi-common", + "atspi-connection", + "atspi-proxies", +] + +[[package]] +name = "atspi-common" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92af95f966d2431f962bc632c2e68eda7777330158bf640c4af4249349b2cdf5" +dependencies = [ + "enumflags2", + "serde", + "static_assertions", + "zbus", + "zbus_names", + "zvariant", +] + +[[package]] +name = "atspi-connection" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c65e7d70f86d4c0e3b2d585d9bf3f979f0b19d635a336725a88d279f76b939" +dependencies = [ + "atspi-common", + "atspi-proxies", + "futures-lite 1.13.0", + "zbus", +] + +[[package]] +name = "atspi-proxies" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6495661273703e7a229356dcbe8c8f38223d697aacfaf0e13590a9ac9977bb52" +dependencies = [ + "atspi-common", + "serde", + "zbus", +] + [[package]] name = "autocfg" version = "1.5.1" @@ -339,31 +563,68 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] -name = "base64" -version = "0.21.7" +name = "av-scenechange" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +checksum = "0f321d77c20e19b92c39e7471cf986812cbb46659d2af674adc4331ef3f18394" +dependencies = [ + "aligned", + "anyhow", + "arg_enum_proc_macro", + "arrayvec", + "log", + "num-rational", + "num-traits", + "pastey", + "rayon", + "thiserror 2.0.18", + "v_frame", + "y4m", +] [[package]] -name = "base64" -version = "0.22.1" +name = "av1-grain" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +checksum = "8cfddb07216410377231960af4fcab838eaa12e013417781b78bd95ee22077f8" +dependencies = [ + "anyhow", + "arrayvec", + "log", + "nom", + "num-rational", + "v_frame", +] + +[[package]] +name = "avif-serialize" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7178fe5f7d460b13895ebb9dcb28a3a6216d2df2574a0806cb51b555d297f38" +dependencies = [ + "arrayvec", +] [[package]] name = "bit-set" -version = "0.8.0" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" dependencies = [ "bit-vec", ] [[package]] name = "bit-vec" -version = "0.8.0" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "bit_field" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6" [[package]] name = "bitflags" @@ -376,10 +637,22 @@ name = "bitflags" version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" + +[[package]] +name = "bitstream-io" +version = "4.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eff00be299a18769011411c9def0d827e8f2d7bf0c3dbf53633147a8867fd1f" dependencies = [ - "serde_core", + "no_std_io2", ] +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + [[package]] name = "block-buffer" version = "0.10.4" @@ -399,12 +672,50 @@ dependencies = [ ] [[package]] -name = "block2" -version = "0.6.2" +name = "block-sys" +version = "0.1.0-beta.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" +checksum = "0fa55741ee90902547802152aaf3f8e5248aab7e21468089560d4c8840561146" dependencies = [ - "objc2", + "objc-sys 0.2.0-beta.2", +] + +[[package]] +name = "block-sys" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae85a0696e7ea3b835a453750bf002770776609115e6d25c6d2ff28a8200f7e7" +dependencies = [ + "objc-sys 0.3.5", +] + +[[package]] +name = "block2" +version = "0.2.0-alpha.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8dd9e63c1744f755c2f60332b88de39d341e5e86239014ad839bd71c106dec42" +dependencies = [ + "block-sys 0.1.0-beta.1", + "objc2-encode 2.0.0-pre.2", +] + +[[package]] +name = "block2" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15b55663a85f33501257357e6421bb33e769d5c9ffb5ba0921c975a123e35e68" +dependencies = [ + "block-sys 0.2.1", + "objc2 0.4.1", +] + +[[package]] +name = "block2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" +dependencies = [ + "objc2 0.5.2", ] [[package]] @@ -421,34 +732,10 @@ dependencies = [ ] [[package]] -name = "brotli" -version = "8.0.3" +name = "built" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8119e4516436f5708bbc474a9d395bf12f1b5395e93a92a56e647ac3388c8610" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", - "brotli-decompressor", -] - -[[package]] -name = "brotli-decompressor" -version = "5.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5962523e1b92ce1b5e793d9169b9943eece10d39f62550bc04bb605d75b94924" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", -] - -[[package]] -name = "bs58" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" -dependencies = [ - "tinyvec", -] +checksum = "5c0e531d93d39c34eef561e929e8a7f86d77a5af08aac4f6d6e39976c51858e9" [[package]] name = "bumpalo" @@ -461,6 +748,20 @@ name = "bytemuck" version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] [[package]] name = "byteorder" @@ -468,80 +769,67 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + [[package]] name = "bytes" version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" -dependencies = [ - "serde", -] [[package]] -name = "cairo-rs" -version = "0.18.5" +name = "calloop" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2" +checksum = "fba7adb4dd5aa98e5553510223000e7148f621165ec5f9acd7113f6ca4995298" dependencies = [ "bitflags 2.13.0", - "cairo-sys-rs", - "glib", - "libc", - "once_cell", + "log", + "polling 3.11.0", + "rustix 0.38.44", + "slab", "thiserror 1.0.69", ] [[package]] -name = "cairo-sys-rs" -version = "0.18.2" +name = "calloop" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "685c9fa8e590b8b3d678873528d83411db17242a73fccaed827770ea0fedda51" +checksum = "4dbf9978365bac10f54d1d4b04f7ce4427e51f71d61f2fe15e3fed5166474df7" dependencies = [ - "glib-sys", - "libc", - "system-deps", + "bitflags 2.13.0", + "polling 3.11.0", + "rustix 1.1.4", + "slab", + "tracing", ] [[package]] -name = "camino" -version = "1.2.2" +name = "calloop-wayland-source" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e629a66d692cb9ff1a1c664e41771b3dcaf961985a9774c0eb0bd1b51cf60a48" +checksum = "0f0ea9b9476c7fad82841a8dbb380e2eae480c21910feba80725b46931ed8f02" dependencies = [ - "serde_core", + "calloop 0.12.4", + "rustix 0.38.44", + "wayland-backend", + "wayland-client", ] [[package]] -name = "cargo-platform" -version = "0.1.9" +name = "calloop-wayland-source" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" +checksum = "138efcf0940a02ebf0cc8d1eff41a1682a46b431630f4c52450d6265876021fa" dependencies = [ - "serde", -] - -[[package]] -name = "cargo_metadata" -version = "0.19.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd5eb614ed4c27c5d706420e4320fbe3216ab31fa1c33cd8246ac36dae4479ba" -dependencies = [ - "camino", - "cargo-platform", - "semver", - "serde", - "serde_json", - "thiserror 2.0.18", -] - -[[package]] -name = "cargo_toml" -version = "0.22.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374b7c592d9c00c1f4972ea58390ac6b18cbb6ab79011f3bdc90a0b82ca06b77" -dependencies = [ - "serde", - "toml 0.9.12+spec-1.1.0", + "calloop 0.14.4", + "rustix 1.1.4", + "wayland-backend", + "wayland-client", ] [[package]] @@ -560,6 +848,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dad887fd958be91b5098c0248def011f4523ab786cd411be668777e55063501f" dependencies = [ "find-msvc-tools", + "jobserver", + "libc", "shlex", ] @@ -569,33 +859,27 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" -[[package]] -name = "cfb" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d38f2da7a0a2c4ccf0065be06397cc26a81f4e528be095826eee9d4adbb8c60f" -dependencies = [ - "byteorder", - "fnv", - "uuid", -] - -[[package]] -name = "cfg-expr" -version = "0.15.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" -dependencies = [ - "smallvec", - "target-lexicon", -] - [[package]] name = "cfg-if" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + +[[package]] +name = "cgl" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ced0551234e87afee12411d535648dd89d2e7f34c78b753395567aff3d447ff" +dependencies = [ + "libc", +] + [[package]] name = "chrono" version = "0.4.45" @@ -605,9 +889,8 @@ dependencies = [ "iana-time-zone", "js-sys", "num-traits", - "serde", "wasm-bindgen", - "windows-link 0.2.1", + "windows-link", ] [[package]] @@ -620,6 +903,62 @@ dependencies = [ "inout", ] +[[package]] +name = "clipboard-win" +version = "5.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bde03770d3df201d4fb868f2c9c59e66a3e4e2bd06692a0fe701e7103c7e84d4" +dependencies = [ + "error-code", +] + +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + +[[package]] +name = "com" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e17887fd17353b65b1b2ef1c526c83e26cd72e74f598a8dc1bee13a48f3d9f6" +dependencies = [ + "com_macros", +] + +[[package]] +name = "com_macros" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d375883580a668c7481ea6631fc1a8863e33cc335bf56bfad8d7e6d4b04b13a5" +dependencies = [ + "com_macros_support", + "proc-macro2", + "syn 1.0.109", +] + +[[package]] +name = "com_macros_support" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad899a1087a9296d5644792d7cb72b8e34c1bec8e7d4fbc002230169a6e8710c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "combine" version = "4.6.7" @@ -639,16 +978,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "cookie" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747" -dependencies = [ - "time", - "version_check", -] - [[package]] name = "core-foundation" version = "0.9.4" @@ -677,12 +1006,12 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "core-graphics" -version = "0.25.0" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "064badf302c3194842cf2c5d61f56cc88e54a759313879cdf03abdd27d0c3b97" +checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" dependencies = [ - "bitflags 2.13.0", - "core-foundation 0.10.1", + "bitflags 1.3.2", + "core-foundation 0.9.4", "core-graphics-types", "foreign-types 0.5.0", "libc", @@ -690,12 +1019,12 @@ dependencies = [ [[package]] name = "core-graphics-types" -version = "0.2.0" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" +checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" dependencies = [ - "bitflags 2.13.0", - "core-foundation 0.10.1", + "bitflags 1.3.2", + "core-foundation 0.9.4", "libc", ] @@ -718,10 +1047,20 @@ dependencies = [ ] [[package]] -name = "crossbeam-channel" -version = "0.5.15" +name = "crossbeam-deque" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ "crossbeam-utils", ] @@ -732,6 +1071,12 @@ version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + [[package]] name = "crypto-common" version = "0.1.7" @@ -743,98 +1088,10 @@ dependencies = [ ] [[package]] -name = "cssparser" -version = "0.36.0" +name = "cursor-icon" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dae61cf9c0abb83bd659dab65b7e4e38d8236824c85f0f804f173567bda257d2" -dependencies = [ - "cssparser-macros", - "dtoa-short", - "itoa", - "phf", - "smallvec", -] - -[[package]] -name = "cssparser-macros" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" -dependencies = [ - "quote", - "syn 2.0.117", -] - -[[package]] -name = "ctor" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "352d39c2f7bef1d6ad73db6f5160efcaed66d94ef8c6c573a8410c00bf909a98" -dependencies = [ - "ctor-proc-macro", - "dtor", -] - -[[package]] -name = "ctor-proc-macro" -version = "0.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52560adf09603e58c9a7ee1fe1dcb95a16927b17c127f0ac02d6e768a0e25bc1" - -[[package]] -name = "darling" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" -dependencies = [ - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 2.0.117", -] - -[[package]] -name = "darling_macro" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" -dependencies = [ - "darling_core", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "dbus" -version = "0.9.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b942602992bb7acfd1f51c49811c58a610ef9181b6e66f3e519d79b540a3bf73" -dependencies = [ - "libc", - "libdbus-sys", - "windows-sys 0.61.2", -] - -[[package]] -name = "deranged" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" -dependencies = [ - "powerfmt", - "serde_core", -] +checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f" [[package]] name = "derivative" @@ -847,27 +1104,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "derive_more" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" -dependencies = [ - "derive_more-impl", -] - -[[package]] -name = "derive_more-impl" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" -dependencies = [ - "proc-macro2", - "quote", - "rustc_version", - "syn 2.0.117", -] - [[package]] name = "digest" version = "0.10.7" @@ -885,16 +1121,7 @@ version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" dependencies = [ - "dirs-sys 0.4.1", -] - -[[package]] -name = "dirs" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" -dependencies = [ - "dirs-sys 0.5.0", + "dirs-sys", ] [[package]] @@ -905,21 +1132,15 @@ checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" dependencies = [ "libc", "option-ext", - "redox_users 0.4.6", + "redox_users", "windows-sys 0.48.0", ] [[package]] -name = "dirs-sys" -version = "0.5.0" +name = "dispatch" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" -dependencies = [ - "libc", - "option-ext", - "redox_users 0.5.2", - "windows-sys 0.61.2", -] +checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" [[package]] name = "dispatch2" @@ -928,9 +1149,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" dependencies = [ "bitflags 2.13.0", - "block2", - "libc", - "objc2", + "objc2 0.6.4", ] [[package]] @@ -945,121 +1164,193 @@ dependencies = [ ] [[package]] -name = "dlopen2" -version = "0.8.2" +name = "dlib" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e2c5bd4158e66d1e215c49b837e11d62f3267b30c92f1d171c4d3105e3dc4d4" +checksum = "ab8ecd87370524b461f8557c119c405552c396ed91fc0a8eec68679eab26f94a" dependencies = [ - "dlopen2_derive", - "libc", - "once_cell", - "winapi", + "libloading 0.7.4", ] [[package]] -name = "dlopen2_derive" -version = "0.4.3" +name = "document-features" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fbbb781877580993a8707ec48672673ec7b81eeba04cfd2310bd28c08e47c8f" +checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", + "litrs", ] [[package]] -name = "dom_query" -version = "0.27.0" +name = "downcast-rs" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "521e380c0c8afb8d9a1e83a1822ee03556fc3e3e7dbc1fd30be14e37f9cb3f89" -dependencies = [ - "bit-set", - "cssparser", - "foldhash 0.2.0", - "html5ever", - "precomputed-hash", - "selectors", - "tendril", -] +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" [[package]] -name = "dpi" -version = "0.1.2" +name = "ecolor" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" +checksum = "2e6b451ff1143f6de0f33fc7f1b68fecfd2c7de06e104de96c4514de3f5396f8" dependencies = [ + "bytemuck", + "emath", "serde", ] [[package]] -name = "dtoa" -version = "1.0.11" +name = "eframe" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c3cf4824e2d5f025c7b531afcb2325364084a16806f6d47fbc1f5fbd9960590" - -[[package]] -name = "dtoa-short" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd1511a7b6a56299bd043a9c167a6d2bfb37bf84a6dfceaba651168adfb43c87" +checksum = "6490ef800b2e41ee129b1f32f9ac15f713233fe3bc18e241a1afe1e4fb6811e0" dependencies = [ - "dtoa", + "ahash", + "bytemuck", + "document-features", + "egui", + "egui-wgpu", + "egui-winit", + "egui_glow", + "glow", + "glutin", + "glutin-winit", + "image", + "js-sys", + "log", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", + "parking_lot", + "percent-encoding", + "raw-window-handle 0.5.2", + "raw-window-handle 0.6.2", + "static_assertions", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "web-time", + "winapi", + "winit", ] [[package]] -name = "dtor" -version = "0.3.0" +name = "egui" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1057d6c64987086ff8ed0fd3fbf377a6b7d205cc7715868cd401705f715cbe4" +checksum = "20c97e70a2768de630f161bb5392cbd3874fcf72868f14df0e002e82e06cb798" dependencies = [ - "dtor-proc-macro", + "accesskit", + "ahash", + "emath", + "epaint", + "log", + "nohash-hasher", + "serde", ] [[package]] -name = "dtor-proc-macro" -version = "0.0.6" +name = "egui-wgpu" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f678cf4a922c215c63e0de95eb1ff08a958a81d47e485cf9da1e27bf6305cfa5" - -[[package]] -name = "dunce" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" - -[[package]] -name = "dyn-clone" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" - -[[package]] -name = "embed-resource" -version = "3.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31a88c8d26de40ed18fe748c547845aa39de1db3afd958f8cb91579f3644bcb" +checksum = "47c7a7c707877c3362a321ebb4f32be811c0b91f7aebf345fb162405c0218b4c" dependencies = [ - "cc", - "memchr", - "rustc_version", - "toml 1.1.2+spec-1.1.0", - "vswhom", - "winreg", + "ahash", + "bytemuck", + "document-features", + "egui", + "epaint", + "log", + "thiserror 1.0.69", + "type-map", + "web-time", + "wgpu", + "winit", ] [[package]] -name = "embed_plist" -version = "1.2.2" +name = "egui-winit" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ef6b89e5b37196644d8796de5268852ff179b44e96276cf4290264843743bb7" +checksum = "fac4e066af341bf92559f60dbdf2020b2a03c963415349af5f3f8d79ff7a4926" +dependencies = [ + "accesskit_winit", + "ahash", + "arboard", + "egui", + "log", + "raw-window-handle 0.6.2", + "smithay-clipboard", + "web-time", + "webbrowser", + "winit", +] [[package]] -name = "encoding_rs" -version = "0.8.35" +name = "egui_extras" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +checksum = "5bb783d9fa348f69ed5c340aa25af78b5472043090e8b809040e30960cc2a746" dependencies = [ - "cfg-if", + "ahash", + "egui", + "enum-map", + "log", + "mime_guess2", + "serde", +] + +[[package]] +name = "egui_glow" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e2bdc8b38cfa17cc712c4ae079e30c71c00cd4c2763c9e16dc7860a02769103" +dependencies = [ + "ahash", + "bytemuck", + "egui", + "glow", + "log", + "memoffset 0.9.1", + "wasm-bindgen", + "web-sys", + "winit", +] + +[[package]] +name = "either" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" + +[[package]] +name = "emath" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6a21708405ea88f63d8309650b4d77431f4bc28fb9d8e6f77d3963b51249e6" +dependencies = [ + "bytemuck", + "serde", +] + +[[package]] +name = "enum-map" +version = "2.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6866f3bfdf8207509a033af1a75a7b08abda06bbaaeae6669323fd5a097df2e9" +dependencies = [ + "enum-map-derive", + "serde", +] + +[[package]] +name = "enum-map-derive" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", ] [[package]] @@ -1083,23 +1374,60 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "enumn" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f9ed6b3789237c8a0c1c505af1c7eb2c560df6186f01b098c3a1064ea532f38" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "epaint" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f0dcc0a0771e7500e94cd1cb797bd13c9f23b9409bdc3c824e2cbc562b7fa01" +dependencies = [ + "ab_glyph", + "ahash", + "bytemuck", + "ecolor", + "emath", + "log", + "nohash-hasher", + "parking_lot", + "serde", +] + +[[package]] +name = "equator" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc" +dependencies = [ + "equator-macro", +] + +[[package]] +name = "equator-macro" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "equivalent" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" -[[package]] -name = "erased-serde" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2add8a07dd6a8d93ff627029c51de145e12686fbc36ecb298ac22e74cf02dec" -dependencies = [ - "serde", - "serde_core", - "typeid", -] - [[package]] name = "errno" version = "0.3.14" @@ -1110,6 +1438,12 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "error-code" +version = "3.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dea2df4cf52843e0452895c455a1a2cfbb842a1e7329671acf418fdc53ed4c59" + [[package]] name = "event-listener" version = "2.5.3" @@ -1148,6 +1482,21 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "exr" +version = "1.74.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4300e043a56aa2cb633c01af81ca8f699a321879a7854d3896a0ba89056363be" +dependencies = [ + "bit_field", + "half", + "lebe", + "miniz_oxide", + "rayon-core", + "smallvec", + "zune-inflate", +] + [[package]] name = "fallible-iterator" version = "0.3.0" @@ -1175,6 +1524,12 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" +[[package]] +name = "fax" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caf1079563223d5d59d83c85886a56e586cfd5c1a26292e971a0fa266531ac5a" + [[package]] name = "fdeflate" version = "0.3.7" @@ -1184,16 +1539,6 @@ dependencies = [ "simd-adler32", ] -[[package]] -name = "field-offset" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f" -dependencies = [ - "memoffset 0.9.1", - "rustc_version", -] - [[package]] name = "find-msvc-tools" version = "0.1.9" @@ -1210,24 +1555,12 @@ dependencies = [ "miniz_oxide", ] -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - [[package]] name = "foldhash" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" -[[package]] -name = "foldhash" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" - [[package]] name = "foreign-types" version = "0.3.2" @@ -1279,21 +1612,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "futures" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - [[package]] name = "futures-channel" version = "0.3.32" @@ -1301,7 +1619,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" dependencies = [ "futures-core", - "futures-sink", ] [[package]] @@ -1310,17 +1627,6 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" -[[package]] -name = "futures-executor" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - [[package]] name = "futures-io" version = "0.3.32" @@ -1384,7 +1690,6 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ - "futures-channel", "futures-core", "futures-io", "futures-macro", @@ -1395,105 +1700,6 @@ dependencies = [ "slab", ] -[[package]] -name = "gdk" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9f245958c627ac99d8e529166f9823fb3b838d1d41fd2b297af3075093c2691" -dependencies = [ - "cairo-rs", - "gdk-pixbuf", - "gdk-sys", - "gio", - "glib", - "libc", - "pango", -] - -[[package]] -name = "gdk-pixbuf" -version = "0.18.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50e1f5f1b0bfb830d6ccc8066d18db35c487b1b2b1e8589b5dfe9f07e8defaec" -dependencies = [ - "gdk-pixbuf-sys", - "gio", - "glib", - "libc", - "once_cell", -] - -[[package]] -name = "gdk-pixbuf-sys" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9839ea644ed9c97a34d129ad56d38a25e6756f99f3a88e15cd39c20629caf7" -dependencies = [ - "gio-sys", - "glib-sys", - "gobject-sys", - "libc", - "system-deps", -] - -[[package]] -name = "gdk-sys" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c2d13f38594ac1e66619e188c6d5a1adb98d11b2fcf7894fc416ad76aa2f3f7" -dependencies = [ - "cairo-sys-rs", - "gdk-pixbuf-sys", - "gio-sys", - "glib-sys", - "gobject-sys", - "libc", - "pango-sys", - "pkg-config", - "system-deps", -] - -[[package]] -name = "gdkwayland-sys" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "140071d506d223f7572b9f09b5e155afbd77428cd5cc7af8f2694c41d98dfe69" -dependencies = [ - "gdk-sys", - "glib-sys", - "gobject-sys", - "libc", - "pkg-config", - "system-deps", -] - -[[package]] -name = "gdkx11" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3caa00e14351bebbc8183b3c36690327eb77c49abc2268dd4bd36b856db3fbfe" -dependencies = [ - "gdk", - "gdkx11-sys", - "gio", - "glib", - "libc", - "x11", -] - -[[package]] -name = "gdkx11-sys" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e2e7445fe01ac26f11601db260dd8608fe172514eb63b3b5e261ea6b0f4428d" -dependencies = [ - "gdk-sys", - "glib-sys", - "libc", - "system-deps", - "x11", -] - [[package]] name = "generic-array" version = "0.14.7" @@ -1504,6 +1710,16 @@ dependencies = [ "version_check", ] +[[package]] +name = "gethostname" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" +dependencies = [ + "rustix 1.1.4", + "windows-link", +] + [[package]] name = "getrandom" version = "0.2.17" @@ -1541,90 +1757,26 @@ dependencies = [ ] [[package]] -name = "gio" -version = "0.18.4" +name = "gif" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fc8f532f87b79cbc51a79748f16a6828fb784be93145a322fa14d06d354c73" +checksum = "ee8cfcc411d9adbbaba82fb72661cc1bcca13e8bba98b364e62b2dba8f960159" dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-util", - "gio-sys", - "glib", - "libc", - "once_cell", - "pin-project-lite", - "smallvec", - "thiserror 1.0.69", + "color_quant", + "weezl", ] [[package]] -name = "gio-sys" -version = "0.18.1" +name = "gl_generator" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37566df850baf5e4cb0dfb78af2e4b9898d817ed9263d1090a2df958c64737d2" +checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d" dependencies = [ - "glib-sys", - "gobject-sys", - "libc", - "system-deps", - "winapi", + "khronos_api", + "log", + "xml-rs", ] -[[package]] -name = "glib" -version = "0.18.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5" -dependencies = [ - "bitflags 2.13.0", - "futures-channel", - "futures-core", - "futures-executor", - "futures-task", - "futures-util", - "gio-sys", - "glib-macros", - "glib-sys", - "gobject-sys", - "libc", - "memchr", - "once_cell", - "smallvec", - "thiserror 1.0.69", -] - -[[package]] -name = "glib-macros" -version = "0.18.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bb0228f477c0900c880fd78c8759b95c7636dbd7842707f49e132378aa2acdc" -dependencies = [ - "heck 0.4.1", - "proc-macro-crate 2.0.2", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "glib-sys" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "063ce2eb6a8d0ea93d2bf8ba1957e78dbab6be1c2220dd3daca57d5a9d869898" -dependencies = [ - "libc", - "system-deps", -] - -[[package]] -name = "glob" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" - [[package]] name = "gloo-timers" version = "0.3.0" @@ -1638,73 +1790,144 @@ dependencies = [ ] [[package]] -name = "gobject-sys" -version = "0.18.0" +name = "glow" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0850127b514d1c4a4654ead6dedadb18198999985908e6ffe4436f53c785ce44" +checksum = "bd348e04c43b32574f2de31c8bb397d96c9fcfa1371bd4ca6d8bdc464ab121b1" dependencies = [ - "glib-sys", - "libc", - "system-deps", + "js-sys", + "slotmap", + "wasm-bindgen", + "web-sys", ] [[package]] -name = "gtk" -version = "0.18.2" +name = "glutin" +version = "0.31.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd56fb197bfc42bd5d2751f4f017d44ff59fbb58140c6b49f9b3b2bdab08506a" +checksum = "18fcd4ae4e86d991ad1300b8f57166e5be0c95ef1f63f3f5b827f8a164548746" dependencies = [ - "atk", - "cairo-rs", - "field-offset", - "futures-channel", - "gdk", - "gdk-pixbuf", - "gio", - "glib", - "gtk-sys", - "gtk3-macros", - "libc", - "pango", - "pkg-config", + "bitflags 2.13.0", + "cfg_aliases", + "cgl", + "core-foundation 0.9.4", + "dispatch", + "glutin_egl_sys", + "glutin_glx_sys", + "glutin_wgl_sys", + "icrate", + "libloading 0.8.9", + "objc2 0.4.1", + "once_cell", + "raw-window-handle 0.5.2", + "wayland-sys", + "windows-sys 0.48.0", + "x11-dl", ] [[package]] -name = "gtk-sys" -version = "0.18.2" +name = "glutin-winit" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f29a1c21c59553eb7dd40e918be54dccd60c52b049b75119d5d96ce6b624414" +checksum = "1ebcdfba24f73b8412c5181e56f092b5eff16671c514ce896b258a0a64bd7735" dependencies = [ - "atk-sys", - "cairo-sys-rs", - "gdk-pixbuf-sys", - "gdk-sys", - "gio-sys", - "glib-sys", - "gobject-sys", - "libc", - "pango-sys", - "system-deps", + "cfg_aliases", + "glutin", + "raw-window-handle 0.5.2", + "winit", ] [[package]] -name = "gtk3-macros" -version = "0.18.2" +name = "glutin_egl_sys" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52ff3c5b21f14f0736fed6dcfc0bfb4225ebf5725f3c0209edeec181e4d73e9d" +checksum = "77cc5623f5309ef433c3dd4ca1223195347fe62c413da8e2fdd0eb76db2d9bcd" dependencies = [ - "proc-macro-crate 1.3.1", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 2.0.117", + "gl_generator", + "windows-sys 0.48.0", ] [[package]] -name = "hashbrown" -version = "0.12.3" +name = "glutin_glx_sys" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +checksum = "a165fd686c10dcc2d45380b35796e577eacfd43d4660ee741ec8ebe2201b3b4f" +dependencies = [ + "gl_generator", + "x11-dl", +] + +[[package]] +name = "glutin_wgl_sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8098adac955faa2d31079b65dc48841251f69efd3ac25477903fc424362ead" +dependencies = [ + "gl_generator", +] + +[[package]] +name = "gpu-alloc" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171" +dependencies = [ + "bitflags 2.13.0", + "gpu-alloc-types", +] + +[[package]] +name = "gpu-alloc-types" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4" +dependencies = [ + "bitflags 2.13.0", +] + +[[package]] +name = "gpu-allocator" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f56f6318968d03c18e1bcf4857ff88c61157e9da8e47c5f29055d60e1228884" +dependencies = [ + "log", + "presser", + "thiserror 1.0.69", + "winapi", + "windows 0.52.0", +] + +[[package]] +name = "gpu-descriptor" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b89c83349105e3732062a895becfc71a8f921bb71ecbbdd8ff99263e3b53a0ca" +dependencies = [ + "bitflags 2.13.0", + "gpu-descriptor-types", + "hashbrown 0.15.5", +] + +[[package]] +name = "gpu-descriptor-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91" +dependencies = [ + "bitflags 2.13.0", +] + +[[package]] +name = "half" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +dependencies = [ + "cfg-if", + "crunchy", + "zerocopy", +] [[package]] name = "hashbrown" @@ -1721,7 +1944,7 @@ version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ - "foldhash 0.1.5", + "foldhash", ] [[package]] @@ -1740,10 +1963,19 @@ dependencies = [ ] [[package]] -name = "heck" -version = "0.4.1" +name = "hassle-rs" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "af2a7e73e1f34c48da31fb668a907f250794837e08faa144fd24f0b8b741e890" +dependencies = [ + "bitflags 2.13.0", + "com", + "libc", + "libloading 0.7.4", + "thiserror 1.0.69", + "widestring", + "winapi", +] [[package]] name = "heck" @@ -1769,6 +2001,12 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hexf-parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" + [[package]] name = "hkdf" version = "0.12.4" @@ -1787,98 +2025,6 @@ dependencies = [ "digest", ] -[[package]] -name = "html5ever" -version = "0.38.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1054432bae2f14e0061e33d23402fbaa67a921d319d56adc6bcf887ddad1cbc2" -dependencies = [ - "log", - "markup5ever", -] - -[[package]] -name = "http" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6970f50e31d6fc17d3fa27329444bfa74e196cf62e95052a3f6fee181dba6425" -dependencies = [ - "bytes", - "itoa", -] - -[[package]] -name = "http-body" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" -dependencies = [ - "bytes", - "http", -] - -[[package]] -name = "http-body-util" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" -dependencies = [ - "bytes", - "futures-core", - "http", - "http-body", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" - -[[package]] -name = "hyper" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55281c53a1894c864990125767da440a4e630446785086f52523b20033b74498" -dependencies = [ - "atomic-waker", - "bytes", - "futures-channel", - "futures-core", - "http", - "http-body", - "httparse", - "itoa", - "pin-project-lite", - "smallvec", - "tokio", - "want", -] - -[[package]] -name = "hyper-util" -version = "0.1.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" -dependencies = [ - "base64 0.22.1", - "bytes", - "futures-channel", - "futures-util", - "http", - "http-body", - "hyper", - "ipnet", - "libc", - "percent-encoding", - "pin-project-lite", - "socket2 0.6.4", - "tokio", - "tower-service", - "tracing", -] - [[package]] name = "iana-time-zone" version = "0.1.65" @@ -1904,13 +2050,14 @@ dependencies = [ ] [[package]] -name = "ico" -version = "0.5.0" +name = "icrate" +version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e795dff5605e0f04bff85ca41b51a96b83e80b281e96231bcaaf1ac35103371" +checksum = "99d3aaff8a54577104bafdf686ff18565c3b6903ca5782a2026ef06e2c7aa319" dependencies = [ - "byteorder", - "png 0.17.16", + "block2 0.3.0", + "dispatch", + "objc2 0.4.1", ] [[package]] @@ -2001,12 +2148,6 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - [[package]] name = "idna" version = "1.1.0" @@ -2029,16 +2170,45 @@ dependencies = [ ] [[package]] -name = "indexmap" -version = "1.9.3" +name = "image" +version = "0.25.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104" dependencies = [ - "autocfg", - "hashbrown 0.12.3", - "serde", + "bytemuck", + "byteorder-lite", + "color_quant", + "exr", + "gif", + "image-webp", + "moxcms", + "num-traits", + "png", + "qoi", + "ravif", + "rayon", + "rgb", + "tiff", + "zune-core", + "zune-jpeg", ] +[[package]] +name = "image-webp" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525e9ff3e1a4be2fbea1fdf0e98686a6d98b4d8f937e1bf7402245af1909e8c3" +dependencies = [ + "byteorder-lite", + "quick-error", +] + +[[package]] +name = "imgref" +version = "1.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89194689a993ab15268672e99e7b0e19da2da3268ac682e8f02d29d4d1434cd7" + [[package]] name = "indexmap" version = "2.14.0" @@ -2051,15 +2221,6 @@ dependencies = [ "serde_core", ] -[[package]] -name = "infer" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a588916bfdfd92e71cacef98a63d9b1f0d74d6599980d11894290e7ddefffcf7" -dependencies = [ - "cfb", -] - [[package]] name = "inout" version = "0.1.4" @@ -2079,6 +2240,17 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "interpolate_name" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "io-lifetimes" version = "1.0.11" @@ -2091,28 +2263,12 @@ dependencies = [ ] [[package]] -name = "ipnet" -version = "2.12.0" +name = "itertools" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" - -[[package]] -name = "is-docker" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "928bae27f42bc99b60d9ac7334e3a21d10ad8f1835a4e12ec3ec0464765ed1b3" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" dependencies = [ - "once_cell", -] - -[[package]] -name = "is-wsl" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "173609498df190136aa7dea1a91db051746d339e18476eed5ca40521f02d7aa5" -dependencies = [ - "is-docker", - "once_cell", + "either", ] [[package]] @@ -2121,29 +2277,6 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" -[[package]] -name = "javascriptcore-rs" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca5671e9ffce8ffba57afc24070e906da7fc4b1ba66f2cabebf61bf2ea257fcc" -dependencies = [ - "bitflags 1.3.2", - "glib", - "javascriptcore-rs-sys", -] - -[[package]] -name = "javascriptcore-rs-sys" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af1be78d14ffa4b75b66df31840478fef72b51f8c2465d4ca7c194da9f7a5124" -dependencies = [ - "glib-sys", - "gobject-sys", - "libc", - "system-deps", -] - [[package]] name = "jni" version = "0.21.1" @@ -2160,6 +2293,36 @@ dependencies = [ "windows-sys 0.45.0", ] +[[package]] +name = "jni" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" +dependencies = [ + "cfg-if", + "combine", + "jni-macros", + "jni-sys 0.4.1", + "log", + "simd_cesu8", + "thiserror 2.0.18", + "walkdir", + "windows-link", +] + +[[package]] +name = "jni-macros" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version", + "simd_cesu8", + "syn 2.0.117", +] + [[package]] name = "jni-sys" version = "0.3.1" @@ -2188,6 +2351,16 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.4", + "libc", +] + [[package]] name = "js-sys" version = "0.3.102" @@ -2199,39 +2372,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "json-patch" -version = "3.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "863726d7afb6bc2590eeff7135d923545e5e964f004c2ccf8716c25e70a86f08" -dependencies = [ - "jsonptr", - "serde", - "serde_json", - "thiserror 1.0.69", -] - -[[package]] -name = "jsonptr" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dea2b27dd239b2556ed7a25ba842fe47fd602e7fc7433c2a8d6106d4d9edd70" -dependencies = [ - "serde", - "serde_json", -] - -[[package]] -name = "keyboard-types" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b750dcadc39a09dbadd74e118f6dd6598df77fa01df0cfcdc52c28dece74528a" -dependencies = [ - "bitflags 2.13.0", - "serde", - "unicode-segmentation", -] - [[package]] name = "keyring" version = "2.3.3" @@ -2246,6 +2386,23 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "khronos-egl" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76" +dependencies = [ + "libc", + "libloading 0.8.9", + "pkg-config", +] + +[[package]] +name = "khronos_api" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" + [[package]] name = "kv-log-macro" version = "1.0.7" @@ -2291,28 +2448,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] -name = "libappindicator" -version = "0.9.0" +name = "lebe" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03589b9607c868cc7ae54c0b2a22c8dc03dd41692d48f2d7df73615c6a95dc0a" -dependencies = [ - "glib", - "gtk", - "gtk-sys", - "libappindicator-sys", - "log", -] - -[[package]] -name = "libappindicator-sys" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e9ec52138abedcc58dc17a7c6c0c00a2bdb4f3427c7f63fa97fd0d859155caf" -dependencies = [ - "gtk-sys", - "libloading", - "once_cell", -] +checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8" [[package]] name = "libc" @@ -2321,12 +2460,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] -name = "libdbus-sys" -version = "0.2.7" +name = "libfuzzer-sys" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "328c4789d42200f1eeec05bd86c9c13c7f091d2ba9a6ea35acdf51f31bc0f043" +checksum = "a9fd2f41a1cba099f79a0b6b6c35656cf7c03351a7bae8ff0f28f25270f929d2" dependencies = [ - "pkg-config", + "arbitrary", + "cc", ] [[package]] @@ -2339,13 +2479,26 @@ dependencies = [ "winapi", ] +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link", +] + [[package]] name = "libredox" version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f02ab6bace2054fb888a3c16f990117b579d14a3088e472d63c6011fa185c9d3" dependencies = [ + "bitflags 2.13.0", "libc", + "plain", + "redox_syscall 0.8.1", ] [[package]] @@ -2419,6 +2572,12 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" +[[package]] +name = "litrs" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" + [[package]] name = "lock_api" version = "0.4.14" @@ -2433,25 +2592,22 @@ name = "loflum" version = "0.1.0" dependencies = [ "anyhow", - "async-std", "async-trait", - "camino", "chrono", - "dirs 5.0.1", - "futures", + "dirs", + "eframe", + "egui", + "egui_extras", + "futures-lite 2.6.1", + "image", "keyring", - "once_cell", "rusqlite", "serde", "serde_json", "ssh2", "suppaftp", - "tauri", - "tauri-build", - "tauri-plugin-shell", "thiserror 1.0.69", "tokio", - "tokio-util", "tracing", "tracing-subscriber", "uuid", @@ -2467,14 +2623,31 @@ dependencies = [ ] [[package]] -name = "markup5ever" -version = "0.38.0" +name = "loop9" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8983d30f2915feeaaab2d6babdd6bc7e9ed1a00b66b5e6d74df19aa9c0e91862" +checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" dependencies = [ - "log", - "tendril", - "web_atoms", + "imgref", +] + +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + +[[package]] +name = "maybe-rayon" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" +dependencies = [ + "cfg-if", + "rayon", ] [[package]] @@ -2483,6 +2656,15 @@ version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" +[[package]] +name = "memmap2" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3" +dependencies = [ + "libc", +] + [[package]] name = "memoffset" version = "0.7.1" @@ -2501,12 +2683,39 @@ dependencies = [ "autocfg", ] +[[package]] +name = "metal" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5637e166ea14be6063a3f8ba5ccb9a4159df7d8f6d61c02fc3d480b1f90dcfcb" +dependencies = [ + "bitflags 2.13.0", + "block", + "core-graphics-types", + "foreign-types 0.5.0", + "log", + "objc", + "paste", +] + [[package]] name = "mime" version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "mime_guess2" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1706dc14a2e140dec0a7a07109d9a3d5890b81e85bd6c60b906b249a77adf0ca" +dependencies = [ + "mime", + "phf", + "phf_shared", + "unicase", +] + [[package]] name = "miniz_oxide" version = "0.8.9" @@ -2529,24 +2738,34 @@ dependencies = [ ] [[package]] -name = "muda" -version = "0.19.2" +name = "moxcms" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47a2e3dff89cd322c66647942668faee0a2b1f88ea6cbb4d374b4a8d7e92528c" +checksum = "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b" dependencies = [ - "crossbeam-channel", - "dpi", - "gtk", - "keyboard-types", - "objc2", - "objc2-app-kit", - "objc2-core-foundation", - "objc2-foundation", - "once_cell", - "png 0.18.1", - "serde", - "thiserror 2.0.18", - "windows-sys 0.61.2", + "num-traits", + "pxfm", +] + +[[package]] +name = "naga" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e536ae46fcab0876853bd4a632ede5df4b1c2527a58f6c5a4150fe86be858231" +dependencies = [ + "arrayvec", + "bit-set", + "bitflags 2.13.0", + "codespan-reporting", + "hexf-parse", + "indexmap", + "log", + "num-traits", + "rustc-hash 1.1.0", + "spirv", + "termcolor", + "thiserror 1.0.69", + "unicode-xid", ] [[package]] @@ -2568,24 +2787,31 @@ dependencies = [ [[package]] name = "ndk" -version = "0.9.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" +checksum = "2076a31b7010b17a38c01907c45b945e8f11495ee4dd588309718901b1f7a5b7" dependencies = [ "bitflags 2.13.0", "jni-sys 0.3.1", "log", "ndk-sys", "num_enum", - "raw-window-handle", + "raw-window-handle 0.5.2", + "raw-window-handle 0.6.2", "thiserror 1.0.69", ] [[package]] -name = "ndk-sys" -version = "0.6.0+11769913" +name = "ndk-context" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + +[[package]] +name = "ndk-sys" +version = "0.5.0+25.2.9519653" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c196769dd60fd4f363e11d948139556a344e79d451aeb2fa2fd040738ef7691" dependencies = [ "jni-sys 0.3.1", ] @@ -2608,6 +2834,36 @@ dependencies = [ "memoffset 0.7.1", ] +[[package]] +name = "no_std_io2" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418abd1b6d34fbf6cae440dc874771b0525a604428704c76e48b29a5e67b8003" +dependencies = [ + "memchr", +] + +[[package]] +name = "nohash-hasher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" + +[[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + +[[package]] +name = "noop_proc_macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" + [[package]] name = "nu-ansi-term" version = "0.50.3" @@ -2651,10 +2907,15 @@ dependencies = [ ] [[package]] -name = "num-conv" -version = "0.2.2" +name = "num-derive" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] [[package]] name = "num-integer" @@ -2718,14 +2979,81 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] + +[[package]] +name = "objc-sys" +version = "0.2.0-beta.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b9834c1e95694a05a828b59f55fa2afec6288359cda67146126b3f90a55d7" + +[[package]] +name = "objc-sys" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" + +[[package]] +name = "objc2" +version = "0.3.0-beta.3.patch-leaks.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e01640f9f2cb1220bbe80325e179e532cb3379ebcd1bf2279d703c19fe3a468" +dependencies = [ + "block2 0.2.0-alpha.6", + "objc-sys 0.2.0-beta.2", + "objc2-encode 2.0.0-pre.2", +] + +[[package]] +name = "objc2" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "559c5a40fdd30eb5e344fbceacf7595a81e242529fb4e21cf5f43fb4f11ff98d" +dependencies = [ + "objc-sys 0.3.5", + "objc2-encode 3.0.0", +] + +[[package]] +name = "objc2" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" +dependencies = [ + "objc-sys 0.3.5", + "objc2-encode 4.1.0", +] + [[package]] name = "objc2" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" dependencies = [ - "objc2-encode", - "objc2-exception-helper", + "objc2-encode 4.1.0", +] + +[[package]] +name = "objc2-app-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" +dependencies = [ + "bitflags 2.13.0", + "block2 0.5.1", + "libc", + "objc2 0.5.2", + "objc2-core-data", + "objc2-core-image", + "objc2-foundation 0.2.2", + "objc2-quartz-core", ] [[package]] @@ -2735,31 +3063,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" dependencies = [ "bitflags 2.13.0", - "block2", - "objc2", - "objc2-core-foundation", - "objc2-foundation", -] - -[[package]] -name = "objc2-cloud-kit" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c" -dependencies = [ - "bitflags 2.13.0", - "objc2", - "objc2-foundation", + "objc2 0.6.4", + "objc2-core-graphics", + "objc2-foundation 0.3.2", ] [[package]] name = "objc2-core-data" -version = "0.3.2" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa" +checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" dependencies = [ - "objc2", - "objc2-foundation", + "bitflags 2.13.0", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", ] [[package]] @@ -2770,7 +3088,7 @@ checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ "bitflags 2.13.0", "dispatch2", - "objc2", + "objc2 0.6.4", ] [[package]] @@ -2781,42 +3099,37 @@ checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" dependencies = [ "bitflags 2.13.0", "dispatch2", - "objc2", + "objc2 0.6.4", "objc2-core-foundation", "objc2-io-surface", ] [[package]] name = "objc2-core-image" -version = "0.3.2" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d563b38d2b97209f8e861173de434bd0214cf020e3423a52624cd1d989f006" +checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" dependencies = [ - "objc2", - "objc2-foundation", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-metal", ] [[package]] -name = "objc2-core-location" -version = "0.3.2" +name = "objc2-encode" +version = "2.0.0-pre.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca347214e24bc973fc025fd0d36ebb179ff30536ed1f80252706db19ee452009" +checksum = "abfcac41015b00a120608fdaa6938c44cb983fee294351cc4bac7638b4e50512" dependencies = [ - "objc2", - "objc2-foundation", + "objc-sys 0.2.0-beta.2", ] [[package]] -name = "objc2-core-text" -version = "0.3.2" +name = "objc2-encode" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d" -dependencies = [ - "bitflags 2.13.0", - "objc2", - "objc2-core-foundation", - "objc2-core-graphics", -] +checksum = "d079845b37af429bfe5dfa76e6d087d788031045b25cfc6fd898486fd9847666" [[package]] name = "objc2-encode" @@ -2825,12 +3138,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" [[package]] -name = "objc2-exception-helper" -version = "0.1.1" +name = "objc2-foundation" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7a1c5fbb72d7735b076bb47b578523aedc40f3c439bea6dfd595c089d79d98a" +checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" dependencies = [ - "cc", + "bitflags 2.13.0", + "block2 0.5.1", + "libc", + "objc2 0.5.2", ] [[package]] @@ -2840,8 +3156,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ "bitflags 2.13.0", - "block2", - "objc2", + "objc2 0.6.4", "objc2-core-foundation", ] @@ -2852,65 +3167,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" dependencies = [ "bitflags 2.13.0", - "objc2", + "objc2 0.6.4", "objc2-core-foundation", ] +[[package]] +name = "objc2-metal" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" +dependencies = [ + "bitflags 2.13.0", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + [[package]] name = "objc2-quartz-core" -version = "0.3.2" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" +checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" dependencies = [ "bitflags 2.13.0", - "objc2", - "objc2-core-foundation", - "objc2-foundation", -] - -[[package]] -name = "objc2-ui-kit" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" -dependencies = [ - "bitflags 2.13.0", - "block2", - "objc2", - "objc2-cloud-kit", - "objc2-core-data", - "objc2-core-foundation", - "objc2-core-graphics", - "objc2-core-image", - "objc2-core-location", - "objc2-core-text", - "objc2-foundation", - "objc2-quartz-core", - "objc2-user-notifications", -] - -[[package]] -name = "objc2-user-notifications" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9df9128cbbfef73cda168416ccf7f837b62737d748333bfe9ab71c245d76613e" -dependencies = [ - "objc2", - "objc2-foundation", -] - -[[package]] -name = "objc2-web-kit" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2e5aaab980c433cf470df9d7af96a7b46a9d892d521a2cbbb2f8a4c16751e7f" -dependencies = [ - "bitflags 2.13.0", - "block2", - "objc2", - "objc2-app-kit", - "objc2-core-foundation", - "objc2-foundation", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-metal", ] [[package]] @@ -2919,18 +3202,6 @@ version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" -[[package]] -name = "open" -version = "5.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fbaa89d2ddc8473c78a3adf69eea8cffa28c483b8e02a971ef31527cd0fc92c" -dependencies = [ - "dunce", - "is-wsl", - "libc", - "pathdiff", -] - [[package]] name = "openssl" version = "0.10.81" @@ -2980,6 +3251,16 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +[[package]] +name = "orbclient" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5df339f526ea9a60e371768d50efc2f2508c7203290731565d1f7a6f71d21747" +dependencies = [ + "libc", + "libredox", +] + [[package]] name = "ordered-stream" version = "0.2.0" @@ -2991,38 +3272,12 @@ dependencies = [ ] [[package]] -name = "os_pipe" -version = "1.2.3" +name = "owned_ttf_parser" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d8fae84b431384b68627d0f9b3b1245fcf9f46f6c0e3dc902e9dce64edd1967" +checksum = "36820e9051aca1014ddc75770aab4d68bc1e9e632f0f5627c4086bc216fb583b" dependencies = [ - "libc", - "windows-sys 0.61.2", -] - -[[package]] -name = "pango" -version = "0.18.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ca27ec1eb0457ab26f3036ea52229edbdb74dee1edd29063f5b9b010e7ebee4" -dependencies = [ - "gio", - "glib", - "libc", - "once_cell", - "pango-sys", -] - -[[package]] -name = "pango-sys" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436737e391a843e5933d6d9aa102cb126d501e815b83601365a948a518555dc5" -dependencies = [ - "glib-sys", - "gobject-sys", - "libc", - "system-deps", + "ttf-parser", ] [[package]] @@ -3049,16 +3304,22 @@ checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.5.18", "smallvec", - "windows-link 0.2.1", + "windows-link", ] [[package]] -name = "pathdiff" -version = "0.2.3" +name = "paste" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pastey" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35fb2e5f958ec131621fdd531e9fc186ed768cbe395337403ae56c17a74c68ec" [[package]] name = "percent-encoding" @@ -3068,55 +3329,46 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "phf" -version = "0.13.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" dependencies = [ "phf_macros", "phf_shared", - "serde", -] - -[[package]] -name = "phf_codegen" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49aa7f9d80421bca176ca8dbfebe668cc7a2684708594ec9f3c0db0805d5d6e1" -dependencies = [ - "phf_generator", - "phf_shared", ] [[package]] name = "phf_generator" -version = "0.13.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737" +checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ - "fastrand 2.4.1", "phf_shared", + "rand 0.8.6", ] [[package]] name = "phf_macros" -version = "0.13.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef" +checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" dependencies = [ "phf_generator", "phf_shared", "proc-macro2", "quote", "syn 2.0.117", + "unicase", ] [[package]] name = "phf_shared" -version = "0.13.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" dependencies = [ "siphasher", + "unicase", ] [[package]] @@ -3169,30 +3421,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" [[package]] -name = "plist" -version = "1.9.0" +name = "plain" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "092791278e026273c1b65bbdcfbba3a300f2994c896bd01ab01da613c29c46f1" -dependencies = [ - "base64 0.22.1", - "indexmap 2.14.0", - "quick-xml", - "serde", - "time", -] - -[[package]] -name = "png" -version = "0.17.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" -dependencies = [ - "bitflags 1.3.2", - "crc32fast", - "fdeflate", - "flate2", - "miniz_oxide", -] +checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" [[package]] name = "png" @@ -3246,12 +3478,6 @@ dependencies = [ "zerovec", ] -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - [[package]] name = "ppv-lite86" version = "0.2.21" @@ -3262,10 +3488,10 @@ dependencies = [ ] [[package]] -name = "precomputed-hash" -version = "0.1.1" +name = "presser" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" +checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa" [[package]] name = "prettyplease" @@ -3287,16 +3513,6 @@ dependencies = [ "toml_edit 0.19.15", ] -[[package]] -name = "proc-macro-crate" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b00f26d3400549137f92511a46ac1cd8ce37cb5598a96d382381458b992a5d24" -dependencies = [ - "toml_datetime 0.6.3", - "toml_edit 0.20.2", -] - [[package]] name = "proc-macro-crate" version = "3.5.0" @@ -3306,30 +3522,6 @@ dependencies = [ "toml_edit 0.25.12+spec-1.1.0", ] -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - [[package]] name = "proc-macro2" version = "1.0.106" @@ -3339,6 +3531,46 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "profiling" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d595e54a326bc53c1c197b32d295e14b169e3cfeaa8dc82b529f947fba6bcf5" +dependencies = [ + "profiling-procmacros", +] + +[[package]] +name = "profiling-procmacros" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4488a4a36b9a4ba6b9334a32a39971f77c1436ec82c38707bce707699cc3bbcb" +dependencies = [ + "quote", + "syn 2.0.117", +] + +[[package]] +name = "pxfm" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0c5ccf5294c6ccd63a74f1565028353830a9c2f5eb0c682c355c471726a6e3f" + +[[package]] +name = "qoi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + [[package]] name = "quick-xml" version = "0.39.4" @@ -3376,8 +3608,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.5", ] [[package]] @@ -3387,7 +3629,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.5", ] [[package]] @@ -3399,12 +3651,106 @@ dependencies = [ "getrandom 0.2.17", ] +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", +] + +[[package]] +name = "rav1e" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43b6dd56e85d9483277cde964fd1bdb0428de4fec5ebba7540995639a21cb32b" +dependencies = [ + "aligned-vec", + "arbitrary", + "arg_enum_proc_macro", + "arrayvec", + "av-scenechange", + "av1-grain", + "bitstream-io", + "built", + "cfg-if", + "interpolate_name", + "itertools", + "libc", + "libfuzzer-sys", + "log", + "maybe-rayon", + "new_debug_unreachable", + "noop_proc_macro", + "num-derive", + "num-traits", + "paste", + "profiling", + "rand 0.9.4", + "rand_chacha 0.9.0", + "simd_helpers", + "thiserror 2.0.18", + "v_frame", + "wasm-bindgen", +] + +[[package]] +name = "ravif" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e52310197d971b0f5be7fe6b57530dcd27beb35c1b013f29d66c1ad73fbbcc45" +dependencies = [ + "avif-serialize", + "imgref", + "loop9", + "quick-error", + "rav1e", + "rayon", + "rgb", +] + +[[package]] +name = "raw-window-handle" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" + [[package]] name = "raw-window-handle" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" +[[package]] +name = "rayon" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "redox_syscall" version = "0.5.18" @@ -3414,6 +3760,15 @@ dependencies = [ "bitflags 2.13.0", ] +[[package]] +name = "redox_syscall" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b44b894f2a6e36457d665d1e08c3866add6ed5e70050c1b4ba8a8ddedb02ce7" +dependencies = [ + "bitflags 2.13.0", +] + [[package]] name = "redox_users" version = "0.4.6" @@ -3425,37 +3780,6 @@ dependencies = [ "thiserror 1.0.69", ] -[[package]] -name = "redox_users" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" -dependencies = [ - "getrandom 0.2.17", - "libredox", - "thiserror 2.0.18", -] - -[[package]] -name = "ref-cast" -version = "1.0.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" -dependencies = [ - "ref-cast-impl", -] - -[[package]] -name = "ref-cast-impl" -version = "1.0.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "regex" version = "1.12.4" @@ -3486,38 +3810,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" [[package]] -name = "reqwest" -version = "0.13.4" +name = "renderdoc-sys" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "219c5811de6525e5416c7d5d53bb656d3afdbc6c5af816e0802bcfa42dbdc1c3" -dependencies = [ - "base64 0.22.1", - "bytes", - "futures-core", - "futures-util", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-util", - "js-sys", - "log", - "percent-encoding", - "pin-project-lite", - "serde", - "serde_json", - "sync_wrapper", - "tokio", - "tokio-util", - "tower", - "tower-http", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "wasm-streams", - "web-sys", -] +checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" + +[[package]] +name = "rgb" +version = "0.8.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b34b781b31e5d73e9fbc8689c70551fd1ade9a19e3e28cfec8580a79290cc4" [[package]] name = "rusqlite" @@ -3533,6 +3835,12 @@ dependencies = [ "smallvec", ] +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustc-hash" version = "2.1.2" @@ -3613,55 +3921,10 @@ dependencies = [ ] [[package]] -name = "schemars" -version = "0.8.22" +name = "scoped-tls" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fbf2ae1b8bc8e02df939598064d22402220cd5bbcca1c76f7d6a310974d5615" -dependencies = [ - "dyn-clone", - "indexmap 1.9.3", - "schemars_derive", - "serde", - "serde_json", - "url", - "uuid", -] - -[[package]] -name = "schemars" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" -dependencies = [ - "dyn-clone", - "ref-cast", - "serde", - "serde_json", -] - -[[package]] -name = "schemars" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc" -dependencies = [ - "dyn-clone", - "ref-cast", - "serde", - "serde_json", -] - -[[package]] -name = "schemars_derive" -version = "0.8.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32e265784ad618884abaea0600a9adf15393368d840e0222d101a072f3f7534d" -dependencies = [ - "proc-macro2", - "quote", - "serde_derive_internals", - "syn 2.0.117", -] +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" [[package]] name = "scopeguard" @@ -3669,6 +3932,19 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "sctk-adwaita" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70b31447ca297092c5a9916fc3b955203157b37c19ca8edde4f52e9843e602c7" +dependencies = [ + "ab_glyph", + "log", + "memmap2", + "smithay-client-toolkit 0.18.1", + "tiny-skia", +] + [[package]] name = "secret-service" version = "3.1.0" @@ -3682,7 +3958,7 @@ dependencies = [ "hkdf", "num", "once_cell", - "rand", + "rand 0.8.6", "serde", "sha2", "zbus", @@ -3724,34 +4000,11 @@ dependencies = [ "libc", ] -[[package]] -name = "selectors" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5d9c0c92a92d33f08817311cf3f2c29a3538a8240e94a6a3c622ce652d7e00c" -dependencies = [ - "bitflags 2.13.0", - "cssparser", - "derive_more", - "log", - "new_debug_unreachable", - "phf", - "phf_codegen", - "precomputed-hash", - "rustc-hash", - "servo_arc", - "smallvec", -] - [[package]] name = "semver" version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" -dependencies = [ - "serde", - "serde_core", -] [[package]] name = "serde" @@ -3763,18 +4016,6 @@ dependencies = [ "serde_derive", ] -[[package]] -name = "serde-untagged" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9faf48a4a2d2693be24c6289dbe26552776eb7737074e6722891fadbe6c5058" -dependencies = [ - "erased-serde", - "serde", - "serde_core", - "typeid", -] - [[package]] name = "serde_core" version = "1.0.228" @@ -3795,17 +4036,6 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "serde_derive_internals" -version = "0.29.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "serde_json" version = "1.0.150" @@ -3830,87 +4060,6 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "serde_spanned" -version = "0.6.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" -dependencies = [ - "serde", -] - -[[package]] -name = "serde_spanned" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" -dependencies = [ - "serde_core", -] - -[[package]] -name = "serde_with" -version = "3.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76a5c54c7310e7b8b9577c286d7e399ddd876c3e12b3ed917a8aabc4b96e9e8c" -dependencies = [ - "base64 0.22.1", - "bs58", - "chrono", - "hex", - "indexmap 1.9.3", - "indexmap 2.14.0", - "schemars 0.9.0", - "schemars 1.2.1", - "serde_core", - "serde_json", - "serde_with_macros", - "time", -] - -[[package]] -name = "serde_with_macros" -version = "3.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84d57bc0c8b9a17920c178daa6bb924850d54a9c97ab45194bb8c17ad66bb660" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "serialize-to-javascript" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04f3666a07a197cdb77cdf306c32be9b7f598d7060d50cfd4d5aa04bfd92f6c5" -dependencies = [ - "serde", - "serde_json", - "serialize-to-javascript-impl", -] - -[[package]] -name = "serialize-to-javascript-impl" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "772ee033c0916d670af7860b6e1ef7d658a4629a6d0b4c8c3e67f09b3765b75d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "servo_arc" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "170fb83ab34de17dc69aa7c67482b22218ddb85da56546f9bd6b929e32a05930" -dependencies = [ - "stable_deref_trait", -] - [[package]] name = "sha1" version = "0.10.6" @@ -3942,44 +4091,12 @@ dependencies = [ "lazy_static", ] -[[package]] -name = "shared_child" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e362d9935bc50f019969e2f9ecd66786612daae13e8f277be7bfb66e8bed3f7" -dependencies = [ - "libc", - "sigchld", - "windows-sys 0.60.2", -] - [[package]] name = "shlex" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" -[[package]] -name = "sigchld" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47106eded3c154e70176fc83df9737335c94ce22f821c32d17ed1db1f83badb1" -dependencies = [ - "libc", - "os_pipe", - "signal-hook", -] - -[[package]] -name = "signal-hook" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2" -dependencies = [ - "libc", - "signal-hook-registry", -] - [[package]] name = "signal-hook-registry" version = "1.4.8" @@ -3996,6 +4113,31 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" +[[package]] +name = "simd_cesu8" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33" +dependencies = [ + "rustc_version", + "simdutf8", +] + +[[package]] +name = "simd_helpers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" +dependencies = [ + "quote", +] + +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + [[package]] name = "siphasher" version = "1.0.3" @@ -4008,12 +4150,93 @@ version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" +[[package]] +name = "slotmap" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038" +dependencies = [ + "version_check", +] + [[package]] name = "smallvec" version = "1.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" +[[package]] +name = "smithay-client-toolkit" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "922fd3eeab3bd820d76537ce8f582b1cf951eceb5475c28500c7457d9d17f53a" +dependencies = [ + "bitflags 2.13.0", + "calloop 0.12.4", + "calloop-wayland-source 0.2.0", + "cursor-icon", + "libc", + "log", + "memmap2", + "rustix 0.38.44", + "thiserror 1.0.69", + "wayland-backend", + "wayland-client", + "wayland-csd-frame", + "wayland-cursor", + "wayland-protocols 0.31.2", + "wayland-protocols-wlr 0.2.0", + "wayland-scanner", + "xkeysym", +] + +[[package]] +name = "smithay-client-toolkit" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0512da38f5e2b31201a93524adb8d3136276fa4fe4aafab4e1f727a82b534cc0" +dependencies = [ + "bitflags 2.13.0", + "calloop 0.14.4", + "calloop-wayland-source 0.4.1", + "cursor-icon", + "libc", + "log", + "memmap2", + "rustix 1.1.4", + "thiserror 2.0.18", + "wayland-backend", + "wayland-client", + "wayland-csd-frame", + "wayland-cursor", + "wayland-protocols 0.32.12", + "wayland-protocols-experimental", + "wayland-protocols-misc", + "wayland-protocols-wlr 0.3.12", + "wayland-scanner", + "xkeysym", +] + +[[package]] +name = "smithay-clipboard" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71704c03f739f7745053bde45fa203a46c58d25bc5c4efba1d9a60e9dba81226" +dependencies = [ + "libc", + "smithay-client-toolkit 0.20.0", + "wayland-backend", +] + +[[package]] +name = "smol_str" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead" +dependencies = [ + "serde", +] + [[package]] name = "socket2" version = "0.4.10" @@ -4035,51 +4258,12 @@ dependencies = [ ] [[package]] -name = "softbuffer" -version = "0.4.8" +name = "spirv" +version = "0.3.0+sdk-1.3.268.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aac18da81ebbf05109ab275b157c22a653bb3c12cf884450179942f81bcbf6c3" +checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" dependencies = [ - "bytemuck", - "js-sys", - "ndk", - "objc2", - "objc2-core-foundation", - "objc2-core-graphics", - "objc2-foundation", - "objc2-quartz-core", - "raw-window-handle", - "redox_syscall", - "tracing", - "wasm-bindgen", - "web-sys", - "windows-sys 0.61.2", -] - -[[package]] -name = "soup3" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "471f924a40f31251afc77450e781cb26d55c0b650842efafc9c6cbd2f7cc4f9f" -dependencies = [ - "futures-channel", - "gio", - "glib", - "libc", - "soup3-sys", -] - -[[package]] -name = "soup3-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ebe8950a680a12f24f15ebe1bf70db7af98ad242d9db43596ad3108aab86c27" -dependencies = [ - "gio-sys", - "glib-sys", - "gobject-sys", - "libc", - "system-deps", + "bitflags 2.13.0", ] [[package]] @@ -4107,34 +4291,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] -name = "string_cache" -version = "0.9.0" +name = "strict-num" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a18596f8c785a729f2819c0f6a7eae6ebeebdfffbfe4214ae6b087f690e31901" -dependencies = [ - "new_debug_unreachable", - "parking_lot", - "phf_shared", - "precomputed-hash", -] - -[[package]] -name = "string_cache_codegen" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585635e46db231059f76c5849798146164652513eb9e8ab2685939dd90f29b69" -dependencies = [ - "phf_generator", - "phf_shared", - "proc-macro2", - "quote", -] - -[[package]] -name = "strsim" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" [[package]] name = "subtle" @@ -4159,17 +4319,6 @@ dependencies = [ "thiserror 2.0.18", ] -[[package]] -name = "swift-rs" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4057c98e2e852d51fdcfca832aac7b571f6b351ad159f9eda5db1655f8d0c4d7" -dependencies = [ - "base64 0.21.7", - "serde", - "serde_json", -] - [[package]] name = "syn" version = "1.0.109" @@ -4192,15 +4341,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "sync_wrapper" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" -dependencies = [ - "futures-core", -] - [[package]] name = "synstructure" version = "0.13.2" @@ -4212,326 +4352,6 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "system-deps" -version = "6.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" -dependencies = [ - "cfg-expr", - "heck 0.5.0", - "pkg-config", - "toml 0.8.2", - "version-compare", -] - -[[package]] -name = "tao" -version = "0.35.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1c93047acf68669466a34690ac58cca7010bd1b201e1ec86f1fd0a75d3dd4a9" -dependencies = [ - "bitflags 2.13.0", - "block2", - "core-foundation 0.10.1", - "core-graphics", - "crossbeam-channel", - "dbus", - "dispatch2", - "dlopen2", - "dpi", - "gdkwayland-sys", - "gdkx11-sys", - "gtk", - "jni", - "libc", - "log", - "ndk", - "ndk-sys", - "objc2", - "objc2-app-kit", - "objc2-foundation", - "objc2-ui-kit", - "once_cell", - "parking_lot", - "percent-encoding", - "raw-window-handle", - "tao-macros", - "unicode-segmentation", - "url", - "windows", - "windows-core 0.61.2", - "windows-version", - "x11-dl", -] - -[[package]] -name = "tao-macros" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4e16beb8b2ac17db28eab8bca40e62dbfbb34c0fcdc6d9826b11b7b5d047dfd" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "target-lexicon" -version = "0.12.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" - -[[package]] -name = "tauri" -version = "2.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "437404997acf375d85f1177afa7e11bb971f274ed6a7b83a2a3e339015f4cc28" -dependencies = [ - "anyhow", - "bytes", - "cookie", - "dirs 6.0.0", - "dunce", - "embed_plist", - "getrandom 0.3.4", - "glob", - "gtk", - "heck 0.5.0", - "http", - "jni", - "libc", - "log", - "mime", - "muda", - "objc2", - "objc2-app-kit", - "objc2-foundation", - "objc2-ui-kit", - "objc2-web-kit", - "percent-encoding", - "plist", - "raw-window-handle", - "reqwest", - "serde", - "serde_json", - "serde_repr", - "serialize-to-javascript", - "swift-rs", - "tauri-build", - "tauri-macros", - "tauri-runtime", - "tauri-runtime-wry", - "tauri-utils", - "thiserror 2.0.18", - "tokio", - "tray-icon", - "url", - "webkit2gtk", - "webview2-com", - "window-vibrancy", - "windows", -] - -[[package]] -name = "tauri-build" -version = "2.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4aa1f9055fc23919a54e4e125052bed16ed04aef0487086e758fe01a67b451c7" -dependencies = [ - "anyhow", - "cargo_toml", - "dirs 6.0.0", - "glob", - "heck 0.5.0", - "json-patch", - "schemars 0.8.22", - "semver", - "serde", - "serde_json", - "tauri-utils", - "tauri-winres", - "walkdir", -] - -[[package]] -name = "tauri-codegen" -version = "2.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4a0319528a025a38c4078e7dae2c446f4e63620ddb0659a643ede1cb38f90e9" -dependencies = [ - "base64 0.22.1", - "brotli", - "ico", - "json-patch", - "plist", - "png 0.17.16", - "proc-macro2", - "quote", - "semver", - "serde", - "serde_json", - "sha2", - "syn 2.0.117", - "tauri-utils", - "thiserror 2.0.18", - "time", - "url", - "uuid", - "walkdir", -] - -[[package]] -name = "tauri-macros" -version = "2.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae6cb4e3896c21d2f6da5b31251d2faea0153bba56ed0e970f918115dbee4924" -dependencies = [ - "heck 0.5.0", - "proc-macro2", - "quote", - "syn 2.0.117", - "tauri-codegen", - "tauri-utils", -] - -[[package]] -name = "tauri-plugin" -version = "2.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e126abc9e84e35cdfd01596140a73a1850cdb0df0a23acf0185776c30b469a6e" -dependencies = [ - "anyhow", - "glob", - "plist", - "schemars 0.8.22", - "serde", - "serde_json", - "tauri-utils", - "walkdir", -] - -[[package]] -name = "tauri-plugin-shell" -version = "2.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8457dbf9e2bab1edd8df22bb2c20857a59a9868e79cb3eac5ed639eec4d0c73b" -dependencies = [ - "encoding_rs", - "log", - "open", - "os_pipe", - "regex", - "schemars 0.8.22", - "serde", - "serde_json", - "shared_child", - "tauri", - "tauri-plugin", - "thiserror 2.0.18", - "tokio", -] - -[[package]] -name = "tauri-runtime" -version = "2.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48222d7116c8807eaa6fe2f372e023fae125084e61e6eca6d70b7961cdf129ef" -dependencies = [ - "cookie", - "dpi", - "gtk", - "http", - "jni", - "objc2", - "objc2-ui-kit", - "objc2-web-kit", - "raw-window-handle", - "serde", - "serde_json", - "tauri-utils", - "thiserror 2.0.18", - "url", - "webkit2gtk", - "webview2-com", - "windows", -] - -[[package]] -name = "tauri-runtime-wry" -version = "2.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b83849ee63ecb27a8e8d0fe51915ca215076914aca43f96db1179f0f415f6cd9" -dependencies = [ - "gtk", - "http", - "jni", - "log", - "objc2", - "objc2-app-kit", - "once_cell", - "percent-encoding", - "raw-window-handle", - "softbuffer", - "tao", - "tauri-runtime", - "tauri-utils", - "url", - "webkit2gtk", - "webview2-com", - "windows", - "wry", -] - -[[package]] -name = "tauri-utils" -version = "2.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "092379df9a707631978e6c56b1bc2401d387f01e2d4a3c123360d167bbb9aa95" -dependencies = [ - "anyhow", - "brotli", - "cargo_metadata", - "ctor", - "dom_query", - "dunce", - "glob", - "http", - "infer", - "json-patch", - "log", - "memchr", - "phf", - "plist", - "proc-macro2", - "quote", - "regex", - "schemars 0.8.22", - "semver", - "serde", - "serde-untagged", - "serde_json", - "serde_with", - "swift-rs", - "thiserror 2.0.18", - "toml 1.1.2+spec-1.1.0", - "url", - "urlpattern", - "uuid", - "walkdir", -] - -[[package]] -name = "tauri-winres" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc65d45c68858bfe420dd29e834b5d15dbecf8a07a8a16cf4d532c7b1f69d4b6" -dependencies = [ - "dunce", - "embed-resource", - "toml 1.1.2+spec-1.1.0", -] - [[package]] name = "tempfile" version = "3.27.0" @@ -4546,13 +4366,12 @@ dependencies = [ ] [[package]] -name = "tendril" -version = "0.5.0" +name = "termcolor" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4790fc369d5a530f4b544b094e31388b9b3a37c0f4652ade4505945f5660d24" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ - "new_debug_unreachable", - "utf-8", + "winapi-util", ] [[package]] @@ -4605,34 +4424,42 @@ dependencies = [ ] [[package]] -name = "time" -version = "0.3.47" +name = "tiff" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" +checksum = "b63feaf3343d35b6ca4d50483f94843803b0f51634937cc2ec519fc32232bc52" dependencies = [ - "deranged", - "itoa", - "num-conv", - "powerfmt", - "serde_core", - "time-core", - "time-macros", + "fax", + "flate2", + "half", + "quick-error", + "weezl", + "zune-jpeg", ] [[package]] -name = "time-core" -version = "0.1.8" +name = "tiny-skia" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" +checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab" +dependencies = [ + "arrayref", + "arrayvec", + "bytemuck", + "cfg-if", + "log", + "tiny-skia-path", +] [[package]] -name = "time-macros" -version = "0.2.27" +name = "tiny-skia-path" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" +checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93" dependencies = [ - "num-conv", - "time-core", + "arrayref", + "bytemuck", + "strict-num", ] [[package]] @@ -4645,21 +4472,6 @@ dependencies = [ "zerovec", ] -[[package]] -name = "tinyvec" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - [[package]] name = "tokio" version = "1.52.3" @@ -4688,78 +4500,11 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "tokio-util" -version = "0.7.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "toml" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" -dependencies = [ - "serde", - "serde_spanned 0.6.9", - "toml_datetime 0.6.3", - "toml_edit 0.20.2", -] - -[[package]] -name = "toml" -version = "0.9.12+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" -dependencies = [ - "indexmap 2.14.0", - "serde_core", - "serde_spanned 1.1.1", - "toml_datetime 0.7.5+spec-1.1.0", - "toml_parser", - "toml_writer", - "winnow 0.7.15", -] - -[[package]] -name = "toml" -version = "1.1.2+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee" -dependencies = [ - "indexmap 2.14.0", - "serde_core", - "serde_spanned 1.1.1", - "toml_datetime 1.1.1+spec-1.1.0", - "toml_parser", - "toml_writer", - "winnow 1.0.3", -] - [[package]] name = "toml_datetime" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" -dependencies = [ - "serde", -] - -[[package]] -name = "toml_datetime" -version = "0.7.5+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" -dependencies = [ - "serde_core", -] [[package]] name = "toml_datetime" @@ -4776,20 +4521,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.14.0", - "toml_datetime 0.6.3", - "winnow 0.5.40", -] - -[[package]] -name = "toml_edit" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" -dependencies = [ - "indexmap 2.14.0", - "serde", - "serde_spanned 0.6.9", + "indexmap", "toml_datetime 0.6.3", "winnow 0.5.40", ] @@ -4800,7 +4532,7 @@ version = "0.25.12+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2153edc6955a6c354fad8f5efd38b6a8769bdccf9fe50f8e1329f81b0baa5d7" dependencies = [ - "indexmap 2.14.0", + "indexmap", "toml_datetime 1.1.1+spec-1.1.0", "toml_parser", "winnow 1.0.3", @@ -4815,63 +4547,13 @@ dependencies = [ "winnow 1.0.3", ] -[[package]] -name = "toml_writer" -version = "1.1.1+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" - -[[package]] -name = "tower" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" -dependencies = [ - "futures-core", - "futures-util", - "pin-project-lite", - "sync_wrapper", - "tokio", - "tower-layer", - "tower-service", -] - -[[package]] -name = "tower-http" -version = "0.6.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" -dependencies = [ - "bitflags 2.13.0", - "bytes", - "futures-util", - "http", - "http-body", - "pin-project-lite", - "tower", - "tower-layer", - "tower-service", - "url", -] - -[[package]] -name = "tower-layer" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" - -[[package]] -name = "tower-service" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" - [[package]] name = "tracing" version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -4924,39 +4606,20 @@ dependencies = [ ] [[package]] -name = "tray-icon" -version = "0.23.1" +name = "ttf-parser" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15edbb0d80583e85ee8df283410038e17314df5cba30da2087a54a85216c0773" +checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" + +[[package]] +name = "type-map" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb30dbbd9036155e74adad6812e9898d03ec374946234fbcebd5dfc7b9187b90" dependencies = [ - "crossbeam-channel", - "dirs 6.0.0", - "libappindicator", - "muda", - "objc2", - "objc2-app-kit", - "objc2-core-foundation", - "objc2-core-graphics", - "objc2-foundation", - "once_cell", - "png 0.18.1", - "serde", - "thiserror 2.0.18", - "windows-sys 0.61.2", + "rustc-hash 2.1.2", ] -[[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - -[[package]] -name = "typeid" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" - [[package]] name = "typenum" version = "1.20.1" @@ -4975,45 +4638,10 @@ dependencies = [ ] [[package]] -name = "unic-char-property" -version = "0.9.0" +name = "unicase" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221" -dependencies = [ - "unic-char-range", -] - -[[package]] -name = "unic-char-range" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc" - -[[package]] -name = "unic-common" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc" - -[[package]] -name = "unic-ucd-ident" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e230a37c0381caa9219d67cf063aa3a375ffed5bf541a452db16e744bdab6987" -dependencies = [ - "unic-char-property", - "unic-char-range", - "unic-ucd-version", -] - -[[package]] -name = "unic-ucd-version" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4" -dependencies = [ - "unic-common", -] +checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" [[package]] name = "unicode-ident" @@ -5027,6 +4655,12 @@ version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + [[package]] name = "unicode-xid" version = "0.2.6" @@ -5043,27 +4677,8 @@ dependencies = [ "idna", "percent-encoding", "serde", - "serde_derive", ] -[[package]] -name = "urlpattern" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70acd30e3aa1450bc2eece896ce2ad0d178e9c079493819301573dae3c37ba6d" -dependencies = [ - "regex", - "serde", - "unic-ucd-ident", - "url", -] - -[[package]] -name = "utf-8" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" - [[package]] name = "utf8_iter" version = "1.0.4" @@ -5078,7 +4693,17 @@ checksum = "144d6b123cef80b301b8f72a9e2ca4370ddec21950d0a103dd22c437006d2db7" dependencies = [ "getrandom 0.4.2", "js-sys", - "serde_core", + "wasm-bindgen", +] + +[[package]] +name = "v_frame" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "666b7727c8875d6ab5db9533418d7c764233ac9c0cff1d469aec8fa127597be2" +dependencies = [ + "aligned-vec", + "num-traits", "wasm-bindgen", ] @@ -5100,38 +4725,12 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" -[[package]] -name = "version-compare" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c2856837ef78f57382f06b2b8563a2f512f7185d732608fd9176cb3b8edf0e" - [[package]] name = "version_check" version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" -[[package]] -name = "vswhom" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be979b7f07507105799e854203b470ff7c78a1639e330a58f183b5fea574608b" -dependencies = [ - "libc", - "vswhom-sys", -] - -[[package]] -name = "vswhom-sys" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb067e4cbd1ff067d1df46c9194b5de0e98efd2810bbc95c5d5e5f25a3231150" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "waker-fn" version = "1.2.0" @@ -5148,15 +4747,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" @@ -5253,24 +4843,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" dependencies = [ "anyhow", - "indexmap 2.14.0", + "indexmap", "wasm-encoder", "wasmparser", ] -[[package]] -name = "wasm-streams" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d1ec4f6517c9e11ae630e200b2b65d193279042e28edd4a2cda233e46670bbb" -dependencies = [ - "futures-util", - "js-sys", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - [[package]] name = "wasmparser" version = "0.244.0" @@ -5279,10 +4856,170 @@ checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" dependencies = [ "bitflags 2.13.0", "hashbrown 0.15.5", - "indexmap 2.14.0", + "indexmap", "semver", ] +[[package]] +name = "wayland-backend" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2857dd20b54e916ec7253b3d6b4d5c4d7d4ca2c33c2e11c6c76a99bd8744755d" +dependencies = [ + "cc", + "downcast-rs", + "rustix 1.1.4", + "scoped-tls", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-client" +version = "0.31.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c7c96bb74690c3189b5c9cb4ca1627062bb23693a4fad9d8c3de958260144" +dependencies = [ + "bitflags 2.13.0", + "rustix 1.1.4", + "wayland-backend", + "wayland-scanner", +] + +[[package]] +name = "wayland-csd-frame" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" +dependencies = [ + "bitflags 2.13.0", + "cursor-icon", + "wayland-backend", +] + +[[package]] +name = "wayland-cursor" +version = "0.31.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a52d18780be9b1314328a3de5f930b73d2200112e3849ca6cb11822793fb34d" +dependencies = [ + "rustix 1.1.4", + "wayland-client", + "xcursor", +] + +[[package]] +name = "wayland-protocols" +version = "0.31.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f81f365b8b4a97f422ac0e8737c438024b5951734506b0e1d775c73030561f4" +dependencies = [ + "bitflags 2.13.0", + "wayland-backend", + "wayland-client", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols" +version = "0.32.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "563a85523cade2429938e790815fd7319062103b9f4a2dc806e9b53b95982d8f" +dependencies = [ + "bitflags 2.13.0", + "wayland-backend", + "wayland-client", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-experimental" +version = "20250721.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40a1f863128dcaaec790d7b4b396cc9b9a7a079e878e18c47e6c2d2c5a8dcbb1" +dependencies = [ + "bitflags 2.13.0", + "wayland-backend", + "wayland-client", + "wayland-protocols 0.32.12", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-misc" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e9567599ef23e09b8dad6e429e5738d4509dfc46b3b21f32841a304d16b29c8" +dependencies = [ + "bitflags 2.13.0", + "wayland-backend", + "wayland-client", + "wayland-protocols 0.32.12", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-plasma" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23803551115ff9ea9bce586860c5c5a971e360825a0309264102a9495a5ff479" +dependencies = [ + "bitflags 2.13.0", + "wayland-backend", + "wayland-client", + "wayland-protocols 0.31.2", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-wlr" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad1f61b76b6c2d8742e10f9ba5c3737f6530b4c243132c2a2ccc8aa96fe25cd6" +dependencies = [ + "bitflags 2.13.0", + "wayland-backend", + "wayland-client", + "wayland-protocols 0.31.2", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-wlr" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb04e52f7836d7c7976c78ca0250d61e33873c34156a2a1fc9474828ec268234" +dependencies = [ + "bitflags 2.13.0", + "wayland-backend", + "wayland-client", + "wayland-protocols 0.32.12", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.31.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c324a910fd86ebdc364a3e61ec1f11737d3b1d6c273c0239ee8ff4bc0d24b4a" +dependencies = [ + "proc-macro2", + "quick-xml", + "quote", +] + +[[package]] +name = "wayland-sys" +version = "0.31.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8eab23fefc9e41f8e841df4a9c707e8a8c4ed26e944ef69297184de2785e3be" +dependencies = [ + "dlib", + "log", + "once_cell", + "pkg-config", +] + [[package]] name = "web-sys" version = "0.3.102" @@ -5294,96 +5031,146 @@ dependencies = [ ] [[package]] -name = "web_atoms" +name = "web-time" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7cff6eef815df1834fd250e3a2ff436044d82a9f1bc1980ca1dbdf07effc538" +checksum = "aa30049b1c872b72c89866d458eae9f20380ab280ffd1b1e18df2d3e2d98cfe0" dependencies = [ - "phf", - "phf_codegen", - "string_cache", - "string_cache_codegen", + "js-sys", + "wasm-bindgen", ] [[package]] -name = "webkit2gtk" -version = "2.0.2" +name = "webbrowser" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1027150013530fb2eaf806408df88461ae4815a45c541c8975e61d6f2fc4793" +checksum = "0fc95580916af1e68ff6a7be07446fc5db73ebf71cf092de939bbf5f7e189f72" dependencies = [ - "bitflags 1.3.2", - "cairo-rs", - "gdk", - "gdk-sys", - "gio", - "gio-sys", - "glib", - "glib-sys", - "gobject-sys", - "gtk", - "gtk-sys", - "javascriptcore-rs", - "libc", + "core-foundation 0.10.1", + "jni 0.22.4", + "log", + "ndk-context", + "objc2 0.6.4", + "objc2-foundation 0.3.2", + "url", + "web-sys", +] + +[[package]] +name = "weezl" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88" + +[[package]] +name = "wgpu" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90e37c7b9921b75dfd26dd973fdcbce36f13dfa6e2dc82aece584e0ed48c355c" +dependencies = [ + "arrayvec", + "cfg-if", + "cfg_aliases", + "document-features", + "js-sys", + "log", + "parking_lot", + "profiling", + "raw-window-handle 0.6.2", + "smallvec", + "static_assertions", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "wgpu-core", + "wgpu-hal", + "wgpu-types", +] + +[[package]] +name = "wgpu-core" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d50819ab545b867d8a454d1d756b90cd5f15da1f2943334ca314af10583c9d39" +dependencies = [ + "arrayvec", + "bit-vec", + "bitflags 2.13.0", + "cfg_aliases", + "codespan-reporting", + "document-features", + "indexmap", + "log", + "naga", "once_cell", - "soup3", - "webkit2gtk-sys", + "parking_lot", + "profiling", + "raw-window-handle 0.6.2", + "rustc-hash 1.1.0", + "smallvec", + "thiserror 1.0.69", + "web-sys", + "wgpu-hal", + "wgpu-types", ] [[package]] -name = "webkit2gtk-sys" -version = "2.0.2" +name = "wgpu-hal" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "916a5f65c2ef0dfe12fff695960a2ec3d4565359fdbb2e9943c974e06c734ea5" +checksum = "172e490a87295564f3fcc0f165798d87386f6231b04d4548bca458cbbfd63222" dependencies = [ - "bitflags 1.3.2", - "cairo-sys-rs", - "gdk-sys", - "gio-sys", - "glib-sys", - "gobject-sys", - "gtk-sys", - "javascriptcore-rs-sys", + "android_system_properties", + "arrayvec", + "ash", + "bitflags 2.13.0", + "cfg_aliases", + "core-graphics-types", + "glow", + "glutin_wgl_sys", + "gpu-alloc", + "gpu-allocator", + "gpu-descriptor", + "hassle-rs", + "js-sys", + "khronos-egl", "libc", - "pkg-config", - "soup3-sys", - "system-deps", + "libloading 0.7.4", + "log", + "metal", + "naga", + "ndk-sys", + "objc", + "once_cell", + "parking_lot", + "profiling", + "raw-window-handle 0.6.2", + "renderdoc-sys", + "rustc-hash 1.1.0", + "smallvec", + "thiserror 1.0.69", + "wasm-bindgen", + "web-sys", + "wgpu-types", + "winapi", ] [[package]] -name = "webview2-com" -version = "0.38.2" +name = "wgpu-types" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7130243a7a5b33c54a444e54842e6a9e133de08b5ad7b5861cd8ed9a6a5bc96a" +checksum = "1353d9a46bff7f955a680577f34c69122628cc2076e1d6f3a9be6ef00ae793ef" dependencies = [ - "webview2-com-macros", - "webview2-com-sys", - "windows", - "windows-core 0.61.2", - "windows-implement", - "windows-interface", + "bitflags 2.13.0", + "js-sys", + "web-sys", ] [[package]] -name = "webview2-com-macros" -version = "0.8.1" +name = "widestring" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67a921c1b6914c367b2b823cd4cde6f96beec77d30a939c8199bb377cf9b9b54" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "webview2-com-sys" -version = "0.38.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "381336cfffd772377d291702245447a5251a2ffa5bad679c99e61bc48bacbf9c" -dependencies = [ - "thiserror 2.0.18", - "windows", - "windows-core 0.61.2", -] +checksum = "72069c3113ab32ab29e5584db3c6ec55d416895e60715417b5b883a357c3e471" [[package]] name = "winapi" @@ -5417,53 +5204,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "window-vibrancy" -version = "0.6.0" +name = "windows" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9bec5a31f3f9362f2258fd0e9c9dd61a9ca432e7306cc78c444258f0dce9a9c" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ - "objc2", - "objc2-app-kit", - "objc2-core-foundation", - "objc2-foundation", - "raw-window-handle", - "windows-sys 0.59.0", - "windows-version", + "windows-implement 0.48.0", + "windows-interface 0.48.0", + "windows-targets 0.48.5", ] [[package]] name = "windows" -version = "0.61.3" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" +checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" dependencies = [ - "windows-collections", - "windows-core 0.61.2", - "windows-future", - "windows-link 0.1.3", - "windows-numerics", -] - -[[package]] -name = "windows-collections" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" -dependencies = [ - "windows-core 0.61.2", + "windows-core 0.52.0", + "windows-targets 0.52.6", ] [[package]] name = "windows-core" -version = "0.61.2" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-implement", - "windows-interface", - "windows-link 0.1.3", - "windows-result 0.3.4", - "windows-strings 0.4.2", + "windows-targets 0.52.6", ] [[package]] @@ -5472,22 +5239,22 @@ version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ - "windows-implement", - "windows-interface", - "windows-link 0.2.1", - "windows-result 0.4.1", - "windows-strings 0.5.1", + "windows-implement 0.60.2", + "windows-interface 0.59.3", + "windows-link", + "windows-result", + "windows-strings", ] [[package]] -name = "windows-future" -version = "0.2.1" +name = "windows-implement" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" +checksum = "5e2ee588991b9e7e6c8338edf3333fbe4da35dc72092643958ebb43f0ab2c49c" dependencies = [ - "windows-core 0.61.2", - "windows-link 0.1.3", - "windows-threading", + "proc-macro2", + "quote", + "syn 1.0.109", ] [[package]] @@ -5501,6 +5268,17 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "windows-interface" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6fb8df20c9bcaa8ad6ab513f7b40104840c8867d5751126e4df3b08388d0cc7" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "windows-interface" version = "0.59.3" @@ -5512,53 +5290,19 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "windows-link" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" - [[package]] name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" -[[package]] -name = "windows-numerics" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" -dependencies = [ - "windows-core 0.61.2", - "windows-link 0.1.3", -] - -[[package]] -name = "windows-result" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" -dependencies = [ - "windows-link 0.1.3", -] - [[package]] name = "windows-result" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ - "windows-link 0.2.1", -] - -[[package]] -name = "windows-strings" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" -dependencies = [ - "windows-link 0.1.3", + "windows-link", ] [[package]] @@ -5567,7 +5311,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" dependencies = [ - "windows-link 0.2.1", + "windows-link", ] [[package]] @@ -5621,7 +5365,7 @@ version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows-link 0.2.1", + "windows-link", ] [[package]] @@ -5676,7 +5420,7 @@ version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ - "windows-link 0.2.1", + "windows-link", "windows_aarch64_gnullvm 0.53.1", "windows_aarch64_msvc 0.53.1", "windows_i686_gnu 0.53.1", @@ -5687,24 +5431,6 @@ dependencies = [ "windows_x86_64_msvc 0.53.1", ] -[[package]] -name = "windows-threading" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" -dependencies = [ - "windows-link 0.1.3", -] - -[[package]] -name = "windows-version" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4060a1da109b9d0326b7262c8e12c84df67cc0dbc9e33cf49e01ccc2eb63631" -dependencies = [ - "windows-link 0.2.1", -] - [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" @@ -5885,6 +5611,55 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" +[[package]] +name = "winit" +version = "0.29.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d59ad965a635657faf09c8f062badd885748428933dad8e8bdd64064d92e5ca" +dependencies = [ + "ahash", + "android-activity", + "atomic-waker", + "bitflags 2.13.0", + "bytemuck", + "calloop 0.12.4", + "cfg_aliases", + "core-foundation 0.9.4", + "core-graphics", + "cursor-icon", + "icrate", + "js-sys", + "libc", + "log", + "memmap2", + "ndk", + "ndk-sys", + "objc2 0.4.1", + "once_cell", + "orbclient", + "percent-encoding", + "raw-window-handle 0.5.2", + "raw-window-handle 0.6.2", + "redox_syscall 0.3.5", + "rustix 0.38.44", + "sctk-adwaita", + "smithay-client-toolkit 0.18.1", + "smol_str", + "unicode-segmentation", + "wasm-bindgen", + "wasm-bindgen-futures", + "wayland-backend", + "wayland-client", + "wayland-protocols 0.31.2", + "wayland-protocols-plasma", + "web-sys", + "web-time", + "windows-sys 0.48.0", + "x11-dl", + "x11rb", + "xkbcommon-dl", +] + [[package]] name = "winnow" version = "0.5.40" @@ -5894,12 +5669,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "winnow" -version = "0.7.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" - [[package]] name = "winnow" version = "1.0.3" @@ -5909,16 +5678,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "winreg" -version = "0.55.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb5a765337c50e9ec252c2069be9bf91c7df47afb103b642ba3a53bf8101be97" -dependencies = [ - "cfg-if", - "windows-sys 0.59.0", -] - [[package]] name = "wit-bindgen" version = "0.51.0" @@ -5941,7 +5700,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" dependencies = [ "anyhow", - "heck 0.5.0", + "heck", "wit-parser", ] @@ -5952,8 +5711,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" dependencies = [ "anyhow", - "heck 0.5.0", - "indexmap 2.14.0", + "heck", + "indexmap", "prettyplease", "syn 2.0.117", "wasm-metadata", @@ -5984,7 +5743,7 @@ checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" dependencies = [ "anyhow", "bitflags 2.13.0", - "indexmap 2.14.0", + "indexmap", "log", "serde", "serde_derive", @@ -6003,7 +5762,7 @@ checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" dependencies = [ "anyhow", "id-arena", - "indexmap 2.14.0", + "indexmap", "log", "semver", "serde", @@ -6019,60 +5778,6 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" -[[package]] -name = "wry" -version = "0.55.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "186f9871daa55fd9c016578b810d149de58367113db7fb72b462d2323ce19514" -dependencies = [ - "base64 0.22.1", - "block2", - "cookie", - "crossbeam-channel", - "dirs 6.0.0", - "dom_query", - "dpi", - "dunce", - "gdkx11", - "gtk", - "http", - "javascriptcore-rs", - "jni", - "libc", - "ndk", - "objc2", - "objc2-app-kit", - "objc2-core-foundation", - "objc2-foundation", - "objc2-ui-kit", - "objc2-web-kit", - "once_cell", - "percent-encoding", - "raw-window-handle", - "sha2", - "soup3", - "tao-macros", - "thiserror 2.0.18", - "url", - "webkit2gtk", - "webkit2gtk-sys", - "webview2-com", - "windows", - "windows-core 0.61.2", - "windows-version", - "x11-dl", -] - -[[package]] -name = "x11" -version = "2.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "502da5464ccd04011667b11c435cb992822c2c0dbde1770c988480d312a0db2e" -dependencies = [ - "libc", - "pkg-config", -] - [[package]] name = "x11-dl" version = "2.21.0" @@ -6084,6 +5789,33 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "x11rb" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9993aa5be5a26815fe2c3eacfc1fde061fc1a1f094bf1ad2a18bf9c495dd7414" +dependencies = [ + "as-raw-xcb-connection", + "gethostname", + "libc", + "libloading 0.8.9", + "once_cell", + "rustix 1.1.4", + "x11rb-protocol", +] + +[[package]] +name = "x11rb-protocol" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd" + +[[package]] +name = "xcursor" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec9e4a500ca8864c5b47b8b482a73d62e4237670e5b5f1d6b9e3cae50f28f2b" + [[package]] name = "xdg-home" version = "1.3.0" @@ -6094,6 +5826,37 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "xkbcommon-dl" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" +dependencies = [ + "bitflags 2.13.0", + "dlib", + "log", + "once_cell", + "xkeysym", +] + +[[package]] +name = "xkeysym" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" + +[[package]] +name = "xml-rs" +version = "0.8.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" + +[[package]] +name = "y4m" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5a4b21e1a62b67a2970e6831bc091d7b87e119e7f9791aef9702e3bef04448" + [[package]] name = "yoke" version = "0.8.3" @@ -6144,7 +5907,7 @@ dependencies = [ "nix", "once_cell", "ordered-stream", - "rand", + "rand 0.8.6", "serde", "serde_repr", "sha1", @@ -6263,6 +6026,30 @@ version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" +[[package]] +name = "zune-core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb8a0807f7c01457d0379ba880ba6322660448ddebc890ce29bb64da71fb40f9" + +[[package]] +name = "zune-inflate" +version = "0.2.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "zune-jpeg" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27bc9d5b815bc103f142aa054f561d9187d191692ec7c2d1e2b4737f8dbd7296" +dependencies = [ + "zune-core", +] + [[package]] name = "zvariant" version = "3.15.2" diff --git a/README.md b/README.md index 80d1fcd..b2f0113 100644 --- a/README.md +++ b/README.md @@ -1,60 +1,43 @@ # LoFlum -Современный FTP/SFTP клиент на Tauri 2 + Rust + Svelte 5. +![Rust](https://img.shields.io/badge/Rust-000000?style=flat-square&logo=rust&logoColor=white) +![egui](https://img.shields.io/badge/egui-FF5733?style=flat-square&logo=egui&logoColor=white) +![FTP](https://img.shields.io/badge/FTP/SFTP-0078D4?style=flat-square&logo=files&logoColor=white) +![status](https://img.shields.io/badge/status-development-yellow?style=flat-square) +![license](https://img.shields.io/badge/license-GPLv3-blue?style=flat-square) + +FTP/SFTP клиент написанный на Rust с UI на egui/eframe. ## Стек -- **Tauri 2** — шелл +- **egui/eframe** — нативный GUI (чистый Rust, без веба) - **Rust** — протоколы, файловая система, очередь передач -- **Svelte 5** — UI - **tokio** — async runtime ## Протоколы -| Версия | Протоколы | -|--------|-----------| -| v1 | SFTP, FTP, FTPS | -| v2 | S3, WebDAV | -| v3 | Google Drive, Dropbox | +| Версия | Протоколы | +|--------|-------------------| +| v1 | SFTP, FTP, FTPS | +| v2 | S3, WebDAV | +| v3 | Google Drive, Dropbox | ## Разработка ```bash -# Зависимости -bun install - -# Dev режим -bun run tauri dev - -# Сборка -bun run tauri build +cargo run ``` -## Зависимости системы - -- Rust + cargo -- Bun (или npm/pnpm) -- libssh2 (`pacman -S libssh2` на Arch) -- webkit2gtk (`pacman -S webkit2gtk-4.1` на Arch) - ## Архитектура ``` -src-tauri/src/ -├── domain/ — модели данных (Connection, FileEntry, TransferTask, Site) -├── protocols/ — RemoteFs trait + sftp.rs, ftp.rs -├── transfer/ — очередь, воркеры, прогресс -├── storage/ — SQLite (сайты), keychain (пароли) -├── fs/ — локальная ФС + реестр удалённых соединений -└── commands/ — tauri commands (вызовы из фронта) +src/ +├── domain/ -- модели данных (Connection, FileEntry, TransferTask, Site) +├── protocols/ -- RemoteFs trait + sftp.rs, ftp.rs +├── transfer/ -- очередь, воркеры, прогресс +├── storage/ -- SQLite (сайты), keychain (пароли) +├── fs/ -- локальная ФС + реестр удалённых соединений +├── ui/ -- egui панели (в разработке) +└── main.rs -- точка входа eframe ``` -## TODO - -- [ ] Chunked upload/download с прогресс-событиями -- [x] FTP/FTPS — FTP реализован (FTPS — stub) -- [ ] Site Manager UI -- [x] Диалог нового соединения -- [x] Transfer Queue с воркером и прогресс-событиями -- [ ] Drag & drop -- [ ] Горячие клавиши diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index f93f546..7411bf5 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,7 +1,8 @@ [package] name = "loflum" version = "0.1.0" -edition = "2021" +edition = "2024" +license = "GPL-3.0-only" [lib] name = "loflum_lib" @@ -11,32 +12,27 @@ crate-type = ["staticlib", "cdylib", "rlib"] name = "loflum" path = "src/main.rs" -[build-dependencies] -tauri-build = { version = "2", features = [] } - [dependencies] -tauri = { version = "2", features = [] } -tauri-plugin-shell = "2" +eframe = { version = "0.28", features = ["default"] } +egui = "0.28" +egui_extras = "0.28" serde = { version = "1", features = ["derive"] } serde_json = "1" tokio = { version = "1", features = ["full"] } anyhow = "1" thiserror = "1" -camino = { version = "1", features = ["serde1"] } async-trait = "0.1" rusqlite = { version = "0.31", features = ["bundled"] } keyring = "2" suppaftp = { version = "6", features = ["async", "async-native-tls"] } ssh2 = "0.9" -once_cell = "1" uuid = { version = "1", features = ["v4"] } dirs = "5" -tokio-util = { version = "0.7", features = ["io"] } -futures = "0.3" tracing = "0.1" tracing-subscriber = "0.3" chrono = "0.4" -async-std = "1" +futures-lite = "2" +image = "0.25" [profile.release] opt-level = "z" diff --git a/src-tauri/build.rs b/src-tauri/build.rs index d860e1e..c2bce4f 100644 --- a/src-tauri/build.rs +++ b/src-tauri/build.rs @@ -1,3 +1,3 @@ fn main() { - tauri_build::build() + println!("cargo:rerun-if-changed=build.rs"); } diff --git a/src-tauri/src/commands/connection.rs b/src-tauri/src/commands/connection.rs index ea82c49..c432265 100644 --- a/src-tauri/src/commands/connection.rs +++ b/src-tauri/src/commands/connection.rs @@ -1,10 +1,10 @@ -use tauri::State; -use std::sync::Arc; use crate::domain::connection::{ConnectionParams, Protocol}; use crate::fs::remote::RemoteRegistry; -use crate::protocols::sftp::SftpClient; use crate::protocols::ftp::FtpClient; +use crate::protocols::sftp::SftpClient; use crate::storage::keychain; +use std::sync::Arc; +use tauri::State; #[tauri::command] pub async fn connect( @@ -22,22 +22,25 @@ pub async fn connect( if let Some(key_path) = ¶ms.key_path { Arc::new( SftpClient::connect_key(¶ms.host, params.port, ¶ms.username, key_path) - .map_err(|e| e.to_string())? + .map_err(|e| e.to_string())?, ) } else { Arc::new( - SftpClient::connect_password(¶ms.host, params.port, ¶ms.username, &password) - .map_err(|e| e.to_string())? + SftpClient::connect_password( + ¶ms.host, + params.port, + ¶ms.username, + &password, + ) + .map_err(|e| e.to_string())?, ) } } - Protocol::Ftp => { - Arc::new( - FtpClient::connect(¶ms.host, params.port, ¶ms.username, &password) - .await - .map_err(|e| e.to_string())? - ) - } + Protocol::Ftp => Arc::new( + FtpClient::connect(¶ms.host, params.port, ¶ms.username, &password) + .await + .map_err(|e| e.to_string())?, + ), Protocol::Ftps => { return Err("FTPS not yet implemented (suppaftp API compat)".to_string()); } diff --git a/src-tauri/src/commands/fs.rs b/src-tauri/src/commands/fs.rs index e24e782..f01b524 100644 --- a/src-tauri/src/commands/fs.rs +++ b/src-tauri/src/commands/fs.rs @@ -1,7 +1,7 @@ -use std::sync::Arc; -use tauri::State; use crate::domain::file_entry::FileEntry; use crate::fs::{local, remote::RemoteRegistry}; +use std::sync::Arc; +use tauri::State; #[tauri::command] pub fn list_local(path: String) -> Result, String> { @@ -14,7 +14,8 @@ pub async fn list_remote( connection_id: String, path: String, ) -> Result, String> { - let fs = registry.get(&connection_id) + let fs = registry + .get(&connection_id) .ok_or_else(|| format!("no connection: {}", connection_id))?; fs.list(&path).await.map_err(|e| e.to_string()) } @@ -25,7 +26,8 @@ pub async fn remote_mkdir( connection_id: String, path: String, ) -> Result<(), String> { - let fs = registry.get(&connection_id) + let fs = registry + .get(&connection_id) .ok_or_else(|| format!("no connection: {}", connection_id))?; fs.mkdir(&path).await.map_err(|e| e.to_string()) } @@ -37,7 +39,8 @@ pub async fn remote_rename( from: String, to: String, ) -> Result<(), String> { - let fs = registry.get(&connection_id) + let fs = registry + .get(&connection_id) .ok_or_else(|| format!("no connection: {}", connection_id))?; fs.rename(&from, &to).await.map_err(|e| e.to_string()) } @@ -48,7 +51,8 @@ pub async fn remote_delete( connection_id: String, path: String, ) -> Result<(), String> { - let fs = registry.get(&connection_id) + let fs = registry + .get(&connection_id) .ok_or_else(|| format!("no connection: {}", connection_id))?; fs.delete(&path).await.map_err(|e| e.to_string()) } diff --git a/src-tauri/src/commands/sites.rs b/src-tauri/src/commands/sites.rs index 27b7fec..901b36e 100644 --- a/src-tauri/src/commands/sites.rs +++ b/src-tauri/src/commands/sites.rs @@ -1,6 +1,6 @@ -use tauri::State; use crate::domain::site::Site; use crate::storage::db::Db; +use tauri::State; #[tauri::command] pub fn get_sites(db: State<'_, Db>) -> Result, String> { diff --git a/src-tauri/src/commands/transfer.rs b/src-tauri/src/commands/transfer.rs index cfff00b..9a7d765 100644 --- a/src-tauri/src/commands/transfer.rs +++ b/src-tauri/src/commands/transfer.rs @@ -1,9 +1,9 @@ -use tauri::State; use std::sync::Arc; +use tauri::State; -use crate::domain::transfer::{TransferTask, TransferKind, TaskState}; -use crate::transfer::manager::TransferManager; use crate::domain::file_entry::EntryKind; +use crate::domain::transfer::{TaskState, TransferKind, TransferTask}; +use crate::transfer::manager::TransferManager; #[tauri::command] pub async fn upload( @@ -12,7 +12,8 @@ pub async fn upload( local_path: String, remote_path: String, ) -> Result { - let meta = std::fs::metadata(&local_path).map_err(|e| format!("cannot stat local file: {}", e))?; + let meta = + std::fs::metadata(&local_path).map_err(|e| format!("cannot stat local file: {}", e))?; if !meta.is_file() { return Err("local path is not a file".into()); } @@ -50,9 +51,13 @@ pub async fn download( ) -> Result { // Узнаём размер удалённого файла через stat let registry = manager.registry(); - let fs = registry.get(&connection_id) + let fs = registry + .get(&connection_id) .ok_or_else(|| format!("no connection: {}", connection_id))?; - let stat = fs.stat(&remote_path).await.map_err(|e| format!("stat failed: {}", e))?; + let stat = fs + .stat(&remote_path) + .await + .map_err(|e| format!("stat failed: {}", e))?; let file_name = std::path::Path::new(&remote_path) .file_name() diff --git a/src-tauri/src/domain/site.rs b/src-tauri/src/domain/site.rs index fcc1368..e34be31 100644 --- a/src-tauri/src/domain/site.rs +++ b/src-tauri/src/domain/site.rs @@ -1,5 +1,5 @@ -use serde::{Deserialize, Serialize}; use crate::domain::connection::Protocol; +use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] diff --git a/src-tauri/src/domain/transfer.rs b/src-tauri/src/domain/transfer.rs index e664768..bdfbfbb 100644 --- a/src-tauri/src/domain/transfer.rs +++ b/src-tauri/src/domain/transfer.rs @@ -1,5 +1,5 @@ -use std::fmt; use serde::{Deserialize, Serialize}; +use std::fmt; use uuid::Uuid; #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] diff --git a/src-tauri/src/fs/local.rs b/src-tauri/src/fs/local.rs index d39c72b..d7fabc3 100644 --- a/src-tauri/src/fs/local.rs +++ b/src-tauri/src/fs/local.rs @@ -1,23 +1,31 @@ +use crate::domain::file_entry::{EntryKind, FileEntry}; use anyhow::Result; use std::fs; -use crate::domain::file_entry::{FileEntry, EntryKind}; pub fn list(path: &str) -> Result> { let mut entries: Vec = fs::read_dir(path)? .filter_map(|e| e.ok()) .map(|e| { let meta = e.metadata().ok(); - let kind = meta.as_ref().map(|m| { - if m.is_dir() { EntryKind::Dir } - else if m.is_symlink() { EntryKind::Symlink } - else { EntryKind::File } - }).unwrap_or(EntryKind::File); + let kind = meta + .as_ref() + .map(|m| { + if m.is_dir() { + EntryKind::Dir + } else if m.is_symlink() { + EntryKind::Symlink + } else { + EntryKind::File + } + }) + .unwrap_or(EntryKind::File); - let size = meta.as_ref().and_then(|m| { - if m.is_file() { Some(m.len()) } else { None } - }); + let size = meta + .as_ref() + .and_then(|m| if m.is_file() { Some(m.len()) } else { None }); - let modified = meta.as_ref() + let modified = meta + .as_ref() .and_then(|m| m.modified().ok()) .and_then(|t| t.duration_since(std::time::UNIX_EPOCH).ok()) .map(|d| d.as_secs() as i64); @@ -34,13 +42,11 @@ pub fn list(path: &str) -> Result> { .collect(); // папки сначала, потом файлы, по имени - entries.sort_by(|a, b| { - match (&a.kind, &b.kind) { - (EntryKind::Dir, EntryKind::Dir) => a.name.cmp(&b.name), - (EntryKind::Dir, _) => std::cmp::Ordering::Less, - (_, EntryKind::Dir) => std::cmp::Ordering::Greater, - _ => a.name.cmp(&b.name), - } + entries.sort_by(|a, b| match (&a.kind, &b.kind) { + (EntryKind::Dir, EntryKind::Dir) => a.name.cmp(&b.name), + (EntryKind::Dir, _) => std::cmp::Ordering::Less, + (_, EntryKind::Dir) => std::cmp::Ordering::Greater, + _ => a.name.cmp(&b.name), }); Ok(entries) diff --git a/src-tauri/src/fs/remote.rs b/src-tauri/src/fs/remote.rs index 40451ab..e3ea1eb 100644 --- a/src-tauri/src/fs/remote.rs +++ b/src-tauri/src/fs/remote.rs @@ -1,9 +1,9 @@ // Абстракция над RemoteFs для хранения активных соединений // TODO: HashMap> +use crate::protocols::RemoteFs; use std::collections::HashMap; use std::sync::{Arc, Mutex}; -use crate::protocols::RemoteFs; #[derive(Default)] pub struct RemoteRegistry { diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 4ef779a..53f71e9 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -1,47 +1,52 @@ -pub mod commands; pub mod domain; pub mod fs; pub mod protocols; pub mod storage; pub mod transfer; +pub mod ui; +use crate::fs::remote::RemoteRegistry; +use crate::transfer::queue::TransferQueue; +use crate::ui::app::FileManagerApp; use std::sync::Arc; -use tauri::Manager; -use crate::transfer::manager::TransferManager; -#[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { - tracing_subscriber::fmt::init(); + tracing_subscriber::fmt().with_target(false).init(); - tauri::Builder::default() - .plugin(tauri_plugin_shell::init()) - .invoke_handler(tauri::generate_handler![ - commands::fs::list_local, - commands::fs::list_remote, - commands::fs::remote_mkdir, - commands::fs::remote_rename, - commands::fs::remote_delete, - commands::connection::connect, - commands::connection::disconnect, - commands::transfer::upload, - commands::transfer::download, - commands::transfer::get_queue, - commands::transfer::pause_task, - commands::transfer::cancel_task, - commands::sites::get_sites, - commands::sites::save_site, - commands::sites::delete_site, - ]) - .setup(|app| { - let registry = Arc::new(crate::fs::remote::RemoteRegistry::default()); - let manager = TransferManager::new(registry.clone(), app.handle().clone()); + let db_path = dirs::data_dir() + .unwrap_or_else(|| std::path::PathBuf::from(".")) + .join("loflum") + .join("loflum.db"); + if let Some(parent) = db_path.parent() { + std::fs::create_dir_all(parent).ok(); + } + let conn = rusqlite::Connection::open(&db_path).expect("failed to open loflum database"); + storage::db::init_tables(&conn).expect("failed to init db tables"); + let db = Arc::new(std::sync::Mutex::new(conn)); - app.manage(registry); - app.manage(manager); + let sites = { + let c = db.lock().unwrap(); + storage::db::get_sites(&c).unwrap_or_default() + }; - storage::db::init(app.handle())?; - Ok(()) - }) - .run(tauri::generate_context!()) - .expect("error while running loflum"); + let rt = tokio::runtime::Runtime::new().expect("failed to create tokio runtime"); + let rt_handle = rt.handle().clone(); + + let registry = Arc::new(RemoteRegistry::default()); + let queue = TransferQueue::default(); + + transfer::worker::spawn_worker(queue.clone(), registry.clone(), rt_handle); + + let app = FileManagerApp::new(registry, queue, rt, db, sites); + + let native_options = eframe::NativeOptions { + viewport: egui::ViewportBuilder::default() + .with_title("LoFlum") + .with_inner_size([1280.0, 800.0]) + .with_min_inner_size([900.0, 600.0]), + ..Default::default() + }; + + eframe::run_native("LoFlum", native_options, Box::new(|_cc| Ok(Box::new(app)))) + .expect("failed to start LoFlum"); } diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 25b19c2..adc61cb 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -1,4 +1,3 @@ -// Prevents additional console window on Windows in release #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] fn main() { diff --git a/src-tauri/src/protocols/ftp.rs b/src-tauri/src/protocols/ftp.rs index b7b46dd..bcbbeaa 100644 --- a/src-tauri/src/protocols/ftp.rs +++ b/src-tauri/src/protocols/ftp.rs @@ -1,14 +1,14 @@ -use async_trait::async_trait; use anyhow::Result; +use async_trait::async_trait; +use futures_lite::io::{AsyncReadExt, AsyncWriteExt}; use std::str::FromStr; use std::time::SystemTime; use tokio::sync::Mutex; -use async_std::io::{ReadExt, WriteExt}; use suppaftp::{AsyncFtpStream, list::File}; -use crate::domain::file_entry::{FileEntry, EntryKind}; use super::RemoteFs; +use crate::domain::file_entry::{EntryKind, FileEntry}; pub struct FtpClient { pub conn: Mutex>, @@ -17,11 +17,16 @@ pub struct FtpClient { impl FtpClient { pub async fn connect(host: &str, port: u16, user: &str, pass: &str) -> Result { let addr = format!("{}:{}", host, port); - let mut stream = AsyncFtpStream::connect(&addr).await + let mut stream = AsyncFtpStream::connect(&addr) + .await .map_err(|e| anyhow::anyhow!("FTP connect failed: {}", e))?; - stream.login(user, pass).await + stream + .login(user, pass) + .await .map_err(|e| anyhow::anyhow!("FTP login failed: {}", e))?; - Ok(Self { conn: Mutex::new(Some(stream)) }) + Ok(Self { + conn: Mutex::new(Some(stream)), + }) } fn parse_list_entry(line: &str) -> Option { @@ -34,7 +39,8 @@ impl FtpClient { EntryKind::File }; - let modified = file.modified() + let modified = file + .modified() .duration_since(SystemTime::UNIX_EPOCH) .ok() .map(|d| d.as_secs() as i64); @@ -54,49 +60,66 @@ impl FtpClient { impl RemoteFs for FtpClient { async fn list(&self, path: &str) -> Result> { let mut guard = self.conn.lock().await; - let conn = guard.as_mut().ok_or_else(|| anyhow::anyhow!("not connected"))?; - let lines = conn.list(Some(path)).await + let conn = guard + .as_mut() + .ok_or_else(|| anyhow::anyhow!("not connected"))?; + let lines = conn + .list(Some(path)) + .await .map_err(|e| anyhow::anyhow!("FTP list failed: {}", e))?; - let mut entries: Vec = lines.iter() + let mut entries: Vec = lines + .iter() .filter_map(|line| Self::parse_list_entry(line)) .collect(); - entries.sort_by(|a, b| { - match (&a.kind, &b.kind) { - (EntryKind::Dir, EntryKind::Dir) => a.name.cmp(&b.name), - (EntryKind::Dir, _) => std::cmp::Ordering::Less, - (_, EntryKind::Dir) => std::cmp::Ordering::Greater, - _ => a.name.cmp(&b.name), - } + entries.sort_by(|a, b| match (&a.kind, &b.kind) { + (EntryKind::Dir, EntryKind::Dir) => a.name.cmp(&b.name), + (EntryKind::Dir, _) => std::cmp::Ordering::Less, + (_, EntryKind::Dir) => std::cmp::Ordering::Greater, + _ => a.name.cmp(&b.name), }); Ok(entries) } async fn upload(&self, local: &str, remote: &str) -> Result<()> { - let data = std::fs::read(local) - .map_err(|e| anyhow::anyhow!("cannot read local file: {}", e))?; + let data = + std::fs::read(local).map_err(|e| anyhow::anyhow!("cannot read local file: {}", e))?; let mut guard = self.conn.lock().await; - let conn = guard.as_mut().ok_or_else(|| anyhow::anyhow!("not connected"))?; - let mut stream = conn.put_with_stream(remote).await + let conn = guard + .as_mut() + .ok_or_else(|| anyhow::anyhow!("not connected"))?; + let mut stream = conn + .put_with_stream(remote) + .await .map_err(|e| anyhow::anyhow!("FTP upload stream failed: {}", e))?; - stream.write_all(&data).await + stream + .write_all(&data) + .await .map_err(|e| anyhow::anyhow!("FTP upload write failed: {}", e))?; - conn.finalize_put_stream(stream).await + conn.finalize_put_stream(stream) + .await .map_err(|e| anyhow::anyhow!("FTP upload finalize failed: {}", e))?; Ok(()) } async fn download(&self, remote: &str, local: &str) -> Result<()> { let mut guard = self.conn.lock().await; - let conn = guard.as_mut().ok_or_else(|| anyhow::anyhow!("not connected"))?; - let mut stream = conn.retr_as_stream(remote).await + let conn = guard + .as_mut() + .ok_or_else(|| anyhow::anyhow!("not connected"))?; + let mut stream = conn + .retr_as_stream(remote) + .await .map_err(|e| anyhow::anyhow!("FTP download stream failed: {}", e))?; let mut buf = Vec::new(); - stream.read_to_end(&mut buf).await + stream + .read_to_end(&mut buf) + .await .map_err(|e| anyhow::anyhow!("FTP download read failed: {}", e))?; - conn.finalize_retr_stream(stream).await + conn.finalize_retr_stream(stream) + .await .map_err(|e| anyhow::anyhow!("FTP download finalize failed: {}", e))?; std::fs::write(local, &buf) .map_err(|e| anyhow::anyhow!("cannot write local file: {}", e))?; @@ -105,25 +128,34 @@ impl RemoteFs for FtpClient { async fn mkdir(&self, path: &str) -> Result<()> { let mut guard = self.conn.lock().await; - let conn = guard.as_mut().ok_or_else(|| anyhow::anyhow!("not connected"))?; - conn.mkdir(path).await + let conn = guard + .as_mut() + .ok_or_else(|| anyhow::anyhow!("not connected"))?; + conn.mkdir(path) + .await .map_err(|e| anyhow::anyhow!("FTP mkdir failed: {}", e))?; Ok(()) } async fn rename(&self, from: &str, to: &str) -> Result<()> { let mut guard = self.conn.lock().await; - let conn = guard.as_mut().ok_or_else(|| anyhow::anyhow!("not connected"))?; - conn.rename(from, to).await + let conn = guard + .as_mut() + .ok_or_else(|| anyhow::anyhow!("not connected"))?; + conn.rename(from, to) + .await .map_err(|e| anyhow::anyhow!("FTP rename failed: {}", e))?; Ok(()) } async fn delete(&self, path: &str) -> Result<()> { let mut guard = self.conn.lock().await; - let conn = guard.as_mut().ok_or_else(|| anyhow::anyhow!("not connected"))?; + let conn = guard + .as_mut() + .ok_or_else(|| anyhow::anyhow!("not connected"))?; if conn.rm(path).await.is_err() { - conn.rmdir(path).await + conn.rmdir(path) + .await .map_err(|e| anyhow::anyhow!("FTP delete failed: {}", e))?; } Ok(()) @@ -131,10 +163,16 @@ impl RemoteFs for FtpClient { async fn stat(&self, path: &str) -> Result { let mut guard = self.conn.lock().await; - let conn = guard.as_mut().ok_or_else(|| anyhow::anyhow!("not connected"))?; - let size = conn.size(path).await + let conn = guard + .as_mut() + .ok_or_else(|| anyhow::anyhow!("not connected"))?; + let size = conn + .size(path) + .await .map_err(|e| anyhow::anyhow!("FTP stat failed: {}", e))?; - let modified = conn.mdtm(path).await + let modified = conn + .mdtm(path) + .await .map(|dt| dt.and_utc().timestamp()) .ok(); diff --git a/src-tauri/src/protocols/mod.rs b/src-tauri/src/protocols/mod.rs index 9725b4b..328fd80 100644 --- a/src-tauri/src/protocols/mod.rs +++ b/src-tauri/src/protocols/mod.rs @@ -1,9 +1,9 @@ pub mod ftp; pub mod sftp; -use async_trait::async_trait; use crate::domain::file_entry::FileEntry; use anyhow::Result; +use async_trait::async_trait; /// Единый контракт для всех протоколов. /// Очередь передач не знает — FTP это или SFTP. diff --git a/src-tauri/src/protocols/sftp.rs b/src-tauri/src/protocols/sftp.rs index 22e3e2a..c1426f2 100644 --- a/src-tauri/src/protocols/sftp.rs +++ b/src-tauri/src/protocols/sftp.rs @@ -1,11 +1,11 @@ +use anyhow::{Context, Result, bail}; use async_trait::async_trait; -use anyhow::{Result, Context}; -use ssh2::Session; +use ssh2::{CheckResult, HashType, KnownHostFileKind, Session}; use std::net::TcpStream; -use std::path::Path; +use std::path::{Path, PathBuf}; -use crate::domain::file_entry::{FileEntry, EntryKind}; use super::RemoteFs; +use crate::domain::file_entry::{EntryKind, FileEntry}; pub struct SftpClient { session: Session, @@ -14,29 +14,93 @@ pub struct SftpClient { impl SftpClient { /// Подключение по паролю pub fn connect_password(host: &str, port: u16, user: &str, password: &str) -> Result { - let tcp = TcpStream::connect(format!("{}:{}", host, port)) - .context("TCP connect failed")?; + let tcp = TcpStream::connect(format!("{}:{}", host, port)).context("TCP connect failed")?; let mut session = Session::new().context("SSH session init failed")?; session.set_tcp_stream(tcp); session.handshake().context("SSH handshake failed")?; - session.userauth_password(user, password) + verify_host_key(&session, host, port)?; + session + .userauth_password(user, password) .context("SSH password auth failed")?; Ok(Self { session }) } /// Подключение по ключу pub fn connect_key(host: &str, port: u16, user: &str, key_path: &str) -> Result { - let tcp = TcpStream::connect(format!("{}:{}", host, port)) - .context("TCP connect failed")?; + let tcp = TcpStream::connect(format!("{}:{}", host, port)).context("TCP connect failed")?; let mut session = Session::new().context("SSH session init failed")?; session.set_tcp_stream(tcp); session.handshake().context("SSH handshake failed")?; - session.userauth_pubkey_file(user, None, Path::new(key_path), None) + verify_host_key(&session, host, port)?; + session + .userauth_pubkey_file(user, None, Path::new(key_path), None) .context("SSH key auth failed")?; Ok(Self { session }) } } +fn known_hosts_path() -> Option { + dirs::home_dir().map(|p| p.join(".ssh/known_hosts")) +} + +fn fingerprint_hex(session: &Session) -> String { + session + .host_key_hash(HashType::Sha256) + .map(|h| { + h.iter() + .map(|b| format!("{:02x}", b)) + .collect::>() + .join(":") + }) + .unwrap_or_else(|| "unknown".into()) +} + +fn verify_host_key(session: &Session, host: &str, port: u16) -> Result<()> { + let mut known = session.known_hosts().context("known_hosts init failed")?; + + if let Some(ref path) = known_hosts_path() { + let _ = known.read_file(path, KnownHostFileKind::OpenSSH); + } + + let (key, key_type) = session + .host_key() + .context("no host key received from server")?; + + match known.check_port(host, port, key) { + CheckResult::Match => {} // known and verified + CheckResult::Mismatch => { + bail!( + "SSH host key mismatch for {}!\n\ + The server's host key has changed since the last connection.\n\ + This could mean someone is intercepting the connection (MITM attack).\n\ + Fingerprint (SHA256): {}", + host, + fingerprint_hex(session) + ); + } + CheckResult::NotFound => { + tracing::info!( + "Unknown host key for {}, adding to known_hosts (SHA256: {})", + host, + fingerprint_hex(session) + ); + known + .add(host, key, "loflum", key_type.into()) + .context("failed to add host key to known_hosts")?; + if let Some(ref path) = known_hosts_path() + && let Err(e) = known.write_file(path, KnownHostFileKind::OpenSSH) + { + tracing::warn!("failed to write known_hosts: {}", e); + } + } + CheckResult::Failure => { + bail!("known_hosts check failed for {}", host); + } + } + + Ok(()) +} + #[async_trait] impl RemoteFs for SftpClient { async fn list(&self, path: &str) -> Result> { @@ -44,26 +108,30 @@ impl RemoteFs for SftpClient { let sftp = self.session.sftp().context("SFTP subsystem failed")?; let entries = sftp.readdir(Path::new(path)).context("readdir failed")?; - let result = entries.into_iter().map(|(pb, stat)| { - let kind = if stat.is_dir() { - EntryKind::Dir - } else if stat.file_type().is_symlink() { - EntryKind::Symlink - } else { - EntryKind::File - }; - FileEntry { - name: pb.file_name() - .unwrap_or_default() - .to_string_lossy() - .to_string(), - path: pb.to_string_lossy().to_string(), - kind, - size: stat.size, - modified: stat.mtime.map(|t| t as i64), - permissions: None, - } - }).collect(); + let result = entries + .into_iter() + .map(|(pb, stat)| { + let kind = if stat.is_dir() { + EntryKind::Dir + } else if stat.file_type().is_symlink() { + EntryKind::Symlink + } else { + EntryKind::File + }; + FileEntry { + name: pb + .file_name() + .unwrap_or_default() + .to_string_lossy() + .to_string(), + path: pb.to_string_lossy().to_string(), + kind, + size: stat.size, + modified: stat.mtime.map(|t| t as i64), + permissions: None, + } + }) + .collect(); Ok(result) } @@ -71,9 +139,9 @@ impl RemoteFs for SftpClient { async fn upload(&self, local: &str, remote: &str) -> Result<()> { // TODO: chunked upload с прогресс-событиями let sftp = self.session.sftp().context("SFTP subsystem failed")?; - let mut local_file = std::fs::File::open(local) - .context("open local file failed")?; - let mut remote_file = sftp.create(Path::new(remote)) + let mut local_file = std::fs::File::open(local).context("open local file failed")?; + let mut remote_file = sftp + .create(Path::new(remote)) .context("create remote file failed")?; std::io::copy(&mut local_file, &mut remote_file)?; Ok(()) @@ -82,10 +150,10 @@ impl RemoteFs for SftpClient { async fn download(&self, remote: &str, local: &str) -> Result<()> { // TODO: chunked download с прогресс-событиями let sftp = self.session.sftp().context("SFTP subsystem failed")?; - let mut remote_file = sftp.open(Path::new(remote)) + let mut remote_file = sftp + .open(Path::new(remote)) .context("open remote file failed")?; - let mut local_file = std::fs::File::create(local) - .context("create local file failed")?; + let mut local_file = std::fs::File::create(local).context("create local file failed")?; std::io::copy(&mut remote_file, &mut local_file)?; Ok(()) } @@ -122,7 +190,11 @@ impl RemoteFs for SftpClient { .to_string_lossy() .to_string(), path: path.to_string(), - kind: if stat.is_dir() { EntryKind::Dir } else { EntryKind::File }, + kind: if stat.is_dir() { + EntryKind::Dir + } else { + EntryKind::File + }, size: stat.size, modified: stat.mtime.map(|t| t as i64), permissions: None, diff --git a/src-tauri/src/storage/db.rs b/src-tauri/src/storage/db.rs index b01c09a..bcf398b 100644 --- a/src-tauri/src/storage/db.rs +++ b/src-tauri/src/storage/db.rs @@ -1,21 +1,11 @@ +use crate::domain::connection::Protocol; +use crate::domain::site::Site; use anyhow::Result; use rusqlite::{Connection, params}; -use tauri::{AppHandle, Manager}; -use std::sync::Mutex; -use crate::domain::site::Site; -use crate::domain::connection::Protocol; -pub struct Db(pub Mutex); - -pub fn init(app: &AppHandle) -> Result<()> { - let path = app.path().app_data_dir() - .expect("no app data dir") - .join("loflum.db"); - - std::fs::create_dir_all(path.parent().unwrap())?; - let conn = Connection::open(&path)?; - - conn.execute_batch(" +pub fn init_tables(conn: &Connection) -> Result<()> { + conn.execute_batch( + " PRAGMA journal_mode=WAL; CREATE TABLE IF NOT EXISTS sites ( @@ -29,35 +19,37 @@ pub fn init(app: &AppHandle) -> Result<()> { folder TEXT, note TEXT ); - ")?; - - app.manage(Db(Mutex::new(conn))); + ", + )?; Ok(()) } pub fn get_sites(conn: &Connection) -> Result> { let mut stmt = conn.prepare( - "SELECT id, name, protocol, host, port, username, key_path, folder, note FROM sites ORDER BY name" + "SELECT id, name, protocol, host, port, username, key_path, folder, note FROM sites ORDER BY name", )?; - let sites = stmt.query_map([], |row| { - let proto_str: String = row.get(2)?; - let protocol = match proto_str.as_str() { - "sftp" => Protocol::Sftp, - "ftps" => Protocol::Ftps, - _ => Protocol::Ftp, - }; - Ok(Site { - id: row.get(0)?, - name: row.get(1)?, - protocol, - host: row.get(3)?, - port: row.get(4)?, - username: row.get(5)?, - key_path: row.get(6)?, - folder: row.get(7)?, - note: row.get(8)?, - }) - })?.filter_map(|r| r.ok()).collect(); + let sites = stmt + .query_map([], |row| { + let proto_str: String = row.get(2)?; + let protocol = match proto_str.as_str() { + "sftp" => Protocol::Sftp, + "ftps" => Protocol::Ftps, + _ => Protocol::Ftp, + }; + Ok(Site { + id: row.get(0)?, + name: row.get(1)?, + protocol, + host: row.get(3)?, + port: row.get(4)?, + username: row.get(5)?, + key_path: row.get(6)?, + folder: row.get(7)?, + note: row.get(8)?, + }) + })? + .filter_map(|r| r.ok()) + .collect(); Ok(sites) } @@ -72,8 +64,15 @@ pub fn save_site(conn: &Connection, site: &Site) -> Result<()> { (id, name, protocol, host, port, username, key_path, folder, note) VALUES (?1,?2,?3,?4,?5,?6,?7,?8,?9)", params![ - site.id, site.name, proto, site.host, site.port, - site.username, site.key_path, site.folder, site.note + site.id, + site.name, + proto, + site.host, + site.port, + site.username, + site.key_path, + site.folder, + site.note ], )?; Ok(()) diff --git a/src-tauri/src/transfer/manager.rs b/src-tauri/src/transfer/manager.rs index adbf7a2..e495ae0 100644 --- a/src-tauri/src/transfer/manager.rs +++ b/src-tauri/src/transfer/manager.rs @@ -1,32 +1,21 @@ -use std::sync::Arc; -use tauri::AppHandle; -use crate::transfer::queue::TransferQueue; -use crate::transfer::worker::spawn_worker; use crate::fs::remote::RemoteRegistry; +use crate::transfer::queue::TransferQueue; +use std::sync::Arc; -/// Хранит очередь передач и запускает воркер. pub struct TransferManager { pub queue: TransferQueue, - registry: Arc, - app: AppHandle, + pub registry: Arc, } impl TransferManager { - pub fn new(registry: Arc, app: AppHandle) -> Arc { - let manager = Arc::new(Self { + pub fn new(registry: Arc) -> Arc { + Arc::new(Self { queue: TransferQueue::default(), - registry: registry.clone(), - app: app.clone(), - }); - spawn_worker(manager.clone(), registry, app); - manager + registry, + }) } pub fn registry(&self) -> &RemoteRegistry { &self.registry } - - pub fn app(&self) -> &AppHandle { - &self.app - } } diff --git a/src-tauri/src/transfer/queue.rs b/src-tauri/src/transfer/queue.rs index dec0427..d24fc54 100644 --- a/src-tauri/src/transfer/queue.rs +++ b/src-tauri/src/transfer/queue.rs @@ -1,6 +1,6 @@ +use crate::domain::transfer::{TaskState, TransferTask}; use std::collections::VecDeque; use std::sync::{Arc, Mutex}; -use crate::domain::transfer::{TransferTask, TaskState}; #[derive(Clone, Default)] pub struct TransferQueue { @@ -32,10 +32,8 @@ impl TransferQueue { if let Some(t) = q.iter_mut().find(|t| t.id == id) { t.transferred_bytes = transferred; t.speed = Some(speed); - if speed > 0 { - let remaining = t.total_bytes.saturating_sub(transferred); - t.eta_secs = Some(remaining / speed); - } + let remaining = t.total_bytes.saturating_sub(transferred); + t.eta_secs = remaining.checked_div(speed); } } diff --git a/src-tauri/src/transfer/task.rs b/src-tauri/src/transfer/task.rs index 57256c4..e5e9dfe 100644 --- a/src-tauri/src/transfer/task.rs +++ b/src-tauri/src/transfer/task.rs @@ -1,4 +1,4 @@ -use crate::domain::transfer::{TransferTask, TransferKind}; +use crate::domain::transfer::{TransferKind, TransferTask}; pub fn new_task( kind: TransferKind, diff --git a/src-tauri/src/transfer/worker.rs b/src-tauri/src/transfer/worker.rs index 3fa3e74..e71c731 100644 --- a/src-tauri/src/transfer/worker.rs +++ b/src-tauri/src/transfer/worker.rs @@ -1,40 +1,25 @@ use std::sync::Arc; -use tauri::{AppHandle, Emitter}; -use tokio::time::{sleep, Duration}; +use tokio::time::{Duration, sleep}; use crate::domain::transfer::{TaskState, TransferKind}; use crate::fs::remote::RemoteRegistry; -use crate::transfer::manager::TransferManager; - -/// Событие для фронтенда -#[derive(Clone, serde::Serialize)] -#[serde(rename_all = "camelCase")] -struct TransferProgress { - task_id: String, - state: String, - transferred_bytes: u64, - total_bytes: u64, - speed: Option, - eta_secs: Option, - error: Option, -} +use crate::transfer::queue::TransferQueue; pub fn spawn_worker( - manager: Arc, + queue: TransferQueue, registry: Arc, - app: AppHandle, + rt_handle: tokio::runtime::Handle, ) { - tokio::spawn(async move { + rt_handle.spawn(async move { loop { let task = { - let task = manager.queue.pop(); - if let Some(ref t) = task { - if t.state != TaskState::Queued { - // paused/cancelled — не трогаем, вернём - manager.queue.push(t.clone()); - sleep(Duration::from_millis(500)).await; - continue; - } + let task = queue.pop(); + if let Some(ref t) = task + && t.state != TaskState::Queued + { + queue.push(t.clone()); + sleep(Duration::from_millis(500)).await; + continue; } task }; @@ -47,17 +32,14 @@ pub fn spawn_worker( } }; - // Старт task.state = TaskState::Running; - manager.queue.update_state(&task.id, TaskState::Running); - emit_progress(&app, &task, None); + queue.update_state(&task.id, TaskState::Running); let fs = match registry.get(&task.connection_id) { Some(fs) => fs, None => { task.state = TaskState::Failed("connection not found".into()); - manager.queue.update_state(&task.id, task.state.clone()); - emit_progress(&app, &task, Some("connection not found")); + queue.update_state(&task.id, task.state.clone()); continue; } }; @@ -71,29 +53,15 @@ pub fn spawn_worker( Ok(()) => { task.state = TaskState::Completed; task.transferred_bytes = task.total_bytes; - manager.queue.update_state(&task.id, TaskState::Completed); - manager.queue.update_progress(&task.id, task.total_bytes, 0); - emit_progress(&app, &task, None); + queue.update_state(&task.id, TaskState::Completed); + queue.update_progress(&task.id, task.total_bytes, 0); } Err(e) => { let msg = e.to_string(); - task.state = TaskState::Failed(msg.clone()); - manager.queue.update_state(&task.id, TaskState::Failed(msg.clone())); - emit_progress(&app, &task, Some(&msg)); + task.state = TaskState::Failed(msg); + queue.update_state(&task.id, task.state.clone()); } } } }); } - -fn emit_progress(app: &AppHandle, task: &crate::domain::transfer::TransferTask, error: Option<&str>) { - let _ = app.emit("transfer-progress", TransferProgress { - task_id: task.id.clone(), - state: task.state.to_string(), - transferred_bytes: task.transferred_bytes, - total_bytes: task.total_bytes, - speed: task.speed, - eta_secs: task.eta_secs, - error: error.map(|s| s.to_string()), - }); -} diff --git a/src-tauri/src/ui/app.rs b/src-tauri/src/ui/app.rs new file mode 100644 index 0000000..d1577dc --- /dev/null +++ b/src-tauri/src/ui/app.rs @@ -0,0 +1,245 @@ +use std::sync::Arc; + +use egui::{CentralPanel, TopBottomPanel}; + +use crate::domain::connection::ConnectionStatus; +use crate::domain::file_entry::{EntryKind, FileEntry}; +use crate::domain::site::Site; +use crate::fs::remote::RemoteRegistry; +use crate::transfer::queue::TransferQueue; +use crate::ui::dialogs::connection; +use crate::ui::panels::local_pane; +use crate::ui::panels::queue; +use crate::ui::panels::remote_pane; +use crate::ui::panels::status_bar; +use crate::ui::panels::tabs; +use crate::ui::panels::toolbar; + +pub struct FileManagerApp { + pub state: crate::ui::state::AppState, + pub registry: Arc, + pub queue: TransferQueue, + pub rt: tokio::runtime::Runtime, + pub db: Arc>, + pub sites: Vec, + pub first_frame: bool, +} + +impl FileManagerApp { + pub fn new( + registry: Arc, + queue: TransferQueue, + rt: tokio::runtime::Runtime, + db: Arc>, + sites: Vec, + ) -> Self { + let mut state = crate::ui::state::AppState { + local_path: crate::fs::local::home_dir(), + ..Default::default() + }; + local_pane::refresh_local(&mut state); + + Self { + state, + registry, + queue, + rt, + db, + sites, + first_frame: true, + } + } + + fn poll_pending(&mut self) { + let opt = self.state.pending_connect.take(); + if let Some(pc) = opt.as_ref() { + let mut guard = pc.result.lock().unwrap(); + if let Some(res) = guard.take() { + drop(guard); + match res { + Ok((params, entries)) => { + let path = "/".to_string(); + let mut list = vec![FileEntry { + name: "..".into(), + path: path.clone(), + kind: EntryKind::Dir, + size: None, + modified: None, + permissions: None, + }]; + list.extend(entries); + + let tab = crate::ui::state::ConnectionTab { + id: params.id.clone(), + label: params.label.clone(), + params, + status: ConnectionStatus::Connected, + remote_path: path, + remote_entries: list, + remote_selected: None, + loading: false, + }; + self.state.tabs.push(tab); + self.state.active_tab = self.state.tabs.len() - 1; + self.state.status_message = "Connected".into(); + self.state.connect_loading = false; + self.state.show_connect_dialog = false; + } + Err(e) => { + self.state.status_message = format!("Connection failed: {}", e); + self.state.connect_error = e; + self.state.connect_loading = false; + } + } + } else { + drop(guard); + self.state.pending_connect = opt; + } + } + + let mut done: Vec = Vec::new(); + for (i, pending) in self.state.pending_remote_list.iter().enumerate() { + let mut guard = pending.result.lock().unwrap(); + if let Some(res) = guard.take() { + let tab_idx = pending.tab_idx; + match res { + Ok(entries) => { + let path = if tab_idx < self.state.tabs.len() { + self.state.tabs[tab_idx].remote_path.clone() + } else { + "/".into() + }; + let mut list = Vec::new(); + if path != "/" { + let parent = remote_pane::remote_parent(&path); + list.push(FileEntry { + name: "..".into(), + path: parent, + kind: EntryKind::Dir, + size: None, + modified: None, + permissions: None, + }); + } + list.extend(entries); + if tab_idx < self.state.tabs.len() { + self.state.tabs[tab_idx].remote_entries = list; + self.state.tabs[tab_idx].loading = false; + } + } + Err(e) => { + if tab_idx < self.state.tabs.len() { + self.state.tabs[tab_idx].loading = false; + } + self.state.status_message = format!("Remote list error: {}", e); + } + } + done.push(i); + } + } + for i in done.into_iter().rev() { + self.state.pending_remote_list.remove(i); + } + } +} + +impl eframe::App for FileManagerApp { + fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { + if self.first_frame { + self.first_frame = false; + ctx.request_repaint(); + } + + self.poll_pending(); + self.state.queue_tasks = self.queue.all(); + self.state.connected_count = self + .state + .tabs + .iter() + .filter(|t| t.status == ConnectionStatus::Connected) + .count(); + + TopBottomPanel::top("tabs").show(ctx, |ui| { + tabs::render(ui, &mut self.state); + }); + + TopBottomPanel::top("toolbar").show(ctx, |ui| { + toolbar::render( + ui, + &mut self.state, + &self.queue, + &self.registry, + self.rt.handle(), + ); + }); + + let has_connection = self.state.active_tab_ref().is_some() + && self.state.active_tab_ref().unwrap().status == ConnectionStatus::Connected; + + if has_connection { + CentralPanel::default().show(ctx, |ui| { + ui.columns(2, |columns| { + columns[0].vertical(|ui| { + local_pane::render( + ui, + &mut self.state, + &self.queue, + &self.registry, + self.rt.handle(), + ); + }); + + columns[1].vertical(|ui| { + let idx = self.state.active_tab.min(self.state.tabs.len() - 1); + remote_pane::render( + ui, + &mut self.state, + idx, + &self.registry, + self.rt.handle(), + &self.queue, + ); + }); + }); + }); + } else { + CentralPanel::default().show(ctx, |ui| { + ui.vertical_centered(|ui| { + ui.add_space(ui.available_height() * 0.3); + ui.heading("LoFlum"); + ui.label("FTP/SFTP client"); + ui.add_space(20.0); + if ui.button("New Connection").clicked() { + self.state.show_connect_dialog = true; + } + if !self.state.tabs.is_empty() { + ui.add_space(10.0); + ui.label("Select a connection tab above or create a new one"); + } + }); + }); + } + + let has_tasks = !self.state.queue_tasks.is_empty(); + let tasks = self.state.queue_tasks.clone(); + if has_tasks || self.state.show_queue { + TopBottomPanel::bottom("queue_panel") + .resizable(true) + .default_height(150.0) + .min_height(80.0) + .show(ctx, |ui| { + queue::render(ui, &mut self.state, &tasks); + }); + } + + TopBottomPanel::bottom("status_bar").show(ctx, |ui| { + status_bar::render(ui, &self.state); + }); + + if self.state.show_connect_dialog { + connection::render(ctx, &mut self.state, &self.registry, self.rt.handle()); + } + + ctx.request_repaint_after(std::time::Duration::from_millis(200)); + } +} diff --git a/src-tauri/src/ui/dialogs/connection.rs b/src-tauri/src/ui/dialogs/connection.rs new file mode 100644 index 0000000..d0e2ddf --- /dev/null +++ b/src-tauri/src/ui/dialogs/connection.rs @@ -0,0 +1,198 @@ +use crate::domain::connection::{ConnectionParams, Protocol}; +use crate::domain::file_entry::FileEntry; +use crate::fs::remote::RemoteRegistry; +use crate::protocols::{RemoteFs, ftp::FtpClient, sftp::SftpClient}; +use crate::storage::keychain; +use crate::ui::state::{AppState, PendingConnect}; +use std::sync::Arc; + +pub fn render( + ctx: &egui::Context, + state: &mut AppState, + registry: &Arc, + rt_handle: &tokio::runtime::Handle, +) { + let mut open = true; + egui::Window::new("New Connection") + .open(&mut open) + .resizable(false) + .show(ctx, |ui| { + ui.horizontal(|ui| { + ui.label("Protocol:"); + let protocols = ["SFTP", "FTP", "FTPS"]; + egui::ComboBox::from_id_source("protocol") + .selected_text(protocols[state.connect_protocol]) + .show_ui(ui, |ui| { + for (i, p) in protocols.iter().enumerate() { + ui.selectable_value(&mut state.connect_protocol, i, *p); + } + }); + }); + + ui.horizontal(|ui| { + ui.label("Label:"); + ui.add( + egui::TextEdit::singleline(&mut state.connect_label) + .id("label".into()) + .desired_width(200.0), + ); + }); + + ui.horizontal(|ui| { + ui.label("Host:"); + ui.add( + egui::TextEdit::singleline(&mut state.connect_host) + .id("host".into()) + .desired_width(200.0), + ); + }); + + ui.horizontal(|ui| { + ui.label("Port:"); + ui.add( + egui::TextEdit::singleline(&mut state.connect_port) + .id("port".into()) + .desired_width(60.0), + ); + }); + + ui.horizontal(|ui| { + ui.label("Username:"); + ui.add( + egui::TextEdit::singleline(&mut state.connect_user) + .id("user".into()) + .desired_width(200.0), + ); + }); + + ui.horizontal(|ui| { + ui.label("Password:"); + ui.add( + egui::TextEdit::singleline(&mut state.connect_pass) + .password(true) + .id("pass".into()) + .desired_width(200.0), + ); + }); + + if state.connect_protocol == 0 { + ui.horizontal(|ui| { + ui.label("Key path:"); + ui.add( + egui::TextEdit::singleline(&mut state.connect_key_path) + .id("key".into()) + .desired_width(200.0), + ); + }); + } + + if !state.connect_error.is_empty() { + ui.colored_label(egui::Color32::RED, &state.connect_error); + } + + ui.add_enabled_ui(!state.connect_loading, |ui| { + if ui.button("Connect").clicked() { + state.connect_error.clear(); + + let protocol = match state.connect_protocol { + 0 => Protocol::Sftp, + 1 => Protocol::Ftp, + _ => Protocol::Ftps, + }; + + let port: u16 = state.connect_port.parse().unwrap_or(match protocol { + Protocol::Sftp => 22, + Protocol::Ftp => 21, + Protocol::Ftps => 990, + }); + + let params = ConnectionParams { + id: uuid::Uuid::new_v4().to_string(), + label: if state.connect_label.is_empty() { + state.connect_host.clone() + } else { + state.connect_label.clone() + }, + protocol, + host: state.connect_host.clone(), + port, + username: state.connect_user.clone(), + password: if state.connect_pass.is_empty() { + None + } else { + Some(state.connect_pass.clone()) + }, + key_path: if state.connect_key_path.is_empty() { + None + } else { + Some(state.connect_key_path.clone()) + }, + }; + + let registry = registry.clone(); + let params_clone = params.clone(); + let result = Arc::new(std::sync::Mutex::new(None)); + let result_clone = result.clone(); + + state.connect_loading = true; + rt_handle.spawn(async move { + let r = do_connect(®istry, ¶ms_clone).await; + *result_clone.lock().unwrap() = Some(r); + }); + + state.pending_connect = Some(PendingConnect { result }); + } + }); + + if state.connect_loading { + ui.label("Connecting..."); + } + }); + + if !open { + state.show_connect_dialog = false; + } +} + +async fn do_connect( + registry: &RemoteRegistry, + params: &ConnectionParams, +) -> Result<(ConnectionParams, Vec), String> { + let password = if let Some(p) = ¶ms.password { + p.clone() + } else { + keychain::get_password(¶ms.id).map_err(|e| e.to_string())? + }; + + let fs: Arc = match params.protocol { + Protocol::Sftp => { + if let Some(key_path) = ¶ms.key_path { + Arc::new( + SftpClient::connect_key(¶ms.host, params.port, ¶ms.username, key_path) + .map_err(|e| e.to_string())?, + ) + } else { + Arc::new( + SftpClient::connect_password( + ¶ms.host, + params.port, + ¶ms.username, + &password, + ) + .map_err(|e| e.to_string())?, + ) + } + } + Protocol::Ftp => Arc::new( + FtpClient::connect(¶ms.host, params.port, ¶ms.username, &password) + .await + .map_err(|e| e.to_string())?, + ), + Protocol::Ftps => return Err("FTPS not yet implemented".into()), + }; + + registry.insert(params.id.clone(), fs.clone()); + + let entries = fs.list("/").await.map_err(|e| e.to_string())?; + Ok((params.clone(), entries)) +} diff --git a/src-tauri/src/ui/dialogs/mod.rs b/src-tauri/src/ui/dialogs/mod.rs new file mode 100644 index 0000000..b3b606b --- /dev/null +++ b/src-tauri/src/ui/dialogs/mod.rs @@ -0,0 +1 @@ +pub mod connection; diff --git a/src-tauri/src/ui/drag.rs b/src-tauri/src/ui/drag.rs new file mode 100644 index 0000000..63a40e5 --- /dev/null +++ b/src-tauri/src/ui/drag.rs @@ -0,0 +1,47 @@ +use crate::domain::file_entry::FileEntry; + +#[derive(Clone, Debug)] +pub enum DragPayload { + LocalFile(String, String), + RemoteFile(String, String, String), +} + +impl DragPayload { + pub fn file_name(&self) -> &str { + match self { + DragPayload::LocalFile(_, name) => name, + DragPayload::RemoteFile(_, name, _) => name, + } + } +} + +pub fn make_local_payload(entry: &FileEntry) -> Option { + if entry.name == ".." { + return None; + } + Some(DragPayload::LocalFile( + entry.path.clone(), + entry.name.clone(), + )) +} + +pub fn make_remote_payload(entry: &FileEntry, connection_id: &str) -> Option { + if entry.name == ".." { + return None; + } + Some(DragPayload::RemoteFile( + entry.path.clone(), + entry.name.clone(), + connection_id.to_string(), + )) +} + +impl DragPayload { + pub fn is_from_local(&self) -> bool { + matches!(self, DragPayload::LocalFile(_, _)) + } + + pub fn is_from_remote(&self) -> bool { + matches!(self, DragPayload::RemoteFile(_, _, _)) + } +} diff --git a/src-tauri/src/ui/mod.rs b/src-tauri/src/ui/mod.rs new file mode 100644 index 0000000..33d7818 --- /dev/null +++ b/src-tauri/src/ui/mod.rs @@ -0,0 +1,5 @@ +pub mod app; +pub mod dialogs; +pub mod drag; +pub mod panels; +pub mod state; diff --git a/src-tauri/src/ui/panels/file_pane.rs b/src-tauri/src/ui/panels/file_pane.rs new file mode 100644 index 0000000..283b98b --- /dev/null +++ b/src-tauri/src/ui/panels/file_pane.rs @@ -0,0 +1,100 @@ +use crate::domain::file_entry::{EntryKind, FileEntry}; +use crate::ui::drag::DragPayload; +use egui::{Grid, Id}; + +pub fn format_size(bytes: Option) -> String { + match bytes { + None => String::new(), + Some(b) if b < 1024 => format!("{} B", b), + Some(b) if b < 1024 * 1024 => format!("{:.1} KB", b as f64 / 1024.0), + Some(b) if b < 1024 * 1024 * 1024 => { + format!("{:.1} MB", b as f64 / (1024.0 * 1024.0)) + } + Some(b) => format!("{:.2} GB", b as f64 / (1024.0 * 1024.0 * 1024.0)), + } +} + +pub fn format_time(ts: Option) -> String { + match ts.and_then(|t| chrono::DateTime::from_timestamp(t, 0)) { + Some(dt) => dt.format("%Y-%m-%d %H:%M").to_string(), + None => String::new(), + } +} + +pub struct FileTableResponse { + pub double_clicked: Option, + pub clicked: Option, +} + +pub fn file_table( + ui: &mut egui::Ui, + id: &str, + entries: &[FileEntry], + selected: &mut Option, + make_drag_payload: F, +) -> FileTableResponse +where + F: Fn(&FileEntry) -> Option, +{ + let mut double_clicked: Option = None; + let mut clicked: Option = None; + + let mut sorted = entries.to_vec(); + sorted.sort_by(|a, b| match (&a.kind, &b.kind) { + (EntryKind::Dir, EntryKind::Dir) => a.name.cmp(&b.name), + (EntryKind::Dir, _) => std::cmp::Ordering::Less, + (_, EntryKind::Dir) => std::cmp::Ordering::Greater, + _ => a.name.cmp(&b.name), + }); + + egui::ScrollArea::vertical() + .auto_shrink([false; 2]) + .show(ui, |ui| { + Grid::new(id) + .striped(true) + .min_col_width(60.0) + .show(ui, |ui| { + ui.strong("Name"); + ui.strong("Size"); + ui.strong("Type"); + ui.strong("Modified"); + ui.end_row(); + + for entry in &sorted { + let is_selected = selected.as_ref() == Some(&entry.name); + + let response = if let Some(payload) = make_drag_payload(entry) { + let drag_id = Id::new(("drag", id, &entry.name)); + ui.dnd_drag_source(drag_id, payload, |ui| { + ui.selectable_label(is_selected, &entry.name) + }) + .response + } else { + ui.selectable_label(is_selected, &entry.name) + }; + + if response.clicked() { + *selected = Some(entry.name.clone()); + clicked = Some(entry.name.clone()); + } + if response.double_clicked() { + double_clicked = Some(entry.name.clone()); + } + + ui.label(format_size(entry.size)); + ui.label(match entry.kind { + EntryKind::Dir => "Dir", + EntryKind::File => "File", + EntryKind::Symlink => "Link", + }); + ui.label(format_time(entry.modified)); + ui.end_row(); + } + }); + }); + + FileTableResponse { + double_clicked, + clicked, + } +} diff --git a/src-tauri/src/ui/panels/local_pane.rs b/src-tauri/src/ui/panels/local_pane.rs new file mode 100644 index 0000000..ddb6787 --- /dev/null +++ b/src-tauri/src/ui/panels/local_pane.rs @@ -0,0 +1,194 @@ +use crate::domain::connection::ConnectionStatus; +use crate::domain::file_entry::{EntryKind, FileEntry}; +use crate::domain::transfer::{TransferKind, TransferTask}; +use crate::fs::local; +use crate::fs::remote::RemoteRegistry; +use crate::transfer::queue::TransferQueue; +use crate::ui::drag::{make_local_payload, DragPayload}; +use crate::ui::panels::file_pane::{file_table, FileTableResponse}; +use crate::ui::state::AppState; +use egui::TextEdit; +use std::sync::Arc; + +fn parent_path(path: &str) -> String { + let p = std::path::Path::new(path); + p.parent() + .map(|p| p.to_string_lossy().to_string()) + .unwrap_or_else(|| path.to_string()) +} + +fn make_parent_entry(path: &str) -> FileEntry { + FileEntry { + name: "..".into(), + path: parent_path(path), + kind: EntryKind::Dir, + size: None, + modified: None, + permissions: None, + } +} + +pub fn render( + ui: &mut egui::Ui, + state: &mut AppState, + queue: &TransferQueue, + registry: &Arc, + _rt_handle: &tokio::runtime::Handle, +) { + ui.horizontal(|ui| { + ui.heading("\u{1F4C1} Local"); + ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { + if ui.small_button("\u{1F5C4}").clicked() { + state.local_tree_open = !state.local_tree_open; + } + }); + }); + + let frame = egui::Frame::none().inner_margin(egui::Margin::symmetric(4.0, 2.0)); + let (_inner, dropped) = ui.dnd_drop_zone::(frame, |ui| { + if state.local_tree_open { + ui.horizontal(|ui| { + ui.separator(); + ui.vertical(|ui| { + render_tree(ui, state); + }); + ui.separator(); + ui.vertical(|ui| { + render_content(ui, state); + }); + }); + } else { + render_content(ui, state); + } + }); + + if let Some(payload_arc) = dropped { + let payload = &*payload_arc; + match payload { + DragPayload::RemoteFile(remote_path, file_name, conn_id) => { + if registry.get(conn_id).is_none() { + state.status_message = "Connection no longer active".into(); + return; + } + let local_path_str = + format!("{}/{}", state.local_path.trim_end_matches('/'), file_name); + let task = TransferTask::new( + TransferKind::Download, + conn_id.clone(), + local_path_str, + remote_path.clone(), + file_name.clone(), + 0, + ); + queue.push(task); + state.status_message = "Download queued via drag & drop".into(); + } + DragPayload::LocalFile(_, _) => { + state.status_message = "Cannot drop local file onto local pane".into(); + } + } + } +} + +fn render_tree(ui: &mut egui::Ui, state: &mut AppState) { + let home = dirs::home_dir() + .unwrap_or_default() + .to_string_lossy() + .to_string(); + + egui::ScrollArea::vertical() + .auto_shrink([false; 2]) + .min_scrolled_width(120.0) + .show(ui, |ui| { + ui.strong("Folders"); + ui.separator(); + + let roots = [ + ("/", "Root"), + (&home, "Home"), + ("/tmp", "tmp"), + ("/var", "var"), + ("/etc", "etc"), + ]; + + for (root_path, label) in &roots { + let is_current = state.local_path == *root_path + || state.local_path.starts_with(root_path); + let mut btn = egui::Button::new(*label).min_size(egui::vec2(120.0, 20.0)); + if is_current { + btn = btn.fill(egui::Color32::from_rgb(50, 60, 80)); + } + if ui.add(btn).clicked() { + state.local_path = root_path.to_string(); + refresh_local(state); + } + } + }); +} + +fn render_content(ui: &mut egui::Ui, state: &mut AppState) { + ui.horizontal(|ui| { + let mut path = state.local_path.clone(); + ui.add( + TextEdit::singleline(&mut path) + .id("local_path".into()) + .desired_width(f32::INFINITY), + ); + if path != state.local_path { + state.local_path = path; + refresh_local(state); + } + }); + + ui.separator(); + + let entries = state.local_entries.clone(); + let mut selected = state.local_selected.clone(); + + let FileTableResponse { double_clicked, .. } = + file_table(ui, "local_table", &entries, &mut selected, |entry| { + let has_connection = state + .active_tab_ref() + .map(|t| t.status == ConnectionStatus::Connected) + .unwrap_or(false); + if has_connection { + make_local_payload(entry) + } else { + None + } + }); + + state.local_selected = selected; + + if let Some(name) = double_clicked { + if name == ".." { + state.local_path = parent_path(&state.local_path); + } else if let Some(entry) = state.local_entries.iter().find(|e| e.name == name) + && entry.kind == EntryKind::Dir + { + state.local_path = entry.path.clone(); + } + refresh_local(state); + } + + ui.separator(); + ui.horizontal(|ui| { + ui.label(format!("{} items", state.local_entries.len())); + }); +} + +pub fn refresh_local(state: &mut AppState) { + let mut entries = Vec::new(); + if state.local_path != "/" { + entries.push(make_parent_entry(&state.local_path)); + } + match local::list(&state.local_path) { + Ok(mut list) => { + entries.append(&mut list); + state.local_entries = entries; + } + Err(e) => { + state.status_message = format!("Local list error: {}", e); + } + } +} diff --git a/src-tauri/src/ui/panels/mod.rs b/src-tauri/src/ui/panels/mod.rs new file mode 100644 index 0000000..57867e3 --- /dev/null +++ b/src-tauri/src/ui/panels/mod.rs @@ -0,0 +1,7 @@ +pub mod file_pane; +pub mod local_pane; +pub mod queue; +pub mod remote_pane; +pub mod status_bar; +pub mod tabs; +pub mod toolbar; diff --git a/src-tauri/src/ui/panels/queue.rs b/src-tauri/src/ui/panels/queue.rs new file mode 100644 index 0000000..6ea8271 --- /dev/null +++ b/src-tauri/src/ui/panels/queue.rs @@ -0,0 +1,83 @@ +use crate::domain::transfer::TransferTask; +use crate::ui::panels::file_pane::format_size; +use crate::ui::state::AppState; +use egui::Color32; + +pub fn render(ui: &mut egui::Ui, state: &mut AppState, tasks: &[TransferTask]) { + ui.horizontal(|ui| { + ui.heading("\u{1F4E6} Transfer Queue"); + ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { + if ui.small_button("\u{2715}").clicked() { + state.show_queue = false; + } + }); + }); + + ui.separator(); + + if tasks.is_empty() { + ui.label("No pending transfers"); + return; + } + + egui::ScrollArea::vertical() + .auto_shrink([false; 2]) + .max_height(200.0) + .show(ui, |ui| { + for task in tasks { + let bg = match &task.state { + crate::domain::transfer::TaskState::Completed => { + Color32::from_rgb(220, 255, 220) + } + crate::domain::transfer::TaskState::Failed(_) => { + Color32::from_rgb(255, 220, 220) + } + crate::domain::transfer::TaskState::Running => Color32::from_rgb(220, 220, 255), + _ => Color32::TRANSPARENT, + }; + + egui::Frame::none() + .fill(bg) + .inner_margin(egui::Margin::symmetric(4.0, 2.0)) + .show(ui, |ui| { + ui.horizontal(|ui| { + let arrow = match &task.kind { + crate::domain::transfer::TransferKind::Upload => "\u{2191}", + crate::domain::transfer::TransferKind::Download => "\u{2193}", + }; + ui.label(arrow); + ui.label(&task.file_name); + ui.with_layout( + egui::Layout::right_to_left(egui::Align::Center), + |ui| { + ui.label(task.state.to_string()); + }, + ); + }); + + ui.horizontal(|ui| { + let pct = task.progress_pct(); + let pb = egui::ProgressBar::new(pct as f32 / 100.0) + .text(format!("{:.1}%", pct)) + .desired_width(ui.available_width() * 0.6); + ui.add(pb); + + ui.label(format!( + "{}/{}", + format_size(Some(task.transferred_bytes)), + format_size(Some(task.total_bytes)) + )); + }); + + ui.horizontal(|ui| { + if let Some(speed) = task.speed { + ui.label(format!("{}/s", format_size(Some(speed)))); + } + if let Some(eta) = task.eta_secs { + ui.label(format!("ETA: {}s", eta)); + } + }); + }); + } + }); +} diff --git a/src-tauri/src/ui/panels/remote_pane.rs b/src-tauri/src/ui/panels/remote_pane.rs new file mode 100644 index 0000000..6c0d7bc --- /dev/null +++ b/src-tauri/src/ui/panels/remote_pane.rs @@ -0,0 +1,215 @@ +use crate::domain::connection::ConnectionStatus; +use crate::domain::file_entry::{EntryKind, FileEntry}; +use crate::domain::transfer::{TransferKind, TransferTask}; +use crate::fs::remote::RemoteRegistry; +use crate::transfer::queue::TransferQueue; +use crate::ui::drag::{make_remote_payload, DragPayload}; +use crate::ui::panels::file_pane::{file_table, FileTableResponse}; +use crate::ui::state::{AppState, PendingRemoteList}; +use egui::TextEdit; +use std::sync::Arc; + +pub fn remote_parent(path: &str) -> String { + let trimmed = path.trim_end_matches('/'); + if trimmed.is_empty() || trimmed == "/" { + return "/".into(); + } + if let Some(idx) = trimmed.rfind('/') { + let parent = &trimmed[..idx]; + if parent.is_empty() { + "/".into() + } else { + parent.to_string() + } + } else { + "/".into() + } +} + +pub fn render( + ui: &mut egui::Ui, + state: &mut AppState, + tab_idx: usize, + registry: &Arc, + rt_handle: &tokio::runtime::Handle, + queue: &TransferQueue, +) { + ui.horizontal(|ui| { + ui.heading("\u{1F310} Remote"); + }); + + let frame = egui::Frame::none().inner_margin(egui::Margin::symmetric(4.0, 2.0)); + let (_inner, dropped) = ui.dnd_drop_zone::(frame, |ui| { + render_content(ui, state, tab_idx, registry, rt_handle); + }); + + let is_connected = state.tabs[tab_idx].status == ConnectionStatus::Connected; + let connection_id = state.tabs[tab_idx].id.clone(); + let remote_path = state.tabs[tab_idx].remote_path.clone(); + + if let Some(payload_arc) = dropped { + let payload = &*payload_arc; + match payload { + DragPayload::LocalFile(local_path, file_name) => { + if !is_connected { + state.status_message = "No active connection".into(); + return; + } + let remote_path_str = + format!("{}/{}", remote_path.trim_end_matches('/'), file_name); + let task = TransferTask::new( + TransferKind::Upload, + connection_id.clone(), + local_path.clone(), + remote_path_str, + file_name.clone(), + 0, + ); + queue.push(task); + state.status_message = "Upload queued via drag & drop".into(); + } + DragPayload::RemoteFile(_, _, _) => { + state.status_message = "Cannot drop remote file onto remote pane".into(); + } + } + } +} + +fn render_content( + ui: &mut egui::Ui, + state: &mut AppState, + tab_idx: usize, + registry: &Arc, + rt_handle: &tokio::runtime::Handle, +) { + let label = state.tabs[tab_idx].label.clone(); + ui.horizontal(|ui| { + ui.label(format!("\u{25CF} {}", label)); + if state.tabs[tab_idx].loading { + ui.label("loading..."); + } + }); + + let path_changed; + { + let tab = &state.tabs[tab_idx]; + let mut path = tab.remote_path.clone(); + ui.horizontal(|ui| { + ui.add( + TextEdit::singleline(&mut path) + .id("remote_path".into()) + .desired_width(f32::INFINITY), + ); + }); + path_changed = path != tab.remote_path; + if path_changed { + state.tabs[tab_idx].remote_path = path; + } + } + + if path_changed { + let loading = state.tabs[tab_idx].loading; + if !loading { + trigger_list(state, tab_idx, registry, rt_handle); + } + } + + ui.separator(); + + let entries; + let mut selected; + { + let tab = &state.tabs[tab_idx]; + entries = tab.remote_entries.clone(); + selected = tab.remote_selected.clone(); + } + + let is_connected = state.tabs[tab_idx].status == ConnectionStatus::Connected; + let conn_id = state.tabs[tab_idx].id.clone(); + + let table_id = format!("remote_table_{}", tab_idx); + let FileTableResponse { double_clicked, .. } = + file_table(ui, &table_id, &entries, &mut selected, move |entry| { + if is_connected { + make_remote_payload(entry, &conn_id) + } else { + None + } + }); + + state.tabs[tab_idx].remote_selected = selected; + + if let Some(name) = double_clicked { + let (nav_path, is_dir) = { + if name == ".." { + let parent = remote_parent(state.tabs[tab_idx].remote_path.as_str()); + (parent, true) + } else { + let entry = state.tabs[tab_idx] + .remote_entries + .iter() + .find(|e| e.name == name); + match entry { + Some(e) if e.kind == EntryKind::Dir => (e.path.clone(), true), + _ => (state.tabs[tab_idx].remote_path.clone(), false), + } + } + }; + + if is_dir { + state.tabs[tab_idx].remote_path = nav_path; + let loading = state.tabs[tab_idx].loading; + if !loading { + trigger_list(state, tab_idx, registry, rt_handle); + } + } + } + + ui.separator(); + { + let tab = &state.tabs[tab_idx]; + ui.horizontal(|ui| { + ui.label(format!("{} items", tab.remote_entries.len())); + if tab.loading { + ui.label(" loading..."); + } + }); + } +} + +pub fn trigger_list( + state: &mut AppState, + tab_idx: usize, + registry: &Arc, + rt_handle: &tokio::runtime::Handle, +) { + if state.tabs[tab_idx].status != ConnectionStatus::Connected { + state.status_message = "Not connected".into(); + return; + } + state.tabs[tab_idx].loading = true; + + let connection_id = state.tabs[tab_idx].id.clone(); + let path = state.tabs[tab_idx].remote_path.clone(); + let registry = registry.clone(); + + let result: Arc, String>>>> = + Arc::new(std::sync::Mutex::new(None)); + let result_clone = result.clone(); + + rt_handle.spawn(async move { + let fs = match registry.get(&connection_id) { + Some(fs) => fs, + None => { + *result_clone.lock().unwrap() = Some(Err("connection not found".into())); + return; + } + }; + let r = fs.list(&path).await.map_err(|e| e.to_string()); + *result_clone.lock().unwrap() = Some(r); + }); + + state + .pending_remote_list + .push(PendingRemoteList { tab_idx, result }); +} diff --git a/src-tauri/src/ui/panels/status_bar.rs b/src-tauri/src/ui/panels/status_bar.rs new file mode 100644 index 0000000..34156a6 --- /dev/null +++ b/src-tauri/src/ui/panels/status_bar.rs @@ -0,0 +1,20 @@ +use crate::domain::connection::ConnectionStatus; +use crate::ui::state::AppState; + +pub fn render(ui: &mut egui::Ui, state: &AppState) { + ui.horizontal(|ui| { + ui.label(&state.status_message); + ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { + let queued = state.queue_tasks.len(); + ui.label(format!("Queue: {}", queued)); + ui.separator(); + let connected = state + .tabs + .iter() + .filter(|t| t.status == ConnectionStatus::Connected) + .count(); + let total = state.tabs.len(); + ui.label(format!("Connections: {}/{}", connected, total)); + }); + }); +} diff --git a/src-tauri/src/ui/panels/tabs.rs b/src-tauri/src/ui/panels/tabs.rs new file mode 100644 index 0000000..309dd7c --- /dev/null +++ b/src-tauri/src/ui/panels/tabs.rs @@ -0,0 +1,55 @@ +use crate::domain::connection::ConnectionStatus; +use crate::ui::state::AppState; + +pub fn render(ui: &mut egui::Ui, state: &mut AppState) { + ui.horizontal(|ui| { + if state.tabs.is_empty() { + ui.label("No connections"); + if ui.button("+ New Connection").clicked() { + state.show_connect_dialog = true; + } + return; + } + + let mut to_close: Option = None; + + for (i, tab) in state.tabs.iter().enumerate() { + let is_active = i == state.active_tab; + + let dot = match &tab.status { + ConnectionStatus::Connected => "\u{25CF}", + ConnectionStatus::Disconnected => "\u{25CB}", + ConnectionStatus::Connecting => "\u{25D0}", + ConnectionStatus::Error(_) => "\u{2716}", + }; + + let label = format!("{} {}", dot, tab.label); + + let mut tab_button = egui::Button::new(&label); + if is_active { + tab_button = tab_button.fill(egui::Color32::from_rgb(60, 60, 80)); + } + let response = ui.add(tab_button); + if response.clicked() { + state.active_tab = i; + } + + if ui.small_button("\u{2715}").clicked() { + to_close = Some(i); + } + } + + if let Some(idx) = to_close { + state.tabs.remove(idx); + if state.active_tab >= state.tabs.len() && !state.tabs.is_empty() { + state.active_tab = state.tabs.len() - 1; + } + } + + ui.separator(); + + if ui.button("+").clicked() { + state.show_connect_dialog = true; + } + }); +} diff --git a/src-tauri/src/ui/panels/toolbar.rs b/src-tauri/src/ui/panels/toolbar.rs new file mode 100644 index 0000000..e9589e8 --- /dev/null +++ b/src-tauri/src/ui/panels/toolbar.rs @@ -0,0 +1,139 @@ +use crate::domain::connection::ConnectionStatus; +use crate::domain::file_entry::EntryKind; +use crate::domain::transfer::{TransferKind, TransferTask}; +use crate::fs::remote::RemoteRegistry; +use crate::transfer::queue::TransferQueue; +use crate::ui::state::AppState; +use std::sync::Arc; + +pub fn render( + ui: &mut egui::Ui, + state: &mut AppState, + queue: &TransferQueue, + registry: &Arc, + _rt_handle: &tokio::runtime::Handle, +) { + ui.horizontal(|ui| { + let add_btn = egui::Button::new("+ New Connection"); + if ui.add(add_btn).clicked() { + state.show_connect_dialog = true; + } + + ui.separator(); + + let has_local_selection = state.local_selected.is_some(); + let has_remote_selection = state + .active_tab_ref() + .and_then(|t| t.remote_selected.as_ref()) + .is_some(); + let (is_connected, tab_exists) = { + let active = state.active_tab_ref(); + ( + active + .map(|t| t.status == ConnectionStatus::Connected) + .unwrap_or(false), + active.is_some(), + ) + }; + + let tab_id = state.active_tab_ref().map(|t| t.id.clone()); + let remote_path = state.active_tab_ref().map(|t| t.remote_path.clone()); + + let upload_btn = egui::Button::new("\u{2191} Upload") + .min_size(egui::vec2(100.0, 24.0)); + ui.add_enabled_ui(is_connected && has_local_selection && tab_exists, |ui| { + if ui.add(upload_btn).clicked() + && let Some(sel) = state.local_selected.clone() + && let Some(entry) = state.local_entries.iter().find(|e| e.name == sel) + { + if entry.kind == EntryKind::File { + let file_name = entry.name.clone(); + let remote_base = remote_path.clone().unwrap_or_else(|| "/".into()); + let remote_path_str = + format!("{}/{}", remote_base.trim_end_matches('/'), file_name); + let cid = tab_id.clone().unwrap_or_default(); + let task = TransferTask::new( + TransferKind::Upload, + cid, + entry.path.clone(), + remote_path_str, + file_name, + entry.size.unwrap_or(0), + ); + if registry.get(&task.connection_id).is_some() { + queue.push(task); + state.status_message = "Upload queued".into(); + } else { + state.status_message = "No connection".into(); + } + } else { + state.status_message = "Cannot upload directory".into(); + } + } + }); + + let download_btn = egui::Button::new("\u{2193} Download") + .min_size(egui::vec2(100.0, 24.0)); + ui.add_enabled_ui(is_connected && has_remote_selection && tab_exists, |ui| { + if ui.add(download_btn).clicked() + && let Some(sel) = tab_remote_selected(state) + { + let file_name = sel.clone(); + let remote_base = remote_path.clone().unwrap_or_else(|| "/".into()); + let remote_path_str = + format!("{}/{}", remote_base.trim_end_matches('/'), file_name); + let local_path_str = + format!("{}/{}", state.local_path.trim_end_matches('/'), file_name); + let size = state + .active_tab_ref() + .map(|t| { + t.remote_entries + .iter() + .find(|e| e.name == sel) + .and_then(|e| e.size) + .unwrap_or(0) + }) + .unwrap_or(0); + let cid = tab_id.clone().unwrap_or_default(); + let task = TransferTask::new( + TransferKind::Download, + cid, + local_path_str, + remote_path_str, + file_name, + size, + ); + if registry.get(&task.connection_id).is_some() { + queue.push(task); + state.status_message = "Download queued".into(); + } else { + state.status_message = "No connection".into(); + } + } + }); + + ui.separator(); + + let queue_label = if state.show_queue { + "Queue \u{25BC}" + } else { + "Queue \u{25B2}" + }; + if ui.button(queue_label).clicked() { + state.show_queue = !state.show_queue; + } + + ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { + ui.separator(); + let task_count = state.queue_tasks.len(); + if task_count > 0 { + ui.label(format!("{} tasks", task_count)); + } + }); + }); +} + +fn tab_remote_selected(state: &AppState) -> Option { + let idx = state.active_tab.min(state.tabs.len().saturating_sub(1)); + state.tabs.get(idx).and_then(|t| t.remote_selected.clone()) +} diff --git a/src-tauri/src/ui/state.rs b/src-tauri/src/ui/state.rs new file mode 100644 index 0000000..b720e7c --- /dev/null +++ b/src-tauri/src/ui/state.rs @@ -0,0 +1,107 @@ +use std::sync::Arc; + +use crate::domain::connection::{ConnectionParams, ConnectionStatus}; +use crate::domain::file_entry::FileEntry; +use crate::domain::transfer::TransferTask; + +#[derive(Clone)] +pub struct ConnectionTab { + pub id: String, + pub label: String, + pub params: ConnectionParams, + pub status: ConnectionStatus, + pub remote_path: String, + pub remote_entries: Vec, + pub remote_selected: Option, + pub loading: bool, +} + +type PendingResult = Arc>>>; + +pub struct PendingConnect { + pub result: PendingResult<(ConnectionParams, Vec)>, +} + +pub struct PendingRemoteList { + pub tab_idx: usize, + pub result: PendingResult>, +} + +pub struct AppState { + pub tabs: Vec, + pub active_tab: usize, + pub local_path: String, + pub local_entries: Vec, + pub local_selected: Option, + pub local_tree_open: bool, + pub show_connect_dialog: bool, + pub connect_label: String, + pub connect_host: String, + pub connect_port: String, + pub connect_user: String, + pub connect_pass: String, + pub connect_key_path: String, + pub connect_protocol: usize, + pub connect_error: String, + pub connect_loading: bool, + pub show_queue: bool, + pub queue_tasks: Vec, + pub status_message: String, + pub agg_speed: u64, + pub connected_count: usize, + pub pending_connect: Option, + pub pending_remote_list: Vec, +} + +impl Default for AppState { + fn default() -> Self { + Self { + tabs: Vec::new(), + active_tab: 0, + local_path: dirs::home_dir() + .unwrap_or_default() + .to_string_lossy() + .to_string(), + local_entries: Vec::new(), + local_selected: None, + local_tree_open: false, + show_connect_dialog: false, + connect_label: String::new(), + connect_host: String::new(), + connect_port: "22".into(), + connect_user: String::new(), + connect_pass: String::new(), + connect_key_path: String::new(), + connect_protocol: 0, + connect_error: String::new(), + connect_loading: false, + show_queue: false, + queue_tasks: Vec::new(), + status_message: "Ready".into(), + agg_speed: 0, + connected_count: 0, + pending_connect: None, + pending_remote_list: Vec::new(), + } + } +} + +impl AppState { + pub fn active_tab_mut(&mut self) -> Option<&mut ConnectionTab> { + if self.tabs.is_empty() { + None + } else { + let idx = self.active_tab.min(self.tabs.len() - 1); + Some(&mut self.tabs[idx]) + } + } + + pub fn active_tab_ref(&self) -> Option<&ConnectionTab> { + if self.tabs.is_empty() { + None + } else { + let idx = self.active_tab.min(self.tabs.len() - 1); + Some(&self.tabs[idx]) + } + } +} diff --git a/todo.md b/todo.md new file mode 100644 index 0000000..d3a9954 --- /dev/null +++ b/todo.md @@ -0,0 +1,10 @@ +# TODO + +- [ ] Chunked upload/download с прогресс-событиями +- [x] FTP/FTPS — FTP реализован (FTPS — stub) +- [ ] Site Manager UI +- [x] Диалог нового соединения +- [x] Transfer Queue с воркером и прогресс-событиями +- [ ] Drag & drop +- [ ] Горячие клавиши +- [ ] egui UI (переезд с Svelte)