diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 0933ad2..4a3ec04 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" @@ -347,9 +341,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", @@ -460,9 +454,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 +467,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", @@ -740,7 +734,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02260d489095346e5cafd04dea8e8cb54d1d74fcd759022a9b72986ebe9a1257" dependencies = [ "serde", - "toml", + "toml 0.8.22", ] [[package]] @@ -795,17 +789,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]] @@ -1193,7 +1186,7 @@ dependencies = [ "libc", "option-ext", "redox_users 0.5.0", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -1237,9 +1230,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", @@ -1294,6 +1287,12 @@ dependencies = [ "chrono", "deranged", "dirs 6.0.0", + "drop-database", + "drop-downloads", + "drop-errors", + "drop-native-library", + "drop-process", + "drop-remote", "droplet-rs", "dynfmt", "filetime", @@ -1307,27 +1306,26 @@ dependencies = [ "known-folders", "log", "log4rs", - "md5", - "native_model", + "md5 0.7.0", "page_size", - "parking_lot 0.12.3", + "parking_lot 0.12.4", "rand 0.9.1", "rayon", "regex", - "reqwest 0.12.22", + "reqwest 0.12.23", "reqwest-middleware 0.4.2", "reqwest-middleware-cache", "reqwest-websocket", "rustbreak", "rustix 0.38.44", - "schemars", + "schemars 0.8.22", "serde", "serde_json", "serde_with", "sha1", "shared_child", "slice-deque", - "sysinfo", + "sysinfo 0.36.1", "tar", "tauri", "tauri-build", @@ -1352,6 +1350,104 @@ dependencies = [ "zstd", ] +[[package]] +name = "drop-database" +version = "0.1.0" +dependencies = [ + "bitcode", + "chrono", + "dirs 6.0.0", + "log", + "native_model", + "rustbreak", + "serde", + "serde_json", + "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 1.3.1", + "humansize", + "reqwest 0.12.23", + "reqwest-websocket", + "serde", + "serde_with", + "tauri-plugin-opener", + "url", +] + +[[package]] +name = "drop-native-library" +version = "0.1.0" +dependencies = [ + "bitcode", + "drop-database", + "drop-downloads", + "drop-errors", + "drop-remote", + "log", + "serde", + "tauri", +] + +[[package]] +name = "drop-process" +version = "0.1.0" +dependencies = [ + "chrono", + "drop-database", + "drop-errors", + "drop-native-library", + "dynfmt", + "log", + "page_size", + "serde", + "shared_child", + "sysinfo 0.37.0", + "tauri", + "tauri-plugin-opener", +] + +[[package]] +name = "drop-remote" +version = "0.1.0" +dependencies = [ + "bitcode", + "chrono", + "drop-database", + "drop-errors", + "droplet-rs", + "gethostname", + "hex 0.4.3", + "http 1.3.1", + "log", + "md5 0.8.0", + "reqwest 0.12.23", + "reqwest-websocket", + "serde", + "tauri", + "url", +] + [[package]] name = "droplet-rs" version = "0.7.3" @@ -1423,7 +1519,7 @@ dependencies = [ "cc", "memchr", "rustc_version", - "toml", + "toml 0.8.22", "vswhom", "winreg 0.52.0", ] @@ -1635,9 +1731,9 @@ checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" [[package]] name = "form_urlencoded" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" dependencies = [ "percent-encoding", ] @@ -1702,9 +1798,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", @@ -2427,9 +2523,11 @@ dependencies = [ "percent-encoding", "pin-project-lite", "socket2", + "system-configuration 0.6.1", "tokio", "tower-service", "tracing", + "windows-registry 0.4.0", ] [[package]] @@ -2560,9 +2658,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", @@ -2871,9 +2969,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,9 +2979,9 @@ 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", @@ -2911,7 +3009,7 @@ dependencies = [ "log", "log-mdc", "once_cell", - "parking_lot 0.12.3", + "parking_lot 0.12.4", "rand 0.8.5", "serde", "serde-value", @@ -2981,6 +3079,12 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" +[[package]] +name = "md5" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae960838283323069879657ca3de837e9f7bbb4c7bf6ea7f1b290d5e9476d2e0" + [[package]] name = "memchr" version = "2.7.4" @@ -3437,6 +3541,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 +3587,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 +3622,8 @@ dependencies = [ "objc2-app-kit", "objc2-core-foundation", "objc2-foundation 0.3.1", + "objc2-javascript-core", + "objc2-security", ] [[package]] @@ -3710,12 +3837,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 +3861,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 +3896,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" @@ -4343,6 +4470,26 @@ dependencies = [ "thiserror 2.0.12", ] +[[package]] +name = "ref-cast" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a0ae411dbe946a674d89546582cea4ba2bb8defac896622d6496f14c23ba5cf" +dependencies = [ + "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]] name = "reflink-copy" version = "0.1.26" @@ -4411,7 +4558,7 @@ dependencies = [ "serde_json", "serde_urlencoded", "sync_wrapper 0.1.2", - "system-configuration", + "system-configuration 0.5.1", "tokio", "tower-service", "url", @@ -4423,12 +4570,13 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.22" +version = "0.12.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbc931937e6ca3a06e3b6c0aa7841849b160a90351d6ab467a8b9b9959767531" +checksum = "d429f34c8092b2d42c7c93cec323bb4adeb7c67698f70839adec842ec10c7ceb" dependencies = [ "base64 0.22.1", "bytes", + "encoding_rs", "futures-channel", "futures-core", "futures-util", @@ -4442,6 +4590,7 @@ dependencies = [ "hyper-util", "js-sys", "log", + "mime", "native-tls", "percent-encoding", "pin-project-lite", @@ -4493,7 +4642,7 @@ dependencies = [ "anyhow", "async-trait", "http 1.3.1", - "reqwest 0.12.22", + "reqwest 0.12.23", "serde", "thiserror 1.0.69", "tower-service", @@ -4521,14 +4670,14 @@ dependencies = [ [[package]] name = "reqwest-websocket" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f91a811daaa8b54faeaec9d507a336897a3d243834a4965254a17d39da8b5c9" +checksum = "cd5f79b25f7f17a62cc9337108974431a66ae5a723ac0d9fe78ac1cce2027720" dependencies = [ "async-tungstenite", "bytes", "futures-util", - "reqwest 0.12.22", + "reqwest 0.12.23", "thiserror 2.0.12", "tokio", "tokio-util", @@ -4769,6 +4918,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 +5025,11 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.219" +version = "1.0.220" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "ceecad4c782e936ac90ecfd6b56532322e3262b14320abf30ce89a92ffdbfe22" dependencies = [ + "serde_core", "serde_derive", ] @@ -4881,10 +5055,19 @@ dependencies = [ ] [[package]] -name = "serde_derive" -version = "1.0.219" +name = "serde_core" +version = "1.0.220" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "ddba47394f3b862d6ff6efdbd26ca4673e3566a307880a0ffb98f274bbe0ec32" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.220" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60e1f3b1761e96def5ec6d04a6e7421c0404fa3cf5c0155f1e2848fae3d8cc08" dependencies = [ "proc-macro2", "quote", @@ -4904,9 +5087,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", @@ -4934,6 +5117,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40734c41988f7306bb04f0ecf60ec0f3f1caa34290e4e8ea471dcd3346483b83" +dependencies = [ + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -4948,15 +5140,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", "indexmap 1.9.3", "indexmap 2.9.0", + "schemars 0.9.0", + "schemars 1.0.4", "serde", "serde_derive", "serde_json", @@ -4966,9 +5160,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 +5185,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 +5196,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]] @@ -5106,12 +5300,13 @@ dependencies = [ [[package]] name = "shared_child" -version = "1.0.2" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e297bd52991bbe0686c086957bee142f13df85d1e79b0b21630a99d374ae9dc" +checksum = "1e362d9935bc50f019969e2f9ecd66786612daae13e8f277be7bfb66e8bed3f7" dependencies = [ "libc", - "windows-sys 0.59.0", + "sigchld", + "windows-sys 0.60.2", ] [[package]] @@ -5120,6 +5315,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" @@ -5282,7 +5498,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", @@ -5394,6 +5610,20 @@ dependencies = [ "windows", ] +[[package]] +name = "sysinfo" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07cec4dc2d2e357ca1e610cfb07de2fa7a10fc3e9fe89f72545f3d244ea87753" +dependencies = [ + "libc", + "memchr", + "ntapi", + "objc2-core-foundation", + "objc2-io-kit", + "windows", +] + [[package]] name = "system-configuration" version = "0.5.1" @@ -5402,7 +5632,18 @@ checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ "bitflags 1.3.2", "core-foundation 0.9.4", - "system-configuration-sys", + "system-configuration-sys 0.5.0", +] + +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags 2.9.1", + "core-foundation 0.9.4", + "system-configuration-sys 0.6.0", ] [[package]] @@ -5415,6 +5656,16 @@ dependencies = [ "libc", ] +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "system-deps" version = "6.2.2" @@ -5424,17 +5675,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 +5707,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", @@ -5506,12 +5758,13 @@ dependencies = [ [[package]] name = "tauri" -version = "2.7.0" +version = "2.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "352a4bc7bf6c25f5624227e3641adf475a6535707451b09bb83271df8b7a6ac7" +checksum = "d4d1d3b3dc4c101ac989fd7db77e045cc6d91a25349cd410455cb5c57d510c1c" dependencies = [ "anyhow", "bytes", + "cookie", "dirs 6.0.0", "dunce", "embed_plist", @@ -5530,10 +5783,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 0.12.23", "serde", "serde_json", "serde_repr", @@ -5557,9 +5811,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 +5821,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", @@ -5606,9 +5860,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 +5874,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 +5919,7 @@ dependencies = [ "thiserror 2.0.12", "tracing", "url", - "windows-registry", + "windows-registry 0.5.2", "windows-result", ] @@ -5697,7 +5951,7 @@ dependencies = [ "dunce", "glob", "percent-encoding", - "schemars", + "schemars 0.8.22", "serde", "serde_json", "serde_repr", @@ -5705,22 +5959,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 +5987,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 +6014,7 @@ dependencies = [ "open", "os_pipe", "regex", - "schemars", + "schemars 0.8.22", "serde", "serde_json", "shared_child", @@ -5788,9 +6042,9 @@ 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", @@ -5799,20 +6053,23 @@ dependencies = [ "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", @@ -5837,9 +6094,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", @@ -5858,7 +6115,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "schemars", + "schemars 0.8.22", "semver", "serde", "serde-untagged", @@ -5866,7 +6123,7 @@ dependencies = [ "serde_with", "swift-rs", "thiserror 2.0.12", - "toml", + "toml 0.9.5", "url", "urlpattern", "uuid", @@ -5881,7 +6138,7 @@ checksum = "e8d321dbc6f998d825ab3f0d62673e810c861aac2d0de2cc2c395328f1d113b4" dependencies = [ "embed-resource", "indexmap 2.9.0", - "toml", + "toml 0.8.22", ] [[package]] @@ -6105,11 +6362,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 +6391,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 +6407,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 +6418,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 +6430,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" @@ -6273,9 +6569,9 @@ 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", @@ -6414,9 +6710,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", @@ -6791,11 +7087,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 +7151,7 @@ dependencies = [ "windows-collections", "windows-core", "windows-future", - "windows-link", + "windows-link 0.1.1", "windows-numerics", ] @@ -6876,9 +7172,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 +7184,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 +7216,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 +7229,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 +7249,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 +7260,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 +7278,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 +7317,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 +7365,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 +7403,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 +7424,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 +7448,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 +7472,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 +7508,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 +7532,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 +7556,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 +7580,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" @@ -7255,14 +7650,15 @@ 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", @@ -7405,9 +7801,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", @@ -7430,7 +7826,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 +7835,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 55f017c..89f4bae 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,129 +1,142 @@ [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" + +[workspace] +resolver = "3" +members = [ + "drop-database", + "drop-downloads", + "drop-errors", + "drop-native-library", + "drop-process", + "drop-remote", +] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html -[target."cfg(any(target_os = \"macos\", windows, target_os = \"linux\"))".dependencies] -tauri-plugin-single-instance = { version = "2.0.0", features = ["deep-link"] } - [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" -hex = "0.4.3" -tauri-plugin-dialog = "2" -http = "1.1.0" -urlencoding = "2.1.3" -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" +bitcode = "0.6.6" +boxcar = "0.2.7" +bytes = "1.10.1" cacache = "13.1.0" +chrono = "0.4.38" +deranged = "=0.4.0" +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" } +droplet-rs = "0.7.3" +filetime = "0.2.25" +futures-core = "0.3.31" +futures-lite = "2.6.0" +gethostname = "1.0.1" +hex = "0.4.3" +http = "1.1.0" http-serde = "2.1.1" +humansize = "2.1.3" +known-folders = "1.2.0" +log = "0.4.22" +md5 = "0.7.0" +page_size = "0.6.0" +parking_lot = "0.12.3" +rand = "0.9.1" +rayon = "1.10.0" +regex = "1.11.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" -regex = "1.11.1" -tempfile = "3.19.1" -schemars = "0.8.22" -sha1 = "0.10.6" -dirs = "6.0.0" -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" +schemars = "0.8.22" +serde_json = "1" +serde_with = "3.12.0" +sha1 = "0.10.6" +shared_child = "1.0.1" +slice-deque = "0.3.0" sysinfo = "0.36.1" -humansize = "2.1.3" +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" +throttle_my_fn = "0.2.6" tokio-util = { version = "0.7.16", features = ["io"] } -futures-core = "0.3.31" -bytes = "1.10.1" +umu-wrapper-lib = "0.1.0" +url = "2.5.2" +urlencoding = "2.1.3" +walkdir = "2.5.0" +webbrowser = "1.0.2" +whoami = "1.6.0" +zstd = "0.13.3" # 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"] - [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.rustbreak] +version = "2" +features = ["other_errors"] # You can also use "yaml_enc" or "bin_enc" + +[dependencies.rustix] +version = "0.38.37" +features = ["fs"] + [dependencies.serde] version = "1" features = ["derive", "rc"] +[dependencies.tokio] +version = "1.40.0" +features = ["rt", "signal", "tokio-macros"] + +[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-database/Cargo.toml b/src-tauri/drop-database/Cargo.toml new file mode 100644 index 0000000..18aa56a --- /dev/null +++ b/src-tauri/drop-database/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "drop-database" +version = "0.1.0" +edition = "2024" + +[dependencies] +bitcode = "0.6.7" +chrono = "0.4.42" +dirs = "6.0.0" +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_json = "1.0.143" +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 87% rename from src-tauri/src/database/db.rs rename to src-tauri/drop-database/src/db.rs index 2a50f3a..c4b8ad6 100644 --- a/src-tauri/src/database/db.rs +++ b/src-tauri/drop-database/src/db.rs @@ -123,8 +123,8 @@ fn handle_invalid_database( } // 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; @@ -158,24 +158,4 @@ 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}"); - } - } -} +} \ No newline at end of file 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 52ad3fb..196fa77 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 0000000..4bc1256 --- /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 96% rename from src-tauri/src/database/models.rs rename to src-tauri/drop-database/src/models.rs index 848169a..4e649b9 100644 --- a/src-tauri/src/database/models.rs +++ b/src-tauri/drop-database/src/models.rs @@ -4,7 +4,7 @@ pub mod data { use native_model::native_model; use serde::{Deserialize, Serialize}; - // NOTE: Within each version, you should NEVER use these types. + // NOTE: Within each version, you should NEVER use these types. // Declare it using the actual version that it is from, i.e. v1::Settings rather than just Settings from here pub type GameVersion = v1::GameVersion; @@ -37,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,15 @@ 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 + #[serde(skip)] + pub games: HashMap, 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 { @@ -291,6 +293,7 @@ pub mod data { .into_iter() .map(|x| (x.0, x.1.into())) .collect::>(), + games: HashMap::new(), install_dirs: value.install_dirs, game_versions: value.game_versions, installed_game_version: value.installed_game_version, @@ -302,10 +305,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 { @@ -344,6 +344,7 @@ pub mod data { Self { applications: DatabaseApplications { install_dirs: vec![games_base_dir.into()], + games: HashMap::new(), game_statuses: HashMap::new(), game_versions: HashMap::new(), installed_game_version: HashMap::new(), @@ -357,6 +358,5 @@ pub mod data { 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 0000000..26428b5 --- /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 0000000..545f068 --- /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 0000000..e1d2d48 --- /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 b346120..e7ff421 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 13d20e6..c9ccbc4 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 547daf8..0c5133e 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 0000000..e0b3884 --- /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 0000000..02dd730 --- /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 43c8d76..e637937 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 c4fda82..5c481b1 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 0000000..0aa44fc --- /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 100% rename from src-tauri/src/error/drop_server_error.rs rename to src-tauri/drop-errors/src/drop_server_error.rs 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 100% rename from src-tauri/src/error/remote_access_error.rs rename to src-tauri/drop-errors/src/remote_access_error.rs diff --git a/src-tauri/drop-native-library/Cargo.toml b/src-tauri/drop-native-library/Cargo.toml new file mode 100644 index 0000000..7a94c69 --- /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 = "0.6.7" +drop-database = { path = "../drop-database" } +drop-downloads = { path = "../drop-downloads" } +drop-errors = { path = "../drop-errors" } +drop-remote = { path = "../drop-remote" } +log = "0.4.28" +serde = { version = "1.0.219", features = ["derive"] } +tauri = "2.8.5" diff --git a/src-tauri/src/games/collections/collection.rs b/src-tauri/drop-native-library/src/collections.rs similarity index 93% rename from src-tauri/src/games/collections/collection.rs rename to src-tauri/drop-native-library/src/collections.rs index ea29474..7dd6707 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 0000000..77f24d6 --- /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/src/games/mod.rs b/src-tauri/drop-native-library/src/lib.rs similarity index 58% rename from src-tauri/src/games/mod.rs rename to src-tauri/drop-native-library/src/lib.rs index 0d81d10..b5a98e6 100644 --- a/src-tauri/src/games/mod.rs +++ b/src-tauri/drop-native-library/src/lib.rs @@ -1,5 +1,4 @@ pub mod collections; -pub mod commands; -pub mod downloads; pub mod library; pub mod state; +pub mod events; \ No newline at end of file diff --git a/src-tauri/src/games/library.rs b/src-tauri/drop-native-library/src/library.rs similarity index 73% rename from src-tauri/src/games/library.rs rename to src-tauri/drop-native-library/src/library.rs index 2978908..683c401 100644 --- a/src-tauri/src/games/library.rs +++ b/src-tauri/drop-native-library/src/library.rs @@ -1,30 +1,33 @@ 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::DropServerError; +use drop_errors::library_error::LibraryError; +use drop_errors::remote_access_error::RemoteAccessError; +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 tauri::Emitter as _; -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 crate::events::GameUpdateEvent; +use crate::state::GameStatusManager; +use crate::state::GameStatusWithTransient; #[derive(Serialize, Deserialize, Debug)] pub struct FetchGameStruct { @@ -33,55 +36,7 @@ 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>>, - hard_fresh: Option, -) -> Result, RemoteAccessError> { +pub async fn fetch_library_logic(hard_fresh: Option) -> Result, RemoteAccessError> { let do_hard_refresh = hard_fresh.unwrap_or(false); if !do_hard_refresh && let Ok(library) = get_cached_object("library") { return Ok(library); @@ -106,12 +61,10 @@ 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 @@ -140,14 +93,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")?; @@ -167,13 +118,8 @@ pub async fn fetch_library_logic_offline( Ok(games) } -pub async fn fetch_game_logic( - id: String, - state: tauri::State<'_, Mutex>>, -) -> Result { +pub async fn fetch_game_logic(id: String) -> 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 +133,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); @@ -214,7 +160,7 @@ pub async fn fetch_game_logic( .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 +175,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 +202,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 { @@ -285,7 +229,6 @@ pub async fn fetch_game_logic_offline( pub async fn fetch_game_version_options_logic( game_id: String, - state: tauri::State<'_, Mutex>>, ) -> Result, RemoteAccessError> { let client = DROP_CLIENT_ASYNC.clone(); @@ -304,19 +247,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) } @@ -543,49 +473,4 @@ 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(()) -} +} \ No newline at end of file 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 9cffc6d..2928275 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 0000000..365b895 --- /dev/null +++ b/src-tauri/drop-process/Cargo.toml @@ -0,0 +1,19 @@ +[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 = "0.1.5" +log = "0.4.28" +page_size = "0.6.0" +serde = "1.0.220" +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 0000000..4d6c616 --- /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 dcbee5c..9e9559e 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 901671f..8fc475a 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 41f9239..7395756 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 0000000..84f01fa --- /dev/null +++ b/src-tauri/drop-remote/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "drop-remote" +version = "0.1.0" +edition = "2024" + +[dependencies] +bitcode = "0.6.7" +chrono = "0.4.42" +drop-database = { path = "../drop-database" } +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" +reqwest-websocket = "0.5.1" +serde = { version = "1.0.220", features = ["derive"] } +tauri = "2.8.5" +url = "2.5.7" diff --git a/src-tauri/src/remote/auth.rs b/src-tauri/drop-remote/src/auth.rs similarity index 68% rename from src-tauri/src/remote/auth.rs rename to src-tauri/drop-remote/src/auth.rs index 88b7771..e89f761 100644 --- a/src-tauri/src/remote/auth.rs +++ b/src-tauri/drop-remote/src/auth.rs @@ -1,24 +1,17 @@ use std::{collections::HashMap, env, sync::Mutex}; use chrono::Utc; +use drop_database::{borrow_db_checked, borrow_db_mut_checked, models::data::DatabaseAuth, runtime_models::User}; +use drop_errors::{drop_server_error::DropServerError, remote_access_error::RemoteAccessError}; 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 crate::{requests::make_authenticated_get, utils::{DROP_CLIENT_ASYNC, DROP_CLIENT_SYNC}}; -use super::{ - cache::{cache_object, get_cached_object}, - requests::generate_url, -}; +use super::requests::generate_url; #[derive(Serialize)] #[serde(rename_all = "camelCase")] @@ -80,10 +73,10 @@ pub async fn fetch_user() -> Result { .map_err(std::convert::Into::into) } -async fn recieve_handshake_logic(app: &AppHandle, path: String) -> Result<(), RemoteAccessError> { +pub async fn recieve_handshake_logic(path: String) -> Result<(), RemoteAccessError> { let path_chunks: Vec<&str> = path.split('/').collect(); if path_chunks.len() != 3 { - app.emit("auth/failed", ()).unwrap(); +// app.emit("auth/failed", ()).unwrap(); return Err(RemoteAccessError::HandshakeFailed( "failed to parse token".to_string(), )); @@ -139,34 +132,6 @@ async fn recieve_handshake_logic(app: &AppHandle, path: String) -> Result<(), Re 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(); @@ -199,26 +164,4 @@ pub fn auth_initiate_logic(mode: String) -> Result { 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) -} +} \ No newline at end of file diff --git a/src-tauri/src/remote/cache.rs b/src-tauri/drop-remote/src/cache.rs similarity index 92% rename from src-tauri/src/remote/cache.rs rename to src-tauri/drop-remote/src/cache.rs index d4afd14..a4f4fed 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_database::{borrow_db_checked, models::data::Database}; +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 diff --git a/src-tauri/src/remote/fetch_object.rs b/src-tauri/drop-remote/src/fetch_object.rs similarity index 94% rename from src-tauri/src/remote/fetch_object.rs rename to src-tauri/drop-remote/src/fetch_object.rs index 4b5d7fb..3b50490 100644 --- a/src-tauri/src/remote/fetch_object.rs +++ b/src-tauri/drop-remote/src/fetch_object.rs @@ -1,8 +1,10 @@ +use drop_database::{db::DatabaseImpls as _, DB}; use http::{header::CONTENT_TYPE, response::Builder as ResponseBuilder}; use log::warn; use tauri::UriSchemeResponder; -use crate::{database::db::DatabaseImpls, remote::utils::DROP_CLIENT_ASYNC, DB}; + +use crate::utils::DROP_CLIENT_ASYNC; use super::{ auth::generate_authorization_header, diff --git a/src-tauri/drop-remote/src/lib.rs b/src-tauri/drop-remote/src/lib.rs new file mode 100644 index 0000000..007a1c8 --- /dev/null +++ b/src-tauri/drop-remote/src/lib.rs @@ -0,0 +1,5 @@ +pub mod auth; +pub mod cache; +pub mod fetch_object; +pub mod requests; +pub mod utils; diff --git a/src-tauri/src/remote/requests.rs b/src-tauri/drop-remote/src/requests.rs similarity index 79% rename from src-tauri/src/remote/requests.rs rename to src-tauri/drop-remote/src/requests.rs index 7ebf7b1..c43581b 100644 --- a/src-tauri/src/remote/requests.rs +++ b/src-tauri/drop-remote/src/requests.rs @@ -1,11 +1,8 @@ +use drop_database::{db::DatabaseImpls as _, DB}; +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}; pub fn generate_url>( path_components: &[T], 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 87de927..293705c 100644 --- a/src-tauri/src/remote/utils.rs +++ b/src-tauri/drop-remote/src/utils.rs @@ -1,26 +1,13 @@ use std::{ fs::{self, File}, io::Read, - sync::{LazyLock, Mutex}, - time::Duration, + sync::LazyLock, }; -use log::{debug, info, warn}; +use drop_database::db::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 +69,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 0000000..c31e7e4 --- /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 a35f480..47f68d7 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 c6f0e80..2485ab9 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 b47a348..3f50c6e 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 c4de82b..11c1a72 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 6c77e25..084d3a2 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 9e447cf..e2eadba 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 e336c23..00d93e7 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 756a1ad..82b6da3 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 b837592..0000000 --- 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 e36d934..0000000 --- a/src-tauri/src/games/commands.rs +++ /dev/null @@ -1,78 +0,0 @@ -use std::sync::Mutex; - -use tauri::AppHandle; - -use crate::{ - AppState, - database::{ - db::borrow_db_checked, - models::data::GameVersion, - }, - error::{library_error::LibraryError, remote_access_error::RemoteAccessError}, - games::library::{ - fetch_game_logic_offline, fetch_library_logic_offline, get_current_meta, - uninstall_game_logic, - }, - offline, -}; - -use super::{ - library::{ - FetchGameStruct, Game, fetch_game_logic, fetch_game_version_options_logic, - fetch_library_logic, - }, - state::{GameStatusManager, GameStatusWithTransient}, -}; - -#[tauri::command] -pub async fn fetch_library( - state: tauri::State<'_, Mutex>>, - hard_refresh: Option, -) -> Result, RemoteAccessError> { - offline!( - state, - fetch_library_logic, - fetch_library_logic_offline, - state, - hard_refresh - ).await -} - -#[tauri::command] -pub async fn fetch_game( - game_id: String, - state: tauri::State<'_, Mutex>>, -) -> Result { - offline!( - state, - fetch_game_logic, - fetch_game_logic_offline, - game_id, - state - ).await -} - -#[tauri::command] -pub fn fetch_game_status(id: String) -> GameStatusWithTransient { - let db_handle = borrow_db_checked(); - GameStatusManager::fetch_state(&id, &db_handle) -} - -#[tauri::command] -pub fn uninstall_game(game_id: String, app_handle: AppHandle) -> Result<(), LibraryError> { - let meta = match get_current_meta(&game_id) { - Some(data) => data, - None => return Err(LibraryError::MetaNotFound(game_id)), - }; - uninstall_game_logic(meta, &app_handle); - - Ok(()) -} - -#[tauri::command] -pub async fn fetch_game_version_options( - game_id: String, - state: tauri::State<'_, Mutex>>, -) -> Result, RemoteAccessError> { - fetch_game_version_options_logic(game_id, state).await -} diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 90caf5c..7923ff6 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -4,78 +4,61 @@ #![feature(duration_millis_float)] #![feature(iterator_try_collect)] #![deny(clippy::all)] +#![warn(unused_extern_crates)] -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::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 +73,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, + process_manager: &'static Mutex>, } -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, - } -} - -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", @@ -316,11 +152,11 @@ pub fn run() { update_game_configuration, // Collections fetch_collections, - fetch_collection, - create_collection, - add_game_to_collection, - delete_collection, - delete_game_in_collection, + // fetch_collection, + // create_collection, + // add_game_to_collection, + // delete_collection, + // delete_game_in_collection, // Downloads download_game, resume_download, @@ -346,7 +182,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 0db6a49..6941534 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 0000000..abac57a --- /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 83aee8e..ab5b0db 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 e832f3c..bea9459 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 cd45919..e899bc9 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::DropServerError; +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; 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 dc9e277..c4326bb 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 1d11cb8..91a8182 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 0000000..7df4c06 --- /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 13b89fa..d3a96c3 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 fa1089e..6be336e 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/commands.rs b/src-tauri/src/remote/commands.rs index 3f20493..c58a3ea 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 c5e1843..388c1e5 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 ed07c9b..d831a8b 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 0000000..25a805a --- /dev/null +++ b/src-tauri/src/setup.rs @@ -0,0 +1,121 @@ +use std::{collections::HashMap, 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, + } +}