diff --git a/.gitignore b/.gitignore index c60be72..b2300d2 100644 --- a/.gitignore +++ b/.gitignore @@ -29,4 +29,6 @@ src-tauri/flamegraph.svg src-tauri/perf* /*.AppImage -/squashfs-root \ No newline at end of file +/squashfs-root + +/target/ diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 0cc2dc7..22a9832 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -4,18 +4,18 @@ version = 4 [[package]] name = "addr2line" -version = "0.24.2" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" dependencies = [ "gimli", ] [[package]] name = "adler2" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "aho-corasick" @@ -41,12 +41,6 @@ dependencies = [ "alloc-no-stdlib", ] -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - [[package]] name = "android_system_properties" version = "0.1.5" @@ -58,9 +52,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.98" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" [[package]] name = "arc-swap" @@ -83,12 +77,15 @@ dependencies = [ "enumflags2", "futures-channel", "futures-util", - "rand 0.9.1", + "rand 0.9.2", "raw-window-handle", "serde", "serde_repr", "tokio", "url", + "wayland-backend", + "wayland-client", + "wayland-protocols", "zbus", ] @@ -120,7 +117,7 @@ dependencies = [ "nom", "num-traits", "rusticata-macros", - "thiserror 2.0.12", + "thiserror 2.0.17", "time", ] @@ -132,7 +129,7 @@ checksum = "965c2d33e53cb6b267e148a4cb0760bc01f4904c1cd4bb4002a085bb016d1490" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.106", "synstructure", ] @@ -144,7 +141,7 @@ checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.106", "synstructure", ] @@ -156,7 +153,7 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.106", ] [[package]] @@ -165,7 +162,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" dependencies = [ - "event-listener 5.4.0", + "event-listener 5.4.1", "event-listener-strategy", "futures-core", "pin-project-lite", @@ -184,9 +181,9 @@ dependencies = [ [[package]] name = "async-channel" -version = "2.3.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" +checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" dependencies = [ "concurrent-queue", "event-listener-strategy", @@ -196,9 +193,9 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.13.2" +version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb812ffb58524bdd10860d7d974e2f01cc0950c2438a74ee5ec2e2280c6c4ffa" +checksum = "497c00e0fd83a72a79a39fcbd8e3e2f055d6f6c7e025f3b3d91f4f8e76527fb8" dependencies = [ "async-task", "concurrent-queue", @@ -214,7 +211,7 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" dependencies = [ - "async-channel 2.3.1", + "async-channel 2.5.0", "async-executor", "async-io", "async-lock", @@ -225,51 +222,49 @@ dependencies = [ [[package]] name = "async-io" -version = "2.4.1" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1237c0ae75a0f3765f58910ff9cdd0a12eeb39ab2f4c7de23262f337f0aacbb3" +checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" dependencies = [ - "async-lock", + "autocfg", "cfg-if", "concurrent-queue", "futures-io", "futures-lite", "parking", "polling", - "rustix 1.0.7", + "rustix 1.1.2", "slab", - "tracing", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "async-lock" -version = "3.4.0" +version = "3.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" +checksum = "5fd03604047cee9b6ce9de9f70c6cd540a0520c813cbd49bae61f33ab80ed1dc" dependencies = [ - "event-listener 5.4.0", + "event-listener 5.4.1", "event-listener-strategy", "pin-project-lite", ] [[package]] name = "async-process" -version = "2.3.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde3f4e40e6021d7acffc90095cbd6dc54cb593903d1de5832f435eb274b85dc" +checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75" dependencies = [ - "async-channel 2.3.1", + "async-channel 2.5.0", "async-io", "async-lock", "async-signal", "async-task", "blocking", "cfg-if", - "event-listener 5.4.0", + "event-listener 5.4.1", "futures-lite", - "rustix 1.0.7", - "tracing", + "rustix 1.1.2", ] [[package]] @@ -280,14 +275,14 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.106", ] [[package]] name = "async-signal" -version = "0.2.11" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7605a4e50d4b06df3898d5a70bf5fde51ed9059b0434b73105193bc27acce0d" +checksum = "43c070bbf59cd3570b6b2dd54cd772527c7c3620fce8be898406dd3ed6adc64c" dependencies = [ "async-io", "async-lock", @@ -295,17 +290,17 @@ dependencies = [ "cfg-if", "futures-core", "futures-io", - "rustix 1.0.7", + "rustix 1.1.2", "signal-hook-registry", "slab", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "async-std" -version = "1.13.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "730294c1c08c2e0f85759590518f6333f0d5a0a766a27d519c1b244c3dfd8a24" +checksum = "2c8e079a4ab67ae52b7403632e4618815d6db36d2a010cfe41b02c1b1578f93b" dependencies = [ "async-channel 1.9.0", "async-global-executor", @@ -336,20 +331,20 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.88" +version = "0.1.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.106", ] [[package]] name = "async-tungstenite" -version = "0.29.1" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef0f7efedeac57d9b26170f72965ecfd31473ca52ca7a64e925b0b6f5f079886" +checksum = "ee88b4c88ac8c9ea446ad43498955750a4bbe64c4392f21ccfe5d952865e318f" dependencies = [ "atomic-waker", "futures-core", @@ -386,9 +381,9 @@ dependencies = [ [[package]] name = "atomic-instant-full" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db6541700e074cda41b1c6f98c2cae6cde819967bf142078f069cad85387cdbe" +checksum = "83148e838612d8d701ce16b9f64b8674c097e1b4a14037b294baec03d9072228" [[package]] name = "atomic-waker" @@ -409,15 +404,15 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "backtrace" -version = "0.3.75" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" +checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" dependencies = [ "addr2line", "cfg-if", @@ -425,7 +420,7 @@ dependencies = [ "miniz_oxide", "object", "rustc-demangle", - "windows-targets 0.52.6", + "windows-link 0.2.1", ] [[package]] @@ -460,9 +455,9 @@ dependencies = [ [[package]] name = "bitcode" -version = "0.6.6" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf300f4aa6e66f3bdff11f1236a88c622fe47ea814524792240b4d554d9858ee" +checksum = "648bd963d2e5d465377acecfb4b827f9f553b6bc97a8f61715779e9ed9e52b74" dependencies = [ "arrayvec", "bitcode_derive", @@ -473,13 +468,13 @@ dependencies = [ [[package]] name = "bitcode_derive" -version = "0.6.5" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42b6b4cb608b8282dc3b53d0f4c9ab404655d562674c682db7e6c0458cc83c23" +checksum = "ffebfc2d28a12b262c303cb3860ee77b91bd83b1f20f0bd2a9693008e2f55a9e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.106", ] [[package]] @@ -490,9 +485,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.9.1" +version = "2.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" dependencies = [ "serde", ] @@ -515,7 +510,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ - "generic-array 0.14.7", + "generic-array 0.14.8", ] [[package]] @@ -524,7 +519,7 @@ version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "generic-array 0.14.7", + "generic-array 0.14.8", ] [[package]] @@ -547,20 +542,20 @@ dependencies = [ [[package]] name = "block2" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "340d2f0bdb2a43c1d3cd40513185b2bd7def0aa1052f956455114bc98f82dcf2" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" dependencies = [ - "objc2 0.6.1", + "objc2 0.6.3", ] [[package]] name = "blocking" -version = "1.6.1" +version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" +checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" dependencies = [ - "async-channel 2.3.1", + "async-channel 2.5.0", "async-task", "futures-io", "futures-lite", @@ -569,15 +564,15 @@ dependencies = [ [[package]] name = "boxcar" -version = "0.2.12" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66bb12751a83493ef4b8da1120451a262554e216a247f14b48cb5e8fe7ed8bdf" +checksum = "36f64beae40a84da1b4b26ff2761a5b895c12adc41dc25aaee1c4f2bbfe97a6e" [[package]] name = "brotli" -version = "8.0.1" +version = "8.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9991eea70ea4f293524138648e41ee89b0b2b12ddef3b255effa43c8056e0e0d" +checksum = "4bd8b9603c7aa97359dbd97ecf258968c95f3adddd6db2f7e7a5bef101c84560" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -596,9 +591,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.17.0" +version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "byte-tools" @@ -608,9 +603,9 @@ checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" [[package]] name = "bytemuck" -version = "1.23.0" +version = "1.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9134a6ef01ce4b366b50689c94f82c14bc72bc5d0386829828a2e2752ef7958c" +checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" [[package]] name = "byteorder" @@ -682,7 +677,7 @@ version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.4", "cairo-sys-rs", "glib", "libc", @@ -703,11 +698,11 @@ dependencies = [ [[package]] name = "camino" -version = "1.1.9" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" +checksum = "276a59bf2b2c967788139340c9f0c5b12d7fd6630315c15c217e559de85d2609" dependencies = [ - "serde", + "serde_core", ] [[package]] @@ -730,25 +725,26 @@ dependencies = [ "semver", "serde", "serde_json", - "thiserror 2.0.12", + "thiserror 2.0.17", ] [[package]] name = "cargo_toml" -version = "0.22.1" +version = "0.22.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02260d489095346e5cafd04dea8e8cb54d1d74fcd759022a9b72986ebe9a1257" +checksum = "374b7c592d9c00c1f4972ea58390ac6b18cbb6ab79011f3bdc90a0b82ca06b77" dependencies = [ "serde", - "toml", + "toml 0.9.8", ] [[package]] name = "cc" -version = "1.2.24" +version = "1.2.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16595d3be041c03b09d08d0858631facccee9221e579704070e6e9e4915d3bc7" +checksum = "ac9fe6cdbb24b6ade63616c0a0688e45bb56732262c158df3c0c4bea4ca47cb7" dependencies = [ + "find-msvc-tools", "jobserver", "libc", "shlex", @@ -783,9 +779,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" [[package]] name = "cfg_aliases" @@ -795,17 +791,47 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" -version = "0.4.41" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" +checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" dependencies = [ - "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "serde", "wasm-bindgen", - "windows-link", + "windows-link 0.2.1", +] + +[[package]] +name = "client" +version = "0.1.0" +dependencies = [ + "bitcode", + "database", + "log", + "serde", + "tauri", + "tauri-plugin-autostart", +] + +[[package]] +name = "cloud_saves" +version = "0.1.0" +dependencies = [ + "database", + "dirs 6.0.0", + "log", + "regex", + "rustix 1.1.2", + "serde", + "serde_json", + "serde_with", + "tar", + "tempfile", + "uuid", + "whoami", + "zstd", ] [[package]] @@ -895,7 +921,7 @@ version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa95a34622365fa5bbf40b20b75dba8dfa8c94c734aea8ac9a5ca38af14316f1" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.4", "core-foundation 0.10.1", "core-graphics-types", "foreign-types 0.5.0", @@ -908,7 +934,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.4", "core-foundation 0.10.1", "libc", ] @@ -924,9 +950,9 @@ dependencies = [ [[package]] name = "crc32fast" -version = "1.4.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" dependencies = [ "cfg-if", ] @@ -967,9 +993,9 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crunchy" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" [[package]] name = "crypto-common" @@ -977,7 +1003,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "generic-array 0.14.7", + "generic-array 0.14.8", "typenum", ] @@ -1005,7 +1031,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.101", + "syn 2.0.106", ] [[package]] @@ -1015,14 +1041,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501" dependencies = [ "quote", - "syn 2.0.101", + "syn 2.0.106", ] [[package]] name = "darling" -version = "0.20.11" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" dependencies = [ "darling_core", "darling_macro", @@ -1030,27 +1056,27 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.11" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim", - "syn 2.0.101", + "syn 2.0.106", ] [[package]] name = "darling_macro" -version = "0.20.11" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ "darling_core", "quote", - "syn 2.0.101", + "syn 2.0.106", ] [[package]] @@ -1059,6 +1085,21 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" +[[package]] +name = "database" +version = "0.1.0" +dependencies = [ + "chrono", + "dirs 6.0.0", + "log", + "native_model", + "rustbreak", + "serde", + "serde_with", + "url", + "whoami", +] + [[package]] name = "der-parser" version = "9.0.0" @@ -1092,20 +1133,15 @@ name = "deranged" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" -dependencies = [ - "powerfmt", - "serde", -] [[package]] -name = "derivative" -version = "2.2.0" +name = "deranged" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +checksum = "a41953f86f8a05768a6cda24def994fd2f424b04ec5c719cf89989779f199071" dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "powerfmt", + "serde_core", ] [[package]] @@ -1118,7 +1154,28 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.101", + "syn 2.0.106", +] + +[[package]] +name = "derive_more" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", + "unicode-xid", ] [[package]] @@ -1142,7 +1199,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ - "generic-array 0.14.7", + "generic-array 0.14.8", ] [[package]] @@ -1192,8 +1249,8 @@ checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" dependencies = [ "libc", "option-ext", - "redox_users 0.5.0", - "windows-sys 0.59.0", + "redox_users 0.5.2", + "windows-sys 0.61.2", ] [[package]] @@ -1202,26 +1259,16 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" -[[package]] -name = "dispatch2" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a0d569e003ff27784e0e14e4a594048698e0c0f0b66cabcb51511be55a7caa0" -dependencies = [ - "bitflags 2.9.1", - "block2 0.6.1", - "libc", - "objc2 0.6.1", -] - [[package]] name = "dispatch2" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" dependencies = [ - "bitflags 2.9.1", - "objc2 0.6.1", + "bitflags 2.9.4", + "block2 0.6.2", + "libc", + "objc2 0.6.3", ] [[package]] @@ -1232,14 +1279,23 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.106", +] + +[[package]] +name = "dlib" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" +dependencies = [ + "libloading 0.8.9", ] [[package]] name = "dlopen2" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1297103d2bbaea85724fcee6294c2d50b1081f9ad47d0f6f6f61eda65315a6" +checksum = "b54f373ccf864bf587a89e880fb7610f8d73f3045f13580948ccbcaff26febff" dependencies = [ "dlopen2_derive", "libc", @@ -1255,7 +1311,7 @@ checksum = "788160fb30de9cdd857af31c6a2675904b16ece8fc2737b2c7127ba368c9d0f4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.106", ] [[package]] @@ -1273,6 +1329,29 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + +[[package]] +name = "download_manager" +version = "0.1.0" +dependencies = [ + "atomic-instant-full", + "database", + "humansize", + "log", + "parking_lot 0.12.5", + "remote", + "serde", + "serde_with", + "tauri", + "throttle_my_fn", + "utils", +] + [[package]] name = "dpi" version = "0.1.2" @@ -1292,13 +1371,17 @@ dependencies = [ "bytes", "cacache 13.1.0", "chrono", - "deranged", + "client", + "database", + "deranged 0.4.0", "dirs 6.0.0", + "download_manager", "droplet-rs", "dynfmt", "filetime", "futures-core", "futures-lite", + "games", "gethostname", "hex 0.4.3", "http 1.3.1", @@ -1307,27 +1390,29 @@ dependencies = [ "known-folders", "log", "log4rs", - "md5", + "md5 0.7.0", "native_model", "page_size", - "parking_lot 0.12.3", - "rand 0.9.1", + "parking_lot 0.12.5", + "process", + "rand 0.9.2", "rayon", "regex", - "reqwest 0.12.22", + "remote", + "reqwest 0.12.23", "reqwest-middleware 0.4.2", "reqwest-middleware-cache", "reqwest-websocket", "rustbreak", "rustix 0.38.44", - "schemars", + "schemars 0.8.22", "serde", "serde_json", "serde_with", "sha1", "shared_child", "slice-deque", - "sysinfo", + "sysinfo 0.36.1", "tar", "tauri", "tauri-build", @@ -1345,6 +1430,7 @@ dependencies = [ "umu-wrapper-lib", "url", "urlencoding", + "utils", "uuid", "walkdir", "webbrowser", @@ -1390,9 +1476,9 @@ checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" [[package]] name = "dyn-clone" -version = "1.0.19" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" [[package]] name = "dynfmt" @@ -1416,16 +1502,16 @@ checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "embed-resource" -version = "3.0.2" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fbc6e0d8e0c03a655b53ca813f0463d2c956bc4db8138dbc89f120b066551e3" +checksum = "55a075fc573c64510038d7ee9abc7990635863992f83ebc52c8b433b8411a02e" dependencies = [ "cc", "memchr", "rustc_version", - "toml", + "toml 0.9.8", "vswhom", - "winreg 0.52.0", + "winreg 0.55.0", ] [[package]] @@ -1451,9 +1537,9 @@ checksum = "a3d8a32ae18130a3c84dd492d4215c3d913c3b07c6b63c2eb3eb7ff1101ab7bf" [[package]] name = "enumflags2" -version = "0.7.11" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba2f4b465f5318854c6f8dd686ede6c0a9dc67d4b1ac241cf0eb51521a309147" +checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef" dependencies = [ "enumflags2_derive", "serde", @@ -1461,13 +1547,13 @@ dependencies = [ [[package]] name = "enumflags2_derive" -version = "0.7.11" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc4caf64a58d7a6d65ab00639b046ff54399a39f5f2554728895ace4b297cd79" +checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.106", ] [[package]] @@ -1487,22 +1573,23 @@ dependencies = [ [[package]] name = "erased-serde" -version = "0.4.6" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e004d887f51fcb9fef17317a2f3525c887d8aa3f4f50fed920816a688284a5b7" +checksum = "259d404d09818dec19332e31d94558aeb442fea04c817006456c24b5460bbd4b" dependencies = [ "serde", + "serde_core", "typeid", ] [[package]] name = "errno" -version = "0.3.12" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1513,9 +1600,9 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "event-listener" -version = "5.4.0" +version = "5.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae" +checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" dependencies = [ "concurrent-queue", "parking", @@ -1528,7 +1615,7 @@ version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" dependencies = [ - "event-listener 5.4.0", + "event-listener 5.4.1", "pin-project-lite", ] @@ -1565,21 +1652,27 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.25" +version = "0.2.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" +checksum = "bc0505cd1b6fa6580283f6bdf70a73fcf4aba1184038c90902b92b3dd0df63ed" dependencies = [ "cfg-if", "libc", "libredox", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] -name = "flate2" -version = "1.1.1" +name = "find-msvc-tools" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece" +checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127" + +[[package]] +name = "flate2" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc5a4e564e38c699f2880d3fda590bedc2e69f3f84cd48b457bd892ce61d0aa9" dependencies = [ "crc32fast", "miniz_oxide", @@ -1618,7 +1711,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.106", ] [[package]] @@ -1635,9 +1728,9 @@ checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" [[package]] name = "form_urlencoded" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" dependencies = [ "percent-encoding", ] @@ -1702,9 +1795,9 @@ checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-lite" -version = "2.6.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5edaec856126859abb19ed65f39e90fea3a9574b9707f13539acf4abf7eb532" +checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" dependencies = [ "fastrand", "futures-core", @@ -1721,7 +1814,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.106", ] [[package]] @@ -1763,6 +1856,32 @@ dependencies = [ "byteorder", ] +[[package]] +name = "games" +version = "0.1.0" +dependencies = [ + "atomic-instant-full", + "bitcode", + "boxcar", + "database", + "download_manager", + "hex 0.4.3", + "log", + "md5 0.8.0", + "native_model", + "rayon", + "remote", + "reqwest 0.12.23", + "rustix 1.1.2", + "serde", + "serde_json", + "serde_with", + "sysinfo 0.37.2", + "tauri", + "throttle_my_fn", + "utils", +] + [[package]] name = "gdk" version = "0.18.2" @@ -1873,9 +1992,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.7" +version = "0.14.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +checksum = "1dc8f7d2ded5f9209535e4b3fd4d39c002f30902ff5ce9f64e2c33d549576500" dependencies = [ "typenum", "version_check", @@ -1887,7 +2006,7 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc257fdb4038301ce4b9cd1b3b51704509692bb3ff716a410cbd07925d9dae55" dependencies = [ - "rustix 1.0.7", + "rustix 1.1.2", "windows-targets 0.52.6", ] @@ -1911,7 +2030,7 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi 0.11.1+wasi-snapshot-preview1", "wasm-bindgen", ] @@ -1925,15 +2044,15 @@ dependencies = [ "js-sys", "libc", "r-efi", - "wasi 0.14.2+wasi-0.2.4", + "wasi 0.14.7+wasi-0.2.4", "wasm-bindgen", ] [[package]] name = "gimli" -version = "0.31.1" +version = "0.32.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" [[package]] name = "gio" @@ -1969,9 +2088,9 @@ dependencies = [ [[package]] name = "glam" -version = "0.30.4" +version = "0.30.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50a99dbe56b72736564cfa4b85bf9a33079f16ae8b74983ab06af3b1a3696b11" +checksum = "e12d847aeb25f41be4c0ec9587d624e9cd631bc007a8fd7ce3f5851e064c6460" [[package]] name = "glib" @@ -1979,7 +2098,7 @@ version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.4", "futures-channel", "futures-core", "futures-executor", @@ -2003,11 +2122,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bb0228f477c0900c880fd78c8759b95c7636dbd7842707f49e132378aa2acdc" dependencies = [ "heck 0.4.1", - "proc-macro-crate 2.0.0", + "proc-macro-crate 2.0.2", "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.106", ] [[package]] @@ -2022,9 +2141,9 @@ dependencies = [ [[package]] name = "glob" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" [[package]] name = "gloo-timers" @@ -2098,14 +2217,14 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.106", ] [[package]] name = "h2" -version = "0.3.26" +version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" +checksum = "0beca50380b1fc32983fc1cb4587bfa4bb9e78fc259aad4a0032d2080309222d" dependencies = [ "bytes", "fnv", @@ -2113,7 +2232,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.9.0", + "indexmap 2.11.4", "slab", "tokio", "tokio-util", @@ -2122,9 +2241,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.10" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9421a676d1b147b16b82c9225157dc629087ef8ec4d5e2960f9437a90dac0a5" +checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" dependencies = [ "atomic-waker", "bytes", @@ -2132,7 +2251,7 @@ dependencies = [ "futures-core", "futures-sink", "http 1.3.1", - "indexmap 2.9.0", + "indexmap 2.11.4", "slab", "tokio", "tokio-util", @@ -2153,9 +2272,9 @@ checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "hashbrown" -version = "0.15.3" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" [[package]] name = "heck" @@ -2171,9 +2290,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f154ce46856750ed433c8649605bf7ed2de3bc35fd9d2a9f30cddd873c80cb08" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] name = "hex" @@ -2187,15 +2306,6 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -[[package]] -name = "home" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" -dependencies = [ - "windows-sys 0.59.0", -] - [[package]] name = "html5ever" version = "0.29.1" @@ -2326,9 +2436,9 @@ dependencies = [ [[package]] name = "humantime" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f" +checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424" [[package]] name = "hyper" @@ -2340,14 +2450,14 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2 0.3.26", + "h2 0.3.27", "http 0.2.12", "http-body 0.4.6", "httparse", "httpdate", "itoa", "pin-project-lite", - "socket2", + "socket2 0.5.10", "tokio", "tower-service", "tracing", @@ -2356,19 +2466,21 @@ dependencies = [ [[package]] name = "hyper" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" +checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e" dependencies = [ + "atomic-waker", "bytes", "futures-channel", - "futures-util", - "h2 0.4.10", + "futures-core", + "h2 0.4.12", "http 1.3.1", "http-body 1.0.1", "httparse", "itoa", "pin-project-lite", + "pin-utils", "smallvec", "tokio", "want", @@ -2376,12 +2488,12 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.6" +version = "0.27.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03a01595e11bdcec50946522c32dde3fc6914743000a68b93000965f2f02406d" +checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" dependencies = [ "http 1.3.1", - "hyper 1.6.0", + "hyper 1.7.0", "hyper-util", "rustls", "rustls-native-certs", @@ -2400,7 +2512,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", - "hyper 1.6.0", + "hyper 1.7.0", "hyper-util", "native-tls", "tokio", @@ -2410,9 +2522,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.13" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c293b6b3d21eca78250dc7dbebd6b9210ec5530e038cbfe0661b5c47ab06e8" +checksum = "3c6995591a8f1380fcb4ba966a252a4b29188d51d2b89e3a252f5305be65aea8" dependencies = [ "base64 0.22.1", "bytes", @@ -2421,22 +2533,24 @@ dependencies = [ "futures-util", "http 1.3.1", "http-body 1.0.1", - "hyper 1.6.0", + "hyper 1.7.0", "ipnet", "libc", "percent-encoding", "pin-project-lite", - "socket2", + "socket2 0.6.0", + "system-configuration 0.6.1", "tokio", "tower-service", "tracing", + "windows-registry", ] [[package]] name = "iana-time-zone" -version = "0.1.63" +version = "0.1.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" +checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -2444,7 +2558,7 @@ dependencies = [ "js-sys", "log", "wasm-bindgen", - "windows-core", + "windows-core 0.62.2", ] [[package]] @@ -2560,9 +2674,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "1.0.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" dependencies = [ "idna_adapter", "smallvec", @@ -2592,13 +2706,14 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.9.0" +version = "2.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" +checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5" dependencies = [ "equivalent", - "hashbrown 0.15.3", + "hashbrown 0.16.0", "serde", + "serde_core", ] [[package]] @@ -2619,6 +2734,17 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "io-uring" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b" +dependencies = [ + "bitflags 2.9.4", + "cfg-if", + "libc", +] + [[package]] name = "ipnet" version = "2.11.0" @@ -2707,9 +2833,9 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "jobserver" -version = "0.1.33" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" dependencies = [ "getrandom 0.3.3", "libc", @@ -2717,9 +2843,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.77" +version = "0.3.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305" dependencies = [ "once_cell", "wasm-bindgen", @@ -2753,18 +2879,18 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b750dcadc39a09dbadd74e118f6dd6598df77fa01df0cfcdc52c28dece74528a" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.4", "serde", "unicode-segmentation", ] [[package]] name = "known-folders" -version = "1.2.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7d9a1740cc8b46e259a0eb787d79d855e79ff10b9855a5eba58868d5da7927c" +checksum = "d463f34ca3c400fde3a054da0e0b8c6ffa21e4590922f3e18281bb5eeef4cbdc" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -2775,7 +2901,7 @@ checksum = "02cb977175687f33fa4afa0c95c112b987ea1443e5a51c8f8ff27dc618270cc2" dependencies = [ "cssparser", "html5ever", - "indexmap 2.9.0", + "indexmap 2.11.4", "selectors", ] @@ -2814,15 +2940,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e9ec52138abedcc58dc17a7c6c0c00a2bdb4f3427c7f63fa97fd0d859155caf" dependencies = [ "gtk-sys", - "libloading", + "libloading 0.7.4", "once_cell", ] [[package]] name = "libc" -version = "0.2.174" +version = "0.2.177" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" [[package]] name = "libloading" @@ -2834,6 +2960,16 @@ 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 0.2.1", +] + [[package]] name = "libm" version = "0.2.15" @@ -2842,13 +2978,13 @@ checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] name = "libredox" -version = "0.1.3" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.4", "libc", - "redox_syscall 0.5.12", + "redox_syscall 0.5.18", ] [[package]] @@ -2859,9 +2995,9 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "linux-raw-sys" -version = "0.9.4" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" [[package]] name = "litemap" @@ -2871,19 +3007,18 @@ checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" [[package]] name = "lock_api" -version = "0.4.12" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.27" +version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" dependencies = [ "serde", "value-bag", @@ -2897,29 +3032,30 @@ checksum = "a94d21414c1f4a51209ad204c1776a3d0765002c76c6abcb602a6f09f1e881c7" [[package]] name = "log4rs" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0816135ae15bd0391cf284eab37e6e3ee0a6ee63d2ceeb659862bd8d0a984ca6" +checksum = "3e947bb896e702c711fccc2bf02ab2abb6072910693818d1d6b07ee2b9dfd86c" dependencies = [ "anyhow", "arc-swap", "chrono", - "derivative", + "derive_more 2.0.1", "fnv", "humantime", "libc", "log", "log-mdc", - "once_cell", - "parking_lot 0.12.3", - "rand 0.8.5", + "mock_instant", + "parking_lot 0.12.5", + "rand 0.9.2", "serde", "serde-value", "serde_json", "serde_yaml", - "thiserror 1.0.69", + "thiserror 2.0.17", "thread-id", "typemap-ors", + "unicode-segmentation", "winapi", ] @@ -2966,7 +3102,7 @@ checksum = "88a9689d8d44bf9964484516275f5cd4c9b59457a6940c1d5d0ecbb94510a36b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.106", ] [[package]] @@ -2982,10 +3118,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" [[package]] -name = "memchr" -version = "2.7.4" +name = "md5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "ae960838283323069879657ca3de837e9f7bbb4c7bf6ea7f1b290d5e9476d2e0" + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "memmap" @@ -3035,7 +3177,7 @@ checksum = "49e7bc1560b95a3c4a25d03de42fe76ca718ab92d1a22a55b9b4cf67b3ae635c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.106", ] [[package]] @@ -3062,9 +3204,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", "simd-adler32", @@ -3077,29 +3219,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" dependencies = [ "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi 0.11.1+wasi-snapshot-preview1", "windows-sys 0.59.0", ] [[package]] -name = "muda" -version = "0.17.0" +name = "mock_instant" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58b89bf91c19bf036347f1ab85a81c560f08c0667c8601bece664d860a600988" +checksum = "dce6dd36094cac388f119d2e9dc82dc730ef91c32a6222170d630e5414b956e6" + +[[package]] +name = "muda" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01c1738382f66ed56b3b9c8119e794a2e23148ac8ea214eda86622d4cb9d415a" dependencies = [ "crossbeam-channel", "dpi", "gtk", "keyboard-types", - "objc2 0.6.1", + "objc2 0.6.3", "objc2-app-kit", "objc2-core-foundation", - "objc2-foundation 0.3.1", + "objc2-foundation 0.3.2", "once_cell", "png", "serde", - "thiserror 2.0.12", - "windows-sys 0.59.0", + "thiserror 2.0.17", + "windows-sys 0.60.2", ] [[package]] @@ -3131,7 +3279,7 @@ dependencies = [ "native_model_macro", "rmp-serde", "serde", - "thiserror 2.0.12", + "thiserror 2.0.17", "zerocopy", ] @@ -3143,7 +3291,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.106", ] [[package]] @@ -3152,7 +3300,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.4", "jni-sys", "log", "ndk-sys", @@ -3188,7 +3336,7 @@ version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.4", "cfg-if", "cfg_aliases", "libc", @@ -3256,23 +3404,24 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" +checksum = "a973b4e44ce6cad84ce69d797acf9a044532e4184c4f267913d1b546a0727b7a" dependencies = [ "num_enum_derive", + "rustversion", ] [[package]] name = "num_enum_derive" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" +checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d" dependencies = [ - "proc-macro-crate 3.3.0", + "proc-macro-crate 3.4.0", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.106", ] [[package]] @@ -3293,9 +3442,9 @@ dependencies = [ [[package]] name = "objc2" -version = "0.6.1" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88c6597e14493ab2e44ce58f2fdecf095a51f12ca57bec060a11c57332520551" +checksum = "b7c2599ce0ec54857b29ce62166b0ed9b4f6f1a70ccc9a71165b6154caca8c05" dependencies = [ "objc2-encode", "objc2-exception-helper", @@ -3303,77 +3452,104 @@ dependencies = [ [[package]] name = "objc2-app-kit" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6f29f568bec459b0ddff777cec4fe3fd8666d82d5a40ebd0ff7e66134f89bcc" +checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" dependencies = [ - "bitflags 2.9.1", - "block2 0.6.1", + "bitflags 2.9.4", + "block2 0.6.2", "libc", - "objc2 0.6.1", + "objc2 0.6.3", "objc2-cloud-kit", "objc2-core-data", "objc2-core-foundation", "objc2-core-graphics", "objc2-core-image", - "objc2-foundation 0.3.1", - "objc2-quartz-core 0.3.1", + "objc2-core-text", + "objc2-core-video", + "objc2-foundation 0.3.2", + "objc2-quartz-core 0.3.2", ] [[package]] name = "objc2-cloud-kit" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17614fdcd9b411e6ff1117dfb1d0150f908ba83a7df81b1f118005fe0a8ea15d" +checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c" dependencies = [ - "bitflags 2.9.1", - "objc2 0.6.1", - "objc2-foundation 0.3.1", + "bitflags 2.9.4", + "objc2 0.6.3", + "objc2-foundation 0.3.2", ] [[package]] name = "objc2-core-data" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291fbbf7d29287518e8686417cf7239c74700fd4b607623140a7d4a3c834329d" +checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa" dependencies = [ - "bitflags 2.9.1", - "objc2 0.6.1", - "objc2-foundation 0.3.1", + "bitflags 2.9.4", + "objc2 0.6.3", + "objc2-foundation 0.3.2", ] [[package]] name = "objc2-core-foundation" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ - "bitflags 2.9.1", - "dispatch2 0.3.0", - "objc2 0.6.1", + "bitflags 2.9.4", + "dispatch2", + "objc2 0.6.3", ] [[package]] name = "objc2-core-graphics" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "989c6c68c13021b5c2d6b71456ebb0f9dc78d752e86a98da7c716f4f9470f5a4" +checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" dependencies = [ - "bitflags 2.9.1", - "dispatch2 0.3.0", - "objc2 0.6.1", + "bitflags 2.9.4", + "dispatch2", + "objc2 0.6.3", "objc2-core-foundation", "objc2-io-surface", ] [[package]] name = "objc2-core-image" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79b3dc0cc4386b6ccf21c157591b34a7f44c8e75b064f85502901ab2188c007e" +checksum = "e5d563b38d2b97209f8e861173de434bd0214cf020e3423a52624cd1d989f006" dependencies = [ - "objc2 0.6.1", - "objc2-foundation 0.3.1", + "objc2 0.6.3", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-core-text" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d" +dependencies = [ + "bitflags 2.9.4", + "objc2 0.6.3", + "objc2-core-foundation", + "objc2-core-graphics", +] + +[[package]] +name = "objc2-core-video" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d425caf1df73233f29fd8a5c3e5edbc30d2d4307870f802d18f00d83dc5141a6" +dependencies = [ + "bitflags 2.9.4", + "objc2 0.6.3", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-io-surface", ] [[package]] @@ -3397,7 +3573,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.4", "block2 0.5.1", "libc", "objc2 0.5.2", @@ -3405,22 +3581,22 @@ dependencies = [ [[package]] name = "objc2-foundation" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c" +checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ - "bitflags 2.9.1", - "block2 0.6.1", + "bitflags 2.9.4", + "block2 0.6.2", "libc", - "objc2 0.6.1", + "objc2 0.6.3", "objc2-core-foundation", ] [[package]] name = "objc2-io-kit" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71c1c64d6120e51cd86033f67176b1cb66780c2efe34dec55176f77befd93c0a" +checksum = "33fafba39597d6dc1fb709123dfa8289d39406734be322956a69f0931c73bb15" dependencies = [ "libc", "objc2-core-foundation", @@ -3428,12 +3604,22 @@ dependencies = [ [[package]] name = "objc2-io-surface" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7282e9ac92529fa3457ce90ebb15f4ecbc383e8338060960760fa2cf75420c3c" +checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" dependencies = [ - "bitflags 2.9.1", - "objc2 0.6.1", + "bitflags 2.9.4", + "objc2 0.6.3", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-javascript-core" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a1e6550c4caed348956ce3370c9ffeca70bb1dbed4fa96112e7c6170e074586" +dependencies = [ + "objc2 0.6.3", "objc2-core-foundation", ] @@ -3443,7 +3629,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.4", "block2 0.5.1", "objc2 0.5.2", "objc2-foundation 0.2.2", @@ -3455,7 +3641,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.4", "block2 0.5.1", "objc2 0.5.2", "objc2-foundation 0.2.2", @@ -3464,46 +3650,59 @@ dependencies = [ [[package]] name = "objc2-quartz-core" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ffb6a0cd5f182dc964334388560b12a57f7b74b3e2dec5e2722aa2dfb2ccd5" +checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" dependencies = [ - "bitflags 2.9.1", - "objc2 0.6.1", - "objc2-foundation 0.3.1", + "bitflags 2.9.4", + "objc2 0.6.3", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-security" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "709fe137109bd1e8b5a99390f77a7d8b2961dafc1a1c5db8f2e60329ad6d895a" +dependencies = [ + "bitflags 2.9.4", + "objc2 0.6.3", + "objc2-core-foundation", ] [[package]] name = "objc2-ui-kit" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25b1312ad7bc8a0e92adae17aa10f90aae1fb618832f9b993b022b591027daed" +checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" dependencies = [ - "bitflags 2.9.1", - "objc2 0.6.1", + "bitflags 2.9.4", + "objc2 0.6.3", "objc2-core-foundation", - "objc2-foundation 0.3.1", + "objc2-foundation 0.3.2", ] [[package]] name = "objc2-web-kit" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91672909de8b1ce1c2252e95bbee8c1649c9ad9d14b9248b3d7b4c47903c47ad" +checksum = "b2e5aaab980c433cf470df9d7af96a7b46a9d892d521a2cbbb2f8a4c16751e7f" dependencies = [ - "bitflags 2.9.1", - "block2 0.6.1", - "objc2 0.6.1", + "bitflags 2.9.4", + "block2 0.6.2", + "objc2 0.6.3", "objc2-app-kit", "objc2-core-foundation", - "objc2-foundation 0.3.1", + "objc2-foundation 0.3.2", + "objc2-javascript-core", + "objc2-security", ] [[package]] name = "object" -version = "0.36.7" +version = "0.37.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" dependencies = [ "memchr", ] @@ -3562,7 +3761,7 @@ version = "0.10.73" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.4", "cfg-if", "foreign-types 0.3.2", "libc", @@ -3579,7 +3778,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.106", ] [[package]] @@ -3637,23 +3836,24 @@ dependencies = [ [[package]] name = "os_info" -version = "3.11.0" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41fc863e2ca13dc2d5c34fb22ea4a588248ac14db929616ba65c45f21744b1e9" +checksum = "d0e1ac5fde8d43c34139135df8ea9ee9465394b2d8d20f032d38998f64afffc3" dependencies = [ "log", + "plist", "serde", "windows-sys 0.52.0", ] [[package]] name = "os_pipe" -version = "1.2.2" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db335f4760b14ead6290116f2427bf33a14d4f0617d49f78a246de10c1831224" +checksum = "7d8fae84b431384b68627d0f9b3b1245fcf9f46f6c0e3dc902e9dce64edd1967" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -3710,12 +3910,12 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.3" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", - "parking_lot_core 0.9.10", + "parking_lot_core 0.9.12", ] [[package]] @@ -3734,15 +3934,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.10" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.12", + "redox_syscall 0.5.18", "smallvec", - "windows-targets 0.52.6", + "windows-link 0.2.1", ] [[package]] @@ -3759,19 +3959,19 @@ checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" [[package]] name = "pem" -version = "3.0.5" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38af38e8470ac9dee3ce1bae1af9c1671fffc44ddfd8bd1d0a3445bf349a8ef3" +checksum = "1d30c53c26bc5b31a98cd02d20f25a7c8567146caf63ed593a9d87b2775291be" dependencies = [ "base64 0.22.1", - "serde", + "serde_core", ] [[package]] name = "percent-encoding" -version = "2.3.1" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "phf" @@ -3877,7 +4077,7 @@ dependencies = [ "phf_shared 0.11.3", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.106", ] [[package]] @@ -3938,13 +4138,13 @@ checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] name = "plist" -version = "1.7.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac26e981c03a6e53e0aee43c113e3202f5581d5360dae7bd2c70e800dd0451d" +checksum = "740ebea15c5d1428f910cd1a5f52cebf8d25006245ed8ade92702f4943d91e07" dependencies = [ "base64 0.22.1", - "indexmap 2.9.0", - "quick-xml", + "indexmap 2.11.4", + "quick-xml 0.38.3", "serde", "time", ] @@ -3964,24 +4164,23 @@ dependencies = [ [[package]] name = "polling" -version = "3.8.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b53a684391ad002dd6a596ceb6c74fd004fdce75f4be2e3f615068abbea5fd50" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" dependencies = [ "cfg-if", "concurrent-queue", "hermit-abi", "pin-project-lite", - "rustix 1.0.7", - "tracing", - "windows-sys 0.59.0", + "rustix 1.1.2", + "windows-sys 0.61.2", ] [[package]] name = "potential_utf" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a" dependencies = [ "zerovec", ] @@ -4019,20 +4218,21 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "2.0.0" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" +checksum = "b00f26d3400549137f92511a46ac1cd8ce37cb5598a96d382381458b992a5d24" dependencies = [ - "toml_edit 0.20.7", + "toml_datetime 0.6.3", + "toml_edit 0.20.2", ] [[package]] name = "proc-macro-crate" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" +checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" dependencies = [ - "toml_edit 0.22.26", + "toml_edit 0.23.7", ] [[package]] @@ -4067,27 +4267,55 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.95" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" dependencies = [ "unicode-ident", ] +[[package]] +name = "process" +version = "0.1.0" +dependencies = [ + "chrono", + "client", + "database", + "dynfmt", + "games", + "log", + "page_size", + "serde", + "serde_with", + "shared_child", + "tauri", + "tauri-plugin-opener", + "utils", +] + [[package]] name = "quick-xml" -version = "0.32.0" +version = "0.37.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d3a6e5838b60e0e8fa7a43f22ade549a37d61f8bdbe636d0d7816191de969c2" +checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb" +dependencies = [ + "memchr", +] + +[[package]] +name = "quick-xml" +version = "0.38.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42a232e7487fc2ef313d96dde7948e7a3c05101870d8985e4fd8d26aedd27b89" dependencies = [ "memchr", ] [[package]] name = "quinn" -version = "0.11.8" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "626214629cda6781b6dc1d316ba307189c85ba657213ce642d9c77670f8202c8" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" dependencies = [ "bytes", "cfg_aliases", @@ -4096,8 +4324,8 @@ dependencies = [ "quinn-udp", "rustc-hash", "rustls", - "socket2", - "thiserror 2.0.12", + "socket2 0.6.0", + "thiserror 2.0.17", "tokio", "tracing", "web-time", @@ -4105,20 +4333,20 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.12" +version = "0.11.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49df843a9161c85bb8aae55f101bc0bac8bcafd637a620d9122fd7e0b2f7422e" +checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" dependencies = [ "bytes", "getrandom 0.3.3", "lru-slab", - "rand 0.9.1", + "rand 0.9.2", "ring", "rustc-hash", "rustls", "rustls-pki-types", "slab", - "thiserror 2.0.12", + "thiserror 2.0.17", "tinyvec", "tracing", "web-time", @@ -4126,32 +4354,32 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.5.12" +version = "0.5.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee4e529991f949c5e25755532370b8af5d114acae52326361d68d47af64aa842" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2", + "socket2 0.6.0", "tracing", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] name = "quote" -version = "1.0.40" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" dependencies = [ "proc-macro2", ] [[package]] name = "r-efi" -version = "5.2.0" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] name = "rand" @@ -4180,9 +4408,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.3", @@ -4271,9 +4499,9 @@ checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" [[package]] name = "rayon" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" dependencies = [ "either", "rayon-core", @@ -4281,9 +4509,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.12.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" dependencies = [ "crossbeam-deque", "crossbeam-utils", @@ -4314,11 +4542,11 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.12" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.4", ] [[package]] @@ -4334,32 +4562,52 @@ dependencies = [ [[package]] name = "redox_users" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" +checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ "getrandom 0.2.16", "libredox", - "thiserror 2.0.12", + "thiserror 2.0.17", +] + +[[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.106", ] [[package]] name = "reflink-copy" -version = "0.1.26" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78c81d000a2c524133cc00d2f92f019d399e57906c3b7119271a2495354fe895" +checksum = "23bbed272e39c47a095a5242218a67412a220006842558b03fe2935e8f3d7b92" dependencies = [ "cfg-if", "libc", - "rustix 1.0.7", - "windows", + "rustix 1.1.2", + "windows 0.62.2", ] [[package]] name = "regex" -version = "1.11.1" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +checksum = "4a52d8d02cacdb176ef4678de6c052efb4b3da14b78e4db683a4252762be5433" dependencies = [ "aho-corasick", "memchr", @@ -4369,9 +4617,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.9" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +checksum = "722166aa0d7438abbaa4d5cc2c649dac844e8c56d82fb3d33e9c34b5cd268fc6" dependencies = [ "aho-corasick", "memchr", @@ -4380,9 +4628,32 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.5" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +checksum = "c3160422bbd54dd5ecfdca71e5fd59b7b8fe2b1697ab2baf64f6d05dcc66d298" + +[[package]] +name = "remote" +version = "0.1.0" +dependencies = [ + "bitcode", + "chrono", + "client", + "database", + "droplet-rs", + "gethostname", + "hex 0.4.3", + "http 1.3.1", + "log", + "md5 0.8.0", + "reqwest 0.12.23", + "reqwest-websocket", + "serde", + "serde_with", + "tauri", + "url", + "utils", +] [[package]] name = "reqwest" @@ -4395,7 +4666,7 @@ dependencies = [ "encoding_rs", "futures-core", "futures-util", - "h2 0.3.26", + "h2 0.3.27", "http 0.2.12", "http-body 0.4.6", "hyper 0.14.32", @@ -4411,7 +4682,7 @@ dependencies = [ "serde_json", "serde_urlencoded", "sync_wrapper 0.1.2", - "system-configuration", + "system-configuration 0.5.1", "tokio", "tower-service", "url", @@ -4423,25 +4694,27 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.22" +version = "0.12.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbc931937e6ca3a06e3b6c0aa7841849b160a90351d6ab467a8b9b9959767531" +checksum = "d429f34c8092b2d42c7c93cec323bb4adeb7c67698f70839adec842ec10c7ceb" dependencies = [ "base64 0.22.1", "bytes", + "encoding_rs", "futures-channel", "futures-core", "futures-util", - "h2 0.4.10", + "h2 0.4.12", "http 1.3.1", "http-body 1.0.1", "http-body-util", - "hyper 1.6.0", + "hyper 1.7.0", "hyper-rustls", "hyper-tls", "hyper-util", "js-sys", "log", + "mime", "native-tls", "percent-encoding", "pin-project-lite", @@ -4493,7 +4766,7 @@ dependencies = [ "anyhow", "async-trait", "http 1.3.1", - "reqwest 0.12.22", + "reqwest 0.12.23", "serde", "thiserror 1.0.69", "tower-service", @@ -4521,15 +4794,15 @@ dependencies = [ [[package]] name = "reqwest-websocket" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f91a811daaa8b54faeaec9d507a336897a3d243834a4965254a17d39da8b5c9" +checksum = "cd5f79b25f7f17a62cc9337108974431a66ae5a723ac0d9fe78ac1cce2027720" dependencies = [ "async-tungstenite", "bytes", "futures-util", - "reqwest 0.12.22", - "thiserror 2.0.12", + "reqwest 0.12.23", + "thiserror 2.0.17", "tokio", "tokio-util", "tracing", @@ -4539,22 +4812,22 @@ dependencies = [ [[package]] name = "rfd" -version = "0.15.3" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80c844748fdc82aae252ee4594a89b6e7ebef1063de7951545564cbc4e57075d" +checksum = "ef2bee61e6cffa4635c72d7d81a84294e28f0930db0ddcb0f66d10244674ebed" dependencies = [ "ashpd", - "block2 0.6.1", - "dispatch2 0.2.0", + "block2 0.6.2", + "dispatch2", "glib-sys", "gobject-sys", "gtk-sys", "js-sys", "log", - "objc2 0.6.1", + "objc2 0.6.3", "objc2-app-kit", "objc2-core-foundation", - "objc2-foundation 0.3.1", + "objc2-foundation 0.3.2", "raw-window-handle", "wasm-bindgen", "wasm-bindgen-futures", @@ -4600,13 +4873,12 @@ dependencies = [ [[package]] name = "rust-ini" -version = "0.21.1" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e310ef0e1b6eeb79169a1171daf9abcb87a2e17c03bee2c4bb100b55c75409f" +checksum = "796e8d2b6696392a43bea58116b667fb4c29727dc5abd27d6acf338bb4f688c7" dependencies = [ "cfg-if", "ordered-multimap", - "trim-in-place", ] [[package]] @@ -4623,9 +4895,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.24" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" [[package]] name = "rustc-hash" @@ -4657,7 +4929,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.4", "errno", "libc", "linux-raw-sys 0.4.15", @@ -4666,22 +4938,22 @@ dependencies = [ [[package]] name = "rustix" -version = "1.0.7" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" +checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.4", "errno", "libc", - "linux-raw-sys 0.9.4", - "windows-sys 0.59.0", + "linux-raw-sys 0.11.0", + "windows-sys 0.61.2", ] [[package]] name = "rustls" -version = "0.23.27" +version = "0.23.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "730944ca083c1c233a75c09f199e973ca499344a2b7ba9e755c457e86fb4a321" +checksum = "cd3c25631629d034ce7cd9940adc9d45762d46de2b0f57193c4443b92c6d4d40" dependencies = [ "once_cell", "ring", @@ -4700,7 +4972,7 @@ dependencies = [ "openssl-probe", "rustls-pki-types", "schannel", - "security-framework 3.2.0", + "security-framework 3.5.1", ] [[package]] @@ -4715,9 +4987,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.3" +version = "0.103.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4a72fe2bcf7a6ac6fd7d0b9e5cb68aeb7d4c0a0271730218b3e92d43b4eb435" +checksum = "e10b3f4191e8a80e6b43eebabfac91e5dcecebb27a71f04e820c47ec41d314bf" dependencies = [ "ring", "rustls-pki-types", @@ -4726,9 +4998,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.21" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" @@ -4747,11 +5019,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -4769,6 +5041,30 @@ dependencies = [ "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.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82d20c4491bc164fa2f6c5d44565947a52ad80b9505d8e36f8d54c27c739fcd0" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + [[package]] name = "schemars_derive" version = "0.8.22" @@ -4778,9 +5074,15 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.101", + "syn 2.0.106", ] +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + [[package]] name = "scopeguard" version = "1.2.0" @@ -4793,7 +5095,7 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.4", "core-foundation 0.9.4", "core-foundation-sys", "libc", @@ -4802,11 +5104,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "3.2.0" +version = "3.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316" +checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.4", "core-foundation 0.10.1", "core-foundation-sys", "libc", @@ -4815,9 +5117,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.14.0" +version = "2.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" +checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" dependencies = [ "core-foundation-sys", "libc", @@ -4831,7 +5133,7 @@ checksum = "0c37578180969d00692904465fb7f6b3d50b9a2b952b87c23d0e2e5cb5013416" dependencies = [ "bitflags 1.3.2", "cssparser", - "derive_more", + "derive_more 0.99.20", "fxhash", "log", "phf 0.8.0", @@ -4843,30 +5145,33 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.26" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" dependencies = [ "serde", + "serde_core", ] [[package]] name = "serde" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ + "serde_core", "serde_derive", ] [[package]] name = "serde-untagged" -version = "0.1.7" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "299d9c19d7d466db4ab10addd5703e4c615dec2a5a16dbbafe191045e87ee66e" +checksum = "f9faf48a4a2d2693be24c6289dbe26552776eb7737074e6722891fadbe6c5058" dependencies = [ - "erased-serde 0.4.6", + "erased-serde 0.4.8", "serde", + "serde_core", "typeid", ] @@ -4881,14 +5186,23 @@ dependencies = [ ] [[package]] -name = "serde_derive" -version = "1.0.219" +name = "serde_core" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.106", ] [[package]] @@ -4899,19 +5213,20 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.106", ] [[package]] name = "serde_json" -version = "1.0.140" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ "itoa", "memchr", "ryu", "serde", + "serde_core", ] [[package]] @@ -4922,18 +5237,27 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.106", ] [[package]] name = "serde_spanned" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e24345aa0fe688594e73770a5f6d1b216508b4f93484c0026d521acd30134392" +dependencies = [ + "serde_core", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -4948,17 +5272,18 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.12.0" +version = "3.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6b6f7f2fcb69f747921f79f3926bd1e203fce4fef62c268dd3abfb6d86029aa" +checksum = "6093cd8c01b25262b84927e0f7151692158fab02d961e04c979d3903eba7ecc5" dependencies = [ "base64 0.22.1", "chrono", "hex 0.4.3", "indexmap 1.9.3", - "indexmap 2.9.0", - "serde", - "serde_derive", + "indexmap 2.11.4", + "schemars 0.9.0", + "schemars 1.0.4", + "serde_core", "serde_json", "serde_with_macros", "time", @@ -4966,14 +5291,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.12.0" +version = "3.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d00caa5193a3c8362ac2b73be6b9e768aa5a4b2f721d8f4b339600c3cb51f8e" +checksum = "a7e6c180db0816026a61afa1cff5344fb7ebded7e4d3062772179f2501481c27" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.106", ] [[package]] @@ -4982,7 +5307,7 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.9.0", + "indexmap 2.11.4", "itoa", "ryu", "serde", @@ -4991,9 +5316,9 @@ dependencies = [ [[package]] name = "serialize-to-javascript" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9823f2d3b6a81d98228151fdeaf848206a7855a7a042bbf9bf870449a66cafb" +checksum = "04f3666a07a197cdb77cdf306c32be9b7f598d7060d50cfd4d5aa04bfd92f6c5" dependencies = [ "serde", "serde_json", @@ -5002,13 +5327,13 @@ dependencies = [ [[package]] name = "serialize-to-javascript-impl" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74064874e9f6a15f04c1f3cb627902d0e6b410abbf36668afa873c61889f1763" +checksum = "772ee033c0916d670af7860b6e1ef7d658a4629a6d0b4c8c3e67f09b3765b75d" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.106", ] [[package]] @@ -5106,12 +5431,13 @@ dependencies = [ [[package]] name = "shared_child" -version = "1.0.2" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e297bd52991bbe0686c086957bee142f13df85d1e79b0b21630a99d374ae9dc" +checksum = "1e362d9935bc50f019969e2f9ecd66786612daae13e8f277be7bfb66e8bed3f7" dependencies = [ "libc", - "windows-sys 0.59.0", + "sigchld", + "windows-sys 0.60.2", ] [[package]] @@ -5121,10 +5447,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] -name = "signal-hook-registry" -version = "1.4.5" +name = "sigchld" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" +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.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" dependencies = [ "libc", ] @@ -5149,12 +5496,9 @@ checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" [[package]] name = "slab" -version = "0.4.9" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" [[package]] name = "slice-deque" @@ -5169,9 +5513,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.15.0" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "socket2" @@ -5183,6 +5527,16 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "socket2" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + [[package]] name = "softbuffer" version = "0.4.6" @@ -5199,7 +5553,7 @@ dependencies = [ "objc2-foundation 0.2.2", "objc2-quartz-core 0.2.2", "raw-window-handle", - "redox_syscall 0.5.12", + "redox_syscall 0.5.18", "wasm-bindgen", "web-sys", "windows-sys 0.59.0", @@ -5265,9 +5619,9 @@ dependencies = [ [[package]] name = "stable_deref_trait" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "static_assertions" @@ -5282,7 +5636,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f" dependencies = [ "new_debug_unreachable", - "parking_lot 0.12.3", + "parking_lot 0.12.5", "phf_shared 0.11.3", "precomputed-hash", "serde", @@ -5336,9 +5690,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.101" +version = "2.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" dependencies = [ "proc-macro2", "quote", @@ -5368,7 +5722,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.106", ] [[package]] @@ -5391,7 +5745,21 @@ dependencies = [ "ntapi", "objc2-core-foundation", "objc2-io-kit", - "windows", + "windows 0.61.3", +] + +[[package]] +name = "sysinfo" +version = "0.37.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16607d5caffd1c07ce073528f9ed972d88db15dd44023fa57142963be3feb11f" +dependencies = [ + "libc", + "memchr", + "ntapi", + "objc2-core-foundation", + "objc2-io-kit", + "windows 0.61.3", ] [[package]] @@ -5402,7 +5770,18 @@ checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ "bitflags 1.3.2", "core-foundation 0.9.4", - "system-configuration-sys", + "system-configuration-sys 0.5.0", +] + +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags 2.9.4", + "core-foundation 0.9.4", + "system-configuration-sys 0.6.0", ] [[package]] @@ -5415,6 +5794,16 @@ dependencies = [ "libc", ] +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "system-deps" version = "6.2.2" @@ -5424,17 +5813,18 @@ dependencies = [ "cfg-expr", "heck 0.5.0", "pkg-config", - "toml", + "toml 0.8.2", "version-compare", ] [[package]] name = "tao" -version = "0.34.0" +version = "0.34.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49c380ca75a231b87b6c9dd86948f035012e7171d1a7c40a9c2890489a7ffd8a" +checksum = "959469667dbcea91e5485fc48ba7dd6023face91bb0f1a14681a70f99847c3f7" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.4", + "block2 0.6.2", "core-foundation 0.10.1", "core-graphics", "crossbeam-channel", @@ -5451,18 +5841,18 @@ dependencies = [ "ndk", "ndk-context", "ndk-sys", - "objc2 0.6.1", + "objc2 0.6.3", "objc2-app-kit", - "objc2-foundation 0.3.1", + "objc2-foundation 0.3.2", "once_cell", - "parking_lot 0.12.3", + "parking_lot 0.12.5", "raw-window-handle", "scopeguard", "tao-macros", "unicode-segmentation", "url", - "windows", - "windows-core", + "windows 0.61.3", + "windows-core 0.61.2", "windows-version", "x11-dl", ] @@ -5475,7 +5865,7 @@ checksum = "f4e16beb8b2ac17db28eab8bca40e62dbfbb34c0fcdc6d9826b11b7b5d047dfd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.106", ] [[package]] @@ -5506,12 +5896,13 @@ dependencies = [ [[package]] name = "tauri" -version = "2.7.0" +version = "2.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "352a4bc7bf6c25f5624227e3641adf475a6535707451b09bb83271df8b7a6ac7" +checksum = "d4d1d3b3dc4c101ac989fd7db77e045cc6d91a25349cd410455cb5c57d510c1c" dependencies = [ "anyhow", "bytes", + "cookie", "dirs 6.0.0", "dunce", "embed_plist", @@ -5526,14 +5917,15 @@ dependencies = [ "log", "mime", "muda", - "objc2 0.6.1", + "objc2 0.6.3", "objc2-app-kit", - "objc2-foundation 0.3.1", + "objc2-foundation 0.3.2", "objc2-ui-kit", + "objc2-web-kit", "percent-encoding", "plist", "raw-window-handle", - "reqwest 0.12.22", + "reqwest 0.12.23", "serde", "serde_json", "serde_repr", @@ -5544,7 +5936,7 @@ dependencies = [ "tauri-runtime", "tauri-runtime-wry", "tauri-utils", - "thiserror 2.0.12", + "thiserror 2.0.17", "tokio", "tray-icon", "url", @@ -5552,14 +5944,14 @@ dependencies = [ "webkit2gtk", "webview2-com", "window-vibrancy", - "windows", + "windows 0.61.3", ] [[package]] name = "tauri-build" -version = "2.3.1" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "182d688496c06bf08ea896459bf483eb29cdff35c1c4c115fb14053514303064" +checksum = "9c432ccc9ff661803dab74c6cd78de11026a578a9307610bbc39d3c55be7943f" dependencies = [ "anyhow", "cargo_toml", @@ -5567,21 +5959,21 @@ dependencies = [ "glob", "heck 0.5.0", "json-patch", - "schemars", + "schemars 0.8.22", "semver", "serde", "serde_json", "tauri-utils", "tauri-winres", - "toml", + "toml 0.9.8", "walkdir", ] [[package]] name = "tauri-codegen" -version = "2.3.1" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b54a99a6cd8e01abcfa61508177e6096a4fe2681efecee9214e962f2f073ae4a" +checksum = "1ab3a62cf2e6253936a8b267c2e95839674e7439f104fa96ad0025e149d54d8a" dependencies = [ "base64 0.22.1", "brotli", @@ -5595,9 +5987,9 @@ dependencies = [ "serde", "serde_json", "sha2 0.10.9", - "syn 2.0.101", + "syn 2.0.106", "tauri-utils", - "thiserror 2.0.12", + "thiserror 2.0.17", "time", "url", "uuid", @@ -5606,74 +5998,75 @@ dependencies = [ [[package]] name = "tauri-macros" -version = "2.3.2" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7945b14dc45e23532f2ded6e120170bbdd4af5ceaa45784a6b33d250fbce3f9e" +checksum = "4368ea8094e7045217edb690f493b55b30caf9f3e61f79b4c24b6db91f07995e" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.106", "tauri-codegen", "tauri-utils", ] [[package]] name = "tauri-plugin" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d9a0bd00bf1930ad1a604d08b0eb6b2a9c1822686d65d7f4731a7723b8901d3" +checksum = "9946a3cede302eac0c6eb6c6070ac47b1768e326092d32efbb91f21ed58d978f" dependencies = [ "anyhow", "glob", "plist", - "schemars", + "schemars 0.8.22", "serde", "serde_json", "tauri-utils", - "toml", + "toml 0.9.8", "walkdir", ] [[package]] name = "tauri-plugin-autostart" -version = "2.3.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c58593aafcb03892dbf9998b35a96ead3b8e597435c7af46aff1654d076d5d03" +checksum = "062cdcd483d5e3148c9a64dabf8c574e239e2aa1193cf208d95cf89a676f87a5" dependencies = [ "auto-launch", "serde", "serde_json", "tauri", "tauri-plugin", - "thiserror 2.0.12", + "thiserror 2.0.17", ] [[package]] name = "tauri-plugin-deep-link" -version = "2.3.0" +version = "2.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4976ac728ebc0487515aa956cfdf200abcc52b784e441493fc544bc6ce369c8" +checksum = "cd67112fb1131834c2a7398ffcba520dbbf62c17de3b10329acd1a3554b1a9bb" dependencies = [ "dunce", + "plist", "rust-ini", "serde", "serde_json", "tauri", "tauri-plugin", "tauri-utils", - "thiserror 2.0.12", + "thiserror 2.0.17", "tracing", "url", "windows-registry", - "windows-result", + "windows-result 0.3.4", ] [[package]] name = "tauri-plugin-dialog" -version = "2.3.2" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e5858cc7b455a73ab4ea2ebc08b5be33682c00ff1bf4cad5537d4fb62499d9" +checksum = "0beee42a4002bc695550599b011728d9dfabf82f767f134754ed6655e434824e" dependencies = [ "log", "raw-window-handle", @@ -5683,59 +6076,59 @@ dependencies = [ "tauri", "tauri-plugin", "tauri-plugin-fs", - "thiserror 2.0.12", + "thiserror 2.0.17", "url", ] [[package]] name = "tauri-plugin-fs" -version = "2.4.1" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c6ef84ee2f2094ce093e55106d90d763ba343fad57566992962e8f76d113f99" +checksum = "315784ec4be45e90a987687bae7235e6be3d6e9e350d2b75c16b8a4bf22c1db7" dependencies = [ "anyhow", "dunce", "glob", "percent-encoding", - "schemars", + "schemars 0.8.22", "serde", "serde_json", "serde_repr", "tauri", "tauri-plugin", "tauri-utils", - "thiserror 2.0.12", - "toml", + "thiserror 2.0.17", + "toml 0.9.8", "url", ] [[package]] name = "tauri-plugin-opener" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecee219f11cdac713ab32959db5d0cceec4810ba4f4458da992292ecf9660321" +checksum = "786156aa8e89e03d271fbd3fe642207da8e65f3c961baa9e2930f332bf80a1f5" dependencies = [ "dunce", "glob", "objc2-app-kit", - "objc2-foundation 0.3.1", + "objc2-foundation 0.3.2", "open", - "schemars", + "schemars 0.8.22", "serde", "serde_json", "tauri", "tauri-plugin", - "thiserror 2.0.12", + "thiserror 2.0.17", "url", - "windows", + "windows 0.61.3", "zbus", ] [[package]] name = "tauri-plugin-os" -version = "2.2.1" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "424f19432397850c2ddd42aa58078630c15287bbce3866eb1d90e7dbee680637" +checksum = "77a1c77ebf6f20417ab2a74e8c310820ba52151406d0c80fbcea7df232e3f6ba" dependencies = [ "gethostname", "log", @@ -5746,81 +6139,84 @@ dependencies = [ "sys-locale", "tauri", "tauri-plugin", - "thiserror 2.0.12", + "thiserror 2.0.17", ] [[package]] name = "tauri-plugin-shell" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b9ffadec5c3523f11e8273465cacb3d86ea7652a28e6e2a2e9b5c182f791d25" +checksum = "54777d0c0d8add34eea3ced84378619ef5b97996bd967d3038c668feefd21071" dependencies = [ "encoding_rs", "log", "open", "os_pipe", "regex", - "schemars", + "schemars 0.8.22", "serde", "serde_json", "shared_child", "tauri", "tauri-plugin", - "thiserror 2.0.12", + "thiserror 2.0.17", "tokio", ] [[package]] name = "tauri-plugin-single-instance" -version = "2.2.4" +version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97d0e07b40fb2eb13778e30778f5979347a2bf30e1b9d47f78ff7fe92d2e4b3d" +checksum = "fb9cac815bf11c4a80fb498666bcdad66d65b89e3ae24669e47806febb76389c" dependencies = [ "serde", "serde_json", "tauri", "tauri-plugin-deep-link", - "thiserror 2.0.12", + "thiserror 2.0.17", "tracing", - "windows-sys 0.59.0", + "windows-sys 0.60.2", "zbus", ] [[package]] name = "tauri-runtime" -version = "2.7.1" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b1cc885be806ea15ff7b0eb47098a7b16323d9228876afda329e34e2d6c4676" +checksum = "d4cfc9ad45b487d3fded5a4731a567872a4812e9552e3964161b08edabf93846" dependencies = [ "cookie", "dpi", "gtk", "http 1.3.1", "jni", - "objc2 0.6.1", + "objc2 0.6.3", "objc2-ui-kit", + "objc2-web-kit", "raw-window-handle", "serde", "serde_json", "tauri-utils", - "thiserror 2.0.12", + "thiserror 2.0.17", "url", - "windows", + "webkit2gtk", + "webview2-com", + "windows 0.61.3", ] [[package]] name = "tauri-runtime-wry" -version = "2.7.2" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe653a2fbbef19fe898efc774bc52c8742576342a33d3d028c189b57eb1d2439" +checksum = "c1fe9d48bd122ff002064e88cfcd7027090d789c4302714e68fcccba0f4b7807" dependencies = [ "gtk", "http 1.3.1", "jni", "log", - "objc2 0.6.1", + "objc2 0.6.3", "objc2-app-kit", - "objc2-foundation 0.3.1", + "objc2-foundation 0.3.2", "once_cell", "percent-encoding", "raw-window-handle", @@ -5831,15 +6227,15 @@ dependencies = [ "url", "webkit2gtk", "webview2-com", - "windows", + "windows 0.61.3", "wry", ] [[package]] name = "tauri-utils" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9330c15cabfe1d9f213478c9e8ec2b0c76dab26bb6f314b8ad1c8a568c1d186e" +checksum = "41a3852fdf9a4f8fbeaa63dc3e9a85284dd6ef7200751f0bd66ceee30c93f212" dependencies = [ "anyhow", "brotli", @@ -5858,15 +6254,15 @@ dependencies = [ "proc-macro2", "quote", "regex", - "schemars", + "schemars 0.8.22", "semver", "serde", "serde-untagged", "serde_json", "serde_with", "swift-rs", - "thiserror 2.0.12", - "toml", + "thiserror 2.0.17", + "toml 0.9.8", "url", "urlpattern", "uuid", @@ -5875,26 +6271,25 @@ dependencies = [ [[package]] name = "tauri-winres" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8d321dbc6f998d825ab3f0d62673e810c861aac2d0de2cc2c395328f1d113b4" +checksum = "fd21509dd1fa9bd355dc29894a6ff10635880732396aa38c0066c1e6c1ab8074" dependencies = [ "embed-resource", - "indexmap 2.9.0", - "toml", + "toml 0.9.8", ] [[package]] name = "tempfile" -version = "3.20.0" +version = "3.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" +checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" dependencies = [ "fastrand", "getrandom 0.3.3", "once_cell", - "rustix 1.0.7", - "windows-sys 0.59.0", + "rustix 1.1.2", + "windows-sys 0.61.2", ] [[package]] @@ -5919,11 +6314,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.12" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" dependencies = [ - "thiserror-impl 2.0.12", + "thiserror-impl 2.0.17", ] [[package]] @@ -5934,28 +6329,28 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.106", ] [[package]] name = "thiserror-impl" -version = "2.0.12" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.106", ] [[package]] name = "thread-id" -version = "4.2.2" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfe8f25bbdd100db7e1d34acf7fd2dc59c4bf8f7483f505eaa7d4f12f76cc0ea" +checksum = "99043e46c5a15af379c06add30d9c93a6c0e8849de00d244c4a2c417da128d80" dependencies = [ "libc", - "winapi", + "windows-sys 0.59.0", ] [[package]] @@ -5972,11 +6367,11 @@ dependencies = [ [[package]] name = "time" -version = "0.3.41" +version = "0.3.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" +checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" dependencies = [ - "deranged", + "deranged 0.5.4", "itoa", "num-conv", "powerfmt", @@ -5987,15 +6382,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.4" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" +checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" [[package]] name = "time-macros" -version = "0.2.22" +version = "0.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" +checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" dependencies = [ "num-conv", "time-core", @@ -6022,9 +6417,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" +checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" dependencies = [ "tinyvec_macros", ] @@ -6037,20 +6432,22 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.45.1" +version = "1.47.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779" +checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" dependencies = [ "backtrace", "bytes", + "io-uring", "libc", "mio", "pin-project-lite", "signal-hook-registry", - "socket2", + "slab", + "socket2 0.6.0", "tokio-macros", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -6061,7 +6458,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.106", ] [[package]] @@ -6076,9 +6473,9 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.26.2" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ "rustls", "tokio", @@ -6100,66 +6497,99 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.22" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ae329d1f08c4d17a59bed7ff5b5a769d062e64a62d34a3261b219e62cd5aae" +checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" dependencies = [ "serde", - "serde_spanned", - "toml_datetime", - "toml_edit 0.22.26", + "serde_spanned 0.6.9", + "toml_datetime 0.6.3", + "toml_edit 0.20.2", +] + +[[package]] +name = "toml" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dc8b1fb61449e27716ec0e1bdf0f6b8f3e8f6b05391e8497b8b6d7804ea6d8" +dependencies = [ + "indexmap 2.11.4", + "serde_core", + "serde_spanned 1.0.3", + "toml_datetime 0.7.3", + "toml_parser", + "toml_writer", + "winnow 0.7.13", ] [[package]] name = "toml_datetime" -version = "0.6.9" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3da5db5a963e24bc68be8b17b6fa82814bb22ee8660f192bb182771d498f09a3" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" dependencies = [ "serde", ] +[[package]] +name = "toml_datetime" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" +dependencies = [ + "serde_core", +] + [[package]] name = "toml_edit" version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.9.0", - "toml_datetime", + "indexmap 2.11.4", + "toml_datetime 0.6.3", "winnow 0.5.40", ] [[package]] name = "toml_edit" -version = "0.20.7" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" +checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" dependencies = [ - "indexmap 2.9.0", - "toml_datetime", - "winnow 0.5.40", -] - -[[package]] -name = "toml_edit" -version = "0.22.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "310068873db2c5b3e7659d2cc35d21855dbafa50d1ce336397c666e3cb08137e" -dependencies = [ - "indexmap 2.9.0", + "indexmap 2.11.4", "serde", - "serde_spanned", - "toml_datetime", - "toml_write", - "winnow 0.7.10", + "serde_spanned 0.6.9", + "toml_datetime 0.6.3", + "winnow 0.5.40", ] [[package]] -name = "toml_write" -version = "0.1.1" +name = "toml_edit" +version = "0.23.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfb942dfe1d8e29a7ee7fcbde5bd2b9a25fb89aa70caea2eba3bee836ff41076" +checksum = "6485ef6d0d9b5d0ec17244ff7eb05310113c3f316f2d14200d4de56b3cb98f8d" +dependencies = [ + "indexmap 2.11.4", + "toml_datetime 0.7.3", + "toml_parser", + "winnow 0.7.13", +] + +[[package]] +name = "toml_parser" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" +dependencies = [ + "winnow 0.7.13", +] + +[[package]] +name = "toml_writer" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df8b2b54733674ad286d16267dcfc7a71ed5c776e4ac7aa3c3e2561f7c637bf2" [[package]] name = "tower" @@ -6182,7 +6612,7 @@ version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.4", "bytes", "futures-util", "http 1.3.1", @@ -6219,52 +6649,46 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.28" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.106", ] [[package]] name = "tracing-core" -version = "0.1.33" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" dependencies = [ "once_cell", ] [[package]] name = "tray-icon" -version = "0.21.0" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2da75ec677957aa21f6e0b361df0daab972f13a5bee3606de0638fd4ee1c666a" +checksum = "a0d92153331e7d02ec09137538996a7786fe679c629c279e82a6be762b7e6fe2" dependencies = [ "crossbeam-channel", "dirs 6.0.0", "libappindicator", "muda", - "objc2 0.6.1", + "objc2 0.6.3", "objc2-app-kit", "objc2-core-foundation", "objc2-core-graphics", - "objc2-foundation 0.3.1", + "objc2-foundation 0.3.2", "once_cell", "png", "serde", - "thiserror 2.0.12", + "thiserror 2.0.17", "windows-sys 0.59.0", ] -[[package]] -name = "trim-in-place" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "343e926fc669bc8cde4fa3129ab681c63671bae288b1f1081ceee6d9d37904fc" - [[package]] name = "try-lock" version = "0.2.5" @@ -6273,18 +6697,18 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "tungstenite" -version = "0.26.2" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4793cb5e56680ecbb1d843515b23b6de9a75eb04b66643e256a396d43be33c13" +checksum = "eadc29d668c91fcc564941132e17b28a7ceb2f3ebf0b9dae3e03fd7a6748eb0d" dependencies = [ "bytes", "data-encoding", "http 1.3.1", "httparse", "log", - "rand 0.9.1", + "rand 0.9.2", "sha1", - "thiserror 2.0.12", + "thiserror 2.0.17", "utf-8", ] @@ -6305,9 +6729,9 @@ dependencies = [ [[package]] name = "typenum" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] name = "uds_windows" @@ -6375,9 +6799,9 @@ checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" [[package]] name = "unicode-ident" -version = "1.0.18" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" [[package]] name = "unicode-segmentation" @@ -6391,6 +6815,12 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + [[package]] name = "unsafe-any-ors" version = "1.0.0" @@ -6414,9 +6844,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.4" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" dependencies = [ "form_urlencoded", "idna", @@ -6454,15 +6884,23 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" +[[package]] +name = "utils" +version = "0.1.0" +dependencies = [ + "log", + "webbrowser", +] + [[package]] name = "uuid" -version = "1.17.0" +version = "1.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" +checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" dependencies = [ "getrandom 0.3.3", "js-sys", - "rand 0.9.1", + "rand 0.9.2", "serde", "uuid-macro-internal", "wasm-bindgen", @@ -6470,13 +6908,13 @@ dependencies = [ [[package]] name = "uuid-macro-internal" -version = "1.17.0" +version = "1.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b682e8c381995ea03130e381928e0e005b7c9eb483c6c8682f50e07b33c2b7" +checksum = "d9384a660318abfbd7f8932c34d67e4d1ec511095f95972ddc01e19d7ba8413f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.106", ] [[package]] @@ -6550,17 +6988,26 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasi" -version = "0.14.2+wasi-0.2.4" +version = "0.14.7+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c" dependencies = [ - "wit-bindgen-rt", + "wasip2", +] + +[[package]] +name = "wasip2" +version = "1.0.1+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +dependencies = [ + "wit-bindgen", ] [[package]] @@ -6571,35 +7018,36 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.100" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d" dependencies = [ "cfg-if", "once_cell", "rustversion", "wasm-bindgen-macro", + "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.100" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19" dependencies = [ "bumpalo", "log", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.106", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.50" +version = "0.4.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +checksum = "7e038d41e478cc73bae0ff9b36c60cff1c98b8f38f8d7e8061e79ee63608ac5c" dependencies = [ "cfg-if", "js-sys", @@ -6610,9 +7058,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.100" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -6620,22 +7068,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.100" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.106", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.100" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1" dependencies = [ "unicode-ident", ] @@ -6654,10 +7102,70 @@ dependencies = [ ] [[package]] -name = "web-sys" -version = "0.3.77" +name = "wayland-backend" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +checksum = "673a33c33048a5ade91a6b139580fa174e19fb0d23f396dca9fa15f2e1e49b35" +dependencies = [ + "cc", + "downcast-rs", + "rustix 1.1.2", + "scoped-tls", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-client" +version = "0.31.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c66a47e840dc20793f2264eb4b3e4ecb4b75d91c0dd4af04b456128e0bdd449d" +dependencies = [ + "bitflags 2.9.4", + "rustix 1.1.2", + "wayland-backend", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols" +version = "0.32.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efa790ed75fbfd71283bd2521a1cfdc022aabcc28bdcff00851f9e4ae88d9901" +dependencies = [ + "bitflags 2.9.4", + "wayland-backend", + "wayland-client", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.31.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54cb1e9dc49da91950bdfd8b848c49330536d9d1fb03d4bfec8cae50caa50ae3" +dependencies = [ + "proc-macro2", + "quick-xml 0.37.5", + "quote", +] + +[[package]] +name = "wayland-sys" +version = "0.31.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34949b42822155826b41db8e5d0c1be3a2bd296c747577a43a3e6daefc296142" +dependencies = [ + "dlib", + "log", + "pkg-config", +] + +[[package]] +name = "web-sys" +version = "0.3.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9367c417a924a74cae129e6a2ae3b47fabb1f8995595ab474029da749a8be120" dependencies = [ "js-sys", "wasm-bindgen", @@ -6675,17 +7183,16 @@ dependencies = [ [[package]] name = "webbrowser" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5df295f8451142f1856b1bd86a606dfe9587d439bc036e319c827700dbd555e" +checksum = "aaf4f3c0ba838e82b4e5ccc4157003fb8c324ee24c058470ffb82820becbde98" dependencies = [ "core-foundation 0.10.1", - "home", "jni", "log", "ndk-context", - "objc2 0.6.1", - "objc2-foundation 0.3.1", + "objc2 0.6.3", + "objc2-foundation 0.3.2", "url", "web-sys", ] @@ -6746,9 +7253,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "1.0.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2853738d1cc4f2da3a225c18ec6c3721abb31961096e9dbf5ab35fa88b19cfdb" +checksum = "32b130c0d2d49f8b6889abc456e795e82525204f27c42cf767cf0d7734e089b8" dependencies = [ "rustls-pki-types", ] @@ -6761,8 +7268,8 @@ checksum = "d4ba622a989277ef3886dd5afb3e280e3dd6d974b766118950a08f8f678ad6a4" dependencies = [ "webview2-com-macros", "webview2-com-sys", - "windows", - "windows-core", + "windows 0.61.3", + "windows-core 0.61.2", "windows-implement", "windows-interface", ] @@ -6775,7 +7282,7 @@ checksum = "1d228f15bba3b9d56dde8bddbee66fa24545bd17b48d5128ccf4a8742b18e431" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.106", ] [[package]] @@ -6784,18 +7291,18 @@ version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "36695906a1b53a3bf5c4289621efedac12b73eeb0b89e7e1a89b517302d5d75c" dependencies = [ - "thiserror 2.0.12", - "windows", - "windows-core", + "thiserror 2.0.17", + "windows 0.61.3", + "windows-core 0.61.2", ] [[package]] name = "whoami" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6994d13118ab492c3c80c1f81928718159254c53c472bf9ce36f8dae4add02a7" +checksum = "5d4a4db5077702ca3015d3d02d74974948aba2ad9e12ab7df718ee64ccd7e97d" dependencies = [ - "redox_syscall 0.5.12", + "libredox", "wasite", "web-sys", ] @@ -6818,11 +7325,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.9" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -6837,10 +7344,10 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9bec5a31f3f9362f2258fd0e9c9dd61a9ca432e7306cc78c444258f0dce9a9c" dependencies = [ - "objc2 0.6.1", + "objc2 0.6.3", "objc2-app-kit", "objc2-core-foundation", - "objc2-foundation 0.3.1", + "objc2-foundation 0.3.2", "raw-window-handle", "windows-sys 0.59.0", "windows-version", @@ -6848,15 +7355,27 @@ dependencies = [ [[package]] name = "windows" -version = "0.61.1" +version = "0.61.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5ee8f3d025738cb02bad7868bbb5f8a6327501e870bf51f1b455b0a2454a419" +checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" dependencies = [ - "windows-collections", - "windows-core", - "windows-future", - "windows-link", - "windows-numerics", + "windows-collections 0.2.0", + "windows-core 0.61.2", + "windows-future 0.2.1", + "windows-link 0.1.3", + "windows-numerics 0.2.0", +] + +[[package]] +name = "windows" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" +dependencies = [ + "windows-collections 0.3.2", + "windows-core 0.62.2", + "windows-future 0.3.2", + "windows-numerics 0.3.1", ] [[package]] @@ -6865,7 +7384,16 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" dependencies = [ - "windows-core", + "windows-core 0.61.2", +] + +[[package]] +name = "windows-collections" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" +dependencies = [ + "windows-core 0.62.2", ] [[package]] @@ -6876,9 +7404,22 @@ checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ "windows-implement", "windows-interface", - "windows-link", - "windows-result", - "windows-strings", + "windows-link 0.1.3", + "windows-result 0.3.4", + "windows-strings 0.4.2", +] + +[[package]] +name = "windows-core" +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", ] [[package]] @@ -6887,38 +7428,55 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" dependencies = [ - "windows-core", - "windows-link", - "windows-threading", + "windows-core 0.61.2", + "windows-link 0.1.3", + "windows-threading 0.1.0", +] + +[[package]] +name = "windows-future" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" +dependencies = [ + "windows-core 0.62.2", + "windows-link 0.2.1", + "windows-threading 0.2.1", ] [[package]] name = "windows-implement" -version = "0.60.0" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.106", ] [[package]] name = "windows-interface" -version = "0.59.1" +version = "0.59.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.106", ] [[package]] name = "windows-link" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" +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" @@ -6926,19 +7484,29 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" dependencies = [ - "windows-core", - "windows-link", + "windows-core 0.61.2", + "windows-link 0.1.3", +] + +[[package]] +name = "windows-numerics" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" +dependencies = [ + "windows-core 0.62.2", + "windows-link 0.2.1", ] [[package]] name = "windows-registry" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3bab093bdd303a1240bb99b8aba8ea8a69ee19d34c9e2ef9594e708a4878820" +checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e" dependencies = [ - "windows-link", - "windows-result", - "windows-strings", + "windows-link 0.1.3", + "windows-result 0.3.4", + "windows-strings 0.4.2", ] [[package]] @@ -6947,7 +7515,16 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" dependencies = [ - "windows-link", + "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]] @@ -6956,7 +7533,16 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" dependencies = [ - "windows-link", + "windows-link 0.1.3", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link 0.2.1", ] [[package]] @@ -6995,6 +7581,24 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link 0.2.1", +] + [[package]] name = "windows-targets" version = "0.42.2" @@ -7034,29 +7638,55 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", + "windows_i686_gnullvm 0.52.6", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link 0.2.1", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "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", + "windows-link 0.1.3", +] + +[[package]] +name = "windows-threading" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" +dependencies = [ + "windows-link 0.2.1", ] [[package]] name = "windows-version" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e04a5c6627e310a23ad2358483286c7df260c964eb2d003d8efd6d0f4e79265c" +checksum = "e4060a1da109b9d0326b7262c8e12c84df67cc0dbc9e33cf49e01ccc2eb63631" dependencies = [ - "windows-link", + "windows-link 0.2.1", ] [[package]] @@ -7077,6 +7707,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + [[package]] name = "windows_aarch64_msvc" version = "0.42.2" @@ -7095,6 +7731,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + [[package]] name = "windows_i686_gnu" version = "0.42.2" @@ -7113,12 +7755,24 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + [[package]] name = "windows_i686_msvc" version = "0.42.2" @@ -7137,6 +7791,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + [[package]] name = "windows_x86_64_gnu" version = "0.42.2" @@ -7155,6 +7815,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" @@ -7173,6 +7839,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + [[package]] name = "windows_x86_64_msvc" version = "0.42.2" @@ -7191,6 +7863,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + [[package]] name = "winnow" version = "0.5.40" @@ -7202,9 +7880,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.7.10" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06928c8748d81b05c9be96aad92e1b6ff01833332f281e8cfca3be4b35fc9ec" +checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" dependencies = [ "memchr", ] @@ -7230,22 +7908,19 @@ dependencies = [ [[package]] name = "winreg" -version = "0.52.0" +version = "0.55.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" +checksum = "cb5a765337c50e9ec252c2069be9bf91c7df47afb103b642ba3a53bf8101be97" dependencies = [ "cfg-if", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] -name = "wit-bindgen-rt" -version = "0.39.0" +name = "wit-bindgen" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" -dependencies = [ - "bitflags 2.9.1", -] +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" [[package]] name = "writeable" @@ -7255,14 +7930,15 @@ checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" [[package]] name = "wry" -version = "0.52.1" +version = "0.53.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12a714d9ba7075aae04a6e50229d6109e3d584774b99a6a8c60de1698ca111b9" +checksum = "6d78ec082b80fa088569a970d043bb3050abaabf4454101d44514ee8d9a8c9f6" dependencies = [ "base64 0.22.1", - "block2 0.6.1", + "block2 0.6.2", "cookie", "crossbeam-channel", + "dirs 6.0.0", "dpi", "dunce", "gdkx11", @@ -7274,10 +7950,10 @@ dependencies = [ "kuchikiki", "libc", "ndk", - "objc2 0.6.1", + "objc2 0.6.3", "objc2-app-kit", "objc2-core-foundation", - "objc2-foundation 0.3.1", + "objc2-foundation 0.3.2", "objc2-ui-kit", "objc2-web-kit", "once_cell", @@ -7286,13 +7962,13 @@ dependencies = [ "sha2 0.10.9", "soup3", "tao-macros", - "thiserror 2.0.12", + "thiserror 2.0.17", "url", "webkit2gtk", "webkit2gtk-sys", "webview2-com", - "windows", - "windows-core", + "windows 0.61.3", + "windows-core 0.61.2", "windows-version", "x11-dl", ] @@ -7350,18 +8026,18 @@ dependencies = [ "oid-registry 0.8.1", "ring", "rusticata-macros", - "thiserror 2.0.12", + "thiserror 2.0.17", "time", ] [[package]] name = "xattr" -version = "1.5.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d65cbf2f12c15564212d48f4e3dfb87923d25d611f2aed18f4cb23f0413d89e" +checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156" dependencies = [ "libc", - "rustix 1.0.7", + "rustix 1.1.2", ] [[package]] @@ -7399,15 +8075,15 @@ checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.106", "synstructure", ] [[package]] name = "zbus" -version = "5.7.1" +version = "5.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3a7c7cee313d044fca3f48fa782cb750c79e4ca76ba7bc7718cd4024cdf6f68" +checksum = "2d07e46d035fb8e375b2ce63ba4e4ff90a7f73cf2ffb0138b29e1158d2eaadf7" dependencies = [ "async-broadcast", "async-executor", @@ -7419,7 +8095,7 @@ dependencies = [ "async-trait", "blocking", "enumflags2", - "event-listener 5.4.0", + "event-listener 5.4.1", "futures-core", "futures-lite", "hex 0.4.3", @@ -7430,8 +8106,8 @@ dependencies = [ "tokio", "tracing", "uds_windows", - "windows-sys 0.59.0", - "winnow 0.7.10", + "windows-sys 0.60.2", + "winnow 0.7.13", "zbus_macros", "zbus_names", "zvariant", @@ -7439,14 +8115,14 @@ dependencies = [ [[package]] name = "zbus_macros" -version = "5.7.1" +version = "5.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17e7e5eec1550f747e71a058df81a9a83813ba0f6a95f39c4e218bdc7ba366a" +checksum = "57e797a9c847ed3ccc5b6254e8bcce056494b375b511b3d6edcec0aeb4defaca" dependencies = [ - "proc-macro-crate 3.3.0", + "proc-macro-crate 3.4.0", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.106", "zbus_names", "zvariant", "zvariant_utils", @@ -7460,28 +8136,28 @@ checksum = "7be68e64bf6ce8db94f63e72f0c7eb9a60d733f7e0499e628dfab0f84d6bcb97" dependencies = [ "serde", "static_assertions", - "winnow 0.7.10", + "winnow 0.7.13", "zvariant", ] [[package]] name = "zerocopy" -version = "0.8.25" +version = "0.8.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb" +checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.25" +version = "0.8.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" +checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.106", ] [[package]] @@ -7501,15 +8177,15 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.106", "synstructure", ] [[package]] name = "zeroize" -version = "1.8.1" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" [[package]] name = "zerotrie" @@ -7524,9 +8200,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.2" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" +checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" dependencies = [ "yoke", "zerofrom", @@ -7541,7 +8217,7 @@ checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.106", ] [[package]] @@ -7564,9 +8240,9 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.15+zstd.1.5.7" +version = "2.0.16+zstd.1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237" +checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748" dependencies = [ "cc", "pkg-config", @@ -7574,42 +8250,41 @@ dependencies = [ [[package]] name = "zvariant" -version = "5.5.3" +version = "5.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d30786f75e393ee63a21de4f9074d4c038d52c5b1bb4471f955db249f9dffb1" +checksum = "999dd3be73c52b1fccd109a4a81e4fcd20fab1d3599c8121b38d04e1419498db" dependencies = [ "endi", "enumflags2", "serde", "url", - "winnow 0.7.10", + "winnow 0.7.13", "zvariant_derive", "zvariant_utils", ] [[package]] name = "zvariant_derive" -version = "5.5.3" +version = "5.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75fda702cd42d735ccd48117b1630432219c0e9616bf6cb0f8350844ee4d9580" +checksum = "6643fd0b26a46d226bd90d3f07c1b5321fe9bb7f04673cb37ac6d6883885b68e" dependencies = [ - "proc-macro-crate 3.3.0", + "proc-macro-crate 3.4.0", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.106", "zvariant_utils", ] [[package]] name = "zvariant_utils" -version = "3.2.0" +version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e16edfee43e5d7b553b77872d99bc36afdda75c223ca7ad5e3fbecd82ca5fc34" +checksum = "c6949d142f89f6916deca2232cf26a8afacf2b9fdc35ce766105e104478be599" dependencies = [ "proc-macro2", "quote", "serde", - "static_assertions", - "syn 2.0.101", - "winnow 0.7.10", + "syn 2.0.106", + "winnow 0.7.13", ] diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 55f017c..4001a30 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -78,6 +78,16 @@ futures-core = "0.3.31" bytes = "1.10.1" # tailscale = { path = "./tailscale" } + +# Workspaces +client = { version = "0.1.0", path = "./client" } +database = { path = "./database" } +process = { path = "./process" } +remote = { version = "0.1.0", path = "./remote" } +utils = { path = "./utils" } +games = { version = "0.1.0", path = "./games" } +download_manager = { version = "0.1.0", path = "./download_manager" } + [dependencies.dynfmt] version = "0.1.5" features = ["curly"] @@ -127,3 +137,18 @@ features = ["derive", "rc"] lto = true codegen-units = 1 panic = 'abort' + + +[workspace] +members = [ + "client", + "database", + "process", + "remote", + "utils", + "cloud_saves", + "download_manager", + "games", +] + +resolver = "3" \ No newline at end of file diff --git a/src-tauri/client/Cargo.lock b/src-tauri/client/Cargo.lock new file mode 100644 index 0000000..84410eb --- /dev/null +++ b/src-tauri/client/Cargo.lock @@ -0,0 +1,4862 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "addr2line" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "alloc-no-stdlib" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" + +[[package]] +name = "alloc-stdlib" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" +dependencies = [ + "alloc-no-stdlib", +] + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anyhow" +version = "1.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" + +[[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 = "auto-launch" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f012b8cc0c850f34117ec8252a44418f2e34a2cf501de89e29b241ae5f79471" +dependencies = [ + "dirs 4.0.0", + "thiserror 1.0.69", + "winreg 0.10.1", +] + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "backtrace" +version = "0.3.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-link 0.2.1", +] + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" +dependencies = [ + "serde", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[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]] +name = "block2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" +dependencies = [ + "objc2 0.6.3", +] + +[[package]] +name = "brotli" +version = "8.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bd8b9603c7aa97359dbd97ecf258968c95f3adddd6db2f7e7a5bef101c84560" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", +] + +[[package]] +name = "brotli-decompressor" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "874bb8112abecc98cbd6d81ea4fa7e94fb9449648c93cc89aa40c81c24d7de03" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", +] + +[[package]] +name = "bumpalo" +version = "3.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" + +[[package]] +name = "bytemuck" +version = "1.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +dependencies = [ + "serde", +] + +[[package]] +name = "cairo-rs" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2" +dependencies = [ + "bitflags 2.9.4", + "cairo-sys-rs", + "glib", + "libc", + "once_cell", + "thiserror 1.0.69", +] + +[[package]] +name = "cairo-sys-rs" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "685c9fa8e590b8b3d678873528d83411db17242a73fccaed827770ea0fedda51" +dependencies = [ + "glib-sys", + "libc", + "system-deps", +] + +[[package]] +name = "camino" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "276a59bf2b2c967788139340c9f0c5b12d7fd6630315c15c217e559de85d2609" +dependencies = [ + "serde_core", +] + +[[package]] +name = "cargo-platform" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" +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.17", +] + +[[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.7", +] + +[[package]] +name = "cc" +version = "1.2.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d05d92f4b1fd76aad469d46cdd858ca761576082cd37df81416691e50199fb" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cesu8" +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.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "chrono" +version = "0.4.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" +dependencies = [ + "iana-time-zone", + "num-traits", + "serde", + "windows-link 0.2.1", +] + +[[package]] +name = "client" +version = "0.1.0" +dependencies = [ + "database", + "log", + "tauri", + "tauri-plugin-autostart", +] + +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[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.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "core-graphics" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa95a34622365fa5bbf40b20b75dba8dfa8c94c734aea8ac9a5ca38af14316f1" +dependencies = [ + "bitflags 2.9.4", + "core-foundation", + "core-graphics-types", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" +dependencies = [ + "bitflags 2.9.4", + "core-foundation", + "libc", +] + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "cssparser" +version = "0.29.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93d03419cb5950ccfd3daf3ff1c7a36ace64609a1a8746d493df1ca0afde0fa" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa", + "matches", + "phf 0.10.1", + "proc-macro2", + "quote", + "smallvec", + "syn 1.0.109", +] + +[[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.106", +] + +[[package]] +name = "ctor" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501" +dependencies = [ + "quote", + "syn 2.0.106", +] + +[[package]] +name = "darling" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.106", +] + +[[package]] +name = "darling_macro" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "database" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4851b30af1e6d2db292e4873b486fa2ad00a6fb6466da44f827e18bdac62f50" + +[[package]] +name = "deranged" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a41953f86f8a05768a6cda24def994fd2f424b04ec5c719cf89989779f199071" +dependencies = [ + "powerfmt", + "serde_core", +] + +[[package]] +name = "derive_more" +version = "0.99.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.106", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys 0.3.7", +] + +[[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", +] + +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users 0.4.6", + "winapi", +] + +[[package]] +name = "dirs-sys" +version = "0.5.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", +] + +[[package]] +name = "dispatch" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" + +[[package]] +name = "dispatch2" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" +dependencies = [ + "bitflags 2.9.4", + "objc2 0.6.3", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "dlopen2" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b54f373ccf864bf587a89e880fb7610f8d73f3045f13580948ccbcaff26febff" +dependencies = [ + "dlopen2_derive", + "libc", + "once_cell", + "winapi", +] + +[[package]] +name = "dlopen2_derive" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "788160fb30de9cdd857af31c6a2675904b16ece8fc2737b2c7127ba368c9d0f4" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "dpi" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" +dependencies = [ + "serde", +] + +[[package]] +name = "dtoa" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6add3b8cff394282be81f3fc1a0605db594ed69890078ca6e2cab1c408bcf04" + +[[package]] +name = "dtoa-short" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd1511a7b6a56299bd043a9c167a6d2bfb37bf84a6dfceaba651168adfb43c87" +dependencies = [ + "dtoa", +] + +[[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.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55a075fc573c64510038d7ee9abc7990635863992f83ebc52c8b433b8411a02e" +dependencies = [ + "cc", + "memchr", + "rustc_version", + "toml 0.9.7", + "vswhom", + "winreg 0.55.0", +] + +[[package]] +name = "embed_plist" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ef6b89e5b37196644d8796de5268852ff179b44e96276cf4290264843743bb7" + +[[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.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "259d404d09818dec19332e31d94558aeb442fea04c817006456c24b5460bbd4b" +dependencies = [ + "serde", + "serde_core", + "typeid", +] + +[[package]] +name = "fdeflate" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" +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", + "rustc_version", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0399f9d26e5191ce32c498bebd31e7a3ceabc2745f0ac54af3f335126c3f24b3" + +[[package]] +name = "flate2" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc5a4e564e38c699f2880d3fda590bedc2e69f3f84cd48b457bd892ce61d0aa9" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" +dependencies = [ + "mac", + "new_debug_unreachable", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi 0.14.7+wasi-0.2.4", +] + +[[package]] +name = "gimli" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" + +[[package]] +name = "gio" +version = "0.18.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fc8f532f87b79cbc51a79748f16a6828fb784be93145a322fa14d06d354c73" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "gio-sys", + "glib", + "libc", + "once_cell", + "pin-project-lite", + "smallvec", + "thiserror 1.0.69", +] + +[[package]] +name = "gio-sys" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37566df850baf5e4cb0dfb78af2e4b9898d817ed9263d1090a2df958c64737d2" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", + "winapi", +] + +[[package]] +name = "glib" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5" +dependencies = [ + "bitflags 2.9.4", + "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.106", +] + +[[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 = "gobject-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0850127b514d1c4a4654ead6dedadb18198999985908e6ffe4436f53c785ce44" +dependencies = [ + "glib-sys", + "libc", + "system-deps", +] + +[[package]] +name = "gtk" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd56fb197bfc42bd5d2751f4f017d44ff59fbb58140c6b49f9b3b2bdab08506a" +dependencies = [ + "atk", + "cairo-rs", + "field-offset", + "futures-channel", + "gdk", + "gdk-pixbuf", + "gio", + "glib", + "gtk-sys", + "gtk3-macros", + "libc", + "pango", + "pkg-config", +] + +[[package]] +name = "gtk-sys" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f29a1c21c59553eb7dd40e918be54dccd60c52b049b75119d5d96ce6b624414" +dependencies = [ + "atk-sys", + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gdk-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "pango-sys", + "system-deps", +] + +[[package]] +name = "gtk3-macros" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ff3c5b21f14f0736fed6dcfc0bfb4225ebf5725f3c0209edeec181e4d73e9d" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "html5ever" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b7410cae13cbc75623c98ac4cbfd1f0bedddf3227afc24f370cf0f50a44a11c" +dependencies = [ + "log", + "mac", + "markup5ever", + "match_token", +] + +[[package]] +name = "http" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +dependencies = [ + "bytes", + "fnv", + "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.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "pin-utils", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-util" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c6995591a8f1380fcb4ba966a252a4b29188d51d2b89e3a252f5305be65aea8" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http", + "http-body", + "hyper", + "ipnet", + "libc", + "percent-encoding", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core 0.62.2", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ico" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc50b891e4acf8fe0e71ef88ec43ad82ee07b3810ad09de10f1d01f072ed4b98" +dependencies = [ + "byteorder", + "png", +] + +[[package]] +name = "icu_collections" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" + +[[package]] +name = "icu_properties" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "potential_utf", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" + +[[package]] +name = "icu_provider" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +dependencies = [ + "displaydoc", + "icu_locale_core", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5" +dependencies = [ + "equivalent", + "hashbrown 0.16.0", + "serde", + "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 = "io-uring" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b" +dependencies = [ + "bitflags 2.9.4", + "cfg-if", + "libc", +] + +[[package]] +name = "ipnet" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" + +[[package]] +name = "iri-string" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys", + "log", + "thiserror 1.0.69", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "js-sys" +version = "0.3.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305" +dependencies = [ + "once_cell", + "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.9.4", + "serde", + "unicode-segmentation", +] + +[[package]] +name = "kuchikiki" +version = "0.8.8-speedreader" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02cb977175687f33fa4afa0c95c112b987ea1443e5a51c8f8ff27dc618270cc2" +dependencies = [ + "cssparser", + "html5ever", + "indexmap 2.11.4", + "selectors", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libappindicator" +version = "0.9.0" +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", +] + +[[package]] +name = "libc" +version = "0.2.176" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58f929b4d672ea937a23a1ab494143d968337a5f47e56d0815df1e0890ddf174" + +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + +[[package]] +name = "libredox" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" +dependencies = [ + "bitflags 2.9.4", + "libc", +] + +[[package]] +name = "litemap" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" + +[[package]] +name = "mac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" + +[[package]] +name = "markup5ever" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7a7213d12e1864c0f002f52c2923d4556935a43dec5e71355c2760e0f6e7a18" +dependencies = [ + "log", + "phf 0.11.3", + "phf_codegen 0.11.3", + "string_cache", + "string_cache_codegen", + "tendril", +] + +[[package]] +name = "match_token" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88a9689d8d44bf9964484516275f5cd4c9b59457a6940c1d5d0ecbb94510a36b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "matches" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "mio" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +dependencies = [ + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", + "windows-sys 0.59.0", +] + +[[package]] +name = "muda" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01c1738382f66ed56b3b9c8119e794a2e23148ac8ea214eda86622d4cb9d415a" +dependencies = [ + "crossbeam-channel", + "dpi", + "gtk", + "keyboard-types", + "objc2 0.6.3", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "once_cell", + "png", + "serde", + "thiserror 2.0.17", + "windows-sys 0.60.2", +] + +[[package]] +name = "ndk" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" +dependencies = [ + "bitflags 2.9.4", + "jni-sys", + "log", + "ndk-sys", + "num_enum", + "raw-window-handle", + "thiserror 1.0.69", +] + +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + +[[package]] +name = "ndk-sys" +version = "0.6.0+11769913" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" +dependencies = [ + "jni-sys", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "nodrop" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_enum" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a973b4e44ce6cad84ce69d797acf9a044532e4184c4f267913d1b546a0727b7a" +dependencies = [ + "num_enum_derive", + "rustversion", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d" +dependencies = [ + "proc-macro-crate 3.4.0", + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[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.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" +dependencies = [ + "objc-sys", + "objc2-encode", +] + +[[package]] +name = "objc2" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c2599ce0ec54857b29ce62166b0ed9b4f6f1a70ccc9a71165b6154caca8c05" +dependencies = [ + "objc2-encode", + "objc2-exception-helper", +] + +[[package]] +name = "objc2-app-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" +dependencies = [ + "bitflags 2.9.4", + "block2 0.6.2", + "libc", + "objc2 0.6.3", + "objc2-cloud-kit", + "objc2-core-data", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-core-image", + "objc2-core-text", + "objc2-core-video", + "objc2-foundation 0.3.2", + "objc2-quartz-core 0.3.2", +] + +[[package]] +name = "objc2-cloud-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c" +dependencies = [ + "bitflags 2.9.4", + "objc2 0.6.3", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-core-data" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa" +dependencies = [ + "bitflags 2.9.4", + "objc2 0.6.3", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" +dependencies = [ + "bitflags 2.9.4", + "dispatch2", + "objc2 0.6.3", +] + +[[package]] +name = "objc2-core-graphics" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" +dependencies = [ + "bitflags 2.9.4", + "dispatch2", + "objc2 0.6.3", + "objc2-core-foundation", + "objc2-io-surface", +] + +[[package]] +name = "objc2-core-image" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d563b38d2b97209f8e861173de434bd0214cf020e3423a52624cd1d989f006" +dependencies = [ + "objc2 0.6.3", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-core-text" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d" +dependencies = [ + "bitflags 2.9.4", + "objc2 0.6.3", + "objc2-core-foundation", + "objc2-core-graphics", +] + +[[package]] +name = "objc2-core-video" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d425caf1df73233f29fd8a5c3e5edbc30d2d4307870f802d18f00d83dc5141a6" +dependencies = [ + "bitflags 2.9.4", + "objc2 0.6.3", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-io-surface", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "objc2-exception-helper" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7a1c5fbb72d7735b076bb47b578523aedc40f3c439bea6dfd595c089d79d98a" +dependencies = [ + "cc", +] + +[[package]] +name = "objc2-foundation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" +dependencies = [ + "bitflags 2.9.4", + "block2 0.5.1", + "libc", + "objc2 0.5.2", +] + +[[package]] +name = "objc2-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" +dependencies = [ + "bitflags 2.9.4", + "block2 0.6.2", + "libc", + "objc2 0.6.3", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-io-surface" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" +dependencies = [ + "bitflags 2.9.4", + "objc2 0.6.3", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-javascript-core" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a1e6550c4caed348956ce3370c9ffeca70bb1dbed4fa96112e7c6170e074586" +dependencies = [ + "objc2 0.6.3", + "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.9.4", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" +dependencies = [ + "bitflags 2.9.4", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-metal", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" +dependencies = [ + "bitflags 2.9.4", + "objc2 0.6.3", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-security" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "709fe137109bd1e8b5a99390f77a7d8b2961dafc1a1c5db8f2e60329ad6d895a" +dependencies = [ + "bitflags 2.9.4", + "objc2 0.6.3", + "objc2-core-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.9.4", + "objc2 0.6.3", + "objc2-core-foundation", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-web-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2e5aaab980c433cf470df9d7af96a7b46a9d892d521a2cbbb2f8a4c16751e7f" +dependencies = [ + "bitflags 2.9.4", + "block2 0.6.2", + "objc2 0.6.3", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "objc2-javascript-core", + "objc2-security", +] + +[[package]] +name = "object" +version = "0.37.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[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", +] + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link 0.2.1", +] + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "phf" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" +dependencies = [ + "phf_shared 0.8.0", +] + +[[package]] +name = "phf" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +dependencies = [ + "phf_macros 0.10.0", + "phf_shared 0.10.0", + "proc-macro-hack", +] + +[[package]] +name = "phf" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" +dependencies = [ + "phf_macros 0.11.3", + "phf_shared 0.11.3", +] + +[[package]] +name = "phf_codegen" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815" +dependencies = [ + "phf_generator 0.8.0", + "phf_shared 0.8.0", +] + +[[package]] +name = "phf_codegen" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" +dependencies = [ + "phf_generator 0.11.3", + "phf_shared 0.11.3", +] + +[[package]] +name = "phf_generator" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526" +dependencies = [ + "phf_shared 0.8.0", + "rand 0.7.3", +] + +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared 0.10.0", + "rand 0.8.5", +] + +[[package]] +name = "phf_generator" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" +dependencies = [ + "phf_shared 0.11.3", + "rand 0.8.5", +] + +[[package]] +name = "phf_macros" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58fdf3184dd560f160dd73922bea2d5cd6e8f064bf4b13110abd81b03697b4e0" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", + "proc-macro-hack", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "phf_macros" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" +dependencies = [ + "phf_generator 0.11.3", + "phf_shared 0.11.3", + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "phf_shared" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7" +dependencies = [ + "siphasher 0.3.11", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher 0.3.11", +] + +[[package]] +name = "phf_shared" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" +dependencies = [ + "siphasher 1.0.1", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "plist" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "740ebea15c5d1428f910cd1a5f52cebf8d25006245ed8ade92702f4943d91e07" +dependencies = [ + "base64 0.22.1", + "indexmap 2.11.4", + "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", +] + +[[package]] +name = "potential_utf" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "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.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" +dependencies = [ + "toml_edit 0.23.6", +] + +[[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-macro-hack" +version = "0.5.20+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" + +[[package]] +name = "proc-macro2" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quick-xml" +version = "0.38.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42a232e7487fc2ef313d96dde7948e7a3c05101870d8985e4fd8d26aedd27b89" +dependencies = [ + "memchr", +] + +[[package]] +name = "quote" +version = "1.0.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", + "rand_pcg", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.16", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "rand_pcg" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "raw-window-handle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags 2.9.4", +] + +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom 0.2.16", + "libredox", + "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.16", + "libredox", + "thiserror 2.0.17", +] + +[[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.106", +] + +[[package]] +name = "regex" +version = "1.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b5288124840bee7b386bc413c487869b360b2b4ec421ea56425128692f2a82c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "833eb9ce86d40ef33cb1306d8accf7bc8ec2bfea4355cbdebb3df68b40925cad" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" + +[[package]] +name = "reqwest" +version = "0.12.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d429f34c8092b2d42c7c93cec323bb4adeb7c67698f70839adec842ec10c7ceb" +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", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-util", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schemars" +version = "0.8.22" +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.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82d20c4491bc164fa2f6c5d44565947a52ad80b9505d8e36f8d54c27c739fcd0" +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.106", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "selectors" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c37578180969d00692904465fb7f6b3d50b9a2b952b87c23d0e2e5cb5013416" +dependencies = [ + "bitflags 1.3.2", + "cssparser", + "derive_more", + "fxhash", + "log", + "phf 0.8.0", + "phf_codegen 0.8.0", + "precomputed-hash", + "servo_arc", + "smallvec", +] + +[[package]] +name = "semver" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[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.106", +] + +[[package]] +name = "serde_json" +version = "1.0.145" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", + "serde_core", +] + +[[package]] +name = "serde_repr" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[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.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5417783452c2be558477e104686f7de5dae53dba813c28435e0e70f82d9b04ee" +dependencies = [ + "serde_core", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_with" +version = "3.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6093cd8c01b25262b84927e0f7151692158fab02d961e04c979d3903eba7ecc5" +dependencies = [ + "base64 0.22.1", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.11.4", + "schemars 0.9.0", + "schemars 1.0.4", + "serde_core", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7e6c180db0816026a61afa1cff5344fb7ebded7e4d3062772179f2501481c27" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[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.106", +] + +[[package]] +name = "servo_arc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52aa42f8fdf0fed91e5ce7f23d8138441002fa31dca008acf47e6fd4721f741" +dependencies = [ + "nodrop", + "stable_deref_trait", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "siphasher" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" + +[[package]] +name = "slab" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "socket2" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "softbuffer" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18051cdd562e792cad055119e0cdb2cfc137e44e3987532e0f9659a77931bb08" +dependencies = [ + "bytemuck", + "cfg_aliases", + "core-graphics", + "foreign-types", + "js-sys", + "log", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-quartz-core 0.2.2", + "raw-window-handle", + "redox_syscall", + "wasm-bindgen", + "web-sys", + "windows-sys 0.59.0", +] + +[[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", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "string_cache" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f" +dependencies = [ + "new_debug_unreachable", + "parking_lot", + "phf_shared 0.11.3", + "precomputed-hash", + "serde", +] + +[[package]] +name = "string_cache_codegen" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c711928715f1fe0fe509c53b43e993a9a557babc2d0a3567d0a3006f1ac931a0" +dependencies = [ + "phf_generator 0.11.3", + "phf_shared 0.11.3", + "proc-macro2", + "quote", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +dependencies = [ + "proc-macro2", + "quote", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[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.34.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "959469667dbcea91e5485fc48ba7dd6023face91bb0f1a14681a70f99847c3f7" +dependencies = [ + "bitflags 2.9.4", + "block2 0.6.2", + "core-foundation", + "core-graphics", + "crossbeam-channel", + "dispatch", + "dlopen2", + "dpi", + "gdkwayland-sys", + "gdkx11-sys", + "gtk", + "jni", + "lazy_static", + "libc", + "log", + "ndk", + "ndk-context", + "ndk-sys", + "objc2 0.6.3", + "objc2-app-kit", + "objc2-foundation 0.3.2", + "once_cell", + "parking_lot", + "raw-window-handle", + "scopeguard", + "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.106", +] + +[[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.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4d1d3b3dc4c101ac989fd7db77e045cc6d91a25349cd410455cb5c57d510c1c" +dependencies = [ + "anyhow", + "bytes", + "cookie", + "dirs 6.0.0", + "dunce", + "embed_plist", + "getrandom 0.3.3", + "glob", + "gtk", + "heck 0.5.0", + "http", + "jni", + "libc", + "log", + "mime", + "muda", + "objc2 0.6.3", + "objc2-app-kit", + "objc2-foundation 0.3.2", + "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.17", + "tokio", + "tray-icon", + "url", + "urlpattern", + "webkit2gtk", + "webview2-com", + "window-vibrancy", + "windows", +] + +[[package]] +name = "tauri-build" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c432ccc9ff661803dab74c6cd78de11026a578a9307610bbc39d3c55be7943f" +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", + "toml 0.9.7", + "walkdir", +] + +[[package]] +name = "tauri-codegen" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ab3a62cf2e6253936a8b267c2e95839674e7439f104fa96ad0025e149d54d8a" +dependencies = [ + "base64 0.22.1", + "brotli", + "ico", + "json-patch", + "plist", + "png", + "proc-macro2", + "quote", + "semver", + "serde", + "serde_json", + "sha2", + "syn 2.0.106", + "tauri-utils", + "thiserror 2.0.17", + "time", + "url", + "uuid", + "walkdir", +] + +[[package]] +name = "tauri-macros" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4368ea8094e7045217edb690f493b55b30caf9f3e61f79b4c24b6db91f07995e" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.106", + "tauri-codegen", + "tauri-utils", +] + +[[package]] +name = "tauri-plugin" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9946a3cede302eac0c6eb6c6070ac47b1768e326092d32efbb91f21ed58d978f" +dependencies = [ + "anyhow", + "glob", + "plist", + "schemars 0.8.22", + "serde", + "serde_json", + "tauri-utils", + "toml 0.9.7", + "walkdir", +] + +[[package]] +name = "tauri-plugin-autostart" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "062cdcd483d5e3148c9a64dabf8c574e239e2aa1193cf208d95cf89a676f87a5" +dependencies = [ + "auto-launch", + "serde", + "serde_json", + "tauri", + "tauri-plugin", + "thiserror 2.0.17", +] + +[[package]] +name = "tauri-runtime" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4cfc9ad45b487d3fded5a4731a567872a4812e9552e3964161b08edabf93846" +dependencies = [ + "cookie", + "dpi", + "gtk", + "http", + "jni", + "objc2 0.6.3", + "objc2-ui-kit", + "objc2-web-kit", + "raw-window-handle", + "serde", + "serde_json", + "tauri-utils", + "thiserror 2.0.17", + "url", + "webkit2gtk", + "webview2-com", + "windows", +] + +[[package]] +name = "tauri-runtime-wry" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1fe9d48bd122ff002064e88cfcd7027090d789c4302714e68fcccba0f4b7807" +dependencies = [ + "gtk", + "http", + "jni", + "log", + "objc2 0.6.3", + "objc2-app-kit", + "objc2-foundation 0.3.2", + "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.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41a3852fdf9a4f8fbeaa63dc3e9a85284dd6ef7200751f0bd66ceee30c93f212" +dependencies = [ + "anyhow", + "brotli", + "cargo_metadata", + "ctor", + "dunce", + "glob", + "html5ever", + "http", + "infer", + "json-patch", + "kuchikiki", + "log", + "memchr", + "phf 0.11.3", + "proc-macro2", + "quote", + "regex", + "schemars 0.8.22", + "semver", + "serde", + "serde-untagged", + "serde_json", + "serde_with", + "swift-rs", + "thiserror 2.0.17", + "toml 0.9.7", + "url", + "urlpattern", + "uuid", + "walkdir", +] + +[[package]] +name = "tauri-winres" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd21509dd1fa9bd355dc29894a6ff10635880732396aa38c0066c1e6c1ab8074" +dependencies = [ + "embed-resource", + "toml 0.9.7", +] + +[[package]] +name = "tendril" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" +dependencies = [ + "futf", + "mac", + "utf-8", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +dependencies = [ + "thiserror-impl 2.0.17", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "time" +version = "0.3.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" + +[[package]] +name = "time-macros" +version = "0.2.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tinystr" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tokio" +version = "1.47.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" +dependencies = [ + "backtrace", + "bytes", + "io-uring", + "libc", + "mio", + "pin-project-lite", + "slab", + "socket2", + "windows-sys 0.59.0", +] + +[[package]] +name = "tokio-util" +version = "0.7.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" +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.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00e5e5d9bf2475ac9d4f0d9edab68cc573dc2fd644b0dba36b0c30a92dd9eaa0" +dependencies = [ + "indexmap 2.11.4", + "serde_core", + "serde_spanned 1.0.2", + "toml_datetime 0.7.2", + "toml_parser", + "toml_writer", + "winnow 0.7.13", +] + +[[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.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32f1085dec27c2b6632b04c80b3bb1b4300d6495d1e129693bdda7d91e72eec1" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap 2.11.4", + "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.11.4", + "serde", + "serde_spanned 0.6.9", + "toml_datetime 0.6.3", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.23.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3effe7c0e86fdff4f69cdd2ccc1b96f933e24811c5441d44904e8683e27184b" +dependencies = [ + "indexmap 2.11.4", + "toml_datetime 0.7.2", + "toml_parser", + "winnow 0.7.13", +] + +[[package]] +name = "toml_parser" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cf893c33be71572e0e9aa6dd15e6677937abd686b066eac3f8cd3531688a627" +dependencies = [ + "winnow 0.7.13", +] + +[[package]] +name = "toml_writer" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d163a63c116ce562a22cda521fcc4d79152e7aba014456fb5eb442f6d6a10109" + +[[package]] +name = "tower" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-http" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" +dependencies = [ + "bitflags 2.9.4", + "bytes", + "futures-util", + "http", + "http-body", + "iri-string", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", +] + +[[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.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +dependencies = [ + "once_cell", +] + +[[package]] +name = "tray-icon" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0d92153331e7d02ec09137538996a7786fe679c629c279e82a6be762b7e6fe2" +dependencies = [ + "crossbeam-channel", + "dirs 6.0.0", + "libappindicator", + "muda", + "objc2 0.6.3", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-foundation 0.3.2", + "once_cell", + "png", + "serde", + "thiserror 2.0.17", + "windows-sys 0.59.0", +] + +[[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.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" + +[[package]] +name = "unic-char-property" +version = "0.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", +] + +[[package]] +name = "unicode-ident" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "url" +version = "2.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "uuid" +version = "1.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" +dependencies = [ + "getrandom 0.3.3", + "js-sys", + "serde", + "wasm-bindgen", +] + +[[package]] +name = "version-compare" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" + +[[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 = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "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.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasi" +version = "0.14.7+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c" +dependencies = [ + "wasip2", +] + +[[package]] +name = "wasip2" +version = "1.0.1+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn 2.0.106", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e038d41e478cc73bae0ff9b36c60cff1c98b8f38f8d7e8061e79ee63608ac5c" +dependencies = [ + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasm-streams" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "web-sys" +version = "0.3.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9367c417a924a74cae129e6a2ae3b47fabb1f8995595ab474029da749a8be120" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webkit2gtk" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76b1bc1e54c581da1e9f179d0b38512ba358fb1af2d634a1affe42e37172361a" +dependencies = [ + "bitflags 1.3.2", + "cairo-rs", + "gdk", + "gdk-sys", + "gio", + "gio-sys", + "glib", + "glib-sys", + "gobject-sys", + "gtk", + "gtk-sys", + "javascriptcore-rs", + "libc", + "once_cell", + "soup3", + "webkit2gtk-sys", +] + +[[package]] +name = "webkit2gtk-sys" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62daa38afc514d1f8f12b8693d30d5993ff77ced33ce30cd04deebc267a6d57c" +dependencies = [ + "bitflags 1.3.2", + "cairo-sys-rs", + "gdk-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "gtk-sys", + "javascriptcore-rs-sys", + "libc", + "pkg-config", + "soup3-sys", + "system-deps", +] + +[[package]] +name = "webview2-com" +version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4ba622a989277ef3886dd5afb3e280e3dd6d974b766118950a08f8f678ad6a4" +dependencies = [ + "webview2-com-macros", + "webview2-com-sys", + "windows", + "windows-core 0.61.2", + "windows-implement", + "windows-interface", +] + +[[package]] +name = "webview2-com-macros" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d228f15bba3b9d56dde8bddbee66fa24545bd17b48d5128ccf4a8742b18e431" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "webview2-com-sys" +version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36695906a1b53a3bf5c4289621efedac12b73eeb0b89e7e1a89b517302d5d75c" +dependencies = [ + "thiserror 2.0.17", + "windows", + "windows-core 0.61.2", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "window-vibrancy" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9bec5a31f3f9362f2258fd0e9c9dd61a9ca432e7306cc78c444258f0dce9a9c" +dependencies = [ + "objc2 0.6.3", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "raw-window-handle", + "windows-sys 0.59.0", + "windows-version", +] + +[[package]] +name = "windows" +version = "0.61.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" +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", +] + +[[package]] +name = "windows-core" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link 0.1.3", + "windows-result 0.3.4", + "windows-strings 0.4.2", +] + +[[package]] +name = "windows-core" +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", +] + +[[package]] +name = "windows-future" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" +dependencies = [ + "windows-core 0.61.2", + "windows-link 0.1.3", + "windows-threading", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[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", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link 0.2.1", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link 0.2.1", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link 0.2.1", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "0.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" +dependencies = [ + "memchr", +] + +[[package]] +name = "winreg" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +dependencies = [ + "winapi", +] + +[[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.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" + +[[package]] +name = "writeable" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" + +[[package]] +name = "wry" +version = "0.53.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d78ec082b80fa088569a970d043bb3050abaabf4454101d44514ee8d9a8c9f6" +dependencies = [ + "base64 0.22.1", + "block2 0.6.2", + "cookie", + "crossbeam-channel", + "dirs 6.0.0", + "dpi", + "dunce", + "gdkx11", + "gtk", + "html5ever", + "http", + "javascriptcore-rs", + "jni", + "kuchikiki", + "libc", + "ndk", + "objc2 0.6.3", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "objc2-ui-kit", + "objc2-web-kit", + "once_cell", + "percent-encoding", + "raw-window-handle", + "sha2", + "soup3", + "tao-macros", + "thiserror 2.0.17", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" +dependencies = [ + "libc", + "once_cell", + "pkg-config", +] + +[[package]] +name = "yoke" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.8.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", + "synstructure", +] + +[[package]] +name = "zerotrie" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] diff --git a/src-tauri/client/Cargo.toml b/src-tauri/client/Cargo.toml new file mode 100644 index 0000000..6e32523 --- /dev/null +++ b/src-tauri/client/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "client" +version = "0.1.0" +edition = "2024" + +[dependencies] +bitcode = "0.6.7" +database = { version = "0.1.0", path = "../database" } +log = "0.4.28" +serde = { version = "1.0.228", features = ["derive"] } +tauri = "2.8.5" +tauri-plugin-autostart = "2.5.0" diff --git a/src-tauri/src/cloud_saves/strict_path.rs b/src-tauri/client/src/app_state.rs similarity index 100% rename from src-tauri/src/cloud_saves/strict_path.rs rename to src-tauri/client/src/app_state.rs diff --git a/src-tauri/client/src/app_status.rs b/src-tauri/client/src/app_status.rs new file mode 100644 index 0000000..c33874e --- /dev/null +++ b/src-tauri/client/src/app_status.rs @@ -0,0 +1,12 @@ +use serde::Serialize; + +#[derive(Clone, Copy, Serialize, Eq, PartialEq)] +pub enum AppStatus { + NotConfigured, + Offline, + ServerError, + SignedOut, + SignedIn, + SignedInNeedsReauth, + ServerUnavailable, +} diff --git a/src-tauri/client/src/autostart.rs b/src-tauri/client/src/autostart.rs new file mode 100644 index 0000000..26b2efd --- /dev/null +++ b/src-tauri/client/src/autostart.rs @@ -0,0 +1,26 @@ +use database::borrow_db_checked; +use log::debug; +use tauri::AppHandle; +use tauri_plugin_autostart::ManagerExt; + +// New function to sync state on startup +pub fn sync_autostart_on_startup(app: &AppHandle) -> Result<(), String> { + let db_handle = borrow_db_checked(); + let should_be_enabled = db_handle.settings.autostart; + drop(db_handle); + + let manager = app.autolaunch(); + let current_state = manager.is_enabled().map_err(|e| e.to_string())?; + + if current_state != should_be_enabled { + if should_be_enabled { + manager.enable().map_err(|e| e.to_string())?; + debug!("synced autostart: enabled"); + } else { + manager.disable().map_err(|e| e.to_string())?; + debug!("synced autostart: disabled"); + } + } + + Ok(()) +} diff --git a/src-tauri/client/src/compat.rs b/src-tauri/client/src/compat.rs new file mode 100644 index 0000000..0bd04b6 --- /dev/null +++ b/src-tauri/client/src/compat.rs @@ -0,0 +1,52 @@ +use std::{ + ffi::OsStr, + path::PathBuf, + process::{Command, Stdio}, + sync::LazyLock, +}; + +use log::info; + +pub static COMPAT_INFO: LazyLock> = LazyLock::new(create_new_compat_info); + +pub static UMU_LAUNCHER_EXECUTABLE: LazyLock> = LazyLock::new(|| { + let x = get_umu_executable(); + info!("{:?}", &x); + x +}); + +#[derive(Clone)] +pub struct CompatInfo { + pub umu_installed: bool, +} + +fn create_new_compat_info() -> Option { + #[cfg(target_os = "windows")] + return None; + + let has_umu_installed = UMU_LAUNCHER_EXECUTABLE.is_some(); + Some(CompatInfo { + umu_installed: has_umu_installed, + }) +} + +const UMU_BASE_LAUNCHER_EXECUTABLE: &str = "umu-run"; +const UMU_INSTALL_DIRS: [&str; 4] = ["/app/share", "/use/local/share", "/usr/share", "/opt"]; + +fn get_umu_executable() -> Option { + if check_executable_exists(UMU_BASE_LAUNCHER_EXECUTABLE) { + return Some(PathBuf::from(UMU_BASE_LAUNCHER_EXECUTABLE)); + } + + for dir in UMU_INSTALL_DIRS { + let p = PathBuf::from(dir).join(UMU_BASE_LAUNCHER_EXECUTABLE); + if check_executable_exists(&p) { + return Some(p); + } + } + None +} +fn check_executable_exists>(exec: P) -> bool { + let has_umu_installed = Command::new(exec).stdout(Stdio::null()).output(); + has_umu_installed.is_ok() +} diff --git a/src-tauri/client/src/lib.rs b/src-tauri/client/src/lib.rs new file mode 100644 index 0000000..cb5afe9 --- /dev/null +++ b/src-tauri/client/src/lib.rs @@ -0,0 +1,4 @@ +pub mod app_status; +pub mod autostart; +pub mod compat; +pub mod user; diff --git a/src-tauri/client/src/user.rs b/src-tauri/client/src/user.rs new file mode 100644 index 0000000..8f8462a --- /dev/null +++ b/src-tauri/client/src/user.rs @@ -0,0 +1,12 @@ +use bitcode::{Decode, Encode}; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Serialize, Deserialize, Encode, Decode)] +#[serde(rename_all = "camelCase")] +pub struct User { + id: String, + username: String, + admin: bool, + display_name: String, + profile_picture_object_id: String, +} diff --git a/src-tauri/cloud_saves/Cargo.toml b/src-tauri/cloud_saves/Cargo.toml new file mode 100644 index 0000000..806d1b0 --- /dev/null +++ b/src-tauri/cloud_saves/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "cloud_saves" +version = "0.1.0" +edition = "2024" + +[dependencies] +database = { version = "0.1.0", path = "../database" } +dirs = "6.0.0" +log = "0.4.28" +regex = "1.11.3" +rustix = "1.1.2" +serde = "1.0.228" +serde_json = "1.0.145" +serde_with = "3.15.0" +tar = "0.4.44" +tempfile = "3.23.0" +uuid = "1.18.1" +whoami = "1.6.1" +zstd = "0.13.3" diff --git a/src-tauri/cloud_saves/src/backup_manager.rs b/src-tauri/cloud_saves/src/backup_manager.rs new file mode 100644 index 0000000..db8e9f2 --- /dev/null +++ b/src-tauri/cloud_saves/src/backup_manager.rs @@ -0,0 +1,234 @@ +use std::{collections::HashMap, path::PathBuf, str::FromStr}; + +#[cfg(target_os = "linux")] +use database::platform::Platform; +use database::{GameVersion, db::DATA_ROOT_DIR}; +use log::warn; + +use crate::error::BackupError; + +use super::path::CommonPath; + +pub struct BackupManager<'a> { + pub current_platform: Platform, + pub sources: HashMap<(Platform, Platform), &'a (dyn BackupHandler + Sync + Send)>, +} + +impl Default for BackupManager<'_> { + fn default() -> Self { + Self::new() + } +} + +impl BackupManager<'_> { + pub fn new() -> Self { + BackupManager { + #[cfg(target_os = "windows")] + current_platform: Platform::Windows, + + #[cfg(target_os = "macos")] + current_platform: Platform::MacOs, + + #[cfg(target_os = "linux")] + current_platform: Platform::Linux, + + sources: HashMap::from([ + // Current platform to target platform + ( + (Platform::Windows, Platform::Windows), + &WindowsBackupManager {} as &(dyn BackupHandler + Sync + Send), + ), + ( + (Platform::Linux, Platform::Linux), + &LinuxBackupManager {} as &(dyn BackupHandler + Sync + Send), + ), + ( + (Platform::MacOs, Platform::MacOs), + &MacBackupManager {} as &(dyn BackupHandler + Sync + Send), + ), + ]), + } + } +} + +pub trait BackupHandler: Send + Sync { + fn root_translate(&self, _path: &PathBuf, _game: &GameVersion) -> Result { + Ok(DATA_ROOT_DIR.join("games")) + } + fn game_translate(&self, _path: &PathBuf, game: &GameVersion) -> Result { + Ok(PathBuf::from_str(&game.game_id).unwrap()) + } + fn base_translate(&self, path: &PathBuf, game: &GameVersion) -> Result { + Ok(self + .root_translate(path, game)? + .join(self.game_translate(path, game)?)) + } + fn home_translate(&self, _path: &PathBuf, _game: &GameVersion) -> Result { + let c = CommonPath::Home.get().ok_or(BackupError::NotFound); + println!("{:?}", c); + c + } + fn store_user_id_translate( + &self, + _path: &PathBuf, + game: &GameVersion, + ) -> Result { + PathBuf::from_str(&game.game_id).map_err(|_| BackupError::ParseError) + } + fn os_user_name_translate( + &self, + _path: &PathBuf, + _game: &GameVersion, + ) -> Result { + Ok(PathBuf::from_str(&whoami::username()).unwrap()) + } + fn win_app_data_translate( + &self, + _path: &PathBuf, + _game: &GameVersion, + ) -> Result { + warn!("Unexpected Windows Reference in Backup "); + Err(BackupError::InvalidSystem) + } + fn win_local_app_data_translate( + &self, + _path: &PathBuf, + _game: &GameVersion, + ) -> Result { + warn!("Unexpected Windows Reference in Backup "); + Err(BackupError::InvalidSystem) + } + fn win_local_app_data_low_translate( + &self, + _path: &PathBuf, + _game: &GameVersion, + ) -> Result { + warn!("Unexpected Windows Reference in Backup "); + Err(BackupError::InvalidSystem) + } + fn win_documents_translate( + &self, + _path: &PathBuf, + _game: &GameVersion, + ) -> Result { + warn!("Unexpected Windows Reference in Backup "); + Err(BackupError::InvalidSystem) + } + fn win_public_translate( + &self, + _path: &PathBuf, + _game: &GameVersion, + ) -> Result { + warn!("Unexpected Windows Reference in Backup "); + Err(BackupError::InvalidSystem) + } + fn win_program_data_translate( + &self, + _path: &PathBuf, + _game: &GameVersion, + ) -> Result { + warn!("Unexpected Windows Reference in Backup "); + Err(BackupError::InvalidSystem) + } + fn win_dir_translate( + &self, + _path: &PathBuf, + _game: &GameVersion, + ) -> Result { + warn!("Unexpected Windows Reference in Backup "); + Err(BackupError::InvalidSystem) + } + fn xdg_data_translate( + &self, + _path: &PathBuf, + _game: &GameVersion, + ) -> Result { + warn!("Unexpected XDG Reference in Backup "); + Err(BackupError::InvalidSystem) + } + fn xdg_config_translate( + &self, + _path: &PathBuf, + _game: &GameVersion, + ) -> Result { + warn!("Unexpected XDG Reference in Backup "); + Err(BackupError::InvalidSystem) + } + fn skip_translate(&self, _path: &PathBuf, _game: &GameVersion) -> Result { + Ok(PathBuf::new()) + } +} + +pub struct LinuxBackupManager {} +impl BackupHandler for LinuxBackupManager { + fn xdg_config_translate( + &self, + _path: &PathBuf, + _game: &GameVersion, + ) -> Result { + CommonPath::Data.get().ok_or(BackupError::NotFound) + } + fn xdg_data_translate( + &self, + _path: &PathBuf, + _game: &GameVersion, + ) -> Result { + CommonPath::Config.get().ok_or(BackupError::NotFound) + } +} +pub struct WindowsBackupManager {} +impl BackupHandler for WindowsBackupManager { + fn win_app_data_translate( + &self, + _path: &PathBuf, + _game: &GameVersion, + ) -> Result { + CommonPath::Config.get().ok_or(BackupError::NotFound) + } + fn win_local_app_data_translate( + &self, + _path: &PathBuf, + _game: &GameVersion, + ) -> Result { + CommonPath::DataLocal.get().ok_or(BackupError::NotFound) + } + fn win_local_app_data_low_translate( + &self, + _path: &PathBuf, + _game: &GameVersion, + ) -> Result { + CommonPath::DataLocalLow + .get() + .ok_or(BackupError::NotFound) + } + fn win_dir_translate( + &self, + _path: &PathBuf, + _game: &GameVersion, + ) -> Result { + Ok(PathBuf::from_str("C:/Windows").unwrap()) + } + fn win_documents_translate( + &self, + _path: &PathBuf, + _game: &GameVersion, + ) -> Result { + CommonPath::Document.get().ok_or(BackupError::NotFound) + } + fn win_program_data_translate( + &self, + _path: &PathBuf, + _game: &GameVersion, + ) -> Result { + Ok(PathBuf::from_str("C:/ProgramData").unwrap()) + } + fn win_public_translate( + &self, + _path: &PathBuf, + _game: &GameVersion, + ) -> Result { + CommonPath::Public.get().ok_or(BackupError::NotFound) + } +} +pub struct MacBackupManager {} +impl BackupHandler for MacBackupManager {} diff --git a/src-tauri/src/cloud_saves/conditions.rs b/src-tauri/cloud_saves/src/conditions.rs similarity index 61% rename from src-tauri/src/cloud_saves/conditions.rs rename to src-tauri/cloud_saves/src/conditions.rs index 1b3af87..8c8828f 100644 --- a/src-tauri/src/cloud_saves/conditions.rs +++ b/src-tauri/cloud_saves/src/conditions.rs @@ -1,6 +1,7 @@ -use crate::process::process_manager::Platform; +use database::platform::Platform; #[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub enum Condition { - Os(Platform) + Os(Platform), + Other } diff --git a/src-tauri/cloud_saves/src/error.rs b/src-tauri/cloud_saves/src/error.rs new file mode 100644 index 0000000..28015bf --- /dev/null +++ b/src-tauri/cloud_saves/src/error.rs @@ -0,0 +1,27 @@ +use std::fmt::Display; + +use serde_with::SerializeDisplay; + +#[derive(Debug, SerializeDisplay, Clone, Copy)] + +pub enum BackupError { + InvalidSystem, + + NotFound, + + ParseError, +} + +impl Display for BackupError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let s = match self { + BackupError::InvalidSystem => "Attempted to generate path for invalid system", + + BackupError::NotFound => "Could not generate or find path", + + BackupError::ParseError => "Failed to parse path", + }; + + write!(f, "{}", s) + } +} diff --git a/src-tauri/cloud_saves/src/lib.rs b/src-tauri/cloud_saves/src/lib.rs new file mode 100644 index 0000000..3302ebf --- /dev/null +++ b/src-tauri/cloud_saves/src/lib.rs @@ -0,0 +1,8 @@ +pub mod backup_manager; +pub mod conditions; +pub mod error; +pub mod metadata; +pub mod normalise; +pub mod path; +pub mod placeholder; +pub mod resolver; diff --git a/src-tauri/src/cloud_saves/metadata.rs b/src-tauri/cloud_saves/src/metadata.rs similarity index 74% rename from src-tauri/src/cloud_saves/metadata.rs rename to src-tauri/cloud_saves/src/metadata.rs index eefa587..21980f5 100644 --- a/src-tauri/src/cloud_saves/metadata.rs +++ b/src-tauri/cloud_saves/src/metadata.rs @@ -1,7 +1,6 @@ -use crate::database::db::GameVersion; - -use super::conditions::{Condition}; +use database::GameVersion; +use super::conditions::Condition; #[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub struct CloudSaveMetadata { @@ -16,15 +15,17 @@ pub struct GameFile { pub id: Option, pub data_type: DataType, pub tags: Vec, - pub conditions: Vec + pub conditions: Vec, } #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, serde::Serialize, serde::Deserialize)] pub enum DataType { Registry, File, - Other + Other, } -#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, serde::Serialize, serde::Deserialize)] +#[derive( + Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, serde::Serialize, serde::Deserialize, +)] #[serde(rename_all = "camelCase")] pub enum Tag { Config, @@ -32,4 +33,4 @@ pub enum Tag { #[default] #[serde(other)] Other, -} \ No newline at end of file +} diff --git a/src-tauri/src/cloud_saves/mod.rs b/src-tauri/cloud_saves/src/mod.rs similarity index 100% rename from src-tauri/src/cloud_saves/mod.rs rename to src-tauri/cloud_saves/src/mod.rs diff --git a/src-tauri/src/cloud_saves/normalise.rs b/src-tauri/cloud_saves/src/normalise.rs similarity index 81% rename from src-tauri/src/cloud_saves/normalise.rs rename to src-tauri/cloud_saves/src/normalise.rs index 67da752..04785ae 100644 --- a/src-tauri/src/cloud_saves/normalise.rs +++ b/src-tauri/cloud_saves/src/normalise.rs @@ -1,11 +1,10 @@ use std::sync::LazyLock; +use database::platform::Platform; use regex::Regex; -use crate::process::process_manager::Platform; use super::placeholder::*; - pub fn normalize(path: &str, os: Platform) -> String { let mut path = path.trim().trim_end_matches(['/', '\\']).replace('\\', "/"); @@ -14,18 +13,25 @@ pub fn normalize(path: &str, os: Platform) -> String { } static CONSECUTIVE_SLASHES: LazyLock = LazyLock::new(|| Regex::new(r"/{2,}").unwrap()); - static UNNECESSARY_DOUBLE_STAR_1: LazyLock = LazyLock::new(|| Regex::new(r"([^/*])\*{2,}").unwrap()); - static UNNECESSARY_DOUBLE_STAR_2: LazyLock = LazyLock::new(|| Regex::new(r"\*{2,}([^/*])").unwrap()); + static UNNECESSARY_DOUBLE_STAR_1: LazyLock = + LazyLock::new(|| Regex::new(r"([^/*])\*{2,}").unwrap()); + static UNNECESSARY_DOUBLE_STAR_2: LazyLock = + LazyLock::new(|| Regex::new(r"\*{2,}([^/*])").unwrap()); static ENDING_WILDCARD: LazyLock = LazyLock::new(|| Regex::new(r"(/\*)+$").unwrap()); static ENDING_DOT: LazyLock = LazyLock::new(|| Regex::new(r"(/\.)$").unwrap()); static INTERMEDIATE_DOT: LazyLock = LazyLock::new(|| Regex::new(r"(/\./)").unwrap()); static BLANK_SEGMENT: LazyLock = LazyLock::new(|| Regex::new(r"(/\s+/)").unwrap()); static APP_DATA: LazyLock = LazyLock::new(|| Regex::new(r"(?i)%appdata%").unwrap()); - static APP_DATA_ROAMING: LazyLock = LazyLock::new(|| Regex::new(r"(?i)%userprofile%/AppData/Roaming").unwrap()); - static APP_DATA_LOCAL: LazyLock = LazyLock::new(|| Regex::new(r"(?i)%localappdata%").unwrap()); - static APP_DATA_LOCAL_2: LazyLock = LazyLock::new(|| Regex::new(r"(?i)%userprofile%/AppData/Local/").unwrap()); - static USER_PROFILE: LazyLock = LazyLock::new(|| Regex::new(r"(?i)%userprofile%").unwrap()); - static DOCUMENTS: LazyLock = LazyLock::new(|| Regex::new(r"(?i)%userprofile%/Documents").unwrap()); + static APP_DATA_ROAMING: LazyLock = + LazyLock::new(|| Regex::new(r"(?i)%userprofile%/AppData/Roaming").unwrap()); + static APP_DATA_LOCAL: LazyLock = + LazyLock::new(|| Regex::new(r"(?i)%localappdata%").unwrap()); + static APP_DATA_LOCAL_2: LazyLock = + LazyLock::new(|| Regex::new(r"(?i)%userprofile%/AppData/Local/").unwrap()); + static USER_PROFILE: LazyLock = + LazyLock::new(|| Regex::new(r"(?i)%userprofile%").unwrap()); + static DOCUMENTS: LazyLock = + LazyLock::new(|| Regex::new(r"(?i)%userprofile%/Documents").unwrap()); for (pattern, replacement) in [ (&CONSECUTIVE_SLASHES, "/"), @@ -66,7 +72,9 @@ pub fn normalize(path: &str, os: Platform) -> String { fn too_broad(path: &str) -> bool { println!("Path: {}", path); - use {BASE, HOME, ROOT, STORE_USER_ID, WIN_APP_DATA, WIN_DIR, WIN_DOCUMENTS, XDG_CONFIG, XDG_DATA}; + use { + BASE, HOME, ROOT, STORE_USER_ID, WIN_APP_DATA, WIN_DIR, WIN_DOCUMENTS, XDG_CONFIG, XDG_DATA, + }; let path_lower = path.to_lowercase(); @@ -77,7 +85,9 @@ fn too_broad(path: &str) -> bool { } for item in AVOID_WILDCARDS { - if path.starts_with(&format!("{}/*", item)) || path.starts_with(&format!("{}/{}", item, STORE_USER_ID)) { + if path.starts_with(&format!("{}/*", item)) + || path.starts_with(&format!("{}/{}", item, STORE_USER_ID)) + { return true; } } @@ -124,7 +134,6 @@ fn too_broad(path: &str) -> bool { return true; } } - // Drive letters: let drives: Regex = Regex::new(r"^[a-zA-Z]:$").unwrap(); @@ -159,4 +168,4 @@ pub fn usable(path: &str) -> bool { && !path.starts_with("../") && !too_broad(path) && !unprintable.is_match(path) -} \ No newline at end of file +} diff --git a/src-tauri/src/cloud_saves/path.rs b/src-tauri/cloud_saves/src/path.rs similarity index 84% rename from src-tauri/src/cloud_saves/path.rs rename to src-tauri/cloud_saves/src/path.rs index 92aaaf9..d3b83d0 100644 --- a/src-tauri/src/cloud_saves/path.rs +++ b/src-tauri/cloud_saves/src/path.rs @@ -13,12 +13,12 @@ pub enum CommonPath { impl CommonPath { pub fn get(&self) -> Option { - static CONFIG: LazyLock> = LazyLock::new(|| dirs::config_dir()); - static DATA: LazyLock> = LazyLock::new(|| dirs::data_dir()); - static DATA_LOCAL: LazyLock> = LazyLock::new(|| dirs::data_local_dir()); - static DOCUMENT: LazyLock> = LazyLock::new(|| dirs::document_dir()); - static HOME: LazyLock> = LazyLock::new(|| dirs::home_dir()); - static PUBLIC: LazyLock> = LazyLock::new(|| dirs::public_dir()); + static CONFIG: LazyLock> = LazyLock::new(dirs::config_dir); + static DATA: LazyLock> = LazyLock::new(dirs::data_dir); + static DATA_LOCAL: LazyLock> = LazyLock::new(dirs::data_local_dir); + static DOCUMENT: LazyLock> = LazyLock::new(dirs::document_dir); + static HOME: LazyLock> = LazyLock::new(dirs::home_dir); + static PUBLIC: LazyLock> = LazyLock::new(dirs::public_dir); #[cfg(windows)] static DATA_LOCAL_LOW: LazyLock> = LazyLock::new(|| { diff --git a/src-tauri/src/cloud_saves/placeholder.rs b/src-tauri/cloud_saves/src/placeholder.rs similarity index 96% rename from src-tauri/src/cloud_saves/placeholder.rs rename to src-tauri/cloud_saves/src/placeholder.rs index 3224565..03d297a 100644 --- a/src-tauri/src/cloud_saves/placeholder.rs +++ b/src-tauri/cloud_saves/src/placeholder.rs @@ -48,4 +48,4 @@ pub const XDG_DATA: &str = ""; // %WINDIR% on Windows pub const XDG_CONFIG: &str = ""; // $XDG_DATA_HOME on Linux pub const SKIP: &str = ""; // $XDG_CONFIG_HOME on Linux -pub static OS_USERNAME: LazyLock = LazyLock::new(|| whoami::username()); \ No newline at end of file +pub static OS_USERNAME: LazyLock = LazyLock::new(whoami::username); diff --git a/src-tauri/src/cloud_saves/resolver.rs b/src-tauri/cloud_saves/src/resolver.rs similarity index 77% rename from src-tauri/src/cloud_saves/resolver.rs rename to src-tauri/cloud_saves/src/resolver.rs index c78fc36..8fd3fd7 100644 --- a/src-tauri/src/cloud_saves/resolver.rs +++ b/src-tauri/cloud_saves/src/resolver.rs @@ -1,22 +1,17 @@ use std::{ - fs::{self, create_dir_all, File}, - io::{self, ErrorKind, Read, Write}, + fs::{self, File, create_dir_all}, + io::{self, Read, Write}, path::{Path, PathBuf}, - thread::sleep, - time::Duration, }; -use super::{ - backup_manager::BackupHandler, conditions::Condition, metadata::GameFile, placeholder::*, -}; +use crate::error::BackupError; + +use super::{backup_manager::BackupHandler, placeholder::*}; +use database::GameVersion; use log::{debug, warn}; use rustix::path::Arg; use tempfile::tempfile; -use crate::{ - database::db::GameVersion, error::backup_error::BackupError, process::process_manager::Platform, -}; - use super::{backup_manager::BackupManager, metadata::CloudSaveMetadata, normalise::normalize}; pub fn resolve(meta: &mut CloudSaveMetadata) -> File { @@ -31,7 +26,7 @@ pub fn resolve(meta: &mut CloudSaveMetadata) -> File { .iter() .find_map(|p| match p { super::conditions::Condition::Os(os) => Some(os), - _ => None, + _ => None }) .cloned() { @@ -64,7 +59,7 @@ pub fn resolve(meta: &mut CloudSaveMetadata) -> File { let binding = serde_json::to_string(meta).unwrap(); let serialized = binding.as_bytes(); let mut file = tempfile().unwrap(); - file.write(serialized).unwrap(); + file.write_all(serialized).unwrap(); tarball.append_file("metadata", &mut file).unwrap(); tarball.into_inner().unwrap().finish().unwrap() } @@ -97,7 +92,7 @@ pub fn extract(file: PathBuf) -> Result<(), BackupError> { .iter() .find_map(|p| match p { super::conditions::Condition::Os(os) => Some(os), - _ => None, + _ => None }) .cloned() { @@ -116,7 +111,7 @@ pub fn extract(file: PathBuf) -> Result<(), BackupError> { }; let new_path = parse_path(file.path.into(), handler, &manifest.game_version)?; - create_dir_all(&new_path.parent().unwrap()).unwrap(); + create_dir_all(new_path.parent().unwrap()).unwrap(); println!( "Current path {:?} copying to {:?}", @@ -133,23 +128,22 @@ pub fn copy_item>(src: P, dest: P) -> io::Result<()> { let src_path = src.as_ref(); let dest_path = dest.as_ref(); - let metadata = fs::metadata(&src_path)?; + let metadata = fs::metadata(src_path)?; if metadata.is_file() { // Ensure the parent directory of the destination exists for a file copy if let Some(parent) = dest_path.parent() { fs::create_dir_all(parent)?; } - fs::copy(&src_path, &dest_path)?; + fs::copy(src_path, dest_path)?; } else if metadata.is_dir() { // For directories, we call the recursive helper function. // The destination for the recursive copy is the `dest_path` itself. - copy_dir_recursive(&src_path, &dest_path)?; + copy_dir_recursive(src_path, dest_path)?; } else { // Handle other file types like symlinks if necessary, // for now, return an error or skip. - return Err(io::Error::new( - io::ErrorKind::Other, + return Err(io::Error::other( format!("Source {:?} is neither a file nor a directory", src_path), )); } @@ -158,7 +152,7 @@ pub fn copy_item>(src: P, dest: P) -> io::Result<()> { } fn copy_dir_recursive(src: &Path, dest: &Path) -> io::Result<()> { - fs::create_dir_all(&dest)?; + fs::create_dir_all(dest)?; for entry in fs::read_dir(src)? { let entry = entry?; @@ -220,43 +214,3 @@ pub fn parse_path( println!("Final line: {:?}", &s); Ok(s) } - -pub fn test() { - let mut meta = CloudSaveMetadata { - files: vec![ - GameFile { - path: String::from("/favicon.png"), - id: None, - data_type: super::metadata::DataType::File, - tags: Vec::new(), - conditions: vec![Condition::Os(Platform::Linux)], - }, - GameFile { - path: String::from("/Documents/Pixel Art"), - id: None, - data_type: super::metadata::DataType::File, - tags: Vec::new(), - conditions: vec![Condition::Os(Platform::Linux)], - }, - ], - game_version: GameVersion { - game_id: String::new(), - version_name: String::new(), - platform: Platform::Linux, - launch_command: String::new(), - launch_args: Vec::new(), - launch_command_template: String::new(), - setup_command: String::new(), - setup_args: Vec::new(), - setup_command_template: String::new(), - only_setup: true, - version_index: 0, - delta: false, - umu_id_override: None, - }, - save_id: String::from("aaaaaaa"), - }; - //resolve(&mut meta); - - extract("save".into()).unwrap(); -} diff --git a/src-tauri/cloud_saves/src/strict_path.rs b/src-tauri/cloud_saves/src/strict_path.rs new file mode 100644 index 0000000..e69de29 diff --git a/src-tauri/database/Cargo.toml b/src-tauri/database/Cargo.toml new file mode 100644 index 0000000..9fbb499 --- /dev/null +++ b/src-tauri/database/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "database" +version = "0.1.0" +edition = "2024" + +[dependencies] +chrono = "0.4.42" +dirs = "6.0.0" +log = "0.4.28" +native_model = { version = "0.6.4", features = ["rmp_serde_1_3"], git = "https://github.com/Drop-OSS/native_model.git"} +rustbreak = "2.0.0" +serde = "1.0.228" +serde_with = "3.15.0" +url = "2.5.7" +whoami = "1.6.1" diff --git a/src-tauri/database/src/db.rs b/src-tauri/database/src/db.rs new file mode 100644 index 0000000..313eb80 --- /dev/null +++ b/src-tauri/database/src/db.rs @@ -0,0 +1,45 @@ +use std::{ + path::PathBuf, + sync::{Arc, LazyLock}, +}; + +use rustbreak::{DeSerError, DeSerializer}; +use serde::{Serialize, de::DeserializeOwned}; + +use crate::interface::{DatabaseImpls, DatabaseInterface}; + +pub static DB: LazyLock = LazyLock::new(DatabaseInterface::set_up_database); + +#[cfg(not(debug_assertions))] +static DATA_ROOT_PREFIX: &str = "drop"; +#[cfg(debug_assertions)] +static DATA_ROOT_PREFIX: &str = "drop-debug"; + +pub static DATA_ROOT_DIR: LazyLock> = LazyLock::new(|| { + Arc::new( + dirs::data_dir() + .expect("Failed to get data dir") + .join(DATA_ROOT_PREFIX), + ) +}); + +// Custom JSON serializer to support everything we need +#[derive(Debug, Default, Clone)] +pub struct DropDatabaseSerializer; + +impl DeSerializer + for DropDatabaseSerializer +{ + fn serialize(&self, val: &T) -> rustbreak::error::DeSerResult> { + native_model::encode(val).map_err(|e| DeSerError::Internal(e.to_string())) + } + + fn deserialize(&self, mut s: R) -> rustbreak::error::DeSerResult { + let mut buf = Vec::new(); + s.read_to_end(&mut buf) + .map_err(|e| rustbreak::error::DeSerError::Other(e.into()))?; + let (val, _version) = + native_model::decode(buf).map_err(|e| DeSerError::Internal(e.to_string()))?; + Ok(val) + } +} diff --git a/src-tauri/src/database/debug.rs b/src-tauri/database/src/debug.rs similarity index 100% rename from src-tauri/src/database/debug.rs rename to src-tauri/database/src/debug.rs diff --git a/src-tauri/src/database/db.rs b/src-tauri/database/src/interface.rs similarity index 80% rename from src-tauri/src/database/db.rs rename to src-tauri/database/src/interface.rs index e5d0905..969c93d 100644 --- a/src-tauri/src/database/db.rs +++ b/src-tauri/database/src/interface.rs @@ -3,53 +3,18 @@ use std::{ mem::ManuallyDrop, ops::{Deref, DerefMut}, path::PathBuf, - sync::{Arc, LazyLock, RwLockReadGuard, RwLockWriteGuard}, + sync::{RwLockReadGuard, RwLockWriteGuard}, }; use chrono::Utc; use log::{debug, error, info, warn}; -use rustbreak::{DeSerError, DeSerializer, PathDatabase, RustbreakError}; -use serde::{Serialize, de::DeserializeOwned}; +use rustbreak::{PathDatabase, RustbreakError}; use url::Url; -use crate::DB; - -use super::models::data::Database; - -#[cfg(not(debug_assertions))] -static DATA_ROOT_PREFIX: &'static str = "drop"; -#[cfg(debug_assertions)] -static DATA_ROOT_PREFIX: &str = "drop-debug"; - -pub static DATA_ROOT_DIR: LazyLock> = LazyLock::new(|| { - Arc::new( - dirs::data_dir() - .expect("Failed to get data dir") - .join(DATA_ROOT_PREFIX), - ) -}); - -// Custom JSON serializer to support everything we need -#[derive(Debug, Default, Clone)] -pub struct DropDatabaseSerializer; - -impl DeSerializer - for DropDatabaseSerializer -{ - fn serialize(&self, val: &T) -> rustbreak::error::DeSerResult> { - native_model::encode(val) - .map_err(|e| DeSerError::Internal(e.to_string())) - } - - fn deserialize(&self, mut s: R) -> rustbreak::error::DeSerResult { - let mut buf = Vec::new(); - s.read_to_end(&mut buf) - .map_err(|e| rustbreak::error::DeSerError::Other(e.into()))?; - let (val, _version) = native_model::decode(buf) - .map_err(|e| DeSerError::Internal(e.to_string()))?; - Ok(val) - } -} +use crate::{ + db::{DATA_ROOT_DIR, DB, DropDatabaseSerializer}, + models::data::Database, +}; pub type DatabaseInterface = rustbreak::Database; diff --git a/src-tauri/database/src/lib.rs b/src-tauri/database/src/lib.rs new file mode 100644 index 0000000..df8b27e --- /dev/null +++ b/src-tauri/database/src/lib.rs @@ -0,0 +1,14 @@ +#![feature(nonpoison_rwlock)] + +pub mod db; +pub mod debug; +pub mod interface; +pub mod models; +pub mod platform; + +pub use db::DB; +pub use interface::{borrow_db_checked, borrow_db_mut_checked}; +pub use models::data::{ + ApplicationTransientStatus, Database, DatabaseApplications, DatabaseAuth, DownloadType, + DownloadableMetadata, GameDownloadStatus, GameVersion, Settings, +}; diff --git a/src-tauri/src/database/models.rs b/src-tauri/database/src/models.rs similarity index 94% rename from src-tauri/src/database/models.rs rename to src-tauri/database/src/models.rs index 848169a..7877886 100644 --- a/src-tauri/src/database/models.rs +++ b/src-tauri/database/src/models.rs @@ -4,7 +4,7 @@ pub mod data { use native_model::native_model; use serde::{Deserialize, Serialize}; - // NOTE: Within each version, you should NEVER use these types. + // NOTE: Within each version, you should NEVER use these types. // Declare it using the actual version that it is from, i.e. v1::Settings rather than just Settings from here pub type GameVersion = v1::GameVersion; @@ -37,17 +37,18 @@ pub mod data { } mod v1 { - use crate::process::process_manager::Platform; use serde_with::serde_as; use std::{collections::HashMap, path::PathBuf}; + use crate::platform::Platform; + use super::{Deserialize, Serialize, native_model}; fn default_template() -> String { "{}".to_owned() } - #[derive(Serialize, Deserialize, Clone, Debug)] + #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] #[serde(rename_all = "camelCase")] #[native_model(id = 2, version = 1, with = native_model::rmp_serde_1_3::RmpSerde)] pub struct GameVersion { @@ -190,9 +191,7 @@ pub mod data { use serde_with::serde_as; - use super::{ - Deserialize, Serialize, native_model, v1, - }; + use super::{Deserialize, Serialize, native_model, v1}; #[native_model(id = 1, version = 2, with = native_model::rmp_serde_1_3::RmpSerde, from = v1::Database)] #[derive(Serialize, Deserialize, Clone, Default)] @@ -276,12 +275,13 @@ pub mod data { pub install_dirs: Vec, // Guaranteed to exist if the game also exists in the app state map pub game_statuses: HashMap, - + pub game_versions: HashMap>, pub installed_game_version: HashMap, #[serde(skip)] - pub transient_statuses: HashMap, + pub transient_statuses: + HashMap, } impl From for DatabaseApplications { fn from(value: v1::DatabaseApplications) -> Self { @@ -302,10 +302,7 @@ pub mod data { mod v3 { use std::path::PathBuf; - use super::{ - Deserialize, Serialize, - native_model, v2, v1, - }; + use super::{Deserialize, Serialize, native_model, v1, v2}; #[native_model(id = 1, version = 3, with = native_model::rmp_serde_1_3::RmpSerde, from = v2::Database)] #[derive(Serialize, Deserialize, Clone, Default)] pub struct Database { @@ -357,6 +354,20 @@ pub mod data { compat_info: None, } } - + } + impl DatabaseAuth { + pub fn new( + private: String, + cert: String, + client_id: String, + web_token: Option, + ) -> Self { + Self { + private, + cert, + client_id, + web_token, + } + } } } diff --git a/src-tauri/database/src/platform.rs b/src-tauri/database/src/platform.rs new file mode 100644 index 0000000..10c95f4 --- /dev/null +++ b/src-tauri/database/src/platform.rs @@ -0,0 +1,46 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Eq, Hash, PartialEq, Serialize, Deserialize, Clone, Copy, Debug)] +pub enum Platform { + Windows, + Linux, + MacOs, +} + +impl Platform { + #[cfg(target_os = "windows")] + pub const HOST: Platform = Self::Windows; + #[cfg(target_os = "macos")] + pub const HOST: Platform = Self::MacOs; + #[cfg(target_os = "linux")] + pub const HOST: Platform = Self::Linux; + + pub fn is_case_sensitive(&self) -> bool { + match self { + Self::Windows | Self::MacOs => false, + Self::Linux => true, + } + } +} + +impl From<&str> for Platform { + fn from(value: &str) -> Self { + match value.to_lowercase().trim() { + "windows" => Self::Windows, + "linux" => Self::Linux, + "mac" | "macos" => Self::MacOs, + _ => unimplemented!(), + } + } +} + +impl From for Platform { + fn from(value: whoami::Platform) -> Self { + match value { + whoami::Platform::Windows => Platform::Windows, + whoami::Platform::Linux => Platform::Linux, + whoami::Platform::MacOS => Platform::MacOs, + platform => unimplemented!("Playform {} is not supported", platform), + } + } +} diff --git a/src-tauri/download_manager/Cargo.toml b/src-tauri/download_manager/Cargo.toml new file mode 100644 index 0000000..56a9e93 --- /dev/null +++ b/src-tauri/download_manager/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "download_manager" +version = "0.1.0" +edition = "2024" + +[dependencies] +atomic-instant-full = "0.1.0" +database = { version = "0.1.0", path = "../database" } +humansize = "2.1.3" +log = "0.4.28" +parking_lot = "0.12.5" +remote = { version = "0.1.0", path = "../remote" } +serde = "1.0.228" +serde_with = "3.15.0" +tauri = "2.8.5" +throttle_my_fn = "0.2.6" +utils = { version = "0.1.0", path = "../utils" } diff --git a/src-tauri/src/download_manager/download_manager_builder.rs b/src-tauri/download_manager/src/download_manager_builder.rs similarity index 96% rename from src-tauri/src/download_manager/download_manager_builder.rs rename to src-tauri/download_manager/src/download_manager_builder.rs index 68016f5..3504773 100644 --- a/src-tauri/src/download_manager/download_manager_builder.rs +++ b/src-tauri/download_manager/src/download_manager_builder.rs @@ -7,11 +7,15 @@ use std::{ thread::{JoinHandle, spawn}, }; +use database::DownloadableMetadata; use log::{debug, error, info, warn}; -use tauri::{AppHandle, Emitter}; +use tauri::AppHandle; +use utils::{app_emit, lock, send}; use crate::{ - app_emit, database::models::data::DownloadableMetadata, download_manager::download_manager_frontend::DownloadStatus, error::application_download_error::ApplicationDownloadError, games::library::{QueueUpdateEvent, QueueUpdateEventQueueData, StatsUpdateEvent}, lock, send + download_manager_frontend::DownloadStatus, + error::ApplicationDownloadError, + frontend_updates::{QueueUpdateEvent, QueueUpdateEventQueueData, StatsUpdateEvent}, }; use super::{ @@ -288,7 +292,10 @@ impl DownloadManagerBuilder { if validate_result { download_agent.on_complete(&app_handle); - send!(sender, DownloadManagerSignal::Completed(download_agent.metadata())); + send!( + sender, + DownloadManagerSignal::Completed(download_agent.metadata()) + ); send!(sender, DownloadManagerSignal::UpdateUIQueue); return; } @@ -369,7 +376,7 @@ impl DownloadManagerBuilder { fn push_ui_stats_update(&self, kbs: usize, time: usize) { let event_data = StatsUpdateEvent { speed: kbs, time }; - app_emit!(self.app_handle, "update_stats", event_data); + app_emit!(&self.app_handle, "update_stats", event_data); } fn push_ui_queue_update(&self) { let queue = &self.download_queue.read(); @@ -388,6 +395,6 @@ impl DownloadManagerBuilder { .collect(); let event_data = QueueUpdateEvent { queue: queue_objs }; - app_emit!(self.app_handle, "update_queue", event_data); + app_emit!(&self.app_handle, "update_queue", event_data); } } diff --git a/src-tauri/src/download_manager/download_manager_frontend.rs b/src-tauri/download_manager/src/download_manager_frontend.rs similarity index 93% rename from src-tauri/src/download_manager/download_manager_frontend.rs rename to src-tauri/download_manager/src/download_manager_frontend.rs index eee9985..fe50c55 100644 --- a/src-tauri/src/download_manager/download_manager_frontend.rs +++ b/src-tauri/download_manager/src/download_manager_frontend.rs @@ -9,13 +9,12 @@ use std::{ thread::JoinHandle, }; +use database::DownloadableMetadata; use log::{debug, info}; use serde::Serialize; +use utils::{lock, send}; -use crate::{ - database::models::data::DownloadableMetadata, - error::application_download_error::ApplicationDownloadError, lock, send, -}; +use crate::error::ApplicationDownloadError; use super::{ download_manager_builder::{CurrentProgressObject, DownloadAgent}, @@ -80,6 +79,7 @@ pub enum DownloadStatus { /// The actual download queue may be accessed through the .`edit()` function, /// which provides raw access to the underlying queue. /// THIS EDITING IS BLOCKING!!! +#[derive(Debug)] pub struct DownloadManager { terminator: Mutex>>>, download_queue: Queue, @@ -124,8 +124,11 @@ impl DownloadManager { } pub fn rearrange_string(&self, meta: &DownloadableMetadata, new_index: usize) { let mut queue = self.edit(); - let current_index = get_index_from_id(&mut queue, meta).expect("Failed to get meta index from id"); - let to_move = queue.remove(current_index).expect("Failed to remove meta at index from queue"); + let current_index = + get_index_from_id(&mut queue, meta).expect("Failed to get meta index from id"); + let to_move = queue + .remove(current_index) + .expect("Failed to remove meta at index from queue"); queue.insert(new_index, to_move); send!(self.command_sender, DownloadManagerSignal::UpdateUIQueue); } diff --git a/src-tauri/src/download_manager/downloadable.rs b/src-tauri/download_manager/src/downloadable.rs similarity index 89% rename from src-tauri/src/download_manager/downloadable.rs rename to src-tauri/download_manager/src/downloadable.rs index 547daf8..0740ff3 100644 --- a/src-tauri/src/download_manager/downloadable.rs +++ b/src-tauri/download_manager/src/downloadable.rs @@ -1,11 +1,9 @@ use std::sync::Arc; +use database::DownloadableMetadata; use tauri::AppHandle; -use crate::{ - database::models::data::DownloadableMetadata, - error::application_download_error::ApplicationDownloadError, -}; +use crate::error::ApplicationDownloadError; use super::{ download_manager_frontend::DownloadStatus, diff --git a/src-tauri/src/error/application_download_error.rs b/src-tauri/download_manager/src/error.rs similarity index 56% rename from src-tauri/src/error/application_download_error.rs rename to src-tauri/download_manager/src/error.rs index 86b09c3..21201e8 100644 --- a/src-tauri/src/error/application_download_error.rs +++ b/src-tauri/download_manager/src/error.rs @@ -1,12 +1,36 @@ +use humansize::{BINARY, format_size}; use std::{ fmt::{Display, Formatter}, - io, sync::Arc, + io, + sync::{Arc, mpsc::SendError}, }; +use remote::error::RemoteAccessError; use serde_with::SerializeDisplay; -use humansize::{format_size, BINARY}; -use super::remote_access_error::RemoteAccessError; +#[derive(SerializeDisplay)] +pub enum DownloadManagerError { + IOError(io::Error), + SignalError(SendError), +} +impl Display for DownloadManagerError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + DownloadManagerError::IOError(error) => write!(f, "{error}"), + DownloadManagerError::SignalError(send_error) => write!(f, "{send_error}"), + } + } +} +impl From> for DownloadManagerError { + fn from(value: SendError) -> Self { + DownloadManagerError::SignalError(value) + } +} +impl From for DownloadManagerError { + fn from(value: io::Error) -> Self { + DownloadManagerError::IOError(value) + } +} // TODO: Rename / separate from downloads #[derive(Debug, SerializeDisplay)] @@ -24,7 +48,9 @@ pub enum ApplicationDownloadError { impl Display for ApplicationDownloadError { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { - ApplicationDownloadError::NotInitialized => write!(f, "Download not initalized, did something go wrong?"), + ApplicationDownloadError::NotInitialized => { + write!(f, "Download not initalized, did something go wrong?") + } ApplicationDownloadError::DiskFull(required, available) => write!( f, "Game requires {}, {} remaining left on disk.", @@ -40,10 +66,9 @@ impl Display for ApplicationDownloadError { write!(f, "checksum failed to validate for download") } ApplicationDownloadError::IoError(error) => write!(f, "io error: {error}"), - ApplicationDownloadError::DownloadError(error) => write!( - f, - "Download failed with error {error:?}" - ), + ApplicationDownloadError::DownloadError(error) => { + write!(f, "Download failed with error {error:?}") + } } } } @@ -52,4 +77,4 @@ impl From for ApplicationDownloadError { fn from(value: io::Error) -> Self { ApplicationDownloadError::IoError(Arc::new(value)) } -} \ No newline at end of file +} diff --git a/src-tauri/download_manager/src/frontend_updates.rs b/src-tauri/download_manager/src/frontend_updates.rs new file mode 100644 index 0000000..eb0a01b --- /dev/null +++ b/src-tauri/download_manager/src/frontend_updates.rs @@ -0,0 +1,24 @@ +use database::DownloadableMetadata; +use serde::Serialize; + +use crate::download_manager_frontend::DownloadStatus; + +#[derive(Serialize, Clone)] +pub struct QueueUpdateEventQueueData { + pub meta: DownloadableMetadata, + pub status: DownloadStatus, + pub progress: f64, + pub current: usize, + pub max: usize, +} + +#[derive(Serialize, Clone)] +pub struct QueueUpdateEvent { + pub queue: Vec, +} + +#[derive(Serialize, Clone)] +pub struct StatsUpdateEvent { + pub speed: usize, + pub time: usize, +} diff --git a/src-tauri/download_manager/src/lib.rs b/src-tauri/download_manager/src/lib.rs new file mode 100644 index 0000000..e4e9599 --- /dev/null +++ b/src-tauri/download_manager/src/lib.rs @@ -0,0 +1,44 @@ +#![feature(duration_millis_float)] +#![feature(nonpoison_mutex)] +#![feature(sync_nonpoison)] + +use std::{ops::Deref, sync::OnceLock}; + +use tauri::AppHandle; + +use crate::{ + download_manager_builder::DownloadManagerBuilder, download_manager_frontend::DownloadManager, +}; + +pub mod download_manager_builder; +pub mod download_manager_frontend; +pub mod downloadable; +pub mod error; +pub mod frontend_updates; +pub mod util; + +pub static DOWNLOAD_MANAGER: DownloadManagerWrapper = DownloadManagerWrapper::new(); + +pub struct DownloadManagerWrapper(OnceLock); +impl DownloadManagerWrapper { + const fn new() -> Self { + DownloadManagerWrapper(OnceLock::new()) + } + pub fn init(app_handle: AppHandle) { + DOWNLOAD_MANAGER + .0 + .set(DownloadManagerBuilder::build(app_handle)) + .expect("Failed to initialise download manager"); + } +} + +impl Deref for DownloadManagerWrapper { + type Target = DownloadManager; + + fn deref(&self) -> &Self::Target { + match self.0.get() { + Some(download_manager) => download_manager, + None => unreachable!("Download manager should always be initialised"), + } + } +} diff --git a/src-tauri/src/download_manager/util/download_thread_control_flag.rs b/src-tauri/download_manager/src/util/download_thread_control_flag.rs similarity index 88% rename from src-tauri/src/download_manager/util/download_thread_control_flag.rs rename to src-tauri/download_manager/src/util/download_thread_control_flag.rs index 222f5e8..07ce57b 100644 --- a/src-tauri/src/download_manager/util/download_thread_control_flag.rs +++ b/src-tauri/download_manager/src/util/download_thread_control_flag.rs @@ -1,6 +1,6 @@ use std::sync::{ - atomic::{AtomicBool, Ordering}, Arc, + atomic::{AtomicBool, Ordering}, }; #[derive(PartialEq, Eq, PartialOrd, Ord)] @@ -22,7 +22,11 @@ impl From for bool { /// false => Stop impl From for DownloadThreadControlFlag { fn from(value: bool) -> Self { - if value { DownloadThreadControlFlag::Go } else { DownloadThreadControlFlag::Stop } + if value { + DownloadThreadControlFlag::Go + } else { + DownloadThreadControlFlag::Stop + } } } diff --git a/src-tauri/src/download_manager/util/mod.rs b/src-tauri/download_manager/src/util/mod.rs similarity index 100% rename from src-tauri/src/download_manager/util/mod.rs rename to src-tauri/download_manager/src/util/mod.rs diff --git a/src-tauri/src/download_manager/util/progress_object.rs b/src-tauri/download_manager/src/util/progress_object.rs similarity index 93% rename from src-tauri/src/download_manager/util/progress_object.rs rename to src-tauri/download_manager/src/util/progress_object.rs index ff97d0e..9f61c5d 100644 --- a/src-tauri/src/download_manager/util/progress_object.rs +++ b/src-tauri/download_manager/src/util/progress_object.rs @@ -9,12 +9,13 @@ use std::{ use atomic_instant_full::AtomicInstant; use throttle_my_fn::throttle; +use utils::{lock, send}; -use crate::{download_manager::download_manager_frontend::DownloadManagerSignal, lock, send}; +use crate::download_manager_frontend::DownloadManagerSignal; use super::rolling_progress_updates::RollingProgressWindow; -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct ProgressObject { max: Arc>, progress_instances: Arc>>>, @@ -116,7 +117,9 @@ pub fn calculate_update(progress: &ProgressObject) { let last_update_time = progress .last_update_time .swap(Instant::now(), Ordering::SeqCst); - let time_since_last_update = Instant::now().duration_since(last_update_time).as_millis_f64(); + let time_since_last_update = Instant::now() + .duration_since(last_update_time) + .as_millis_f64(); let current_bytes_downloaded = progress.sum(); let max = progress.get_max(); @@ -124,7 +127,8 @@ pub fn calculate_update(progress: &ProgressObject) { .bytes_last_update .swap(current_bytes_downloaded, Ordering::Acquire); - let bytes_since_last_update = current_bytes_downloaded.saturating_sub(bytes_at_last_update) as f64; + let bytes_since_last_update = + current_bytes_downloaded.saturating_sub(bytes_at_last_update) as f64; let kilobytes_per_second = bytes_since_last_update / time_since_last_update; diff --git a/src-tauri/src/download_manager/util/queue.rs b/src-tauri/download_manager/src/util/queue.rs similarity index 92% rename from src-tauri/src/download_manager/util/queue.rs rename to src-tauri/download_manager/src/util/queue.rs index c81a406..3bd9581 100644 --- a/src-tauri/src/download_manager/util/queue.rs +++ b/src-tauri/download_manager/src/util/queue.rs @@ -3,9 +3,10 @@ use std::{ sync::{Arc, Mutex, MutexGuard}, }; -use crate::{database::models::data::DownloadableMetadata, lock}; +use database::DownloadableMetadata; +use utils::lock; -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct Queue { inner: Arc>>, } diff --git a/src-tauri/src/download_manager/util/rolling_progress_updates.rs b/src-tauri/download_manager/src/util/rolling_progress_updates.rs similarity index 90% rename from src-tauri/src/download_manager/util/rolling_progress_updates.rs rename to src-tauri/download_manager/src/util/rolling_progress_updates.rs index 868b200..df4f97c 100644 --- a/src-tauri/src/download_manager/util/rolling_progress_updates.rs +++ b/src-tauri/download_manager/src/util/rolling_progress_updates.rs @@ -3,11 +3,17 @@ use std::sync::{ atomic::{AtomicUsize, Ordering}, }; -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct RollingProgressWindow { window: Arc<[AtomicUsize; S]>, current: Arc, } +impl Default for RollingProgressWindow { + fn default() -> Self { + Self::new() + } +} + impl RollingProgressWindow { pub fn new() -> Self { Self { @@ -31,7 +37,7 @@ impl RollingProgressWindow { .collect::>(); let amount = valid.len(); let sum = valid.into_iter().sum::(); - + sum / amount } pub fn reset(&self) { diff --git a/src-tauri/games/Cargo.toml b/src-tauri/games/Cargo.toml new file mode 100644 index 0000000..c50507b --- /dev/null +++ b/src-tauri/games/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "games" +version = "0.1.0" +edition = "2024" + +[dependencies] +atomic-instant-full = "0.1.0" +bitcode = "0.6.7" +boxcar = "0.2.14" +database = { version = "0.1.0", path = "../database" } +download_manager = { version = "0.1.0", path = "../download_manager" } +hex = "0.4.3" +log = "0.4.28" +md5 = "0.8.0" +rayon = "1.11.0" +remote = { version = "0.1.0", path = "../remote" } +reqwest = "0.12.23" +rustix = "1.1.2" +serde = { version = "1.0.228", features = ["derive"] } +serde_with = "3.15.0" +sysinfo = "0.37.2" +tauri = "2.8.5" +throttle_my_fn = "0.2.6" +utils = { version = "0.1.0", path = "../utils" } +native_model = { version = "0.6.4", features = ["rmp_serde_1_3"], git = "https://github.com/Drop-OSS/native_model.git"} +serde_json = "1.0.145" diff --git a/src-tauri/src/games/collections/collection.rs b/src-tauri/games/src/collections/collection.rs similarity index 94% rename from src-tauri/src/games/collections/collection.rs rename to src-tauri/games/src/collections/collection.rs index ea29474..2eef9b2 100644 --- a/src-tauri/src/games/collections/collection.rs +++ b/src-tauri/games/src/collections/collection.rs @@ -1,7 +1,7 @@ use bitcode::{Decode, Encode}; use serde::{Deserialize, Serialize}; -use crate::games::library::Game; +use crate::library::Game; pub type Collections = Vec; diff --git a/src-tauri/src/games/collections/mod.rs b/src-tauri/games/src/collections/mod.rs similarity index 52% rename from src-tauri/src/games/collections/mod.rs rename to src-tauri/games/src/collections/mod.rs index b837592..a3907ad 100644 --- a/src-tauri/src/games/collections/mod.rs +++ b/src-tauri/games/src/collections/mod.rs @@ -1,2 +1 @@ pub mod collection; -pub mod commands; diff --git a/src-tauri/src/games/downloads/download_agent.rs b/src-tauri/games/src/downloads/download_agent.rs similarity index 94% rename from src-tauri/src/games/downloads/download_agent.rs rename to src-tauri/games/src/downloads/download_agent.rs index c8b9b64..1d54ca0 100644 --- a/src-tauri/src/games/downloads/download_agent.rs +++ b/src-tauri/games/src/downloads/download_agent.rs @@ -1,28 +1,20 @@ -use crate::auth::generate_authorization_header; -use crate::database::db::{borrow_db_checked, borrow_db_mut_checked}; -use crate::database::models::data::{ - ApplicationTransientStatus, DownloadType, DownloadableMetadata, +use database::{ + ApplicationTransientStatus, DownloadType, DownloadableMetadata, borrow_db_checked, + borrow_db_mut_checked, }; -use crate::download_manager::download_manager_frontend::{DownloadManagerSignal, DownloadStatus}; -use crate::download_manager::downloadable::Downloadable; -use crate::download_manager::util::download_thread_control_flag::{ +use download_manager::download_manager_frontend::{DownloadManagerSignal, DownloadStatus}; +use download_manager::downloadable::Downloadable; +use download_manager::error::ApplicationDownloadError; +use download_manager::util::download_thread_control_flag::{ DownloadThreadControl, DownloadThreadControlFlag, }; -use crate::download_manager::util::progress_object::{ProgressHandle, ProgressObject}; -use crate::error::application_download_error::ApplicationDownloadError; -use crate::error::remote_access_error::RemoteAccessError; -use crate::games::downloads::manifest::{ - DownloadBucket, DownloadContext, DownloadDrop, DropManifest, DropValidateContext, ManifestBody, -}; -use crate::games::downloads::validate::validate_game_chunk; -use crate::games::library::{on_game_complete, push_game_update, set_partially_installed}; -use crate::games::state::GameStatusManager; -use crate::process::utils::get_disk_available; -use crate::remote::requests::generate_url; -use crate::remote::utils::{DROP_CLIENT_ASYNC, DROP_CLIENT_SYNC}; -use crate::{app_emit, lock, send}; +use download_manager::util::progress_object::{ProgressHandle, ProgressObject}; use log::{debug, error, info, warn}; use rayon::ThreadPoolBuilder; +use remote::auth::generate_authorization_header; +use remote::error::RemoteAccessError; +use remote::requests::generate_url; +use remote::utils::{DROP_CLIENT_ASYNC, DROP_CLIENT_SYNC}; use std::collections::{HashMap, HashSet}; use std::fs::{OpenOptions, create_dir_all}; use std::io; @@ -30,11 +22,20 @@ use std::path::{Path, PathBuf}; use std::sync::mpsc::Sender; use std::sync::{Arc, Mutex}; use std::time::Instant; -use tauri::{AppHandle, Emitter}; +use tauri::AppHandle; +use utils::{app_emit, lock, send}; #[cfg(target_os = "linux")] use rustix::fs::{FallocateFlags, fallocate}; +use crate::downloads::manifest::{ + DownloadBucket, DownloadContext, DownloadDrop, DropManifest, DropValidateContext, ManifestBody, +}; +use crate::downloads::utils::get_disk_available; +use crate::downloads::validate::validate_game_chunk; +use crate::library::{on_game_complete, push_game_update, set_partially_installed}; +use crate::state::GameStatusManager; + use super::download_logic::download_game_bucket; use super::drop_data::DropData; @@ -103,8 +104,7 @@ impl GameDownloadAgent { result.ensure_manifest_exists().await?; - let required_space = lock!(result - .manifest) + let required_space = lock!(result.manifest) .as_ref() .unwrap() .values() @@ -453,9 +453,13 @@ impl GameDownloadAgent { let sender = self.sender.clone(); - let download_context = download_contexts - .get(&bucket.version) - .unwrap_or_else(|| panic!("Could not get bucket version {}. Corrupted state.", bucket.version)); + let download_context = + download_contexts.get(&bucket.version).unwrap_or_else(|| { + panic!( + "Could not get bucket version {}. Corrupted state.", + bucket.version + ) + }); scope.spawn(move |_| { // 3 attempts @@ -693,7 +697,10 @@ impl Downloadable for GameDownloadAgent { Ok(_) => {} Err(e) => { error!("could not mark game as complete: {e}"); - send!(self.sender, DownloadManagerSignal::Error(ApplicationDownloadError::DownloadError(e))); + send!( + self.sender, + DownloadManagerSignal::Error(ApplicationDownloadError::DownloadError(e)) + ); } } } diff --git a/src-tauri/src/games/downloads/download_logic.rs b/src-tauri/games/src/downloads/download_logic.rs similarity index 91% rename from src-tauri/src/games/downloads/download_logic.rs rename to src-tauri/games/src/downloads/download_logic.rs index afc9389..2b40ac7 100644 --- a/src-tauri/src/games/downloads/download_logic.rs +++ b/src-tauri/games/src/downloads/download_logic.rs @@ -1,18 +1,3 @@ -use crate::download_manager::util::download_thread_control_flag::{ - DownloadThreadControl, DownloadThreadControlFlag, -}; -use crate::download_manager::util::progress_object::ProgressHandle; -use crate::error::application_download_error::ApplicationDownloadError; -use crate::error::drop_server_error::DropServerError; -use crate::error::remote_access_error::RemoteAccessError; -use crate::games::downloads::manifest::{ChunkBody, DownloadBucket, DownloadContext, DownloadDrop}; -use crate::remote::auth::generate_authorization_header; -use crate::remote::requests::generate_url; -use crate::remote::utils::DROP_CLIENT_SYNC; -use log::{debug, info, warn}; -use md5::{Context, Digest}; -use reqwest::blocking::Response; - use std::fs::{Permissions, set_permissions}; use std::io::Read; #[cfg(unix)] @@ -25,6 +10,21 @@ use std::{ path::PathBuf, }; +use download_manager::error::ApplicationDownloadError; +use download_manager::util::download_thread_control_flag::{ + DownloadThreadControl, DownloadThreadControlFlag, +}; +use download_manager::util::progress_object::ProgressHandle; +use log::{debug, info, warn}; +use md5::{Context, Digest}; +use remote::auth::generate_authorization_header; +use remote::error::{DropServerError, RemoteAccessError}; +use remote::requests::generate_url; +use remote::utils::DROP_CLIENT_SYNC; +use reqwest::blocking::Response; + +use crate::downloads::manifest::{ChunkBody, DownloadBucket, DownloadContext, DownloadDrop}; + static MAX_PACKET_LENGTH: usize = 4096 * 4; static BUMP_SIZE: usize = 4096 * 16; @@ -49,7 +49,7 @@ impl DropWriter { fn finish(mut self) -> io::Result { self.flush()?; - Ok(self.hasher.compute()) + Ok(self.hasher.finalize()) } } // Write automatically pushes to file and hasher @@ -118,9 +118,12 @@ impl<'a> DropDownloadPipeline<'a, Response, File> { let mut last_bump = 0; loop { let size = MAX_PACKET_LENGTH.min(remaining); - let size = self.source.read(&mut copy_buffer[0..size]).inspect_err(|_| { - info!("got error from {}", drop.filename); - })?; + let size = self + .source + .read(&mut copy_buffer[0..size]) + .inspect_err(|_| { + info!("got error from {}", drop.filename); + })?; remaining -= size; last_bump += size; diff --git a/src-tauri/src/games/downloads/drop_data.rs b/src-tauri/games/src/downloads/drop_data.rs similarity index 90% rename from src-tauri/src/games/downloads/drop_data.rs rename to src-tauri/games/src/downloads/drop_data.rs index d077f46..0c952cf 100644 --- a/src-tauri/src/games/downloads/drop_data.rs +++ b/src-tauri/games/src/downloads/drop_data.rs @@ -1,11 +1,13 @@ use std::{ - collections::HashMap, fs::File, io::{self, Read, Write}, path::{Path, PathBuf} + collections::HashMap, + fs::File, + io::{self, Read, Write}, + path::{Path, PathBuf}, }; use log::error; use native_model::{Decode, Encode}; - -use crate::lock; +use utils::lock; pub type DropData = v1::DropData; @@ -78,7 +80,10 @@ impl DropData { } } pub fn set_contexts(&self, completed_contexts: &[(String, bool)]) { - *lock!(self.contexts) = completed_contexts.iter().map(|s| (s.0.clone(), s.1)).collect(); + *lock!(self.contexts) = completed_contexts + .iter() + .map(|s| (s.0.clone(), s.1)) + .collect(); } pub fn set_context(&self, context: String, state: bool) { lock!(self.contexts).entry(context).insert_entry(state); diff --git a/src-tauri/games/src/downloads/error.rs b/src-tauri/games/src/downloads/error.rs new file mode 100644 index 0000000..c7f3a2b --- /dev/null +++ b/src-tauri/games/src/downloads/error.rs @@ -0,0 +1,29 @@ +use std::fmt::Display; + +use serde_with::SerializeDisplay; + +#[derive(SerializeDisplay)] +pub enum LibraryError { + MetaNotFound(String), + VersionNotFound(String), +} +impl Display for LibraryError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{}", + match self { + LibraryError::MetaNotFound(id) => { + format!( + "Could not locate any installed version of game ID {id} in the database" + ) + } + LibraryError::VersionNotFound(game_id) => { + format!( + "Could not locate any installed version for game id {game_id} in the database" + ) + } + } + ) + } +} diff --git a/src-tauri/src/games/downloads/manifest.rs b/src-tauri/games/src/downloads/manifest.rs similarity index 100% rename from src-tauri/src/games/downloads/manifest.rs rename to src-tauri/games/src/downloads/manifest.rs diff --git a/src-tauri/src/games/downloads/mod.rs b/src-tauri/games/src/downloads/mod.rs similarity index 76% rename from src-tauri/src/games/downloads/mod.rs rename to src-tauri/games/src/downloads/mod.rs index dc9e277..7cd01d0 100644 --- a/src-tauri/src/games/downloads/mod.rs +++ b/src-tauri/games/src/downloads/mod.rs @@ -1,6 +1,7 @@ -pub mod commands; pub mod download_agent; mod download_logic; pub mod drop_data; +pub mod error; mod manifest; +pub mod utils; pub mod validate; diff --git a/src-tauri/src/process/utils.rs b/src-tauri/games/src/downloads/utils.rs similarity index 71% rename from src-tauri/src/process/utils.rs rename to src-tauri/games/src/downloads/utils.rs index 41f9239..595c08d 100644 --- a/src-tauri/src/process/utils.rs +++ b/src-tauri/games/src/downloads/utils.rs @@ -1,10 +1,8 @@ -use std::{path::PathBuf, sync::Arc}; +use std::{io, path::PathBuf, sync::Arc}; -use futures_lite::io; +use download_manager::error::ApplicationDownloadError; use sysinfo::{Disk, DiskRefreshKind, Disks}; -use crate::error::application_download_error::ApplicationDownloadError; - pub fn get_disk_available(mount_point: PathBuf) -> Result { let disks = Disks::new_with_refreshed_list_specifics(DiskRefreshKind::nothing().with_storage()); @@ -21,7 +19,7 @@ pub fn get_disk_available(mount_point: PathBuf) -> Result Result { debug!( "Starting chunk validation {}, {}, {} #{}", - ctx.path.display(), ctx.index, ctx.offset, ctx.checksum + ctx.path.display(), + ctx.index, + ctx.offset, + ctx.checksum ); // If we're paused if control_flag.get() == DownloadThreadControlFlag::Stop { @@ -42,13 +45,12 @@ pub fn validate_game_chunk( let mut hasher = md5::Context::new(); - let completed = - validate_copy(&mut source, &mut hasher, ctx.length, control_flag, progress)?; + let completed = validate_copy(&mut source, &mut hasher, ctx.length, control_flag, progress)?; if !completed { return Ok(false); } - let res = hex::encode(hasher.compute().0); + let res = hex::encode(hasher.finalize().0); if res != ctx.checksum { return Ok(false); } diff --git a/src-tauri/src/games/mod.rs b/src-tauri/games/src/lib.rs similarity index 59% rename from src-tauri/src/games/mod.rs rename to src-tauri/games/src/lib.rs index 0d81d10..7cd794a 100644 --- a/src-tauri/src/games/mod.rs +++ b/src-tauri/games/src/lib.rs @@ -1,5 +1,7 @@ +#![feature(iterator_try_collect)] + pub mod collections; -pub mod commands; pub mod downloads; pub mod library; +pub mod scan; pub mod state; diff --git a/src-tauri/games/src/library.rs b/src-tauri/games/src/library.rs new file mode 100644 index 0000000..c58d3c0 --- /dev/null +++ b/src-tauri/games/src/library.rs @@ -0,0 +1,300 @@ +use bitcode::{Decode, Encode}; +use database::{ + ApplicationTransientStatus, Database, DownloadableMetadata, GameDownloadStatus, GameVersion, + borrow_db_checked, borrow_db_mut_checked, +}; +use log::{debug, error, warn}; +use remote::{ + auth::generate_authorization_header, error::RemoteAccessError, requests::generate_url, + utils::DROP_CLIENT_SYNC, +}; +use serde::{Deserialize, Serialize}; +use std::fs::remove_dir_all; +use std::thread::spawn; +use tauri::AppHandle; +use utils::app_emit; + +use crate::state::{GameStatusManager, GameStatusWithTransient}; + +#[derive(Serialize, Deserialize, Debug)] +pub struct FetchGameStruct { + game: Game, + status: GameStatusWithTransient, + version: Option, +} + +impl FetchGameStruct { + pub fn new(game: Game, status: GameStatusWithTransient, version: Option) -> Self { + Self { + game, + status, + version, + } + } +} + +#[derive(Serialize, Deserialize, Clone, Debug, Default, Encode, Decode)] +#[serde(rename_all = "camelCase")] +pub struct Game { + id: String, + m_name: String, + m_short_description: String, + m_description: String, + // mDevelopers + // mPublishers + m_icon_object_id: String, + m_banner_object_id: String, + m_cover_object_id: String, + m_image_library_object_ids: Vec, + m_image_carousel_object_ids: Vec, +} +impl Game { + pub fn id(&self) -> &String { + &self.id + } +} +#[derive(serde::Serialize, Clone)] +pub struct GameUpdateEvent { + pub game_id: String, + pub status: ( + Option, + Option, + ), + pub version: Option, +} + +/** + * Called by: + * - on_cancel, when cancelled, for obvious reasons + * - when downloading, so if drop unexpectedly quits, we can resume the download. hidden by the "Downloading..." transient state, though + * - when scanning, to import the game + */ +pub fn set_partially_installed( + meta: &DownloadableMetadata, + install_dir: String, + app_handle: Option<&AppHandle>, +) { + set_partially_installed_db(&mut borrow_db_mut_checked(), meta, install_dir, app_handle); +} + +pub fn set_partially_installed_db( + db_lock: &mut Database, + meta: &DownloadableMetadata, + install_dir: String, + app_handle: Option<&AppHandle>, +) { + db_lock.applications.transient_statuses.remove(meta); + db_lock.applications.game_statuses.insert( + meta.id.clone(), + GameDownloadStatus::PartiallyInstalled { + version_name: meta.version.as_ref().unwrap().clone(), + install_dir, + }, + ); + db_lock + .applications + .installed_game_version + .insert(meta.id.clone(), meta.clone()); + + if let Some(app_handle) = app_handle { + push_game_update( + app_handle, + &meta.id, + None, + GameStatusManager::fetch_state(&meta.id, db_lock), + ); + } +} + +pub fn uninstall_game_logic(meta: DownloadableMetadata, app_handle: &AppHandle) { + debug!("triggered uninstall for agent"); + let mut db_handle = borrow_db_mut_checked(); + db_handle + .applications + .transient_statuses + .insert(meta.clone(), ApplicationTransientStatus::Uninstalling {}); + + push_game_update( + app_handle, + &meta.id, + None, + GameStatusManager::fetch_state(&meta.id, &db_handle), + ); + + let previous_state = db_handle.applications.game_statuses.get(&meta.id).cloned(); + + let previous_state = if let Some(state) = previous_state { + state + } else { + warn!("uninstall job doesn't have previous state, failing silently"); + return; + }; + + if let Some((_, install_dir)) = match previous_state { + GameDownloadStatus::Installed { + version_name, + install_dir, + } => Some((version_name, install_dir)), + GameDownloadStatus::SetupRequired { + version_name, + install_dir, + } => Some((version_name, install_dir)), + GameDownloadStatus::PartiallyInstalled { + version_name, + install_dir, + } => Some((version_name, install_dir)), + _ => None, + } { + db_handle + .applications + .transient_statuses + .insert(meta.clone(), ApplicationTransientStatus::Uninstalling {}); + + drop(db_handle); + + let app_handle = app_handle.clone(); + spawn(move || { + if let Err(e) = remove_dir_all(install_dir) { + error!("{e}"); + } else { + let mut db_handle = borrow_db_mut_checked(); + db_handle.applications.transient_statuses.remove(&meta); + db_handle + .applications + .installed_game_version + .remove(&meta.id); + db_handle + .applications + .game_statuses + .insert(meta.id.clone(), GameDownloadStatus::Remote {}); + let _ = db_handle.applications.transient_statuses.remove(&meta); + + push_game_update( + &app_handle, + &meta.id, + None, + GameStatusManager::fetch_state(&meta.id, &db_handle), + ); + + debug!("uninstalled game id {}", &meta.id); + app_emit!(&app_handle, "update_library", ()); + } + }); + } else { + warn!("invalid previous state for uninstall, failing silently."); + } +} + +pub fn get_current_meta(game_id: &String) -> Option { + borrow_db_checked() + .applications + .installed_game_version + .get(game_id) + .cloned() +} + +pub fn on_game_complete( + meta: &DownloadableMetadata, + install_dir: String, + app_handle: &AppHandle, +) -> Result<(), RemoteAccessError> { + // Fetch game version information from remote + if meta.version.is_none() { + return Err(RemoteAccessError::GameNotFound(meta.id.clone())); + } + + let client = DROP_CLIENT_SYNC.clone(); + let response = generate_url( + &["/api/v1/client/game/version"], + &[ + ("id", &meta.id), + ("version", meta.version.as_ref().unwrap()), + ], + )?; + let response = client + .get(response) + .header("Authorization", generate_authorization_header()) + .send()?; + + let game_version: GameVersion = response.json()?; + + let mut handle = borrow_db_mut_checked(); + handle + .applications + .game_versions + .entry(meta.id.clone()) + .or_default() + .insert(meta.version.clone().unwrap(), game_version.clone()); + handle + .applications + .installed_game_version + .insert(meta.id.clone(), meta.clone()); + + drop(handle); + + let status = if game_version.setup_command.is_empty() { + GameDownloadStatus::Installed { + version_name: meta.version.clone().unwrap(), + install_dir, + } + } else { + GameDownloadStatus::SetupRequired { + version_name: meta.version.clone().unwrap(), + install_dir, + } + }; + + let mut db_handle = borrow_db_mut_checked(); + db_handle + .applications + .game_statuses + .insert(meta.id.clone(), status.clone()); + drop(db_handle); + app_emit!( + app_handle, + &format!("update_game/{}", meta.id), + GameUpdateEvent { + game_id: meta.id.clone(), + status: (Some(status), None), + version: Some(game_version), + } + ); + + Ok(()) +} + +pub fn push_game_update( + app_handle: &AppHandle, + game_id: &String, + version: Option, + status: GameStatusWithTransient, +) { + if let Some(GameDownloadStatus::Installed { .. } | GameDownloadStatus::SetupRequired { .. }) = + &status.0 + && version.is_none() + { + panic!("pushed game for installed game that doesn't have version information"); + } + + app_emit!( + app_handle, + &format!("update_game/{game_id}"), + GameUpdateEvent { + game_id: game_id.clone(), + status, + version, + } + ); +} + +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct FrontendGameOptions { + launch_string: String, +} + +impl FrontendGameOptions { + pub fn launch_string(&self) -> &String { + &self.launch_string + } +} diff --git a/src-tauri/src/database/scan.rs b/src-tauri/games/src/scan.rs similarity index 84% rename from src-tauri/src/database/scan.rs rename to src-tauri/games/src/scan.rs index 88ee32e..4a711fc 100644 --- a/src-tauri/src/database/scan.rs +++ b/src-tauri/games/src/scan.rs @@ -1,16 +1,11 @@ use std::fs; +use database::{DownloadType, DownloadableMetadata, borrow_db_mut_checked}; use log::warn; use crate::{ - database::{ - db::borrow_db_mut_checked, - models::data::{DownloadType, DownloadableMetadata}, - }, - games::{ - downloads::drop_data::{DropData, DROP_DATA_PATH}, - library::set_partially_installed_db, - }, + downloads::drop_data::{DROP_DATA_PATH, DropData}, + library::set_partially_installed_db, }; pub fn scan_install_dirs() { diff --git a/src-tauri/src/games/state.rs b/src-tauri/games/src/state.rs similarity index 95% rename from src-tauri/src/games/state.rs rename to src-tauri/games/src/state.rs index 9cffc6d..08ed228 100644 --- a/src-tauri/src/games/state.rs +++ b/src-tauri/games/src/state.rs @@ -1,4 +1,4 @@ -use crate::database::models::data::{ +use database::models::data::{ ApplicationTransientStatus, Database, DownloadType, DownloadableMetadata, GameDownloadStatus, }; @@ -19,7 +19,7 @@ impl GameStatusManager { version: None, }) .cloned(); - + let offline_state = database.applications.game_statuses.get(game_id).cloned(); if online_state.is_some() { diff --git a/src-tauri/process/Cargo.toml b/src-tauri/process/Cargo.toml new file mode 100644 index 0000000..d3d67a1 --- /dev/null +++ b/src-tauri/process/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "process" +version = "0.1.0" +edition = "2024" + +[dependencies] +chrono = "0.4.42" +client = { version = "0.1.0", path = "../client" } +database = { version = "0.1.0", path = "../database" } +dynfmt = "0.1.5" +games = { version = "0.1.0", path = "../games" } +log = "0.4.28" +page_size = "0.6.0" +serde = "1.0.228" +serde_with = "3.15.0" +shared_child = "1.1.1" +tauri = "2.8.5" +tauri-plugin-opener = "2.5.0" +utils = { version = "0.1.0", path = "../utils" } diff --git a/src-tauri/src/error/process_error.rs b/src-tauri/process/src/error.rs similarity index 74% rename from src-tauri/src/error/process_error.rs rename to src-tauri/process/src/error.rs index 6d5c36e..c196284 100644 --- a/src-tauri/src/error/process_error.rs +++ b/src-tauri/process/src/error.rs @@ -12,7 +12,8 @@ pub enum ProcessError { FormatError(String), // String errors supremacy InvalidPlatform, OpenerError(tauri_plugin_opener::Error), - InvalidArguments(String) + InvalidArguments(String), + FailedLaunch(String), } impl Display for ProcessError { @@ -26,8 +27,13 @@ impl Display for ProcessError { ProcessError::InvalidPlatform => "This game cannot be played on the current platform", ProcessError::FormatError(error) => &format!("Could not format template: {error:?}"), ProcessError::OpenerError(error) => &format!("Could not open directory: {error:?}"), - ProcessError::InvalidArguments(arguments) => &format!("Invalid arguments in command {arguments}"), - }; + ProcessError::InvalidArguments(arguments) => { + &format!("Invalid arguments in command {arguments}") + } + ProcessError::FailedLaunch(game_id) => { + &format!("Drop detected that the game {game_id} may have failed to launch properly") + } + }; write!(f, "{s}") } } diff --git a/src-tauri/src/process/format.rs b/src-tauri/process/src/format.rs similarity index 84% rename from src-tauri/src/process/format.rs rename to src-tauri/process/src/format.rs index 785746d..bc19ea3 100644 --- a/src-tauri/src/process/format.rs +++ b/src-tauri/process/src/format.rs @@ -8,7 +8,12 @@ pub struct DropFormatArgs { } impl DropFormatArgs { - pub fn new(launch_string: String, working_dir: &String, executable_name: &String, absolute_executable_name: String) -> Self { + pub fn new( + launch_string: String, + working_dir: &String, + executable_name: &String, + absolute_executable_name: String, + ) -> Self { let mut positional = Vec::new(); let mut map: HashMap<&'static str, String> = HashMap::new(); diff --git a/src-tauri/process/src/lib.rs b/src-tauri/process/src/lib.rs new file mode 100644 index 0000000..ec3c19e --- /dev/null +++ b/src-tauri/process/src/lib.rs @@ -0,0 +1,41 @@ +#![feature(nonpoison_mutex)] +#![feature(sync_nonpoison)] + +use std::{ + ops::Deref, + sync::{OnceLock, nonpoison::Mutex}, +}; + +use tauri::AppHandle; + +use crate::process_manager::ProcessManager; + +pub static PROCESS_MANAGER: ProcessManagerWrapper = ProcessManagerWrapper::new(); + +pub mod error; +pub mod format; +pub mod process_handlers; +pub mod process_manager; + +pub struct ProcessManagerWrapper(OnceLock>>); +impl ProcessManagerWrapper { + const fn new() -> Self { + ProcessManagerWrapper(OnceLock::new()) + } + pub fn init(app_handle: AppHandle) { + PROCESS_MANAGER + .0 + .set(Mutex::new(ProcessManager::new(app_handle))) + .unwrap_or_else(|_| panic!("Failed to initialise Process Manager")); // Using panic! here because we can't implement Debug + } +} +impl Deref for ProcessManagerWrapper { + type Target = Mutex>; + + fn deref(&self) -> &Self::Target { + match self.0.get() { + Some(process_manager) => process_manager, + None => unreachable!("Download manager should always be initialised"), + } + } +} diff --git a/src-tauri/src/process/process_handlers.rs b/src-tauri/process/src/process_handlers.rs similarity index 59% rename from src-tauri/src/process/process_handlers.rs rename to src-tauri/process/src/process_handlers.rs index 00a6be3..76b1ab2 100644 --- a/src-tauri/src/process/process_handlers.rs +++ b/src-tauri/process/src/process_handlers.rs @@ -1,18 +1,8 @@ -use std::{ - ffi::OsStr, - path::PathBuf, - process::{Command, Stdio}, - sync::LazyLock, -}; +use client::compat::{COMPAT_INFO, UMU_LAUNCHER_EXECUTABLE}; +use database::{Database, DownloadableMetadata, GameVersion, platform::Platform}; +use log::debug; -use log::{debug, info}; - -use crate::{ - AppState, - database::models::data::{Database, DownloadableMetadata, GameVersion}, - error::process_error::ProcessError, - process::process_manager::{Platform, ProcessHandler}, -}; +use crate::{error::ProcessError, process_manager::ProcessHandler}; pub struct NativeGameLauncher; impl ProcessHandler for NativeGameLauncher { @@ -27,36 +17,11 @@ impl ProcessHandler for NativeGameLauncher { Ok(format!("\"{}\" {}", launch_command, args.join(" "))) } - fn valid_for_platform(&self, _db: &Database, _state: &AppState, _target: &Platform) -> bool { + fn valid_for_platform(&self, _db: &Database, _target: &Platform) -> bool { true } } -pub static UMU_LAUNCHER_EXECUTABLE: LazyLock> = LazyLock::new(|| { - let x = get_umu_executable(); - info!("{:?}", &x); - x -}); -const UMU_BASE_LAUNCHER_EXECUTABLE: &str = "umu-run"; -const UMU_INSTALL_DIRS: [&str; 4] = ["/app/share", "/use/local/share", "/usr/share", "/opt"]; - -fn get_umu_executable() -> Option { - if check_executable_exists(UMU_BASE_LAUNCHER_EXECUTABLE) { - return Some(PathBuf::from(UMU_BASE_LAUNCHER_EXECUTABLE)); - } - - for dir in UMU_INSTALL_DIRS { - let p = PathBuf::from(dir).join(UMU_BASE_LAUNCHER_EXECUTABLE); - if check_executable_exists(&p) { - return Some(p); - } - } - None -} -fn check_executable_exists>(exec: P) -> bool { - let has_umu_installed = Command::new(exec).stdout(Stdio::null()).output(); - has_umu_installed.is_ok() -} pub struct UMULauncher; impl ProcessHandler for UMULauncher { fn create_launch_process( @@ -80,14 +45,16 @@ impl ProcessHandler for UMULauncher { }; Ok(format!( "GAMEID={game_id} {umu:?} \"{launch}\" {args}", - umu = UMU_LAUNCHER_EXECUTABLE.as_ref().expect("Failed to get UMU_LAUNCHER_EXECUTABLE as ref"), + umu = UMU_LAUNCHER_EXECUTABLE + .as_ref() + .expect("Failed to get UMU_LAUNCHER_EXECUTABLE as ref"), launch = launch_command, args = args.join(" ") )) } - fn valid_for_platform(&self, _db: &Database, state: &AppState, _target: &Platform) -> bool { - let Some(ref compat_info) = state.compat_info else { + fn valid_for_platform(&self, _db: &Database, _target: &Platform) -> bool { + let Some(compat_info) = &*COMPAT_INFO else { return false; }; compat_info.umu_installed @@ -120,14 +87,19 @@ impl ProcessHandler for AsahiMuvmLauncher { .next() .ok_or(ProcessError::InvalidArguments(umu_string.clone()))? .trim(); - let cmd = format!("umu-run{}", args_cmd.next().ok_or(ProcessError::InvalidArguments(umu_string.clone()))?); + let cmd = format!( + "umu-run{}", + args_cmd + .next() + .ok_or(ProcessError::InvalidArguments(umu_string.clone()))? + ); Ok(format!("{args} muvm -- {cmd}")) } #[allow(unreachable_code)] #[allow(unused_variables)] - fn valid_for_platform(&self, _db: &Database, state: &AppState, _target: &Platform) -> bool { + fn valid_for_platform(&self, _db: &Database, _target: &Platform) -> bool { #[cfg(not(target_os = "linux"))] return false; @@ -139,7 +111,7 @@ impl ProcessHandler for AsahiMuvmLauncher { return false; } - let Some(ref compat_info) = state.compat_info else { + let Some(compat_info) = &*COMPAT_INFO else { return false; }; diff --git a/src-tauri/src/process/process_manager.rs b/src-tauri/process/src/process_manager.rs similarity index 78% rename from src-tauri/src/process/process_manager.rs rename to src-tauri/process/src/process_manager.rs index 54651c6..6fce4fe 100644 --- a/src-tauri/src/process/process_manager.rs +++ b/src-tauri/process/src/process_manager.rs @@ -1,39 +1,31 @@ use std::{ collections::HashMap, fs::{OpenOptions, create_dir_all}, - io::{self}, + io, path::PathBuf, process::{Command, ExitStatus}, str::FromStr, - sync::{Arc, Mutex}, + sync::Arc, thread::spawn, time::{Duration, SystemTime}, }; +use database::{ + ApplicationTransientStatus, Database, DownloadType, DownloadableMetadata, GameDownloadStatus, + GameVersion, borrow_db_checked, borrow_db_mut_checked, db::DATA_ROOT_DIR, platform::Platform, +}; use dynfmt::Format; use dynfmt::SimpleCurlyFormat; +use games::{library::push_game_update, state::GameStatusManager}; use log::{debug, info, warn}; -use serde::{Deserialize, Serialize}; use shared_child::SharedChild; -use tauri::{AppHandle, Emitter, Manager}; -use tauri_plugin_opener::OpenerExt; +use tauri::AppHandle; use crate::{ - AppState, - database::{ - db::{DATA_ROOT_DIR, borrow_db_checked, borrow_db_mut_checked}, - models::data::{ - ApplicationTransientStatus, Database, DownloadType, DownloadableMetadata, - GameDownloadStatus, GameVersion, - }, - }, - error::process_error::ProcessError, - games::{library::push_game_update, state::GameStatusManager}, - process::{ - format::DropFormatArgs, - process_handlers::{AsahiMuvmLauncher, NativeGameLauncher, UMULauncher}, - }, - lock, + PROCESS_MANAGER, + error::ProcessError, + format::DropFormatArgs, + process_handlers::{AsahiMuvmLauncher, NativeGameLauncher, UMULauncher}, }; pub struct RunningProcess { @@ -46,11 +38,11 @@ pub struct ProcessManager<'a> { current_platform: Platform, log_output_dir: PathBuf, processes: HashMap, - app_handle: AppHandle, game_launchers: Vec<( (Platform, Platform), &'a (dyn ProcessHandler + Sync + Send + 'static), )>, + app_handle: AppHandle, } impl ProcessManager<'_> { @@ -67,7 +59,6 @@ impl ProcessManager<'_> { #[cfg(target_os = "linux")] current_platform: Platform::Linux, - app_handle, processes: HashMap::new(), log_output_dir, game_launchers: vec![ @@ -93,6 +84,7 @@ impl ProcessManager<'_> { &UMULauncher {} as &(dyn ProcessHandler + Sync + Send + 'static), ), ], + app_handle, } } @@ -111,25 +103,20 @@ impl ProcessManager<'_> { } } - fn get_log_dir(&self, game_id: String) -> PathBuf { + pub fn get_log_dir(&self, game_id: String) -> PathBuf { self.log_output_dir.join(game_id) } - pub fn open_process_logs(&mut self, game_id: String) -> Result<(), ProcessError> { - let dir = self.get_log_dir(game_id); - self.app_handle - .opener() - .open_path(dir.display().to_string(), None::<&str>) - .map_err(ProcessError::OpenerError)?; - Ok(()) - } - - fn on_process_finish(&mut self, game_id: String, result: Result) { + fn on_process_finish( + &mut self, + game_id: String, + result: Result, + ) -> Result<(), ProcessError> { if !self.processes.contains_key(&game_id) { warn!( "process on_finish was called, but game_id is no longer valid. finished with result: {result:?}" ); - return; + return Ok(()); } debug!("process for {:?} exited with {:?}", &game_id, result); @@ -138,7 +125,7 @@ impl ProcessManager<'_> { Some(process) => process, None => { info!("Attempted to stop process {game_id} which didn't exist"); - return; + return Ok(()); } }; @@ -176,7 +163,8 @@ impl ProcessManager<'_> { && (elapsed.as_secs() <= 2 || result.map_or(true, |r| !r.success())) { warn!("drop detected that the game {game_id} may have failed to launch properly"); - let _ = self.app_handle.emit("launch_external_error", &game_id); + return Err(ProcessError::FailedLaunch(game_id)); + // let _ = self.app_handle.emit("launch_external_error", &game_id); } let version_data = match db_handle.applications.game_versions.get(&game_id) { @@ -193,12 +181,12 @@ impl ProcessManager<'_> { Some(version_data.clone()), status, ); + Ok(()) } fn fetch_process_handler( &self, db_lock: &Database, - state: &AppState, target_platform: &Platform, ) -> Result<&(dyn ProcessHandler + Send + Sync), ProcessError> { Ok(self @@ -208,23 +196,20 @@ impl ProcessManager<'_> { let (e_current, e_target) = e.0; e_current == self.current_platform && e_target == *target_platform - && e.1.valid_for_platform(db_lock, state, target_platform) + && e.1.valid_for_platform(db_lock, target_platform) }) .ok_or(ProcessError::InvalidPlatform)? .1) } - pub fn valid_platform(&self, platform: &Platform, state: &AppState) -> bool { + pub fn valid_platform(&self, platform: &Platform) -> bool { let db_lock = borrow_db_checked(); - let process_handler = self.fetch_process_handler(&db_lock, state, platform); + let process_handler = self.fetch_process_handler(&db_lock, platform); process_handler.is_ok() } - pub fn launch_process( - &mut self, - game_id: String, - state: &AppState, - ) -> Result<(), ProcessError> { + /// Must be called through spawn as it is currently blocking + pub fn launch_process(&mut self, game_id: String) -> Result<(), ProcessError> { if self.processes.contains_key(&game_id) { return Err(ProcessError::AlreadyRunning); } @@ -306,7 +291,7 @@ impl ProcessManager<'_> { let target_platform = game_version.platform; - let process_handler = self.fetch_process_handler(&db_lock, state, &target_platform)?; + let process_handler = self.fetch_process_handler(&db_lock, &target_platform)?; let (launch, args) = match game_status { GameDownloadStatus::Installed { @@ -388,27 +373,8 @@ impl ProcessManager<'_> { ); let wait_thread_handle = launch_process_handle.clone(); - let wait_thread_apphandle = self.app_handle.clone(); let wait_thread_game_id = meta.clone(); - spawn(move || { - let result: Result = launch_process_handle.wait(); - - let app_state = wait_thread_apphandle.state::>(); - let app_state_handle = lock!(app_state); - - let mut process_manager_handle = app_state_handle - .process_manager - .lock() - .expect("Failed to lock onto process manager"); - process_manager_handle.on_process_finish(wait_thread_game_id.id, result); - - // As everything goes out of scope, they should get dropped - // But just to explicit about it - drop(process_manager_handle); - drop(app_state_handle); - }); - self.processes.insert( meta.id, RunningProcess { @@ -417,55 +383,17 @@ impl ProcessManager<'_> { manually_killed: false, }, ); + spawn(move || { + let result: Result = launch_process_handle.wait(); + + PROCESS_MANAGER + .lock() + .on_process_finish(wait_thread_game_id.id, result) + }); Ok(()) } } -#[derive(Eq, Hash, PartialEq, Serialize, Deserialize, Clone, Copy, Debug)] -pub enum Platform { - Windows, - Linux, - MacOs, -} - -impl Platform { - #[cfg(target_os = "windows")] - pub const HOST: Platform = Self::Windows; - #[cfg(target_os = "macos")] - pub const HOST: Platform = Self::MacOs; - #[cfg(target_os = "linux")] - pub const HOST: Platform = Self::Linux; - - pub fn is_case_sensitive(&self) -> bool { - match self { - Self::Windows | Self::MacOs => false, - Self::Linux => true, - } - } -} - -impl From<&str> for Platform { - fn from(value: &str) -> Self { - match value.to_lowercase().trim() { - "windows" => Self::Windows, - "linux" => Self::Linux, - "mac" | "macos" => Self::MacOs, - _ => unimplemented!(), - } - } -} - -impl From for Platform { - fn from(value: whoami::Platform) -> Self { - match value { - whoami::Platform::Windows => Platform::Windows, - whoami::Platform::Linux => Platform::Linux, - whoami::Platform::MacOS => Platform::MacOs, - _ => unimplemented!(), - } - } -} - pub trait ProcessHandler: Send + 'static { fn create_launch_process( &self, @@ -476,5 +404,5 @@ pub trait ProcessHandler: Send + 'static { current_dir: &str, ) -> Result; - fn valid_for_platform(&self, db: &Database, state: &AppState, target: &Platform) -> bool; + fn valid_for_platform(&self, db: &Database, target: &Platform) -> bool; } diff --git a/src-tauri/remote/Cargo.toml b/src-tauri/remote/Cargo.toml new file mode 100644 index 0000000..f352359 --- /dev/null +++ b/src-tauri/remote/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "remote" +version = "0.1.0" +edition = "2024" + +[dependencies] +bitcode = "0.6.7" +chrono = "0.4.42" +client = { version = "0.1.0", path = "../client" } +database = { version = "0.1.0", path = "../database" } +droplet-rs = "0.7.3" +gethostname = "1.0.2" +hex = "0.4.3" +http = "1.3.1" +log = "0.4.28" +md5 = "0.8.0" +reqwest = "0.12.23" +reqwest-websocket = "0.5.1" +serde = "1.0.228" +serde_with = "3.15.0" +tauri = "2.8.5" +url = "2.5.7" +utils = { version = "0.1.0", path = "../utils" } diff --git a/src-tauri/src/remote/auth.rs b/src-tauri/remote/src/auth.rs similarity index 52% rename from src-tauri/src/remote/auth.rs rename to src-tauri/remote/src/auth.rs index ce82587..9f1ab98 100644 --- a/src-tauri/src/remote/auth.rs +++ b/src-tauri/remote/src/auth.rs @@ -1,18 +1,18 @@ -use std::{collections::HashMap, env, sync::Mutex}; +use std::{collections::HashMap, env}; use chrono::Utc; +use client::{app_status::AppStatus, user::User}; +use database::{DatabaseAuth, interface::borrow_db_checked}; use droplet_rs::ssl::sign_nonce; use gethostname::gethostname; -use log::{debug, error, warn}; +use log::{error, warn}; use serde::{Deserialize, Serialize}; -use tauri::{AppHandle, Emitter, Manager}; use url::Url; use crate::{ - app_emit, database::{ - db::{borrow_db_checked, borrow_db_mut_checked}, - models::data::DatabaseAuth, - }, error::{drop_server_error::DropServerError, remote_access_error::RemoteAccessError}, lock, remote::{cache::clear_cached_object, requests::make_authenticated_get, utils::{DROP_CLIENT_ASYNC, DROP_CLIENT_SYNC}}, AppState, AppStatus, User + error::{DropServerError, RemoteAccessError}, + requests::make_authenticated_get, + utils::DROP_CLIENT_SYNC, }; use super::{ @@ -35,19 +35,31 @@ struct InitiateRequestBody { #[derive(Serialize)] #[serde(rename_all = "camelCase")] -struct HandshakeRequestBody { +pub struct HandshakeRequestBody { client_id: String, token: String, } +impl HandshakeRequestBody { + pub fn new(client_id: String, token: String) -> Self { + Self { client_id, token } + } +} + #[derive(Deserialize)] #[serde(rename_all = "camelCase")] -struct HandshakeResponse { +pub struct HandshakeResponse { private: String, certificate: String, id: String, } +impl From for DatabaseAuth { + fn from(value: HandshakeResponse) -> Self { + DatabaseAuth::new(value.private, value.certificate, value.id, None) + } +} + pub fn generate_authorization_header() -> String { let certs = { let db = borrow_db_checked(); @@ -81,94 +93,6 @@ pub async fn fetch_user() -> Result { .map_err(std::convert::Into::into) } -async fn recieve_handshake_logic(app: &AppHandle, path: String) -> Result<(), RemoteAccessError> { - let path_chunks: Vec<&str> = path.split('/').collect(); - if path_chunks.len() != 3 { - app_emit!(app, "auth/failed", ()); - return Err(RemoteAccessError::HandshakeFailed( - "failed to parse token".to_string(), - )); - } - - let base_url = { - let handle = borrow_db_checked(); - Url::parse(handle.base_url.as_str())? - }; - - let client_id = path_chunks - .get(1) - .expect("Failed to get client id from path chunks"); - let token = path_chunks - .get(2) - .expect("Failed to get token from path chunks"); - let body = HandshakeRequestBody { - client_id: (client_id).to_string(), - token: (token).to_string(), - }; - - let endpoint = base_url.join("/api/v1/client/auth/handshake")?; - let client = DROP_CLIENT_ASYNC.clone(); - let response = client.post(endpoint).json(&body).send().await?; - debug!("handshake responsded with {}", response.status().as_u16()); - if !response.status().is_success() { - return Err(RemoteAccessError::InvalidResponse(response.json().await?)); - } - let response_struct: HandshakeResponse = response.json().await?; - - { - let mut handle = borrow_db_mut_checked(); - handle.auth = Some(DatabaseAuth { - private: response_struct.private, - cert: response_struct.certificate, - client_id: response_struct.id, - web_token: None, - }); - } - - let web_token = { - let header = generate_authorization_header(); - let token = client - .post(base_url.join("/api/v1/client/user/webtoken")?) - .header("Authorization", header) - .send() - .await?; - - token.text().await? - }; - let mut handle = borrow_db_mut_checked(); - handle.auth.as_mut().unwrap().web_token = Some(web_token); - - Ok(()) -} - -pub async fn recieve_handshake(app: AppHandle, path: String) { - // Tell the app we're processing - app_emit!(app, "auth/processing", ()); - - let handshake_result = recieve_handshake_logic(&app, path).await; - if let Err(e) = handshake_result { - warn!("error with authentication: {e}"); - app_emit!(app, "auth/failed", e.to_string()); - return; - } - - let app_state = app.state::>(); - - let (app_status, user) = setup().await; - - let mut state_lock = lock!(app_state); - - state_lock.status = app_status; - state_lock.user = user; - - let _ = clear_cached_object("collections"); - let _ = clear_cached_object("library"); - - drop(state_lock); - - app_emit!(app, "auth/finished", ()); -} - pub fn auth_initiate_logic(mode: String) -> Result { let base_url = { let db_lock = borrow_db_checked(); diff --git a/src-tauri/src/remote/cache.rs b/src-tauri/remote/src/cache.rs similarity index 83% rename from src-tauri/src/remote/cache.rs rename to src-tauri/remote/src/cache.rs index 084e9a4..3a21a0a 100644 --- a/src-tauri/src/remote/cache.rs +++ b/src-tauri/remote/src/cache.rs @@ -5,18 +5,19 @@ use std::{ time::SystemTime, }; -use crate::{ - database::{db::borrow_db_checked, models::data::Database}, - error::{cache_error::CacheError, remote_access_error::RemoteAccessError}, -}; use bitcode::{Decode, DecodeOwned, Encode}; -use http::{header::{CONTENT_TYPE}, response::Builder as ResponseBuilder, Response}; +use database::{Database, borrow_db_checked}; +use http::{Response, header::CONTENT_TYPE, response::Builder as ResponseBuilder}; + +use crate::error::{CacheError, RemoteAccessError}; #[macro_export] macro_rules! offline { ($var:expr, $func1:expr, $func2:expr, $( $arg:expr ),* ) => { - async move { if $crate::borrow_db_checked().settings.force_offline || $crate::lock!($var).status == $crate::AppStatus::Offline { + async move { + if ::database::borrow_db_checked().settings.force_offline + || $var.lock().status == ::client::app_status::AppStatus::Offline { $func2( $( $arg ), *).await } else { $func1( $( $arg ), *).await @@ -82,10 +83,7 @@ pub fn get_cached_object_db( pub fn clear_cached_object(key: &str) -> Result<(), RemoteAccessError> { clear_cached_object_db(key, &borrow_db_checked()) } -pub fn clear_cached_object_db( - key: &str, - db: &Database, -) -> Result<(), RemoteAccessError> { +pub fn clear_cached_object_db(key: &str, db: &Database) -> Result<(), RemoteAccessError> { delete_sync(&db.cache_dir, key).map_err(RemoteAccessError::Cache)?; Ok(()) } @@ -104,9 +102,9 @@ impl ObjectCache { } } -impl TryFrom>> for ObjectCache { +impl TryFrom>> for ObjectCache { type Error = CacheError; - + fn try_from(value: Response>) -> Result { Ok(ObjectCache { content_type: value @@ -119,14 +117,15 @@ impl TryFrom>> for ObjectCache { body: value.body().clone(), expiry: get_sys_time_in_secs() + 60 * 60 * 24, }) - } } impl TryFrom for Response> { type Error = CacheError; fn try_from(value: ObjectCache) -> Result { let resp_builder = ResponseBuilder::new().header(CONTENT_TYPE, value.content_type); - resp_builder.body(value.body).map_err(CacheError::ConstructionError) + resp_builder + .body(value.body) + .map_err(CacheError::ConstructionError) } } impl TryFrom<&ObjectCache> for Response> { @@ -134,6 +133,8 @@ impl TryFrom<&ObjectCache> for Response> { fn try_from(value: &ObjectCache) -> Result { let resp_builder = ResponseBuilder::new().header(CONTENT_TYPE, value.content_type.clone()); - resp_builder.body(value.body.clone()).map_err(CacheError::ConstructionError) + resp_builder + .body(value.body.clone()) + .map_err(CacheError::ConstructionError) } } diff --git a/src-tauri/src/error/remote_access_error.rs b/src-tauri/remote/src/error.rs similarity index 74% rename from src-tauri/src/error/remote_access_error.rs rename to src-tauri/remote/src/error.rs index 21a4fbe..a939d61 100644 --- a/src-tauri/src/error/remote_access_error.rs +++ b/src-tauri/remote/src/error.rs @@ -4,11 +4,20 @@ use std::{ sync::Arc, }; -use http::StatusCode; +use http::{HeaderName, StatusCode, header::ToStrError}; use serde_with::SerializeDisplay; use url::ParseError; -use super::drop_server_error::DropServerError; +use serde::Deserialize; + +#[derive(Deserialize, Debug, Clone)] +#[serde(rename_all = "camelCase")] +pub struct DropServerError { + pub status_code: usize, + pub status_message: String, + // pub message: String, + // pub url: String, +} #[derive(Debug, SerializeDisplay)] pub enum RemoteAccessError { @@ -104,3 +113,31 @@ impl From for RemoteAccessError { } } impl std::error::Error for RemoteAccessError {} + +#[derive(Debug, SerializeDisplay)] +pub enum CacheError { + HeaderNotFound(HeaderName), + ParseError(ToStrError), + Remote(RemoteAccessError), + ConstructionError(http::Error), +} + +impl Display for CacheError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let s = match self { + CacheError::HeaderNotFound(header_name) => { + format!("Could not find header {header_name} in cache") + } + CacheError::ParseError(to_str_error) => { + format!("Could not parse cache with error {to_str_error}") + } + CacheError::Remote(remote_access_error) => { + format!("Cache got remote access error: {remote_access_error}") + } + CacheError::ConstructionError(error) => { + format!("Could not construct cache body with error {error}") + } + }; + write!(f, "{s}") + } +} diff --git a/src-tauri/src/remote/fetch_object.rs b/src-tauri/remote/src/fetch_object.rs similarity index 73% rename from src-tauri/src/remote/fetch_object.rs rename to src-tauri/remote/src/fetch_object.rs index 436ec39..e80a043 100644 --- a/src-tauri/src/remote/fetch_object.rs +++ b/src-tauri/remote/src/fetch_object.rs @@ -1,8 +1,9 @@ -use http::{header::CONTENT_TYPE, response::Builder as ResponseBuilder, Response}; +use database::{DB, interface::DatabaseImpls}; +use http::{Response, header::CONTENT_TYPE, response::Builder as ResponseBuilder}; use log::{debug, warn}; use tauri::UriSchemeResponder; -use crate::{database::db::DatabaseImpls, error::cache_error::CacheError, remote::utils::DROP_CLIENT_ASYNC, DB}; +use crate::{error::CacheError, utils::DROP_CLIENT_ASYNC}; use super::{ auth::generate_authorization_header, @@ -14,13 +15,19 @@ pub async fn fetch_object_wrapper(request: http::Request>, responder: Ur Ok(r) => responder.respond(r), Err(e) => { warn!("Cache error: {e}"); - responder.respond(Response::builder().status(500).body(Vec::new()).expect("Failed to build error response")); + responder.respond( + Response::builder() + .status(500) + .body(Vec::new()) + .expect("Failed to build error response"), + ); } }; } -pub async fn fetch_object(request: http::Request>) -> Result>, CacheError> -{ +pub async fn fetch_object( + request: http::Request>, +) -> Result>, CacheError> { // Drop leading / let object_id = &request.uri().path()[1..]; @@ -47,13 +54,13 @@ pub async fn fetch_object(request: http::Request>) -> Result Vec::from(data), Err(e) => { - warn!( - "Could not get data from cache object {object_id} with error {e}", - ); + warn!("Could not get data from cache object {object_id} with error {e}",); Vec::new() } }; - let resp = resp_builder.body(data).expect("Failed to build object cache response body"); + let resp = resp_builder + .body(data) + .expect("Failed to build object cache response body"); if cache_result.map_or(true, |x| x.has_expired()) { cache_object::(object_id, &resp.clone().try_into()?) .expect("Failed to create cached object"); diff --git a/src-tauri/src/remote/mod.rs b/src-tauri/remote/src/lib.rs similarity index 76% rename from src-tauri/src/remote/mod.rs rename to src-tauri/remote/src/lib.rs index c5e1843..3bc0ff6 100644 --- a/src-tauri/src/remote/mod.rs +++ b/src-tauri/remote/src/lib.rs @@ -1,8 +1,10 @@ pub mod auth; #[macro_use] pub mod cache; -pub mod commands; +pub mod error; pub mod fetch_object; pub mod requests; pub mod server_proto; pub mod utils; + +pub use auth::setup; diff --git a/src-tauri/src/remote/requests.rs b/src-tauri/remote/src/requests.rs similarity index 81% rename from src-tauri/src/remote/requests.rs rename to src-tauri/remote/src/requests.rs index 7ebf7b1..df74269 100644 --- a/src-tauri/src/remote/requests.rs +++ b/src-tauri/remote/src/requests.rs @@ -1,10 +1,8 @@ +use database::{DB, interface::DatabaseImpls}; use url::Url; use crate::{ - DB, - database::db::DatabaseImpls, - error::remote_access_error::RemoteAccessError, - remote::{auth::generate_authorization_header, utils::DROP_CLIENT_ASYNC}, + auth::generate_authorization_header, error::RemoteAccessError, utils::DROP_CLIENT_ASYNC, }; pub fn generate_url>( diff --git a/src-tauri/src/remote/server_proto.rs b/src-tauri/remote/src/server_proto.rs similarity index 63% rename from src-tauri/src/remote/server_proto.rs rename to src-tauri/remote/src/server_proto.rs index 54af4e5..54334df 100644 --- a/src-tauri/src/remote/server_proto.rs +++ b/src-tauri/remote/src/server_proto.rs @@ -1,24 +1,30 @@ use std::str::FromStr; -use http::{uri::PathAndQuery, Request, Response, StatusCode, Uri}; +use database::borrow_db_checked; +use http::{Request, Response, StatusCode, Uri, uri::PathAndQuery}; use log::{error, warn}; use tauri::UriSchemeResponder; +use utils::webbrowser_open::webbrowser_open; -use crate::{database::db::borrow_db_checked, remote::utils::DROP_CLIENT_SYNC, utils::webbrowser_open::webbrowser_open}; +use crate::utils::DROP_CLIENT_SYNC; -pub async fn handle_server_proto_offline_wrapper(request: Request>, responder: UriSchemeResponder) { +pub async fn handle_server_proto_offline_wrapper( + request: Request>, + responder: UriSchemeResponder, +) { responder.respond(match handle_server_proto_offline(request).await { Ok(res) => res, - Err(_) => unreachable!() + Err(_) => unreachable!(), }); } -pub async fn handle_server_proto_offline(_request: Request>) -> Result>, StatusCode>{ +pub async fn handle_server_proto_offline( + _request: Request>, +) -> Result>, StatusCode> { Ok(Response::builder() .status(StatusCode::NOT_FOUND) .body(Vec::new()) .expect("Failed to build error response for proto offline")) - } pub async fn handle_server_proto_wrapper(request: Request>, responder: UriSchemeResponder) { @@ -26,7 +32,12 @@ pub async fn handle_server_proto_wrapper(request: Request>, responder: U Ok(r) => responder.respond(r), Err(e) => { warn!("Cache error: {e}"); - responder.respond(Response::builder().status(e).body(Vec::new()).expect("Failed to build error response")); + responder.respond( + Response::builder() + .status(e) + .body(Vec::new()) + .expect("Failed to build error response"), + ); } } } @@ -37,20 +48,25 @@ async fn handle_server_proto(request: Request>) -> Result auth, None => { error!("Could not find auth in database"); - return Err(StatusCode::UNAUTHORIZED) + return Err(StatusCode::UNAUTHORIZED); } }; let web_token = match &auth.web_token { Some(token) => token, None => return Err(StatusCode::UNAUTHORIZED), }; - let remote_uri = db_handle.base_url.parse::().expect("Failed to parse base url"); + let remote_uri = db_handle + .base_url + .parse::() + .expect("Failed to parse base url"); let path = request.uri().path(); let mut new_uri = request.uri().clone().into_parts(); - new_uri.path_and_query = - Some(PathAndQuery::from_str(&format!("{path}?noWrapper=true")).expect("Failed to parse request path in proto")); + new_uri.path_and_query = Some( + PathAndQuery::from_str(&format!("{path}?noWrapper=true")) + .expect("Failed to parse request path in proto"), + ); new_uri.authority = remote_uri.authority().cloned(); new_uri.scheme = remote_uri.scheme().cloned(); let err_msg = &format!("Failed to build new uri from parts {new_uri:?}"); @@ -60,7 +76,7 @@ async fn handle_server_proto(request: Request>) -> Result>) -> Result response, - Err(e) => { - warn!("Could not send response. Got {e} when sending"); - return Err(e.status().unwrap_or(StatusCode::BAD_REQUEST)) - }, - }; + .send() + { + Ok(response) => response, + Err(e) => { + warn!("Could not send response. Got {e} when sending"); + return Err(e.status().unwrap_or(StatusCode::BAD_REQUEST)); + } + }; let response_status = response.status(); let response_body = match response.bytes() { diff --git a/src-tauri/src/remote/utils.rs b/src-tauri/remote/src/utils.rs similarity index 67% rename from src-tauri/src/remote/utils.rs rename to src-tauri/remote/src/utils.rs index 58e588f..6ca4e0b 100644 --- a/src-tauri/src/remote/utils.rs +++ b/src-tauri/remote/src/utils.rs @@ -1,25 +1,24 @@ use std::{ fs::{self, File}, io::Read, - sync::{LazyLock, Mutex}, - time::Duration, + sync::LazyLock, }; +use database::db::DATA_ROOT_DIR; use log::{debug, info, warn}; use reqwest::Certificate; use serde::Deserialize; -use url::Url; - -use crate::{ - database::db::{borrow_db_mut_checked, DATA_ROOT_DIR}, error::remote_access_error::RemoteAccessError, lock, AppState, AppStatus -}; #[derive(Deserialize)] #[serde(rename_all = "camelCase")] -struct DropHealthcheck { +pub struct DropHealthcheck { app_name: String, } - +impl DropHealthcheck { + pub fn app_name(&self) -> &String { + &self.app_name + } +} static DROP_CERT_BUNDLE: LazyLock> = LazyLock::new(fetch_certificates); pub static DROP_CLIENT_SYNC: LazyLock = LazyLock::new(get_client_sync); pub static DROP_CLIENT_ASYNC: LazyLock = LazyLock::new(get_client_async); @@ -47,11 +46,13 @@ fn fetch_certificates() -> Vec { } } .read_to_end(&mut buf) - .unwrap_or_else(|e| panic!( - "Failed to read to end of certificate file {} with error {}", - c.path().display(), - e - )); + .unwrap_or_else(|e| { + panic!( + "Failed to read to end of certificate file {} with error {}", + c.path().display(), + e + ) + }); match Certificate::from_pem_bundle(&buf) { Ok(certificates) => { @@ -88,7 +89,10 @@ pub fn get_client_sync() -> reqwest::blocking::Client { for cert in DROP_CERT_BUNDLE.iter() { client = client.add_root_certificate(cert.clone()); } - client.use_rustls_tls().build().expect("Failed to build synchronous client") + client + .use_rustls_tls() + .build() + .expect("Failed to build synchronous client") } pub fn get_client_async() -> reqwest::Client { let mut client = reqwest::ClientBuilder::new(); @@ -96,7 +100,10 @@ pub fn get_client_async() -> reqwest::Client { for cert in DROP_CERT_BUNDLE.iter() { client = client.add_root_certificate(cert.clone()); } - client.use_rustls_tls().build().expect("Failed to build asynchronous client") + client + .use_rustls_tls() + .build() + .expect("Failed to build asynchronous client") } pub fn get_client_ws() -> reqwest::Client { let mut client = reqwest::ClientBuilder::new(); @@ -110,36 +117,3 @@ pub fn get_client_ws() -> reqwest::Client { .build() .expect("Failed to build websocket client") } - -pub async fn use_remote_logic( - url: String, - state: tauri::State<'_, Mutex>>, -) -> Result<(), RemoteAccessError> { - debug!("connecting to url {url}"); - let base_url = Url::parse(&url)?; - - // Test Drop url - let test_endpoint = base_url.join("/api/v1")?; - let client = DROP_CLIENT_ASYNC.clone(); - let response = client - .get(test_endpoint.to_string()) - .timeout(Duration::from_secs(3)) - .send() - .await?; - - let result: DropHealthcheck = response.json().await?; - - if result.app_name != "Drop" { - warn!("user entered drop endpoint that connected, but wasn't identified as Drop"); - return Err(RemoteAccessError::InvalidEndpoint); - } - - let mut app_state = lock!(state); - app_state.status = AppStatus::SignedOut; - drop(app_state); - - let mut db_state = borrow_db_mut_checked(); - db_state.base_url = base_url.to_string(); - - Ok(()) -} diff --git a/src-tauri/src/client/autostart.rs b/src-tauri/src/client.rs similarity index 51% rename from src-tauri/src/client/autostart.rs rename to src-tauri/src/client.rs index a35f480..46ae65f 100644 --- a/src-tauri/src/client/autostart.rs +++ b/src-tauri/src/client.rs @@ -1,9 +1,41 @@ -use crate::database::db::{borrow_db_checked, borrow_db_mut_checked}; -use log::debug; +use std::sync::nonpoison::Mutex; + +use database::{borrow_db_checked, borrow_db_mut_checked}; +use download_manager::DOWNLOAD_MANAGER; +use log::{debug, error}; use tauri::AppHandle; use tauri_plugin_autostart::ManagerExt; -pub fn toggle_autostart_logic(app: AppHandle, enabled: bool) -> Result<(), String> { +use crate::AppState; + +#[tauri::command] +pub fn fetch_state(state: tauri::State<'_, Mutex>) -> Result { + let guard = state.lock(); + let cloned_state = serde_json::to_string(&guard.clone()).map_err(|e| e.to_string())?; + drop(guard); + Ok(cloned_state) +} + +#[tauri::command] +pub fn quit(app: tauri::AppHandle) { + cleanup_and_exit(&app); +} + +pub fn cleanup_and_exit(app: &AppHandle) { + debug!("cleaning up and exiting application"); + match DOWNLOAD_MANAGER.ensure_terminated() { + Ok(res) => match res { + Ok(()) => debug!("download manager terminated correctly"), + Err(()) => error!("download manager failed to terminate correctly"), + }, + Err(e) => panic!("{e:?}"), + } + + app.exit(0); +} + +#[tauri::command] +pub fn toggle_autostart(app: AppHandle, enabled: bool) -> Result<(), String> { let manager = app.autolaunch(); if enabled { manager.enable().map_err(|e| e.to_string())?; @@ -16,13 +48,11 @@ pub fn toggle_autostart_logic(app: AppHandle, enabled: bool) -> Result<(), Strin // Store the state in DB let mut db_handle = borrow_db_mut_checked(); db_handle.settings.autostart = enabled; - drop(db_handle); - Ok(()) } -pub fn get_autostart_enabled_logic(app: AppHandle) -> Result { - // First check DB state +#[tauri::command] +pub fn get_autostart_enabled(app: AppHandle) -> Result { let db_handle = borrow_db_checked(); let db_state = db_handle.settings.autostart; drop(db_handle); @@ -42,34 +72,3 @@ pub fn get_autostart_enabled_logic(app: AppHandle) -> Result Result<(), String> { - let db_handle = borrow_db_checked(); - let should_be_enabled = db_handle.settings.autostart; - drop(db_handle); - - let manager = app.autolaunch(); - let current_state = manager.is_enabled().map_err(|e| e.to_string())?; - - if current_state != should_be_enabled { - if should_be_enabled { - manager.enable().map_err(|e| e.to_string())?; - debug!("synced autostart: enabled"); - } else { - manager.disable().map_err(|e| e.to_string())?; - debug!("synced autostart: disabled"); - } - } - - Ok(()) -} -#[tauri::command] -pub fn toggle_autostart(app: AppHandle, enabled: bool) -> Result<(), String> { - toggle_autostart_logic(app, enabled) -} - -#[tauri::command] -pub fn get_autostart_enabled(app: AppHandle) -> Result { - get_autostart_enabled_logic(app) -} diff --git a/src-tauri/src/client/cleanup.rs b/src-tauri/src/client/cleanup.rs deleted file mode 100644 index b0d9739..0000000 --- a/src-tauri/src/client/cleanup.rs +++ /dev/null @@ -1,23 +0,0 @@ -use log::{debug, error}; -use tauri::AppHandle; - -use crate::{lock, AppState}; - -#[tauri::command] -pub fn quit(app: tauri::AppHandle, state: tauri::State<'_, std::sync::Mutex>>) { - cleanup_and_exit(&app, &state); -} - -pub fn cleanup_and_exit(app: &AppHandle, state: &tauri::State<'_, std::sync::Mutex>>) { - debug!("cleaning up and exiting application"); - let download_manager = lock!(state).download_manager.clone(); - match download_manager.ensure_terminated() { - Ok(res) => match res { - Ok(()) => debug!("download manager terminated correctly"), - Err(()) => error!("download manager failed to terminate correctly"), - }, - Err(e) => panic!("{e:?}"), - } - - app.exit(0); -} diff --git a/src-tauri/src/client/commands.rs b/src-tauri/src/client/commands.rs deleted file mode 100644 index ef3c9a6..0000000 --- a/src-tauri/src/client/commands.rs +++ /dev/null @@ -1,11 +0,0 @@ -use crate::{lock, AppState}; - -#[tauri::command] -pub fn fetch_state( - state: tauri::State<'_, std::sync::Mutex>>, -) -> Result { - let guard = lock!(state); - let cloned_state = serde_json::to_string(&guard.clone()).map_err(|e| e.to_string())?; - drop(guard); - Ok(cloned_state) -} diff --git a/src-tauri/src/client/mod.rs b/src-tauri/src/client/mod.rs deleted file mode 100644 index 48b6821..0000000 --- a/src-tauri/src/client/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod autostart; -pub mod cleanup; -pub mod commands; diff --git a/src-tauri/src/cloud_saves/backup_manager.rs b/src-tauri/src/cloud_saves/backup_manager.rs deleted file mode 100644 index 522126c..0000000 --- a/src-tauri/src/cloud_saves/backup_manager.rs +++ /dev/null @@ -1,102 +0,0 @@ -use std::{collections::HashMap, path::PathBuf, str::FromStr}; - -use log::warn; - -use crate::{database::db::{GameVersion, DATA_ROOT_DIR}, error::backup_error::BackupError, process::process_manager::Platform}; - -use super::path::CommonPath; - -pub struct BackupManager<'a> { - pub current_platform: Platform, - pub sources: HashMap<(Platform, Platform), &'a (dyn BackupHandler + Sync + Send)>, -} - -impl BackupManager<'_> { - pub fn new() -> Self { - BackupManager { - #[cfg(target_os = "windows")] - current_platform: Platform::Windows, - - #[cfg(target_os = "macos")] - current_platform: Platform::MacOs, - - #[cfg(target_os = "linux")] - current_platform: Platform::Linux, - - sources: HashMap::from([ - // Current platform to target platform - ( - (Platform::Windows, Platform::Windows), - &WindowsBackupManager {} as &(dyn BackupHandler + Sync + Send), - ), - ( - (Platform::Linux, Platform::Linux), - &LinuxBackupManager {} as &(dyn BackupHandler + Sync + Send), - ), - ( - (Platform::MacOs, Platform::MacOs), - &MacBackupManager {} as &(dyn BackupHandler + Sync + Send), - ), - - ]), - } - } - -} - -pub trait BackupHandler: Send + Sync { - fn root_translate(&self, _path: &PathBuf, _game: &GameVersion) -> Result { Ok(DATA_ROOT_DIR.lock().unwrap().join("games")) } - fn game_translate(&self, _path: &PathBuf, game: &GameVersion) -> Result { Ok(PathBuf::from_str(&game.game_id).unwrap()) } - fn base_translate(&self, path: &PathBuf, game: &GameVersion) -> Result { Ok(self.root_translate(path, game)?.join(self.game_translate(path, game)?)) } - fn home_translate(&self, _path: &PathBuf, _game: &GameVersion) -> Result { let c = CommonPath::Home.get().ok_or(BackupError::NotFound); println!("{:?}", c); c } - fn store_user_id_translate(&self, _path: &PathBuf, game: &GameVersion) -> Result { PathBuf::from_str(&game.game_id).map_err(|_| BackupError::ParseError) } - fn os_user_name_translate(&self, _path: &PathBuf, _game: &GameVersion) -> Result { Ok(PathBuf::from_str(&whoami::username()).unwrap()) } - fn win_app_data_translate(&self, _path: &PathBuf, _game: &GameVersion) -> Result { warn!("Unexpected Windows Reference in Backup "); Err(BackupError::InvalidSystem) } - fn win_local_app_data_translate(&self, _path: &PathBuf, _game: &GameVersion) -> Result { warn!("Unexpected Windows Reference in Backup "); Err(BackupError::InvalidSystem) } - fn win_local_app_data_low_translate(&self, _path: &PathBuf, _game: &GameVersion) -> Result { warn!("Unexpected Windows Reference in Backup "); Err(BackupError::InvalidSystem) } - fn win_documents_translate(&self, _path: &PathBuf, _game: &GameVersion) -> Result { warn!("Unexpected Windows Reference in Backup "); Err(BackupError::InvalidSystem) } - fn win_public_translate(&self, _path: &PathBuf, _game: &GameVersion) -> Result { warn!("Unexpected Windows Reference in Backup "); Err(BackupError::InvalidSystem) } - fn win_program_data_translate(&self, _path: &PathBuf, _game: &GameVersion) -> Result { warn!("Unexpected Windows Reference in Backup "); Err(BackupError::InvalidSystem) } - fn win_dir_translate(&self, _path: &PathBuf,_game: &GameVersion) -> Result { warn!("Unexpected Windows Reference in Backup "); Err(BackupError::InvalidSystem) } - fn xdg_data_translate(&self, _path: &PathBuf,_game: &GameVersion) -> Result { warn!("Unexpected XDG Reference in Backup "); Err(BackupError::InvalidSystem) } - fn xdg_config_translate(&self, _path: &PathBuf,_game: &GameVersion) -> Result { warn!("Unexpected XDG Reference in Backup "); Err(BackupError::InvalidSystem) } - fn skip_translate(&self, _path: &PathBuf, _game: &GameVersion) -> Result { Ok(PathBuf::new()) } -} - -pub struct LinuxBackupManager {} -impl BackupHandler for LinuxBackupManager { - fn xdg_config_translate(&self, _path: &PathBuf,_game: &GameVersion) -> Result { - Ok(CommonPath::Data.get().ok_or(BackupError::NotFound)?) - } - fn xdg_data_translate(&self, _path: &PathBuf,_game: &GameVersion) -> Result { - Ok(CommonPath::Config.get().ok_or(BackupError::NotFound)?) - } -} -pub struct WindowsBackupManager {} -impl BackupHandler for WindowsBackupManager { - fn win_app_data_translate(&self, _path: &PathBuf, _game: &GameVersion) -> Result { - Ok(CommonPath::Config.get().ok_or(BackupError::NotFound)?) - } - fn win_local_app_data_translate(&self, _path: &PathBuf, _game: &GameVersion) -> Result { - Ok(CommonPath::DataLocal.get().ok_or(BackupError::NotFound)?) - } - fn win_local_app_data_low_translate(&self, _path: &PathBuf, _game: &GameVersion) -> Result { - Ok(CommonPath::DataLocalLow.get().ok_or(BackupError::NotFound)?) - } - fn win_dir_translate(&self, _path: &PathBuf,_game: &GameVersion) -> Result { - Ok(PathBuf::from_str("C:/Windows").unwrap()) - } - fn win_documents_translate(&self, _path: &PathBuf, _game: &GameVersion) -> Result { - Ok(CommonPath::Document.get().ok_or(BackupError::NotFound)?) - - } - fn win_program_data_translate(&self, _path: &PathBuf, _game: &GameVersion) -> Result { - Ok(PathBuf::from_str("C:/ProgramData").unwrap()) - } - fn win_public_translate(&self, _path: &PathBuf, _game: &GameVersion) -> Result { - Ok(CommonPath::Public.get().ok_or(BackupError::NotFound)?) - - } -} -pub struct MacBackupManager {} -impl BackupHandler for MacBackupManager {} \ No newline at end of file diff --git a/src-tauri/src/games/collections/commands.rs b/src-tauri/src/collections.rs similarity index 89% rename from src-tauri/src/games/collections/commands.rs rename to src-tauri/src/collections.rs index 0db6a49..2a1bc2c 100644 --- a/src-tauri/src/games/collections/commands.rs +++ b/src-tauri/src/collections.rs @@ -1,16 +1,12 @@ -use serde_json::json; - -use crate::{ - error::remote_access_error::RemoteAccessError, - remote::{ - auth::generate_authorization_header, - cache::{cache_object, get_cached_object}, - requests::{generate_url, make_authenticated_get}, - utils::DROP_CLIENT_ASYNC, - }, +use games::collections::collection::{Collection, Collections}; +use remote::{ + auth::generate_authorization_header, + cache::{cache_object, get_cached_object}, + error::RemoteAccessError, + requests::{generate_url, make_authenticated_get}, + utils::DROP_CLIENT_ASYNC, }; - -use super::collection::{Collection, Collections}; +use serde_json::json; #[tauri::command] pub async fn fetch_collections( diff --git a/src-tauri/src/database/mod.rs b/src-tauri/src/database/mod.rs deleted file mode 100644 index 6c77e25..0000000 --- a/src-tauri/src/database/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod commands; -pub mod db; -pub mod debug; -pub mod models; -pub mod scan; \ No newline at end of file diff --git a/src-tauri/src/download_manager.rs b/src-tauri/src/download_manager.rs new file mode 100644 index 0000000..cfc49c6 --- /dev/null +++ b/src-tauri/src/download_manager.rs @@ -0,0 +1,22 @@ +use database::DownloadableMetadata; +use download_manager::DOWNLOAD_MANAGER; + +#[tauri::command] +pub fn pause_downloads() { + DOWNLOAD_MANAGER.pause_downloads(); +} + +#[tauri::command] +pub fn resume_downloads() { + DOWNLOAD_MANAGER.resume_downloads(); +} + +#[tauri::command] +pub fn move_download_in_queue(old_index: usize, new_index: usize) { + DOWNLOAD_MANAGER.rearrange(old_index, new_index); +} + +#[tauri::command] +pub fn cancel_game(meta: DownloadableMetadata) { + DOWNLOAD_MANAGER.cancel(meta); +} diff --git a/src-tauri/src/download_manager/commands.rs b/src-tauri/src/download_manager/commands.rs deleted file mode 100644 index 3ee07e1..0000000 --- a/src-tauri/src/download_manager/commands.rs +++ /dev/null @@ -1,29 +0,0 @@ -use std::sync::Mutex; - -use crate::{AppState, database::models::data::DownloadableMetadata, lock}; - -#[tauri::command] -pub fn pause_downloads(state: tauri::State<'_, Mutex>) { - lock!(state).download_manager.pause_downloads(); -} - -#[tauri::command] -pub fn resume_downloads(state: tauri::State<'_, Mutex>) { - lock!(state).download_manager.resume_downloads(); -} - -#[tauri::command] -pub fn move_download_in_queue( - state: tauri::State<'_, Mutex>, - old_index: usize, - new_index: usize, -) { - lock!(state) - .download_manager - .rearrange(old_index, new_index); -} - -#[tauri::command] -pub fn cancel_game(state: tauri::State<'_, Mutex>, meta: DownloadableMetadata) { - lock!(state).download_manager.cancel(meta); -} diff --git a/src-tauri/src/download_manager/mod.rs b/src-tauri/src/download_manager/mod.rs deleted file mode 100644 index 756a1ad..0000000 --- a/src-tauri/src/download_manager/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod commands; -pub mod download_manager_builder; -pub mod download_manager_frontend; -pub mod downloadable; -pub mod util; diff --git a/src-tauri/src/games/downloads/commands.rs b/src-tauri/src/downloads.rs similarity index 55% rename from src-tauri/src/games/downloads/commands.rs rename to src-tauri/src/downloads.rs index b029fff..7625a67 100644 --- a/src-tauri/src/games/downloads/commands.rs +++ b/src-tauri/src/downloads.rs @@ -1,34 +1,31 @@ -use std::{ - path::PathBuf, - sync::{Arc, Mutex}, +use std::{path::PathBuf, sync::Arc}; + +use database::{GameDownloadStatus, borrow_db_checked}; +use download_manager::{ + DOWNLOAD_MANAGER, downloadable::Downloadable, error::ApplicationDownloadError, }; - - -use crate::{ - database::{ - db::borrow_db_checked, - models::data::GameDownloadStatus, - }, download_manager::downloadable::Downloadable, error::application_download_error::ApplicationDownloadError, lock, AppState -}; - -use super::download_agent::GameDownloadAgent; +use games::downloads::download_agent::GameDownloadAgent; #[tauri::command] pub async fn download_game( game_id: String, game_version: String, install_dir: usize, - state: tauri::State<'_, Mutex>>, ) -> Result<(), ApplicationDownloadError> { - let sender = { lock!(state).download_manager.get_sender().clone() }; + let sender = { DOWNLOAD_MANAGER.get_sender().clone() }; - let game_download_agent = - GameDownloadAgent::new_from_index(game_id.clone(), game_version.clone(), install_dir, sender).await?; + let game_download_agent = GameDownloadAgent::new_from_index( + game_id.clone(), + game_version.clone(), + install_dir, + sender, + ) + .await?; let game_download_agent = Arc::new(Box::new(game_download_agent) as Box); - lock!(state) - .download_manager + + DOWNLOAD_MANAGER .queue_download(game_download_agent.clone()) .unwrap(); @@ -36,10 +33,7 @@ pub async fn download_game( } #[tauri::command] -pub async fn resume_download( - game_id: String, - state: tauri::State<'_, Mutex>>, -) -> Result<(), ApplicationDownloadError> { +pub async fn resume_download(game_id: String) -> Result<(), ApplicationDownloadError> { let s = borrow_db_checked() .applications .game_statuses @@ -57,21 +51,25 @@ pub async fn resume_download( } => (version_name, install_dir), }; - let sender = lock!(state).download_manager.get_sender(); + let sender = DOWNLOAD_MANAGER.get_sender(); let parent_dir: PathBuf = install_dir.into(); let game_download_agent = Arc::new(Box::new( GameDownloadAgent::new( game_id, version_name.clone(), - parent_dir.parent().unwrap_or_else(|| panic!("Failed to get parent directry of {}", parent_dir.display())).to_path_buf(), + parent_dir + .parent() + .unwrap_or_else(|| { + panic!("Failed to get parent directry of {}", parent_dir.display()) + }) + .to_path_buf(), sender, ) .await?, ) as Box); - lock!(state) - .download_manager + DOWNLOAD_MANAGER .queue_download(game_download_agent) .unwrap(); Ok(()) diff --git a/src-tauri/src/error/cache_error.rs b/src-tauri/src/error/cache_error.rs deleted file mode 100644 index 8646a89..0000000 --- a/src-tauri/src/error/cache_error.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::fmt::Display; - -use http::{header::ToStrError, HeaderName}; -use serde_with::SerializeDisplay; - -use crate::error::remote_access_error::RemoteAccessError; - -#[derive(Debug, SerializeDisplay)] -pub enum CacheError { - HeaderNotFound(HeaderName), - ParseError(ToStrError), - Remote(RemoteAccessError), - ConstructionError(http::Error) -} - -impl Display for CacheError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let s = match self { - CacheError::HeaderNotFound(header_name) => format!("Could not find header {header_name} in cache"), - CacheError::ParseError(to_str_error) => format!("Could not parse cache with error {to_str_error}"), - CacheError::Remote(remote_access_error) => format!("Cache got remote access error: {remote_access_error}"), - CacheError::ConstructionError(error) => format!("Could not construct cache body with error {error}"), - }; - write!(f, "{s}") - } -} \ No newline at end of file diff --git a/src-tauri/src/error/download_manager_error.rs b/src-tauri/src/error/download_manager_error.rs deleted file mode 100644 index b2ca365..0000000 --- a/src-tauri/src/error/download_manager_error.rs +++ /dev/null @@ -1,27 +0,0 @@ -use std::{fmt::Display, io, sync::mpsc::SendError}; - -use serde_with::SerializeDisplay; - -#[derive(SerializeDisplay)] -pub enum DownloadManagerError { - IOError(io::Error), - SignalError(SendError), -} -impl Display for DownloadManagerError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - DownloadManagerError::IOError(error) => write!(f, "{error}"), - DownloadManagerError::SignalError(send_error) => write!(f, "{send_error}"), - } - } -} -impl From> for DownloadManagerError { - fn from(value: SendError) -> Self { - DownloadManagerError::SignalError(value) - } -} -impl From for DownloadManagerError { - fn from(value: io::Error) -> Self { - DownloadManagerError::IOError(value) - } -} diff --git a/src-tauri/src/error/drop_server_error.rs b/src-tauri/src/error/drop_server_error.rs deleted file mode 100644 index 26f371b..0000000 --- a/src-tauri/src/error/drop_server_error.rs +++ /dev/null @@ -1,10 +0,0 @@ -use serde::Deserialize; - -#[derive(Deserialize, Debug, Clone)] -#[serde(rename_all = "camelCase")] -pub struct DropServerError { - pub status_code: usize, - pub status_message: String, - // pub message: String, - // pub url: String, -} diff --git a/src-tauri/src/error/library_error.rs b/src-tauri/src/error/library_error.rs deleted file mode 100644 index 5d0ad4c..0000000 --- a/src-tauri/src/error/library_error.rs +++ /dev/null @@ -1,21 +0,0 @@ -use std::fmt::{Display}; - -use serde_with::SerializeDisplay; - -#[derive(SerializeDisplay)] -pub enum LibraryError { - MetaNotFound(String), - VersionNotFound(String), -} -impl Display for LibraryError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", match self { - LibraryError::MetaNotFound(id) => { - format!("Could not locate any installed version of game ID {id} in the database") - } - LibraryError::VersionNotFound(game_id) => { - format!("Could not locate any installed version for game id {game_id} in the database") - } - }) - } -} diff --git a/src-tauri/src/error/mod.rs b/src-tauri/src/error/mod.rs deleted file mode 100644 index 874837f..0000000 --- a/src-tauri/src/error/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -pub mod application_download_error; -pub mod download_manager_error; -pub mod drop_server_error; -pub mod library_error; -pub mod process_error; -pub mod remote_access_error; -pub mod cache_error; \ No newline at end of file diff --git a/src-tauri/src/games.rs b/src-tauri/src/games.rs new file mode 100644 index 0000000..cd72666 --- /dev/null +++ b/src-tauri/src/games.rs @@ -0,0 +1,344 @@ +use std::sync::nonpoison::Mutex; + +use database::{GameDownloadStatus, GameVersion, borrow_db_checked, borrow_db_mut_checked}; +use games::{ + downloads::error::LibraryError, + library::{FetchGameStruct, FrontendGameOptions, Game, get_current_meta, uninstall_game_logic}, + state::{GameStatusManager, GameStatusWithTransient}, +}; +use log::warn; +use process::PROCESS_MANAGER; +use remote::{ + auth::generate_authorization_header, + cache::{cache_object, cache_object_db, get_cached_object, get_cached_object_db}, + error::{DropServerError, RemoteAccessError}, + offline, + requests::generate_url, + utils::DROP_CLIENT_ASYNC, +}; +use tauri::AppHandle; + +use crate::AppState; + +#[tauri::command] +pub async fn fetch_library( + state: tauri::State<'_, Mutex>, + hard_refresh: Option, +) -> Result, RemoteAccessError> { + offline!( + state, + fetch_library_logic, + fetch_library_logic_offline, + state, + hard_refresh + ) + .await +} + +pub async fn fetch_library_logic( + state: tauri::State<'_, Mutex>, + hard_fresh: Option, +) -> Result, RemoteAccessError> { + let do_hard_refresh = hard_fresh.unwrap_or(false); + if !do_hard_refresh && let Ok(library) = get_cached_object("library") { + return Ok(library); + } + + let client = DROP_CLIENT_ASYNC.clone(); + let response = generate_url(&["/api/v1/client/user/library"], &[])?; + let response = client + .get(response) + .header("Authorization", generate_authorization_header()) + .send() + .await?; + + if response.status() != 200 { + let err = response.json().await.unwrap_or(DropServerError { + status_code: 500, + status_message: "Invalid response from server.".to_owned(), + }); + warn!("{err:?}"); + return Err(RemoteAccessError::InvalidResponse(err)); + } + + let mut games: Vec = response.json().await?; + + let mut handle = state.lock(); + + let mut db_handle = borrow_db_mut_checked(); + + for game in &games { + handle.games.insert(game.id().clone(), game.clone()); + if !db_handle.applications.game_statuses.contains_key(game.id()) { + db_handle + .applications + .game_statuses + .insert(game.id().clone(), GameDownloadStatus::Remote {}); + } + } + + // Add games that are installed but no longer in library + for meta in db_handle.applications.installed_game_version.values() { + if games.iter().any(|e| *e.id() == meta.id) { + continue; + } + // We should always have a cache of the object + // Pass db_handle because otherwise we get a gridlock + let game = match get_cached_object_db::(&meta.id.clone(), &db_handle) { + Ok(game) => game, + Err(err) => { + warn!( + "{} is installed, but encountered error fetching its error: {}.", + meta.id, err + ); + continue; + } + }; + games.push(game); + } + + drop(handle); + drop(db_handle); + cache_object("library", &games)?; + + Ok(games) +} +pub async fn fetch_library_logic_offline( + _state: tauri::State<'_, Mutex>, + _hard_refresh: Option, +) -> Result, RemoteAccessError> { + let mut games: Vec = get_cached_object("library")?; + + let db_handle = borrow_db_checked(); + + games.retain(|game| { + matches!( + &db_handle + .applications + .game_statuses + .get(game.id()) + .unwrap_or(&GameDownloadStatus::Remote {}), + GameDownloadStatus::Installed { .. } | GameDownloadStatus::SetupRequired { .. } + ) + }); + + Ok(games) +} +pub async fn fetch_game_logic( + id: String, + state: tauri::State<'_, Mutex>, +) -> Result { + let version = { + let state_handle = state.lock(); + + let db_lock = borrow_db_checked(); + + let metadata_option = db_lock.applications.installed_game_version.get(&id); + let version = match metadata_option { + None => None, + Some(metadata) => db_lock + .applications + .game_versions + .get(&metadata.id) + .map(|v| v.get(metadata.version.as_ref().unwrap()).unwrap()) + .cloned(), + }; + + let game = state_handle.games.get(&id); + if let Some(game) = game { + let status = GameStatusManager::fetch_state(&id, &db_lock); + + let data = FetchGameStruct::new(game.clone(), status, version); + + cache_object_db(&id, game, &db_lock)?; + + return Ok(data); + } + + version + }; + + let client = DROP_CLIENT_ASYNC.clone(); + let response = generate_url(&["/api/v1/client/game/", &id], &[])?; + let response = client + .get(response) + .header("Authorization", generate_authorization_header()) + .send() + .await?; + + if response.status() == 404 { + let offline_fetch = fetch_game_logic_offline(id.clone(), state).await; + if let Ok(fetch_data) = offline_fetch { + return Ok(fetch_data); + } + + return Err(RemoteAccessError::GameNotFound(id)); + } + if response.status() != 200 { + let err = response.json().await?; + warn!("{err:?}"); + return Err(RemoteAccessError::InvalidResponse(err)); + } + + let game: Game = response.json().await?; + + let mut state_handle = state.lock(); + state_handle.games.insert(id.clone(), game.clone()); + + let mut db_handle = borrow_db_mut_checked(); + + db_handle + .applications + .game_statuses + .entry(id.clone()) + .or_insert(GameDownloadStatus::Remote {}); + + let status = GameStatusManager::fetch_state(&id, &db_handle); + + drop(db_handle); + + let data = FetchGameStruct::new(game.clone(), status, version); + + cache_object(&id, &game)?; + + Ok(data) +} + +pub async fn fetch_game_version_options_logic( + game_id: String, + state: tauri::State<'_, Mutex>, +) -> Result, RemoteAccessError> { + let client = DROP_CLIENT_ASYNC.clone(); + + let response = generate_url(&["/api/v1/client/game/versions"], &[("id", &game_id)])?; + let response = client + .get(response) + .header("Authorization", generate_authorization_header()) + .send() + .await?; + + if response.status() != 200 { + let err = response.json().await?; + warn!("{err:?}"); + return Err(RemoteAccessError::InvalidResponse(err)); + } + + let data: Vec = response.json().await?; + + let state_lock = state.lock(); + let process_manager_lock = PROCESS_MANAGER.lock(); + let data: Vec = data + .into_iter() + .filter(|v| process_manager_lock.valid_platform(&v.platform)) + .collect(); + drop(process_manager_lock); + drop(state_lock); + + Ok(data) +} + +pub async fn fetch_game_logic_offline( + id: String, + _state: tauri::State<'_, Mutex>, +) -> Result { + let db_handle = borrow_db_checked(); + let metadata_option = db_handle.applications.installed_game_version.get(&id); + let version = match metadata_option { + None => None, + Some(metadata) => db_handle + .applications + .game_versions + .get(&metadata.id) + .map(|v| v.get(metadata.version.as_ref().unwrap()).unwrap()) + .cloned(), + }; + + let status = GameStatusManager::fetch_state(&id, &db_handle); + let game = get_cached_object::(&id)?; + + drop(db_handle); + + Ok(FetchGameStruct::new(game, status, version)) +} + +#[tauri::command] +pub async fn fetch_game( + game_id: String, + state: tauri::State<'_, Mutex>, +) -> Result { + offline!( + state, + fetch_game_logic, + fetch_game_logic_offline, + game_id, + state + ) + .await +} + +#[tauri::command] +pub fn fetch_game_status(id: String) -> GameStatusWithTransient { + let db_handle = borrow_db_checked(); + GameStatusManager::fetch_state(&id, &db_handle) +} + +#[tauri::command] +pub fn uninstall_game(game_id: String, app_handle: AppHandle) -> Result<(), LibraryError> { + let meta = match get_current_meta(&game_id) { + Some(data) => data, + None => return Err(LibraryError::MetaNotFound(game_id)), + }; + uninstall_game_logic(meta, &app_handle); + + Ok(()) +} + +#[tauri::command] +pub async fn fetch_game_version_options( + game_id: String, + state: tauri::State<'_, Mutex>, +) -> Result, RemoteAccessError> { + fetch_game_version_options_logic(game_id, state).await +} + +#[tauri::command] +pub fn update_game_configuration( + game_id: String, + options: FrontendGameOptions, +) -> Result<(), LibraryError> { + let mut handle = borrow_db_mut_checked(); + let installed_version = handle + .applications + .installed_game_version + .get(&game_id) + .ok_or(LibraryError::MetaNotFound(game_id))?; + + let id = installed_version.id.clone(); + let version = installed_version + .version + .clone() + .ok_or(LibraryError::VersionNotFound(id.clone()))?; + + let mut existing_configuration = handle + .applications + .game_versions + .get(&id) + .unwrap() + .get(&version) + .unwrap() + .clone(); + + // Add more options in here + existing_configuration.launch_command_template = options.launch_string().clone(); + + // Add no more options past here + + handle + .applications + .game_versions + .get_mut(&id) + .unwrap() + .insert(version.to_string(), existing_configuration); + + Ok(()) +} diff --git a/src-tauri/src/games/commands.rs b/src-tauri/src/games/commands.rs deleted file mode 100644 index e36d934..0000000 --- a/src-tauri/src/games/commands.rs +++ /dev/null @@ -1,78 +0,0 @@ -use std::sync::Mutex; - -use tauri::AppHandle; - -use crate::{ - AppState, - database::{ - db::borrow_db_checked, - models::data::GameVersion, - }, - error::{library_error::LibraryError, remote_access_error::RemoteAccessError}, - games::library::{ - fetch_game_logic_offline, fetch_library_logic_offline, get_current_meta, - uninstall_game_logic, - }, - offline, -}; - -use super::{ - library::{ - FetchGameStruct, Game, fetch_game_logic, fetch_game_version_options_logic, - fetch_library_logic, - }, - state::{GameStatusManager, GameStatusWithTransient}, -}; - -#[tauri::command] -pub async fn fetch_library( - state: tauri::State<'_, Mutex>>, - hard_refresh: Option, -) -> Result, RemoteAccessError> { - offline!( - state, - fetch_library_logic, - fetch_library_logic_offline, - state, - hard_refresh - ).await -} - -#[tauri::command] -pub async fn fetch_game( - game_id: String, - state: tauri::State<'_, Mutex>>, -) -> Result { - offline!( - state, - fetch_game_logic, - fetch_game_logic_offline, - game_id, - state - ).await -} - -#[tauri::command] -pub fn fetch_game_status(id: String) -> GameStatusWithTransient { - let db_handle = borrow_db_checked(); - GameStatusManager::fetch_state(&id, &db_handle) -} - -#[tauri::command] -pub fn uninstall_game(game_id: String, app_handle: AppHandle) -> Result<(), LibraryError> { - let meta = match get_current_meta(&game_id) { - Some(data) => data, - None => return Err(LibraryError::MetaNotFound(game_id)), - }; - uninstall_game_logic(meta, &app_handle); - - Ok(()) -} - -#[tauri::command] -pub async fn fetch_game_version_options( - game_id: String, - state: tauri::State<'_, Mutex>>, -) -> Result, RemoteAccessError> { - fetch_game_version_options_logic(game_id, state).await -} diff --git a/src-tauri/src/games/library.rs b/src-tauri/src/games/library.rs deleted file mode 100644 index 06cc58f..0000000 --- a/src-tauri/src/games/library.rs +++ /dev/null @@ -1,588 +0,0 @@ -use std::fs::remove_dir_all; -use std::sync::Mutex; -use std::thread::spawn; - -use log::{debug, error, warn}; -use serde::{Deserialize, Serialize}; -use tauri::AppHandle; -use tauri::Emitter; - -use crate::AppState; -use crate::app_emit; -use crate::database::db::{borrow_db_checked, borrow_db_mut_checked}; -use crate::database::models::data::Database; -use crate::database::models::data::{ - ApplicationTransientStatus, DownloadableMetadata, GameDownloadStatus, GameVersion, -}; -use crate::download_manager::download_manager_frontend::DownloadStatus; -use crate::error::drop_server_error::DropServerError; -use crate::error::library_error::LibraryError; -use crate::error::remote_access_error::RemoteAccessError; -use crate::games::state::{GameStatusManager, GameStatusWithTransient}; -use crate::lock; -use crate::remote::auth::generate_authorization_header; -use crate::remote::cache::cache_object_db; -use crate::remote::cache::{cache_object, get_cached_object, get_cached_object_db}; -use crate::remote::requests::generate_url; -use crate::remote::utils::DROP_CLIENT_ASYNC; -use crate::remote::utils::DROP_CLIENT_SYNC; -use bitcode::{Decode, Encode}; - -#[derive(Serialize, Deserialize, Debug)] -pub struct FetchGameStruct { - game: Game, - status: GameStatusWithTransient, - version: Option, -} - -#[derive(Serialize, Deserialize, Clone, Debug, Default, Encode, Decode)] -#[serde(rename_all = "camelCase")] -pub struct Game { - id: String, - m_name: String, - m_short_description: String, - m_description: String, - // mDevelopers - // mPublishers - m_icon_object_id: String, - m_banner_object_id: String, - m_cover_object_id: String, - m_image_library_object_ids: Vec, - m_image_carousel_object_ids: Vec, -} -#[derive(serde::Serialize, Clone)] -pub struct GameUpdateEvent { - pub game_id: String, - pub status: ( - Option, - Option, - ), - pub version: Option, -} - -#[derive(Serialize, Clone)] -pub struct QueueUpdateEventQueueData { - pub meta: DownloadableMetadata, - pub status: DownloadStatus, - pub progress: f64, - pub current: usize, - pub max: usize, -} - -#[derive(serde::Serialize, Clone)] -pub struct QueueUpdateEvent { - pub queue: Vec, -} - -#[derive(serde::Serialize, Clone)] -pub struct StatsUpdateEvent { - pub speed: usize, - pub time: usize, -} - -pub async fn fetch_library_logic( - state: tauri::State<'_, Mutex>>, - hard_fresh: Option, -) -> Result, RemoteAccessError> { - let do_hard_refresh = hard_fresh.unwrap_or(false); - if !do_hard_refresh && let Ok(library) = get_cached_object("library") { - return Ok(library); - } - - let client = DROP_CLIENT_ASYNC.clone(); - let response = generate_url(&["/api/v1/client/user/library"], &[])?; - let response = client - .get(response) - .header("Authorization", generate_authorization_header()) - .send() - .await?; - - if response.status() != 200 { - let err = response.json().await.unwrap_or(DropServerError { - status_code: 500, - status_message: "Invalid response from server.".to_owned(), - }); - warn!("{err:?}"); - return Err(RemoteAccessError::InvalidResponse(err)); - } - - let mut games: Vec = response.json().await?; - - let mut handle = lock!(state); - - let mut db_handle = borrow_db_mut_checked(); - - for game in &games { - handle.games.insert(game.id.clone(), game.clone()); - if !db_handle.applications.game_statuses.contains_key(&game.id) { - db_handle - .applications - .game_statuses - .insert(game.id.clone(), GameDownloadStatus::Remote {}); - } - } - - // Add games that are installed but no longer in library - for meta in db_handle.applications.installed_game_version.values() { - if games.iter().any(|e| e.id == meta.id) { - continue; - } - // We should always have a cache of the object - // Pass db_handle because otherwise we get a gridlock - let game = match get_cached_object_db::(&meta.id.clone(), &db_handle) { - Ok(game) => game, - Err(err) => { - warn!( - "{} is installed, but encountered error fetching its error: {}.", - meta.id, err - ); - continue; - } - }; - games.push(game); - } - - drop(handle); - drop(db_handle); - cache_object("library", &games)?; - - Ok(games) -} -pub async fn fetch_library_logic_offline( - _state: tauri::State<'_, Mutex>>, - _hard_refresh: Option, -) -> Result, RemoteAccessError> { - let mut games: Vec = get_cached_object("library")?; - - let db_handle = borrow_db_checked(); - - games.retain(|game| { - matches!( - &db_handle - .applications - .game_statuses - .get(&game.id) - .unwrap_or(&GameDownloadStatus::Remote {}), - GameDownloadStatus::Installed { .. } | GameDownloadStatus::SetupRequired { .. } - ) - }); - - Ok(games) -} -pub async fn fetch_game_logic( - id: String, - state: tauri::State<'_, Mutex>>, -) -> Result { - let version = { - let state_handle = lock!(state); - - let db_lock = borrow_db_checked(); - - let metadata_option = db_lock.applications.installed_game_version.get(&id); - let version = match metadata_option { - None => None, - Some(metadata) => db_lock - .applications - .game_versions - .get(&metadata.id) - .map(|v| v.get(metadata.version.as_ref().unwrap()).unwrap()) - .cloned(), - }; - - let game = state_handle.games.get(&id); - if let Some(game) = game { - let status = GameStatusManager::fetch_state(&id, &db_lock); - - let data = FetchGameStruct { - game: game.clone(), - status, - version, - }; - - cache_object_db(&id, game, &db_lock)?; - - return Ok(data); - } - - version - }; - - let client = DROP_CLIENT_ASYNC.clone(); - let response = generate_url(&["/api/v1/client/game/", &id], &[])?; - let response = client - .get(response) - .header("Authorization", generate_authorization_header()) - .send() - .await?; - - if response.status() == 404 { - let offline_fetch = fetch_game_logic_offline(id.clone(), state).await; - if let Ok(fetch_data) = offline_fetch { - return Ok(fetch_data); - } - - return Err(RemoteAccessError::GameNotFound(id)); - } - if response.status() != 200 { - let err = response.json().await?; - warn!("{err:?}"); - return Err(RemoteAccessError::InvalidResponse(err)); - } - - let game: Game = response.json().await?; - - let mut state_handle = lock!(state); - state_handle.games.insert(id.clone(), game.clone()); - - let mut db_handle = borrow_db_mut_checked(); - - db_handle - .applications - .game_statuses - .entry(id.clone()) - .or_insert(GameDownloadStatus::Remote {}); - - let status = GameStatusManager::fetch_state(&id, &db_handle); - - drop(db_handle); - - let data = FetchGameStruct { - game: game.clone(), - status, - version, - }; - - cache_object(&id, &game)?; - - Ok(data) -} - -pub async fn fetch_game_logic_offline( - id: String, - _state: tauri::State<'_, Mutex>>, -) -> Result { - let db_handle = borrow_db_checked(); - let metadata_option = db_handle.applications.installed_game_version.get(&id); - let version = match metadata_option { - None => None, - Some(metadata) => db_handle - .applications - .game_versions - .get(&metadata.id) - .map(|v| v.get(metadata.version.as_ref().unwrap()).unwrap()) - .cloned(), - }; - - let status = GameStatusManager::fetch_state(&id, &db_handle); - let game = get_cached_object::(&id)?; - - drop(db_handle); - - Ok(FetchGameStruct { - game, - status, - version, - }) -} - -pub async fn fetch_game_version_options_logic( - game_id: String, - state: tauri::State<'_, Mutex>>, -) -> Result, RemoteAccessError> { - let client = DROP_CLIENT_ASYNC.clone(); - - let response = generate_url(&["/api/v1/client/game/versions"], &[("id", &game_id)])?; - let response = client - .get(response) - .header("Authorization", generate_authorization_header()) - .send() - .await?; - - if response.status() != 200 { - let err = response.json().await?; - warn!("{err:?}"); - return Err(RemoteAccessError::InvalidResponse(err)); - } - - let data: Vec = response.json().await?; - - let state_lock = lock!(state); - let process_manager_lock = lock!(state_lock.process_manager); - let data: Vec = data - .into_iter() - .filter(|v| process_manager_lock.valid_platform(&v.platform, &state_lock)) - .collect(); - drop(process_manager_lock); - drop(state_lock); - - Ok(data) -} - -/** - * Called by: - * - on_cancel, when cancelled, for obvious reasons - * - when downloading, so if drop unexpectedly quits, we can resume the download. hidden by the "Downloading..." transient state, though - * - when scanning, to import the game - */ -pub fn set_partially_installed( - meta: &DownloadableMetadata, - install_dir: String, - app_handle: Option<&AppHandle>, -) { - set_partially_installed_db(&mut borrow_db_mut_checked(), meta, install_dir, app_handle); -} - -pub fn set_partially_installed_db( - db_lock: &mut Database, - meta: &DownloadableMetadata, - install_dir: String, - app_handle: Option<&AppHandle>, -) { - db_lock.applications.transient_statuses.remove(meta); - db_lock.applications.game_statuses.insert( - meta.id.clone(), - GameDownloadStatus::PartiallyInstalled { - version_name: meta.version.as_ref().unwrap().clone(), - install_dir, - }, - ); - db_lock - .applications - .installed_game_version - .insert(meta.id.clone(), meta.clone()); - - if let Some(app_handle) = app_handle { - push_game_update( - app_handle, - &meta.id, - None, - GameStatusManager::fetch_state(&meta.id, db_lock), - ); - } -} - -pub fn uninstall_game_logic(meta: DownloadableMetadata, app_handle: &AppHandle) { - debug!("triggered uninstall for agent"); - let mut db_handle = borrow_db_mut_checked(); - db_handle - .applications - .transient_statuses - .insert(meta.clone(), ApplicationTransientStatus::Uninstalling {}); - - push_game_update( - app_handle, - &meta.id, - None, - GameStatusManager::fetch_state(&meta.id, &db_handle), - ); - - let previous_state = db_handle.applications.game_statuses.get(&meta.id).cloned(); - - let previous_state = if let Some(state) = previous_state { - state - } else { - warn!("uninstall job doesn't have previous state, failing silently"); - return; - }; - - if let Some((_, install_dir)) = match previous_state { - GameDownloadStatus::Installed { - version_name, - install_dir, - } => Some((version_name, install_dir)), - GameDownloadStatus::SetupRequired { - version_name, - install_dir, - } => Some((version_name, install_dir)), - GameDownloadStatus::PartiallyInstalled { - version_name, - install_dir, - } => Some((version_name, install_dir)), - _ => None, - } { - db_handle - .applications - .transient_statuses - .insert(meta.clone(), ApplicationTransientStatus::Uninstalling {}); - - drop(db_handle); - - let app_handle = app_handle.clone(); - spawn(move || { - if let Err(e) = remove_dir_all(install_dir) { - error!("{e}"); - } else { - let mut db_handle = borrow_db_mut_checked(); - db_handle.applications.transient_statuses.remove(&meta); - db_handle - .applications - .installed_game_version - .remove(&meta.id); - db_handle - .applications - .game_statuses - .insert(meta.id.clone(), GameDownloadStatus::Remote {}); - let _ = db_handle.applications.transient_statuses.remove(&meta); - - push_game_update( - &app_handle, - &meta.id, - None, - GameStatusManager::fetch_state(&meta.id, &db_handle), - ); - - debug!("uninstalled game id {}", &meta.id); - app_emit!(app_handle, "update_library", ()); - } - }); - } else { - warn!("invalid previous state for uninstall, failing silently."); - } -} - -pub fn get_current_meta(game_id: &String) -> Option { - borrow_db_checked() - .applications - .installed_game_version - .get(game_id) - .cloned() -} - -pub fn on_game_complete( - meta: &DownloadableMetadata, - install_dir: String, - app_handle: &AppHandle, -) -> Result<(), RemoteAccessError> { - // Fetch game version information from remote - if meta.version.is_none() { - return Err(RemoteAccessError::GameNotFound(meta.id.clone())); - } - - let client = DROP_CLIENT_SYNC.clone(); - let response = generate_url( - &["/api/v1/client/game/version"], - &[ - ("id", &meta.id), - ("version", meta.version.as_ref().unwrap()), - ], - )?; - let response = client - .get(response) - .header("Authorization", generate_authorization_header()) - .send()?; - - let game_version: GameVersion = response.json()?; - - let mut handle = borrow_db_mut_checked(); - handle - .applications - .game_versions - .entry(meta.id.clone()) - .or_default() - .insert(meta.version.clone().unwrap(), game_version.clone()); - handle - .applications - .installed_game_version - .insert(meta.id.clone(), meta.clone()); - - drop(handle); - - let status = if game_version.setup_command.is_empty() { - GameDownloadStatus::Installed { - version_name: meta.version.clone().unwrap(), - install_dir, - } - } else { - GameDownloadStatus::SetupRequired { - version_name: meta.version.clone().unwrap(), - install_dir, - } - }; - - let mut db_handle = borrow_db_mut_checked(); - db_handle - .applications - .game_statuses - .insert(meta.id.clone(), status.clone()); - drop(db_handle); - app_emit!( - app_handle, - &format!("update_game/{}", meta.id), - GameUpdateEvent { - game_id: meta.id.clone(), - status: (Some(status), None), - version: Some(game_version), - } - ); - - Ok(()) -} - -pub fn push_game_update( - app_handle: &AppHandle, - game_id: &String, - version: Option, - status: GameStatusWithTransient, -) { - if let Some(GameDownloadStatus::Installed { .. } | GameDownloadStatus::SetupRequired { .. }) = - &status.0 - && version.is_none() - { - panic!("pushed game for installed game that doesn't have version information"); - } - - app_emit!( - app_handle, - &format!("update_game/{game_id}"), - GameUpdateEvent { - game_id: game_id.clone(), - status, - version, - } - ); -} - -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct FrontendGameOptions { - launch_string: String, -} - -#[tauri::command] -pub fn update_game_configuration( - game_id: String, - options: FrontendGameOptions, -) -> Result<(), LibraryError> { - let mut handle = borrow_db_mut_checked(); - let installed_version = handle - .applications - .installed_game_version - .get(&game_id) - .ok_or(LibraryError::MetaNotFound(game_id))?; - - let id = installed_version.id.clone(); - let version = installed_version.version.clone().ok_or(LibraryError::VersionNotFound(id.clone()))?; - - let mut existing_configuration = handle - .applications - .game_versions - .get(&id) - .unwrap() - .get(&version) - .unwrap() - .clone(); - - // Add more options in here - existing_configuration.launch_command_template = options.launch_string; - - // Add no more options past here - - handle - .applications - .game_versions - .get_mut(&id) - .unwrap() - .insert(version.to_string(), existing_configuration); - - Ok(()) -} diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 2b68ffd..0a84f6c 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -3,136 +3,79 @@ #![feature(duration_constructors)] #![feature(duration_millis_float)] #![feature(iterator_try_collect)] +#![feature(nonpoison_mutex)] +#![feature(sync_nonpoison)] #![deny(clippy::all)] -mod database; -mod games; - -mod client; -mod download_manager; -mod error; -mod process; -mod remote; -mod utils; - -use crate::database::scan::scan_install_dirs; -use crate::process::commands::open_process_logs; -use crate::process::process_handlers::UMU_LAUNCHER_EXECUTABLE; -use crate::remote::commands::auth_initiate_code; -use crate::remote::fetch_object::fetch_object_wrapper; -use crate::remote::server_proto::handle_server_proto_wrapper; -use crate::{database::db::DatabaseImpls, games::downloads::commands::resume_download}; -use bitcode::{Decode, Encode}; -use client::commands::fetch_state; -use client::{ - autostart::{get_autostart_enabled, sync_autostart_on_startup, toggle_autostart}, - cleanup::{cleanup_and_exit, quit}, -}; -use database::commands::{ - add_download_dir, delete_download_dir, fetch_download_dir_stats, fetch_settings, - fetch_system_data, update_settings, -}; -use database::db::{DATA_ROOT_DIR, DatabaseInterface, borrow_db_checked, borrow_db_mut_checked}; -use database::models::data::GameDownloadStatus; -use download_manager::commands::{ - cancel_game, move_download_in_queue, pause_downloads, resume_downloads, -}; -use download_manager::download_manager_builder::DownloadManagerBuilder; -use download_manager::download_manager_frontend::DownloadManager; -use games::collections::commands::{ - add_game_to_collection, create_collection, delete_collection, delete_game_in_collection, - fetch_collection, fetch_collections, -}; -use games::commands::{ - fetch_game, fetch_game_status, fetch_game_version_options, fetch_library, uninstall_game, -}; -use games::downloads::commands::download_game; -use games::library::{Game, update_game_configuration}; -use log::{LevelFilter, debug, info, warn}; -use log4rs::Config; -use log4rs::append::console::ConsoleAppender; -use log4rs::append::file::FileAppender; -use log4rs::config::{Appender, Root}; -use log4rs::encode::pattern::PatternEncoder; -use process::commands::{kill_game, launch_game}; -use process::process_manager::ProcessManager; -use remote::auth::{self, recieve_handshake}; -use remote::commands::{ - auth_initiate, fetch_drop_object, gen_drop_url, manual_recieve_handshake, retry_connect, - sign_out, use_remote, -}; -use remote::server_proto::handle_server_proto_offline_wrapper; -use serde::{Deserialize, Serialize}; -use std::fs::File; -use std::io::Write; -use std::panic::PanicHookInfo; -use std::path::Path; -use std::str::FromStr; -use std::sync::Arc; -use std::time::SystemTime; use std::{ - collections::HashMap, - sync::{LazyLock, Mutex}, + collections::HashMap, env, fs::File, io::Write, panic::PanicHookInfo, path::Path, str::FromStr, + sync::nonpoison::Mutex, time::SystemTime, +}; + +use ::client::{app_status::AppStatus, autostart::sync_autostart_on_startup, user::User}; +use ::download_manager::DownloadManagerWrapper; +use ::games::{library::Game, scan::scan_install_dirs}; +use ::process::ProcessManagerWrapper; +use ::remote::{ + auth::{self, HandshakeRequestBody, HandshakeResponse, generate_authorization_header}, + cache::clear_cached_object, + error::RemoteAccessError, + fetch_object::fetch_object_wrapper, + offline, + server_proto::{handle_server_proto_offline_wrapper, handle_server_proto_wrapper}, + utils::DROP_CLIENT_ASYNC, +}; +use database::{ + DB, GameDownloadStatus, borrow_db_checked, borrow_db_mut_checked, db::DATA_ROOT_DIR, + interface::DatabaseImpls, +}; +use log::{LevelFilter, debug, info, warn}; +use log4rs::{ + Config, + append::{console::ConsoleAppender, file::FileAppender}, + config::{Appender, Root}, + encode::pattern::PatternEncoder, +}; +use serde::Serialize; +use tauri::{ + AppHandle, Manager, RunEvent, WindowEvent, + menu::{Menu, MenuItem, PredefinedMenuItem}, + tray::TrayIconBuilder, }; -use std::{env, panic}; -use tauri::menu::{Menu, MenuItem, PredefinedMenuItem}; -use tauri::tray::TrayIconBuilder; -use tauri::{AppHandle, Manager, RunEvent, WindowEvent}; use tauri_plugin_deep_link::DeepLinkExt; use tauri_plugin_dialog::DialogExt; +use url::Url; +use utils::app_emit; -#[derive(Clone, Copy, Serialize, Eq, PartialEq)] -pub enum AppStatus { - NotConfigured, - Offline, - ServerError, - SignedOut, - SignedIn, - SignedInNeedsReauth, - ServerUnavailable, -} +use crate::client::cleanup_and_exit; -#[derive(Clone, Serialize, Deserialize, Encode, Decode)] -#[serde(rename_all = "camelCase")] -pub struct User { - id: String, - username: String, - admin: bool, - display_name: String, - profile_picture_object_id: String, -} +mod client; +mod collections; +mod download_manager; +mod downloads; +mod games; +mod process; +mod remote; +mod settings; -#[derive(Clone)] -pub struct CompatInfo { - umu_installed: bool, -} - -fn create_new_compat_info() -> Option { - #[cfg(target_os = "windows")] - return None; - - let has_umu_installed = UMU_LAUNCHER_EXECUTABLE.is_some(); - Some(CompatInfo { - umu_installed: has_umu_installed, - }) -} +use client::*; +use collections::*; +use download_manager::*; +use downloads::*; +use games::*; +use process::*; +use remote::*; +use settings::*; #[derive(Clone, Serialize)] #[serde(rename_all = "camelCase")] -pub struct AppState<'a> { +pub struct AppState { status: AppStatus, user: Option, games: HashMap, - - #[serde(skip_serializing)] - download_manager: Arc, - #[serde(skip_serializing)] - process_manager: Arc>>, - #[serde(skip_serializing)] - compat_info: Option, } -async fn setup(handle: AppHandle) -> AppState<'static> { +async fn setup(handle: AppHandle) -> AppState { let logfile = FileAppender::builder() .encoder(Box::new(PatternEncoder::new( "{d} | {l} | {f}:{L} - {m}{n}", @@ -164,9 +107,9 @@ async fn setup(handle: AppHandle) -> AppState<'static> { log4rs::init_config(config).expect("Failed to initialise log4rs"); let games = HashMap::new(); - let download_manager = Arc::new(DownloadManagerBuilder::build(handle.clone())); - let process_manager = Arc::new(Mutex::new(ProcessManager::new(handle.clone()))); - let compat_info = create_new_compat_info(); + + ProcessManagerWrapper::init(handle.clone()); + DownloadManagerWrapper::init(handle.clone()); debug!("checking if database is set up"); let is_set_up = DB.database_is_set_up(); @@ -178,9 +121,6 @@ async fn setup(handle: AppHandle) -> AppState<'static> { status: AppStatus::NotConfigured, user: None, games, - download_manager, - process_manager, - compat_info, }; } @@ -243,14 +183,9 @@ async fn setup(handle: AppHandle) -> AppState<'static> { status: app_status, user, games, - download_manager, - process_manager, - compat_info, } } -pub static DB: LazyLock = LazyLock::new(DatabaseInterface::set_up_database); - pub fn custom_panic_handler(e: &PanicHookInfo) -> Option<()> { let crash_file = DATA_ROOT_DIR.join(format!( "crash-{}.log", @@ -269,7 +204,7 @@ pub fn custom_panic_handler(e: &PanicHookInfo) -> Option<()> { #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { - panic::set_hook(Box::new(|e| { + std::panic::set_hook(Box::new(|e| { let _ = custom_panic_handler(e); println!("{e}"); })); @@ -385,17 +320,20 @@ pub fn run() { } }; if let Some("handshake") = url.host_str() { - tauri::async_runtime::spawn(recieve_handshake( - handle.clone(), - url.path().to_string(), - )); + tauri::async_runtime::spawn(recieve_handshake( + handle.clone(), + url.path().to_string(), + )); } }); - let open_menu_item = MenuItem::with_id(app, "open", "Open", true, None::<&str>).expect("Failed to generate open menu item"); - - let sep = PredefinedMenuItem::separator(app).expect("Failed to generate menu separator item"); + let open_menu_item = MenuItem::with_id(app, "open", "Open", true, None::<&str>) + .expect("Failed to generate open menu item"); - let quit_menu_item = MenuItem::with_id(app, "quit", "Quit", true, None::<&str>).expect("Failed to generate quit menu item"); + let sep = PredefinedMenuItem::separator(app) + .expect("Failed to generate menu separator item"); + + let quit_menu_item = MenuItem::with_id(app, "quit", "Quit", true, None::<&str>) + .expect("Failed to generate quit menu item"); let menu = Menu::with_items( app, @@ -414,7 +352,11 @@ pub fn run() { run_on_tray(|| { TrayIconBuilder::new() - .icon(app.default_window_icon().expect("Failed to get default window icon").clone()) + .icon( + app.default_window_icon() + .expect("Failed to get default window icon") + .clone(), + ) .menu(&menu) .on_menu_event(|app, event| match event.id.as_ref() { "open" => { @@ -425,7 +367,7 @@ pub fn run() { .expect("Failed to show window"); } "quit" => { - cleanup_and_exit(app, &app.state()); + cleanup_and_exit(app); } _ => { @@ -511,3 +453,85 @@ fn run_on_tray(f: T) { (f)(); } } + +// TODO: Refactor +pub async fn recieve_handshake(app: AppHandle, path: String) { + // Tell the app we're processing + app_emit!(&app, "auth/processing", ()); + + let handshake_result = recieve_handshake_logic(&app, path).await; + if let Err(e) = handshake_result { + warn!("error with authentication: {e}"); + app_emit!(&app, "auth/failed", e.to_string()); + return; + } + + let app_state = app.state::>(); + + let (app_status, user) = auth::setup().await; + + let mut state_lock = app_state.lock(); + + state_lock.status = app_status; + state_lock.user = user; + + let _ = clear_cached_object("collections"); + let _ = clear_cached_object("library"); + + drop(state_lock); + + app_emit!(&app, "auth/finished", ()); +} + +// TODO: Refactor +async fn recieve_handshake_logic(app: &AppHandle, path: String) -> Result<(), RemoteAccessError> { + let path_chunks: Vec<&str> = path.split('/').collect(); + if path_chunks.len() != 3 { + app_emit!(app, "auth/failed", ()); + return Err(RemoteAccessError::HandshakeFailed( + "failed to parse token".to_string(), + )); + } + + let base_url = { + let handle = borrow_db_checked(); + Url::parse(handle.base_url.as_str())? + }; + + let client_id = path_chunks + .get(1) + .expect("Failed to get client id from path chunks"); + let token = path_chunks + .get(2) + .expect("Failed to get token from path chunks"); + let body = HandshakeRequestBody::new((client_id).to_string(), (token).to_string()); + + let endpoint = base_url.join("/api/v1/client/auth/handshake")?; + let client = DROP_CLIENT_ASYNC.clone(); + let response = client.post(endpoint).json(&body).send().await?; + debug!("handshake responsded with {}", response.status().as_u16()); + if !response.status().is_success() { + return Err(RemoteAccessError::InvalidResponse(response.json().await?)); + } + let response_struct: HandshakeResponse = response.json().await?; + + { + let mut handle = borrow_db_mut_checked(); + handle.auth = Some(response_struct.into()); + } + + let web_token = { + let header = generate_authorization_header(); + let token = client + .post(base_url.join("/api/v1/client/user/webtoken")?) + .header("Authorization", header) + .send() + .await?; + + token.text().await? + }; + let mut handle = borrow_db_mut_checked(); + handle.auth.as_mut().unwrap().web_token = Some(web_token); + + Ok(()) +} diff --git a/src-tauri/src/process.rs b/src-tauri/src/process.rs new file mode 100644 index 0000000..fb5f153 --- /dev/null +++ b/src-tauri/src/process.rs @@ -0,0 +1,50 @@ +use std::sync::nonpoison::Mutex; + +use process::{PROCESS_MANAGER, error::ProcessError}; +use tauri::AppHandle; +use tauri_plugin_opener::OpenerExt; + +use crate::AppState; + +#[tauri::command] +pub fn launch_game( + id: String, + state: tauri::State<'_, Mutex>, +) -> Result<(), ProcessError> { + let state_lock = state.lock(); + let mut process_manager_lock = PROCESS_MANAGER.lock(); + //let meta = DownloadableMetadata { + // id, + // version: Some(version), + // download_type: DownloadType::Game, + //}; + + match process_manager_lock.launch_process(id) { + Ok(()) => {} + Err(e) => return Err(e), + } + + drop(process_manager_lock); + drop(state_lock); + + Ok(()) +} + +#[tauri::command] +pub fn kill_game(game_id: String) -> Result<(), ProcessError> { + PROCESS_MANAGER + .lock() + .kill_game(game_id) + .map_err(ProcessError::IOError) +} + +#[tauri::command] +pub fn open_process_logs(game_id: String, app_handle: AppHandle) -> Result<(), ProcessError> { + let process_manager_lock = PROCESS_MANAGER.lock(); + + let dir = process_manager_lock.get_log_dir(game_id); + app_handle + .opener() + .open_path(dir.display().to_string(), None::<&str>) + .map_err(ProcessError::OpenerError) +} diff --git a/src-tauri/src/process/commands.rs b/src-tauri/src/process/commands.rs deleted file mode 100644 index 29a554c..0000000 --- a/src-tauri/src/process/commands.rs +++ /dev/null @@ -1,50 +0,0 @@ -use std::sync::Mutex; - -use crate::{error::process_error::ProcessError, lock, AppState}; - -#[tauri::command] -pub fn launch_game( - id: String, - state: tauri::State<'_, Mutex>, -) -> Result<(), ProcessError> { - let state_lock = lock!(state); - let mut process_manager_lock = lock!(state_lock.process_manager); - - //let meta = DownloadableMetadata { - // id, - // version: Some(version), - // download_type: DownloadType::Game, - //}; - - match process_manager_lock.launch_process(id, &state_lock) { - Ok(()) => {} - Err(e) => return Err(e), - } - - drop(process_manager_lock); - drop(state_lock); - - Ok(()) -} - -#[tauri::command] -pub fn kill_game( - game_id: String, - state: tauri::State<'_, Mutex>, -) -> Result<(), ProcessError> { - let state_lock = lock!(state); - let mut process_manager_lock = lock!(state_lock.process_manager); - process_manager_lock - .kill_game(game_id) - .map_err(ProcessError::IOError) -} - -#[tauri::command] -pub fn open_process_logs( - game_id: String, - state: tauri::State<'_, Mutex>, -) -> Result<(), ProcessError> { - let state_lock = lock!(state); - let mut process_manager_lock = lock!(state_lock.process_manager); - process_manager_lock.open_process_logs(game_id) -} diff --git a/src-tauri/src/process/mod.rs b/src-tauri/src/process/mod.rs deleted file mode 100644 index fa1089e..0000000 --- a/src-tauri/src/process/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod commands; -pub mod process_manager; -pub mod process_handlers; -pub mod format; -pub mod utils; \ No newline at end of file diff --git a/src-tauri/src/remote/commands.rs b/src-tauri/src/remote.rs similarity index 72% rename from src-tauri/src/remote/commands.rs rename to src-tauri/src/remote.rs index b71e360..2d4585f 100644 --- a/src-tauri/src/remote/commands.rs +++ b/src-tauri/src/remote.rs @@ -1,37 +1,57 @@ -use std::sync::Mutex; +use std::{sync::nonpoison::Mutex, time::Duration}; +use client::app_status::AppStatus; +use database::{borrow_db_checked, borrow_db_mut_checked}; use futures_lite::StreamExt; use log::{debug, warn}; +use remote::{ + auth::{auth_initiate_logic, generate_authorization_header}, + cache::{cache_object, get_cached_object}, + error::RemoteAccessError, + requests::generate_url, + setup, + utils::{DROP_CLIENT_ASYNC, DROP_CLIENT_WS_CLIENT, DropHealthcheck}, +}; use reqwest_websocket::{Message, RequestBuilderExt}; use serde::Deserialize; -use tauri::{AppHandle, Emitter, Manager}; +use tauri::{AppHandle, Manager}; use url::Url; +use utils::{app_emit, webbrowser_open::webbrowser_open}; -use crate::{ - AppState, AppStatus, app_emit, - database::db::{borrow_db_checked, borrow_db_mut_checked}, - error::remote_access_error::RemoteAccessError, - lock, - remote::{ - auth::generate_authorization_header, - requests::generate_url, - utils::{DROP_CLIENT_SYNC, DROP_CLIENT_WS_CLIENT}, - }, - utils::webbrowser_open::webbrowser_open, -}; - -use super::{ - auth::{auth_initiate_logic, recieve_handshake, setup}, - cache::{cache_object, get_cached_object}, - utils::use_remote_logic, -}; +use crate::{AppState, recieve_handshake}; #[tauri::command] pub async fn use_remote( url: String, - state: tauri::State<'_, Mutex>>, + state: tauri::State<'_, Mutex>, ) -> Result<(), RemoteAccessError> { - use_remote_logic(url, state).await + debug!("connecting to url {url}"); + let base_url = Url::parse(&url)?; + + // Test Drop url + let test_endpoint = base_url.join("/api/v1")?; + let client = DROP_CLIENT_ASYNC.clone(); + let response = client + .get(test_endpoint.to_string()) + .timeout(Duration::from_secs(3)) + .send() + .await?; + + let result: DropHealthcheck = response.json().await?; + + if result.app_name() != "Drop" { + warn!("user entered drop endpoint that connected, but wasn't identified as Drop"); + return Err(RemoteAccessError::InvalidEndpoint); + } + + let mut app_state = state.lock(); + app_state.status = AppStatus::SignedOut; + drop(app_state); + + let mut db_state = borrow_db_mut_checked(); + db_state.base_url = base_url.to_string(); + + Ok(()) } #[tauri::command] @@ -51,7 +71,7 @@ pub fn gen_drop_url(path: String) -> Result { pub fn fetch_drop_object(path: String) -> Result, RemoteAccessError> { let _drop_url = gen_drop_url(path.clone())?; let req = generate_url(&[&path], &[])?; - let req = DROP_CLIENT_SYNC + let req = remote::utils::DROP_CLIENT_SYNC .get(req) .header("Authorization", generate_authorization_header()) .send(); @@ -78,21 +98,21 @@ pub fn sign_out(app: AppHandle) { // Update app state { - let app_state = app.state::>(); - let mut app_state_handle = lock!(app_state); + let state = app.state::>(); + let mut app_state_handle = state.lock(); app_state_handle.status = AppStatus::SignedOut; app_state_handle.user = None; } // Emit event for frontend - app_emit!(app, "auth/signedout", ()); + app_emit!(&app, "auth/signedout", ()); } #[tauri::command] -pub async fn retry_connect(state: tauri::State<'_, Mutex>>) -> Result<(), ()> { +pub async fn retry_connect(state: tauri::State<'_, Mutex>) -> Result<(), ()> { let (app_status, user) = setup().await; - let mut guard = lock!(state); + let mut guard = state.lock(); guard.status = app_status; guard.user = user; drop(guard); @@ -168,7 +188,7 @@ pub fn auth_initiate_code(app: AppHandle) -> Result { let result = load().await; if let Err(err) = result { warn!("{err}"); - app_emit!(app, "auth/failed", err.to_string()); + app_emit!(&app, "auth/failed", err.to_string()); } }); diff --git a/src-tauri/src/database/commands.rs b/src-tauri/src/settings.rs similarity index 91% rename from src-tauri/src/database/commands.rs rename to src-tauri/src/settings.rs index ae486f7..9faeab2 100644 --- a/src-tauri/src/database/commands.rs +++ b/src-tauri/src/settings.rs @@ -4,20 +4,14 @@ use std::{ path::{Path, PathBuf}, }; +use database::{ + Settings, borrow_db_checked, borrow_db_mut_checked, db::DATA_ROOT_DIR, debug::SystemData, +}; +use download_manager::error::DownloadManagerError; +use games::scan::scan_install_dirs; use log::error; use serde_json::Value; -use crate::{ - database::{db::borrow_db_mut_checked, scan::scan_install_dirs}, - error::download_manager_error::DownloadManagerError, -}; - -use super::{ - db::{DATA_ROOT_DIR, borrow_db_checked}, - debug::SystemData, - models::data::Settings, -}; - // Will, in future, return disk/remaining size // Just returns the directories that have been set up #[tauri::command] diff --git a/src-tauri/src/utils/app_emit.rs b/src-tauri/src/utils/app_emit.rs deleted file mode 100644 index 0402b2d..0000000 --- a/src-tauri/src/utils/app_emit.rs +++ /dev/null @@ -1,6 +0,0 @@ -#[macro_export] -macro_rules! app_emit { - ($app:expr, $event:expr, $p:expr) => { - $app.emit($event, $p).expect(&format!("Failed to emit event {}", $event)); - }; -} diff --git a/src-tauri/src/utils/download_manager_send.rs b/src-tauri/src/utils/download_manager_send.rs deleted file mode 100644 index b9f5e80..0000000 --- a/src-tauri/src/utils/download_manager_send.rs +++ /dev/null @@ -1,6 +0,0 @@ -#[macro_export] -macro_rules! send { - ($download_manager:expr, $signal:expr) => { - $download_manager.send($signal).unwrap_or_else(|_| panic!("Failed to send signal {} to the download manager", stringify!(signal))) - }; -} \ No newline at end of file diff --git a/src-tauri/src/utils/lock.rs b/src-tauri/src/utils/lock.rs deleted file mode 100644 index 6634fe2..0000000 --- a/src-tauri/src/utils/lock.rs +++ /dev/null @@ -1,6 +0,0 @@ -#[macro_export] -macro_rules! lock { - ($mutex:expr) => { - $mutex.lock().unwrap_or_else(|_| panic!("Failed to lock onto {}", stringify!($mutex))) - }; -} \ No newline at end of file diff --git a/src-tauri/src/utils/webbrowser_open.rs b/src-tauri/src/utils/webbrowser_open.rs deleted file mode 100644 index 9cbec6c..0000000 --- a/src-tauri/src/utils/webbrowser_open.rs +++ /dev/null @@ -1,7 +0,0 @@ -use log::warn; - -pub fn webbrowser_open>(url: T) { - if let Err(e) = webbrowser::open(url.as_ref()) { - warn!("Could not open web browser to url {} with error {}", url.as_ref(), e); - }; -} \ No newline at end of file diff --git a/src-tauri/utils/Cargo.toml b/src-tauri/utils/Cargo.toml new file mode 100644 index 0000000..921e852 --- /dev/null +++ b/src-tauri/utils/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "utils" +version = "0.1.0" +edition = "2024" + +[dependencies] +log = "0.4.28" +webbrowser = "1.0.5" diff --git a/src-tauri/utils/src/app_emit.rs b/src-tauri/utils/src/app_emit.rs new file mode 100644 index 0000000..c70b932 --- /dev/null +++ b/src-tauri/utils/src/app_emit.rs @@ -0,0 +1,7 @@ +#[macro_export] +macro_rules! app_emit { + ($app:expr, $event:expr, $p:expr) => { + ::tauri::Emitter::emit($app, $event, $p) + .expect(&format!("Failed to emit event {}", $event)); + }; +} diff --git a/src-tauri/utils/src/download_manager_send.rs b/src-tauri/utils/src/download_manager_send.rs new file mode 100644 index 0000000..dc98429 --- /dev/null +++ b/src-tauri/utils/src/download_manager_send.rs @@ -0,0 +1,11 @@ +#[macro_export] +macro_rules! send { + ($download_manager:expr, $signal:expr) => { + $download_manager.send($signal).unwrap_or_else(|_| { + panic!( + "Failed to send signal {} to the download manager", + stringify!(signal) + ) + }) + }; +} diff --git a/src-tauri/src/utils/mod.rs b/src-tauri/utils/src/lib.rs similarity index 100% rename from src-tauri/src/utils/mod.rs rename to src-tauri/utils/src/lib.rs diff --git a/src-tauri/utils/src/lock.rs b/src-tauri/utils/src/lock.rs new file mode 100644 index 0000000..18c376d --- /dev/null +++ b/src-tauri/utils/src/lock.rs @@ -0,0 +1,8 @@ +#[macro_export] +macro_rules! lock { + ($mutex:expr) => { + $mutex + .lock() + .unwrap_or_else(|_| panic!("Failed to lock onto {}", stringify!($mutex))) + }; +} diff --git a/src-tauri/utils/src/webbrowser_open.rs b/src-tauri/utils/src/webbrowser_open.rs new file mode 100644 index 0000000..81a6db1 --- /dev/null +++ b/src-tauri/utils/src/webbrowser_open.rs @@ -0,0 +1,11 @@ +use log::warn; + +pub fn webbrowser_open>(url: T) { + if let Err(e) = webbrowser::open(url.as_ref()) { + warn!( + "Could not open web browser to url {} with error {}", + url.as_ref(), + e + ); + }; +}