diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 8837ed95..77ab9b0a 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -17,6 +17,19 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "ahash" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" +dependencies = [ + "cfg-if", + "getrandom 0.2.10", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "aho-corasick" version = "1.0.4" @@ -41,6 +54,12 @@ dependencies = [ "alloc-no-stdlib", ] +[[package]] +name = "allocator-api2" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" + [[package]] name = "android-tzdata" version = "0.1.1" @@ -56,6 +75,54 @@ dependencies = [ "libc", ] +[[package]] +name = "anstream" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" + +[[package]] +name = "anstyle-parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +dependencies = [ + "windows-sys 0.48.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" +dependencies = [ + "anstyle", + "windows-sys 0.48.0", +] + [[package]] name = "anyhow" version = "1.0.75" @@ -210,6 +277,39 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +[[package]] +name = "cached" +version = "0.46.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7c8c50262271cdf5abc979a5f76515c234e764fa025d1ba4862c0f0bcda0e95" +dependencies = [ + "ahash", + "cached_proc_macro", + "cached_proc_macro_types", + "hashbrown 0.14.0", + "instant", + "once_cell", + "thiserror", +] + +[[package]] +name = "cached_proc_macro" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c878c71c2821aa2058722038a59a67583a4240524687c6028571c9b395ded61f" +dependencies = [ + "darling 0.14.4", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "cached_proc_macro_types" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a4f925191b4367301851c6d99b09890311d74b0d43f274c0b34c86d308a3663" + [[package]] name = "cairo-rs" version = "0.15.12" @@ -301,6 +401,29 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a48563284b67c003ba0fb7243c87fab68885e1532c605704228a80238512e31" +[[package]] +name = "charset-normalizer-rs" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e93dc84801d1e3b2cbcd5859154ce8500804296fe8fa11f2452da33314962d7" +dependencies = [ + "ahash", + "cached", + "clap", + "counter", + "dialoguer", + "encoding", + "env_logger", + "lazy_static", + "log", + "ordered-float", + "regex", + "serde", + "serde_json", + "strsim", + "unic", +] + [[package]] name = "chrono" version = "0.4.26" @@ -314,6 +437,46 @@ dependencies = [ "winapi", ] +[[package]] +name = "clap" +version = "4.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07cdf1b148b25c1e1f7a42225e30a0d99a615cd4637eae7365548dd4529b95bc" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "clap_lex" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" + [[package]] name = "cocoa" version = "0.24.1" @@ -351,6 +514,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + [[package]] name = "combine" version = "4.6.6" @@ -361,6 +530,19 @@ dependencies = [ "memchr", ] +[[package]] +name = "console" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "unicode-width", + "windows-sys 0.45.0", +] + [[package]] name = "const_panic" version = "0.2.8" @@ -413,6 +595,15 @@ dependencies = [ "libc", ] +[[package]] +name = "counter" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d458e66999348f56fd3ffcfbb7f7951542075ca8359687c703de6500c1ddccd" +dependencies = [ + "num-traits", +] + [[package]] name = "cpufeatures" version = "0.2.9" @@ -531,14 +722,38 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "darling" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" +dependencies = [ + "darling_core 0.14.4", + "darling_macro 0.14.4", +] + [[package]] name = "darling" version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.20.3", + "darling_macro 0.20.3", +] + +[[package]] +name = "darling_core" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 1.0.109", ] [[package]] @@ -555,13 +770,24 @@ dependencies = [ "syn 2.0.32", ] +[[package]] +name = "darling_macro" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" +dependencies = [ + "darling_core 0.14.4", + "quote", + "syn 1.0.109", +] + [[package]] name = "darling_macro" version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" dependencies = [ - "darling_core", + "darling_core 0.20.3", "quote", "syn 2.0.32", ] @@ -588,6 +814,18 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "dialoguer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59c6f2989294b9a498d3ad5491a79c6deb604617378e1cdc4bfc1c1361fe2f87" +dependencies = [ + "console", + "shell-words", + "tempfile", + "zeroize", +] + [[package]] name = "digest" version = "0.10.7" @@ -706,6 +944,12 @@ version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ef6b89e5b37196644d8796de5268852ff179b44e96276cf4290264843743bb7" +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + [[package]] name = "encoding" version = "0.2.33" @@ -779,6 +1023,19 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "env_logger" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95b3f3e67048839cb0d0781f445682a35113da7121f7c949db0e2be96a4fbece" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -1284,6 +1541,10 @@ name = "hashbrown" version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +dependencies = [ + "ahash", + "allocator-api2", +] [[package]] name = "heck" @@ -1352,6 +1613,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21dec9db110f5f872ed9699c3ecf50cf16f423502706ba5c72462e28d3157573" +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + [[package]] name = "iana-time-zone" version = "0.1.57" @@ -1480,6 +1747,17 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "is-terminal" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +dependencies = [ + "hermit-abi", + "rustix", + "windows-sys 0.48.0", +] + [[package]] name = "itertools" version = "0.8.2" @@ -1929,6 +2207,7 @@ version = "0.0.1" dependencies = [ "byteorder", "chardet", + "charset-normalizer-rs", "dirs-next", "discord-rich-presence", "dll-syringe", @@ -1962,6 +2241,15 @@ dependencies = [ "windows-sys 0.42.0", ] +[[package]] +name = "ordered-float" +version = "3.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1e1c390732d15f1d48471625cd92d154e66db2c56645e29a9cd26f4699f72dc" +dependencies = [ + "num-traits", +] + [[package]] name = "os_info" version = "3.7.0" @@ -2707,7 +2995,7 @@ version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e6be15c453eb305019bfa438b1593c731f36a289a7853f7707ee29e870b3b3c" dependencies = [ - "darling", + "darling 0.20.3", "proc-macro2", "quote", "syn 2.0.32", @@ -2765,6 +3053,12 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shell-words" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" + [[package]] name = "shrinkwraprs" version = "0.3.0" @@ -3278,6 +3572,15 @@ dependencies = [ "utf-8", ] +[[package]] +name = "termcolor" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449" +dependencies = [ + "winapi-util", +] + [[package]] name = "thin-slice" version = "0.1.1" @@ -3524,6 +3827,302 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "945af58d18def2f6ec6fbe24c52c8e72121c5498aafe7e0a82ed5fa68574595a" +[[package]] +name = "unic" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e31748f3e294dc6a9243a44686e8155a162af9a11cd56e07c0ebbc530b2a8a87" +dependencies = [ + "unic-bidi", + "unic-char", + "unic-common", + "unic-emoji", + "unic-idna", + "unic-normal", + "unic-segment", + "unic-ucd", +] + +[[package]] +name = "unic-bidi" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1356b759fb6a82050666f11dce4b6fe3571781f1449f3ef78074e408d468ec09" +dependencies = [ + "matches", + "unic-ucd-bidi", +] + +[[package]] +name = "unic-char" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af25df79bd134107f088ba725d9c470600f16263205d0be36c75e75b020bac0a" +dependencies = [ + "unic-char-basics", + "unic-char-property", + "unic-char-range", +] + +[[package]] +name = "unic-char-basics" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20e5d239bc6394309225a0c1b13e1d059565ff2cfef1a437aff4a5871fa06c4b" + +[[package]] +name = "unic-char-property" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221" +dependencies = [ + "unic-char-range", +] + +[[package]] +name = "unic-char-range" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc" + +[[package]] +name = "unic-common" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc" + +[[package]] +name = "unic-emoji" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74193f32f7966ad20b819e70e29c6f1ac8c386692a9d5e90078eef80ea008bfb" +dependencies = [ + "unic-emoji-char", +] + +[[package]] +name = "unic-emoji-char" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b07221e68897210270a38bde4babb655869637af0f69407f96053a34f76494d" +dependencies = [ + "unic-char-property", + "unic-char-range", + "unic-ucd-version", +] + +[[package]] +name = "unic-idna" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "621e9cf526f2094d2c2ced579766458a92f8f422d6bb934c503ba1a95823a62d" +dependencies = [ + "matches", + "unic-idna-mapping", + "unic-idna-punycode", + "unic-normal", + "unic-ucd-bidi", + "unic-ucd-normal", + "unic-ucd-version", +] + +[[package]] +name = "unic-idna-mapping" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4de70fd4e5331537347a50a0dbc938efb1f127c9f6e5efec980fc90585aa1343" +dependencies = [ + "unic-char-property", + "unic-char-range", + "unic-ucd-version", +] + +[[package]] +name = "unic-idna-punycode" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06feaedcbf9f1fc259144d833c0d630b8b15207b0486ab817d29258bc89f2f8a" + +[[package]] +name = "unic-normal" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f09d64d33589a94628bc2aeb037f35c2e25f3f049c7348b5aa5580b48e6bba62" +dependencies = [ + "unic-ucd-normal", +] + +[[package]] +name = "unic-segment" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4ed5d26be57f84f176157270c112ef57b86debac9cd21daaabbe56db0f88f23" +dependencies = [ + "unic-ucd-segment", +] + +[[package]] +name = "unic-ucd" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "625b18f7601e1127504a20ae731dc3c7826d0e86d5f7fe3434f8137669240efd" +dependencies = [ + "unic-ucd-age", + "unic-ucd-bidi", + "unic-ucd-block", + "unic-ucd-case", + "unic-ucd-category", + "unic-ucd-common", + "unic-ucd-hangul", + "unic-ucd-ident", + "unic-ucd-name", + "unic-ucd-name_aliases", + "unic-ucd-normal", + "unic-ucd-segment", + "unic-ucd-version", +] + +[[package]] +name = "unic-ucd-age" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8cfdfe71af46b871dc6af2c24fcd360e2f3392ee4c5111877f2947f311671c" +dependencies = [ + "unic-char-property", + "unic-char-range", + "unic-ucd-version", +] + +[[package]] +name = "unic-ucd-bidi" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1d568b51222484e1f8209ce48caa6b430bf352962b877d592c29ab31fb53d8c" +dependencies = [ + "unic-char-property", + "unic-char-range", + "unic-ucd-version", +] + +[[package]] +name = "unic-ucd-block" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b2a16f2d7ecd25325a1053ca5a66e7fa1b68911a65c5e97f8d2e1b236b6f1d7" +dependencies = [ + "unic-char-property", + "unic-char-range", + "unic-ucd-version", +] + +[[package]] +name = "unic-ucd-case" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d98d6246a79bac6cf66beee01422bda7c882e11d837fa4969bfaaba5fdea6d3" +dependencies = [ + "unic-char-property", + "unic-char-range", + "unic-ucd-version", +] + +[[package]] +name = "unic-ucd-category" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b8d4591f5fcfe1bd4453baaf803c40e1b1e69ff8455c47620440b46efef91c0" +dependencies = [ + "matches", + "unic-char-property", + "unic-char-range", + "unic-ucd-version", +] + +[[package]] +name = "unic-ucd-common" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9b78b910beafa1aae5c59bf00877c6cece1c5db28a1241ad801e86cecdff4ad" +dependencies = [ + "unic-char-property", + "unic-char-range", + "unic-ucd-version", +] + +[[package]] +name = "unic-ucd-hangul" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb1dc690e19010e1523edb9713224cba5ef55b54894fe33424439ec9a40c0054" +dependencies = [ + "unic-ucd-version", +] + +[[package]] +name = "unic-ucd-ident" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e230a37c0381caa9219d67cf063aa3a375ffed5bf541a452db16e744bdab6987" +dependencies = [ + "unic-char-property", + "unic-char-range", + "unic-ucd-version", +] + +[[package]] +name = "unic-ucd-name" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8fc55a45b2531089dc1773bf60c1f104b38e434b774ffc37b9c29a9b0f492e" +dependencies = [ + "unic-char-property", + "unic-ucd-hangul", + "unic-ucd-version", +] + +[[package]] +name = "unic-ucd-name_aliases" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b7674212643087699ba247a63dd05f1204c7e4880ec9342e545a7cffcc6a46f" +dependencies = [ + "unic-char-property", + "unic-ucd-version", +] + +[[package]] +name = "unic-ucd-normal" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86aed873b8202d22b13859dda5fe7c001d271412c31d411fd9b827e030569410" +dependencies = [ + "unic-char-property", + "unic-char-range", + "unic-ucd-category", + "unic-ucd-hangul", + "unic-ucd-version", +] + +[[package]] +name = "unic-ucd-segment" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2079c122a62205b421f499da10f3ee0f7697f012f55b675e002483c73ea34700" +dependencies = [ + "unic-char-property", + "unic-char-range", + "unic-ucd-version", +] + +[[package]] +name = "unic-ucd-version" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4" +dependencies = [ + "unic-common", +] + [[package]] name = "unicode-bidi" version = "0.3.13" @@ -3551,6 +4150,12 @@ version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" +[[package]] +name = "unicode-width" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" + [[package]] name = "url" version = "2.4.0" @@ -3569,6 +4174,12 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + [[package]] name = "uuid" version = "0.8.2" @@ -4234,3 +4845,29 @@ checksum = "f4686009f71ff3e5c4dbcf1a282d0a44db3f021ba69350cd42086b3e5f1c6985" dependencies = [ "libc", ] + +[[package]] +name = "zerocopy" +version = "0.7.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e97e415490559a91254a2979b4829267a57d2fcd741a98eee8b722fb57289aa0" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd7e48ccf166952882ca8bd778a43502c64f33bf94c12ebe2a7f08e5a0f6689f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "zeroize" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index c2a928b2..c5aeb10a 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -27,6 +27,7 @@ runas = "1.1.0" sysinfo = "0.29.10" simple-logging = "2.0.2" log = "0.4.20" +charset-normalizer-rs = "1.0.6" [target.'cfg(target_os = "windows")'.dependencies] dll-syringe = "0.15.2" diff --git a/src-tauri/src/helpers.rs b/src-tauri/src/helpers.rs index 6814609c..b27abf50 100644 --- a/src-tauri/src/helpers.rs +++ b/src-tauri/src/helpers.rs @@ -1,30 +1,50 @@ use chardet::{charset2encoding, detect}; +use charset_normalizer_rs::from_bytes; use encoding::label::encoding_from_whatwg_label; use encoding::DecoderTrap; -pub fn decode_buffer(buf: Vec) -> String { - let result = detect(&buf); - let mut str_encoding = charset2encoding(&result.0); - // let's just say it's cp1251 if encoding is not detected - // FIXME: find a way to actually detect cp1251 and cp1252 from together +pub fn decode_buffer(buf: Vec) -> (String, String, String) { + let buff_output: String; + let first_encoding: String; + let second_encoding: String; + let mut str_encoding: String; - if result.0 == "MacCyrillic" - || (result.0 == "KOI8-R" && result.1 < 0.7 && result.2 == "Russian") + // chardet + first_encoding = charset2encoding(&detect(&buf).0).to_string(); + + // charset_normalizer_rs + second_encoding = match from_bytes(&buf, None).get_best() { + Some(cd) => cd.encoding().to_string(), + None => "not_found".to_string(), + }; + + str_encoding = first_encoding.clone(); + + if first_encoding == "KOI8-R" + || first_encoding == "MacCyrillic" + || first_encoding == "x-mac-cyrillic" { - str_encoding = "cp1251"; + str_encoding = "cp1251".to_string(); } - if str_encoding.len() < 1 { - str_encoding = "cp1251"; + if second_encoding == "koi8-r" || second_encoding == "macintosh" || second_encoding == "ibm866" + { + str_encoding = "cp1251".to_string(); } - let coder = encoding_from_whatwg_label(str_encoding); + // if str_encoding.len() < 1 { + // str_encoding = "cp1251".to_string(); + // } + + let coder = encoding_from_whatwg_label(str_encoding.as_str()); if coder.is_some() { - coder + buff_output = coder .unwrap() .decode(&buf, DecoderTrap::Ignore) - .expect("Error") + .expect("Error"); } else { - String::from_utf8_lossy(buf.as_slice()).to_string() + buff_output = String::from_utf8_lossy(buf.as_slice()).to_string(); } + + (buff_output, first_encoding, second_encoding) } diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 0b26f98f..43327ccc 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -78,10 +78,10 @@ async fn ping_server(ip: &str, port: i32) -> Result { let before = Instant::now(); match q.recv().await { Ok(_p) => Ok(before.elapsed().as_millis() as u32), - Err(_) => Ok(0), + Err(_) => Ok(9999), } } - Err(_) => Ok(0), + Err(_) => Ok(9999), } } diff --git a/src-tauri/src/query.rs b/src-tauri/src/query.rs index 28312601..34b2470d 100644 --- a/src-tauri/src/query.rs +++ b/src-tauri/src/query.rs @@ -158,17 +158,17 @@ impl Query { let hostname_len = packet.read_u32::().unwrap(); let mut hostname_buf = vec![0u8; hostname_len as usize]; packet.read_exact(&mut hostname_buf).unwrap(); - data.hostname = helpers::decode_buffer(hostname_buf); + data.hostname = helpers::decode_buffer(hostname_buf).0; let gamemode_len = packet.read_u32::().unwrap(); let mut gamemode_buf = vec![0u8; gamemode_len as usize]; packet.read_exact(&mut gamemode_buf).unwrap(); - data.gamemode = helpers::decode_buffer(gamemode_buf); + data.gamemode = helpers::decode_buffer(gamemode_buf).0; let language_len = packet.read_u32::().unwrap(); let mut language_buf = vec![0u8; language_len as usize]; packet.read_exact(&mut language_buf).unwrap(); - data.language = helpers::decode_buffer(language_buf); + data.language = helpers::decode_buffer(language_buf).0; Ok(serde_json::to_string(&data).unwrap()) } @@ -184,7 +184,7 @@ impl Query { let player_name_len = packet.read_u8().unwrap(); let mut player_name_buf = vec![0u8; player_name_len as usize]; packet.read_exact(&mut player_name_buf).unwrap(); - player.name = helpers::decode_buffer(player_name_buf); + player.name = helpers::decode_buffer(player_name_buf).0; player.score = packet.read_i32::().unwrap(); } @@ -202,12 +202,12 @@ impl Query { let rule_name_len = packet.read_u8().unwrap(); let mut rule_name_buf = vec![0u8; rule_name_len as usize]; packet.read_exact(&mut rule_name_buf).unwrap(); - rule.push(helpers::decode_buffer(rule_name_buf)); + rule.push(helpers::decode_buffer(rule_name_buf).0); let rule_value_len = packet.read_u8().unwrap(); let mut rule_value_buf = vec![0u8; rule_value_len as usize]; packet.read_exact(&mut rule_value_buf).unwrap(); - rule.push(helpers::decode_buffer(rule_value_buf)); + rule.push(helpers::decode_buffer(rule_value_buf).0); rules.push(rule); } diff --git a/src-tauri/src/samp.rs b/src-tauri/src/samp.rs index 75001615..b9236567 100644 --- a/src-tauri/src/samp.rs +++ b/src-tauri/src/samp.rs @@ -120,7 +120,7 @@ pub fn get_samp_favorite_list() -> String { let ip_len = r.read_u32::().unwrap(); let mut pos: u32 = r.position().try_into().unwrap(); let server_ip = buffer[pos as usize..(pos + ip_len) as usize].to_vec(); - server_info.ip = helpers::decode_buffer(server_ip); + server_info.ip = helpers::decode_buffer(server_ip).0; r.set_position((pos + ip_len).try_into().unwrap()); server_info.port = r.read_u32::().unwrap(); @@ -128,14 +128,14 @@ pub fn get_samp_favorite_list() -> String { let name_len = r.read_u32::().unwrap(); pos = r.position().try_into().unwrap(); let server_name = buffer[pos as usize..(pos + name_len) as usize].to_vec(); - server_info.name = helpers::decode_buffer(server_name); + server_info.name = helpers::decode_buffer(server_name).0; r.set_position((pos + name_len).try_into().unwrap()); let password_len = r.read_u32::().unwrap(); if password_len != 0 { pos = r.position().try_into().unwrap(); let server_password = buffer[pos as usize..(pos + password_len) as usize].to_vec(); - server_info.password = helpers::decode_buffer(server_password); + server_info.password = helpers::decode_buffer(server_password).0; r.set_position((pos + password_len).try_into().unwrap()); } @@ -143,7 +143,7 @@ pub fn get_samp_favorite_list() -> String { if rcon_len != 0 { pos = r.position().try_into().unwrap(); let server_rcon = buffer[pos as usize..(pos + rcon_len) as usize].to_vec(); - server_info.rcon = helpers::decode_buffer(server_rcon); + server_info.rcon = helpers::decode_buffer(server_rcon).0; r.set_position((pos + rcon_len).try_into().unwrap()); } diff --git a/src/hooks/query.tsx b/src/hooks/query.tsx index cc2d6520..6156e525 100644 --- a/src/hooks/query.tsx +++ b/src/hooks/query.tsx @@ -1,14 +1,12 @@ import { useEffect, useRef } from "react"; -import { usePersistentServers, useServers } from "../states/servers"; +import { useServers } from "../states/servers"; import { queryServer } from "../utils/query"; import { Server } from "../utils/types"; export const useQuery = () => { const queryTimer = useRef(undefined); - const { selected, updateServer, setSelected } = useServers(); - const { updateInFavoritesList, updateInRecentlyJoinedList } = - usePersistentServers(); + const { selected, setSelected } = useServers(); const selectedServer = useRef(selected); useEffect(() => { @@ -37,21 +35,7 @@ export const useQuery = () => { }; const getServerInfo = (srv: Server) => { - queryServer(srv) - .then((server) => { - if (server && selectedServer.current) { - if ( - server.ip == selectedServer.current.ip && - server.port == selectedServer.current.port - ) { - updateServer(server); - updateInFavoritesList(server); - updateInRecentlyJoinedList(server); - setSelected(server); - } - } - }) - .catch((e) => console.log(e)); + queryServer(srv); }; return { diff --git a/src/locales/index.ts b/src/locales/index.ts index 0d2104ac..9e226167 100644 --- a/src/locales/index.ts +++ b/src/locales/index.ts @@ -4,10 +4,15 @@ import English from "./translations/en"; import Spanish from "./translations/es"; import Farsi from "./translations/fa"; import Filipino from "./translations/fil"; -import France from "./translations/fr"; +import French from "./translations/fr"; +import Hindi from "./translations/hi"; import Italian from "./translations/it"; +import Portuguese from "./translations/pt"; import Romanian from "./translations/ro"; import Indonesia from "./translations/id"; +import Polish from "./translations/pl"; +import Bosnian from "./translations/bs"; +import Russian from "./translations/ru"; i18n.use(initReactI18next).init({ // we init with resources @@ -24,11 +29,17 @@ i18n.use(initReactI18next).init({ fil: { translations: Filipino, }, + fr: { + translations: French, + }, + hi: { + translations: Hindi, + }, it: { translations: Italian, }, - fr: { - translations: France, + pt: { + translations: Portuguese, }, ro: { translations: Romanian, @@ -36,6 +47,15 @@ i18n.use(initReactI18next).init({ id: { translations: Indonesia, }, + pl: { + translations: Polish, + }, + bs: { + translations: Bosnian, + }, + ru: { + translations: Russian, + }, }, fallbackLng: "en", debug: true, diff --git a/src/locales/translations/bs.ts b/src/locales/translations/bs.ts new file mode 100644 index 00000000..fd7b98a5 --- /dev/null +++ b/src/locales/translations/bs.ts @@ -0,0 +1,79 @@ +export default { + favorites: "Favoriti", + internet: "Internet", + partners: "Partneri", + recently_joined: "Nedavno posjećen", + nickname: "Nadimak", + settings: "Postavke", + minimize: "Minimiziraj", + maximize: "Maksimiziraj", + close: "Zatvori", + add_server_modal_description_1: "Dodaj server ručno na svoju listu favorita.", + add_server_modal_description_2: "Primjer: 127.0.0.1:7777", + add: "Dodaj", + server: "Server", + address: "Adresa", + players: "Igrači", + server_join_prompt_enter_password: + "Ovaj server je zaštićen, molimo da unesete lozinku.", + server_join_prompt_enter_password_input_placeholder: "Unesi lozinku...", + server_join_prompt_nickname_input_placeholder: "Unesi nadimak...", + connect: "Konektuj", + copy: "Kopiraj", + remove_from_favorites: "Izbriši iz Favorita", + add_to_favorites: "Dodaj u Favorite", + filters: "Filteri", + filter_only_omp_servers: "Samo open.mp serveri", + filter_non_empty_servers: "Neprazni Serveri", + filter_unpassworded_servers: "Serveri bez lozinke", + rule: "Pravilo", + value: "Vrijednost", + player: "Igrač", + score: "Rezultat", + locked: "Zaključano", + unlocked: "Otključano", + openmp_server: "open.mp server", + name: "Ime", + ping: "Ping", + mode: "Mode", + filter_servers: "Filtriraj Servere", + search_for_server_hostname_mode: "Pretraži za ime/mode servera", + clear_recently_joined_list: "Izbriši Nedavno Posjećene Servere", + refresh_servers: "Osvježi Server Listu", + play: "Igraj", + remove_selected_server_from_favorites: + "Ukloni Izabrani Server iz Favorita", + add_selected_server_to_favorites: "Dodaj Izabrani Server u Favorite", + add_server: "Dodaj Server", + hide_player_and_rule_list: "Sakrij listu igrača i pravila", + show_player_and_rule_list: "Prikaži listu igrača i pravila", + copy_server_info: "Kopiraj Server Info", + settings_gta_path_input_label: + "Lokacija GTA: San Andreas-a (gdje je SA-MP također instaliran)", + browse: "Pretraži", + settings_import_nickname_gta_path_from_samp: + "Prenesi nadimak i GTA SA lokaciju iz SA-MP postavki", + settings_import_samp_favorite_list: "Prenesi listu favorita iz SA-MP podataka", + settings_reset_application_data: + "Restartuj podatke aplikacije (očisti postavke i liste)", + settings_new_update_available: "⚠ Novo ažuriranje dostupno. Klikni da skineš! ⚠", + settings_credits_made_by: "Napravio s ❤️", + settings_credits_view_source_on_github: "Pogledaj izvorni kod na GitHub-u", + update_modal_update_available_title: "Dostupno ažuriranje!", + update_modal_update_available_description: + 'Dostupan je novi build launcher-a!\nBuild verzija tvoga launhcer-a: {{ version }}\nTrenutna build verzija launcher-a: {{ newVersion }}\nKlikni "Skini" da otvorite stranicu izdanja', + download: "Skini", + update_modal_remind_me_next_time: "Podjseti Me Slijedeći Put", + update_modal_skip_this_update: "Preskoči Ovo Ažuriranje", + gta_path_modal_cant_find_game_title: "GTA San Andreas nije pronađen!", + gta_path_modal_cant_find_game_description: + 'GTA San Andreas nije pronađen u ovom direktoriju:\n - "{{ path }}"\n"gta_sa.exe" nije pronađen u datom direktoriju.', + open_settings: "Otvori Postavke", + cancel: "Otkaži", + gta_path_modal_cant_find_samp_title: "SA-MP nije pronađen!", + gta_path_modal_cant_find_samp_description: + 'SA-MP instalacija nije pronađena u ovom direktoriju:\n - "{{ path }}"\n"samp.dll" nije pronađen u datom direktoriju.\n\nAko nemaš instaliran SA-MP, možeš ga skinuti sa https://sa-mp.mp/ klikom na **Skini**', + notification_add_to_favorites_title: "Dodan u Favorite!", + notification_add_to_favorites_description: + "{{ server }} je dodan u tvoju listu favorita.", +}; diff --git a/src/locales/translations/en.ts b/src/locales/translations/en.ts index b269d21d..687701b6 100644 --- a/src/locales/translations/en.ts +++ b/src/locales/translations/en.ts @@ -76,4 +76,14 @@ export default { notification_add_to_favorites_title: "Added to Favorites!", notification_add_to_favorites_description: "{{ server }} has been added to your favorite list.", + nickname_modal_name_not_set_title: "No Nickname!", + nickname_modal_name_not_set_description: + "You must choose a nickname for yourself before joining a server.", + gta_path_modal_path_not_set_title: "GTA San Andreas path is not set!", + gta_path_modal_path_not_set_description: + "You didn't set GTA San Andreas path, go to settings and search for game folder.", + admin_permissions_required_modal_title: "Admin permissions required!", + admin_permissions_required_modal_description: + 'It seems like your GTA: San Andreas game requires administration permissions to run. This can be due to many causes, like having your game installed in "C" drive. Please re-open open.mp launcher as administrator either using "Run as Admin" button or manually by yourself', + run_as_admin: "Run as Admin", }; diff --git a/src/locales/translations/fa.ts b/src/locales/translations/fa.ts index 7d6353b8..7bcd6669 100644 --- a/src/locales/translations/fa.ts +++ b/src/locales/translations/fa.ts @@ -78,4 +78,14 @@ export default { notification_add_to_favorites_title: "به مورد علاقه ها اضافه شد!", notification_add_to_favorites_description: "سرور {{ server }} به لیست مورد علاقه های شما اضافه شدt.", + nickname_modal_name_not_set_title: "نام مستعار ندارید!", + nickname_modal_name_not_set_description: + "قبل از ورود به سرور باید برای خود نام مستعار انتخاب کنید.", + gta_path_modal_path_not_set_title: "مسیر GTA San Andreas خالی است!", + gta_path_modal_path_not_set_description: + "شما مسیر GTA San Andreas را انتخاب نکردید، به تنظیمات برید و حستحو را بزنید.", + admin_permissions_required_modal_title: "دسترسی ادمین نیاز است", + admin_permissions_required_modal_description: + 'به نظر میرسد GTA: San Andreas نیاز به دسترسی ادیمن برای اجرا است. این میتواند به چند دلیل باشد، مثال: بازی شما در درایو C نصب شده است. لانچر را با دسترس ادمین باز کنید، یا از دکمه "اجرا توسط ادمین" استفاده کنید.', + run_as_admin: "اجرا توسط ادمین", }; diff --git a/src/locales/translations/hi.ts b/src/locales/translations/hi.ts new file mode 100644 index 00000000..c2aa64c6 --- /dev/null +++ b/src/locales/translations/hi.ts @@ -0,0 +1,80 @@ +export default { + favorites: "पसंदीदा", + internet: "इंटरनेट", + partners: "भागीदार", + recently_joined: "हाल ही में शामिल हुए", + nickname: "उपनाम", + settings: "सेटिंग्स", + minimize: "न्यूनतम", + maximize: "अधिकतम", + close: "बंद", + add_server_modal_description_1: + "पसंदीदा सूची में सर्वर को मैन्युअल रूप से जोड़ें।", + add_server_modal_description_2: "उदाहरण: 127.0.0.1:7777", + add: "जोड़े", + server: "सर्वर", + address: "अड्रेस", + players: "खिलड़ी", + server_join_prompt_enter_password: + "यह सर्वर संरक्षित है, कृपया पासवर्ड दर्ज करें।", + server_join_prompt_enter_password_input_placeholder: "पासवर्ड डालें...", + server_join_prompt_nickname_input_placeholder: "उपनाम डालें...", + connect: "जोड़ें", + copy: "कॉपी", + remove_from_favorites: "पसंदीदा से हटाएँ", + add_to_favorites: "पसंदीदा में जोड़े", + filters: "फ़िल्टर", + filter_only_omp_servers: "सिर्फ open.mp सर्वर", + filter_non_empty_servers: "गैर-रिक्त सर्वर", + filter_unpassworded_servers: "गैर-पासवर्ड सर्वर", + rule: "नियम", + value: "मान", + player: "खिलाड़ी", + score: "अंक", + locked: "लॉक किया गया", + unlocked: "अनलॉक किया गया", + openmp_server: "open.mp सर्वर", + name: "नाम", + ping: "पिंग", + mode: "विधा", + filter_servers: "फ़िल्टर सर्वर", + search_for_server_hostname_mode: "सर्वर होस्टनाम/विधा खोजें", + clear_recently_joined_list: "हाल ही में शामिल हुई सूची साफ़ करें", + refresh_servers: "सर्वर सूची ताज़ा करें", + play: "खेलें", + remove_selected_server_from_favorites: "चयनित सर्वर को पसंदीदा से हटाएँ", + add_selected_server_to_favorites: "चयनित सर्वर को पसंदीदा में जोड़ें", + add_server: "सर्वर जोड़ें", + hide_player_and_rule_list: "खिलाड़ी और नियम सूची छिपाएँ", + show_player_and_rule_list: "खिलाड़ी और नियम सूची दिखाएँ", + copy_server_info: "सर्वर की जानकारी कॉपी करें", + settings_gta_path_input_label: + "GTA: San Andreas पथ (जहां SA-MP भी स्थापित है)", + browse: "ब्राउज़", + settings_import_nickname_gta_path_from_samp: + "SA-MP सेटिंग्स से उपनाम और gtasa पथ आयात करें", + settings_import_samp_favorite_list: "SA-MP डेटा से पसंदीदा सूची आयात करें", + settings_reset_application_data: + "एप्लिकेशन डेटा रीसेट करें (सेटिंग और सूचियाँ साफ़ करता है)", + settings_new_update_available: + "⚠ नया अद्यतन उपलब्ध है। डाउनलोड करने हेतु क्लिक करें! ⚠", + settings_credits_made_by: "❤️ से बनाया गया। निर्माता:", + settings_credits_view_source_on_github: "GitHub पर स्रोत कोड देखें", + update_modal_update_available_title: "उपलब्ध अद्यतन!", + update_modal_update_available_description: + 'नया लॉन्चर बिल्ड उपलब्ध है!\nआपका लॉन्चर बिल्ड संस्करण: {{ version }}\nवर्तमान लॉन्चर बिल्ड संस्करण: {{ newVersion }}\nरिलीज़ पेज खोलने के लिए "डाउनलोड" पर क्लिक करें', + download: "डाउनलोड", + update_modal_remind_me_next_time: "मुझे अगली बार याद दिलाएं", + update_modal_skip_this_update: "इस अद्यतन को छोड़ें", + gta_path_modal_cant_find_game_title: "GTA San Andreas नहीं मिल सका!", + gta_path_modal_cant_find_game_description: + 'इस निर्देशिका में GTA San Andreas नहीं मिल सका:\n - "{{ path }}"\nआपके दिए गए पथ में "gta_sa.exe" ढूँढने में असमर्थ।', + open_settings: "सेटिंग खोलें", + cancel: "रद्द करें", + gta_path_modal_cant_find_samp_title: "SA-MP नहीं मिल सका!", + gta_path_modal_cant_find_samp_description: + 'इस निर्देशिका में SA-MP संस्थापन नहीं मिल सका:\n - "{{ path }}"\nआपके दिए गए पथ में "samp.dll" ढूँढने में असमर्थ।\n\nयदि आपके पास SA-MP स्थापित नहीं है, आप https://sa-mp.mp/ से डाउनलोड कर सकते हैं। इसे क्लिक करें **डाउनलोड**.', + notification_add_to_favorites_title: "पसंदीदा में जोड़ा गया!", + notification_add_to_favorites_description: + "{{ server }} आपकी पसंदीदा सूची में जोड़ा गया।", +}; diff --git a/src/locales/translations/pl.ts b/src/locales/translations/pl.ts new file mode 100644 index 00000000..c191e5c2 --- /dev/null +++ b/src/locales/translations/pl.ts @@ -0,0 +1,77 @@ +export default { + favorites: "Ulubione", + internet: "Internet", + partners: "Partnerzy", + recently_joined: "Ostatnio Dołączone", + nickname: "Pseudonim", + settings: "Ustawienia", + minimize: "Minimalizuj", + maximize: "Maksymalizuj", + close: "Zamknij", + add_server_modal_description_1: "Ręcznie dodaj serwer do listy ulubionych.", + add_server_modal_description_2: "Przykład: 127.0.0.1:7777", + add: "Dodaj", + server: "Serwer", + address: "Adres", + players: "Gracze", + server_join_prompt_enter_password: "Ten serwer ma hasło, wprowadź je:", + server_join_prompt_enter_password_input_placeholder: "Wprowadź hasło...", + server_join_prompt_nickname_input_placeholder: "Wprowadź pseudonim...", + connect: "Połącz", + copy: "Kopiuj", + remove_from_favorites: "Usuń z Ulubionych", + add_to_favorites: "Dodaj do Ulubionych", + filters: "Filtry", + filter_only_omp_servers: "Tylko serwery open.mp", + filter_non_empty_servers: "Serwery z graczami", + filter_unpassworded_servers: "Serwery bez hasła", + rule: "Reguła", + value: "Wartość", + player: "Gracz", + score: "Punkty", + locked: "Zabezpieczony", + unlocked: "Otwarty", + openmp_server: "Serwer open.mp", + name: "Nazwa", + ping: "Ping", + mode: "Tryb", + filter_servers: "Filtruj Serwery", + search_for_server_hostname_mode: "Szukaj według nazwy/trybu serwera", + clear_recently_joined_list: "Wyczyść Ostatnio Dołączone", + refresh_servers: "Odśwież Listę Serwerów", + play: "Graj", + remove_selected_server_from_favorites: "Usuń Wybrany Serwer z Ulubionych", + add_selected_server_to_favorites: "Dodaj Wybrany Serwer do Ulubionych", + add_server: "Dodaj Serwer", + hide_player_and_rule_list: "Ukryj listę graczy i reguł", + show_player_and_rule_list: "Pokaż listę graczy i reguł", + copy_server_info: "Kopiuj Informacje o Serwerze", + settings_gta_path_input_label: "Ścieżka GTA San Andreas (gdzie zainstalowany jest SA-MP)", + browse: "Przeglądaj", + settings_import_nickname_gta_path_from_samp: "Importuj pseudonim i ścieżkę gtasa z ustawień SA-MP", + settings_import_samp_favorite_list: "Importuj listę ulubionych serwerów z danych SA-MP", + settings_reset_application_data: "Zresetuj dane aplikacji (czyści ustawienia i listy)", + settings_new_update_available: "⚠ Nowa aktualizacja dostępna. Kliknij, aby pobrać! ⚠", + settings_credits_made_by: "Stworzone z ❤️ przez", + settings_credits_view_source_on_github: "Zobacz kod źródłowy na GitHubie", + update_modal_update_available_title: "Dostępna Aktualizacja!", + update_modal_update_available_description: 'Nowa wersja launcher\'a jest dostępna!\nTwoja wersja: {{ version }}\nAktualna wersja: {{ newVersion }}\nKliknij "Pobierz", aby otworzyć stronę z aktualizacją.', + download: "Pobierz", + update_modal_remind_me_next_time: "Przypomnij mi następnym razem", + update_modal_skip_this_update: "Pomiń tę aktualizację", + gta_path_modal_cant_find_game_title: "Nie można znaleźć GTA San Andreas!", + gta_path_modal_cant_find_game_description: 'Nie można znaleźć GTA San Andreas w tej lokalizacji:\n - "{{ path }}"\nNie można odnaleźć "gta_sa.exe" w podanej ścieżce.', + nickname_modal_name_not_set_title: "Brak Pseudonimu!", + nickname_modal_name_not_set_description: "Należy wybrać pseudonim przed dołączeniem do serwera.", + gta_path_modal_path_not_set_title: "Ścieżka do GTA San Andreas nie jest ustawiona!", + gta_path_modal_path_not_set_description: "Nie ustawiono ścieżki do GTA San Andreas. Należy przejść do ustawień i wyszukać folder z grą.", + admin_permissions_required_modal_title: "Wymagane są uprawnienia administratora!", + admin_permissions_required_modal_description: "Wygląda na to, że gra GTA San Andreas wymaga uprawnień administratora do uruchomienia. Może to być spowodowane różnymi przyczynami, np. zainstalowaniem gry na dysku \"C\". Otwórz ponownie launcher open.mp jako administrator, używając przycisku \"Uruchom jako Administrator\" lub wykonaj to ręcznie przez siebie.", + run_as_admin: "Uruchom jako Administrator", + open_settings: "Ustawienia", + cancel: "Anuluj", + gta_path_modal_cant_find_samp_title: "Nie można znaleźć SA-MP!", + gta_path_modal_cant_find_samp_description: 'Nie można znaleźć zainstalowanego SA-MP w tej lokalizacji:\n - "{{ path }}"\nNie można odnaleźć "samp.dll" w podanej ścieżce.\n\nJeśli nie masz zainstalowanego SA-MP, możesz pobrać go z https://sa-mp.mp/, klikając **Pobierz**.', + notification_add_to_favorites_title: "Dodano do Ulubionych!", + notification_add_to_favorites_description: "{{ server }} został dodany do listy ulubionych.", +}; diff --git a/src/locales/translations/pt.ts b/src/locales/translations/pt.ts new file mode 100644 index 00000000..ce9469c3 --- /dev/null +++ b/src/locales/translations/pt.ts @@ -0,0 +1,83 @@ +export default { + favorites: "Favoritos", + internet: "Internet", + partners: "Parceiros", + recently_joined: "Entrado Recentemente", + nickname: "Usuário", + settings: "Configurações", + minimize: "Minimizar", + maximize: "Maximizar", + close: "Fechar", + add_server_modal_description_1: + "Adicione servidores manualmente à lista de favoritos.", + add_server_modal_description_2: "Exemplo: 127.0.0.1:7777", + add: "Adicionar", + server: "Servidores", + address: "Endereço IP", + players: "Jogadores", + server_join_prompt_enter_password: + "Este servidor está trancado, por favor digite a senha.", + server_join_prompt_enter_password_input_placeholder: "Digite a senha...", + server_join_prompt_nickname_input_placeholder: "Digite o Nome de Usuário...", + connect: "Conectar", + copy: "Copiar", + remove_from_favorites: "Remover dos favoritos", + add_to_favorites: "Adicionar aos favoritos", + filters: "Filtros", + filter_only_omp_servers: "Somente servidores open.mp", + filter_non_empty_servers: "Servidores não vazios", + filter_unpassworded_servers: "Servidores sem senha", + rule: "Regra", + value: "Valor", + player: "Player", + score: "Score", + locked: "Trancado", + unlocked: "Destrancado", + openmp_server: "Servidor open.mp", + name: "Nome", + ping: "Ping", + mode: "Modo", + filter_servers: "Filtrar servidores", + search_for_server_hostname_mode: "Procurar pelo nome/modo do servidor", + clear_recently_joined_list: "Limpar lista de servidores recentes", + refresh_servers: "Atualizar lista de servidores", + play: "Jogar", + remove_selected_server_from_favorites: + "Remover servidor selecionado dos favoritos", + add_selected_server_to_favorites: + "Adicionar servidor selecionado aos favoritos", + add_server: "Adicionar Servidor", + hide_player_and_rule_list: "Ocultar lista de jogadores e regras", + show_player_and_rule_list: "Mostrar lista de jogadores e regras", + copy_server_info: "Copiar informações do servidor", + settings_gta_path_input_label: + "Caminho do GTA: San Andreas (onde o SA-MP está instalado)", + browse: "Selecionar", + settings_import_nickname_gta_path_from_samp: + "Importar configurações do SA-MP", + settings_import_samp_favorite_list: "Importar lista de favoritos do SA-MP", + settings_reset_application_data: + "Redefinir dados do aplicativo (limpar configurações e listas)", + settings_new_update_available: + "⚠ Nova atualização disponível. Clique aqui para baixar a atualização! ⚠", + settings_credits_made_by: "Feito com ❤️ por", + settings_credits_view_source_on_github: "Código fonte disponível no GitHub", + update_modal_update_available_title: "Atualização disponível!", + update_modal_update_available_description: + 'Nova versão do launcher disponível!\nVersão do seu launcher: {{ version }}\nVersão atual do launcher: {{ newVersion }}\nClique em "Baixar" para abrir a página de downloads', + download: "Baixar", + update_modal_remind_me_next_time: "Me lembre mais tarde", + update_modal_skip_this_update: "Ignorar esta atualização", + gta_path_modal_cant_find_game_title: + "Não foi possível encontrar o GTA San Andreas!", + gta_path_modal_cant_find_game_description: + 'Não é possível encontrar o GTA San Andreas neste diretório:\n - "{{ path }}"\nNão é possível encontrar "gta_sa.exe" no caminho fornecido', + open_settings: "Abrir Configurações", + cancel: "Cancelar", + gta_path_modal_cant_find_samp_title: "Não foi possível encontrar o SA-MP!", + gta_path_modal_cant_find_samp_description: + 'Não é possível encontrar a instalação do SA-MP neste diretório:\n - "{{ path }}"\nNão é possível encontrar "samp.dll" no caminho fornecido\n\nSe você não tem o SA-MP instalado, você pode baixá-lo em https://sa-mp.mp/ clicando em **Baixar**.', + notification_add_to_favorites_title: "Adicionado aos Favoritos!", + notification_add_to_favorites_description: + "{{ server }} foi adicionado à sua lista de favoritos.", +}; diff --git a/src/locales/translations/ru.ts b/src/locales/translations/ru.ts new file mode 100644 index 00000000..a0d41a95 --- /dev/null +++ b/src/locales/translations/ru.ts @@ -0,0 +1,86 @@ +export default { + favorites: "Избранные", + internet: "Интернет", + partners: "Партнеры", + recently_joined: "Недавние", + nickname: "Никнейм", + settings: "Настройки", + minimize: "Свернуть", + maximize: "Развернуть", + close: "Закрыть", + add_server_modal_description_1: "Добавить сервер в список избранных вручную.", + add_server_modal_description_2: "Пример: 127.0.0.1:7777", + add: "Добавить", + server: "Сервер", + address: "Адрес", + players: "Игроки", + server_join_prompt_enter_password: + "Этот сервер защищен паролем, введите его.", + server_join_prompt_enter_password_input_placeholder: "Введите пароль...", + server_join_prompt_nickname_input_placeholder: "Введите никнейм...", + connect: "Подключиться", + copy: "Копировать", + remove_from_favorites: "Удалить из избранных", + add_to_favorites: "Добавить в избранные", + filters: "Фильтры", + filter_only_omp_servers: "Только open.mp серверы", + filter_non_empty_servers: "Непустые серверы", + filter_unpassworded_servers: "Серверы без пароля", + rule: "Правило", + value: "Значение", + player: "Игрок", + score: "Очки", + locked: "С паролем", + unlocked: "Без пароля", + openmp_server: "open.mp сервер", + name: "Название", + ping: "Пинг", + mode: "Режим", + filter_servers: "Фильтр серверов", + search_for_server_hostname_mode: "Поиск по названию/режиму сервера", + clear_recently_joined_list: "Очистить список недавних", + refresh_servers: "Обновить список серверов", + play: "Играть", + remove_selected_server_from_favorites: + "Удалить сервер из избранных", + add_selected_server_to_favorites: "Добавить сервер в избранные", + add_server: "Добавить сервер", + hide_player_and_rule_list: "Скрыть список игроков и правил", + show_player_and_rule_list: "Показать список игроков и правил", + copy_server_info: "Скопировать информацию", + settings_gta_path_input_label: + "Путь к GTA: San Andreas (где также установлен SA-MP)", + browse: "Обзор", + settings_import_nickname_gta_path_from_samp: + "Импортировать никнейм и путь к игре из SA-MP настроек", + settings_import_samp_favorite_list: "Импортировать список избранных из SA-MP данных", + settings_reset_application_data: + "Сброс данных приложения (очистка настроек и списков)", + settings_new_update_available: "⚠ Доступно обновление. Нажмите для его загрузки! ⚠", + settings_credits_made_by: "Сделано с ❤️ ", + settings_credits_view_source_on_github: "Исходный код на GitHub", + update_modal_update_available_title: "Доступно обновление!", + update_modal_update_available_description: + 'Доступна новая версия лаунчера!\nВаша версия лаунчера: {{ version }}\nАктуальная версия лаунчера: {{ newVersion }}\nНажмите "Загрузить" для открытия страницы релиза', + download: "Загрузить", + update_modal_remind_me_next_time: "Напомнить позже", + update_modal_skip_this_update: "Пропустить обновление", + gta_path_modal_cant_find_game_title: "GTA San Andreas не найдена!", + gta_path_modal_cant_find_game_description: + 'Не удается найти GTA San Andreas в этой папке:\n - "{{ path }}"\nОтсутствует "gta_sa.exe" по указанному пути.', + open_settings: "Открыть настройки", + cancel: "Отмена", + gta_path_modal_cant_find_samp_title: "SA-MP не найден!", + gta_path_modal_cant_find_samp_description: + 'Не удается найти SA-MP в этой папке:\n - "{{ path }}"\nОтсутствует "samp.dll" по указанному пути.\n\nЕсли у вас не установлен SA-MP, вы можете загрузить его здесь https://sa-mp.mp/ нажав **Загрузить**.', + notification_add_to_favorites_title: "Добавлено в избранные!", + notification_add_to_favorites_description: + "{{ server }} добавлен в ваш список избранных.", + nickname_modal_name_not_set_title: "Не указан никнейм!", + nickname_modal_name_not_set_description: "Прежде чем присоединиться к серверу, вы должны выбрать себе никнейм.", + gta_path_modal_path_not_set_title: "Путь к GTA San Andreas не установлен!", + gta_path_modal_path_not_set_description: "Вы не указали путь к GTA San Andreas, зайдите в настройки и укажите папку с игрой.", + admin_permissions_required_modal_title: "Требуются права администратора!", + admin_permissions_required_modal_description: "Похоже, что для запуска GTA: San Andreas требуются права администратора. Это может произойти по разным причинам, например, если ваша игра установлена на диске \"C\". Пожалуйста, откройте open.mp лаунчер повторно от имени администратора с помощью кнопки \"Запуск от имени администратора\" либо вручную", + run_as_admin: "Запуск от имени администратора", +}; diff --git a/src/states/servers.ts b/src/states/servers.ts index e058acac..52aa0bf5 100644 --- a/src/states/servers.ts +++ b/src/states/servers.ts @@ -135,4 +135,3 @@ const usePersistentServers = create()( ); export { usePersistentServers, useServers }; - diff --git a/src/utils/helpers.ts b/src/utils/helpers.ts index 5c4cd46a..aa42f833 100644 --- a/src/utils/helpers.ts +++ b/src/utils/helpers.ts @@ -1,6 +1,5 @@ import { invoke, process, shell } from "@tauri-apps/api"; import { getVersion } from "@tauri-apps/api/app"; - import { exists } from "@tauri-apps/api/fs"; import { type } from "@tauri-apps/api/os"; import { t } from "i18next"; @@ -41,9 +40,7 @@ export const mapAPIResponseServerListToAppStructure = ( export const fetchServers = async (cached: boolean = true) => { if (cached) { - const { updateServer } = useServers.getState(); - const { updateInFavoritesList, updateInRecentlyJoinedList, favorites } = - usePersistentServers.getState(); + const { favorites } = usePersistentServers.getState(); if (Array.isArray(favorites)) { // let's query servers from server list so players have updated data @@ -51,13 +48,7 @@ export const fetchServers = async (cached: boolean = true) => { setTimeout(() => { for (let offset = 0; offset < 10; offset++) { if (favorites[i + offset]) { - queryServer(favorites[i + offset]) - .then((server) => { - updateServer(server); - updateInFavoritesList(server); - updateInRecentlyJoinedList(server); - }) - .catch((e) => console.log(e)); + queryServer(favorites[i + offset], "favorites"); } } }, 500 + (i % 10) * 1000); @@ -74,13 +65,7 @@ export const fetchServers = async (cached: boolean = true) => { setTimeout(() => { for (let offset = 0; offset < 15; offset++) { if (response.servers[i + offset]) - queryServer(response.servers[i + offset]) - .then((server) => { - updateServer(server); - updateInFavoritesList(server); - updateInRecentlyJoinedList(server); - }) - .catch((e) => console.log(e)); + queryServer(response.servers[i + offset], "internet"); } }, 500 + (i / 15) * 1000); } @@ -174,12 +159,11 @@ export const startGame = async ( if (!gtasaPath || gtasaPath.length < 1) { showMessageBox({ - title: "GTA San Andreas path is not set!", - description: - "You didn't set GTA San Andreas path, go to settings and search for game folder.", + title: t("gta_path_modal_path_not_set_title"), + description: t("gta_path_modal_path_not_set_description"), buttons: [ { - title: "Open Settings", + title: t("open_settings"), onPress: () => { showPrompt(false); showSettings(); @@ -187,7 +171,7 @@ export const startGame = async ( }, }, { - title: "Cancel", + title: t("cancel"), onPress: () => { showPrompt(true); setServer(server); @@ -201,9 +185,8 @@ export const startGame = async ( if (!nickname || nickname.length < 1) { showMessageBox({ - title: "No Nickname!", - description: - "You must choose a nickname for yourself before joining a server.", + title: t("nickname_modal_name_not_set_title"), + description: t("nickname_modal_name_not_set_description"), buttons: [ { title: "Okay", @@ -237,12 +220,11 @@ export const startGame = async ( }).catch(async (e) => { if (e == "need_admin") { showMessageBox({ - title: "Admin perms required!", - description: - 'It seems like your GTA: San Andreas game requires administration permissions to run. This can be due to many causes, like having your game installed in "C" drive. Please re-open open.mp launcher as administrator either using "Run as Admin" button or manually by yourself', + title: t("admin_permissions_required_modal_title"), + description: t("admin_permissions_required_modal_description"), buttons: [ { - title: "Run as Admin", + title: t("run_as_admin"), onPress: async () => { await invoke("rerun_as_admin").then(() => { process.exit(); @@ -250,7 +232,7 @@ export const startGame = async ( }, }, { - title: "Cancel", + title: t("cancel"), onPress: () => hideMessageBox(), }, ], @@ -316,7 +298,7 @@ export const checkDirectoryValidity = async ( }, }, { - title: t("Cancel"), + title: t("cancel"), onPress: () => { if (onFail) { onFail(); diff --git a/src/utils/query.ts b/src/utils/query.ts index 89e0d1ce..9d2332d7 100644 --- a/src/utils/query.ts +++ b/src/utils/query.ts @@ -1,122 +1,215 @@ import { invoke } from "@tauri-apps/api"; -import { Player, Server } from "./types"; - -export const queryServer = async (server: Server) => { - return new Promise(async (resolve, reject) => { - try { - const { ip, port } = server; - let newSrv: Server = { ...server }; - - newSrv = { ...newSrv, ...(await getServerInfo(ip, port)) }; - newSrv.ip = ip; - newSrv.port = port; - const players = await getServerPlayers(ip, port); - if (players === false) { - newSrv.players = server.players; - } else { - newSrv.players = [...players]; - } +import { usePersistentServers, useServers } from "../states/servers"; +import { ListType, Server } from "./types"; + +export const queryServer = ( + server: Server, + listType: ListType = "internet" +) => { + try { + const { ip, port } = server; + + getServerInfo(ip, port, listType); + getServerPlayers(ip, port, listType); + getServerRules(ip, port, listType); + getServerOmpStatus(ip, port, listType); + getServerPing(ip, port, listType); + } catch (error) { + console.log("[query.ts: queryServer]", error); + } +}; - newSrv.rules = await getServerRules(ip, port); - newSrv.usingOmp = await getServerOmpStatus(ip, port); - const ping = await getServerPing(ip, port); - newSrv.ping = ping == 0 ? server.ping : ping; +const getServerInfo = async (ip: string, port: number, listType: ListType) => { + try { + const serverInfo = await invoke("request_server_info", { + ip: ip, + port: port, + }); + + if (serverInfo === "no_data") { + return console.log( + "[query.ts: getServerInfo]", + "There was a problem getting server main info" + ); + } - return resolve(newSrv); - } catch (error) { - reject(error); + let queryObj = JSON.parse(serverInfo); + const data = { + hasPassword: queryObj.password, + playerCount: queryObj.players, + maxPlayers: queryObj.max_players, + hostname: queryObj.hostname, + gameMode: queryObj.gamemode, + language: queryObj.language, + }; + + let server = getServerFromList(ip, port, listType); + if (server) { + server = { ...server, ...data }; + + updateServerEveryWhere(server); } - }); + } catch (e) { + console.log("[query.ts: getServerInfo]", e); + } }; -const getServerInfo = async (ip: string, port: number) => { - const serverInfo = await invoke("request_server_info", { - ip: ip, - port: port, - }); +const getServerPlayers = async ( + ip: string, + port: number, + listType: ListType +) => { + try { + const serverPlayers = await invoke("request_server_players", { + ip: ip, + port: port, + }); + + if (serverPlayers === "no_data") { + return console.log( + "[query.ts: getServerPlayers]", + "There was a problem getting server player list" + ); + } + + let server = getServerFromList(ip, port, listType); - if (serverInfo === "no_data") { - throw new Error("[Query] There was a problem getting server main info"); - } + if (server) { + let queryObj = JSON.parse(serverPlayers); - let queryObj = JSON.parse(serverInfo); - const server = { - hasPassword: queryObj.password, - playerCount: queryObj.players, - maxPlayers: queryObj.max_players, - hostname: queryObj.hostname, - gameMode: queryObj.gamemode, - language: queryObj.language, - }; - - return server; + if (queryObj.error) { + server = { ...server }; + updateServerEveryWhere(server); + } else if (Array.isArray(queryObj)) { + server = { ...server, players: [...queryObj] }; + updateServerEveryWhere(server); + } + } + } catch (e) { + console.log("[query.ts: getServerPlayers]", e); + } }; -const getServerPlayers = async (ip: string, port: number) => { - const serverPlayers = await invoke("request_server_players", { - ip: ip, - port: port, - }); +const getServerRules = async (ip: string, port: number, listType: ListType) => { + try { + const serverRules = await invoke("request_server_rules", { + ip: ip, + port: port, + }); + + if (serverRules === "no_data" || !Array.isArray(JSON.parse(serverRules))) { + return console.log( + "[query.ts: getServerRules]", + "There was a problem getting server rule list" + ); + } - if (serverPlayers === "no_data") { - throw new Error("[Query] There was a problem getting server player list"); - } + let server = getServerFromList(ip, port, listType); - let queryObj = JSON.parse(serverPlayers); - if (queryObj.error) { - return false; - } else if (Array.isArray(queryObj)) { - const players: Player[] = [...queryObj]; - return players; - } - return []; -}; + if (server) { + let queryObj = JSON.parse(serverRules); + const rules: Server["rules"] = {} as Server["rules"]; -const getServerRules = async (ip: string, port: number) => { - const serverRules = await invoke("request_server_rules", { - ip: ip, - port: port, - }); + queryObj.forEach((rule: [string, string]) => { + rules[rule[0]] = rule[1]; + }); - if (serverRules === "no_data" || !Array.isArray(JSON.parse(serverRules))) { - throw new Error("[Query] There was a problem getting server rule list"); + server = { ...server, rules: rules }; + updateServerEveryWhere(server); + } + } catch (e) { + console.log("[query.ts: getServerRules]", e); } +}; - let queryObj = JSON.parse(serverRules); - const rules: Server["rules"] = {} as Server["rules"]; +const getServerOmpStatus = async ( + ip: string, + port: number, + listType: ListType +) => { + try { + const serverOmpStatus = await invoke("request_server_is_omp", { + ip: ip, + port: port, + }); + + let server = getServerFromList(ip, port, listType); + if (server) { + if ( + serverOmpStatus === "no_data" || + JSON.parse(serverOmpStatus).isOmp == undefined + ) { + server = { ...server, usingOmp: false }; + updateServerEveryWhere(server); + return; + } - queryObj.forEach((rule: [string, string]) => { - rules[rule[0]] = rule[1]; - }); + server = { + ...server, + usingOmp: JSON.parse(serverOmpStatus).isOmp as boolean, + }; + updateServerEveryWhere(server); + } + } catch (e) {} +}; + +const getServerPing = async (ip: string, port: number, listType: ListType) => { + try { + const serverPing = await invoke("ping_server", { + ip: ip, + port: port, + }); + + let server = getServerFromList(ip, port, listType); + if (server) { + let ping = server.ping; + + if (typeof serverPing === "number") { + if (serverPing !== 9999) { + ping = serverPing; + } else { + if (server.ping === 0) { + ping = serverPing; + } + } + } - return rules; + server = { + ...server, + ping: ping, + }; + updateServerEveryWhere(server); + } + } catch (e) {} }; -const getServerOmpStatus = async (ip: string, port: number) => { - const serverOmpStatus = await invoke("request_server_is_omp", { - ip: ip, - port: port, - }); - - if ( - serverOmpStatus === "no_data" || - JSON.parse(serverOmpStatus).isOmp == undefined - ) { - return false; - } +const getListBasedOnType = (listType: ListType) => { + const { servers } = useServers.getState(); + const { favorites, recentlyJoined } = usePersistentServers.getState(); - return JSON.parse(serverOmpStatus).isOmp as boolean; + if (listType === "internet" || listType === "partners") return servers; + else if (listType === "favorites") return favorites; + else if (listType === "recentlyjoined") return recentlyJoined; + else return servers; }; -const getServerPing = async (ip: string, port: number) => { - const serverPing = await invoke("ping_server", { - ip: ip, - port: port, - }); +const getServerFromList = (ip: string, port: number, listType: ListType) => { + const list = getListBasedOnType(listType); + return list.find((server) => server.ip === ip && server.port === port); +}; - if (typeof serverPing !== "number") { - return 0; - } +const updateServerEveryWhere = (server: Server) => { + const { updateServer, selected, setSelected } = useServers.getState(); + const { updateInFavoritesList, updateInRecentlyJoinedList } = + usePersistentServers.getState(); - return serverPing; + updateServer(server); + updateInFavoritesList(server); + updateInRecentlyJoinedList(server); + + if (selected) { + if (server.ip == selected.ip && server.port == selected.port) { + setSelected(server); + } + } };