diff --git a/Cargo.lock b/Cargo.lock index aa97103..16589c9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -138,6 +138,19 @@ dependencies = [ "libloading", ] +[[package]] +name = "async-compression" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59a194f9d963d8099596278594b3107448656ba73831c9d8c783e613ce86da64" +dependencies = [ + "flate2", + "futures-core", + "memchr", + "pin-project-lite", + "tokio", +] + [[package]] name = "atomic-waker" version = "1.1.2" @@ -194,6 +207,12 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + [[package]] name = "bincode" version = "1.3.3" @@ -251,15 +270,6 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - [[package]] name = "block2" version = "0.5.1" @@ -497,7 +507,7 @@ dependencies = [ "bitflags 1.3.2", "core-foundation 0.9.4", "core-graphics-types 0.1.3", - "foreign-types", + "foreign-types 0.5.0", "libc", ] @@ -510,7 +520,7 @@ dependencies = [ "bitflags 2.9.0", "core-foundation 0.10.0", "core-graphics-types 0.2.0", - "foreign-types", + "foreign-types 0.5.0", "libc", ] @@ -559,15 +569,6 @@ dependencies = [ "unicode-segmentation", ] -[[package]] -name = "cpufeatures" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" -dependencies = [ - "libc", -] - [[package]] name = "crc32fast" version = "1.4.2" @@ -620,16 +621,6 @@ dependencies = [ "wgpu", ] -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - [[package]] name = "ctor-lite" version = "0.1.0" @@ -642,16 +633,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991" -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", -] - [[package]] name = "directories" version = "6.0.0" @@ -764,6 +745,15 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + [[package]] name = "equivalent" version = "1.0.2" @@ -851,6 +841,12 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + [[package]] name = "foldhash" version = "0.1.5" @@ -889,6 +885,15 @@ dependencies = [ "ttf-parser 0.20.0", ] +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared 0.1.1", +] + [[package]] name = "foreign-types" version = "0.5.0" @@ -896,7 +901,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" dependencies = [ "foreign-types-macros", - "foreign-types-shared", + "foreign-types-shared 0.3.1", ] [[package]] @@ -910,6 +915,12 @@ dependencies = [ "syn", ] +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "foreign-types-shared" version = "0.3.1" @@ -1015,16 +1026,6 @@ dependencies = [ "slab", ] -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - [[package]] name = "gethostname" version = "0.4.3" @@ -1333,6 +1334,25 @@ dependencies = [ "svg_fmt", ] +[[package]] +name = "h2" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75249d144030531f8dee69fe9cea04d3edf809a017ae445e2abdff6629e86633" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "half" version = "2.6.0" @@ -1376,6 +1396,119 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" +[[package]] +name = "http" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "hyper" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" +dependencies = [ + "futures-util", + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497bbc33a26fdd4af9ed9c70d63f61cf56a938375fbb32df34db9b1cd6d643f2" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "libc", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + [[package]] name = "iced" version = "0.14.0-dev" @@ -1797,6 +1930,12 @@ dependencies = [ "syn", ] +[[package]] +name = "ipnet" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" + [[package]] name = "itertools" version = "0.12.1" @@ -2067,12 +2206,18 @@ dependencies = [ "bitflags 2.9.0", "block", "core-graphics-types 0.1.3", - "foreign-types", + "foreign-types 0.5.0", "log", "objc", "paste", ] +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -2134,6 +2279,23 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "native-tls" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + [[package]] name = "ndk" version = "0.9.0" @@ -2503,6 +2665,50 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +[[package]] +name = "openssl" +version = "0.10.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da" +dependencies = [ + "bitflags 2.9.0", + "cfg-if", + "foreign-types 0.3.2", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "openssl-probe" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" + +[[package]] +name = "openssl-sys" +version = "0.9.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e145e1651e858e820e4860f7b9c5e169bc1d8ce1c86043be79fa7b7634821847" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "option-ext" version = "0.2.0" @@ -2900,16 +3106,63 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" +[[package]] +name = "reqwest" +version = "0.12.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb" +dependencies = [ + "async-compression", + "base64", + "bytes", + "encoding_rs", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-tls", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-native-tls", + "tokio-util", + "tower", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows-registry", +] + [[package]] name = "reversed-rooms-launcher" -version = "0.2.0" +version = "0.3.0" dependencies = [ "directories", "file-format", "iced", "iced_video_player", "image", - "rust-embed", + "reqwest", "serde", "serde_json", "strum 0.27.1", @@ -2924,46 +3177,26 @@ version = "0.8.50" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.15", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + [[package]] name = "roxmltree" version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97" -[[package]] -name = "rust-embed" -version = "8.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5fbc0ee50fcb99af7cebb442e5df7b5b45e9460ffa3f8f549cd26b862bec49d" -dependencies = [ - "rust-embed-impl", - "rust-embed-utils", - "walkdir", -] - -[[package]] -name = "rust-embed-impl" -version = "8.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bf418c9a2e3f6663ca38b8a7134cc2c2167c9d69688860e8961e3faa731702e" -dependencies = [ - "proc-macro2", - "quote", - "rust-embed-utils", - "syn", - "walkdir", -] - -[[package]] -name = "rust-embed-utils" -version = "8.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d55b95147fe01265d06b3955db798bdaed52e60e2211c41137701b3aba8e21" -dependencies = [ - "sha2", - "walkdir", -] - [[package]] name = "rustc-demangle" version = "0.1.24" @@ -3008,6 +3241,45 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "rustls" +version = "0.23.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df51b5869f3a441595eac5e8ff14d486ff285f7b8c0df8770e49c3b56351f0f0" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" + +[[package]] +name = "rustls-webpki" +version = "0.103.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fef8b8769aaccf73098557a87cd1816b4f9c7c16811c9c77142aa695c16f2c03" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + [[package]] name = "rustversion" version = "1.0.20" @@ -3046,6 +3318,15 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "schannel" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +dependencies = [ + "windows-sys 0.59.0", +] + [[package]] name = "scoped-tls" version = "1.0.1" @@ -3071,6 +3352,29 @@ dependencies = [ "tiny-skia", ] +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags 2.9.0", + "core-foundation 0.9.4", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "self_cell" version = "1.1.0" @@ -3128,14 +3432,15 @@ dependencies = [ ] [[package]] -name = "sha2" -version = "0.10.8" +name = "serde_urlencoded" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ - "cfg-if", - "cpufeatures", - "digest", + "form_urlencoded", + "itoa", + "ryu", + "serde", ] [[package]] @@ -3260,7 +3565,7 @@ dependencies = [ "core-graphics 0.24.0", "drm", "fastrand", - "foreign-types", + "foreign-types 0.5.0", "js-sys", "log", "memmap2", @@ -3348,6 +3653,12 @@ dependencies = [ "syn", ] +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + [[package]] name = "svg_fmt" version = "0.4.4" @@ -3376,6 +3687,15 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + [[package]] name = "synstructure" version = "0.13.1" @@ -3396,6 +3716,27 @@ dependencies = [ "libc", ] +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags 2.9.0", + "core-foundation 0.9.4", + "system-configuration-sys", +] + +[[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" @@ -3592,6 +3933,39 @@ dependencies = [ "syn", ] +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + [[package]] name = "toml" version = "0.8.20" @@ -3626,6 +4000,33 @@ dependencies = [ "winnow", ] +[[package]] +name = "tower" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + [[package]] name = "tracing" version = "0.1.41" @@ -3657,6 +4058,12 @@ dependencies = [ "once_cell", ] +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + [[package]] name = "ttf-parser" version = "0.20.0" @@ -3675,12 +4082,6 @@ version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" -[[package]] -name = "typenum" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" - [[package]] name = "unicode-bidi" version = "0.3.18" @@ -3741,6 +4142,12 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.5.4" @@ -3775,6 +4182,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + [[package]] name = "version-compare" version = "0.2.0" @@ -3797,6 +4210,15 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -4182,8 +4604,8 @@ checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" dependencies = [ "windows-implement", "windows-interface", - "windows-result", - "windows-strings", + "windows-result 0.2.0", + "windows-strings 0.1.0", "windows-targets 0.52.6", ] @@ -4209,6 +4631,23 @@ dependencies = [ "syn", ] +[[package]] +name = "windows-link" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" + +[[package]] +name = "windows-registry" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3" +dependencies = [ + "windows-result 0.3.2", + "windows-strings 0.3.1", + "windows-targets 0.53.0", +] + [[package]] name = "windows-result" version = "0.2.0" @@ -4218,16 +4657,34 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-result" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-strings" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" dependencies = [ - "windows-result", + "windows-result 0.2.0", "windows-targets 0.52.6", ] +[[package]] +name = "windows-strings" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-sys" version = "0.45.0" @@ -4294,13 +4751,29 @@ 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.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" +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_aarch64_gnullvm" version = "0.42.2" @@ -4319,6 +4792,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" @@ -4337,6 +4816,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" @@ -4355,12 +4840,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" @@ -4379,6 +4876,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" @@ -4397,6 +4900,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" @@ -4415,6 +4924,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" @@ -4433,6 +4948,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 = "winit" version = "0.30.8" @@ -4683,6 +5204,12 @@ dependencies = [ "synstructure", ] +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" + [[package]] name = "zerovec" version = "0.10.4" diff --git a/Cargo.toml b/Cargo.toml index bd3fb22..c31d85b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ #![feature(let_chains)] [package] name = "reversed-rooms-launcher" -version = "0.2.0" +version = "0.3.0" edition = "2024" [dependencies] @@ -13,13 +13,30 @@ serde_json = "1.0.140" tempfile = "3.19.1" iced_video_player = {path = "./iced_video_player"} url = "2.5.4" -rust-embed = "8.7.0" file-format = "0.26.0" strum = "0.27.1" strum_macros = "0.27.1" +reqwest = { version = "0.12.15", features = ["blocking", "gzip", "json"] } [profile.release] -strip = true # Automatically strip symbols from the binary. -lto = true # Link-time optimization. -opt-level = 3 # Optimize for speed. -codegen-units = 1 # Maximum size reduction optimizations. \ No newline at end of file +strip = true # Automatically strip symbols from the binary +lto = "fat" # More aggressive Link Time Optimization +opt-level = 3 # Optimize for speed +codegen-units = 1 # Maximum size reduction optimizations +panic = "abort" # Remove panic unwinding code +debug = false # No debug symbols +overflow-checks = false # Disable runtime integer overflow checks +rpath = false # Don't embed runtime search path + +[profile.dev] +opt-level = 0 # No optimizations for faster compilation +debug = true # Full debug info +debug-assertions = true # Enable debug assertions +overflow-checks = true # Enable runtime integer overflow checks +lto = false # Disable link-time optimization +incremental = true # Enable incremental compilation +codegen-units = 256 # Use many codegen units for parallel compilation +split-debuginfo = "unpacked" # Faster debug builds on some platforms + +[profile.dev.package."*"] +opt-level = 0 # No optimization for most dependencies \ No newline at end of file diff --git a/resources/genshinimpact-icon.png b/resources/genshinimpact-icon.png deleted file mode 100644 index b101929..0000000 Binary files a/resources/genshinimpact-icon.png and /dev/null differ diff --git a/resources/honkaistarrail-icon.png b/resources/honkaistarrail-icon.png deleted file mode 100644 index fced2d8..0000000 Binary files a/resources/honkaistarrail-icon.png and /dev/null differ diff --git a/resources/placeholder.png b/resources/placeholder.png deleted file mode 100644 index 74a560c..0000000 Binary files a/resources/placeholder.png and /dev/null differ diff --git a/resources/wutheringwaves-bg.mp4 b/resources/wutheringwaves-bg.mp4 deleted file mode 100644 index 690b94a..0000000 Binary files a/resources/wutheringwaves-bg.mp4 and /dev/null differ diff --git a/resources/zenlesszonezero-icon.png b/resources/zenlesszonezero-icon.png deleted file mode 100644 index 0e9fe05..0000000 Binary files a/resources/zenlesszonezero-icon.png and /dev/null differ diff --git a/src/components/installer.rs b/src/components/installer.rs new file mode 100644 index 0000000..baac838 --- /dev/null +++ b/src/components/installer.rs @@ -0,0 +1,240 @@ +use std::{fs::create_dir_all, io::Write, path::Path}; +use std::fs::OpenOptions; + +use directories::ProjectDirs; +use reqwest::blocking::Client; +use reqwest::header::{HeaderMap, HeaderValue, ACCEPT_ENCODING}; +use serde::{Deserialize, Serialize}; + +const KURO_BASE_URL: &str = "https://prod-alicdn-gamestarter.kurogame.com/launcher/launcher/50004_obOHXFrFanqsaIEOmuKroCcbZkQRBC7c/G153"; + +#[derive(Serialize, Deserialize, Debug)] +struct BackgroundFunctionCode { + background: String +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all(serialize = "camelCase", deserialize = "camelCase"))] +struct KuroVersionIndex { + function_code: BackgroundFunctionCode +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all(serialize = "camelCase", deserialize = "camelCase"))] +struct KuroBackgroundInformation { + function_switch: i32, + background_file: String, + background_file_type: i32, + first_frame_image: String, + slogan: String +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all(serialize = "camelCase", deserialize = "camelCase"))] +struct HoyoImageInformation { + url: String, +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all(serialize = "camelCase", deserialize = "camelCase"))] +struct HoyoDisplayInformation { + name: String, + icon: HoyoImageInformation, + background: HoyoImageInformation +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all(serialize = "camelCase", deserialize = "camelCase"))] +struct HoyoGameInformation { + display: HoyoDisplayInformation +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all(serialize = "camelCase", deserialize = "camelCase"))] +struct HoyoGameList { + games: Vec +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all(serialize = "camelCase", deserialize = "camelCase"))] +struct HoyoLauncherInformation { + data: HoyoGameList +} + +pub fn refresh_install() -> Result<(), String> { + let reqwest_client = build_client()?; + let proj_dirs = ProjectDirs::from("com", "RabbyDevs", "rr-launcher") + .ok_or_else(|| "Failed to get project directories".to_string())?; + + if let Err(e) = refresh_kuro_install(&proj_dirs, &reqwest_client) { + eprintln!("Error in Kuro install: {}", e); + } + + if let Err(e) = refresh_hoyo_install(&proj_dirs, &reqwest_client) { + eprintln!("Error in Hoyo install: {}", e); + } + + Ok(()) +} + +fn build_client() -> Result { + let mut headers = HeaderMap::new(); + headers.insert(ACCEPT_ENCODING, HeaderValue::from_static("gzip, deflate, br")); + + Client::builder() + .default_headers(headers) + .gzip(true) + .build() + .map_err(|e| format!("Failed to build HTTP client: {}", e)) +} + +fn refresh_kuro_install(proj_dirs: &ProjectDirs, client: &Client) -> Result<(), String> { + let data_dir_buf = proj_dirs.data_dir().join("kuro/wuwa"); + let data_dir = data_dir_buf.as_path(); + + create_dir_all(data_dir) + .map_err(|e| format!("Failed to create directory: {}", e))?; + + let kuro_url = KURO_BASE_URL.to_string(); + let index_url = format!("{}{}", kuro_url, "/index.json"); + + eprintln!("Fetching index from: {}", index_url); + + let response = client + .get(&index_url) + .send() + .map_err(|e| format!("Failed to send HTTP request: {}", e))?; + + if !response.status().is_success() { + return Err(format!("HTTP request failed with status {}", response.status())); + } + + eprintln!("Response headers: {:?}", response.headers()); + + let version_index: KuroVersionIndex = response + .json() + .map_err(|e| { + format!("Failed to parse JSON - {}", e) + })?; + + eprintln!("Successfully parsed index.json: {:?}", version_index); + + let bg_info_url = format!("{}{}{}{}", + "https://prod-alicdn-gamestarter.kurogame.com/launcher/50004_obOHXFrFanqsaIEOmuKroCcbZkQRBC7c/G153", + "/background/", + version_index.function_code.background, + "/en.json" + ); + + eprintln!("Fetching background info from: {}", bg_info_url); + + let bg_response = client + .get(&bg_info_url) + .send() + .map_err(|e| format!("Failed to send background info request: {}", e))?; + + if !bg_response.status().is_success() { + return Err(format!("Background info request failed with status {}", bg_response.status())); + } + + let bg_information: KuroBackgroundInformation = bg_response + .json() + .map_err(|e| format!("Failed to parse background info JSON: {}", e))?; + + eprintln!("Successfully parsed background info: {:?}", bg_information); + + update_file_if_needed(data_dir, client, &bg_information.background_file, "background")?; + update_file_if_needed(data_dir, client, &bg_information.slogan, "splash")?; + + Ok(()) +} + +fn update_file_if_needed(dir: &Path, client: &Client, file_url: &str, file_type: &str) -> Result<(), String> { + let filename = extract_filename_from_url(file_url); + let expected_file = format!("{}_{}", file_type, filename); + let file_path = dir.join(&expected_file); + + let file_exists = file_path.exists(); + + if !file_exists { + eprintln!("Downloading {} file from: {}", file_type, file_url); + let file_bytes = client + .get(file_url) + .send() + .map_err(|e| format!("Failed to send request for {} file: {}", file_type, e))? + .bytes() + .map_err(|e| format!("Failed to get bytes for {} file: {}", file_type, e))?; + + let mut file = OpenOptions::new() + .write(true) + .create(true) + .truncate(true) + .open(&file_path) + .map_err(|e| format!("Failed to create {} file ({}): {}", file_type, file_path.display(), e))?; + + file.write_all(&file_bytes) + .map_err(|e| format!("Failed to write {} file: {}", file_type, e))?; + + file.flush() + .map_err(|e| format!("Failed to flush {} file: {}", file_type, e))?; + + eprintln!("Successfully downloaded {} file to: {}", file_type, file_path.display()); + } else { + eprintln!("{} file already exists at: {}", file_type, file_path.display()); + } + + Ok(()) +} + +fn refresh_hoyo_install(proj_dirs: &ProjectDirs, client: &Client) -> Result<(), String> { + let hoyo_url = "https://sg-hyp-api.hoyoverse.com/hyp/hyp-connect/api/getGames?launcher_id=VYTpXlbWo8&language=en-us"; + + eprintln!("Fetching Hoyo launcher info from: {}", hoyo_url); + + let response = client + .get(hoyo_url) + .send() + .map_err(|e| format!("Failed to fetch Hoyo launcher info: {}", e))?; + + if !response.status().is_success() { + return Err(format!("Hoyo launcher info request failed with status {}", response.status())); + } + + let hoyo_launcher_info: HoyoLauncherInformation = response + .json() + .map_err(|e| format!("Failed to parse Hoyo launcher info: {}", e))?; + + eprintln!("Successfully parsed Hoyo launcher info"); + + for game in hoyo_launcher_info.data.games { + let game_abbreviation = match game.display.name.as_str() { + "Zenless Zone Zero" => "zzz", + "Honkai Star Rail" => "hsr", + "Genshin Impact" => "gi", + _ => { + eprintln!("Skipping unknown game: {}", game.display.name); + continue; + } + }; + + let data_dir_buf = proj_dirs.data_dir().join(format!("hoyoverse/{}", game_abbreviation)); + let data_dir = data_dir_buf.as_path(); + + create_dir_all(data_dir) + .map_err(|e| format!("Failed to create directory for {}: {}", game_abbreviation, e))?; + + eprintln!("Processing game: {} ({})", game.display.name, game_abbreviation); + + let icon_url = &game.display.icon.url; + update_file_if_needed(data_dir, client, icon_url, "icon")?; + } + + Ok(()) +} + +fn extract_filename_from_url(url: &str) -> String { + match url.split('/').next_back() { + Some(filename) => String::from(filename), + None => String::from("unknown_file"), + } +} \ No newline at end of file diff --git a/src/components/mod.rs b/src/components/mod.rs new file mode 100644 index 0000000..089d4ca --- /dev/null +++ b/src/components/mod.rs @@ -0,0 +1 @@ +pub mod installer; \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 809f6c9..b484a63 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,40 +1,38 @@ -// #![windows_subsystem = "windows"] +#![windows_subsystem = "windows"] mod utils; +mod components; -use file_format::FileFormat; +use components::installer::refresh_install; +use directories::ProjectDirs; use ::image::{DynamicImage, ImageReader}; use iced::{ - alignment::Vertical::{Bottom, Top}, border, font::{self, Family, Stretch, Weight}, gradient, mouse::{self, Interaction}, wgpu::naga::back, widget::{button, center, column, container, image, mouse_area, opaque, row, stack, text, Column, Space}, window::{self, icon, Settings}, Alignment::Center, Color, Element, Font, Length::{self, Fill}, Padding, Point, Renderer, Size, Subscription, Task, Theme + alignment::Vertical::{Bottom, Top}, border, event, font::{Stretch, Weight}, mouse::Interaction, widget::{button, column, container, image, mouse_area, opaque, row, stack, text, Space}, window::{self, icon, Settings}, Alignment::Center, Color, Element, Event, Font, Length, Padding, Size, Subscription, Task }; use iced_video_player::{Video, VideoPlayer}; use serde::{Deserialize, Serialize}; use strum::IntoEnumIterator; use strum_macros::EnumIter; -use utils::{img_utils::round_image, visual_helper::{get_game_background, get_game_icon_dynamic_image, style_container}}; +use utils::visual_helper::{get_game_background, get_game_icon_dynamic_image, style_container}; use std::{ - collections::HashMap, env, fs::{self, create_dir_all, read_to_string}, io::{Cursor, Read, Write}, path::PathBuf, sync::Arc + collections::HashMap, env, fs::{self, create_dir_all, read_to_string}, io::{Cursor, Write}, path::PathBuf }; trait InterfaceImage { - fn into_handle(&self) -> image::Handle; + fn into_handle(self) -> image::Handle; } impl InterfaceImage for DynamicImage { - fn into_handle(&self) -> image::Handle { + fn into_handle(self) -> image::Handle { image::Handle::from_rgba(self.width(), self.height(), self.to_rgba8().into_raw()) } } -#[derive(rust_embed::Embed)] -#[folder = "resources"] -struct Assets; - pub fn main() -> iced::Result { - let segoe_assets = Assets::get("segoe-mdl2-assets.ttf").unwrap(); - let main_font = Assets::get("QuodlibetSans-Regular.ttf").unwrap(); - let icon_file = Assets::get("icon.png").unwrap(); + let segoe_assets = include_bytes!("../resources/segoe-mdl2-assets.ttf"); + let main_font = include_bytes!("../resources/QuodlibetSans-Regular.ttf"); + let icon_file = include_bytes!("../resources/icon.png"); - let icon_image = ImageReader::new(Cursor::new(icon_file.data)) + let icon_image = ImageReader::new(Cursor::new(icon_file)) .with_guessed_format() .unwrap() .decode() @@ -54,15 +52,16 @@ pub fn main() -> iced::Result { resizable: false, transparent: false, level: window::Level::Normal, - exit_on_close_request: true, + exit_on_close_request: false, ..Settings::default() }; iced::application(Launcher::boot, Launcher::update, Launcher::view) + .subscription(Launcher::subscription) .title(Launcher::title) .window(settings) - .font(segoe_assets.data) - .font(main_font.data) + .font(segoe_assets) + .font(main_font) .window_size((1280.0, 760.0)) .run() } @@ -78,7 +77,6 @@ enum PossibleGames { #[derive(Debug)] enum Launcher { - Loading, Loaded(Box), } @@ -119,7 +117,7 @@ impl State { fn create_game_icon(&self, game: &PossibleGames) -> Element { let icon = self.icon_images.get(game).unwrap(); let img = if &self.selected_game == game { - image(icon.into_handle()) + image(icon.clone().into_handle()) .width(Length::Fixed(52.0)) .height(Length::Fixed(68.0)) } else { @@ -131,7 +129,7 @@ impl State { mouse_area( img ) - .on_press(Message::GameSelected(game.clone())) + // .on_press(Message::GameSelected(game.clone())) .interaction(Interaction::Pointer) .into() } @@ -139,6 +137,7 @@ impl State { #[derive(Debug, Default, Clone, Serialize, Deserialize)] struct SavedState { + selected_game: PossibleGames, installed_games: Vec, installed_game_servers: Vec, db_software_installed: bool, @@ -146,7 +145,7 @@ struct SavedState { impl From for Box { fn from(val: SavedState) -> Self { - Box::new(State { installed_games: val.installed_games, installed_game_servers: val.installed_game_servers, db_software_installed: val.db_software_installed, ..State::default() }) + Box::new(State { selected_game: val.selected_game, installed_games: val.installed_games, installed_game_servers: val.installed_game_servers, db_software_installed: val.db_software_installed, ..State::default() }) } } @@ -164,67 +163,73 @@ enum SaveError { #[derive(Debug, Clone)] enum Message { - Loaded(Result), + EventOccurred(Event), DragStarted(), - GameSelected(PossibleGames), + // GameSelected(PossibleGames), Close, Minimize } impl State { - // fn path() -> PathBuf { - // path.push("launcher-state.json"); + fn path() -> PathBuf { + let project_dirs = ProjectDirs::from("com", "RabbyDevs", "rr-launcher").unwrap(); + let path = project_dirs.config_dir(); - // path - // } + path.join("launcher-state.json").to_path_buf() + } - // fn load() -> Result { - // let contents = read_to_string(Self::path()).map_err(|_| LoadError::File)?; + fn load(self) -> Result { + let contents = read_to_string(Self::path()).map_err(|_| LoadError::File)?; - // let saved_state: SavedState = - // serde_json::from_str(&contents).map_err(|_| LoadError::Format)?; + let saved_state: SavedState = + serde_json::from_str(&contents).map_err(|_| LoadError::Format)?; - // Ok(State { - // selected_game: PossibleGames::WutheringWaves, - // installed_games: saved_state.installed_games, - // installed_game_servers: saved_state.installed_game_servers, - // db_software_installed: saved_state.db_software_installed, - // }) - // } + Ok(State { + selected_game: saved_state.selected_game, + installed_games: saved_state.installed_games, + installed_game_servers: saved_state.installed_game_servers, + db_software_installed: saved_state.db_software_installed, + background: self.background, + icon_images: self.icon_images + }) + } - // async fn save(self) -> Result<(), SaveError> { - // let saved_state = SavedState { - // installed_games: self.installed_games, - // installed_game_servers: self.installed_game_servers, - // db_software_installed: self.db_software_installed, - // }; + fn save(&mut self) -> Result<(), SaveError> { + let saved_state = SavedState { + selected_game: self.selected_game.clone(), + installed_games: self.installed_games.clone(), + installed_game_servers: self.installed_game_servers.clone(), + db_software_installed: self.db_software_installed, + }; - // let json = serde_json::to_string_pretty(&saved_state).map_err(|_| SaveError::Format)?; + let json = serde_json::to_string_pretty(&saved_state).map_err(|_| SaveError::Format)?; - // let path = Self::path(); + let path = Self::path(); - // if let Some(dir) = path.parent() { - // create_dir_all(dir).map_err(|_| SaveError::Write)?; - // } + if let Some(dir) = path.parent() { + create_dir_all(dir).map_err(|_| SaveError::Write)?; + } - // { - // fs::write(path, json.as_bytes()).map_err(|_| SaveError::Write)?; - // } + { + let mut file = fs::File::open(path).unwrap(); + file.write_all(json.as_bytes()).map_err(|_| SaveError::Write)?; + file.flush().map_err(|_| SaveError::Write)?; + } - // sleep(std::time::Duration::from_secs(2)); - - // Ok(()) - // } + Ok(()) + } } impl Launcher { fn boot() -> (Self, Task) { - let launcher_bg = get_game_background(&State::default()); + refresh_install().unwrap(); + let launcher_bg = get_game_background(&PossibleGames::default()); let mut icons = HashMap::new(); for game in PossibleGames::iter() { let icon = get_game_icon_dynamic_image(&game); icons.insert(game, icon); } + let final_state = State { background: Some(launcher_bg), icon_images: icons, @@ -239,14 +244,7 @@ impl Launcher { fn update(&mut self, message: Message) -> Task { match self { - Launcher::Loading => match message { - Message::Loaded(Ok(save_state)) => { - *self = Launcher::Loaded(save_state.into()); - Task::none() - }, - _ => Task::none(), - }, - Launcher::Loaded(_) => { + Launcher::Loaded(state) => { match message { Message::DragStarted() => { window::get_latest().and_then(move |id: window::Id| { @@ -262,6 +260,14 @@ impl Launcher { window::get_latest().and_then(move |id: window::Id| { window::minimize(id, true) }) + }, + Message::EventOccurred(event) => { + if let Event::Window(window::Event::CloseRequested) = event { + state.save().unwrap(); + window::get_latest().and_then(window::close) + } else { + Task::none() + } } _ => Task::none() } @@ -269,6 +275,15 @@ impl Launcher { } } + fn subscription(&self) -> Subscription { + event::listen_with(|event, _status, _| { + match event { + Event::Window(window::Event::CloseRequested) => Some(Message::EventOccurred(event)), + _ => None, + } + }) + } + fn view(&self) -> Element { let mut font = Font::with_name("Quodlibet Sans"); font.weight = Weight::Normal; @@ -279,7 +294,6 @@ impl Launcher { bolded_font.stretch = Stretch::Normal; println!("Rerender triggered!"); match self { - Launcher::Loading => center(text("Loading...").size(50)).into(), Launcher::Loaded(state) => { let top_bar = stack![ mouse_area(container( @@ -295,7 +309,7 @@ impl Launcher { state.get_game_icon_row(), ] ) - .padding(Padding { top: 5.0, right: 10.0, bottom: 5.0, left: 10.0 }) + .padding(Padding { top: 5.0, right: 10.0, bottom: 5.0, left: 5.0 }) .align_y(Top) .align_x(Center) .width(Length::Fill) @@ -340,5 +354,4 @@ impl Launcher { } } } -} - +} \ No newline at end of file diff --git a/src/utils/visual_helper.rs b/src/utils/visual_helper.rs index f352f72..0cec164 100644 --- a/src/utils/visual_helper.rs +++ b/src/utils/visual_helper.rs @@ -1,76 +1,121 @@ -use std::{io::{Cursor, Write}, sync::Arc}; +use std::{fs::DirEntry, io::{Cursor, Write}, sync::Arc}; +use directories::ProjectDirs; use file_format::FileFormat; use iced_video_player::Video; use ::image::{DynamicImage, ImageReader}; use iced::{gradient, widget::container, Color}; use tempfile::NamedTempFile; -use crate::{Assets, LauncherBackground, PossibleGames, State}; +use crate::{LauncherBackground, PossibleGames}; use super::img_utils::round_image; -pub fn get_game_background(state: &State) -> LauncherBackground { - let file_path: &str = match state.selected_game { - PossibleGames::WutheringWaves => "wutheringwaves-bg.mp4", - PossibleGames::ZenlessZoneZero => "zenlesszonezero-bg.png", - PossibleGames::HonkaiStarRail => "honkaistarrail-bg.png", - PossibleGames::GenshinImpact => "genshinimpact-bg.png", - }; +pub fn get_game_background(game: &PossibleGames) -> LauncherBackground { + let proj_dirs = ProjectDirs::from("com", "RabbyDevs", "rr-launcher").unwrap(); + let background_bytes = get_background_file(&proj_dirs, game).unwrap(); + let data = Arc::new(background_bytes); + let file_format = FileFormat::from_bytes(&*data); - if let Some(file) = Assets::get(file_path) { - let data = Arc::new(file.data); - let file_format = FileFormat::from_bytes(&*data); - if file_format.extension() == "mp4" { - let mut temp_file = NamedTempFile::new().unwrap(); - temp_file.write_all(&data).unwrap(); + if file_format.extension() == "mp4" { + let mut temp_file = NamedTempFile::new().unwrap(); + temp_file.write_all(&data).unwrap(); - let temp_path = temp_file.path().to_str().unwrap().to_string(); - match Video::new(url::Url::from_file_path(temp_path).unwrap()) { - Ok(mut video) => { - video.set_looping(true); - LauncherBackground::Video(video) - }, - Err(err) => { - panic!("{:#?}", err) - }, - } - } else { - let img = ImageReader::new(Cursor::new(&*data)) - .with_guessed_format() - .unwrap() - .decode() - .unwrap(); - LauncherBackground::Image(img) + let temp_path = temp_file.path().to_str().unwrap().to_string(); + match Video::new(url::Url::from_file_path(temp_path).unwrap()) { + Ok(mut video) => { + video.set_looping(true); + LauncherBackground::Video(video) + }, + Err(err) => { + panic!("{:#?}", err) + }, } - } else { - panic!("Missing icon for {:?}, path: {}", state.selected_game, file_path) + let img = ImageReader::new(Cursor::new(&*data)) + .with_guessed_format() + .unwrap() + .decode() + .unwrap(); + LauncherBackground::Image(img) } } -pub fn get_game_icon_dynamic_image(game: &PossibleGames) -> DynamicImage { - let file_path: &str = match game { - PossibleGames::WutheringWaves => "wutheringwaves-icon.png", - PossibleGames::ZenlessZoneZero => "zenlesszonezero-icon.png", - PossibleGames::HonkaiStarRail => "honkaistarrail-icon.png", - PossibleGames::GenshinImpact => "genshinimpact-icon.png", +fn get_background_file(proj_dirs: &ProjectDirs, game: &PossibleGames) -> Result, std::io::Error> { + let game_dir = match game { + PossibleGames::WutheringWaves => proj_dirs.data_dir().join("kuro/wuwa"), + PossibleGames::ZenlessZoneZero => proj_dirs.data_dir().join("zzz"), + PossibleGames::HonkaiStarRail => proj_dirs.data_dir().join("hsr"), + PossibleGames::GenshinImpact => proj_dirs.data_dir().join("gi"), }; - if let Some(img_file) = Assets::get(file_path) { - let data_cursor = Cursor::new(img_file.data); - - let img = ImageReader::new(data_cursor) - .with_guessed_format() - .unwrap() - .decode() - .unwrap() - .resize(128, 128, ::image::imageops::FilterType::Lanczos3); - - round_image(img) - .unwrap() - } else { - panic!("Missing icon for {:?}, path: {}", game, file_path) + + if !game_dir.exists() { + return Err(std::io::Error::new( + std::io::ErrorKind::NotFound, + format!("Game directory does not exist: {:?}", game_dir) + )); } + + let entries = std::fs::read_dir(&game_dir)?; + + for entry in entries { + let entry = entry?; + let file_name = entry.file_name().into_string().unwrap_or_default(); + + if file_name.starts_with("background_") { + return std::fs::read(entry.path()); + } + } + + Err(std::io::Error::new( + std::io::ErrorKind::NotFound, + format!("No background file found in {:?}", game_dir) + )) +} + +pub fn get_game_icon_dynamic_image(game: &PossibleGames) -> DynamicImage { + let proj_dirs = ProjectDirs::from("com", "RabbyDevs", "rr-launcher").unwrap(); + let file_data: &[u8] = match game { + PossibleGames::WutheringWaves => include_bytes!("../../resources/wutheringwaves-icon.png"), + PossibleGames::ZenlessZoneZero => &get_hoyo_game_icon_file(&proj_dirs, game), + PossibleGames::HonkaiStarRail => &get_hoyo_game_icon_file(&proj_dirs, game), + PossibleGames::GenshinImpact => &get_hoyo_game_icon_file(&proj_dirs, game), + }; + + let data_cursor = Cursor::new(file_data); + + let img = ImageReader::new(data_cursor) + .with_guessed_format() + .unwrap() + .decode() + .unwrap() + .resize(128, 128, ::image::imageops::FilterType::Lanczos3); + + round_image(img) + .unwrap() +} + +fn get_hoyo_game_icon_file(proj_dirs: &ProjectDirs, game: &PossibleGames) -> Vec { + let game_abbrevation = match game { + PossibleGames::ZenlessZoneZero => "zzz", + PossibleGames::HonkaiStarRail => "hsr", + PossibleGames::GenshinImpact => "gi", + _ => panic!("Wuwa inputted in hoyo only func") + }; + + let data_dir = proj_dirs.data_dir().join(format!("hoyoverse/{}", game_abbrevation)); + let icon: Option = { + let mut icon = None; + for path in data_dir.read_dir().unwrap() { + let path = path.unwrap(); + if path.file_name().into_string().unwrap().starts_with("icon_") { + icon = Some(path); + } + } + icon + }; + + std::fs::read(icon.expect("installation went wrong.").path()).unwrap() } fn rad(deg: f32) -> f32 {