diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 0933ad26..b80961ac 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -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" @@ -165,23 +159,12 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" dependencies = [ - "event-listener 5.4.0", + "event-listener", "event-listener-strategy", "futures-core", "pin-project-lite", ] -[[package]] -name = "async-channel" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" -dependencies = [ - "concurrent-queue", - "event-listener 2.5.3", - "futures-core", -] - [[package]] name = "async-channel" version = "2.3.1" @@ -208,21 +191,6 @@ dependencies = [ "slab", ] -[[package]] -name = "async-global-executor" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" -dependencies = [ - "async-channel 2.3.1", - "async-executor", - "async-io", - "async-lock", - "blocking", - "futures-lite", - "once_cell", -] - [[package]] name = "async-io" version = "2.4.1" @@ -248,7 +216,7 @@ version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" dependencies = [ - "event-listener 5.4.0", + "event-listener", "event-listener-strategy", "pin-project-lite", ] @@ -259,14 +227,14 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cde3f4e40e6021d7acffc90095cbd6dc54cb593903d1de5832f435eb274b85dc" dependencies = [ - "async-channel 2.3.1", + "async-channel", "async-io", "async-lock", "async-signal", "async-task", "blocking", "cfg-if", - "event-listener 5.4.0", + "event-listener", "futures-lite", "rustix 1.0.7", "tracing", @@ -301,33 +269,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "async-std" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "730294c1c08c2e0f85759590518f6333f0d5a0a766a27d519c1b244c3dfd8a24" -dependencies = [ - "async-channel 1.9.0", - "async-global-executor", - "async-io", - "async-lock", - "async-process", - "crossbeam-utils", - "futures-channel", - "futures-core", - "futures-io", - "futures-lite", - "gloo-timers", - "kv-log-macro", - "log", - "memchr", - "once_cell", - "pin-project-lite", - "pin-utils", - "slab", - "wasm-bindgen-futures", -] - [[package]] name = "async-task" version = "4.7.1" @@ -347,9 +288,9 @@ dependencies = [ [[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", @@ -428,15 +369,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "base64" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" -dependencies = [ - "byteorder", -] - [[package]] name = "base64" version = "0.21.7" @@ -460,9 +392,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,9 +405,9 @@ 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", @@ -497,43 +429,13 @@ dependencies = [ "serde", ] -[[package]] -name = "block-buffer" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" -dependencies = [ - "block-padding", - "byte-tools", - "byteorder", - "generic-array 0.12.4", -] - -[[package]] -name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "generic-array 0.14.7", -] - [[package]] name = "block-buffer" version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "generic-array 0.14.7", -] - -[[package]] -name = "block-padding" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" -dependencies = [ - "byte-tools", + "generic-array", ] [[package]] @@ -560,7 +462,7 @@ version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" dependencies = [ - "async-channel 2.3.1", + "async-channel", "async-task", "futures-io", "futures-lite", @@ -600,12 +502,6 @@ version = "3.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" -[[package]] -name = "byte-tools" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" - [[package]] name = "bytemuck" version = "1.23.0" @@ -627,55 +523,6 @@ dependencies = [ "serde", ] -[[package]] -name = "cacache" -version = "9.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "205ae2da91f7633dd4ecc1b12fac60c991a48b61b2cd801ad533085b15392537" -dependencies = [ - "async-std", - "digest 0.9.0", - "either", - "futures", - "hex 0.4.3", - "memmap", - "serde", - "serde_derive", - "serde_json", - "sha-1 0.9.8", - "sha2 0.9.9", - "ssri 7.0.0", - "tempfile", - "thiserror 1.0.69", - "walkdir", -] - -[[package]] -name = "cacache" -version = "13.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5063741c7b2e260bbede781cf4679632dd90e2718e99f7715e46824b65670b" -dependencies = [ - "async-std", - "digest 0.10.7", - "either", - "futures", - "hex 0.4.3", - "libc", - "memmap2", - "miette", - "reflink-copy", - "serde", - "serde_derive", - "serde_json", - "sha1", - "sha2 0.10.9", - "ssri 9.2.0", - "tempfile", - "thiserror 1.0.69", - "walkdir", -] - [[package]] name = "cairo-rs" version = "0.18.5" @@ -740,7 +587,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02260d489095346e5cafd04dea8e8cb54d1d74fcd759022a9b72986ebe9a1257" dependencies = [ "serde", - "toml", + "toml 0.8.22", ] [[package]] @@ -795,17 +642,16 @@ 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.0", ] [[package]] @@ -977,7 +823,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", "typenum", ] @@ -1127,31 +973,13 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c877555693c14d2f84191cfd3ad8582790fc52b5e2274b40b59cf5f5cea25c7" -[[package]] -name = "digest" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" -dependencies = [ - "generic-array 0.12.4", -] - -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array 0.14.7", -] - [[package]] name = "digest" version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer 0.10.4", + "block-buffer", "crypto-common", ] @@ -1193,7 +1021,7 @@ dependencies = [ "libc", "option-ext", "redox_users 0.5.0", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -1237,9 +1065,9 @@ dependencies = [ [[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", @@ -1286,48 +1114,28 @@ dependencies = [ name = "drop-app" version = "0.3.3" dependencies = [ - "atomic-instant-full", - "bitcode", "boxcar", - "bytes", - "cacache 13.1.0", - "chrono", - "deranged", "dirs 6.0.0", - "droplet-rs", - "dynfmt", - "filetime", - "futures-core", + "drop-database", + "drop-downloads", + "drop-errors", + "drop-native-library", + "drop-process", + "drop-remote", "futures-lite", - "gethostname", - "hex 0.4.3", - "http 1.3.1", - "http-serde 2.1.1", - "humansize", + "hex", + "http", "known-folders", "log", "log4rs", - "md5", - "native_model", - "page_size", - "parking_lot 0.12.3", - "rand 0.9.1", + "md5 0.7.0", "rayon", "regex", - "reqwest 0.12.22", - "reqwest-middleware 0.4.2", - "reqwest-middleware-cache", + "reqwest", "reqwest-websocket", - "rustbreak", "rustix 0.38.44", - "schemars", "serde", "serde_json", - "serde_with", - "sha1", - "shared_child", - "slice-deque", - "sysinfo", "tar", "tauri", "tauri-build", @@ -1339,26 +1147,135 @@ dependencies = [ "tauri-plugin-shell", "tauri-plugin-single-instance", "tempfile", - "throttle_my_fn", - "tokio", - "tokio-util", - "umu-wrapper-lib", "url", - "urlencoding", "uuid", - "walkdir", "webbrowser", "whoami", "zstd", ] +[[package]] +name = "drop-consts" +version = "0.1.0" +dependencies = [ + "dirs 6.0.0", +] + +[[package]] +name = "drop-database" +version = "0.1.0" +dependencies = [ + "bitcode", + "chrono", + "drop-consts", + "drop-library", + "drop-native-library", + "log", + "native_model", + "rustbreak", + "serde", + "serde_with", + "url", + "whoami", +] + +[[package]] +name = "drop-downloads" +version = "0.1.0" +dependencies = [ + "atomic-instant-full", + "drop-database", + "drop-errors", + "log", + "parking_lot 0.12.4", + "serde", + "tauri", + "throttle_my_fn", +] + +[[package]] +name = "drop-errors" +version = "0.1.0" +dependencies = [ + "http", + "humansize", + "reqwest", + "reqwest-websocket", + "serde", + "serde_with", + "tauri-plugin-opener", + "url", +] + +[[package]] +name = "drop-library" +version = "0.1.0" +dependencies = [ + "drop-errors", + "http", + "reqwest", + "serde", + "tauri", +] + +[[package]] +name = "drop-native-library" +version = "0.1.0" +dependencies = [ + "bitcode", + "drop-errors", + "drop-library", + "drop-remote", + "log", + "serde", + "tauri", + "url", +] + +[[package]] +name = "drop-process" +version = "0.1.0" +dependencies = [ + "chrono", + "drop-database", + "drop-errors", + "drop-native-library", + "dynfmt", + "log", + "page_size", + "shared_child", + "sysinfo", + "tauri", + "tauri-plugin-opener", +] + +[[package]] +name = "drop-remote" +version = "0.1.0" +dependencies = [ + "bitcode", + "chrono", + "drop-consts", + "drop-errors", + "droplet-rs", + "gethostname", + "hex", + "http", + "log", + "md5 0.8.0", + "reqwest", + "serde", + "tauri", + "url", +] + [[package]] name = "droplet-rs" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "926e179267dfe9fd891d4141d65d71fba06b6b82cd6834916a6310794df7d739" dependencies = [ - "hex 0.4.3", + "hex", "rcgen", "ring", "time", @@ -1423,7 +1340,7 @@ dependencies = [ "cc", "memchr", "rustc_version", - "toml", + "toml 0.8.22", "vswhom", "winreg 0.52.0", ] @@ -1505,12 +1422,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "event-listener" -version = "2.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" - [[package]] name = "event-listener" version = "5.4.0" @@ -1528,16 +1439,10 @@ version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" dependencies = [ - "event-listener 5.4.0", + "event-listener", "pin-project-lite", ] -[[package]] -name = "fake-simd" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" - [[package]] name = "fastrand" version = "2.3.0" @@ -1635,9 +1540,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", ] @@ -1652,21 +1557,6 @@ dependencies = [ "new_debug_unreachable", ] -[[package]] -name = "futures" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - [[package]] name = "futures-channel" version = "0.3.31" @@ -1702,9 +1592,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", @@ -1742,7 +1632,6 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ - "futures-channel", "futures-core", "futures-io", "futures-macro", @@ -1862,15 +1751,6 @@ dependencies = [ "x11", ] -[[package]] -name = "generic-array" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" -dependencies = [ - "typenum", -] - [[package]] name = "generic-array" version = "0.14.7" @@ -2026,18 +1906,6 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" -[[package]] -name = "gloo-timers" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" -dependencies = [ - "futures-channel", - "futures-core", - "js-sys", - "wasm-bindgen", -] - [[package]] name = "gobject-sys" version = "0.18.0" @@ -2101,25 +1969,6 @@ dependencies = [ "syn 2.0.101", ] -[[package]] -name = "h2" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http 0.2.12", - "indexmap 2.9.0", - "slab", - "tokio", - "tokio-util", - "tracing", -] - [[package]] name = "h2" version = "0.4.10" @@ -2131,7 +1980,7 @@ dependencies = [ "fnv", "futures-core", "futures-sink", - "http 1.3.1", + "http", "indexmap 2.9.0", "slab", "tokio", @@ -2175,12 +2024,6 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f154ce46856750ed433c8649605bf7ed2de3bc35fd9d2a9f30cddd873c80cb08" -[[package]] -name = "hex" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" - [[package]] name = "hex" version = "0.4.3" @@ -2202,21 +2045,10 @@ 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 = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" -dependencies = [ - "bytes", - "fnv", - "itoa", + "log", + "mac", + "markup5ever", + "match_token", ] [[package]] @@ -2230,17 +2062,6 @@ dependencies = [ "itoa", ] -[[package]] -name = "http-body" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" -dependencies = [ - "bytes", - "http 0.2.12", - "pin-project-lite", -] - [[package]] name = "http-body" version = "1.0.1" @@ -2248,7 +2069,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http 1.3.1", + "http", ] [[package]] @@ -2259,62 +2080,23 @@ checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", "futures-core", - "http 1.3.1", - "http-body 1.0.1", + "http", + "http-body", "pin-project-lite", ] -[[package]] -name = "http-cache-semantics" -version = "0.9.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "486d14f0f5e6981578cc683e01c5f50e2be31c984a75ff5517949af2e4268519" -dependencies = [ - "chrono", - "http 0.2.12", - "http-serde 1.1.3", - "reqwest 0.11.27", - "serde", -] - [[package]] name = "http-range" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21dec9db110f5f872ed9699c3ecf50cf16f423502706ba5c72462e28d3157573" -[[package]] -name = "http-serde" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f560b665ad9f1572cfcaf034f7fb84338a7ce945216d64a90fd81f046a3caee" -dependencies = [ - "http 0.2.12", - "serde", -] - -[[package]] -name = "http-serde" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f056c8559e3757392c8d091e796416e4649d8e49e88b8d76df6c002f05027fd" -dependencies = [ - "http 1.3.1", - "serde", -] - [[package]] name = "httparse" version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - [[package]] name = "humansize" version = "2.1.3" @@ -2330,30 +2112,6 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f" -[[package]] -name = "hyper" -version = "0.14.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2 0.3.26", - "http 0.2.12", - "http-body 0.4.6", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", - "want", -] - [[package]] name = "hyper" version = "1.6.0" @@ -2363,9 +2121,9 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "h2 0.4.10", - "http 1.3.1", - "http-body 1.0.1", + "h2", + "http", + "http-body", "httparse", "itoa", "pin-project-lite", @@ -2380,8 +2138,8 @@ version = "0.27.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03a01595e11bdcec50946522c32dde3fc6914743000a68b93000965f2f02406d" dependencies = [ - "http 1.3.1", - "hyper 1.6.0", + "http", + "hyper", "hyper-util", "rustls", "rustls-native-certs", @@ -2400,7 +2158,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", - "hyper 1.6.0", + "hyper", "hyper-util", "native-tls", "tokio", @@ -2419,17 +2177,19 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "http 1.3.1", - "http-body 1.0.1", - "hyper 1.6.0", + "http", + "http-body", + "hyper", "ipnet", "libc", "percent-encoding", "pin-project-lite", "socket2", + "system-configuration", "tokio", "tower-service", "tracing", + "windows-registry 0.4.0", ] [[package]] @@ -2560,9 +2320,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", @@ -2779,15 +2539,6 @@ dependencies = [ "selectors", ] -[[package]] -name = "kv-log-macro" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" -dependencies = [ - "log", -] - [[package]] name = "lazy_static" version = "1.5.0" @@ -2871,9 +2622,9 @@ checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" [[package]] name = "lock_api" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" dependencies = [ "autocfg", "scopeguard", @@ -2881,12 +2632,11 @@ dependencies = [ [[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", ] [[package]] @@ -2911,7 +2661,7 @@ dependencies = [ "log", "log-mdc", "once_cell", - "parking_lot 0.12.3", + "parking_lot 0.12.4", "rand 0.8.5", "serde", "serde-value", @@ -2935,15 +2685,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" -[[package]] -name = "mach" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" -dependencies = [ - "libc", -] - [[package]] name = "markup5ever" version = "0.14.1" @@ -2982,29 +2723,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" [[package]] -name = "memchr" -version = "2.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" - -[[package]] -name = "memmap" -version = "0.7.0" +name = "md5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" -dependencies = [ - "libc", - "winapi", -] +checksum = "ae960838283323069879657ca3de837e9f7bbb4c7bf6ea7f1b290d5e9476d2e0" [[package]] -name = "memmap2" -version = "0.5.10" +name = "memchr" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" -dependencies = [ - "libc", -] +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memoffset" @@ -3015,45 +2743,12 @@ dependencies = [ "autocfg", ] -[[package]] -name = "miette" -version = "5.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59bb584eaeeab6bd0226ccf3509a69d7936d148cf3d036ad350abe35e8c6856e" -dependencies = [ - "miette-derive", - "once_cell", - "thiserror 1.0.69", - "unicode-width", -] - -[[package]] -name = "miette-derive" -version = "5.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49e7bc1560b95a3c4a25d03de42fe76ca718ab92d1a22a55b9b4cf67b3ae635c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", -] - [[package]] name = "mime" version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" -[[package]] -name = "mime_guess" -version = "2.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" -dependencies = [ - "mime", - "unicase", -] - [[package]] name = "minimal-lexical" version = "0.2.1" @@ -3437,6 +3132,16 @@ dependencies = [ "objc2-core-foundation", ] +[[package]] +name = "objc2-javascript-core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9052cb1bb50a4c161d934befcf879526fb87ae9a68858f241e693ca46225cf5a" +dependencies = [ + "objc2 0.6.1", + "objc2-core-foundation", +] + [[package]] name = "objc2-metal" version = "0.2.2" @@ -3473,6 +3178,17 @@ dependencies = [ "objc2-foundation 0.3.1", ] +[[package]] +name = "objc2-security" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1f8e0ef3ab66b08c42644dcb34dba6ec0a574bbd8adbb8bdbdc7a2779731a44" +dependencies = [ + "bitflags 2.9.1", + "objc2 0.6.1", + "objc2-core-foundation", +] + [[package]] name = "objc2-ui-kit" version = "0.3.1" @@ -3497,6 +3213,8 @@ dependencies = [ "objc2-app-kit", "objc2-core-foundation", "objc2-foundation 0.3.1", + "objc2-javascript-core", + "objc2-security", ] [[package]] @@ -3532,18 +3250,6 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" -[[package]] -name = "opaque-debug" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" - -[[package]] -name = "opaque-debug" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" - [[package]] name = "open" version = "5.3.2" @@ -3710,12 +3416,12 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" dependencies = [ "lock_api", - "parking_lot_core 0.9.10", + "parking_lot_core 0.9.11", ] [[package]] @@ -3734,9 +3440,9 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.10" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" dependencies = [ "cfg-if", "libc", @@ -3769,9 +3475,9 @@ dependencies = [ [[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" @@ -4344,15 +4050,23 @@ dependencies = [ ] [[package]] -name = "reflink-copy" -version = "0.1.26" +name = "ref-cast" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78c81d000a2c524133cc00d2f92f019d399e57906c3b7119271a2495354fe895" +checksum = "4a0ae411dbe946a674d89546582cea4ba2bb8defac896622d6496f14c23ba5cf" dependencies = [ - "cfg-if", - "libc", - "rustix 1.0.7", - "windows", + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", ] [[package]] @@ -4386,62 +4100,27 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" -version = "0.11.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" -dependencies = [ - "base64 0.21.7", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2 0.3.26", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.32", - "ipnet", - "js-sys", - "log", - "mime", - "mime_guess", - "once_cell", - "percent-encoding", - "pin-project-lite", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper 0.1.2", - "system-configuration", - "tokio", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "winreg 0.50.0", -] - -[[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", - "http 1.3.1", - "http-body 1.0.1", + "h2", + "http", + "http-body", "http-body-util", - "hyper 1.6.0", + "hyper", "hyper-rustls", "hyper-tls", "hyper-util", "js-sys", "log", + "mime", "native-tls", "percent-encoding", "pin-project-lite", @@ -4452,7 +4131,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", - "sync_wrapper 1.0.2", + "sync_wrapper", "tokio", "tokio-native-tls", "tokio-rustls", @@ -4468,67 +4147,16 @@ dependencies = [ "webpki-roots", ] -[[package]] -name = "reqwest-middleware" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69539cea4148dce683bec9dc95be3f0397a9bb2c248a49c8296a9d21659a8cdd" -dependencies = [ - "anyhow", - "async-trait", - "futures", - "http 0.2.12", - "reqwest 0.11.27", - "serde", - "task-local-extensions", - "thiserror 1.0.69", -] - -[[package]] -name = "reqwest-middleware" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57f17d28a6e6acfe1733fe24bcd30774d13bffa4b8a22535b4c8c98423088d4e" -dependencies = [ - "anyhow", - "async-trait", - "http 1.3.1", - "reqwest 0.12.22", - "serde", - "thiserror 1.0.69", - "tower-service", -] - -[[package]] -name = "reqwest-middleware-cache" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64dbc0a15e4d69f96e9b66ea5ff8102e2f4cce287bc26562363013d1c39d8f66" -dependencies = [ - "anyhow", - "async-trait", - "bincode", - "cacache 9.0.0", - "http 0.2.12", - "http-cache-semantics", - "httpdate", - "reqwest 0.11.27", - "reqwest-middleware 0.1.6", - "serde", - "task-local-extensions", - "url", -] - [[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", + "reqwest", "thiserror 2.0.12", "tokio", "tokio-util", @@ -4615,7 +4243,6 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "460d97902465327d69ecfe8cefdb5972c6f94d6127ac9e992acdb51458bebc27" dependencies = [ - "anyhow", "serde", "tempfile", "thiserror 1.0.69", @@ -4769,6 +4396,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" @@ -4852,10 +4503,11 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.219" +version = "1.0.225" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "fd6c24dee235d0da097043389623fb913daddf92c76e9f5a1db88607a0bcbd1d" dependencies = [ + "serde_core", "serde_derive", ] @@ -4880,11 +4532,20 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_core" +version = "1.0.225" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "659356f9a0cb1e529b24c01e43ad2bdf520ec4ceaf83047b83ddcc2251f96383" +dependencies = [ + "serde_derive", +] + [[package]] name = "serde_derive" -version = "1.0.219" +version = "1.0.225" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "0ea936adf78b1f766949a4977b91d2f5595825bd6ec079aa9543ad2685fc4516" dependencies = [ "proc-macro2", "quote", @@ -4904,9 +4565,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.140" +version = "1.0.143" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" dependencies = [ "itoa", "memchr", @@ -4927,9 +4588,18 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.8" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_spanned" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +checksum = "40734c41988f7306bb04f0ecf60ec0f3f1caa34290e4e8ea471dcd3346483b83" dependencies = [ "serde", ] @@ -4948,15 +4618,17 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.12.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6b6f7f2fcb69f747921f79f3926bd1e203fce4fef62c268dd3abfb6d86029aa" +checksum = "f2c45cd61fefa9db6f254525d46e392b852e0e61d9a1fd36e5bd183450a556d5" dependencies = [ "base64 0.22.1", "chrono", - "hex 0.4.3", + "hex", "indexmap 1.9.3", "indexmap 2.9.0", + "schemars 0.9.0", + "schemars 1.0.4", "serde", "serde_derive", "serde_json", @@ -4966,9 +4638,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.12.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d00caa5193a3c8362ac2b73be6b9e768aa5a4b2f721d8f4b339600c3cb51f8e" +checksum = "de90945e6565ce0d9a25098082ed4ee4002e047cb59892c318d66821e14bb30f" dependencies = [ "darling", "proc-macro2", @@ -4991,9 +4663,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 +4674,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.101", ] [[package]] @@ -5021,42 +4693,6 @@ dependencies = [ "stable_deref_trait", ] -[[package]] -name = "sha-1" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" -dependencies = [ - "block-buffer 0.7.3", - "digest 0.8.1", - "fake-simd", - "opaque-debug 0.2.3", -] - -[[package]] -name = "sha-1" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if", - "cpufeatures", - "digest 0.9.0", - "opaque-debug 0.3.1", -] - -[[package]] -name = "sha-1" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", -] - [[package]] name = "sha1" version = "0.10.6" @@ -5065,32 +4701,7 @@ checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "sha2" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" -dependencies = [ - "block-buffer 0.7.3", - "digest 0.8.1", - "fake-simd", - "opaque-debug 0.2.3", -] - -[[package]] -name = "sha2" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if", - "cpufeatures", - "digest 0.9.0", - "opaque-debug 0.3.1", + "digest", ] [[package]] @@ -5101,17 +4712,18 @@ checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.7", + "digest", ] [[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]] @@ -5120,6 +4732,27 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "sigchld" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47106eded3c154e70176fc83df9737335c94ce22f821c32d17ed1db1f83badb1" +dependencies = [ + "libc", + "os_pipe", + "signal-hook", +] + +[[package]] +name = "signal-hook" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2" +dependencies = [ + "libc", + "signal-hook-registry", +] + [[package]] name = "signal-hook-registry" version = "1.4.5" @@ -5156,17 +4789,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "slice-deque" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31ef6ee280cdefba6d2d0b4b78a84a1c1a3f3a4cec98c2d4231c8bc225de0f25" -dependencies = [ - "libc", - "mach", - "winapi", -] - [[package]] name = "smallvec" version = "1.15.0" @@ -5231,38 +4853,6 @@ dependencies = [ "system-deps", ] -[[package]] -name = "ssri" -version = "7.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9cec0d388f39fbe79d7aa600e8d38053bf97b1bc8d350da7c0ba800d0f423f2" -dependencies = [ - "base64 0.10.1", - "digest 0.8.1", - "hex 0.3.2", - "serde", - "sha-1 0.8.2", - "sha2 0.8.2", - "thiserror 1.0.69", -] - -[[package]] -name = "ssri" -version = "9.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da7a2b3c2bc9693bcb40870c4e9b5bf0d79f9cb46273321bf855ec513e919082" -dependencies = [ - "base64 0.21.7", - "digest 0.10.7", - "hex 0.4.3", - "miette", - "serde", - "sha-1 0.10.1", - "sha2 0.10.9", - "thiserror 1.0.69", - "xxhash-rust", -] - [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -5282,7 +4872,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.4", "phf_shared 0.11.3", "precomputed-hash", "serde", @@ -5345,12 +4935,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "sync_wrapper" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" - [[package]] name = "sync_wrapper" version = "1.0.2" @@ -5382,9 +4966,9 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.36.1" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "252800745060e7b9ffb7b2badbd8b31cfa4aa2e61af879d0a3bf2a317c20217d" +checksum = "07cec4dc2d2e357ca1e610cfb07de2fa7a10fc3e9fe89f72545f3d244ea87753" dependencies = [ "libc", "memchr", @@ -5396,20 +4980,20 @@ dependencies = [ [[package]] name = "system-configuration" -version = "0.5.1" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.9.1", "core-foundation 0.9.4", "system-configuration-sys", ] [[package]] name = "system-configuration-sys" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" dependencies = [ "core-foundation-sys", "libc", @@ -5424,17 +5008,18 @@ dependencies = [ "cfg-expr", "heck 0.5.0", "pkg-config", - "toml", + "toml 0.8.22", "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", + "block2 0.6.1", "core-foundation 0.10.1", "core-graphics", "crossbeam-channel", @@ -5455,7 +5040,7 @@ dependencies = [ "objc2-app-kit", "objc2-foundation 0.3.1", "once_cell", - "parking_lot 0.12.3", + "parking_lot 0.12.4", "raw-window-handle", "scopeguard", "tao-macros", @@ -5495,23 +5080,15 @@ version = "0.12.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" -[[package]] -name = "task-local-extensions" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba323866e5d033818e3240feeb9f7db2c4296674e4d9e16b97b7bf8f490434e8" -dependencies = [ - "pin-utils", -] - [[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", @@ -5519,7 +5096,7 @@ dependencies = [ "glob", "gtk", "heck 0.5.0", - "http 1.3.1", + "http", "http-range", "jni", "libc", @@ -5530,10 +5107,11 @@ dependencies = [ "objc2-app-kit", "objc2-foundation 0.3.1", "objc2-ui-kit", + "objc2-web-kit", "percent-encoding", "plist", "raw-window-handle", - "reqwest 0.12.22", + "reqwest", "serde", "serde_json", "serde_repr", @@ -5557,9 +5135,9 @@ dependencies = [ [[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 +5145,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.5", "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", @@ -5594,7 +5172,7 @@ dependencies = [ "semver", "serde", "serde_json", - "sha2 0.10.9", + "sha2", "syn 2.0.101", "tauri-utils", "thiserror 2.0.12", @@ -5606,9 +5184,9 @@ 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", @@ -5620,18 +5198,18 @@ dependencies = [ [[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.5", "walkdir", ] @@ -5665,7 +5243,7 @@ dependencies = [ "thiserror 2.0.12", "tracing", "url", - "windows-registry", + "windows-registry 0.5.2", "windows-result", ] @@ -5697,7 +5275,7 @@ dependencies = [ "dunce", "glob", "percent-encoding", - "schemars", + "schemars 0.8.22", "serde", "serde_json", "serde_repr", @@ -5705,22 +5283,22 @@ dependencies = [ "tauri-plugin", "tauri-utils", "thiserror 2.0.12", - "toml", + "toml 0.8.22", "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", "open", - "schemars", + "schemars 0.8.22", "serde", "serde_json", "tauri", @@ -5733,9 +5311,9 @@ dependencies = [ [[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", @@ -5760,7 +5338,7 @@ dependencies = [ "open", "os_pipe", "regex", - "schemars", + "schemars 0.8.22", "serde", "serde_json", "shared_child", @@ -5788,34 +5366,37 @@ dependencies = [ [[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", + "http", "jni", "objc2 0.6.1", "objc2-ui-kit", + "objc2-web-kit", "raw-window-handle", "serde", "serde_json", "tauri-utils", "thiserror 2.0.12", "url", + "webkit2gtk", + "webview2-com", "windows", ] [[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", + "http", "jni", "log", "objc2 0.6.1", @@ -5837,9 +5418,9 @@ dependencies = [ [[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", @@ -5848,7 +5429,7 @@ dependencies = [ "dunce", "glob", "html5ever", - "http 1.3.1", + "http", "infer", "json-patch", "kuchikiki", @@ -5858,7 +5439,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "schemars", + "schemars 0.8.22", "semver", "serde", "serde-untagged", @@ -5866,7 +5447,7 @@ dependencies = [ "serde_with", "swift-rs", "thiserror 2.0.12", - "toml", + "toml 0.9.5", "url", "urlpattern", "uuid", @@ -5881,7 +5462,7 @@ checksum = "e8d321dbc6f998d825ab3f0d62673e810c861aac2d0de2cc2c395328f1d113b4" dependencies = [ "embed-resource", "indexmap 2.9.0", - "toml", + "toml 0.8.22", ] [[package]] @@ -6105,11 +5686,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05ae329d1f08c4d17a59bed7ff5b5a769d062e64a62d34a3261b219e62cd5aae" dependencies = [ "serde", - "serde_spanned", - "toml_datetime", + "serde_spanned 0.6.8", + "toml_datetime 0.6.9", "toml_edit 0.22.26", ] +[[package]] +name = "toml" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75129e1dc5000bfbaa9fee9d1b21f974f9fbad9daec557a521ee6e080825f6e8" +dependencies = [ + "indexmap 2.9.0", + "serde", + "serde_spanned 1.0.0", + "toml_datetime 0.7.0", + "toml_parser", + "toml_writer", + "winnow 0.7.10", +] + [[package]] name = "toml_datetime" version = "0.6.9" @@ -6119,6 +5715,15 @@ dependencies = [ "serde", ] +[[package]] +name = "toml_datetime" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bade1c3e902f58d73d3f294cd7f20391c1cb2fbcb643b73566bc773971df91e3" +dependencies = [ + "serde", +] + [[package]] name = "toml_edit" version = "0.19.15" @@ -6126,7 +5731,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ "indexmap 2.9.0", - "toml_datetime", + "toml_datetime 0.6.9", "winnow 0.5.40", ] @@ -6137,7 +5742,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" dependencies = [ "indexmap 2.9.0", - "toml_datetime", + "toml_datetime 0.6.9", "winnow 0.5.40", ] @@ -6149,18 +5754,33 @@ checksum = "310068873db2c5b3e7659d2cc35d21855dbafa50d1ce336397c666e3cb08137e" dependencies = [ "indexmap 2.9.0", "serde", - "serde_spanned", - "toml_datetime", + "serde_spanned 0.6.8", + "toml_datetime 0.6.9", "toml_write", "winnow 0.7.10", ] +[[package]] +name = "toml_parser" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b551886f449aa90d4fe2bdaa9f4a2577ad2dde302c61ecf262d80b116db95c10" +dependencies = [ + "winnow 0.7.10", +] + [[package]] name = "toml_write" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfb942dfe1d8e29a7ee7fcbde5bd2b9a25fb89aa70caea2eba3bee836ff41076" +[[package]] +name = "toml_writer" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc842091f2def52017664b53082ecbbeb5c7731092bad69d2c63050401dfd64" + [[package]] name = "tower" version = "0.5.2" @@ -6170,7 +5790,7 @@ dependencies = [ "futures-core", "futures-util", "pin-project-lite", - "sync_wrapper 1.0.2", + "sync_wrapper", "tokio", "tower-layer", "tower-service", @@ -6185,8 +5805,8 @@ dependencies = [ "bitflags 2.9.1", "bytes", "futures-util", - "http 1.3.1", - "http-body 1.0.1", + "http", + "http-body", "iri-string", "pin-project-lite", "tower", @@ -6273,13 +5893,13 @@ 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", + "http", "httparse", "log", "rand 0.9.1", @@ -6320,12 +5940,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "umu-wrapper-lib" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baa36636bef667cee9eb4f497c24279182b8b9f098fd04b0b8c5d2ebc4e451f1" - [[package]] name = "unic-char-property" version = "0.9.0" @@ -6367,12 +5981,6 @@ dependencies = [ "unic-common", ] -[[package]] -name = "unicase" -version = "2.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" - [[package]] name = "unicode-ident" version = "1.0.18" @@ -6385,12 +5993,6 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" -[[package]] -name = "unicode-width" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" - [[package]] name = "unsafe-any-ors" version = "1.0.0" @@ -6414,9 +6016,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", @@ -6424,12 +6026,6 @@ dependencies = [ "serde", ] -[[package]] -name = "urlencoding" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" - [[package]] name = "urlpattern" version = "0.3.0" @@ -6479,12 +6075,6 @@ dependencies = [ "syn 2.0.101", ] -[[package]] -name = "value-bag" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "943ce29a8a743eb10d6082545d861b24f9d1b160b7d741e0f2cdf726bec909c5" - [[package]] name = "vcpkg" version = "0.2.15" @@ -6791,11 +6381,11 @@ dependencies = [ [[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", ] @@ -6855,7 +6445,7 @@ dependencies = [ "windows-collections", "windows-core", "windows-future", - "windows-link", + "windows-link 0.1.1", "windows-numerics", ] @@ -6876,9 +6466,9 @@ checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ "windows-implement", "windows-interface", - "windows-link", + "windows-link 0.1.1", "windows-result", - "windows-strings", + "windows-strings 0.4.2", ] [[package]] @@ -6888,7 +6478,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" dependencies = [ "windows-core", - "windows-link", + "windows-link 0.1.1", "windows-threading", ] @@ -6920,6 +6510,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" +[[package]] +name = "windows-link" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" + [[package]] name = "windows-numerics" version = "0.2.0" @@ -6927,7 +6523,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" dependencies = [ "windows-core", - "windows-link", + "windows-link 0.1.1", +] + +[[package]] +name = "windows-registry" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3" +dependencies = [ + "windows-result", + "windows-strings 0.3.1", + "windows-targets 0.53.2", ] [[package]] @@ -6936,9 +6543,9 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3bab093bdd303a1240bb99b8aba8ea8a69ee19d34c9e2ef9594e708a4878820" dependencies = [ - "windows-link", + "windows-link 0.1.1", "windows-result", - "windows-strings", + "windows-strings 0.4.2", ] [[package]] @@ -6947,7 +6554,16 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" dependencies = [ - "windows-link", + "windows-link 0.1.1", +] + +[[package]] +name = "windows-strings" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" +dependencies = [ + "windows-link 0.1.1", ] [[package]] @@ -6956,7 +6572,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" dependencies = [ - "windows-link", + "windows-link 0.1.1", ] [[package]] @@ -6995,6 +6611,15 @@ 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.2", +] + [[package]] name = "windows-targets" version = "0.42.2" @@ -7034,20 +6659,36 @@ 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.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" +dependencies = [ + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] + [[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.1", ] [[package]] @@ -7056,7 +6697,7 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e04a5c6627e310a23ad2358483286c7df260c964eb2d003d8efd6d0f4e79265c" dependencies = [ - "windows-link", + "windows-link 0.1.1", ] [[package]] @@ -7077,6 +6718,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.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + [[package]] name = "windows_aarch64_msvc" version = "0.42.2" @@ -7095,6 +6742,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.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + [[package]] name = "windows_i686_gnu" version = "0.42.2" @@ -7113,12 +6766,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.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + [[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.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + [[package]] name = "windows_i686_msvc" version = "0.42.2" @@ -7137,6 +6802,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.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + [[package]] name = "windows_x86_64_gnu" version = "0.42.2" @@ -7155,6 +6826,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.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" @@ -7173,6 +6850,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.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + [[package]] name = "windows_x86_64_msvc" version = "0.42.2" @@ -7191,6 +6874,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.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + [[package]] name = "winnow" version = "0.5.40" @@ -7218,16 +6907,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "winreg" -version = "0.50.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] - [[package]] name = "winreg" version = "0.52.0" @@ -7255,20 +6934,21 @@ checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" [[package]] name = "wry" -version = "0.52.1" +version = "0.53.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12a714d9ba7075aae04a6e50229d6109e3d584774b99a6a8c60de1698ca111b9" +checksum = "31f0e9642a0d061f6236c54ccae64c2722a7879ad4ec7dff59bd376d446d8e90" dependencies = [ "base64 0.22.1", "block2 0.6.1", "cookie", "crossbeam-channel", + "dirs 6.0.0", "dpi", "dunce", "gdkx11", "gtk", "html5ever", - "http 1.3.1", + "http", "javascriptcore-rs", "jni", "kuchikiki", @@ -7283,7 +6963,7 @@ dependencies = [ "once_cell", "percent-encoding", "raw-window-handle", - "sha2 0.10.9", + "sha2", "soup3", "tao-macros", "thiserror 2.0.12", @@ -7364,12 +7044,6 @@ dependencies = [ "rustix 1.0.7", ] -[[package]] -name = "xxhash-rust" -version = "0.8.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3" - [[package]] name = "yasna" version = "0.5.2" @@ -7405,9 +7079,9 @@ dependencies = [ [[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,10 +7093,10 @@ dependencies = [ "async-trait", "blocking", "enumflags2", - "event-listener 5.4.0", + "event-listener", "futures-core", "futures-lite", - "hex 0.4.3", + "hex", "nix", "ordered-stream", "serde", @@ -7430,7 +7104,7 @@ dependencies = [ "tokio", "tracing", "uds_windows", - "windows-sys 0.59.0", + "windows-sys 0.60.2", "winnow 0.7.10", "zbus_macros", "zbus_names", @@ -7439,9 +7113,9 @@ 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-macro2", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 55f017cf..dcb2358d 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,129 +1,101 @@ [package] name = "drop-app" version = "0.3.3" -description = "The client application for the open-source, self-hosted game distribution platform Drop" -authors = ["Drop OSS"] +# authors = ["Drop OSS"] edition = "2024" +description = "The client application for the open-source, self-hosted game distribution platform Drop" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[workspace] +resolver = "3" +members = ["drop-consts", + "drop-database", + "drop-downloads", + "drop-errors", "drop-library", + "drop-native-library", + "drop-process", + "drop-remote", +] -[target."cfg(any(target_os = \"macos\", windows, target_os = \"linux\"))".dependencies] -tauri-plugin-single-instance = { version = "2.0.0", features = ["deep-link"] } +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [lib] +crate-type = ["cdylib", "rlib", "staticlib"] # The `_lib` suffix may seem redundant but it is necessary # to make the lib name unique and wouldn't conflict with the bin name. # This seems to be only an issue on Windows, see https://github.com/rust-lang/cargo/issues/8519 name = "drop_app_lib" -crate-type = ["staticlib", "cdylib", "rlib"] -rustflags = ["-C", "target-feature=+aes,+sse2"] - - -[build-dependencies] -tauri-build = { version = "2.0.0", features = [] } +# rustflags = ["-C", "target-feature=+aes,+sse2"] [dependencies] -tauri-plugin-shell = "2.2.1" -serde_json = "1" -rayon = "1.10.0" -webbrowser = "1.0.2" -url = "2.5.2" -tauri-plugin-deep-link = "2" -log = "0.4.22" +boxcar = "0.2.7" +dirs = "6.0.0" +drop-database = { path = "./drop-database" } +drop-downloads = { path = "./drop-downloads" } +drop-errors = { path = "./drop-errors" } +drop-native-library = { path = "./drop-native-library" } +drop-process = { path = "./drop-process" } +drop-remote = { path = "./drop-remote" } +futures-lite = "2.6.0" hex = "0.4.3" -tauri-plugin-dialog = "2" http = "1.1.0" -urlencoding = "2.1.3" +known-folders = "1.2.0" +log = "0.4.22" md5 = "0.7.0" -chrono = "0.4.38" -tauri-plugin-os = "2" -boxcar = "0.2.7" -umu-wrapper-lib = "0.1.0" -tauri-plugin-autostart = "2.0.0" -shared_child = "1.0.1" -serde_with = "3.12.0" -slice-deque = "0.3.0" -throttle_my_fn = "0.2.6" -parking_lot = "0.12.3" -atomic-instant-full = "0.1.0" -cacache = "13.1.0" -http-serde = "2.1.1" -reqwest-middleware = "0.4.0" -reqwest-middleware-cache = "0.1.1" -deranged = "=0.4.0" -droplet-rs = "0.7.3" -gethostname = "1.0.1" -zstd = "0.13.3" -tar = "0.4.44" -rand = "0.9.1" +rayon = "1.10.0" regex = "1.11.1" +reqwest-websocket = "0.5.0" +serde_json = "1" +tar = "0.4.44" +tauri = { version = "2.7.0", features = ["protocol-asset", "tray-icon"] } +tauri-plugin-autostart = "2.0.0" +tauri-plugin-deep-link = "2" +tauri-plugin-dialog = "2" +tauri-plugin-opener = "2.4.0" +tauri-plugin-os = "2" +tauri-plugin-shell = "2.2.1" tempfile = "3.19.1" -schemars = "0.8.22" -sha1 = "0.10.6" -dirs = "6.0.0" +url = "2.5.2" +webbrowser = "1.0.2" whoami = "1.6.0" -filetime = "0.2.25" -walkdir = "2.5.0" -known-folders = "1.2.0" -native_model = { version = "0.6.4", features = ["rmp_serde_1_3"], git = "https://github.com/Drop-OSS/native_model.git"} -tauri-plugin-opener = "2.4.0" -bitcode = "0.6.6" -reqwest-websocket = "0.5.0" -futures-lite = "2.6.0" -page_size = "0.6.0" -sysinfo = "0.36.1" -humansize = "2.1.3" -tokio-util = { version = "0.7.16", features = ["io"] } -futures-core = "0.3.31" -bytes = "1.10.1" -# tailscale = { path = "./tailscale" } - -[dependencies.dynfmt] -version = "0.1.5" -features = ["curly"] - -[dependencies.tauri] -version = "2.7.0" -features = ["protocol-asset", "tray-icon"] - -[dependencies.tokio] -version = "1.40.0" -features = ["rt", "tokio-macros", "signal"] +zstd = "0.13.3" [dependencies.log4rs] version = "1.3.0" features = ["console_appender", "file_appender"] -[dependencies.rustix] -version = "0.38.37" -features = ["fs"] - -[dependencies.uuid] -version = "1.10.0" -features = ["v4", "fast-rng", "macro-diagnostics"] - -[dependencies.rustbreak] -version = "2" -features = ["other_errors"] # You can also use "yaml_enc" or "bin_enc" - [dependencies.reqwest] version = "0.12.22" default-features = false features = [ - "json", - "http2", - "blocking", - "rustls-tls", - "native-tls-alpn", - "rustls-tls-native-roots", - "stream", + "blocking", + "http2", + "json", + "native-tls-alpn", + "rustls-tls", + "rustls-tls-native-roots", + "stream", ] +[dependencies.rustix] +version = "0.38.37" +features = ["fs"] + [dependencies.serde] version = "1" features = ["derive", "rc"] +[dependencies.uuid] +version = "1.10.0" +features = ["fast-rng", "macro-diagnostics", "v4"] + +[build-dependencies] +tauri-build = { version = "2.0.0", features = [] } + +[target."cfg(any(target_os = \"macos\", windows, target_os = \"linux\"))".dependencies] +tauri-plugin-single-instance = { version = "2.0.0", features = ["deep-link"] } + [profile.release] lto = true +panic = "abort" codegen-units = 1 -panic = 'abort' + diff --git a/src-tauri/drop-consts/Cargo.toml b/src-tauri/drop-consts/Cargo.toml new file mode 100644 index 00000000..3485b2c2 --- /dev/null +++ b/src-tauri/drop-consts/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "drop-consts" +version = "0.1.0" +edition = "2024" + +[dependencies] +dirs = "6.0.0" diff --git a/src-tauri/drop-consts/src/lib.rs b/src-tauri/drop-consts/src/lib.rs new file mode 100644 index 00000000..91389db0 --- /dev/null +++ b/src-tauri/drop-consts/src/lib.rs @@ -0,0 +1,15 @@ +use std::{ + path::PathBuf, + sync::{Arc, LazyLock}, +}; + +#[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<&'static PathBuf> = + LazyLock::new(|| Box::leak(Box::new(dirs::data_dir().unwrap().join(DATA_ROOT_PREFIX)))); + +pub static CACHE_DIR: LazyLock<&'static PathBuf> = + LazyLock::new(|| Box::leak(Box::new(DATA_ROOT_DIR.join("cache")))); diff --git a/src-tauri/drop-database/Cargo.toml b/src-tauri/drop-database/Cargo.toml new file mode 100644 index 00000000..023176e5 --- /dev/null +++ b/src-tauri/drop-database/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "drop-database" +version = "0.1.0" +edition = "2024" + +[dependencies] +bitcode = "0.6.7" +chrono = "0.4.42" +drop-consts = { path = "../drop-consts" } +drop-library = { path = "../drop-library" } +drop-native-library = { path = "../drop-native-library" } +log = "0.4.28" +native_model = { git = "https://github.com/Drop-OSS/native_model.git", version = "0.6.4", features = [ + "rmp_serde_1_3", +] } +rustbreak = "2.0.0" +serde = { version = "1.0.219", features = ["derive"] } +serde_with = "3.14.0" +url = "2.5.7" +whoami = "1.6.1" + diff --git a/src-tauri/src/database/db.rs b/src-tauri/drop-database/src/db.rs similarity index 69% rename from src-tauri/src/database/db.rs rename to src-tauri/drop-database/src/db.rs index 2a50f3ac..83652fe9 100644 --- a/src-tauri/src/database/db.rs +++ b/src-tauri/drop-database/src/db.rs @@ -7,23 +7,15 @@ use std::{ }; use chrono::Utc; +use drop_consts::DATA_ROOT_DIR; use log::{debug, error, info, warn}; use rustbreak::{DeSerError, DeSerializer, PathDatabase, RustbreakError}; use serde::{Serialize, de::DeserializeOwned}; -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().unwrap().join(DATA_ROOT_PREFIX))); - // Custom JSON serializer to support everything we need #[derive(Debug, Default, Clone)] pub struct DropDatabaseSerializer; @@ -32,16 +24,15 @@ impl DeSerializer for DropDatabaseSerializer { fn serialize(&self, val: &T) -> rustbreak::error::DeSerResult> { - native_model::encode(val) - .map_err(|e| DeSerError::Internal(e.to_string())) + 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()))?; + .map_err(|e| rustbreak::error::DeSerError::Internal(e.to_string()))?; + let (val, _version) = + native_model::decode(buf).map_err(|e| DeSerError::Internal(e.to_string()))?; Ok(val) } } @@ -51,8 +42,6 @@ pub type DatabaseInterface = pub trait DatabaseImpls { fn set_up_database() -> DatabaseInterface; - fn database_is_set_up(&self) -> bool; - fn fetch_base_url(&self) -> Url; } impl DatabaseImpls for DatabaseInterface { fn set_up_database() -> DatabaseInterface { @@ -77,7 +66,7 @@ impl DatabaseImpls for DatabaseInterface { Err(e) => handle_invalid_database(e, db_path, games_base_dir, cache_dir), } } else { - let default = Database::new(games_base_dir, None, cache_dir); + let default = Database::new(games_base_dir, None); debug!( "Creating database at path {}", db_path.as_os_str().to_str().unwrap() @@ -85,15 +74,6 @@ impl DatabaseImpls for DatabaseInterface { PathDatabase::create_at_path(db_path, default).expect("Database could not be created") } } - - fn database_is_set_up(&self) -> bool { - !self.borrow_data().unwrap().base_url.is_empty() - } - - fn fetch_base_url(&self) -> Url { - let handle = self.borrow_data().unwrap(); - Url::parse(&handle.base_url).unwrap() - } } // TODO: Make the error relelvant rather than just assume that it's a Deserialize error @@ -116,15 +96,14 @@ fn handle_invalid_database( let db = Database::new( games_base_dir.into_os_string().into_string().unwrap(), Some(new_path), - cache_dir, ); PathDatabase::create_at_path(db_path, db).expect("Database could not be created") } // To automatically save the database upon drop -pub struct DBRead<'a>(RwLockReadGuard<'a, Database>); -pub struct DBWrite<'a>(ManuallyDrop>); +pub struct DBRead<'a>(pub(crate) RwLockReadGuard<'a, Database>); +pub struct DBWrite<'a>(pub(crate) ManuallyDrop>); impl<'a> Deref for DBWrite<'a> { type Target = Database; @@ -159,23 +138,3 @@ impl Drop for DBWrite<'_> { } } } - -pub fn borrow_db_checked<'a>() -> DBRead<'a> { - match DB.borrow_data() { - Ok(data) => DBRead(data), - Err(e) => { - error!("database borrow failed with error {e}"); - panic!("database borrow failed with error {e}"); - } - } -} - -pub fn borrow_db_mut_checked<'a>() -> DBWrite<'a> { - match DB.borrow_data_mut() { - Ok(data) => DBWrite(ManuallyDrop::new(data)), - Err(e) => { - error!("database borrow mut failed with error {e}"); - panic!("database borrow mut failed with error {e}"); - } - } -} diff --git a/src-tauri/src/database/debug.rs b/src-tauri/drop-database/src/debug.rs similarity index 100% rename from src-tauri/src/database/debug.rs rename to src-tauri/drop-database/src/debug.rs diff --git a/src-tauri/src/games/downloads/drop_data.rs b/src-tauri/drop-database/src/drop_data.rs similarity index 99% rename from src-tauri/src/games/downloads/drop_data.rs rename to src-tauri/drop-database/src/drop_data.rs index 52ad3fb8..196fa77f 100644 --- a/src-tauri/src/games/downloads/drop_data.rs +++ b/src-tauri/drop-database/src/drop_data.rs @@ -9,7 +9,7 @@ pub type DropData = v1::DropData; pub static DROP_DATA_PATH: &str = ".dropdata"; -pub mod v1 { +mod v1 { use std::{collections::HashMap, path::PathBuf, sync::Mutex}; use native_model::native_model; diff --git a/src-tauri/drop-database/src/lib.rs b/src-tauri/drop-database/src/lib.rs new file mode 100644 index 00000000..4bc12565 --- /dev/null +++ b/src-tauri/drop-database/src/lib.rs @@ -0,0 +1,34 @@ +use std::{mem::ManuallyDrop, sync::LazyLock}; + +use log::error; + +use crate::db::{DBRead, DBWrite, DatabaseImpls, DatabaseInterface}; + +pub mod db; +pub mod debug; +pub mod models; +pub mod process; +pub mod runtime_models; +pub mod drop_data; + +pub static DB: LazyLock = LazyLock::new(DatabaseInterface::set_up_database); + +pub fn borrow_db_checked<'a>() -> DBRead<'a> { + match DB.borrow_data() { + Ok(data) => DBRead(data), + Err(e) => { + error!("database borrow failed with error {e}"); + panic!("database borrow failed with error {e}"); + } + } +} + +pub fn borrow_db_mut_checked<'a>() -> DBWrite<'a> { + match DB.borrow_data_mut() { + Ok(data) => DBWrite(ManuallyDrop::new(data)), + Err(e) => { + error!("database borrow mut failed with error {e}"); + panic!("database borrow mut failed with error {e}"); + } + } +} diff --git a/src-tauri/src/database/models.rs b/src-tauri/drop-database/src/models.rs similarity index 82% rename from src-tauri/src/database/models.rs rename to src-tauri/drop-database/src/models.rs index 848169a5..e8c7f432 100644 --- a/src-tauri/src/database/models.rs +++ b/src-tauri/drop-database/src/models.rs @@ -4,11 +4,11 @@ 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; - pub type Database = v3::Database; + pub type Database = v4::Database; pub type Settings = v1::Settings; pub type DatabaseAuth = v1::DatabaseAuth; @@ -19,7 +19,7 @@ pub mod data { */ pub type DownloadableMetadata = v1::DownloadableMetadata; pub type DownloadType = v1::DownloadType; - pub type DatabaseApplications = v2::DatabaseApplications; + pub type DatabaseApplications = v4::DatabaseApplications; // pub type DatabaseCompatInfo = v2::DatabaseCompatInfo; use std::collections::HashMap; @@ -37,10 +37,11 @@ pub mod data { } mod v1 { - use crate::process::process_manager::Platform; use serde_with::serde_as; use std::{collections::HashMap, path::PathBuf}; + use crate::process::Platform; + use super::{Deserialize, Serialize, native_model}; fn default_template() -> String { @@ -190,9 +191,9 @@ pub mod data { use serde_with::serde_as; - use super::{ - Deserialize, Serialize, native_model, v1, - }; + use crate::runtime_models::Game; + + 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)] @@ -274,14 +275,13 @@ pub mod data { #[native_model(id = 3, version = 2, with = native_model::rmp_serde_1_3::RmpSerde, from=v1::DatabaseApplications)] pub struct DatabaseApplications { 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 { @@ -335,28 +332,73 @@ pub mod data { } } + mod v4 { + use std::{collections::HashMap, path::PathBuf}; + use drop_library::libraries::LibraryProviderIdentifier; + use drop_native_library::impls::DropNativeLibraryProvider; + use serde_with::serde_as; + use crate::models::data::v3; + use super::{Deserialize, Serialize, native_model, v1, v2}; + + #[derive(Serialize, Deserialize, Clone)] + pub enum Library { + NativeLibrary(DropNativeLibraryProvider), + } + + #[serde_as] + #[derive(Serialize, Deserialize, Default, Clone)] + #[serde(rename_all = "camelCase")] + #[native_model(id = 3, version = 4, with = native_model::rmp_serde_1_3::RmpSerde, from=v2::DatabaseApplications)] + pub struct DatabaseApplications { + pub install_dirs: Vec, + pub libraries: HashMap, + + #[serde(skip)] + pub transient_statuses: + HashMap, + } + + impl From for DatabaseApplications { + fn from(value: v2::DatabaseApplications) -> Self { + todo!() + } + } + + #[native_model(id = 1, version = 4, with = native_model::rmp_serde_1_3::RmpSerde, from = v3::Database)] + #[derive(Serialize, Deserialize, Default, Clone)] + pub struct Database { + #[serde(default)] + pub settings: v1::Settings, + pub drop_applications: DatabaseApplications, + #[serde(skip)] + pub prev_database: Option, + } + + impl From for Database { + fn from(value: v3::Database) -> Self { + Database { + settings: value.settings, + drop_applications: value.applications.into(), + prev_database: value.prev_database, + } + } + } + } + impl Database { pub fn new>( games_base_dir: T, prev_database: Option, - cache_dir: PathBuf, ) -> Self { Self { - applications: DatabaseApplications { + drop_applications: DatabaseApplications { install_dirs: vec![games_base_dir.into()], - game_statuses: HashMap::new(), - game_versions: HashMap::new(), - installed_game_version: HashMap::new(), + libraries: HashMap::new(), transient_statuses: HashMap::new(), }, prev_database, - base_url: String::new(), - auth: None, settings: Settings::default(), - cache_dir, - compat_info: None, } } - } } diff --git a/src-tauri/drop-database/src/process.rs b/src-tauri/drop-database/src/process.rs new file mode 100644 index 00000000..26428b52 --- /dev/null +++ b/src-tauri/drop-database/src/process.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, + _ => unimplemented!(), + } + } +} diff --git a/src-tauri/drop-database/src/runtime_models.rs b/src-tauri/drop-database/src/runtime_models.rs new file mode 100644 index 00000000..545f068f --- /dev/null +++ b/src-tauri/drop-database/src/runtime_models.rs @@ -0,0 +1,28 @@ +use bitcode::{Decode, Encode}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Clone, Debug, Default, Encode, Decode)] +#[serde(rename_all = "camelCase")] +pub struct Game { + pub 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(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/drop-downloads/Cargo.toml b/src-tauri/drop-downloads/Cargo.toml new file mode 100644 index 00000000..e1d2d489 --- /dev/null +++ b/src-tauri/drop-downloads/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "drop-downloads" +version = "0.1.0" +edition = "2024" + +[dependencies] +atomic-instant-full = "0.1.0" +drop-database = { path = "../drop-database" } +drop-errors = { path = "../drop-errors" } +# can't depend, cycle +# drop-native-library = { path = "../drop-native-library" } +log = "0.4.22" +parking_lot = "0.12.4" +serde = "1.0.219" +tauri = { version = "2.7.0" } +throttle_my_fn = "0.2.6" diff --git a/src-tauri/src/download_manager/download_manager_builder.rs b/src-tauri/drop-downloads/src/download_manager_builder.rs similarity index 86% rename from src-tauri/src/download_manager/download_manager_builder.rs rename to src-tauri/drop-downloads/src/download_manager_builder.rs index b3461203..e7ff4216 100644 --- a/src-tauri/src/download_manager/download_manager_builder.rs +++ b/src-tauri/drop-downloads/src/download_manager_builder.rs @@ -7,14 +7,13 @@ use std::{ thread::{JoinHandle, spawn}, }; +use drop_database::models::data::DownloadableMetadata; +use drop_errors::application_download_error::ApplicationDownloadError; use log::{debug, error, info, warn}; use tauri::{AppHandle, Emitter}; use crate::{ - database::models::data::DownloadableMetadata, - download_manager::download_manager_frontend::DownloadStatus, - error::application_download_error::ApplicationDownloadError, - games::library::{QueueUpdateEvent, QueueUpdateEventQueueData, StatsUpdateEvent}, + download_manager_frontend::DownloadStatus, events::{QueueUpdateEvent, QueueUpdateEventQueueData, StatsUpdateEvent} }; use super::{ @@ -30,43 +29,6 @@ use super::{ pub type DownloadAgent = Arc>; pub type CurrentProgressObject = Arc>>>; -/* - -Welcome to the download manager, the most overengineered, glorious piece of bullshit. - -The download manager takes a queue of ids and their associated -DownloadAgents, and then, one-by-one, executes them. It provides an interface -to interact with the currently downloading agent, and manage the queue. - -When the DownloadManager is initialised, it is designed to provide a reference -which can be used to provide some instructions (the DownloadManagerInterface), -but other than that, it runs without any sort of interruptions. - -It does this by opening up two data structures. Primarily is the command_receiver, -and mpsc (multi-channel-single-producer) which allows commands to be sent from -the Interface, and queued up for the Manager to process. - -These have been mapped in the DownloadManagerSignal docs. - -The other way to interact with the DownloadManager is via the donwload_queue, -which is just a collection of ids which may be rearranged to suit -whichever download queue order is required. - -+----------------------------------------------------------------------------+ -| DO NOT ATTEMPT TO ADD OR REMOVE FROM THE QUEUE WITHOUT USING SIGNALS!! | -| THIS WILL CAUSE A DESYNC BETWEEN THE DOWNLOAD AGENT REGISTRY AND THE QUEUE | -| WHICH HAS NOT BEEN ACCOUNTED FOR | -+----------------------------------------------------------------------------+ - -This download queue does not actually own any of the DownloadAgents. It is -simply an id-based reference system. The actual Agents are stored in the -download_agent_registry HashMap, as ordering is no issue here. This is why -appending or removing from the download_queue must be done via signals. - -Behold, my madness - quexeky - -*/ - pub struct DownloadManagerBuilder { download_agent_registry: HashMap, download_queue: Queue, diff --git a/src-tauri/src/download_manager/download_manager_frontend.rs b/src-tauri/drop-downloads/src/download_manager_frontend.rs similarity index 97% rename from src-tauri/src/download_manager/download_manager_frontend.rs rename to src-tauri/drop-downloads/src/download_manager_frontend.rs index 13d20e62..c9ccbc44 100644 --- a/src-tauri/src/download_manager/download_manager_frontend.rs +++ b/src-tauri/drop-downloads/src/download_manager_frontend.rs @@ -9,14 +9,11 @@ use std::{ thread::JoinHandle, }; +use drop_database::models::data::DownloadableMetadata; +use drop_errors::application_download_error::ApplicationDownloadError; use log::{debug, info}; use serde::Serialize; -use crate::{ - database::models::data::DownloadableMetadata, - error::application_download_error::ApplicationDownloadError, -}; - use super::{ download_manager_builder::{CurrentProgressObject, DownloadAgent}, util::queue::Queue, diff --git a/src-tauri/src/download_manager/downloadable.rs b/src-tauri/drop-downloads/src/downloadable.rs similarity index 88% rename from src-tauri/src/download_manager/downloadable.rs rename to src-tauri/drop-downloads/src/downloadable.rs index 547daf80..0c5133e8 100644 --- a/src-tauri/src/download_manager/downloadable.rs +++ b/src-tauri/drop-downloads/src/downloadable.rs @@ -1,12 +1,9 @@ use std::sync::Arc; +use drop_database::models::data::DownloadableMetadata; +use drop_errors::application_download_error::ApplicationDownloadError; use tauri::AppHandle; -use crate::{ - database::models::data::DownloadableMetadata, - error::application_download_error::ApplicationDownloadError, -}; - use super::{ download_manager_frontend::DownloadStatus, util::{download_thread_control_flag::DownloadThreadControl, progress_object::ProgressObject}, diff --git a/src-tauri/drop-downloads/src/events.rs b/src-tauri/drop-downloads/src/events.rs new file mode 100644 index 00000000..e0b38848 --- /dev/null +++ b/src-tauri/drop-downloads/src/events.rs @@ -0,0 +1,24 @@ +use drop_database::models::data::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/drop-downloads/src/lib.rs b/src-tauri/drop-downloads/src/lib.rs new file mode 100644 index 00000000..02dd730f --- /dev/null +++ b/src-tauri/drop-downloads/src/lib.rs @@ -0,0 +1,7 @@ +#![feature(duration_millis_float)] + +pub mod download_manager_builder; +pub mod download_manager_frontend; +pub mod downloadable; +pub mod events; +pub mod util; diff --git a/src-tauri/src/download_manager/util/download_thread_control_flag.rs b/src-tauri/drop-downloads/src/util/download_thread_control_flag.rs similarity index 100% rename from src-tauri/src/download_manager/util/download_thread_control_flag.rs rename to src-tauri/drop-downloads/src/util/download_thread_control_flag.rs diff --git a/src-tauri/src/download_manager/util/mod.rs b/src-tauri/drop-downloads/src/util/mod.rs similarity index 100% rename from src-tauri/src/download_manager/util/mod.rs rename to src-tauri/drop-downloads/src/util/mod.rs diff --git a/src-tauri/src/download_manager/util/progress_object.rs b/src-tauri/drop-downloads/src/util/progress_object.rs similarity index 98% rename from src-tauri/src/download_manager/util/progress_object.rs rename to src-tauri/drop-downloads/src/util/progress_object.rs index 43c8d76d..e6379374 100644 --- a/src-tauri/src/download_manager/util/progress_object.rs +++ b/src-tauri/drop-downloads/src/util/progress_object.rs @@ -10,7 +10,7 @@ use std::{ use atomic_instant_full::AtomicInstant; use throttle_my_fn::throttle; -use crate::download_manager::download_manager_frontend::DownloadManagerSignal; +use crate::download_manager_frontend::DownloadManagerSignal; use super::rolling_progress_updates::RollingProgressWindow; diff --git a/src-tauri/src/download_manager/util/queue.rs b/src-tauri/drop-downloads/src/util/queue.rs similarity index 95% rename from src-tauri/src/download_manager/util/queue.rs rename to src-tauri/drop-downloads/src/util/queue.rs index c4fda823..5c481b16 100644 --- a/src-tauri/src/download_manager/util/queue.rs +++ b/src-tauri/drop-downloads/src/util/queue.rs @@ -3,7 +3,7 @@ use std::{ sync::{Arc, Mutex, MutexGuard}, }; -use crate::database::models::data::DownloadableMetadata; +use drop_database::models::data::DownloadableMetadata; #[derive(Clone)] pub struct Queue { diff --git a/src-tauri/src/download_manager/util/rolling_progress_updates.rs b/src-tauri/drop-downloads/src/util/rolling_progress_updates.rs similarity index 100% rename from src-tauri/src/download_manager/util/rolling_progress_updates.rs rename to src-tauri/drop-downloads/src/util/rolling_progress_updates.rs diff --git a/src-tauri/drop-errors/Cargo.toml b/src-tauri/drop-errors/Cargo.toml new file mode 100644 index 00000000..0aa44fc1 --- /dev/null +++ b/src-tauri/drop-errors/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "drop-errors" +version = "0.1.0" +edition = "2024" + +[dependencies] +http = "1.3.1" +humansize = "2.1.3" +reqwest = "0.12.23" +reqwest-websocket = "0.5.1" +serde = { version = "1.0.219", features = ["derive"] } +serde_with = "3.14.0" +tauri-plugin-opener = "2.5.0" +url = "2.5.7" diff --git a/src-tauri/src/error/application_download_error.rs b/src-tauri/drop-errors/src/application_download_error.rs similarity index 100% rename from src-tauri/src/error/application_download_error.rs rename to src-tauri/drop-errors/src/application_download_error.rs diff --git a/src-tauri/src/error/download_manager_error.rs b/src-tauri/drop-errors/src/download_manager_error.rs similarity index 100% rename from src-tauri/src/error/download_manager_error.rs rename to src-tauri/drop-errors/src/download_manager_error.rs diff --git a/src-tauri/src/error/drop_server_error.rs b/src-tauri/drop-errors/src/drop_server_error.rs similarity index 87% rename from src-tauri/src/error/drop_server_error.rs rename to src-tauri/drop-errors/src/drop_server_error.rs index 26f371b7..cbb9b8a3 100644 --- a/src-tauri/src/error/drop_server_error.rs +++ b/src-tauri/drop-errors/src/drop_server_error.rs @@ -2,7 +2,7 @@ use serde::Deserialize; #[derive(Deserialize, Debug, Clone)] #[serde(rename_all = "camelCase")] -pub struct DropServerError { +pub struct ServerError { pub status_code: usize, pub status_message: String, // pub message: String, diff --git a/src-tauri/src/error/mod.rs b/src-tauri/drop-errors/src/lib.rs similarity index 100% rename from src-tauri/src/error/mod.rs rename to src-tauri/drop-errors/src/lib.rs diff --git a/src-tauri/src/error/library_error.rs b/src-tauri/drop-errors/src/library_error.rs similarity index 100% rename from src-tauri/src/error/library_error.rs rename to src-tauri/drop-errors/src/library_error.rs diff --git a/src-tauri/src/error/process_error.rs b/src-tauri/drop-errors/src/process_error.rs similarity index 100% rename from src-tauri/src/error/process_error.rs rename to src-tauri/drop-errors/src/process_error.rs diff --git a/src-tauri/src/error/remote_access_error.rs b/src-tauri/drop-errors/src/remote_access_error.rs similarity index 97% rename from src-tauri/src/error/remote_access_error.rs rename to src-tauri/drop-errors/src/remote_access_error.rs index d57ce15d..61220479 100644 --- a/src-tauri/src/error/remote_access_error.rs +++ b/src-tauri/drop-errors/src/remote_access_error.rs @@ -8,7 +8,7 @@ use http::StatusCode; use serde_with::SerializeDisplay; use url::ParseError; -use super::drop_server_error::DropServerError; +use super::drop_server_error::ServerError; #[derive(Debug, SerializeDisplay)] pub enum RemoteAccessError { @@ -18,7 +18,7 @@ pub enum RemoteAccessError { InvalidEndpoint, HandshakeFailed(String), GameNotFound(String), - InvalidResponse(DropServerError), + InvalidResponse(ServerError), UnparseableResponse(String), ManifestDownloadFailed(StatusCode, String), OutOfSync, diff --git a/src-tauri/drop-library/Cargo.toml b/src-tauri/drop-library/Cargo.toml new file mode 100644 index 00000000..a5d9d79e --- /dev/null +++ b/src-tauri/drop-library/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "drop-library" +version = "0.1.0" +edition = "2024" + +[dependencies] +drop-errors = { path = "../drop-errors" } +http = "*" +reqwest = { version = "*", default-features = false } +serde = { version = "*", default-features = false, features = ["derive"] } +tauri = "*" diff --git a/src-tauri/drop-library/src/errors.rs b/src-tauri/drop-library/src/errors.rs new file mode 100644 index 00000000..ff4d4ead --- /dev/null +++ b/src-tauri/drop-library/src/errors.rs @@ -0,0 +1,11 @@ +pub enum DropLibraryError { + NetworkError(reqwest::Error), + ServerError(drop_errors::drop_server_error::ServerError), + Unconfigured, +} + +impl From for DropLibraryError { + fn from(value: reqwest::Error) -> Self { + DropLibraryError::NetworkError(value) + } +} \ No newline at end of file diff --git a/src-tauri/drop-library/src/game.rs b/src-tauri/drop-library/src/game.rs new file mode 100644 index 00000000..1a9cdae7 --- /dev/null +++ b/src-tauri/drop-library/src/game.rs @@ -0,0 +1,30 @@ +use crate::libraries::LibraryProviderIdentifier; + +pub struct LibraryGamePreview { + pub library: LibraryProviderIdentifier, + pub internal_id: String, + pub name: String, + pub short_description: String, + pub icon: String, +} + +pub struct LibraryGame { + pub library: LibraryProviderIdentifier, + pub internal_id: String, + pub name: String, + pub short_description: String, + pub md_description: String, + pub icon: String, +} + +impl From for LibraryGamePreview { + fn from(value: LibraryGame) -> Self { + LibraryGamePreview { + library: value.library, + internal_id: value.internal_id, + name: value.name, + short_description: value.short_description, + icon: value.icon, + } + } +} diff --git a/src-tauri/drop-library/src/lib.rs b/src-tauri/drop-library/src/lib.rs new file mode 100644 index 00000000..a1fa7b26 --- /dev/null +++ b/src-tauri/drop-library/src/lib.rs @@ -0,0 +1,3 @@ +pub mod libraries; +pub mod game; +pub mod errors; \ No newline at end of file diff --git a/src-tauri/drop-library/src/libraries.rs b/src-tauri/drop-library/src/libraries.rs new file mode 100644 index 00000000..db6e4492 --- /dev/null +++ b/src-tauri/drop-library/src/libraries.rs @@ -0,0 +1,76 @@ +use std::{ + fmt::Display, + hash::{DefaultHasher, Hash, Hasher}, +}; + +use http::Request; +use serde::{Deserialize, Serialize, de::DeserializeOwned}; +use tauri::UriSchemeResponder; + +use crate::{ + errors::DropLibraryError, + game::{LibraryGame, LibraryGamePreview}, +}; + +#[derive(Clone, Serialize, Deserialize)] +pub struct LibraryProviderIdentifier { + internal_id: usize, + name: String, +} + +impl PartialEq for LibraryProviderIdentifier { + fn eq(&self, other: &Self) -> bool { + self.internal_id == other.internal_id + } +} + +impl Eq for LibraryProviderIdentifier {} + +impl Hash for LibraryProviderIdentifier { + fn hash(&self, state: &mut H) { + self.internal_id.hash(state); + } +} + +impl Display for LibraryProviderIdentifier { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(&self.name) + } +} + +impl LibraryProviderIdentifier { + pub fn str_hash(&self) -> String { + let mut hasher = DefaultHasher::new(); + self.hash(&mut hasher); + hasher.finish().to_string() + } +} + +pub struct LibraryFetchConfig { + pub hard_refresh: bool, +} + +pub trait DropLibraryProvider: Serialize + DeserializeOwned + Sized { + fn build(identifier: LibraryProviderIdentifier) -> Self; + fn id(&self) -> &LibraryProviderIdentifier; + fn load_object( + &self, + request: Request>, + responder: UriSchemeResponder, + ) -> impl Future> + Send; + + fn fetch_library( + &self, + config: &LibraryFetchConfig, + ) -> impl Future, DropLibraryError>> + Send; + fn fetch_game( + &self, + config: &LibraryFetchConfig, + ) -> impl Future> + Send; + + + + fn owns_game(&self, id: &LibraryProviderIdentifier) -> bool { + self.id().internal_id == id.internal_id + } +} diff --git a/src-tauri/drop-native-library/Cargo.toml b/src-tauri/drop-native-library/Cargo.toml new file mode 100644 index 00000000..127a67d6 --- /dev/null +++ b/src-tauri/drop-native-library/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "drop-native-library" +version = "0.1.0" +edition = "2024" + +[dependencies] +bitcode = "*" +drop-errors = { path = "../drop-errors" } +drop-library = { path = "../drop-library" } +drop-remote = { path = "../drop-remote" } +log = "*" +serde = { version = "*", features = ["derive"] } +tauri = "*" +url = "*" diff --git a/src-tauri/src/games/collections/collection.rs b/src-tauri/drop-native-library/src/collections.rs similarity index 92% rename from src-tauri/src/games/collections/collection.rs rename to src-tauri/drop-native-library/src/collections.rs index ea29474c..64c2a319 100644 --- a/src-tauri/src/games/collections/collection.rs +++ b/src-tauri/drop-native-library/src/collections.rs @@ -1,8 +1,7 @@ use bitcode::{Decode, Encode}; +// use drop_database::runtime_models::Game; use serde::{Deserialize, Serialize}; -use crate::games::library::Game; - pub type Collections = Vec; #[derive(Serialize, Deserialize, Debug, Clone, Default, Encode, Decode)] diff --git a/src-tauri/drop-native-library/src/events.rs b/src-tauri/drop-native-library/src/events.rs new file mode 100644 index 00000000..77f24d67 --- /dev/null +++ b/src-tauri/drop-native-library/src/events.rs @@ -0,0 +1,11 @@ +use drop_database::models::data::{ApplicationTransientStatus, GameDownloadStatus, GameVersion}; + +#[derive(serde::Serialize, Clone)] +pub struct GameUpdateEvent { + pub game_id: String, + pub status: ( + Option, + Option, + ), + pub version: Option, +} \ No newline at end of file diff --git a/src-tauri/drop-native-library/src/impls.rs b/src-tauri/drop-native-library/src/impls.rs new file mode 100644 index 00000000..8875d0f0 --- /dev/null +++ b/src-tauri/drop-native-library/src/impls.rs @@ -0,0 +1,50 @@ +use drop_library::{ + errors::DropLibraryError, game::{LibraryGame, LibraryGamePreview}, libraries::{DropLibraryProvider, LibraryFetchConfig, LibraryProviderIdentifier} +}; +use drop_remote::{fetch_object::fetch_object, DropRemoteContext}; +use serde::{Deserialize, Serialize}; +use url::Url; + +#[derive(Serialize, Deserialize, Clone)] +pub struct DropNativeLibraryProvider { + identifier: LibraryProviderIdentifier, + context: Option, +} + +impl DropNativeLibraryProvider { + pub fn configure(&mut self, base_url: Url) { + self.context = Some(DropRemoteContext::new(base_url)); + } +} + +impl DropLibraryProvider for DropNativeLibraryProvider { + fn build(identifier: LibraryProviderIdentifier) -> Self { + Self { + identifier, + context: None, + } + } + + fn id(&self) -> &LibraryProviderIdentifier { + &self.identifier + } + + async fn load_object(&self, request: tauri::http::Request>, responder: tauri::UriSchemeResponder) -> Result<(), DropLibraryError> { + let context = self.context.as_ref().ok_or(DropLibraryError::Unconfigured)?; + fetch_object(context, request, responder).await; + Ok(()) + } + + async fn fetch_library( + &self, + config: &LibraryFetchConfig + ) -> Result, DropLibraryError> { + todo!() + } + + async fn fetch_game(&self, config: &LibraryFetchConfig) -> Result { + todo!() + } + + +} diff --git a/src-tauri/drop-native-library/src/lib.rs b/src-tauri/drop-native-library/src/lib.rs new file mode 100644 index 00000000..ab58949f --- /dev/null +++ b/src-tauri/drop-native-library/src/lib.rs @@ -0,0 +1,5 @@ +//pub mod collections; +//pub mod library; +//pub mod state; +//pub mod events; +pub mod impls; diff --git a/src-tauri/src/games/library.rs b/src-tauri/drop-native-library/src/library.rs similarity index 71% rename from src-tauri/src/games/library.rs rename to src-tauri/drop-native-library/src/library.rs index 2978908c..4b562e01 100644 --- a/src-tauri/src/games/library.rs +++ b/src-tauri/drop-native-library/src/library.rs @@ -1,30 +1,34 @@ use std::fs::remove_dir_all; -use std::sync::Mutex; use std::thread::spawn; +use drop_database::borrow_db_checked; +use drop_database::borrow_db_mut_checked; +use drop_database::models::data::ApplicationTransientStatus; +use drop_database::models::data::Database; +use drop_database::models::data::DownloadableMetadata; +use drop_database::models::data::GameDownloadStatus; +use drop_database::models::data::GameVersion; +use drop_database::runtime_models::Game; +use drop_errors::drop_server_error::ServerError; +use drop_errors::library_error::LibraryError; +use drop_errors::remote_access_error::RemoteAccessError; +use drop_remote::DropRemoteContext; +use drop_remote::auth::generate_authorization_header; +use drop_remote::cache::cache_object; +use drop_remote::cache::cache_object_db; +use drop_remote::cache::get_cached_object; +use drop_remote::cache::get_cached_object_db; +use drop_remote::requests::generate_url; +use drop_remote::utils::DROP_CLIENT_ASYNC; +use drop_remote::utils::DROP_CLIENT_SYNC; use log::{debug, error, warn}; use serde::{Deserialize, Serialize}; use tauri::AppHandle; -use tauri::Emitter; - -use crate::AppState; -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::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}; +use tauri::Emitter as _; + +use crate::events::GameUpdateEvent; +use crate::state::GameStatusManager; +use crate::state::GameStatusWithTransient; #[derive(Serialize, Deserialize, Debug)] pub struct FetchGameStruct { @@ -33,53 +37,8 @@ pub struct FetchGameStruct { 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>>, + context: &DropRemoteContext, hard_fresh: Option, ) -> Result, RemoteAccessError> { let do_hard_refresh = hard_fresh.unwrap_or(false); @@ -88,15 +47,15 @@ pub async fn fetch_library_logic( } let client = DROP_CLIENT_ASYNC.clone(); - let response = generate_url(&["/api/v1/client/user/library"], &[])?; + let response = generate_url(context, &["/api/v1/client/user/library"], &[])?; let response = client .get(response) - .header("Authorization", generate_authorization_header()) + .header("Authorization", generate_authorization_header(context)) .send() .await?; if response.status() != 200 { - let err = response.json().await.unwrap_or(DropServerError { + let err = response.json().await.unwrap_or(ServerError { status_code: 500, status_message: "Invalid response from server.".to_owned(), }); @@ -106,12 +65,13 @@ pub async fn fetch_library_logic( let mut games: Vec = response.json().await?; - let mut handle = state.lock().unwrap(); - let mut db_handle = borrow_db_mut_checked(); for game in &games { - handle.games.insert(game.id.clone(), game.clone()); + db_handle + .applications + .games + .insert(game.id.clone(), game.clone()); if !db_handle.applications.game_statuses.contains_key(&game.id) { db_handle .applications @@ -127,7 +87,7 @@ pub async fn fetch_library_logic( } // 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) { + let game = match get_cached_object_db::(&meta.id.clone()) { Ok(game) => game, Err(err) => { warn!( @@ -140,14 +100,12 @@ pub async fn fetch_library_logic( 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")?; @@ -168,12 +126,10 @@ pub async fn fetch_library_logic_offline( Ok(games) } pub async fn fetch_game_logic( + context: &DropRemoteContext, id: String, - state: tauri::State<'_, Mutex>>, ) -> Result { let version = { - let state_handle = state.lock().unwrap(); - let db_lock = borrow_db_checked(); let metadata_option = db_lock.applications.installed_game_version.get(&id); @@ -187,7 +143,7 @@ pub async fn fetch_game_logic( .cloned(), }; - let game = state_handle.games.get(&id); + let game = db_lock.applications.games.get(&id); if let Some(game) = game { let status = GameStatusManager::fetch_state(&id, &db_lock); @@ -206,15 +162,15 @@ pub async fn fetch_game_logic( }; let client = DROP_CLIENT_ASYNC.clone(); - let response = generate_url(&["/api/v1/client/game/", &id], &[])?; + let response = generate_url(context, &["/api/v1/client/game/", &id], &[])?; let response = client .get(response) - .header("Authorization", generate_authorization_header()) + .header("Authorization", generate_authorization_header(context)) .send() .await?; if response.status() == 404 { - let offline_fetch = fetch_game_logic_offline(id.clone(), state).await; + let offline_fetch = fetch_game_logic_offline(id.clone()).await; if let Ok(fetch_data) = offline_fetch { return Ok(fetch_data); } @@ -229,10 +185,11 @@ pub async fn fetch_game_logic( let game: Game = response.json().await?; - let mut state_handle = state.lock().unwrap(); - state_handle.games.insert(id.clone(), game.clone()); - let mut db_handle = borrow_db_mut_checked(); + db_handle + .applications + .games + .insert(id.clone(), game.clone()); db_handle .applications @@ -255,10 +212,7 @@ pub async fn fetch_game_logic( Ok(data) } -pub async fn fetch_game_logic_offline( - id: String, - _state: tauri::State<'_, Mutex>>, -) -> Result { +pub async fn fetch_game_logic_offline(id: String) -> Result { let db_handle = borrow_db_checked(); let metadata_option = db_handle.applications.installed_game_version.get(&id); let version = match metadata_option { @@ -284,15 +238,19 @@ pub async fn fetch_game_logic_offline( } pub async fn fetch_game_version_options_logic( + context: &DropRemoteContext, 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 = generate_url( + context, + &["/api/v1/client/game/versions"], + &[("id", &game_id)], + )?; let response = client .get(response) - .header("Authorization", generate_authorization_header()) + .header("Authorization", generate_authorization_header(context)) .send() .await?; @@ -304,19 +262,6 @@ pub async fn fetch_game_version_options_logic( let data: Vec = response.json().await?; - let state_lock = state.lock().unwrap(); - let process_manager_lock = state_lock.process_manager.lock().unwrap(); - let data: Vec = data - .into_iter() - .filter(|v| { - process_manager_lock - .valid_platform(&v.platform, &state_lock) - .unwrap() - }) - .collect(); - drop(process_manager_lock); - drop(state_lock); - Ok(data) } @@ -449,6 +394,7 @@ pub fn get_current_meta(game_id: &String) -> Option { } pub fn on_game_complete( + context: &DropRemoteContext, meta: &DownloadableMetadata, install_dir: String, app_handle: &AppHandle, @@ -460,6 +406,7 @@ pub fn on_game_complete( let client = DROP_CLIENT_SYNC.clone(); let response = generate_url( + context, &["/api/v1/client/game/version"], &[ ("id", &meta.id), @@ -468,7 +415,7 @@ pub fn on_game_complete( )?; let response = client .get(response) - .header("Authorization", generate_authorization_header()) + .header("Authorization", generate_authorization_header(context)) .send()?; let game_version: GameVersion = response.json()?; @@ -544,48 +491,3 @@ pub fn push_game_update( ) .unwrap(); } - -#[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().unwrap(); - - 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/games/state.rs b/src-tauri/drop-native-library/src/state.rs similarity index 86% rename from src-tauri/src/games/state.rs rename to src-tauri/drop-native-library/src/state.rs index 9cffc6d5..65aef6ec 100644 --- a/src-tauri/src/games/state.rs +++ b/src-tauri/drop-native-library/src/state.rs @@ -1,6 +1,4 @@ -use crate::database::models::data::{ - ApplicationTransientStatus, Database, DownloadType, DownloadableMetadata, GameDownloadStatus, -}; +// use drop_database::models::data::{ApplicationTransientStatus, Database, DownloadType, DownloadableMetadata, GameDownloadStatus}; pub type GameStatusWithTransient = ( Option, diff --git a/src-tauri/drop-process/Cargo.toml b/src-tauri/drop-process/Cargo.toml new file mode 100644 index 00000000..f0b195ea --- /dev/null +++ b/src-tauri/drop-process/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "drop-process" +version = "0.1.0" +edition = "2024" + +[dependencies] +chrono = "0.4.42" +drop-database = { path = "../drop-database" } +drop-errors = { path = "../drop-errors" } +drop-native-library = { path = "../drop-native-library" } +dynfmt = { version = "0.1.5", features = ["curly"] } +log = "0.4.28" +page_size = "0.6.0" +shared_child = "1.1.1" +sysinfo = "0.37.0" +tauri = "2.8.5" +tauri-plugin-opener = "2.5.0" + diff --git a/src-tauri/src/process/format.rs b/src-tauri/drop-process/src/format.rs similarity index 100% rename from src-tauri/src/process/format.rs rename to src-tauri/drop-process/src/format.rs diff --git a/src-tauri/drop-process/src/lib.rs b/src-tauri/drop-process/src/lib.rs new file mode 100644 index 00000000..4d6c6162 --- /dev/null +++ b/src-tauri/drop-process/src/lib.rs @@ -0,0 +1,4 @@ +mod format; +mod process_handlers; +pub mod process_manager; +pub mod utils; diff --git a/src-tauri/src/process/process_handlers.rs b/src-tauri/drop-process/src/process_handlers.rs similarity index 82% rename from src-tauri/src/process/process_handlers.rs rename to src-tauri/drop-process/src/process_handlers.rs index dcbee5cc..9e9559e3 100644 --- a/src-tauri/src/process/process_handlers.rs +++ b/src-tauri/drop-process/src/process_handlers.rs @@ -5,13 +5,11 @@ use std::{ sync::LazyLock, }; +use drop_database::{models::data::{Database, DownloadableMetadata, GameVersion}, process::Platform}; use log::{debug, info}; -use crate::{ - AppState, - database::models::data::{Database, DownloadableMetadata, GameVersion}, - process::process_manager::{Platform, ProcessHandler}, -}; +use crate::process_manager::ProcessHandler; + pub struct NativeGameLauncher; impl ProcessHandler for NativeGameLauncher { @@ -26,7 +24,7 @@ impl ProcessHandler for NativeGameLauncher { 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 } } @@ -85,11 +83,8 @@ impl ProcessHandler for UMULauncher { ) } - fn valid_for_platform(&self, _db: &Database, state: &AppState, _target: &Platform) -> bool { - let Some(ref compat_info) = state.compat_info else { - return false; - }; - compat_info.umu_installed + fn valid_for_platform(&self, _db: &Database, _target: &Platform) -> bool { + UMU_LAUNCHER_EXECUTABLE.is_some() } } @@ -123,7 +118,7 @@ impl ProcessHandler for AsahiMuvmLauncher { #[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; @@ -135,10 +130,6 @@ impl ProcessHandler for AsahiMuvmLauncher { return false; } - let Some(ref compat_info) = state.compat_info else { - return false; - }; - - compat_info.umu_installed + UMU_LAUNCHER_EXECUTABLE.is_some() } } diff --git a/src-tauri/src/process/process_manager.rs b/src-tauri/drop-process/src/process_manager.rs similarity index 83% rename from src-tauri/src/process/process_manager.rs rename to src-tauri/drop-process/src/process_manager.rs index 901671fa..8fc475ab 100644 --- a/src-tauri/src/process/process_manager.rs +++ b/src-tauri/drop-process/src/process_manager.rs @@ -10,30 +10,17 @@ use std::{ time::{Duration, SystemTime}, }; +use drop_database::{borrow_db_checked, borrow_db_mut_checked, db::DATA_ROOT_DIR, models::data::{ApplicationTransientStatus, Database, DownloadType, DownloadableMetadata, GameDownloadStatus, GameVersion}, process::Platform, DB}; +use drop_errors::process_error::ProcessError; +use drop_native_library::{library::push_game_update, state::GameStatusManager}; use dynfmt::Format; use dynfmt::SimpleCurlyFormat; use log::{debug, info, warn}; -use serde::{Deserialize, Serialize}; use shared_child::SharedChild; -use tauri::{AppHandle, Emitter, Manager}; +use tauri::{AppHandle, Emitter}; use tauri_plugin_opener::OpenerExt; -use crate::{ - AppState, DB, - 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}, - }, -}; +use crate::{format::DropFormatArgs, process_handlers::{AsahiMuvmLauncher, NativeGameLauncher, UMULauncher}}; pub struct RunningProcess { handle: Arc, @@ -194,7 +181,6 @@ impl ProcessManager<'_> { fn fetch_process_handler( &self, db_lock: &Database, - state: &AppState, target_platform: &Platform, ) -> Result<&(dyn ProcessHandler + Send + Sync), ProcessError> { Ok(self @@ -204,22 +190,22 @@ 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) -> Result { + pub fn valid_platform(&self, platform: &Platform,) -> Result { 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); Ok(process_handler.is_ok()) } pub fn launch_process( &mut self, game_id: String, - state: &AppState, + process_manager_lock: &'static Mutex>, ) -> Result<(), ProcessError> { if self.processes.contains_key(&game_id) { return Err(ProcessError::AlreadyRunning); @@ -304,7 +290,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 { @@ -385,22 +371,17 @@ 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 = app_state.lock().unwrap(); - - let mut process_manager_handle = app_state_handle.process_manager.lock().unwrap(); + let mut process_manager_handle = process_manager_lock.lock().unwrap(); 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( @@ -415,51 +396,6 @@ impl ProcessManager<'_> { } } -#[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, @@ -470,5 +406,5 @@ pub trait ProcessHandler: Send + 'static { current_dir: &str, ) -> String; - 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/src/process/utils.rs b/src-tauri/drop-process/src/utils.rs similarity index 84% rename from src-tauri/src/process/utils.rs rename to src-tauri/drop-process/src/utils.rs index 41f9239c..73957562 100644 --- a/src-tauri/src/process/utils.rs +++ b/src-tauri/drop-process/src/utils.rs @@ -1,10 +1,8 @@ -use std::{path::PathBuf, sync::Arc}; +use std::{io, path::PathBuf, sync::Arc}; -use futures_lite::io; +use drop_errors::application_download_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()); diff --git a/src-tauri/drop-remote/Cargo.toml b/src-tauri/drop-remote/Cargo.toml new file mode 100644 index 00000000..95cd5ab3 --- /dev/null +++ b/src-tauri/drop-remote/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "drop-remote" +version = "0.1.0" +edition = "2024" + +[dependencies] +bitcode = "0.6.7" +chrono = "0.4.42" +drop-consts = { path = "../drop-consts" } +drop-errors = { path = "../drop-errors" } +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" +serde = { version = "1.0.220", features = ["derive"] } +tauri = "2.8.5" +url = "2.5.7" diff --git a/src-tauri/drop-remote/src/auth.rs b/src-tauri/drop-remote/src/auth.rs new file mode 100644 index 00000000..9aedb27f --- /dev/null +++ b/src-tauri/drop-remote/src/auth.rs @@ -0,0 +1,156 @@ +use std::{collections::HashMap, env, sync::Mutex}; + +use chrono::Utc; +use drop_errors::{drop_server_error::ServerError, remote_access_error::RemoteAccessError}; +use droplet_rs::ssl::sign_nonce; +use gethostname::gethostname; +use log::{debug, error, warn}; +use serde::{Deserialize, Serialize}; +use url::Url; + +use crate::{ + requests::make_authenticated_get, utils::{DROP_CLIENT_ASYNC, DROP_CLIENT_SYNC}, DropRemoteAuth, DropRemoteContext +}; + +use super::requests::generate_url; + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +struct CapabilityConfiguration {} + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +struct InitiateRequestBody { + name: String, + platform: String, + capabilities: HashMap, + mode: String, +} + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +struct HandshakeRequestBody { + client_id: String, + token: String, +} + +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +struct HandshakeResponse { + private: String, + certificate: String, + id: String, +} + +pub fn generate_authorization_header(context: &DropRemoteContext) -> String { + let auth = if let Some(auth) = &context.auth { + auth + } else { + return "".to_owned(); + }; + let nonce = Utc::now().timestamp_millis().to_string(); + + let signature = sign_nonce(auth.private.clone(), nonce.clone()).unwrap(); + + format!("Nonce {} {} {}", auth.client_id, nonce, signature) +} + +pub async fn fetch_user(context: &DropRemoteContext) -> Result, RemoteAccessError> { + let response = + make_authenticated_get(context, generate_url(context, &["/api/v1/client/user"], &[])?).await?; + if response.status() != 200 { + let err: ServerError = response.json().await?; + warn!("{err:?}"); + + if err.status_message == "Nonce expired" { + return Err(RemoteAccessError::OutOfSync); + } + + return Err(RemoteAccessError::InvalidResponse(err)); + } + + response + .bytes() + .await + .map_err(std::convert::Into::into) + .map(|v| v.to_vec()) +} + +pub async fn recieve_handshake_logic( + context: &mut DropRemoteContext, + path: String, +) -> Result<(), RemoteAccessError> { + let path_chunks: Vec<&str> = path.split('/').collect(); + if path_chunks.len() != 3 { + // app.emit("auth/failed", ()).unwrap(); + return Err(RemoteAccessError::HandshakeFailed( + "failed to parse token".to_string(), + )); + } + + let client_id = path_chunks.get(1).unwrap(); + let token = path_chunks.get(2).unwrap(); + let body = HandshakeRequestBody { + client_id: (*client_id).to_string(), + token: (*token).to_string(), + }; + + let endpoint = generate_url(context, &["/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 web_token = { + let header = generate_authorization_header(context); + let token = client + .post(generate_url(context, &["/api/v1/client/user/webtoken"], &[])?) + .header("Authorization", header) + .send() + .await + .unwrap(); + + token.text().await.unwrap() + }; + + context.auth = Some(DropRemoteAuth { + private: response_struct.private, + cert: response_struct.certificate, + client_id: response_struct.id, + web_token: web_token, + }); + + Ok(()) +} + +pub fn auth_initiate_logic(context: &DropRemoteContext, mode: String) -> Result { + let hostname = gethostname(); + + let endpoint = generate_url(context, &["/api/v1/client/auth/initiate"], &[])?; + let body = InitiateRequestBody { + name: format!("{} (Desktop)", hostname.into_string().unwrap()), + platform: env::consts::OS.to_string(), + capabilities: HashMap::from([ + ("peerAPI".to_owned(), CapabilityConfiguration {}), + ("cloudSaves".to_owned(), CapabilityConfiguration {}), + ]), + mode, + }; + + let client = DROP_CLIENT_SYNC.clone(); + let response = client.post(endpoint.to_string()).json(&body).send()?; + + if response.status() != 200 { + let data: ServerError = response.json()?; + error!("could not start handshake: {}", data.status_message); + + return Err(RemoteAccessError::HandshakeFailed(data.status_message)); + } + + let response = response.text()?; + + Ok(response) +} diff --git a/src-tauri/src/remote/cache.rs b/src-tauri/drop-remote/src/cache.rs similarity index 81% rename from src-tauri/src/remote/cache.rs rename to src-tauri/drop-remote/src/cache.rs index d4afd145..7f39084c 100644 --- a/src-tauri/src/remote/cache.rs +++ b/src-tauri/drop-remote/src/cache.rs @@ -5,18 +5,18 @@ use std::{ time::SystemTime, }; -use crate::{ - database::{db::borrow_db_checked, models::data::Database}, - error::remote_access_error::RemoteAccessError, -}; use bitcode::{Decode, DecodeOwned, Encode}; +use drop_consts::CACHE_DIR; +use drop_errors::remote_access_error::RemoteAccessError; use http::{Response, header::CONTENT_TYPE, response::Builder as ResponseBuilder}; #[macro_export] macro_rules! offline { ($var:expr, $func1:expr, $func2:expr, $( $arg:expr ),* ) => { - async move { if $crate::borrow_db_checked().settings.force_offline || $var.lock().unwrap().status == $crate::AppStatus::Offline { + // TODO add offline mode back + // || $var.lock().unwrap().status == AppStatus::Offline + async move { if drop_database::borrow_db_checked().settings.force_offline { $func2( $( $arg ), *).await } else { $func1( $( $arg ), *).await @@ -57,36 +57,33 @@ fn delete_sync(base: &Path, key: &str) -> io::Result<()> { } pub fn cache_object(key: &str, data: &D) -> Result<(), RemoteAccessError> { - cache_object_db(key, data, &borrow_db_checked()) + cache_object_db(key, data) } pub fn cache_object_db( key: &str, data: &D, - database: &Database, ) -> Result<(), RemoteAccessError> { let bytes = bitcode::encode(data); - write_sync(&database.cache_dir, key, bytes).map_err(RemoteAccessError::Cache) + write_sync(&CACHE_DIR, key, bytes).map_err(RemoteAccessError::Cache) } pub fn get_cached_object(key: &str) -> Result { - get_cached_object_db::(key, &borrow_db_checked()) + get_cached_object_db::(key) } pub fn get_cached_object_db( key: &str, - db: &Database, ) -> Result { - let bytes = read_sync(&db.cache_dir, key).map_err(RemoteAccessError::Cache)?; + let bytes = read_sync(&CACHE_DIR, key).map_err(RemoteAccessError::Cache)?; let data = bitcode::decode::(&bytes).map_err(|e| RemoteAccessError::Cache(io::Error::other(e)))?; Ok(data) } pub fn clear_cached_object(key: &str) -> Result<(), RemoteAccessError> { - clear_cached_object_db(key, &borrow_db_checked()) + clear_cached_object_db(key) } pub fn clear_cached_object_db( key: &str, - db: &Database, ) -> Result<(), RemoteAccessError> { - delete_sync(&db.cache_dir, key).map_err(RemoteAccessError::Cache)?; + delete_sync(&CACHE_DIR, key).map_err(RemoteAccessError::Cache)?; Ok(()) } diff --git a/src-tauri/src/remote/fetch_object.rs b/src-tauri/drop-remote/src/fetch_object.rs similarity index 77% rename from src-tauri/src/remote/fetch_object.rs rename to src-tauri/drop-remote/src/fetch_object.rs index 4b5d7fbd..b3b1ca45 100644 --- a/src-tauri/src/remote/fetch_object.rs +++ b/src-tauri/drop-remote/src/fetch_object.rs @@ -1,15 +1,16 @@ -use http::{header::CONTENT_TYPE, response::Builder as ResponseBuilder}; +use http::{header::CONTENT_TYPE, response::Builder as ResponseBuilder, Request}; use log::warn; use tauri::UriSchemeResponder; -use crate::{database::db::DatabaseImpls, remote::utils::DROP_CLIENT_ASYNC, DB}; + +use crate::{requests::generate_url, utils::DROP_CLIENT_ASYNC, DropRemoteContext}; use super::{ auth::generate_authorization_header, cache::{ObjectCache, cache_object, get_cached_object}, }; -pub async fn fetch_object(request: http::Request>, responder: UriSchemeResponder) { +pub async fn fetch_object(context: &DropRemoteContext, request: Request>, responder: UriSchemeResponder) { // Drop leading / let object_id = &request.uri().path()[1..]; @@ -21,9 +22,9 @@ pub async fn fetch_object(request: http::Request>, responder: UriSchemeR return; } - let header = generate_authorization_header(); + let header = generate_authorization_header(context); let client = DROP_CLIENT_ASYNC.clone(); - let url = format!("{}api/v1/client/object/{object_id}", DB.fetch_base_url()); + let url = generate_url(context, &["/api/v1/client/object", object_id], &[]).expect("failed to generated object url"); let response = client.get(url).header("Authorization", header).send().await; if response.is_err() { diff --git a/src-tauri/drop-remote/src/lib.rs b/src-tauri/drop-remote/src/lib.rs new file mode 100644 index 00000000..33df2d74 --- /dev/null +++ b/src-tauri/drop-remote/src/lib.rs @@ -0,0 +1,29 @@ +use serde::{Deserialize, Serialize}; +use url::Url; + +pub mod auth; +pub mod cache; +pub mod fetch_object; +pub mod requests; +pub mod utils; + +#[derive(Serialize, Deserialize, Clone)] +struct DropRemoteAuth { + private: String, + cert: String, + client_id: String, + web_token: String, +} + +#[derive(Serialize, Deserialize, Clone)] +pub struct DropRemoteContext { + base_url: Url, + auth: Option, +} + + +impl DropRemoteContext { + pub fn new(base_url: Url) -> Self { + DropRemoteContext { base_url, auth: None } + } +} \ No newline at end of file diff --git a/src-tauri/src/remote/requests.rs b/src-tauri/drop-remote/src/requests.rs similarity index 54% rename from src-tauri/src/remote/requests.rs rename to src-tauri/drop-remote/src/requests.rs index 7ebf7b15..fb4f2dea 100644 --- a/src-tauri/src/remote/requests.rs +++ b/src-tauri/drop-remote/src/requests.rs @@ -1,17 +1,14 @@ +use drop_errors::remote_access_error::RemoteAccessError; use url::Url; -use crate::{ - DB, - database::db::DatabaseImpls, - error::remote_access_error::RemoteAccessError, - remote::{auth::generate_authorization_header, utils::DROP_CLIENT_ASYNC}, -}; +use crate::{auth::generate_authorization_header, utils::DROP_CLIENT_ASYNC, DropRemoteContext}; pub fn generate_url>( + context: &DropRemoteContext, path_components: &[T], query: &[(T, T)], ) -> Result { - let mut base_url = DB.fetch_base_url(); + let mut base_url = context.base_url.clone(); for endpoint in path_components { base_url = base_url.join(endpoint.as_ref())?; } @@ -24,10 +21,10 @@ pub fn generate_url>( Ok(base_url) } -pub async fn make_authenticated_get(url: Url) -> Result { +pub async fn make_authenticated_get(context: &DropRemoteContext, url: Url) -> Result { DROP_CLIENT_ASYNC .get(url) - .header("Authorization", generate_authorization_header()) + .header("Authorization", generate_authorization_header(context)) .send() .await } diff --git a/src-tauri/src/remote/utils.rs b/src-tauri/drop-remote/src/utils.rs similarity index 63% rename from src-tauri/src/remote/utils.rs rename to src-tauri/drop-remote/src/utils.rs index 87de927c..ff0896f5 100644 --- a/src-tauri/src/remote/utils.rs +++ b/src-tauri/drop-remote/src/utils.rs @@ -1,26 +1,12 @@ use std::{ fs::{self, File}, io::Read, - sync::{LazyLock, Mutex}, - time::Duration, + sync::LazyLock, }; -use log::{debug, info, warn}; +use drop_consts::DATA_ROOT_DIR; +use log::{debug, info}; use reqwest::Certificate; -use serde::Deserialize; -use url::Url; - -use crate::{ - AppState, AppStatus, - database::db::{DATA_ROOT_DIR, borrow_db_mut_checked}, - error::remote_access_error::RemoteAccessError, -}; - -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -struct DropHealthcheck { - app_name: String, -} static DROP_CERT_BUNDLE: LazyLock> = LazyLock::new(fetch_certificates); pub static DROP_CLIENT_SYNC: LazyLock = LazyLock::new(get_client_sync); @@ -82,37 +68,4 @@ pub fn get_client_ws() -> reqwest::Client { client = client.add_root_certificate(cert.clone()); } client.use_rustls_tls().http1_only().build().unwrap() -} - -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 = state.lock().unwrap(); - 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(()) -} +} \ No newline at end of file diff --git a/src-tauri/src/auth.rs b/src-tauri/src/auth.rs new file mode 100644 index 00000000..c31e7e45 --- /dev/null +++ b/src-tauri/src/auth.rs @@ -0,0 +1,59 @@ +use std::sync::Mutex; + +use drop_database::{borrow_db_checked, runtime_models::User}; +use drop_errors::remote_access_error::RemoteAccessError; +use drop_remote::{auth::{fetch_user, recieve_handshake_logic}, cache::{cache_object, clear_cached_object, get_cached_object}}; +use log::warn; +use tauri::{AppHandle, Emitter as _, Manager as _}; + +use crate::{AppState, AppStatus}; + +pub async fn setup() -> (AppStatus, Option) { + let auth = { + let data = borrow_db_checked(); + data.auth.clone() + }; + + if auth.is_some() { + let user_result = match fetch_user().await { + Ok(data) => data, + Err(RemoteAccessError::FetchError(_)) => { + let user = get_cached_object::("user").unwrap(); + return (AppStatus::Offline, Some(user)); + } + Err(_) => return (AppStatus::SignedInNeedsReauth, None), + }; + cache_object("user", &user_result).unwrap(); + return (AppStatus::SignedIn, Some(user_result)); + } + + (AppStatus::SignedOut, None) +} + +pub async fn recieve_handshake(app: AppHandle, path: String) { + // Tell the app we're processing + app.emit("auth/processing", ()).unwrap(); + + let handshake_result = recieve_handshake_logic(path).await; + if let Err(e) = handshake_result { + warn!("error with authentication: {e}"); + app.emit("auth/failed", e.to_string()).unwrap(); + return; + } + + let app_state = app.state::>(); + + let (app_status, user) = setup().await; + + let mut state_lock = app_state.lock().unwrap(); + + state_lock.status = app_status; + state_lock.user = user; + + let _ = clear_cached_object("collections"); + let _ = clear_cached_object("library"); + + drop(state_lock); + + app.emit("auth/finished", ()).unwrap(); +} diff --git a/src-tauri/src/client/autostart.rs b/src-tauri/src/client/autostart.rs index a35f4808..47f68d7f 100644 --- a/src-tauri/src/client/autostart.rs +++ b/src-tauri/src/client/autostart.rs @@ -1,4 +1,4 @@ -use crate::database::db::{borrow_db_checked, borrow_db_mut_checked}; +use drop_database::{borrow_db_checked, borrow_db_mut_checked}; use log::debug; use tauri::AppHandle; use tauri_plugin_autostart::ManagerExt; diff --git a/src-tauri/src/client/cleanup.rs b/src-tauri/src/client/cleanup.rs index c6f0e807..2485ab93 100644 --- a/src-tauri/src/client/cleanup.rs +++ b/src-tauri/src/client/cleanup.rs @@ -4,11 +4,11 @@ use tauri::AppHandle; use crate::AppState; #[tauri::command] -pub fn quit(app: tauri::AppHandle, state: tauri::State<'_, std::sync::Mutex>>) { +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>>) { +pub fn cleanup_and_exit(app: &AppHandle, state: &tauri::State<'_, std::sync::Mutex>) { debug!("cleaning up and exiting application"); let download_manager = state.lock().unwrap().download_manager.clone(); match download_manager.ensure_terminated() { diff --git a/src-tauri/src/client/commands.rs b/src-tauri/src/client/commands.rs index b47a348f..3f50c6e0 100644 --- a/src-tauri/src/client/commands.rs +++ b/src-tauri/src/client/commands.rs @@ -2,7 +2,7 @@ use crate::AppState; #[tauri::command] pub fn fetch_state( - state: tauri::State<'_, std::sync::Mutex>>, + state: tauri::State<'_, std::sync::Mutex>, ) -> Result { let guard = state.lock().unwrap(); let cloned_state = serde_json::to_string(&guard.clone()).map_err(|e| e.to_string())?; diff --git a/src-tauri/src/database/commands.rs b/src-tauri/src/database/commands.rs index c4de82bd..11c1a729 100644 --- a/src-tauri/src/database/commands.rs +++ b/src-tauri/src/database/commands.rs @@ -4,17 +4,12 @@ use std::{ path::{Path, PathBuf}, }; +use drop_database::{borrow_db_checked, borrow_db_mut_checked, db::DATA_ROOT_DIR, debug::SystemData, models::data::Settings}; +use drop_errors::download_manager_error::DownloadManagerError; use serde_json::Value; -use crate::{ - database::{db::borrow_db_mut_checked, scan::scan_install_dirs}, error::download_manager_error::DownloadManagerError, -}; +use crate::database::scan::scan_install_dirs; -use super::{ - db::{borrow_db_checked, DATA_ROOT_DIR}, - debug::SystemData, - models::data::Settings, -}; // Will, in future, return disk/remaining size // Just returns the directories that have been set up diff --git a/src-tauri/src/database/mod.rs b/src-tauri/src/database/mod.rs index 6c77e255..084d3a2d 100644 --- a/src-tauri/src/database/mod.rs +++ b/src-tauri/src/database/mod.rs @@ -1,5 +1,2 @@ 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/database/scan.rs b/src-tauri/src/database/scan.rs index 9e447cf3..e2eadbab 100644 --- a/src-tauri/src/database/scan.rs +++ b/src-tauri/src/database/scan.rs @@ -1,18 +1,9 @@ use std::fs; +use drop_database::{borrow_db_mut_checked, drop_data::{DropData, DROP_DATA_PATH}, models::data::{DownloadType, DownloadableMetadata}}; +use drop_native_library::library::set_partially_installed_db; 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, - }, -}; - pub fn scan_install_dirs() { let mut db_lock = borrow_db_mut_checked(); for install_dir in db_lock.applications.install_dirs.clone() { diff --git a/src-tauri/src/download_manager/commands.rs b/src-tauri/src/download_manager/commands.rs index e336c23d..00d93e7c 100644 --- a/src-tauri/src/download_manager/commands.rs +++ b/src-tauri/src/download_manager/commands.rs @@ -1,6 +1,8 @@ use std::sync::Mutex; -use crate::{database::models::data::DownloadableMetadata, AppState}; +use drop_database::models::data::DownloadableMetadata; + +use crate::AppState; #[tauri::command] pub fn pause_downloads(state: tauri::State<'_, Mutex>) { diff --git a/src-tauri/src/download_manager/mod.rs b/src-tauri/src/download_manager/mod.rs index 756a1add..82b6da3c 100644 --- a/src-tauri/src/download_manager/mod.rs +++ b/src-tauri/src/download_manager/mod.rs @@ -1,5 +1 @@ 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/collections/mod.rs b/src-tauri/src/games/collections/mod.rs deleted file mode 100644 index b837592f..00000000 --- a/src-tauri/src/games/collections/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod collection; -pub mod commands; diff --git a/src-tauri/src/games/commands.rs b/src-tauri/src/games/commands.rs deleted file mode 100644 index e36d9343..00000000 --- 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/mod.rs b/src-tauri/src/games/mod.rs deleted file mode 100644 index 0d81d107..00000000 --- a/src-tauri/src/games/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod collections; -pub mod commands; -pub mod downloads; -pub mod library; -pub mod state; diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 90caf5c7..753c8301 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -5,77 +5,59 @@ #![feature(iterator_try_collect)] #![deny(clippy::all)] -mod database; -mod games; - +mod auth; mod client; +mod database; mod download_manager; -mod error; +mod native_library; mod process; mod remote; +mod setup; -use crate::database::scan::scan_install_dirs; -use crate::process::commands::open_process_logs; -use crate::process::process_handlers::UMU_LAUNCHER_EXECUTABLE; +use crate::auth::recieve_handshake; +use crate::native_library::collection_commands::{add_game_to_collection, create_collection, delete_collection, delete_game_in_collection, fetch_collection, fetch_collections}; +use crate::native_library::commands::{ + fetch_game, fetch_game_status, fetch_game_version_options, fetch_library, uninstall_game, +}; +use crate::native_library::downloads::commands::{download_game, resume_download}; +use crate::process::commands::{open_process_logs, update_game_configuration}; use crate::remote::commands::auth_initiate_code; -use crate::{database::db::DatabaseImpls, games::downloads::commands::resume_download}; -use bitcode::{Decode, Encode}; +use crate::remote::server_proto::{handle_server_proto, handle_server_proto_offline}; use client::commands::fetch_state; use client::{ - autostart::{get_autostart_enabled, sync_autostart_on_startup, toggle_autostart}, + autostart::{get_autostart_enabled, 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 drop_database::borrow_db_mut_checked; +use drop_database::db::DATA_ROOT_DIR; +use drop_database::runtime_models::User; +use drop_downloads::download_manager_frontend::DownloadManager; +use drop_process::process_manager::ProcessManager; +use drop_remote::{fetch_object::fetch_object, offline}; +use log::{debug, info, warn}; 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::fetch_object::fetch_object; -use remote::server_proto::{handle_server_proto, handle_server_proto_offline}; -use serde::{Deserialize, Serialize}; +use serde::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::sync::Mutex; use std::time::SystemTime; -use std::{ - collections::HashMap, - sync::{LazyLock, Mutex}, -}; use std::{env, panic}; use tauri::menu::{Menu, MenuItem, PredefinedMenuItem}; use tauri::tray::TrayIconBuilder; -use tauri::{AppHandle, Manager, RunEvent, WindowEvent}; +use tauri::{Manager, RunEvent, WindowEvent}; use tauri_plugin_deep_link::DeepLinkExt; use tauri_plugin_dialog::DialogExt; @@ -90,165 +72,18 @@ pub enum AppStatus { ServerUnavailable, } -#[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, -} - -#[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, - }) -} - #[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> { - let logfile = FileAppender::builder() - .encoder(Box::new(PatternEncoder::new( - "{d} | {l} | {f}:{L} - {m}{n}", - ))) - .append(false) - .build(DATA_ROOT_DIR.join("./drop.log")) - .unwrap(); - - let console = ConsoleAppender::builder() - .encoder(Box::new(PatternEncoder::new( - "{d} | {l} | {f}:{L} - {m}{n}", - ))) - .build(); - - let log_level = env::var("RUST_LOG").unwrap_or(String::from("Info")); - - let config = Config::builder() - .appenders(vec![ - Appender::builder().build("logfile", Box::new(logfile)), - Appender::builder().build("console", Box::new(console)), - ]) - .build( - Root::builder() - .appenders(vec!["logfile", "console"]) - .build(LevelFilter::from_str(&log_level).expect("Invalid log level")), - ) - .unwrap(); - - log4rs::init_config(config).unwrap(); - - 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(); - - debug!("checking if database is set up"); - let is_set_up = DB.database_is_set_up(); - - scan_install_dirs(); - - if !is_set_up { - return AppState { - status: AppStatus::NotConfigured, - user: None, - games, - download_manager, - process_manager, - compat_info, - }; - } - - debug!("database is set up"); - - // TODO: Account for possible failure - let (app_status, user) = auth::setup().await; - - let db_handle = borrow_db_checked(); - let mut missing_games = Vec::new(); - let statuses = db_handle.applications.game_statuses.clone(); - drop(db_handle); - - for (game_id, status) in statuses { - match status { - GameDownloadStatus::Remote {} => {} - GameDownloadStatus::PartiallyInstalled { .. } => {} - GameDownloadStatus::SetupRequired { - version_name: _, - install_dir, - } => { - let install_dir_path = Path::new(&install_dir); - if !install_dir_path.exists() { - missing_games.push(game_id); - } - } - GameDownloadStatus::Installed { - version_name: _, - install_dir, - } => { - let install_dir_path = Path::new(&install_dir); - if !install_dir_path.exists() { - missing_games.push(game_id); - } - } - } - } - - info!("detected games missing: {missing_games:?}"); - - let mut db_handle = borrow_db_mut_checked(); - for game_id in missing_games { - db_handle - .applications - .game_statuses - .entry(game_id) - .and_modify(|v| *v = GameDownloadStatus::Remote {}); - } - - drop(db_handle); - - debug!("finished setup!"); - - // Sync autostart state - if let Err(e) = sync_autostart_on_startup(&handle) { - warn!("failed to sync autostart state: {e}"); - } - - AppState { - status: app_status, - user, - games, - download_manager, - process_manager, - compat_info, - } + process_manager: &'static Mutex>, } -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", @@ -346,7 +181,7 @@ pub fn run() { let handle = app.handle().clone(); tauri::async_runtime::block_on(async move { - let state = setup(handle).await; + let state = setup::setup(handle).await; info!("initialized drop client"); app.manage(Mutex::new(state)); diff --git a/src-tauri/src/games/collections/commands.rs b/src-tauri/src/native_library/collection_commands.rs similarity index 89% rename from src-tauri/src/games/collections/commands.rs rename to src-tauri/src/native_library/collection_commands.rs index 0db6a493..69415348 100644 --- a/src-tauri/src/games/collections/commands.rs +++ b/src-tauri/src/native_library/collection_commands.rs @@ -1,16 +1,9 @@ -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 drop_errors::remote_access_error::RemoteAccessError; +use drop_native_library::collections::{Collection, Collections}; +use drop_remote::{ + auth::generate_authorization_header, cache::{cache_object, get_cached_object}, 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/native_library/commands.rs b/src-tauri/src/native_library/commands.rs new file mode 100644 index 00000000..abac57ad --- /dev/null +++ b/src-tauri/src/native_library/commands.rs @@ -0,0 +1,76 @@ +use std::sync::Mutex; + +use drop_database::{borrow_db_checked, models::data::GameVersion, runtime_models::Game}; +use drop_errors::{library_error::LibraryError, remote_access_error::RemoteAccessError}; +use drop_native_library::{library::{fetch_game_logic, fetch_game_logic_offline, fetch_game_version_options_logic, fetch_library_logic, fetch_library_logic_offline, get_current_meta, uninstall_game_logic, FetchGameStruct}, state::{GameStatusManager, GameStatusWithTransient}}; +use tauri::AppHandle; + +use crate::{AppState, offline}; + +#[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, + 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 + ) + .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> { + let all_versions = fetch_game_version_options_logic(game_id).await?; + + let state_lock = state.lock().unwrap(); + let process_manager_lock = state_lock.process_manager.lock().unwrap(); + let data: Vec = all_versions + .into_iter() + .filter(|v| { + process_manager_lock + .valid_platform(&v.platform) + .unwrap() + }) + .collect(); + drop(process_manager_lock); + drop(state_lock); + + Ok(data) +} diff --git a/src-tauri/src/games/downloads/commands.rs b/src-tauri/src/native_library/downloads/commands.rs similarity index 85% rename from src-tauri/src/games/downloads/commands.rs rename to src-tauri/src/native_library/downloads/commands.rs index 83aee8ed..ab5b0dbe 100644 --- a/src-tauri/src/games/downloads/commands.rs +++ b/src-tauri/src/native_library/downloads/commands.rs @@ -3,16 +3,11 @@ use std::{ sync::{Arc, Mutex}, }; +use drop_database::{borrow_db_checked, models::data::GameDownloadStatus}; +use drop_downloads::downloadable::Downloadable; +use drop_errors::application_download_error::ApplicationDownloadError; -use crate::{ - AppState, - database::{ - db::borrow_db_checked, - models::data::GameDownloadStatus, - }, - download_manager::downloadable::Downloadable, - error::application_download_error::ApplicationDownloadError, -}; +use crate::AppState; use super::download_agent::GameDownloadAgent; @@ -21,7 +16,7 @@ pub async fn download_game( game_id: String, game_version: String, install_dir: usize, - state: tauri::State<'_, Mutex>>, + state: tauri::State<'_, Mutex>, ) -> Result<(), ApplicationDownloadError> { let sender = { state.lock().unwrap().download_manager.get_sender().clone() }; @@ -43,7 +38,7 @@ pub async fn download_game( #[tauri::command] pub async fn resume_download( game_id: String, - state: tauri::State<'_, Mutex>>, + state: tauri::State<'_, Mutex>, ) -> Result<(), ApplicationDownloadError> { let s = borrow_db_checked() .applications diff --git a/src-tauri/src/games/downloads/download_agent.rs b/src-tauri/src/native_library/downloads/download_agent.rs similarity index 94% rename from src-tauri/src/games/downloads/download_agent.rs rename to src-tauri/src/native_library/downloads/download_agent.rs index e832f3cf..bea94591 100644 --- a/src-tauri/src/games/downloads/download_agent.rs +++ b/src-tauri/src/native_library/downloads/download_agent.rs @@ -1,25 +1,18 @@ -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 crate::download_manager::download_manager_frontend::{DownloadManagerSignal, DownloadStatus}; -use crate::download_manager::downloadable::Downloadable; -use crate::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 drop_database::{borrow_db_checked, borrow_db_mut_checked}; +use drop_database::drop_data::DropData; +use drop_database::models::data::{ApplicationTransientStatus, DownloadType, DownloadableMetadata}; +use drop_downloads::download_manager_frontend::{DownloadManagerSignal, DownloadStatus}; +use drop_downloads::downloadable::Downloadable; +use drop_downloads::util::download_thread_control_flag::{DownloadThreadControl, DownloadThreadControlFlag}; +use drop_downloads::util::progress_object::{ProgressHandle, ProgressObject}; +use drop_errors::application_download_error::ApplicationDownloadError; +use drop_errors::remote_access_error::RemoteAccessError; +use drop_native_library::library::{on_game_complete, push_game_update, set_partially_installed}; +use drop_native_library::state::GameStatusManager; +use drop_process::utils::get_disk_available; +use drop_remote::auth::generate_authorization_header; +use drop_remote::requests::generate_url; +use drop_remote::utils::{DROP_CLIENT_ASYNC, DROP_CLIENT_SYNC}; use log::{debug, error, info, warn}; use rayon::ThreadPoolBuilder; use std::collections::{HashMap, HashSet}; @@ -33,8 +26,10 @@ use tauri::{AppHandle, Emitter}; #[cfg(target_os = "linux")] use rustix::fs::{FallocateFlags, fallocate}; +use crate::native_library::downloads::manifest::{DownloadBucket, DownloadContext, DownloadDrop, DropManifest, DropValidateContext, ManifestBody}; +use crate::native_library::downloads::validate::validate_game_chunk; + use super::download_logic::download_game_bucket; -use super::drop_data::DropData; static RETRY_COUNT: usize = 3; diff --git a/src-tauri/src/games/downloads/download_logic.rs b/src-tauri/src/native_library/downloads/download_logic.rs similarity index 92% rename from src-tauri/src/games/downloads/download_logic.rs rename to src-tauri/src/native_library/downloads/download_logic.rs index cd45919a..ad76bed1 100644 --- a/src-tauri/src/games/downloads/download_logic.rs +++ b/src-tauri/src/native_library/downloads/download_logic.rs @@ -1,14 +1,11 @@ -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 drop_downloads::util::download_thread_control_flag::{DownloadThreadControl, DownloadThreadControlFlag}; +use drop_downloads::util::progress_object::ProgressHandle; +use drop_errors::application_download_error::ApplicationDownloadError; +use drop_errors::drop_server_error::ServerError; +use drop_errors::remote_access_error::RemoteAccessError; +use drop_remote::auth::generate_authorization_header; +use drop_remote::requests::generate_url; +use drop_remote::utils::DROP_CLIENT_SYNC; use log::{debug, info, warn}; use md5::{Context, Digest}; use reqwest::blocking::Response; @@ -25,6 +22,8 @@ use std::{ path::PathBuf, }; +use crate::native_library::downloads::manifest::{ChunkBody, DownloadBucket, DownloadContext, DownloadDrop}; + static MAX_PACKET_LENGTH: usize = 4096 * 4; static BUMP_SIZE: usize = 4096 * 16; @@ -198,7 +197,7 @@ pub fn download_game_bucket( ApplicationDownloadError::Communication(RemoteAccessError::FetchError(e.into())) })?; info!("{raw_res}"); - if let Ok(err) = serde_json::from_str::(&raw_res) { + if let Ok(err) = serde_json::from_str::(&raw_res) { return Err(ApplicationDownloadError::Communication( RemoteAccessError::InvalidResponse(err), )); diff --git a/src-tauri/src/games/downloads/manifest.rs b/src-tauri/src/native_library/downloads/manifest.rs similarity index 100% rename from src-tauri/src/games/downloads/manifest.rs rename to src-tauri/src/native_library/downloads/manifest.rs diff --git a/src-tauri/src/games/downloads/mod.rs b/src-tauri/src/native_library/downloads/mod.rs similarity index 83% rename from src-tauri/src/games/downloads/mod.rs rename to src-tauri/src/native_library/downloads/mod.rs index dc9e277c..c4326bb0 100644 --- a/src-tauri/src/games/downloads/mod.rs +++ b/src-tauri/src/native_library/downloads/mod.rs @@ -1,6 +1,5 @@ pub mod commands; pub mod download_agent; mod download_logic; -pub mod drop_data; mod manifest; pub mod validate; diff --git a/src-tauri/src/games/downloads/validate.rs b/src-tauri/src/native_library/downloads/validate.rs similarity index 88% rename from src-tauri/src/games/downloads/validate.rs rename to src-tauri/src/native_library/downloads/validate.rs index 1d11cb8b..91a81822 100644 --- a/src-tauri/src/games/downloads/validate.rs +++ b/src-tauri/src/native_library/downloads/validate.rs @@ -3,17 +3,12 @@ use std::{ io::{self, BufWriter, Read, Seek, SeekFrom, Write}, }; +use drop_downloads::util::{download_thread_control_flag::{DownloadThreadControl, DownloadThreadControlFlag}, progress_object::ProgressHandle}; +use drop_errors::application_download_error::ApplicationDownloadError; use log::debug; use md5::Context; -use crate::{ - download_manager::util::{ - download_thread_control_flag::{DownloadThreadControl, DownloadThreadControlFlag}, - progress_object::ProgressHandle, - }, - error::application_download_error::ApplicationDownloadError, - games::downloads::manifest::DropValidateContext, -}; +use crate::native_library::downloads::manifest::DropValidateContext; pub fn validate_game_chunk( ctx: &DropValidateContext, diff --git a/src-tauri/src/native_library/mod.rs b/src-tauri/src/native_library/mod.rs new file mode 100644 index 00000000..7df4c060 --- /dev/null +++ b/src-tauri/src/native_library/mod.rs @@ -0,0 +1,3 @@ +pub mod collection_commands; +pub mod commands; +pub mod downloads; diff --git a/src-tauri/src/process/commands.rs b/src-tauri/src/process/commands.rs index 13b89faa..d3a96c3a 100644 --- a/src-tauri/src/process/commands.rs +++ b/src-tauri/src/process/commands.rs @@ -1,6 +1,10 @@ use std::sync::Mutex; -use crate::{error::process_error::ProcessError, AppState}; +use drop_database::borrow_db_mut_checked; +use drop_errors::{library_error::LibraryError, process_error::ProcessError}; +use serde::Deserialize; + +use crate::AppState; #[tauri::command] pub fn launch_game( @@ -16,7 +20,7 @@ pub fn launch_game( // download_type: DownloadType::Game, //}; - match process_manager_lock.launch_process(id, &state_lock) { + match process_manager_lock.launch_process(id, state_lock.process_manager) { Ok(()) => {} Err(e) => return Err(e), } @@ -48,3 +52,48 @@ pub fn open_process_logs( let mut process_manager_lock = state_lock.process_manager.lock().unwrap(); process_manager_lock.open_process_logs(game_id) } + +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct FrontendGameOptions { + pub 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().unwrap(); + + 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/process/mod.rs b/src-tauri/src/process/mod.rs index fa1089ed..6be336ee 100644 --- a/src-tauri/src/process/mod.rs +++ b/src-tauri/src/process/mod.rs @@ -1,5 +1 @@ -pub mod commands; -pub mod process_manager; -pub mod process_handlers; -pub mod format; -pub mod utils; \ No newline at end of file +pub mod commands; \ No newline at end of file diff --git a/src-tauri/src/remote/auth.rs b/src-tauri/src/remote/auth.rs deleted file mode 100644 index 88b77718..00000000 --- a/src-tauri/src/remote/auth.rs +++ /dev/null @@ -1,224 +0,0 @@ -use std::{collections::HashMap, env, sync::Mutex}; - -use chrono::Utc; -use droplet_rs::ssl::sign_nonce; -use gethostname::gethostname; -use log::{debug, error, warn}; -use serde::{Deserialize, Serialize}; -use tauri::{AppHandle, Emitter, Manager}; -use url::Url; - -use crate::{ - database::{ - db::{borrow_db_checked, borrow_db_mut_checked}, - models::data::DatabaseAuth, - }, error::{drop_server_error::DropServerError, remote_access_error::RemoteAccessError}, remote::{cache::clear_cached_object, requests::make_authenticated_get, utils::{DROP_CLIENT_ASYNC, DROP_CLIENT_SYNC}}, AppState, AppStatus, User -}; - -use super::{ - cache::{cache_object, get_cached_object}, - requests::generate_url, -}; - -#[derive(Serialize)] -#[serde(rename_all = "camelCase")] -struct CapabilityConfiguration {} - -#[derive(Serialize)] -#[serde(rename_all = "camelCase")] -struct InitiateRequestBody { - name: String, - platform: String, - capabilities: HashMap, - mode: String, -} - -#[derive(Serialize)] -#[serde(rename_all = "camelCase")] -struct HandshakeRequestBody { - client_id: String, - token: String, -} - -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -struct HandshakeResponse { - private: String, - certificate: String, - id: String, -} - -pub fn generate_authorization_header() -> String { - let certs = { - let db = borrow_db_checked(); - db.auth.clone().unwrap() - }; - - let nonce = Utc::now().timestamp_millis().to_string(); - - let signature = sign_nonce(certs.private, nonce.clone()).unwrap(); - - format!("Nonce {} {} {}", certs.client_id, nonce, signature) -} - -pub async fn fetch_user() -> Result { - let response = make_authenticated_get(generate_url(&["/api/v1/client/user"], &[])?).await?; - if response.status() != 200 { - let err: DropServerError = response.json().await?; - warn!("{err:?}"); - - if err.status_message == "Nonce expired" { - return Err(RemoteAccessError::OutOfSync); - } - - return Err(RemoteAccessError::InvalidResponse(err)); - } - - response - .json::() - .await - .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("auth/failed", ()).unwrap(); - 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).unwrap(); - let token = path_chunks.get(2).unwrap(); - 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, // gets created later - }); - } - - let web_token = { - let header = generate_authorization_header(); - let token = client - .post(base_url.join("/api/v1/client/user/webtoken").unwrap()) - .header("Authorization", header) - .send() - .await - .unwrap(); - - token.text().await.unwrap() - }; - - let mut handle = borrow_db_mut_checked(); - let mut_auth = handle.auth.as_mut().unwrap(); - mut_auth.web_token = Some(web_token); - - Ok(()) -} - -pub async fn recieve_handshake(app: AppHandle, path: String) { - // Tell the app we're processing - app.emit("auth/processing", ()).unwrap(); - - let handshake_result = recieve_handshake_logic(&app, path).await; - if let Err(e) = handshake_result { - warn!("error with authentication: {e}"); - app.emit("auth/failed", e.to_string()).unwrap(); - return; - } - - let app_state = app.state::>(); - - let (app_status, user) = setup().await; - - let mut state_lock = app_state.lock().unwrap(); - - state_lock.status = app_status; - state_lock.user = user; - - let _ = clear_cached_object("collections"); - let _ = clear_cached_object("library"); - - drop(state_lock); - - app.emit("auth/finished", ()).unwrap(); -} - -pub fn auth_initiate_logic(mode: String) -> Result { - let base_url = { - let db_lock = borrow_db_checked(); - Url::parse(&db_lock.base_url.clone())? - }; - - let hostname = gethostname(); - - let endpoint = base_url.join("/api/v1/client/auth/initiate")?; - let body = InitiateRequestBody { - name: format!("{} (Desktop)", hostname.into_string().unwrap()), - platform: env::consts::OS.to_string(), - capabilities: HashMap::from([ - ("peerAPI".to_owned(), CapabilityConfiguration {}), - ("cloudSaves".to_owned(), CapabilityConfiguration {}), - ]), - mode, - }; - - let client = DROP_CLIENT_SYNC.clone(); - let response = client.post(endpoint.to_string()).json(&body).send()?; - - if response.status() != 200 { - let data: DropServerError = response.json()?; - error!("could not start handshake: {}", data.status_message); - - return Err(RemoteAccessError::HandshakeFailed(data.status_message)); - } - - let response = response.text()?; - - Ok(response) -} - -pub async fn setup() -> (AppStatus, Option) { - let auth = { - let data = borrow_db_checked(); - data.auth.clone() - }; - - if auth.is_some() { - let user_result = match fetch_user().await { - Ok(data) => data, - Err(RemoteAccessError::FetchError(_)) => { - let user = get_cached_object::("user").unwrap(); - return (AppStatus::Offline, Some(user)); - } - Err(_) => return (AppStatus::SignedInNeedsReauth, None), - }; - cache_object("user", &user_result).unwrap(); - return (AppStatus::SignedIn, Some(user_result)); - } - - (AppStatus::SignedOut, None) -} diff --git a/src-tauri/src/remote/commands.rs b/src-tauri/src/remote/commands.rs index 3f204939..c58a3eac 100644 --- a/src-tauri/src/remote/commands.rs +++ b/src-tauri/src/remote/commands.rs @@ -1,5 +1,8 @@ -use std::sync::Mutex; +use std::{sync::Mutex, time::Duration}; +use drop_database::{borrow_db_checked, borrow_db_mut_checked}; +use drop_errors::remote_access_error::RemoteAccessError; +use drop_remote::{auth::{auth_initiate_logic, generate_authorization_header}, cache::{cache_object, get_cached_object}, requests::generate_url, utils::{DROP_CLIENT_ASYNC, DROP_CLIENT_SYNC, DROP_CLIENT_WS_CLIENT}}; use futures_lite::StreamExt; use log::{debug, warn}; use reqwest_websocket::{Message, RequestBuilderExt}; @@ -7,27 +10,12 @@ use serde::Deserialize; use tauri::{AppHandle, Emitter, Manager}; use url::Url; -use crate::{ - AppState, AppStatus, - database::db::{borrow_db_checked, borrow_db_mut_checked}, - error::remote_access_error::RemoteAccessError, - remote::{ - auth::generate_authorization_header, - requests::generate_url, - utils::{DROP_CLIENT_SYNC, DROP_CLIENT_WS_CLIENT}, - }, -}; - -use super::{ - auth::{auth_initiate_logic, recieve_handshake, setup}, - cache::{cache_object, get_cached_object}, - utils::use_remote_logic, -}; +use crate::{auth::{recieve_handshake, setup}, AppState, AppStatus}; #[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 } @@ -87,7 +75,7 @@ pub fn sign_out(app: AppHandle) { } #[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 = state.lock().unwrap(); @@ -151,7 +139,9 @@ pub fn auth_initiate_code(app: AppHandle) -> Result { match response.response_type.as_str() { "token" => { let recieve_app = app.clone(); - manual_recieve_handshake(recieve_app, response.value).await.unwrap(); + manual_recieve_handshake(recieve_app, response.value) + .await + .unwrap(); return Ok(()); } _ => return Err(RemoteAccessError::HandshakeFailed(response.value)), @@ -180,3 +170,42 @@ pub async fn manual_recieve_handshake(app: AppHandle, token: String) -> Result<( Ok(()) } + +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +struct DropHealthcheck { + app_name: String, +} + +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 = state.lock().unwrap(); + 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/remote/mod.rs b/src-tauri/src/remote/mod.rs index c5e1843a..388c1e50 100644 --- a/src-tauri/src/remote/mod.rs +++ b/src-tauri/src/remote/mod.rs @@ -1,8 +1,2 @@ -pub mod auth; -#[macro_use] -pub mod cache; pub mod commands; -pub mod fetch_object; -pub mod requests; -pub mod server_proto; -pub mod utils; +pub mod server_proto; \ No newline at end of file diff --git a/src-tauri/src/remote/server_proto.rs b/src-tauri/src/remote/server_proto.rs index ed07c9ba..d831a8b0 100644 --- a/src-tauri/src/remote/server_proto.rs +++ b/src-tauri/src/remote/server_proto.rs @@ -1,10 +1,9 @@ use std::str::FromStr; +use drop_database::borrow_db_checked; use http::{uri::PathAndQuery, Request, Response, StatusCode, Uri}; use tauri::UriSchemeResponder; -use crate::{database::db::borrow_db_checked, remote::utils::DROP_CLIENT_SYNC}; - pub async fn handle_server_proto_offline(_request: Request>, responder: UriSchemeResponder) { let four_oh_four = Response::builder() .status(StatusCode::NOT_FOUND) @@ -37,7 +36,7 @@ pub async fn handle_server_proto(request: Request>, responder: UriScheme return; } - let client = DROP_CLIENT_SYNC.clone(); + let client = drop_remote::utils::DROP_CLIENT_SYNC.clone(); let response = client .request(request.method().clone(), new_uri.to_string()) .header("Authorization", format!("Bearer {web_token}")) diff --git a/src-tauri/src/setup.rs b/src-tauri/src/setup.rs new file mode 100644 index 00000000..e84d2212 --- /dev/null +++ b/src-tauri/src/setup.rs @@ -0,0 +1,121 @@ +use std::{env, path::Path, str::FromStr as _, sync::{Arc, Mutex}}; + +use drop_database::{borrow_db_checked, borrow_db_mut_checked, db::{DatabaseImpls as _, DATA_ROOT_DIR}, models::data::GameDownloadStatus, DB}; +use drop_downloads::download_manager_builder::DownloadManagerBuilder; +use drop_process::process_manager::ProcessManager; +use log::{debug, info, warn, LevelFilter}; +use log4rs::{append::{console::ConsoleAppender, file::FileAppender}, config::{Appender, Root}, encode::pattern::PatternEncoder, Config}; +use tauri::AppHandle; + +use crate::{auth, client::autostart::sync_autostart_on_startup, database::scan::scan_install_dirs, AppState, AppStatus}; + +pub async fn setup(handle: AppHandle) -> AppState { + let logfile = FileAppender::builder() + .encoder(Box::new(PatternEncoder::new( + "{d} | {l} | {f}:{L} - {m}{n}", + ))) + .append(false) + .build(DATA_ROOT_DIR.join("./drop.log")) + .unwrap(); + + let console = ConsoleAppender::builder() + .encoder(Box::new(PatternEncoder::new( + "{d} | {l} | {f}:{L} - {m}{n}", + ))) + .build(); + + let log_level = env::var("RUST_LOG").unwrap_or(String::from("Info")); + + let config = Config::builder() + .appenders(vec![ + Appender::builder().build("logfile", Box::new(logfile)), + Appender::builder().build("console", Box::new(console)), + ]) + .build( + Root::builder() + .appenders(vec!["logfile", "console"]) + .build(LevelFilter::from_str(&log_level).expect("Invalid log level")), + ) + .unwrap(); + + log4rs::init_config(config).unwrap(); + + let download_manager = Arc::new(DownloadManagerBuilder::build(handle.clone())); + let process_manager = Box::leak(Box::new(Mutex::new(ProcessManager::new(handle.clone())))); + + debug!("checking if database is set up"); + let is_set_up = DB.database_is_set_up(); + + scan_install_dirs(); + + if !is_set_up { + return AppState { + status: AppStatus::NotConfigured, + user: None, + download_manager, + process_manager, + }; + } + + debug!("database is set up"); + + // TODO: Account for possible failure + let (app_status, user) = auth::setup().await; + + let db_handle = borrow_db_checked(); + let mut missing_games = Vec::new(); + let statuses = db_handle.applications.game_statuses.clone(); + drop(db_handle); + + for (game_id, status) in statuses { + match status { + GameDownloadStatus::Remote {} => {} + GameDownloadStatus::PartiallyInstalled { .. } => {} + GameDownloadStatus::SetupRequired { + version_name: _, + install_dir, + } => { + let install_dir_path = Path::new(&install_dir); + if !install_dir_path.exists() { + missing_games.push(game_id); + } + } + GameDownloadStatus::Installed { + version_name: _, + install_dir, + } => { + let install_dir_path = Path::new(&install_dir); + if !install_dir_path.exists() { + missing_games.push(game_id); + } + } + } + } + + info!("detected games missing: {missing_games:?}"); + + let mut db_handle = borrow_db_mut_checked(); + for game_id in missing_games { + db_handle + .applications + .game_statuses + .entry(game_id) + .and_modify(|v| *v = GameDownloadStatus::Remote {}); + } + + drop(db_handle); + + debug!("finished setup!"); + + // Sync autostart state + if let Err(e) = sync_autostart_on_startup(&handle) { + warn!("failed to sync autostart state: {e}"); + } + + AppState { + status: app_status, + user, + download_manager, + process_manager, + } +}