diff --git a/.github/workflows/buildnup.yml b/.github/workflows/buildnup.yml deleted file mode 100644 index ae884b4..0000000 --- a/.github/workflows/buildnup.yml +++ /dev/null @@ -1,46 +0,0 @@ -name: Build & Upload Launcher - -on: - push: - branches: [ "main", "next" ] - paths: [ "src/**" ] - - pull_request: - branches: [ "main", "next" ] - paths: [ "src/**" ] - - workflow_dispatch: - -env: - CARGO_TERM_COLOR: always - -jobs: - build_and_upload: - runs-on: ubuntu-latest - - container: - image: ubuntu:devel - env: - DEBIAN_FRONTEND: noninteractive - - steps: - - name: Install Deps - run: | - apt update - apt install -y libgtk-4-1 libgtk-4-dev libadwaita-1-0 libadwaita-1-dev git curl openssl libssl-dev - - - uses: dtolnay/rust-toolchain@stable - - - name: Checkout - uses: actions/checkout@v3 - with: - submodules: recursive - - - name: Build - run: cargo build --release --verbose - - - name: Upload a Build Artifact - uses: actions/upload-artifact@v3.1.0 - with: - name: Launcher - path: target/release/anime-game-launcher diff --git a/.github/workflows/check_source_code.yml b/.github/workflows/check_source_code.yml new file mode 100644 index 0000000..a72d2ae --- /dev/null +++ b/.github/workflows/check_source_code.yml @@ -0,0 +1,40 @@ +name: Check source code + +on: + push: + branches: [ "next" ] + paths: [ "src/**" ] + + pull_request: + branches: [ "main", "next" ] + paths: [ "src/**" ] + + workflow_dispatch: + +env: + CARGO_TERM_COLOR: always + +jobs: + check_source_code: + runs-on: ubuntu-latest + + container: + image: ubuntu:devel + env: + DEBIAN_FRONTEND: noninteractive + + steps: + - name: Install dependencies + run: | + apt update + apt install -y libgtk-4-dev libadwaita-1-dev git curl + + - uses: dtolnay/rust-toolchain@stable + with: + toolchain: stable + + - name: Checkout + uses: actions/checkout@v3 + + - name: Check source code + run: cargo check --verbose \ No newline at end of file diff --git a/.github/workflows/target-branch.yml b/.github/workflows/check_target_branch.yml similarity index 96% rename from .github/workflows/target-branch.yml rename to .github/workflows/check_target_branch.yml index 952f4e6..255f1bc 100644 --- a/.github/workflows/target-branch.yml +++ b/.github/workflows/check_target_branch.yml @@ -6,7 +6,7 @@ on: types: [opened, edited] jobs: - check-branch: + check_target_branch: runs-on: ubuntu-latest steps: - uses: Vankka/pr-target-branch-action@v2 diff --git a/.github/workflows/compile_release_build.yml b/.github/workflows/compile_release_build.yml new file mode 100644 index 0000000..295a1b8 --- /dev/null +++ b/.github/workflows/compile_release_build.yml @@ -0,0 +1,45 @@ +name: Compile release build + +on: + push: + branches: [ "main" ] + paths: [ "src/**" ] + + release: + types: [published] + + workflow_dispatch: + +env: + CARGO_TERM_COLOR: always + +jobs: + build_and_upload: + runs-on: ubuntu-latest + + container: + image: ubuntu:devel + env: + DEBIAN_FRONTEND: noninteractive + + steps: + - name: Install dependencies + run: | + apt update + apt install -y libgtk-4-dev libadwaita-1-dev git curl + + - uses: dtolnay/rust-toolchain@stable + with: + toolchain: stable + + - name: Checkout + uses: actions/checkout@v3 + + - name: Compile release build + run: cargo build --release --verbose + + - name: Upload artifact + uses: actions/upload-artifact@v3.1.0 + with: + name: Release build + path: target/release/anime-game-launcher \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 9318aef..32893aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- Added new gamescope version compatibility +- Added "launcher behavior" option +- Added "kill game process" button when chosen behavior keeps launcher window open +- Bundled some icons into the app for consistency across the systems +- Added better panics handler + +### Fixed + +- Fixed predownload button sensitivity + +### Changed + +- Improved pre-downloads state checking +- Replaced translation functions by `tr!` macro +- Reworked app resources structure +- Improved game running status check (wasn't working properly with Chinese client) + ## [3.7.6] - 15.07.2023 ### Fixed diff --git a/Cargo.lock b/Cargo.lock index 4f99b3f..44fda3f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -39,8 +39,8 @@ dependencies = [ [[package]] name = "anime-game-core" -version = "1.13.2" -source = "git+https://github.com/an-anime-team/anime-game-core?tag=1.13.2#a15b8162adcefcc9d99eacbd55ae5cfe1e1fddfe" +version = "1.13.5" +source = "git+https://github.com/an-anime-team/anime-game-core?tag=1.13.5#11e48e47563acf97a6885d3cc369875031dc5f61" dependencies = [ "anyhow", "bzip2", @@ -72,6 +72,7 @@ dependencies = [ "fluent-templates", "glib-build-tools", "gtk4", + "human-panic", "lazy_static", "libadwaita", "md-5", @@ -87,8 +88,8 @@ dependencies = [ [[package]] name = "anime-launcher-sdk" -version = "1.8.6" -source = "git+https://github.com/an-anime-team/anime-launcher-sdk?tag=1.8.6#2740eae5b5832b371e2a2919e33c0decfbe6b8a1" +version = "1.8.13" +source = "git+https://github.com/an-anime-team/anime-launcher-sdk?tag=1.8.13#1669dceafce3eaa3e9332fb4ac6ff78ea9fb1639" dependencies = [ "anime-game-core", "anyhow", @@ -104,10 +105,59 @@ dependencies = [ ] [[package]] -name = "anyhow" -version = "1.0.71" +name = "anstream" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" +checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is-terminal", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd" + +[[package]] +name = "anstyle-parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" +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", +] + +[[package]] +name = "anstyle-wincon" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" +dependencies = [ + "anstyle", + "windows-sys", +] + +[[package]] +name = "anyhow" +version = "1.0.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854" dependencies = [ "backtrace", ] @@ -166,7 +216,7 @@ dependencies = [ "async-lock", "async-task", "concurrent-queue", - "fastrand", + "fastrand 1.9.0", "futures-lite", "slab", ] @@ -212,7 +262,7 @@ dependencies = [ "log", "parking", "polling", - "rustix", + "rustix 0.37.23", "slab", "socket2 0.4.9", "waker-fn", @@ -240,7 +290,7 @@ dependencies = [ "cfg-if", "event-listener", "futures-lite", - "rustix", + "rustix 0.37.23", "signal-hook", "windows-sys", ] @@ -253,7 +303,7 @@ checksum = "0e97ce7de6cf12de5d7226c73f5ba9811622f4db3a5b91b55c53e987e5f91cba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.28", ] [[package]] @@ -290,13 +340,13 @@ checksum = "ecc7ab41815b3c653ccd2978ec3255c81349336702dfdf62ee6f7069b12a3aae" [[package]] name = "async-trait" -version = "0.1.71" +version = "0.1.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a564d521dd56509c4c47480d00b80ee55f7e385ae48db5744c67ad50c92d2ebf" +checksum = "cc6dde6e4ed435a4c1ee4e73592f5ba9da2151af10076cc04858746af9352d09" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.28", ] [[package]] @@ -350,6 +400,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" + [[package]] name = "block" version = "0.1.6" @@ -375,7 +431,7 @@ dependencies = [ "async-lock", "async-task", "atomic-waker", - "fastrand", + "fastrand 1.9.0", "futures-lite", "log", ] @@ -465,7 +521,7 @@ version = "0.17.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab3603c4028a5e368d09b51c8b624b9a46edcd7c3778284077a6125af73c9f0a" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cairo-sys-rs", "glib", "libc", @@ -495,9 +551,9 @@ dependencies = [ [[package]] name = "cfg-expr" -version = "0.15.3" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "215c0072ecc28f92eeb0eea38ba63ddfcb65c2828c46311d646f1a3ff5f9841c" +checksum = "b40ccee03b5175c18cde8f37e7d2a33bcef6f8ec8f7cc0d81090d1bb380949c9" dependencies = [ "smallvec", "target-lexicon", @@ -519,6 +575,12 @@ dependencies = [ "inout", ] +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + [[package]] name = "concurrent-queue" version = "2.2.0" @@ -656,6 +718,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "deranged" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8810e7e2cf385b1e9b50d68264908ec367ba642c96d02edfe61c39e88e2a3c01" + [[package]] name = "derivative" version = "2.2.0" @@ -687,7 +755,7 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "uuid", + "uuid 0.8.2", ] [[package]] @@ -704,7 +772,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.28", ] [[package]] @@ -727,9 +795,9 @@ checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" [[package]] name = "either" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "enum-ordinalize" @@ -741,7 +809,7 @@ dependencies = [ "num-traits", "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.28", ] [[package]] @@ -762,7 +830,7 @@ checksum = "5e9a1f9f7d83e59740248a6e14ecf93929ade55027844dfcea78beafccc15745" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.28", ] [[package]] @@ -773,9 +841,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" dependencies = [ "errno-dragonfly", "libc", @@ -807,6 +875,12 @@ dependencies = [ "instant", ] +[[package]] +name = "fastrand" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" + [[package]] name = "field-offset" version = "0.3.6" @@ -1016,7 +1090,7 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" dependencies = [ - "fastrand", + "fastrand 1.9.0", "futures-core", "futures-io", "memchr", @@ -1033,7 +1107,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.28", ] [[package]] @@ -1072,7 +1146,7 @@ version = "0.17.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "695d6bc846438c5708b07007537b9274d883373dd30858ca881d7d71b5540717" dependencies = [ - "bitflags", + "bitflags 1.3.2", "gdk-pixbuf-sys", "gio", "glib", @@ -1099,7 +1173,7 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3abf96408a26e3eddf881a7f893a1e111767137136e347745e8ea6ed12731ff" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cairo-rs", "gdk-pixbuf", "gdk4-sys", @@ -1161,7 +1235,7 @@ version = "0.17.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6973e92937cf98689b6a054a9e56c657ed4ff76de925e36fc331a15f0c5d30a" dependencies = [ - "bitflags", + "bitflags 1.3.2", "futures-channel", "futures-core", "futures-io", @@ -1194,7 +1268,7 @@ version = "0.17.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3fad45ba8d4d2cea612b432717e834f48031cd8853c8aaf43b2c79fec8d144b" dependencies = [ - "bitflags", + "bitflags 1.3.2", "futures-channel", "futures-core", "futures-executor", @@ -1244,9 +1318,9 @@ dependencies = [ [[package]] name = "globset" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1391ab1f92ffcc08911957149833e682aa3fe252b9f45f966d2ef972274c97df" +checksum = "aca8bbd8e0707c1887a8bbb7e6b40e228f251ff5d62c8220a4a7a53c73aff006" dependencies = [ "aho-corasick", "bstr", @@ -1307,7 +1381,7 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f01ef44fa7cac15e2da9978529383e6bee03e570ba5bf7036b4c10a15cc3a3c" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cairo-rs", "gdk4", "glib", @@ -1339,7 +1413,7 @@ version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b28a32a04cd75cef14a0983f8b0c669e0fe152a0a7725accdeb594e2c764c88b" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cairo-rs", "field-offset", "futures-channel", @@ -1428,6 +1502,22 @@ dependencies = [ "digest", ] +[[package]] +name = "human-panic" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38a841f87949b0dd751864e769a870be79dc34abcee1cf31d737a61d498b22b6" +dependencies = [ + "anstream", + "anstyle", + "backtrace", + "os_info", + "serde", + "serde_derive", + "toml", + "uuid 1.4.1", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -1528,6 +1618,17 @@ dependencies = [ "once_cell", ] +[[package]] +name = "is-terminal" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +dependencies = [ + "hermit-abi", + "rustix 0.38.4", + "windows-sys", +] + [[package]] name = "is-wsl" version = "0.4.0" @@ -1540,9 +1641,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b02a5381cc465bd3041d84623d0fa3b66738b52b8e2fc3bab8ad63ab032f4a" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "jobserver" @@ -1589,7 +1690,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ab9c0843f9f23ff25634df2743690c3a1faffe0a190e60c490878517eb81abf" dependencies = [ - "bitflags", + "bitflags 1.3.2", "gdk-pixbuf", "gdk4", "gio", @@ -1628,6 +1729,12 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" +[[package]] +name = "linux-raw-sys" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" + [[package]] name = "lock_api" version = "0.4.10" @@ -1751,7 +1858,7 @@ version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cfg-if", "libc", "memoffset 0.7.1", @@ -1800,9 +1907,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" dependencies = [ "autocfg", ] @@ -1888,6 +1995,17 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "os_info" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "006e42d5b888366f1880eda20371fedde764ed2213dc8496f49622fa0c99cd5e" +dependencies = [ + "log", + "serde", + "winapi", +] + [[package]] name = "overload" version = "0.1.1" @@ -1900,7 +2018,7 @@ version = "0.17.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35be456fc620e61f62dff7ff70fbd54dcbaf0a4b920c0f16de1107c47d921d48" dependencies = [ - "bitflags", + "bitflags 1.3.2", "gio", "glib", "libc", @@ -2001,7 +2119,7 @@ checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.28", ] [[package]] @@ -2029,7 +2147,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" dependencies = [ "autocfg", - "bitflags", + "bitflags 1.3.2", "cfg-if", "concurrent-queue", "libc", @@ -2092,18 +2210,18 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.64" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78803b62cbf1f46fde80d7c0e803111524b9877184cfe7c3033659490ac7a7da" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.29" +version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" +checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" dependencies = [ "proc-macro2", ] @@ -2172,7 +2290,7 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -2181,7 +2299,7 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -2198,9 +2316,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310" +checksum = "b7b6d6190b7594385f61bd3911cd1be99dfddcfc365a4160cc2ab5bff4aed294" dependencies = [ "aho-corasick", "memchr", @@ -2239,7 +2357,7 @@ checksum = "848a6e1b4954b7aa8155d4a234516d46ed543a614666adc1ea73a922bc841e2a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.28", ] [[package]] @@ -2309,11 +2427,24 @@ version = "0.37.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" dependencies = [ - "bitflags", + "bitflags 1.3.2", "errno", "io-lifetimes", "libc", - "linux-raw-sys", + "linux-raw-sys 0.3.8", + "windows-sys", +] + +[[package]] +name = "rustix" +version = "0.38.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a962918ea88d644592894bc6dc55acc6c0956488adcebbfb6e273506b7fd6e5" +dependencies = [ + "bitflags 2.3.3", + "errno", + "libc", + "linux-raw-sys 0.4.3", "windows-sys", ] @@ -2352,9 +2483,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe232bdf6be8c8de797b22184ee71118d63780ea42ac85b61d1baa6d3b782ae9" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" [[package]] name = "same-file" @@ -2376,9 +2507,9 @@ dependencies = [ [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sct" @@ -2392,11 +2523,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.9.1" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation", "core-foundation-sys", "libc", @@ -2405,9 +2536,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" dependencies = [ "core-foundation-sys", "libc", @@ -2421,35 +2552,35 @@ checksum = "1ef965a420fe14fdac7dd018862966a4c14094f900e1650bbc71ddd7d580c8af" [[package]] name = "semver" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" +checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" [[package]] name = "serde" -version = "1.0.171" +version = "1.0.179" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30e27d1e4fd7659406c492fd6cfaf2066ba8773de45ca75e855590f856dc34a9" +checksum = "0a5bf42b8d227d4abf38a1ddb08602e229108a517cd4e5bb28f9c7eaafdce5c0" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.171" +version = "1.0.179" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389894603bd18c46fa56231694f8d827779c0951a667087194cf9de94ed24682" +checksum = "741e124f5485c7e60c03b043f79f320bff3527f4bbf12cf3831750dc46a0ec2c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.28", ] [[package]] name = "serde_json" -version = "1.0.102" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5062a995d481b2308b6064e9af76011f2921c35f97b0468811ed9f6cd91dfed" +checksum = "076066c5f1078eac5b722a31827a8832fe108bed65dfa75e233c89f8206e976c" dependencies = [ "itoa", "ryu", @@ -2458,13 +2589,13 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.14" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d89a8107374290037607734c0b73a85db7ed80cae314b3c5791f192a496e731" +checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.28", ] [[package]] @@ -2509,9 +2640,9 @@ dependencies = [ [[package]] name = "signal-hook" -version = "0.3.15" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "732768f1176d21d09e076c23a93123d40bba92d50c4058da34d45c8de8e682b9" +checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" dependencies = [ "libc", "signal-hook-registry", @@ -2629,9 +2760,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.25" +version = "2.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15e3fc8c0c74267e2df136e5e5fb656a464158aa57624053375eb9c8c6e25ae2" +checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567" dependencies = [ "proc-macro2", "quote", @@ -2640,9 +2771,9 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.29.4" +version = "0.29.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "751e810399bba86e9326f5762b7f32ac5a085542df78da6a78d94e07d14d7c11" +checksum = "165d6d8539689e3d3bc8b98ac59541e1f21c7de7c85d60dc80e43ae0ed2113db" dependencies = [ "cfg-if", "core-foundation-sys", @@ -2679,42 +2810,41 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.12.9" +version = "0.12.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df8e77cb757a61f51b947ec4a7e3646efd825b73561db1c232a8ccb639e611a0" +checksum = "1d2faeef5759ab89935255b1a4cd98e0baf99d1085e37d36599c625dac49ae8e" [[package]] name = "tempfile" -version = "3.6.0" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" +checksum = "5486094ee78b2e5038a6382ed7645bc084dc2ec433426ca4c3cb61e2007b8998" dependencies = [ - "autocfg", "cfg-if", - "fastrand", + "fastrand 2.0.0", "redox_syscall 0.3.5", - "rustix", + "rustix 0.38.4", "windows-sys", ] [[package]] name = "thiserror" -version = "1.0.43" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a35fc5b8971143ca348fa6df4f024d4d55264f3468c71ad1c2f365b0a4d58c42" +checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.43" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f" +checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.28", ] [[package]] @@ -2729,10 +2859,11 @@ dependencies = [ [[package]] name = "time" -version = "0.3.23" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59e399c068f43a5d116fedaf73b203fa4f9c519f17e2b34f63221d3792f81446" +checksum = "b79eabcd964882a646b3584543ccabeae7869e9ac32a46f6f22b7a5bd405308b" dependencies = [ + "deranged", "serde", "time-core", ] @@ -2789,7 +2920,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.28", ] [[package]] @@ -2815,9 +2946,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.19.13" +version = "0.19.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f8751d9c1b03c6500c387e96f81f815a4f8e72d142d2d4a9ffa6fedd51ddee7" +checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a" dependencies = [ "indexmap", "serde", @@ -2846,7 +2977,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.28", ] [[package]] @@ -2960,9 +3091,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22049a19f4a68748a168c0fc439f9516686aa045927ff767eca0a85101fb6e73" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" [[package]] name = "unicode-normalization" @@ -2993,9 +3124,15 @@ dependencies = [ [[package]] name = "urlencoding" -version = "2.1.2" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8db7427f936968176eaa7cdf81b7f98b980b18495ec28f1b5791ac3bfe3eea9" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" @@ -3006,6 +3143,15 @@ dependencies = [ "getrandom", ] +[[package]] +name = "uuid" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" +dependencies = [ + "getrandom", +] + [[package]] name = "valuable" version = "0.1.0" @@ -3073,7 +3219,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.28", "wasm-bindgen-shared", ] @@ -3107,7 +3253,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.28", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3328,9 +3474,9 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" [[package]] name = "winnow" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fac9742fd1ad1bd9643b991319f72dd031016d44b77039a26977eb667141e7" +checksum = "8bd122eb777186e60c3fdf765a58ac76e41c582f1f535fbf3314434c6b58f3f7" dependencies = [ "memchr", ] diff --git a/Cargo.toml b/Cargo.toml index b67eaff..45f9d8b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,8 @@ name = "anime-game-launcher" version = "3.7.6" description = "Anime Game launcher" authors = ["Nikita Podvirnyy "] +homepage = "https://github.com/an-anime-team/an-anime-game-launcher" +repository = "https://github.com/an-anime-team/an-anime-game-launcher" license = "GPL-3.0" edition = "2021" build = "build.rs" @@ -17,7 +19,7 @@ glib-build-tools = "0.17" [dependencies.anime-launcher-sdk] git = "https://github.com/an-anime-team/anime-launcher-sdk" -tag = "1.8.6" +tag = "1.8.13" features = ["all", "genshin", "genshin-patch"] # path = "../anime-launcher-sdk" # ! for dev purposes only @@ -42,3 +44,5 @@ tracing-subscriber = "0.3" fluent-templates = "0.8" unic-langid = "0.9" + +human-panic = "1.1.5" diff --git a/assets/images/icons/applications-games-symbolic.svg b/assets/images/icons/applications-games-symbolic.svg new file mode 100644 index 0000000..121a8ee --- /dev/null +++ b/assets/images/icons/applications-games-symbolic.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/images/icons/applications-graphics-symbolic.svg b/assets/images/icons/applications-graphics-symbolic.svg new file mode 100644 index 0000000..e47dfa3 --- /dev/null +++ b/assets/images/icons/applications-graphics-symbolic.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/icons/dialog-information-symbolic.svg b/assets/images/icons/dialog-information-symbolic.svg new file mode 100644 index 0000000..c948d27 --- /dev/null +++ b/assets/images/icons/dialog-information-symbolic.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/images/icons/document-properties-symbolic.svg b/assets/images/icons/document-properties-symbolic.svg new file mode 100644 index 0000000..365c303 --- /dev/null +++ b/assets/images/icons/document-properties-symbolic.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/icons/document-save-symbolic.svg b/assets/images/icons/document-save-symbolic.svg new file mode 100644 index 0000000..9c5584d --- /dev/null +++ b/assets/images/icons/document-save-symbolic.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/icons/emblem-ok-symbolic.svg b/assets/images/icons/emblem-ok-symbolic.svg new file mode 100644 index 0000000..7a9551f --- /dev/null +++ b/assets/images/icons/emblem-ok-symbolic.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/icons/emblem-system-symbolic.svg b/assets/images/icons/emblem-system-symbolic.svg new file mode 100644 index 0000000..c01314d --- /dev/null +++ b/assets/images/icons/emblem-system-symbolic.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/icons/folder-symbolic.svg b/assets/images/icons/folder-symbolic.svg new file mode 100644 index 0000000..9ab3c04 --- /dev/null +++ b/assets/images/icons/folder-symbolic.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/images/icons/go-next-symbolic.svg b/assets/images/icons/go-next-symbolic.svg new file mode 100644 index 0000000..0ff48be --- /dev/null +++ b/assets/images/icons/go-next-symbolic.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/icons/go-previous-symbolic.svg b/assets/images/icons/go-previous-symbolic.svg new file mode 100644 index 0000000..1b7901f --- /dev/null +++ b/assets/images/icons/go-previous-symbolic.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/icons/list-add-symbolic.svg b/assets/images/icons/list-add-symbolic.svg new file mode 100644 index 0000000..cf68622 --- /dev/null +++ b/assets/images/icons/list-add-symbolic.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/icons/media-playback-start-symbolic.svg b/assets/images/icons/media-playback-start-symbolic.svg new file mode 100644 index 0000000..4dcac1b --- /dev/null +++ b/assets/images/icons/media-playback-start-symbolic.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/icons/open-menu-symbolic.svg b/assets/images/icons/open-menu-symbolic.svg new file mode 100644 index 0000000..7f44743 --- /dev/null +++ b/assets/images/icons/open-menu-symbolic.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/assets/images/icons/security-high-symbolic.svg b/assets/images/icons/security-high-symbolic.svg new file mode 100644 index 0000000..b1f6447 --- /dev/null +++ b/assets/images/icons/security-high-symbolic.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/icons/user-trash-symbolic.svg b/assets/images/icons/user-trash-symbolic.svg new file mode 100644 index 0000000..b6f8bd1 --- /dev/null +++ b/assets/images/icons/user-trash-symbolic.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/assets/images/icons/view-refresh-symbolic.svg b/assets/images/icons/view-refresh-symbolic.svg new file mode 100644 index 0000000..3248fe7 --- /dev/null +++ b/assets/images/icons/view-refresh-symbolic.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/icons/violence-symbolic.svg b/assets/images/icons/violence-symbolic.svg new file mode 100644 index 0000000..aa74bdc --- /dev/null +++ b/assets/images/icons/violence-symbolic.svg @@ -0,0 +1,2 @@ + + diff --git a/assets/images/icons/window-close-symbolic.svg b/assets/images/icons/window-close-symbolic.svg new file mode 100644 index 0000000..f68a861 --- /dev/null +++ b/assets/images/icons/window-close-symbolic.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/locales/de/errors.ftl b/assets/locales/de/errors.ftl index ab6dbd5..3087b9d 100644 --- a/assets/locales/de/errors.ftl +++ b/assets/locales/de/errors.ftl @@ -13,6 +13,8 @@ failed-get-selected-wine = Die ausgewählte Wine-Version konnte nicht abgerufen downloading-failed = Herunterladen fehlgeschlagen unpacking-failed = Entpacken fehlgeschlagen +kill-game-process-failed = Die Spielprozesse konnten nicht terminiert werden + game-file-repairing-error = Reparieren der Spieldatei fehlgeschlagen integrity-files-getting-error = Integritätsdateien konnten nicht abgerufen werden diff --git a/assets/locales/de/general.ftl b/assets/locales/de/general.ftl index ff29fde..51caa2f 100644 --- a/assets/locales/de/general.ftl +++ b/assets/locales/de/general.ftl @@ -58,6 +58,9 @@ disable-mhypbase-description = Experimentell. Wenn sie diese option aktivieren, ask-superuser-permissions = Superuser-Berechtigungen anfordern ask-superuser-permissions-description = Launcher benötigt Superuser-Zugriff, um Ihre Hosts-Datei automatisch zu aktualisieren. Dies ist in der Flatpak-Edition nicht erforderlich +launcher-behavior = Launcherverhalten +launcher-behavior-description = Was soll der Launcher tun, wenn das Spiel gestartet ist + wine-tools = Wine-Tools command-line = Befehlszeile registry-editor = Registrierungs-Editor diff --git a/assets/locales/de/main.ftl b/assets/locales/de/main.ftl index 4cd9697..d8e8dfc 100644 --- a/assets/locales/de/main.ftl +++ b/assets/locales/de/main.ftl @@ -18,6 +18,8 @@ about = Über close = Schließen +hide = Verstecken +nothing = Nichts save = Speichern continue = Weiter resume = Fortsetzen @@ -62,6 +64,8 @@ update = Updaten download = Herunterladen predownload-update = Vorab-Update von Version {$version} herunterladen ({$size}) +kill-game-process = Spielprozesse terminieren + main-window--patch-unavailable-tooltip = Die Patch-Server sind nicht verfügbar und der Launcher kann den Patch-Status des Spiels nicht überprüfen. Sie können das Spiel auf eigene Gefahr spielen. main-window--patch-outdated-tooltip = Der Patch ist veraltet oder befindet sich in Vorbereitung und kann daher nicht verwendet werden. Kehren Sie später zurück, um den Status zu sehen. main-window--version-outdated-tooltip = Die Version ist zu veraltet und kann nicht aktualisiert werden diff --git a/assets/locales/en/errors.ftl b/assets/locales/en/errors.ftl index 6bfe318..385fe6f 100644 --- a/assets/locales/en/errors.ftl +++ b/assets/locales/en/errors.ftl @@ -13,6 +13,8 @@ failed-get-selected-wine = Failed to get selected wine version downloading-failed = Downloading failed unpacking-failed = Unpacking failed +kill-game-process-failed = Failed to kill the game's process + game-file-repairing-error = Failed to repair game file integrity-files-getting-error = Failed to get integrity files diff --git a/assets/locales/en/general.ftl b/assets/locales/en/general.ftl index eb27de3..c9b70c7 100644 --- a/assets/locales/en/general.ftl +++ b/assets/locales/en/general.ftl @@ -58,6 +58,9 @@ disable-mhypbase-description = Experimental. If enabled, launcher will disable m ask-superuser-permissions = Ask superuser permissions ask-superuser-permissions-description = Launcher will use them to automatically update your hosts file. This is not needed in flatpak edition +launcher-behavior = Launcher behavior +launcher-behavior-description = What should launcher window do when it starts the game + wine-tools = Wine tools command-line = Command line registry-editor = Registry editor diff --git a/assets/locales/en/main.ftl b/assets/locales/en/main.ftl index b8f89e6..f9ebbc4 100644 --- a/assets/locales/en/main.ftl +++ b/assets/locales/en/main.ftl @@ -18,6 +18,8 @@ about = About close = Close +hide = Hide +nothing = Nothing save = Save continue = Continue resume = Resume @@ -62,6 +64,8 @@ update = Update download = Download predownload-update = Pre-download {$version} update ({$size}) +kill-game-process = Kill game process + main-window--patch-unavailable-tooltip = Patch servers are unavailable and launcher can't verify the game's patching status. You're allowed to run the game on your own risk main-window--patch-outdated-tooltip = Patch is outdated or in preparation state, so unavailable for usage. Return back later to see its status main-window--version-outdated-tooltip = Version is too outdated and can't be updated diff --git a/assets/locales/es/errors.ftl b/assets/locales/es/errors.ftl index ad50829..455bff9 100644 --- a/assets/locales/es/errors.ftl +++ b/assets/locales/es/errors.ftl @@ -13,6 +13,8 @@ failed-get-selected-wine = Fallo al buscar la versión elegida de Wine downloading-failed = Descarga fallida unpacking-failed = Descompresión fallida +kill-game-process-failed = Failed to kill the game's process + game-file-repairing-error = Fallo al reparar archivo del juego integrity-files-getting-error = Fallo al buscar archivos de integridad diff --git a/assets/locales/es/general.ftl b/assets/locales/es/general.ftl index 9eb8de6..4660471 100644 --- a/assets/locales/es/general.ftl +++ b/assets/locales/es/general.ftl @@ -58,6 +58,9 @@ disable-mhypbase-description = Experimental. Si se activa, el launcher desactiva ask-superuser-permissions = Pedir permisos de superusuario ask-superuser-permissions-description = El launcher usará los permisos para actualizar automáticamente tu archivo hosts. Esto no es necesario en la versión de Flatpak +launcher-behavior = Launcher behavior +launcher-behavior-description = What should launcher window do when it starts the game + wine-tools = Herramientas de Wine command-line = Línea de Comandos registry-editor = Editor del Registro diff --git a/assets/locales/es/main.ftl b/assets/locales/es/main.ftl index 3b90ed5..97d1e39 100644 --- a/assets/locales/es/main.ftl +++ b/assets/locales/es/main.ftl @@ -18,6 +18,8 @@ about = Acerca de close = Cerrar +hide = Hide +nothing = Nothing save = Guardar continue = Continuar resume = Reanudar @@ -62,6 +64,8 @@ update = Actualizar download = Descargar predownload-update = Pre-descargar actualización {$version} ({$size}) +kill-game-process = Kill game process + main-window--patch-unavailable-tooltip = Los servidores del parche no están disponibles y el launcher no puede verificar el estado de parcheo del juego. Puedes ejecutar el juego bajo tu propio riesgo. main-window--patch-outdated-tooltip = El parche está desactualizado o en fase de preparación, por lo que no está disponible para usarse. Vuelve pronto para comprobar su estado. main-window--version-outdated-tooltip = La versión es demasiado vieja y no puede actualizarse. diff --git a/assets/locales/fr/errors.ftl b/assets/locales/fr/errors.ftl index 07f391c..c6df558 100644 --- a/assets/locales/fr/errors.ftl +++ b/assets/locales/fr/errors.ftl @@ -13,6 +13,8 @@ failed-get-selected-wine = Impossible de récupérer la version de wine sélecti downloading-failed = Le téléchargement a échoué unpacking-failed = L'extraction a échoué +kill-game-process-failed = Failed to kill the game's process + game-file-repairing-error = Impossible de réparer les fichiers du jeu integrity-files-getting-error = Impossible de récupérer les fichiers d'intégrité du jeu diff --git a/assets/locales/fr/general.ftl b/assets/locales/fr/general.ftl index 482f7d0..2b4e36b 100644 --- a/assets/locales/fr/general.ftl +++ b/assets/locales/fr/general.ftl @@ -58,6 +58,9 @@ disable-mhypbase-description = Experimental. If enabled, launcher will disable m ask-superuser-permissions = Ask superuser permissions ask-superuser-permissions-description = Launcher will use them to automatically update your hosts file. This is not needed in flatpak edition +launcher-behavior = Launcher behavior +launcher-behavior-description = What should launcher window do when it starts the game + wine-tools = Wine tools command-line = Command line registry-editor = Registry editor diff --git a/assets/locales/fr/main.ftl b/assets/locales/fr/main.ftl index 82b85b7..cd0d800 100644 --- a/assets/locales/fr/main.ftl +++ b/assets/locales/fr/main.ftl @@ -18,6 +18,8 @@ about = À propos close = Fermer +hide = Hide +nothing = Nothing save = Sauvegarder continue = Continuer resume = Reprendre @@ -62,6 +64,8 @@ update = Mettre à jour download = Télécharger predownload-update = Pré-télécharger la mise à jour {$version} ({$size}) +kill-game-process = Kill game process + main-window--patch-unavailable-tooltip = Les serveurs de patch ne sont pas disponible, et le launcher ne peut pas vérifier l'état de patch du jeu. Lancez le jeu à vos risques et périls main-window--patch-outdated-tooltip = Le patch n'est pas à jour ou encore en train d'être préparé. Il n'est donc pas encore disponible. Revenez plus tard pour voir son état main-window--version-outdated-tooltip = La version du jeu est trop ancienne et ne peut pas être mise à jour diff --git a/assets/locales/hu/errors.ftl b/assets/locales/hu/errors.ftl index b18217d..59ac642 100644 --- a/assets/locales/hu/errors.ftl +++ b/assets/locales/hu/errors.ftl @@ -13,6 +13,8 @@ failed-get-selected-wine = Kiválasztott wine verzió beszerzése sikertelen downloading-failed = Sikertelen letöltés unpacking-failed = Sikertelen kicsomagolás +kill-game-process-failed = Failed to kill the game's process + game-file-repairing-error = Nem sikerült a játékfájlok javítása integrity-files-getting-error = Integritásfájlok beszerzése sikertelen diff --git a/assets/locales/hu/general.ftl b/assets/locales/hu/general.ftl index ff110fb..40b7025 100644 --- a/assets/locales/hu/general.ftl +++ b/assets/locales/hu/general.ftl @@ -58,6 +58,9 @@ disable-mhypbase-description = Tesztelés alatt. Ha bekapcsolod, kikapcsolja a m ask-superuser-permissions = Superuser engedély kérése ask-superuser-permissions-description = A Launcher autómatikusan használni fogja hogy frissítse a hosts fájlodat. A Flatpak verzióhoz nem kell +launcher-behavior = Launcher behavior +launcher-behavior-description = What should launcher window do when it starts the game + wine-tools = Wine eszközök command-line = Parancssor registry-editor = Registry szerksztő diff --git a/assets/locales/hu/main.ftl b/assets/locales/hu/main.ftl index 79ec387..24fd039 100644 --- a/assets/locales/hu/main.ftl +++ b/assets/locales/hu/main.ftl @@ -18,6 +18,8 @@ about = Részletek close = Bezárás +hide = Hide +nothing = Nothing save = Mentés continue = Folytatás resume = Resume @@ -62,6 +64,8 @@ update = Frissítés download = Letöltés predownload-update = {$version} verzió előtöltése ({$size}) +kill-game-process = Kill game process + main-window--patch-unavailable-tooltip = A patch szerverek nem elérhetőek és a launcher nem tudja ellenőrizni a játék patch státuszát. Saját felelősségre futtathatod a játékot main-window--patch-outdated-tooltip = A patch jelenleg nem elérhető mert túl elavult, vagy előkészítés alatt áll. Nézz vissza később main-window--version-outdated-tooltip = Ez a verzió túl elavult és nem lehet frissíteni diff --git a/assets/locales/id/errors.ftl b/assets/locales/id/errors.ftl index 12425c7..4c262ef 100644 --- a/assets/locales/id/errors.ftl +++ b/assets/locales/id/errors.ftl @@ -13,6 +13,8 @@ failed-get-selected-wine = Gagal mendapatkan versi wine yang dipilih downloading-failed = Gagal mengunduh unpacking-failed = Gagal mengekstrak berkas +kill-game-process-failed = Gagal menghentikan paksa proses game + game-file-repairing-error = Gagal memperbaiki file game integrity-files-getting-error = Gagal mendapatkan integritas file diff --git a/assets/locales/id/general.ftl b/assets/locales/id/general.ftl index 79c0433..e127a20 100644 --- a/assets/locales/id/general.ftl +++ b/assets/locales/id/general.ftl @@ -58,6 +58,9 @@ disable-mhypbase-description = Masih dalam pengujicobaan. Jika diaktifkan, launc ask-superuser-permissions = Minta izin dari admin ask-superuser-permissions-description = Launcher akan otomatis memperbarui file hosts Anda. Opsi ini tidak diperlukan jika Anda memakai edisi flatpak +launcher-behavior = Kelakuan launcher +launcher-behavior-description = Apa yang terjadi pada jendela launcher ketika memulai game + wine-tools = Peralatan wine command-line = Command line registry-editor = Editor registry diff --git a/assets/locales/id/main.ftl b/assets/locales/id/main.ftl index 17e3f24..af68365 100644 --- a/assets/locales/id/main.ftl +++ b/assets/locales/id/main.ftl @@ -16,8 +16,17 @@ debug-file = File debug wish-url = Buka wishes about = Tentang +close = { $form -> + [verb] Menutup + *[noun] Tutup +} -close = Tutup +hide = { $form -> + [verb] Sembunyikan + *[noun] Sembunyi +} + +nothing = Tidak berubah save = Simpan continue = Lanjutkan resume = Lanjutkan @@ -62,6 +71,8 @@ update = Perbarui download = Unduh predownload-update = Pra-unduh pembaruan versi {$version} ({$size}) +kill-game-process = Hentikan paksa proses game + main-window--patch-unavailable-tooltip = Server patch tidak tersedia dan launcher tidak bisa memverifikasi status patch game. Anda bisa menjalankan game dengan resiko sendiri main-window--patch-outdated-tooltip = Patch kadaluarsa atau sedang dalam persiapan sehingga tidak tersedia. Kembali lagi nanti untuk melihat status patch main-window--version-outdated-tooltip = Versi terlalu kadaluarsa dan tidak bisa diperbarui diff --git a/assets/locales/it/errors.ftl b/assets/locales/it/errors.ftl index f7a350d..c3dbfb9 100644 --- a/assets/locales/it/errors.ftl +++ b/assets/locales/it/errors.ftl @@ -13,6 +13,8 @@ failed-get-selected-wine = Ottenimento della versione selezionata di wine non ri downloading-failed = Scaricamento non riuscito unpacking-failed = Unpacking non riuscito +kill-game-process-failed = Failed to kill the game's process + game-file-repairing-error = Riparazione del file di gioco non riuscita integrity-files-getting-error = Ottenimento dei file di integrità non riuscito diff --git a/assets/locales/it/general.ftl b/assets/locales/it/general.ftl index fed20bf..fd55ea9 100644 --- a/assets/locales/it/general.ftl +++ b/assets/locales/it/general.ftl @@ -58,6 +58,9 @@ disable-mhypbase-description = Sperimentale. Se abiliata, il launcher disabilite ask-superuser-permissions = Chiedi permessi di amministratore ask-superuser-permissions-description = Il launcher li userà per aggiornare automaticamente il tuo file hosts. Questo non è necessario nell'edizione flatpak +launcher-behavior = Launcher behavior +launcher-behavior-description = What should launcher window do when it starts the game + wine-tools = Strumenti di Wine command-line = Linea di comando registry-editor = Editor del Registro diff --git a/assets/locales/it/main.ftl b/assets/locales/it/main.ftl index fc82c20..384045a 100644 --- a/assets/locales/it/main.ftl +++ b/assets/locales/it/main.ftl @@ -18,6 +18,8 @@ about = Informazioni close = Chiudi +hide = Hide +nothing = Nothing save = Salva continue = Continua resume = Riprendi @@ -62,6 +64,8 @@ update = Aggiorna download = Scarica predownload-update = Prescarica {$version} aggiornamento ({$size}) +kill-game-process = Kill game process + main-window--patch-unavailable-tooltip = I server delle patch non sono disponibili e il launcher non può verificare lo stato del patching del gioco. Hai la possibilità di eseguire il gioco a tuo rischio main-window--patch-outdated-tooltip = La patch non è aggiornata o è in stato di preparazione, quindi non disponibile per l'utilizzo. Torna più tardi per vederne lo stato main-window--version-outdated-tooltip = La versione è troppo vecchia e non può essere aggiornata. diff --git a/assets/locales/ja/errors.ftl b/assets/locales/ja/errors.ftl index 16ba74f..2f509ee 100644 --- a/assets/locales/ja/errors.ftl +++ b/assets/locales/ja/errors.ftl @@ -13,6 +13,8 @@ failed-get-selected-wine = 選択されたwineバージョンを入手できま downloading-failed = ダウンロードに失敗。 unpacking-failed = 展開失敗 +kill-game-process-failed = Failed to kill the game's process + game-file-repairing-error = ゲームファイルの修正に失敗しました。 integrity-files-getting-error = 整合性ファイルの取得に失敗しました diff --git a/assets/locales/ja/general.ftl b/assets/locales/ja/general.ftl index 49c87e6..4afcdbb 100644 --- a/assets/locales/ja/general.ftl +++ b/assets/locales/ja/general.ftl @@ -58,6 +58,9 @@ disable-mhypbase-description = 試験的です。有効にすると、ランチ ask-superuser-permissions = スーパーユーザーを尋ねる。 ask-superuser-permissions-description = あなたのホストのファイルを自動更新するために、 これらを利用します。flatpak版では必要ありません。 +launcher-behavior = Launcher behavior +launcher-behavior-description = What should launcher window do when it starts the game + wine-tools = ワインツール command-line = コマンドライン registry-editor = レジストリエディタ diff --git a/assets/locales/ja/main.ftl b/assets/locales/ja/main.ftl index 1649dd5..711252a 100644 --- a/assets/locales/ja/main.ftl +++ b/assets/locales/ja/main.ftl @@ -18,6 +18,8 @@ about = "An anime Game launcher"について close = 閉じる +hide = Hide +nothing = Nothing save = 保存 continue = 続行 resume = 一時停止 @@ -62,6 +64,8 @@ update = 更新 download = ダウンロード predownload-update = {$version} の早期アップデート({$size}) +kill-game-process = Kill game process + main-window--patch-unavailable-tooltip = パッチサーバーが利用できないため、パッチの状態を確認することができません。リスクを理解した上で実行することができます。 main-window--patch-outdated-tooltip = パッチは期限切れか準備中のため利用できません。しばらく立ってからパッチステータスを確認してください。 main-window--version-outdated-tooltip = バージョンが古すぎるため、更新できませんでした。 diff --git a/assets/locales/ru/errors.ftl b/assets/locales/ru/errors.ftl index 5d1086b..be6f5f4 100644 --- a/assets/locales/ru/errors.ftl +++ b/assets/locales/ru/errors.ftl @@ -13,6 +13,8 @@ failed-get-selected-wine = Не удалось найти выбранную в downloading-failed = Ошибка загрузки unpacking-failed = Ошибка распаковки +kill-game-process-failed = Не удалось убить процесс игры + game-file-repairing-error = Не удалось починить игровой файл integrity-files-getting-error = Не удалось получить верные данные о файлах игры diff --git a/assets/locales/ru/general.ftl b/assets/locales/ru/general.ftl index 3d3575b..552cc4e 100644 --- a/assets/locales/ru/general.ftl +++ b/assets/locales/ru/general.ftl @@ -58,6 +58,9 @@ disable-mhypbase-description = Экспериментально. Когда вк ask-superuser-permissions = Запрашивать права суперпользователя ask-superuser-permissions-description = Лаунчер будет использовать их чтобы автоматически обновлять ваш hosts файл для отключения телеметрии игры. Не требуется при использовании flatpak +launcher-behavior = Поведение лаунчера +launcher-behavior-description = Что должно делать окно лаунчера когда оно запускает игру + wine-tools = Инструменты Wine command-line = Коммандная строка registry-editor = Редактор реестра diff --git a/assets/locales/ru/main.ftl b/assets/locales/ru/main.ftl index e325bd1..f4fef2b 100644 --- a/assets/locales/ru/main.ftl +++ b/assets/locales/ru/main.ftl @@ -17,7 +17,17 @@ wish-url = История молитв about = О программе -close = Закрыть +close = { $form -> + [verb] Закрываться + *[noun] Закрыть +} + +hide = { $form -> + [verb] Скрываться + *[noun] Скрыть +} + +nothing = Ничего save = Сохранить continue = Продолжить resume = Возобновить @@ -68,6 +78,8 @@ update = Обновить download = Установить predownload-update = Предустановить обновление {$version} ({$size}) +kill-game-process = Убить процесс игры + main-window--patch-unavailable-tooltip = Серверы патча недоступны и лаунчер не может проверить статус патча игры. Вам разрешено запустить игру на ваш страх и риск main-window--patch-outdated-tooltip = Патч устарел или находится в процессе разработки, поэтому не может быть применен. Возвращайтесь позже чтобы проверить его статус main-window--version-outdated-tooltip = Версия слишком стара и не может быть обновлена diff --git a/assets/locales/tr/errors.ftl b/assets/locales/tr/errors.ftl index 8a9cff1..4ad1214 100644 --- a/assets/locales/tr/errors.ftl +++ b/assets/locales/tr/errors.ftl @@ -13,6 +13,8 @@ failed-get-selected-wine = Seçilen Wine versiyonunu alma başarısız oldu downloading-failed = İndirme başarısız oldu unpacking-failed = Oyun dosyalarını çıkarma başarısız oldu +kill-game-process-failed = Failed to kill the game's process + game-file-repairing-error = Oyun dosyaları tamir edilemedi integrity-files-getting-error = Dosyaların bütünlüğü kontrol edilemedi diff --git a/assets/locales/tr/general.ftl b/assets/locales/tr/general.ftl index 0228895..c363fff 100644 --- a/assets/locales/tr/general.ftl +++ b/assets/locales/tr/general.ftl @@ -58,6 +58,9 @@ disable-mhypbase-description = Deneysel. Etkinleştirilirse, istemci ana yamayı ask-superuser-permissions = Yönetici izinlerini sor ask-superuser-permissions-description = İstemci yönetici iznini hostunuzun dosyalarını güncellemek için otomatik olarak kullanacaktır. Buna flatpak versiyonunda gerek yoktur +launcher-behavior = Launcher behavior +launcher-behavior-description = What should launcher window do when it starts the game + wine-tools = Wine araçları command-line = Komut istemi registry-editor = Girdi düzenleyicisi diff --git a/assets/locales/tr/main.ftl b/assets/locales/tr/main.ftl index 38e6b18..eaa71ac 100644 --- a/assets/locales/tr/main.ftl +++ b/assets/locales/tr/main.ftl @@ -18,6 +18,8 @@ about = Hakkında close = Kapat +hide = Hide +nothing = Nothing save = Kaydet continue = Devam et resume = Sürdürmek @@ -62,6 +64,8 @@ update = Güncelle download = İndir predownload-update = Güncellemeyi önceden indir{$version} ({$size}) +kill-game-process = Kill game process + main-window--patch-unavailable-tooltip = Yama sunucuları kullanılamıyor ve istemci, oyunun yama durumunu doğrulayamıyor. Oyunu kendi sorumluluğunuzda çalıştırabilirsiniz main-window--patch-outdated-tooltip = Yama güncel değil veya hazırlık aşamasında, bu nedenle kullanım için uygun değil. Durumunu görmek için daha sonra geri dönün main-window--version-outdated-tooltip = Sürüm çok eski ve güncellenemez diff --git a/assets/locales/zh-cn/errors.ftl b/assets/locales/zh-cn/errors.ftl index b39a164..b30b660 100644 --- a/assets/locales/zh-cn/errors.ftl +++ b/assets/locales/zh-cn/errors.ftl @@ -13,6 +13,8 @@ failed-get-selected-wine = 选择 Wine 版本失败 downloading-failed = 下载失败 unpacking-failed = 解压缩失败 +kill-game-process-failed = Failed to kill the game's process + game-file-repairing-error = 修复游戏文件失败 integrity-files-getting-error = 获取一致性文件失败 diff --git a/assets/locales/zh-cn/general.ftl b/assets/locales/zh-cn/general.ftl index 9c7f034..57f933f 100644 --- a/assets/locales/zh-cn/general.ftl +++ b/assets/locales/zh-cn/general.ftl @@ -58,6 +58,9 @@ disable-mhypbase-description = 实验性功能。启用此选项后,启动器 ask-superuser-permissions = 请求超级用户权限 ask-superuser-permissions-description = 启动器需要超级用户权限来修改 hosts 文件。Flatpak 版无需此权限 +launcher-behavior = Launcher behavior +launcher-behavior-description = What should launcher window do when it starts the game + wine-tools = Wine 工具 command-line = 命令行 registry-editor = 注册表编辑器 diff --git a/assets/locales/zh-cn/main.ftl b/assets/locales/zh-cn/main.ftl index a01968a..aac727c 100644 --- a/assets/locales/zh-cn/main.ftl +++ b/assets/locales/zh-cn/main.ftl @@ -18,6 +18,8 @@ about = 关于 close = 关闭 +hide = Hide +nothing = Nothing save = 保存 continue = 继续 resume = 恢复 @@ -62,6 +64,8 @@ update = 更新 download = 下载 predownload-update = 预下载版本更新 {$version} ({$size}) +kill-game-process = Kill game process + main-window--patch-unavailable-tooltip = 补丁服务器不可用,启动器无法验证游戏补丁状态。你可以运行游戏,但是有出问题的风险 main-window--patch-outdated-tooltip = 补丁版本太旧,新版补丁可能还没制作完成,无法使用。请过段时间再回来查看最新状态 main-window--version-outdated-tooltip = 版本太旧,无法更新 diff --git a/assets/resources.xml b/assets/resources.xml index 1ac85ed..362d796 100644 --- a/assets/resources.xml +++ b/assets/resources.xml @@ -1,12 +1,37 @@ - - images/icon.png + + images/modern.svg + images/classic.svg - - images/modern.svg + + + images/icon.png - - images/classic.svg + + + + + images/icons/document-save-symbolic.svg + images/icons/folder-symbolic.svg + images/icons/emblem-ok-symbolic.svg + images/icons/open-menu-symbolic.svg + images/icons/media-playback-start-symbolic.svg + images/icons/window-close-symbolic.svg + images/icons/security-high-symbolic.svg + images/icons/emblem-system-symbolic.svg + images/icons/user-trash-symbolic.svg + images/icons/go-previous-symbolic.svg + images/icons/document-properties-symbolic.svg + images/icons/list-add-symbolic.svg + images/icons/view-refresh-symbolic.svg + images/icons/applications-games-symbolic.svg + images/icons/applications-graphics-symbolic.svg + images/icons/go-next-symbolic.svg + images/icons/dialog-information-symbolic.svg + + + + images/icons/violence-symbolic.svg \ No newline at end of file diff --git a/fluentscan.py b/fluentscan.py index 0affc2f..8558b8d 100755 --- a/fluentscan.py +++ b/fluentscan.py @@ -148,9 +148,9 @@ for filename in os.listdir("assets/locales/en"): # FIXME: it only indexes the first match for line in script.read().split("\n"): if ("tr(\"" in line) and ("#" not in line): - index = line.find('tr("') + index = line.find('tr!("') indexLast = line.find('")',index) - var_name = re.sub('[^\\w-]+', '', line[index:indexLast].replace('tr("', '').replace("Some", "")) + var_name = re.sub('[^\\w-]+', '', line[index:indexLast].replace('tr!("', '').replace("Some", "")) script_entries[var_name] = [script.name, get_line_num(script, var_name)] diff --git a/src/i18n.rs b/src/i18n.rs index e22af8c..45ca93f 100644 --- a/src/i18n.rs +++ b/src/i18n.rs @@ -1,8 +1,7 @@ -use fluent_templates::Loader; use unic_langid::{langid, LanguageIdentifier}; fluent_templates::static_loader! { - static LOCALES = { + pub static LOCALES = { locales: "./assets/locales", core_locales: "./assets/locales/common.ftl", fallback_language: "en" @@ -24,7 +23,7 @@ pub const SUPPORTED_LANGUAGES: &[LanguageIdentifier] = &[ langid!("hu-hu") ]; -static mut LANG: LanguageIdentifier = langid!("en-us"); +pub static mut LANG: LanguageIdentifier = langid!("en-us"); /// Set launcher language pub fn set_lang(lang: LanguageIdentifier) -> anyhow::Result<()> { @@ -75,36 +74,53 @@ pub fn format_lang(lang: &LanguageIdentifier) -> String { }) } -/// Get translated message by key +#[macro_export] +/// Get translated message by key, with optional translation parameters +/// +/// # Examples: +/// +/// Without parameters: /// /// ```no_run -/// println!("Translated message: {}", tr("launch")); -/// ``` -#[allow(clippy::expect_fun_call)] -pub fn tr(id: &str) -> String { - unsafe { - LOCALES - .lookup(&LANG, id) - .expect(&format!("Failed to find message with given id: {id}")) - } -} +/// println!("Translated message: {}", tr!("launch")); +/// ``` +/// +/// With parameters: +/// +/// ```no_run +/// println!("Translated message: {}", tr!("game-outdated", { +/// "latest" = "3.3.0" +/// })); +/// ``` +macro_rules! tr { + ($id:expr) => { + { + use fluent_templates::Loader; -/// Get translated message by key with filled arguments -/// -/// ```no_run -/// println!("Translated message: {}", tr_args("game-outdated", [ -/// ("latest", "3.3.0".into()) -/// ])); -/// ``` -#[allow(clippy::expect_fun_call)] -pub fn tr_args(id: &str, args: I) -> String -where - I: IntoIterator)>, - T: AsRef + std::hash::Hash + Eq -{ - unsafe { - LOCALES - .lookup_with_args(&LANG, id, &std::collections::HashMap::from_iter(args.into_iter())) - .expect(&format!("Failed to find message with given id: {id}")) - } + #[allow(unused_unsafe)] + $crate::i18n::LOCALES + .lookup(unsafe { &$crate::i18n::LANG }, $id) + .expect(&format!("Failed to find a message with given id: {}", stringify!($id))) + } + }; + + ($id:expr, { $($key:literal = $value:expr),* }) => { + { + use std::collections::HashMap; + + use fluent_templates::Loader; + use fluent_templates::fluent_bundle::FluentValue; + + let mut args = HashMap::new(); + + $( + args.insert($key, FluentValue::from($value)); + )* + + #[allow(unused_unsafe)] + $crate::i18n::LOCALES + .lookup_complete(unsafe { &$crate::i18n::LANG }, $id, Some(&args)) + .expect(&format!("Failed to find a message with given id: {}", stringify!($id))) + } + }; } diff --git a/src/main.rs b/src/main.rs index a80b2ed..c6399b6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,6 @@ +use std::path::PathBuf; +use std::sync::atomic::{AtomicBool, Ordering}; + use relm4::prelude::*; use anime_launcher_sdk::config::ConfigExt; @@ -12,9 +15,6 @@ use anime_launcher_sdk::anime_game_core::genshin::prelude::*; use tracing_subscriber::prelude::*; use tracing_subscriber::filter::*; -use std::path::PathBuf; -use std::sync::atomic::{AtomicBool, Ordering}; - pub mod move_folder; pub mod i18n; pub mod background; @@ -24,6 +24,8 @@ use ui::main::*; use ui::first_run::main::*; pub const APP_ID: &str = "moe.launcher.an-anime-game-launcher"; +pub const APP_RESOURCE_PATH: &str = "/moe/launcher/an-anime-game-launcher"; + pub const APP_VERSION: &str = env!("CARGO_PKG_VERSION"); pub const APP_DEBUG: bool = cfg!(debug_assertions); @@ -68,6 +70,9 @@ lazy_static::lazy_static! { } fn main() { + // Setup custom panic handler + human_panic::setup_panic!(human_panic::metadata!()); + // Create launcher folder if it isn't if !LAUNCHER_FOLDER.exists() { std::fs::create_dir_all(LAUNCHER_FOLDER.as_path()).expect("Failed to create launcher folder"); @@ -93,6 +98,9 @@ fn main() { // Forcely run the game let just_run_game = std::env::args().any(|arg| &arg == "--just-run-game"); + // Forcely disable verbode tracing output in stdout + let no_verbose_tracing = std::env::args().any(|arg| &arg == "--no-verbose-tracing"); + // Prepare stdout logger let stdout = tracing_subscriber::fmt::layer() .pretty() @@ -103,8 +111,8 @@ fn main() { LevelFilter::WARN } }) - .with_filter(filter_fn(|metadata| { - !metadata.target().contains("rustls") + .with_filter(filter_fn(move |metadata| { + !metadata.target().contains("rustls") && !no_verbose_tracing })); // Prepare debug file logger @@ -134,6 +142,10 @@ fn main() { gtk::gio::resources_register_include!("resources.gresource") .expect("Failed to register resources"); + // Set icons search path + gtk::IconTheme::for_display(>k::gdk::Display::default().unwrap()) + .add_resource_path(&format!("{APP_RESOURCE_PATH}/icons")); + // Set application's title gtk::glib::set_application_name("An Anime Game Launcher"); gtk::glib::set_program_name(Some("An Anime Game Launcher")); diff --git a/src/ui/about.rs b/src/ui/about.rs index 788c57a..cb295e1 100644 --- a/src/ui/about.rs +++ b/src/ui/about.rs @@ -96,18 +96,37 @@ impl SimpleComponent for AboutDialog { format!("Anime Launcher SDK: {SDK_VERSION}"), format!("Anime Game Core: {CORE_VERSION}"), String::new(), - format!("GTK: {}.{}.{}", gtk::major_version(), gtk::minor_version(), gtk::micro_version()), + format!("gtk: {}.{}.{}", gtk::major_version(), gtk::minor_version(), gtk::micro_version()), format!("libadwaita: {}.{}.{}", adw::major_version(), adw::minor_version(), adw::micro_version()), format!("pango: {}", gtk::pango::version_string()), - format!("cairo: {}", gtk::cairo::version_string()), + format!("cairo: {}", gtk::cairo::version_string()) ].join("\n"), set_release_notes_version: &APP_VERSION, set_release_notes: &[ + "

Added

", + + "
    ", + "
  • Added new gamescope version compatibility
  • ", + "
  • Added \"launcher behavior\" option
  • ", + "
  • Added \"kill game process\" button when chosen behavior keeps launcher window open
  • ", + "
  • Bundled some icons into the app for consistency across the systems
  • ", + "
  • Added better panics handler
  • ", + "
", + "

Fixed

", "
    ", - "
  • Fixed game launching on installs without `launcher.bat` file
  • ", + "
  • Fixed predownload button sensitivity
  • ", + "
", + + "

Changed

", + + "
    ", + "
  • Improved pre-downloads state checking
  • ", + "
  • Replaced translation functions by `tr!` macro
  • ", + "
  • Reworked app resources structure
  • ", + "
  • Improved game running status check (wasn't working properly with Chinese client)
  • ", "
", ].join("\n"), diff --git a/src/ui/components/progress_bar.rs b/src/ui/components/progress_bar.rs index d40ca8d..8b2a35c 100644 --- a/src/ui/components/progress_bar.rs +++ b/src/ui/components/progress_bar.rs @@ -6,7 +6,7 @@ use adw::prelude::*; use anime_launcher_sdk::anime_game_core::prelude::*; use anime_launcher_sdk::anime_game_core::genshin::prelude::*; -use crate::i18n::*; +use crate::*; pub struct ProgressBarInit { pub caption: Option, @@ -133,19 +133,19 @@ impl SimpleAsyncComponent for ProgressBar { ProgressBarMsg::UpdateFromState(state) => { match state { DiffUpdate::CheckingFreeSpace(_) | - DiffUpdate::InstallerUpdate(InstallerUpdate::CheckingFreeSpace(_)) => self.caption = Some(tr("checking-free-space")), + DiffUpdate::InstallerUpdate(InstallerUpdate::CheckingFreeSpace(_)) => self.caption = Some(tr!("checking-free-space")), - DiffUpdate::InstallerUpdate(InstallerUpdate::DownloadingStarted(_)) => self.caption = Some(tr("downloading")), - DiffUpdate::InstallerUpdate(InstallerUpdate::UnpackingStarted(_)) => self.caption = Some(tr("unpacking")), + DiffUpdate::InstallerUpdate(InstallerUpdate::DownloadingStarted(_)) => self.caption = Some(tr!("downloading")), + DiffUpdate::InstallerUpdate(InstallerUpdate::UnpackingStarted(_)) => self.caption = Some(tr!("unpacking")), DiffUpdate::ApplyingHdiffStarted => { - self.caption = Some(tr("applying-hdiff")); + self.caption = Some(tr!("applying-hdiff")); self.display_fraction = false; }, DiffUpdate::RemovingOutdatedStarted => { - self.caption = Some(tr("removing-outdated")); + self.caption = Some(tr!("removing-outdated")); self.display_fraction = false; }, diff --git a/src/ui/first_run/default_paths.rs b/src/ui/first_run/default_paths.rs index ae3e8c1..c62e323 100644 --- a/src/ui/first_run/default_paths.rs +++ b/src/ui/first_run/default_paths.rs @@ -6,7 +6,6 @@ use relm4::component::*; use adw::prelude::*; use crate::*; -use crate::i18n::*; use crate::ui::components::progress_bar::*; use super::main::*; @@ -68,7 +67,7 @@ impl SimpleAsyncComponent for DefaultPathsApp { set_vexpand: true, gtk::Label { - set_label: &tr("choose-default-paths"), + set_label: &tr!("choose-default-paths"), add_css_class: "title-1" } }, @@ -81,7 +80,7 @@ impl SimpleAsyncComponent for DefaultPathsApp { set_sensitive: !model.show_progress, adw::ActionRow { - set_title: &tr("launcher-folder"), + set_title: &tr!("launcher-folder"), set_icon_name: Some("folder-symbolic"), set_activatable: true, @@ -97,8 +96,8 @@ impl SimpleAsyncComponent for DefaultPathsApp { set_vexpand: true, adw::ActionRow { - set_title: &tr("show-all-folders"), - set_subtitle: &tr("show-all-folders-subtitle"), + set_title: &tr!("show-all-folders"), + set_subtitle: &tr!("show-all-folders-subtitle"), add_suffix = >k::Switch { set_valign: gtk::Align::Center, @@ -119,7 +118,7 @@ impl SimpleAsyncComponent for DefaultPathsApp { set_sensitive: !model.show_progress, adw::ActionRow { - set_title: &tr("runners-folder"), + set_title: &tr!("runners-folder"), set_icon_name: Some("folder-symbolic"), set_activatable: true, @@ -130,7 +129,7 @@ impl SimpleAsyncComponent for DefaultPathsApp { }, adw::ActionRow { - set_title: &tr("dxvks-folder"), + set_title: &tr!("dxvks-folder"), set_icon_name: Some("folder-symbolic"), set_activatable: true, @@ -141,7 +140,7 @@ impl SimpleAsyncComponent for DefaultPathsApp { }, adw::ActionRow { - set_title: &tr("wine-prefix-folder"), + set_title: &tr!("wine-prefix-folder"), set_icon_name: Some("folder-symbolic"), set_activatable: true, @@ -152,7 +151,7 @@ impl SimpleAsyncComponent for DefaultPathsApp { }, adw::ActionRow { - set_title: &tr("global-game-installation-folder"), + set_title: &tr!("global-game-installation-folder"), set_icon_name: Some("folder-symbolic"), set_activatable: true, @@ -163,7 +162,7 @@ impl SimpleAsyncComponent for DefaultPathsApp { }, adw::ActionRow { - set_title: &tr("chinese-game-installation-folder"), + set_title: &tr!("chinese-game-installation-folder"), set_icon_name: Some("folder-symbolic"), set_activatable: true, @@ -174,7 +173,7 @@ impl SimpleAsyncComponent for DefaultPathsApp { }, adw::ActionRow { - set_title: &tr("fps-unlocker-folder"), + set_title: &tr!("fps-unlocker-folder"), set_icon_name: Some("folder-symbolic"), set_activatable: true, @@ -185,7 +184,7 @@ impl SimpleAsyncComponent for DefaultPathsApp { }, adw::ActionRow { - set_title: &tr("components-index"), + set_title: &tr!("components-index"), set_icon_name: Some("folder-symbolic"), set_activatable: true, @@ -196,7 +195,7 @@ impl SimpleAsyncComponent for DefaultPathsApp { }, adw::ActionRow { - set_title: &tr("patch-folder"), + set_title: &tr!("patch-folder"), set_icon_name: Some("folder-symbolic"), set_activatable: true, @@ -207,7 +206,7 @@ impl SimpleAsyncComponent for DefaultPathsApp { }, adw::ActionRow { - set_title: &tr("temp-folder"), + set_title: &tr!("temp-folder"), set_icon_name: Some("folder-symbolic"), set_activatable: true, @@ -232,9 +231,9 @@ impl SimpleAsyncComponent for DefaultPathsApp { gtk::Button { set_label: &if model.migrate_installation { - tr("migrate") + tr!("migrate") } else { - tr("continue") + tr!("continue") }, set_css_classes: &["suggested-action", "pill"], @@ -244,9 +243,9 @@ impl SimpleAsyncComponent for DefaultPathsApp { gtk::Button { set_label: &if model.migrate_installation { - tr("close") + tr!("close", { "form" = "noun" }) } else { - tr("exit") + tr!("exit") }, add_css_class: "pill", @@ -407,7 +406,7 @@ impl SimpleAsyncComponent for DefaultPathsApp { Err(err) => { sender.output(Self::Output::Toast { - title: tr("config-update-error"), + title: tr!("config-update-error"), description: Some(err.to_string()) }); } diff --git a/src/ui/first_run/dependencies.rs b/src/ui/first_run/dependencies.rs index 63419b5..c51db17 100644 --- a/src/ui/first_run/dependencies.rs +++ b/src/ui/first_run/dependencies.rs @@ -5,7 +5,7 @@ use adw::prelude::*; use anime_launcher_sdk::is_available; -use crate::i18n::*; +use crate::*; use super::main::FirstRunAppMsg; @@ -36,12 +36,12 @@ impl SimpleAsyncComponent for DependenciesApp { set_vexpand: true, gtk::Label { - set_label: &tr("missing-dependencies-title"), + set_label: &tr!("missing-dependencies-title"), add_css_class: "title-1" }, gtk::Label { - set_label: &tr("missing-dependencies-message"), + set_label: &tr!("missing-dependencies-message"), set_justify: gtk::Justification::Center, set_wrap: true, @@ -120,14 +120,14 @@ impl SimpleAsyncComponent for DependenciesApp { set_spacing: 8, gtk::Button { - set_label: &tr("check"), + set_label: &tr!("check"), set_css_classes: &["suggested-action", "pill"], connect_clicked => DependenciesAppMsg::Continue }, gtk::Button { - set_label: &tr("exit"), + set_label: &tr!("exit"), add_css_class: "pill", connect_clicked => DependenciesAppMsg::Exit @@ -175,7 +175,9 @@ impl SimpleAsyncComponent for DependenciesApp { for package in packages { if !is_available(package) { sender.output(Self::Output::Toast { - title: tr_args("package-not-available", [("package", package.into())]), + title: tr!("package-not-available", { + "package" = package + }), description: None }); diff --git a/src/ui/first_run/download_components.rs b/src/ui/first_run/download_components.rs index 1e8c64a..f091464 100644 --- a/src/ui/first_run/download_components.rs +++ b/src/ui/first_run/download_components.rs @@ -17,7 +17,6 @@ use anime_launcher_sdk::genshin::config::Config; use super::main::FirstRunAppMsg; use crate::ui::components::*; -use crate::i18n::*; use crate::*; fn get_installer(uri: &str, temp: Option) -> anyhow::Result { @@ -88,7 +87,7 @@ impl SimpleAsyncComponent for DownloadComponentsApp { set_vexpand: true, gtk::Label { - set_label: &tr("download-components"), + set_label: &tr!("download-components"), add_css_class: "title-1" } }, @@ -102,7 +101,7 @@ impl SimpleAsyncComponent for DownloadComponentsApp { #[local_ref] wine_combo -> adw::ComboRow { - set_title: &tr("wine-version"), + set_title: &tr!("wine-version"), #[watch] set_model: Some(>k::StringList::new(model.wine_versions.iter() @@ -113,7 +112,7 @@ impl SimpleAsyncComponent for DownloadComponentsApp { #[local_ref] dxvk_combo -> adw::ComboRow { - set_title: &tr("dxvk-version"), + set_title: &tr!("dxvk-version"), #[watch] set_model: Some(>k::StringList::new(model.dxvk_versions.iter() @@ -136,14 +135,14 @@ impl SimpleAsyncComponent for DownloadComponentsApp { set_spacing: 8, gtk::Button { - set_label: &tr("download"), + set_label: &tr!("download"), set_css_classes: &["suggested-action", "pill"], connect_clicked => DownloadComponentsAppMsg::DownloadWine }, gtk::Button { - set_label: &tr("exit"), + set_label: &tr!("exit"), add_css_class: "pill", connect_clicked => DownloadComponentsAppMsg::Exit @@ -159,7 +158,7 @@ impl SimpleAsyncComponent for DownloadComponentsApp { set_visible: model.downloading, adw::ActionRow { - set_title: &tr("download-wine"), + set_title: &tr!("download-wine"), #[watch] set_subtitle: &model.downloading_wine_version, @@ -180,7 +179,7 @@ impl SimpleAsyncComponent for DownloadComponentsApp { }, adw::ActionRow { - set_title: &tr("create-prefix"), + set_title: &tr!("create-prefix"), #[watch] set_subtitle: &model.creating_prefix_path, @@ -201,7 +200,7 @@ impl SimpleAsyncComponent for DownloadComponentsApp { }, adw::ActionRow { - set_title: &tr("download-dxvk"), + set_title: &tr!("download-dxvk"), #[watch] set_subtitle: &model.downloading_dxvk_version, @@ -222,7 +221,7 @@ impl SimpleAsyncComponent for DownloadComponentsApp { }, adw::ActionRow { - set_title: &tr("apply-dxvk"), + set_title: &tr!("apply-dxvk"), #[watch] set_icon_name: match model.applying_dxvk { @@ -356,7 +355,7 @@ impl SimpleAsyncComponent for DownloadComponentsApp { tracing::error!("Failed to update config: {err}"); sender.output(Self::Output::Toast { - title: tr("config-update-error"), + title: tr!("config-update-error"), description: Some(err.to_string()) }); } @@ -384,7 +383,7 @@ impl SimpleAsyncComponent for DownloadComponentsApp { tracing::error!("Failed to download wine: {err}"); sender.output(Self::Output::Toast { - title: tr("wine-download-error"), + title: tr!("wine-download-error"), description: Some(err.to_string()) }); } @@ -393,7 +392,7 @@ impl SimpleAsyncComponent for DownloadComponentsApp { tracing::error!("Failed to unpack wine: {err}"); sender.output(Self::Output::Toast { - title: tr("wine-unpack-errror"), + title: tr!("wine-unpack-errror"), description: Some(err.clone()) }); } @@ -408,7 +407,7 @@ impl SimpleAsyncComponent for DownloadComponentsApp { tracing::error!("Failed to update config: {err}"); sender.output(Self::Output::Toast { - title: tr("config-update-error"), + title: tr!("config-update-error"), description: Some(err.to_string()) }); } @@ -427,7 +426,7 @@ impl SimpleAsyncComponent for DownloadComponentsApp { tracing::error!("Failed to initialize wine installer: {err}"); sender.output(Self::Output::Toast { - title: tr("wine-install-failed"), + title: tr!("wine-install-failed"), description: Some(err.to_string()) }); } @@ -464,7 +463,7 @@ impl SimpleAsyncComponent for DownloadComponentsApp { tracing::error!("Failed to create prefix: {err}"); sender.output(Self::Output::Toast { - title: tr("wine-prefix-update-failed"), + title: tr!("wine-prefix-update-failed"), description: Some(err.to_string()) }); } @@ -510,7 +509,7 @@ impl SimpleAsyncComponent for DownloadComponentsApp { tracing::error!("Failed to download dxvk: {err}"); sender.output(Self::Output::Toast { - title: tr("dxvk-download-error"), + title: tr!("dxvk-download-error"), description: Some(err.to_string()) }); } @@ -519,7 +518,7 @@ impl SimpleAsyncComponent for DownloadComponentsApp { tracing::error!("Failed to unpack dxvk: {err}"); sender.output(Self::Output::Toast { - title: tr("dxvk-unpack-error"), + title: tr!("dxvk-unpack-error"), description: Some(err.clone()) }); } @@ -540,7 +539,7 @@ impl SimpleAsyncComponent for DownloadComponentsApp { tracing::error!("Failed to initialize dxvk installer: {err}"); sender.output(Self::Output::Toast { - title: tr("dxvk-install-failed"), + title: tr!("dxvk-install-failed"), description: Some(err.to_string()) }); } @@ -593,7 +592,7 @@ impl SimpleAsyncComponent for DownloadComponentsApp { tracing::error!("Failed to apply DXVK: {err}"); sender.output(Self::Output::Toast { - title: tr("dxvk-apply-error"), + title: tr!("dxvk-apply-error"), description: Some(err.to_string()) }); } diff --git a/src/ui/first_run/finish.rs b/src/ui/first_run/finish.rs index b59cee6..684ef19 100644 --- a/src/ui/first_run/finish.rs +++ b/src/ui/first_run/finish.rs @@ -3,7 +3,7 @@ use relm4::component::*; use adw::prelude::*; -use crate::i18n::*; +use crate::*; use super::main::*; @@ -30,12 +30,12 @@ impl SimpleAsyncComponent for FinishApp { set_vexpand: true, gtk::Label { - set_label: &tr("finish-title"), + set_label: &tr!("finish-title"), add_css_class: "title-1" }, gtk::Label { - set_label: &tr("finish-message"), + set_label: &tr!("finish-message"), set_justify: gtk::Justification::Center, set_wrap: true, @@ -53,14 +53,14 @@ impl SimpleAsyncComponent for FinishApp { set_spacing: 8, gtk::Button { - set_label: &tr("restart"), + set_label: &tr!("restart"), set_css_classes: &["suggested-action", "pill"], connect_clicked => FinishAppMsg::Restart }, gtk::Button { - set_label: &tr("exit"), + set_label: &tr!("exit"), add_css_class: "pill", connect_clicked => FinishAppMsg::Exit diff --git a/src/ui/first_run/main.rs b/src/ui/first_run/main.rs index 7cb874d..e9b1471 100644 --- a/src/ui/first_run/main.rs +++ b/src/ui/first_run/main.rs @@ -6,7 +6,6 @@ use adw::prelude::*; use anime_launcher_sdk::components::loader::ComponentsLoader; -use crate::i18n::tr; use crate::*; use super::welcome::*; @@ -77,7 +76,7 @@ impl SimpleComponent for FirstRunApp { }, adw::StatusPage { - set_title: &tr("loading-data"), + set_title: &tr!("loading-data"), set_icon_name: Some(APP_ID), set_vexpand: true, @@ -164,7 +163,7 @@ impl SimpleComponent for FirstRunApp { carousel, loading: None, - title: tr("welcome") + title: tr!("welcome") }; let toast_overlay = &model.toast_overlay; @@ -192,32 +191,32 @@ impl SimpleComponent for FirstRunApp { } FirstRunAppMsg::ScrollToTosWarning => { - self.title = tr("tos-violation-warning"); + self.title = tr!("tos-violation-warning"); self.carousel.scroll_to(self.tos_warning.widget(), true); } FirstRunAppMsg::ScrollToDependencies => { - self.title = tr("dependencies"); + self.title = tr!("dependencies"); self.carousel.scroll_to(self.dependencies.widget(), true); } FirstRunAppMsg::ScrollToDefaultPaths => { - self.title = tr("default-paths"); + self.title = tr!("default-paths"); self.carousel.scroll_to(self.default_paths.widget(), true); } FirstRunAppMsg::ScrollToSelectVoiceovers => { - self.title = tr("select-voice-packages"); + self.title = tr!("select-voice-packages"); self.carousel.scroll_to(self.select_voiceovers.widget(), true); } FirstRunAppMsg::ScrollToDownloadComponents => { // Update components index - sender.input(FirstRunAppMsg::SetLoadingStatus(Some(Some(tr("updating-components-index"))))); + sender.input(FirstRunAppMsg::SetLoadingStatus(Some(Some(tr!("updating-components-index"))))); let config = Config::get().unwrap_or_else(|_| CONFIG.clone()); @@ -238,7 +237,7 @@ impl SimpleComponent for FirstRunApp { tracing::error!("Failed to sync components index"); sender.input(FirstRunAppMsg::Toast { - title: tr("components-index-sync-failed"), + title: tr!("components-index-sync-failed"), description: Some(err.to_string()) }); } @@ -250,7 +249,7 @@ impl SimpleComponent for FirstRunApp { tracing::error!("Failed to verify that components index synced"); sender.input(FirstRunAppMsg::Toast { - title: tr("components-index-verify-failed"), + title: tr!("components-index-verify-failed"), description: Some(err.to_string()) }); } @@ -265,13 +264,13 @@ impl SimpleComponent for FirstRunApp { // Scroll to download components page // This will happen in background behind StatusPage - self.title = tr("download-components"); + self.title = tr!("download-components"); self.carousel.scroll_to(self.download_components.widget(), true); } FirstRunAppMsg::ScrollToFinish => { - self.title = tr("finish"); + self.title = tr!("finish"); self.carousel.scroll_to(self.finish.widget(), true); } @@ -282,12 +281,12 @@ impl SimpleComponent for FirstRunApp { toast.set_timeout(4); if let Some(description) = description { - toast.set_button_label(Some(&tr("details"))); + toast.set_button_label(Some(&tr!("details"))); let dialog = adw::MessageDialog::new(MAIN_WINDOW.as_ref(), Some(&title), Some(&description)); - dialog.add_response("close", &tr("close")); - dialog.add_response("save", &tr("save")); + dialog.add_response("close", &tr!("close", { "form" = "noun" })); + dialog.add_response("save", &tr!("save")); dialog.set_response_appearance("save", adw::ResponseAppearance::Suggested); diff --git a/src/ui/first_run/select_voiceovers.rs b/src/ui/first_run/select_voiceovers.rs index 53a5a5c..28fbbe0 100644 --- a/src/ui/first_run/select_voiceovers.rs +++ b/src/ui/first_run/select_voiceovers.rs @@ -6,7 +6,7 @@ use adw::prelude::*; use anime_launcher_sdk::config::ConfigExt; use anime_launcher_sdk::genshin::config::Config; -use crate::i18n::*; +use crate::*; use super::main::*; @@ -38,7 +38,7 @@ impl SimpleAsyncComponent for SelectVoiceoversApp { set_vexpand: true, gtk::Label { - set_label: &tr("select-voice-packages"), + set_label: &tr!("select-voice-packages"), add_css_class: "title-1" } }, @@ -48,7 +48,7 @@ impl SimpleAsyncComponent for SelectVoiceoversApp { set_vexpand: true, adw::ActionRow { - set_title: &tr("english"), + set_title: &tr!("english"), #[local_ref] add_suffix = english -> gtk::Switch { @@ -58,7 +58,7 @@ impl SimpleAsyncComponent for SelectVoiceoversApp { }, adw::ActionRow { - set_title: &tr("japanese"), + set_title: &tr!("japanese"), #[local_ref] add_suffix = japanese -> gtk::Switch { @@ -67,7 +67,7 @@ impl SimpleAsyncComponent for SelectVoiceoversApp { }, adw::ActionRow { - set_title: &tr("korean"), + set_title: &tr!("korean"), #[local_ref] add_suffix = korean -> gtk::Switch { @@ -76,7 +76,7 @@ impl SimpleAsyncComponent for SelectVoiceoversApp { }, adw::ActionRow { - set_title: &tr("chinese"), + set_title: &tr!("chinese"), #[local_ref] add_suffix = chinese -> gtk::Switch { @@ -95,14 +95,14 @@ impl SimpleAsyncComponent for SelectVoiceoversApp { set_spacing: 8, gtk::Button { - set_label: &tr("continue"), + set_label: &tr!("continue"), set_css_classes: &["suggested-action", "pill"], connect_clicked => SelectVoiceoversAppMsg::Continue }, gtk::Button { - set_label: &tr("exit"), + set_label: &tr!("exit"), add_css_class: "pill", connect_clicked => SelectVoiceoversAppMsg::Exit @@ -142,7 +142,7 @@ impl SimpleAsyncComponent for SelectVoiceoversApp { Ok(_) => sender.output(Self::Output::ScrollToDownloadComponents), Err(err) => sender.output(Self::Output::Toast { - title: tr("config-update-error"), + title: tr!("config-update-error"), description: Some(err.to_string()) }) }; diff --git a/src/ui/first_run/tos_warning.rs b/src/ui/first_run/tos_warning.rs index e9fe030..f5a475f 100644 --- a/src/ui/first_run/tos_warning.rs +++ b/src/ui/first_run/tos_warning.rs @@ -5,7 +5,7 @@ use adw::prelude::*; use anime_launcher_sdk::is_available; -use crate::i18n::*; +use crate::*; use super::main::FirstRunAppMsg; @@ -34,14 +34,14 @@ impl SimpleAsyncComponent for TosWarningApp { set_vexpand: true, gtk::Label { - set_label: &tr("tos-violation-warning"), + set_label: &tr!("tos-violation-warning"), add_css_class: "title-1" } }, add = &adw::PreferencesGroup { gtk::Label { - set_label: &tr("tos-violation-warning-message"), + set_label: &tr!("tos-violation-warning-message"), set_wrap: true, set_selectable: true } @@ -57,14 +57,14 @@ impl SimpleAsyncComponent for TosWarningApp { set_spacing: 8, gtk::Button { - set_label: &tr("continue"), + set_label: &tr!("continue"), set_css_classes: &["suggested-action", "pill"], connect_clicked => TosWarningAppMsg::Continue }, gtk::Button { - set_label: &tr("exit"), + set_label: &tr!("exit"), add_css_class: "pill", connect_clicked => TosWarningAppMsg::Exit @@ -91,13 +91,13 @@ impl SimpleAsyncComponent for TosWarningApp { TosWarningAppMsg::Continue => { let dialog = adw::MessageDialog::new( unsafe { MAIN_WINDOW.as_ref() }, - Some(&tr("tos-dialog-title")), - Some(&tr("tos-dialog-message")) + Some(&tr!("tos-dialog-title")), + Some(&tr!("tos-dialog-message")) ); dialog.add_responses(&[ - ("exit", &tr("exit")), - ("continue", &tr("agree")) + ("exit", &tr!("exit")), + ("continue", &tr!("agree")) ]); dialog.connect_response(None, move |_, response| { diff --git a/src/ui/first_run/welcome.rs b/src/ui/first_run/welcome.rs index 9feb986..a465cbb 100644 --- a/src/ui/first_run/welcome.rs +++ b/src/ui/first_run/welcome.rs @@ -3,7 +3,7 @@ use relm4::component::*; use adw::prelude::*; -use crate::i18n::*; +use crate::*; use super::main::FirstRunAppMsg; @@ -29,7 +29,7 @@ impl SimpleAsyncComponent for WelcomeApp { set_vexpand: true, gtk::Image { - set_resource: Some("/org/app/images/icon.png"), + set_icon_name: Some(APP_ID), set_height_request: 128 }, @@ -40,7 +40,7 @@ impl SimpleAsyncComponent for WelcomeApp { }, gtk::Label { - set_label: &tr("welcome-page-message"), + set_label: &tr!("welcome-page-message"), set_justify: gtk::Justification::Center, set_wrap: true, @@ -58,7 +58,7 @@ impl SimpleAsyncComponent for WelcomeApp { set_spacing: 8, gtk::Button { - set_label: &tr("continue"), + set_label: &tr!("continue"), set_css_classes: &["suggested-action", "pill"], connect_clicked => WelcomeAppMsg::Continue diff --git a/src/ui/main/apply_patch.rs b/src/ui/main/apply_patch.rs index 6295c46..46b160f 100644 --- a/src/ui/main/apply_patch.rs +++ b/src/ui/main/apply_patch.rs @@ -1,7 +1,6 @@ use relm4::prelude::*; use crate::*; -use crate::i18n::*; use super::{App, AppMsg}; @@ -22,7 +21,7 @@ pub fn apply_patch(sender: ComponentSender, patch: PlayerPatch, rename_mhyp tracing::error!("Failed to patch the game"); sender.input(AppMsg::Toast { - title: tr("game-patching-error"), + title: tr!("game-patching-error"), description: Some(err.to_string()) }); } @@ -38,7 +37,7 @@ pub fn apply_patch(sender: ComponentSender, patch: PlayerPatch, rename_mhyp tracing::error!("Failed to rename mhypbase file"); sender.input(AppMsg::Toast { - title: tr("game-patching-error"), + title: tr!("game-patching-error"), description: Some(err.to_string()) }); } diff --git a/src/ui/main/create_prefix.rs b/src/ui/main/create_prefix.rs index 9f25e31..3bf7407 100644 --- a/src/ui/main/create_prefix.rs +++ b/src/ui/main/create_prefix.rs @@ -5,7 +5,7 @@ use anime_launcher_sdk::wincompatlib::prelude::*; use anime_launcher_sdk::config::ConfigExt; use anime_launcher_sdk::genshin::config::Config; -use crate::i18n::*; +use crate::*; use super::{App, AppMsg}; @@ -27,7 +27,7 @@ pub fn create_prefix(sender: ComponentSender) { tracing::error!("Failed to create wine prefix"); sender.input(AppMsg::Toast { - title: tr("wine-prefix-update-failed"), + title: tr!("wine-prefix-update-failed"), description: Some(err.to_string()) }); } @@ -44,7 +44,7 @@ pub fn create_prefix(sender: ComponentSender) { tracing::error!("Failed to get selected wine executable"); sender.input(AppMsg::Toast { - title: tr("failed-get-selected-wine"), + title: tr!("failed-get-selected-wine"), description: None }); } @@ -53,7 +53,7 @@ pub fn create_prefix(sender: ComponentSender) { tracing::error!("Failed to get selected wine executable: {err}"); sender.input(AppMsg::Toast { - title: tr("failed-get-selected-wine"), + title: tr!("failed-get-selected-wine"), description: Some(err.to_string()) }); } diff --git a/src/ui/main/disable_telemetry.rs b/src/ui/main/disable_telemetry.rs index 8523a3f..fb4743c 100644 --- a/src/ui/main/disable_telemetry.rs +++ b/src/ui/main/disable_telemetry.rs @@ -3,7 +3,6 @@ use std::process::Command; use relm4::prelude::*; use crate::*; -use crate::i18n::*; use super::{App, AppMsg}; @@ -40,7 +39,7 @@ pub fn disable_telemetry(sender: ComponentSender) { tracing::error!("Failed to update /etc/hosts file"); sender.input(AppMsg::Toast { - title: tr("telemetry-servers-disabling-error"), + title: tr!("telemetry-servers-disabling-error"), description: None // stdout/err is empty }); } @@ -49,7 +48,7 @@ pub fn disable_telemetry(sender: ComponentSender) { tracing::error!("Failed to update /etc/hosts file"); sender.input(AppMsg::Toast { - title: tr("telemetry-servers-disabling-error"), + title: tr!("telemetry-servers-disabling-error"), description: Some(err.to_string()) }); } diff --git a/src/ui/main/download_diff.rs b/src/ui/main/download_diff.rs index 08826a5..cf58f25 100644 --- a/src/ui/main/download_diff.rs +++ b/src/ui/main/download_diff.rs @@ -6,7 +6,6 @@ use relm4::{ use gtk::glib::clone; use crate::*; -use crate::i18n::*; use crate::ui::components::*; use super::{App, AppMsg}; @@ -28,7 +27,7 @@ pub fn download_diff(sender: ComponentSender, progress_bar_input: Sender, progress_bar_input: Sender, progress_bar_input: Sender, progress_bar_input: Sender, progress_bar_input: Sender, progress_bar_input: Sender sender.input(AppMsg::Toast { - title: tr("wine-install-failed"), + title: tr!("wine-install-failed"), description: Some(err.to_string()) }) } @@ -103,7 +102,7 @@ pub fn download_wine(sender: ComponentSender, progress_bar_input: Sender sender.input(AppMsg::Toast { - title: tr("downloaded-wine-list-failed"), + title: tr!("downloaded-wine-list-failed"), description: Some(err.to_string()) }) } diff --git a/src/ui/main/launch.rs b/src/ui/main/launch.rs index 9db2c6e..067b38e 100644 --- a/src/ui/main/launch.rs +++ b/src/ui/main/launch.rs @@ -1,22 +1,51 @@ use relm4::prelude::*; +use gtk::prelude::*; -use crate::i18n::*; +use anime_launcher_sdk::genshin::config::schema::prelude::LauncherBehavior; + +use crate::*; use super::{App, AppMsg}; pub fn launch(sender: ComponentSender) { - sender.input(AppMsg::HideWindow); + let config = Config::get().unwrap(); + + match config.launcher.behavior { + // Disable launch button and show kill game button if behavior set to "Nothing" to prevent sussy actions + LauncherBehavior::Nothing => { + sender.input(AppMsg::DisableButtons(true)); + sender.input(AppMsg::SetKillGameButton(true)); + } + + // Hide launcher window if behavior set to "Hide" or "Close" + LauncherBehavior::Hide | LauncherBehavior::Close => sender.input(AppMsg::HideWindow) + } std::thread::spawn(move || { if let Err(err) = anime_launcher_sdk::genshin::game::run() { tracing::error!("Failed to launch game: {err}"); sender.input(AppMsg::Toast { - title: tr("game-launching-failed"), + title: tr!("game-launching-failed"), description: Some(err.to_string()) }); } - sender.input(AppMsg::ShowWindow); + match config.launcher.behavior { + // Enable launch button and hide kill game button if behavior set to "Nothing" after the game has closed + LauncherBehavior::Nothing => { + sender.input(AppMsg::DisableButtons(false)); + sender.input(AppMsg::SetKillGameButton(false)); + } + + // Show back launcher window if behavior set to "Hide" and the game has closed + LauncherBehavior::Hide => sender.input(AppMsg::ShowWindow), + + // Otherwise close the launcher if behavior set to "Close" and the game has closed + // We're calling quit method from the main context here because otherwise app won't be closed properly + LauncherBehavior::Close => gtk::glib::MainContext::default().invoke(|| { + relm4::main_application().quit(); + }) + } }); } diff --git a/src/ui/main/mod.rs b/src/ui/main/mod.rs index 07ee848..17bf3e4 100644 --- a/src/ui/main/mod.rs +++ b/src/ui/main/mod.rs @@ -30,7 +30,6 @@ use anime_launcher_sdk::genshin::states::*; use anime_launcher_sdk::genshin::consts::*; use crate::*; -use crate::i18n::*; use crate::ui::components::*; use super::preferences::main::*; @@ -60,7 +59,9 @@ pub struct App { state: Option, downloading: bool, - disabled_buttons: bool + disabled_buttons: bool, + kill_game_button: bool, + disabled_kill_game_button: bool } #[derive(Debug)] @@ -90,6 +91,8 @@ pub enum AppMsg { SetDownloading(bool), DisableButtons(bool), + SetKillGameButton(bool), + DisableKillGameButton(bool), OpenPreferences, RepairGame, @@ -115,18 +118,18 @@ impl SimpleComponent for App { menu! { main_menu: { section! { - &tr("launcher-folder") => LauncherFolder, - &tr("game-folder") => GameFolder, - &tr("config-file") => ConfigFile, - &tr("debug-file") => DebugFile, + &tr!("launcher-folder") => LauncherFolder, + &tr!("game-folder") => GameFolder, + &tr!("config-file") => ConfigFile, + &tr!("debug-file") => DebugFile, }, section! { - &tr("wish-url") => WishUrl + &tr!("wish-url") => WishUrl }, section! { - &tr("about") => About + &tr!("about") => About } } } @@ -195,7 +198,7 @@ impl SimpleComponent for App { }, adw::StatusPage { - set_title: &tr("loading-data"), + set_title: &tr!("loading-data"), set_icon_name: Some(APP_ID), set_vexpand: true, @@ -220,7 +223,7 @@ impl SimpleComponent for App { set_visible: model.style == LauncherStyle::Modern, gtk::Picture { - set_resource: Some("/org/app/images/icon.png"), + set_resource: Some(&format!("{APP_RESOURCE_PATH}/icons/hicolor/scalable/apps/{APP_ID}.png")), set_vexpand: true, set_content_fit: gtk::ContentFit::ScaleDown }, @@ -302,13 +305,13 @@ impl SimpleComponent for App { set_width_request: 44, #[watch] - set_tooltip_text: Some(&tr_args("predownload-update", [ - ("version", match model.state.as_ref() { + set_tooltip_text: Some(&tr!("predownload-update", { + "version" = match model.state.as_ref() { Some(LauncherState::PredownloadAvailable { game, .. }) => game.latest().to_string(), _ => String::from("?") - }.into()), + }, - ("size", match model.state.as_ref() { + "size" = match model.state.as_ref() { Some(LauncherState::PredownloadAvailable { game, voices }) => { let mut size = game.downloaded_size().unwrap_or(0); @@ -320,8 +323,8 @@ impl SimpleComponent for App { } _ => String::from("?") - }.into()) - ])), + } + })), #[watch] set_visible: matches!(model.state.as_ref(), Some(LauncherState::PredownloadAvailable { .. })), @@ -332,8 +335,21 @@ impl SimpleComponent for App { let config = Config::get().unwrap(); let temp = config.launcher.temp.unwrap_or_else(std::env::temp_dir); - let downloaded = temp.join(game.file_name().unwrap()).exists() && - voices.iter().all(|voice| temp.join(voice.file_name().unwrap()).exists()); + let mut downloaded = temp.join(game.file_name().unwrap()).metadata() + .map(|metadata| Some(metadata.len()) == game.downloaded_size()) + .unwrap_or(false); + + if downloaded { + for voice in voices { + downloaded = !temp.join(voice.file_name().unwrap()).metadata() + .map(|metadata| Some(metadata.len()) == voice.downloaded_size()) + .unwrap_or(false); + + if downloaded { + break; + } + } + } !downloaded } @@ -347,8 +363,21 @@ impl SimpleComponent for App { let config = Config::get().unwrap(); let temp = config.launcher.temp.unwrap_or_else(std::env::temp_dir); - let downloaded = temp.join(game.file_name().unwrap()).exists() && - voices.iter().all(|voice| temp.join(voice.file_name().unwrap()).exists()); + let mut downloaded = temp.join(game.file_name().unwrap()).metadata() + .map(|metadata| Some(metadata.len()) == game.downloaded_size()) + .unwrap_or(false); + + if downloaded { + for voice in voices { + downloaded = !temp.join(voice.file_name().unwrap()).metadata() + .map(|metadata| Some(metadata.len()) == voice.downloaded_size()) + .unwrap_or(false); + + if downloaded { + break; + } + } + } if downloaded { &["success", "circular"] @@ -370,6 +399,9 @@ impl SimpleComponent for App { adw::Bin { set_css_classes: &["background", "round-bin"], + #[watch] + set_visible: !model.kill_game_button, + gtk::Button { adw::ButtonContent { #[watch] @@ -405,15 +437,15 @@ impl SimpleComponent for App { #[watch] set_label: &match &model.state { Some(LauncherState::Launch) | - Some(LauncherState::PredownloadAvailable { .. }) => tr("launch"), + Some(LauncherState::PredownloadAvailable { .. }) => tr!("launch"), - Some(LauncherState::FolderMigrationRequired { .. }) => tr("migrate-folders"), - Some(LauncherState::PlayerPatchAvailable { .. }) => tr("apply-patch"), + Some(LauncherState::FolderMigrationRequired { .. }) => tr!("migrate-folders"), + Some(LauncherState::PlayerPatchAvailable { .. }) => tr!("apply-patch"), - Some(LauncherState::TelemetryNotDisabled) => tr("disable-telemetry"), + Some(LauncherState::TelemetryNotDisabled) => tr!("disable-telemetry"), - Some(LauncherState::WineNotInstalled) => tr("download-wine"), - Some(LauncherState::PrefixNotExists) => tr("create-prefix"), + Some(LauncherState::WineNotInstalled) => tr!("download-wine"), + Some(LauncherState::PrefixNotExists) => tr!("create-prefix"), Some(LauncherState::GameUpdateAvailable(diff)) | Some(LauncherState::GameOutdated(diff)) | @@ -424,20 +456,20 @@ impl SimpleComponent for App { let temp = config.launcher.temp.unwrap_or_else(std::env::temp_dir); if temp.join(filename).exists() { - tr("resume") + tr!("resume") } else { - tr("update") + tr!("update") } } - _ => tr("update") + _ => tr!("update") } }, Some(LauncherState::GameNotInstalled(_)) | - Some(LauncherState::VoiceNotInstalled(_)) => tr("download"), + Some(LauncherState::VoiceNotInstalled(_)) => tr!("download"), None => String::from("...") } @@ -484,15 +516,15 @@ impl SimpleComponent for App { #[watch] set_tooltip_text: Some(&match &model.state { Some(LauncherState::GameOutdated { .. }) | - Some(LauncherState::VoiceOutdated(_)) => tr("main-window--version-outdated-tooltip"), + Some(LauncherState::VoiceOutdated(_)) => tr!("main-window--version-outdated-tooltip"), - Some(LauncherState::FolderMigrationRequired { .. }) => tr("migrate-folders-tooltip"), + Some(LauncherState::FolderMigrationRequired { .. }) => tr!("migrate-folders-tooltip"), Some(LauncherState::PlayerPatchAvailable { patch: PlayerPatch { status, .. }, .. }) => match status { - PatchStatus::NotAvailable => tr("main-window--patch-unavailable-tooltip"), + PatchStatus::NotAvailable => tr!("main-window--patch-unavailable-tooltip"), PatchStatus::Outdated { .. } | - PatchStatus::Preparation { .. } => tr("main-window--patch-outdated-tooltip"), + PatchStatus::Preparation { .. } => tr!("main-window--patch-outdated-tooltip"), _ => String::new() }, @@ -507,6 +539,97 @@ impl SimpleComponent for App { } }, + adw::Bin { + set_css_classes: &["background", "round-bin"], + + #[watch] + set_visible: model.kill_game_button, + + gtk::Button { + adw::ButtonContent { + set_icon_name: "violence-symbolic", // window-close-symbolic + set_label: &tr!("kill-game-process") + }, + + #[watch] + set_visible: model.kill_game_button, + + #[watch] + set_sensitive: !model.disabled_kill_game_button, + + set_css_classes: &["error", "pill"], + + set_hexpand: false, + set_width_request: 200, + + connect_clicked[sender] => move |_| { + sender.input(AppMsg::DisableKillGameButton(true)); + + std::thread::spawn(clone!(@strong sender => move || { + std::thread::sleep(std::time::Duration::from_secs(3)); + + sender.input(AppMsg::DisableKillGameButton(false)); + })); + + let result = std::process::Command::new("pkill") + .arg("GenshinImpact|YuanShen|unlocker\\.exe") + .spawn(); + + if let Err(err) = result { + sender.input(AppMsg::Toast { + title: tr!("kill-game-process-failed"), + description: Some(err.to_string()) + }); + } + + // Doesn't work on all the systems + // e.g. won't work if you didn't install wine system-wide + // there's some reasons for it + + // match Config::get() { + // Ok(config) => { + // match config.get_selected_wine() { + // Ok(Some(version)) => { + // use anime_launcher_sdk::wincompatlib::prelude::*; + + // let result = version.to_wine(config.components.path, Some(config.game.wine.builds.join(&version.name))) + // .stop_processes(false); + + // if let Err(err) = result { + // sender.input(AppMsg::Toast { + // title: tr!("kill-game-process-failed"), + // description: Some(err.to_string()) + // }); + // } + // } + + // Ok(None) => { + // sender.input(AppMsg::Toast { + // title: tr!("failed-get-selected-wine"), + // description: None + // }); + // } + + // Err(err) => { + // sender.input(AppMsg::Toast { + // title: tr!("failed-get-selected-wine"), + // description: Some(err.to_string()) + // }); + // } + // } + // } + + // Err(err) => { + // sender.input(AppMsg::Toast { + // title: tr!("config-file-opening-error"), + // description: Some(err.to_string()) + // }); + // } + // } + } + } + }, + adw::Bin { set_css_classes: &["background", "round-bin"], @@ -531,7 +654,7 @@ impl SimpleComponent for App { connect_close_request[sender] => move |_| { if let Err(err) = Config::flush() { sender.input(AppMsg::Toast { - title: tr("config-update-error"), + title: tr!("config-update-error"), description: Some(err.to_string()) }); } @@ -565,7 +688,9 @@ impl SimpleComponent for App { state: None, downloading: false, - disabled_buttons: false + disabled_buttons: false, + kill_game_button: false, + disabled_kill_game_button: false }; model.progress_bar.widget().set_halign(gtk::Align::Center); @@ -597,7 +722,7 @@ impl SimpleComponent for App { group.add_action::(RelmAction::new_stateless(clone!(@strong sender => move |_| { if let Err(err) = open::that(LAUNCHER_FOLDER.as_path()) { sender.input(AppMsg::Toast { - title: tr("launcher-folder-opening-error"), + title: tr!("launcher-folder-opening-error"), description: Some(err.to_string()) }); @@ -613,7 +738,7 @@ impl SimpleComponent for App { if let Err(err) = open::that(path) { sender.input(AppMsg::Toast { - title: tr("game-folder-opening-error"), + title: tr!("game-folder-opening-error"), description: Some(err.to_string()) }); @@ -625,7 +750,7 @@ impl SimpleComponent for App { if let Ok(file) = config_file() { if let Err(err) = open::that(file) { sender.input(AppMsg::Toast { - title: tr("config-file-opening-error"), + title: tr!("config-file-opening-error"), description: Some(err.to_string()) }); @@ -637,7 +762,7 @@ impl SimpleComponent for App { group.add_action::(RelmAction::new_stateless(clone!(@strong sender => move |_| { if let Err(err) = open::that(crate::DEBUG_FILE.as_os_str()) { sender.input(AppMsg::Toast { - title: tr("debug-file-opening-error"), + title: tr!("debug-file-opening-error"), description: Some(err.to_string()) }); @@ -685,7 +810,7 @@ impl SimpleComponent for App { tracing::error!("Failed to open wishes URL: {err}"); sender.input(AppMsg::Toast { - title: tr("wish-url-opening-error"), + title: tr!("wish-url-opening-error"), description: Some(err.to_string()) }); } @@ -695,7 +820,7 @@ impl SimpleComponent for App { tracing::error!("Couldn't find wishes URL: no url found"); sender.input(AppMsg::Toast { - title: tr("wish-url-search-failed"), + title: tr!("wish-url-search-failed"), description: None }); } @@ -705,7 +830,7 @@ impl SimpleComponent for App { tracing::error!("Couldn't find wishes URL: failed to open cache file: {err}"); sender.input(AppMsg::Toast { - title: tr("wish-url-search-failed"), + title: tr!("wish-url-search-failed"), description: Some(err.to_string()) }); } @@ -716,7 +841,7 @@ impl SimpleComponent for App { tracing::error!("Couldn't find wishes URL: cache file doesn't exist"); sender.input(AppMsg::Toast { - title: tr("wish-url-search-failed"), + title: tr!("wish-url-search-failed"), description: None }); } @@ -747,7 +872,7 @@ impl SimpleComponent for App { tracing::error!("Failed to download background picture: {err}"); sender.input(AppMsg::Toast { - title: tr("background-downloading-failed"), + title: tr!("background-downloading-failed"), description: Some(err.to_string()) }); } @@ -767,7 +892,7 @@ impl SimpleComponent for App { match components.sync(host) { Ok(changes) => { sender.input(AppMsg::Toast { - title: tr("components-index-updated"), + title: tr!("components-index-updated"), description: if changes.is_empty() { None } else { @@ -785,7 +910,7 @@ impl SimpleComponent for App { tracing::error!("Failed to sync components index"); sender.input(AppMsg::Toast { - title: tr("components-index-sync-failed"), + title: tr!("components-index-sync-failed"), description: Some(err.to_string()) }); } @@ -797,7 +922,7 @@ impl SimpleComponent for App { tracing::error!("Failed to verify that components index synced"); sender.input(AppMsg::Toast { - title: tr("components-index-verify-failed"), + title: tr!("components-index-verify-failed"), description: Some(err.to_string()) }); } @@ -822,7 +947,7 @@ impl SimpleComponent for App { tracing::error!("Failed to sync patch folder with remote: {server}: {err}"); sender.input(AppMsg::Toast { - title: tr("patch-sync-failed"), + title: tr!("patch-sync-failed"), description: Some(err.to_string()) }); } @@ -834,7 +959,7 @@ impl SimpleComponent for App { tracing::error!("Failed to compare local patch folder with remote: {err}"); sender.input(AppMsg::Toast { - title: tr("patch-state-check-failed"), + title: tr!("patch-state-check-failed"), description: Some(err.to_string()) }); } @@ -848,7 +973,7 @@ impl SimpleComponent for App { tracing::error!("Failed to fetch player patch info: {err}"); sender.input(AppMsg::Toast { - title: tr("patch-info-fetching-error"), + title: tr!("patch-info-fetching-error"), description: Some(err.to_string()) }); @@ -868,7 +993,7 @@ impl SimpleComponent for App { tracing::error!("Failed to find game diff: {err}"); sender.input(AppMsg::Toast { - title: tr("game-diff-finding-error"), + title: tr!("game-diff-finding-error"), description: Some(err.to_string()) }); @@ -906,7 +1031,7 @@ impl SimpleComponent for App { // TODO: make function from this message like with toast AppMsg::UpdateLauncherState { perform_on_download_needed, show_status_page } => { if show_status_page { - sender.input(AppMsg::SetLoadingStatus(Some(Some(tr("loading-launcher-state"))))); + sender.input(AppMsg::SetLoadingStatus(Some(Some(tr!("loading-launcher-state"))))); } else { self.disabled_buttons = true; } @@ -915,17 +1040,17 @@ impl SimpleComponent for App { if show_status_page { match state { StateUpdating::Game => { - sender.input(AppMsg::SetLoadingStatus(Some(Some(tr("loading-launcher-state--game"))))); + sender.input(AppMsg::SetLoadingStatus(Some(Some(tr!("loading-launcher-state--game"))))); } StateUpdating::Voice(locale) => { - sender.input(AppMsg::SetLoadingStatus(Some(Some(tr_args("loading-launcher-state--voice", [ - ("locale", locale.to_name().to_owned().into()) - ]))))); + sender.input(AppMsg::SetLoadingStatus(Some(Some(tr!("loading-launcher-state--voice", { + "locale" = locale.to_name() + }))))); } StateUpdating::Patch => { - sender.input(AppMsg::SetLoadingStatus(Some(Some(tr("loading-launcher-state--patch"))))); + sender.input(AppMsg::SetLoadingStatus(Some(Some(tr!("loading-launcher-state--patch"))))); } } } @@ -936,7 +1061,7 @@ impl SimpleComponent for App { Err(err) => { tracing::error!("Failed to update launcher state: {err}"); - self.toast(tr("launcher-state-updating-error"), Some(err.to_string())); + self.toast(tr!("launcher-state-updating-error"), Some(err.to_string())); None } @@ -994,6 +1119,14 @@ impl SimpleComponent for App { self.disabled_buttons = state; } + AppMsg::SetKillGameButton(state) => { + self.kill_game_button = state; + } + + AppMsg::DisableKillGameButton(state) => { + self.disabled_kill_game_button = state; + } + AppMsg::OpenPreferences => unsafe { PREFERENCES_WINDOW.as_ref().unwrap_unchecked().widget().present(); } @@ -1009,7 +1142,7 @@ impl SimpleComponent for App { let progress_bar_input = self.progress_bar.sender().clone(); - progress_bar_input.send(ProgressBarMsg::UpdateCaption(Some(tr("downloading")))); + progress_bar_input.send(ProgressBarMsg::UpdateCaption(Some(tr!("downloading")))); let mut diffs: Vec = vec![game]; @@ -1023,7 +1156,7 @@ impl SimpleComponent for App { if let Err(err) = result { sender.input(AppMsg::Toast { - title: tr("downloading-failed"), + title: tr!("downloading-failed"), description: Some(err.to_string()) }); @@ -1090,7 +1223,7 @@ impl App { toast.set_timeout(4); if let Some(description) = description { - toast.set_button_label(Some(&tr("details"))); + toast.set_button_label(Some(&tr!("details"))); let dialog = adw::MessageDialog::new( Some(unsafe { MAIN_WINDOW.as_ref().unwrap_unchecked() }), @@ -1098,8 +1231,8 @@ impl App { Some(description.as_ref()) ); - dialog.add_response("close", &tr("close")); - dialog.add_response("save", &tr("save")); + dialog.add_response("close", &tr!("close", { "form" = "noun" })); + dialog.add_response("save", &tr!("save")); dialog.set_response_appearance("save", adw::ResponseAppearance::Suggested); diff --git a/src/ui/main/repair_game.rs b/src/ui/main/repair_game.rs index cb56657..c089f92 100644 --- a/src/ui/main/repair_game.rs +++ b/src/ui/main/repair_game.rs @@ -8,7 +8,6 @@ use relm4::{ use gtk::glib::clone; use crate::*; -use crate::i18n::*; use crate::ui::components::*; use super::{App, AppMsg}; @@ -17,7 +16,7 @@ use super::{App, AppMsg}; pub fn repair_game(sender: ComponentSender, progress_bar_input: Sender) { let config = Config::get().unwrap(); - progress_bar_input.send(ProgressBarMsg::UpdateCaption(Some(tr("verifying-files")))); + progress_bar_input.send(ProgressBarMsg::UpdateCaption(Some(tr!("verifying-files")))); sender.input(AppMsg::SetDownloading(true)); std::thread::spawn(move || { @@ -100,7 +99,7 @@ pub fn repair_game(sender: ComponentSender, progress_bar_input: Sender, progress_bar_input: Sender, progress_bar_input: Sender EnvironmentPageMsg::Add @@ -142,12 +141,12 @@ impl SimpleAsyncComponent for EnvironmentPage { #[local_ref] name_entry -> adw::EntryRow { - set_title: &tr("name") + set_title: &tr!("name") }, #[local_ref] value_entry -> adw::EntryRow { - set_title: &tr("value") + set_title: &tr!("value") } }, diff --git a/src/ui/preferences/enhancements/game.rs b/src/ui/preferences/enhancements/game.rs index 59e1298..78857cd 100644 --- a/src/ui/preferences/enhancements/game.rs +++ b/src/ui/preferences/enhancements/game.rs @@ -7,11 +7,10 @@ use adw::prelude::*; use anime_launcher_sdk::sessions::SessionsExt; use anime_launcher_sdk::genshin::sessions::Sessions; -use super::EnhancementsAppMsg; - -use crate::i18n::tr; use crate::*; +use super::EnhancementsAppMsg; + #[derive(Debug)] struct GameSession { name: String, @@ -44,7 +43,7 @@ impl AsyncFactoryComponent for GameSession { set_icon_name: "view-refresh-symbolic", add_css_class: "flat", - set_tooltip_text: Some(&tr("update-session")), + set_tooltip_text: Some(&tr!("update-session")), set_valign: gtk::Align::Center, @@ -57,7 +56,7 @@ impl AsyncFactoryComponent for GameSession { set_icon_name: "user-trash-symbolic", add_css_class: "flat", - set_tooltip_text: Some(&tr("delete-session")), + set_tooltip_text: Some(&tr!("delete-session")), set_valign: gtk::Align::Center, @@ -115,7 +114,7 @@ impl SimpleAsyncComponent for GamePage { adw::HeaderBar { #[wrap(Some)] set_title_widget = &adw::WindowTitle { - set_title: &tr("game") + set_title: &tr!("game") }, pack_start = >k::Button { @@ -128,15 +127,15 @@ impl SimpleAsyncComponent for GamePage { }, adw::PreferencesPage { - set_title: &tr("game"), + set_title: &tr!("game"), set_icon_name: Some("applications-games-symbolic"), add = &adw::PreferencesGroup { - set_title: &tr("game-sessions"), + set_title: &tr!("game-sessions"), #[local_ref] session_name_entry -> adw::EntryRow { - set_title: &tr("name"), + set_title: &tr!("name"), add_suffix = >k::Button { set_icon_name: "list-add-symbolic", @@ -220,7 +219,7 @@ impl SimpleAsyncComponent for GamePage { Err(err) => { sender.output(EnhancementsAppMsg::Toast { - title: tr("game-session-add-failed"), + title: tr!("game-session-add-failed"), description: Some(err.to_string()) }).unwrap(); } @@ -234,7 +233,7 @@ impl SimpleAsyncComponent for GamePage { if let Ok(config) = Config::get() { if let Err(err) = Sessions::update(session.name.clone(), config.get_wine_prefix_path()) { sender.output(EnhancementsAppMsg::Toast { - title: tr("game-session-update-failed"), + title: tr!("game-session-update-failed"), description: Some(err.to_string()) }).unwrap(); } @@ -246,7 +245,7 @@ impl SimpleAsyncComponent for GamePage { if let Some(session) = self.sessions.guard().get(index) { if let Err(err) = Sessions::remove(&session.name) { sender.output(EnhancementsAppMsg::Toast { - title: tr("game-session-remove-failed"), + title: tr!("game-session-remove-failed"), description: Some(err.to_string()) }).unwrap(); @@ -266,7 +265,7 @@ impl SimpleAsyncComponent for GamePage { if let Ok(config) = Config::get() { if let Err(err) = Sessions::set_current(session.name.clone()) { sender.output(EnhancementsAppMsg::Toast { - title: tr("game-session-set-current-failed"), + title: tr!("game-session-set-current-failed"), description: Some(err.to_string()) }).unwrap(); @@ -276,7 +275,7 @@ impl SimpleAsyncComponent for GamePage { if let Err(err) = Sessions::apply(session.name.clone(), config.get_wine_prefix_path()) { sender.output(EnhancementsAppMsg::Toast { - title: tr("game-session-apply-failed"), + title: tr!("game-session-apply-failed"), description: Some(err.to_string()) }).unwrap(); diff --git a/src/ui/preferences/enhancements/mod.rs b/src/ui/preferences/enhancements/mod.rs index f4516e6..6f5414a 100644 --- a/src/ui/preferences/enhancements/mod.rs +++ b/src/ui/preferences/enhancements/mod.rs @@ -21,7 +21,6 @@ use game::*; use sandbox::*; use environment::*; -use crate::i18n::tr; use crate::*; use super::gamescope::*; @@ -123,15 +122,15 @@ impl SimpleAsyncComponent for EnhancementsApp { view! { #[root] adw::PreferencesPage { - set_title: &tr("enhancements"), + set_title: &tr!("enhancements"), set_icon_name: Some("applications-graphics-symbolic"), add = &adw::PreferencesGroup { - set_title: &tr("options"), + set_title: &tr!("options"), adw::ActionRow { - set_title: &tr("game"), - set_subtitle: &tr("game-settings-description"), + set_title: &tr!("game"), + set_subtitle: &tr!("game-settings-description"), add_suffix = >k::Image { set_icon_name: Some("go-next-symbolic") @@ -143,8 +142,8 @@ impl SimpleAsyncComponent for EnhancementsApp { }, adw::ActionRow { - set_title: &tr("sandbox"), - set_subtitle: &tr("sandbox-settings-description"), + set_title: &tr!("sandbox"), + set_subtitle: &tr!("sandbox-settings-description"), add_suffix = >k::Image { set_icon_name: Some("go-next-symbolic") @@ -156,8 +155,8 @@ impl SimpleAsyncComponent for EnhancementsApp { }, adw::ActionRow { - set_title: &tr("environment"), - set_subtitle: &tr("environment-settings-description"), + set_title: &tr!("environment"), + set_subtitle: &tr!("environment-settings-description"), add_suffix = >k::Image { set_icon_name: Some("go-next-symbolic") @@ -170,15 +169,15 @@ impl SimpleAsyncComponent for EnhancementsApp { }, add = &adw::PreferencesGroup { - set_title: &tr("wine"), + set_title: &tr!("wine"), adw::ComboRow { - set_title: &tr("synchronization"), - set_subtitle: &tr("wine-sync-description"), + set_title: &tr!("synchronization"), + set_subtitle: &tr!("wine-sync-description"), #[wrap(Some)] set_model = >k::StringList::new(&[ - &tr("none"), + &tr!("none"), "ESync", "FSync" ]), @@ -197,12 +196,12 @@ impl SimpleAsyncComponent for EnhancementsApp { }, adw::ComboRow { - set_title: &tr("language"), - set_subtitle: &tr("wine-lang-description"), + set_title: &tr!("language"), + set_subtitle: &tr!("wine-lang-description"), #[wrap(Some)] set_model = >k::StringList::new(&[ - &tr("system"), + &tr!("system"), "English", "Русский", "Deutsch", @@ -229,7 +228,7 @@ impl SimpleAsyncComponent for EnhancementsApp { }, adw::ActionRow { - set_title: &tr("borderless-window"), + set_title: &tr!("borderless-window"), add_suffix = >k::Switch { set_valign: gtk::Align::Center, @@ -249,7 +248,7 @@ impl SimpleAsyncComponent for EnhancementsApp { }, adw::ComboRow { - set_title: &tr("virtual-desktop"), + set_title: &tr!("virtual-desktop"), #[wrap(Some)] set_model = >k::StringList::new(&[ @@ -258,7 +257,7 @@ impl SimpleAsyncComponent for EnhancementsApp { "1920x1080", "2560x1440", "3840x2160", - &tr("custom") + &tr!("custom") ]), set_selected: CONFIG.game.wine.virtual_desktop.get_resolution().into(), @@ -295,14 +294,14 @@ impl SimpleAsyncComponent for EnhancementsApp { }, add = &adw::PreferencesGroup { - set_title: &tr("game"), + set_title: &tr!("game"), adw::ComboRow { - set_title: &tr("hud"), + set_title: &tr!("hud"), #[wrap(Some)] set_model = >k::StringList::new(&[ - &tr("none"), + &tr!("none"), "DXVK", "MangoHud" ]), @@ -321,15 +320,15 @@ impl SimpleAsyncComponent for EnhancementsApp { }, adw::ComboRow { - set_title: &tr("fsr"), - set_subtitle: &tr("fsr-description"), + set_title: &tr!("fsr"), + set_subtitle: &tr!("fsr-description"), #[wrap(Some)] set_model = >k::StringList::new(&[ - &tr("ultra-quality"), - &tr("quality"), - &tr("balanced"), - &tr("performance") + &tr!("ultra-quality"), + &tr!("quality"), + &tr!("balanced"), + &tr!("performance") ]), set_selected: CONFIG.game.enhancements.fsr.quality.ordinal() as u32, @@ -362,8 +361,8 @@ impl SimpleAsyncComponent for EnhancementsApp { }, adw::ActionRow { - set_title: &tr("gamemode"), - set_subtitle: &tr("gamemode-description"), + set_title: &tr!("gamemode"), + set_subtitle: &tr!("gamemode-description"), set_sensitive: is_available("gamemoderun"), @@ -385,8 +384,8 @@ impl SimpleAsyncComponent for EnhancementsApp { }, adw::ActionRow { - set_title: &tr("gamescope"), - set_subtitle: &tr("gamescope-description"), + set_title: &tr!("gamescope"), + set_subtitle: &tr!("gamescope-description"), set_sensitive: is_available("gamescope"), @@ -418,11 +417,11 @@ impl SimpleAsyncComponent for EnhancementsApp { }, add = &adw::PreferencesGroup { - set_title: &tr("discord-rpc"), + set_title: &tr!("discord-rpc"), adw::ActionRow { - set_title: &tr("enabled"), - set_subtitle: &tr("discord-rpc-description"), + set_title: &tr!("enabled"), + set_subtitle: &tr!("discord-rpc-description"), add_suffix = >k::Switch { set_valign: gtk::Align::Center, @@ -442,11 +441,11 @@ impl SimpleAsyncComponent for EnhancementsApp { #[local_ref] discord_rpc_icons -> adw::ExpanderRow { - set_title: &tr("icon") + set_title: &tr!("icon") }, adw::EntryRow { - set_title: &tr("title"), + set_title: &tr!("title"), set_text: &CONFIG.launcher.discord_rpc.title, connect_changed: |row| { @@ -461,7 +460,7 @@ impl SimpleAsyncComponent for EnhancementsApp { }, adw::EntryRow { - set_title: &tr("description"), + set_title: &tr!("description"), set_text: &CONFIG.launcher.discord_rpc.subtitle, connect_changed: |row| { @@ -477,11 +476,11 @@ impl SimpleAsyncComponent for EnhancementsApp { }, add = &adw::PreferencesGroup { - set_title: &tr("fps-unlocker"), + set_title: &tr!("fps-unlocker"), adw::ComboRow { - set_title: &tr("enabled"), - set_subtitle: &tr("fps-unlocker-description"), + set_title: &tr!("enabled"), + set_subtitle: &tr!("fps-unlocker-description"), #[wrap(Some)] set_model = >k::StringList::new(&[ @@ -492,7 +491,7 @@ impl SimpleAsyncComponent for EnhancementsApp { "180", "200", "240", - &tr("custom") + &tr!("custom") ]), set_selected: match Fps::from_num(CONFIG.game.enhancements.fps_unlocker.config.fps) { @@ -535,8 +534,8 @@ impl SimpleAsyncComponent for EnhancementsApp { }, adw::ActionRow { - set_title: &tr("power-saving"), - set_subtitle: &tr("power-saving-description"), + set_title: &tr!("power-saving"), + set_subtitle: &tr!("power-saving-description"), add_suffix = >k::Switch { set_valign: gtk::Align::Center, @@ -556,8 +555,8 @@ impl SimpleAsyncComponent for EnhancementsApp { }, adw::ActionRow { - set_title: &tr("monitor"), - set_subtitle: &tr("monitor-description"), + set_title: &tr!("monitor"), + set_subtitle: &tr!("monitor-description"), add_suffix = >k::SpinButton { set_valign: gtk::Align::Center, @@ -578,13 +577,13 @@ impl SimpleAsyncComponent for EnhancementsApp { }, adw::ComboRow { - set_title: &tr("window-mode"), + set_title: &tr!("window-mode"), #[wrap(Some)] set_model = >k::StringList::new(&[ - &tr("default"), - &tr("popup"), - &tr("fullscreen") + &tr!("default"), + &tr!("popup"), + &tr!("fullscreen") ]), set_selected: CONFIG.game.enhancements.fps_unlocker.config.window_mode.ordinal() as u32, @@ -601,17 +600,17 @@ impl SimpleAsyncComponent for EnhancementsApp { }, adw::ComboRow { - set_title: &tr("priority"), - set_subtitle: &tr("priority-description"), + set_title: &tr!("priority"), + set_subtitle: &tr!("priority-description"), #[wrap(Some)] set_model = >k::StringList::new(&[ - &tr("realtime"), - &tr("high"), - &tr("above-normal"), - &tr("normal"), - &tr("below-normal"), - &tr("low") + &tr!("realtime"), + &tr!("high"), + &tr!("above-normal"), + &tr!("normal"), + &tr!("below-normal"), + &tr!("low") ]), set_selected: CONFIG.game.enhancements.fps_unlocker.config.priority as u32, @@ -699,7 +698,7 @@ impl SimpleAsyncComponent for EnhancementsApp { /*if let Err(err) = result { sender.input(EnhancementsAppMsg::Toast { - title: tr("discord-rpc-icon-download-failed"), + title: tr!("discord-rpc-icon-download-failed"), description: Some(err.to_string()) }); }*/ @@ -726,7 +725,7 @@ impl SimpleAsyncComponent for EnhancementsApp { } Err(err) => sender.input(EnhancementsAppMsg::Toast { - title: tr("discord-rpc-icons-fetch-failed"), + title: tr!("discord-rpc-icons-fetch-failed"), description: Some(err.to_string()) }) } diff --git a/src/ui/preferences/enhancements/sandbox.rs b/src/ui/preferences/enhancements/sandbox.rs index 73cf21a..24c5cd0 100644 --- a/src/ui/preferences/enhancements/sandbox.rs +++ b/src/ui/preferences/enhancements/sandbox.rs @@ -8,7 +8,6 @@ use anime_launcher_sdk::is_available; use super::EnhancementsAppMsg; -use crate::i18n::tr; use crate::*; macro_rules! impl_directory { @@ -110,7 +109,7 @@ impl SimpleAsyncComponent for SandboxPage { adw::HeaderBar { #[wrap(Some)] set_title_widget = &adw::WindowTitle { - set_title: &tr("sandbox") + set_title: &tr!("sandbox") }, pack_start = >k::Button { @@ -123,18 +122,18 @@ impl SimpleAsyncComponent for SandboxPage { }, adw::PreferencesPage { - set_title: &tr("sandbox"), + set_title: &tr!("sandbox"), set_icon_name: Some("folder-symbolic"), set_sensitive: is_available("bwrap"), add = &adw::PreferencesGroup { - set_title: &tr("sandbox"), - set_description: Some(&tr("sandbox-description")), + set_title: &tr!("sandbox"), + set_description: Some(&tr!("sandbox-description")), adw::ActionRow { - set_title: &tr("enable-sandboxing"), - set_subtitle: &tr("enable-sandboxing-description"), + set_title: &tr!("enable-sandboxing"), + set_subtitle: &tr!("enable-sandboxing-description"), add_suffix = >k::Switch { set_valign: gtk::Align::Center, @@ -154,8 +153,8 @@ impl SimpleAsyncComponent for SandboxPage { }, adw::ActionRow { - set_title: &tr("hide-home-directory"), - set_subtitle: &tr("hide-home-directory-description"), + set_title: &tr!("hide-home-directory"), + set_subtitle: &tr!("hide-home-directory-description"), add_suffix = >k::Switch { set_valign: gtk::Align::Center, @@ -175,7 +174,7 @@ impl SimpleAsyncComponent for SandboxPage { }, adw::EntryRow { - set_title: &tr("hostname"), + set_title: &tr!("hostname"), set_text: CONFIG.sandbox.hostname.as_ref().unwrap_or(&String::new()).trim(), connect_changed => |entry| { @@ -194,7 +193,7 @@ impl SimpleAsyncComponent for SandboxPage { }, adw::EntryRow { - set_title: &tr("additional-arguments"), + set_title: &tr!("additional-arguments"), set_text: CONFIG.sandbox.args.as_ref().unwrap_or(&String::new()).trim(), connect_changed => |entry| { @@ -220,7 +219,7 @@ impl SimpleAsyncComponent for SandboxPage { connect_clicked[sender] => move |_| { if let Err(err) = open::that("https://man.archlinux.org/man/bwrap.1") { sender.output(EnhancementsAppMsg::Toast { - title: tr("documentation-url-open-failed"), + title: tr!("documentation-url-open-failed"), description: Some(err.to_string()) }).unwrap(); } @@ -230,12 +229,12 @@ impl SimpleAsyncComponent for SandboxPage { }, add = &adw::PreferencesGroup { - set_title: &tr("private-directories"), - set_description: Some(&tr("private-directories-description")), + set_title: &tr!("private-directories"), + set_description: Some(&tr!("private-directories-description")), #[local_ref] private_path_entry -> adw::EntryRow { - set_title: &tr("path"), + set_title: &tr!("path"), add_suffix = >k::Button { set_icon_name: "list-add-symbolic", @@ -252,8 +251,8 @@ impl SimpleAsyncComponent for SandboxPage { add = private_paths -> adw::PreferencesGroup {}, add = &adw::PreferencesGroup { - set_title: &tr("shared-directories"), - set_description: Some(&tr("shared-directories-description")), + set_title: &tr!("shared-directories"), + set_description: Some(&tr!("shared-directories-description")), #[wrap(Some)] set_header_suffix = >k::Button { @@ -263,7 +262,7 @@ impl SimpleAsyncComponent for SandboxPage { adw::ButtonContent { set_icon_name: "list-add-symbolic", - set_label: &tr("add") + set_label: &tr!("add") }, connect_clicked => SandboxPageMsg::AddShared @@ -271,17 +270,17 @@ impl SimpleAsyncComponent for SandboxPage { #[local_ref] shared_path_from_entry -> adw::EntryRow { - set_title: &tr("original-path") + set_title: &tr!("original-path") }, #[local_ref] shared_path_to_entry -> adw::EntryRow { - set_title: &tr("new-path") + set_title: &tr!("new-path") }, adw::ActionRow { - set_title: &tr("read-only"), - set_subtitle: &tr("read-only-description"), + set_title: &tr!("read-only"), + set_subtitle: &tr!("read-only-description"), #[local_ref] add_suffix = read_only_switch -> gtk::Switch { @@ -294,8 +293,8 @@ impl SimpleAsyncComponent for SandboxPage { add = shared_paths -> adw::PreferencesGroup {}, add = &adw::PreferencesGroup { - set_title: &tr("symlinks"), - set_description: Some(&tr("symlinks-description")), + set_title: &tr!("symlinks"), + set_description: Some(&tr!("symlinks-description")), #[wrap(Some)] set_header_suffix = >k::Button { @@ -305,7 +304,7 @@ impl SimpleAsyncComponent for SandboxPage { adw::ButtonContent { set_icon_name: "list-add-symbolic", - set_label: &tr("add") + set_label: &tr!("add") }, connect_clicked => SandboxPageMsg::AddSymlink @@ -313,12 +312,12 @@ impl SimpleAsyncComponent for SandboxPage { #[local_ref] symlink_path_from_entry -> adw::EntryRow { - set_title: &tr("original-path") + set_title: &tr!("original-path") }, #[local_ref] symlink_path_to_entry -> adw::EntryRow { - set_title: &tr("new-path") + set_title: &tr!("new-path") } }, diff --git a/src/ui/preferences/gamescope.rs b/src/ui/preferences/gamescope.rs index b91480f..c5db371 100644 --- a/src/ui/preferences/gamescope.rs +++ b/src/ui/preferences/gamescope.rs @@ -8,7 +8,6 @@ use anime_launcher_sdk::genshin::config::Config; use anime_launcher_sdk::config::schema_blanks::prelude::*; -use crate::i18n::tr; use crate::*; pub struct GamescopeApp; @@ -21,7 +20,7 @@ impl SimpleAsyncComponent for GamescopeApp { view! { adw::PreferencesWindow { - set_title: Some(&tr("gamescope")), + set_title: Some(&tr!("gamescope")), set_modal: true, set_hide_on_close: true, @@ -31,10 +30,10 @@ impl SimpleAsyncComponent for GamescopeApp { add = &adw::PreferencesPage { add = &adw::PreferencesGroup { - set_title: &tr("game-resolution"), + set_title: &tr!("game-resolution"), adw::EntryRow { - set_title: &tr("width"), + set_title: &tr!("width"), set_input_purpose: gtk::InputPurpose::Digits, set_text: &if CONFIG.game.enhancements.gamescope.game.width > 0 { @@ -55,7 +54,7 @@ impl SimpleAsyncComponent for GamescopeApp { }, adw::EntryRow { - set_title: &tr("height"), + set_title: &tr!("height"), set_input_purpose: gtk::InputPurpose::Digits, set_text: &if CONFIG.game.enhancements.gamescope.game.height > 0 { @@ -77,10 +76,10 @@ impl SimpleAsyncComponent for GamescopeApp { }, add = &adw::PreferencesGroup { - set_title: &tr("gamescope-resolution"), + set_title: &tr!("gamescope-resolution"), adw::EntryRow { - set_title: &tr("width"), + set_title: &tr!("width"), set_input_purpose: gtk::InputPurpose::Digits, set_text: &if CONFIG.game.enhancements.gamescope.gamescope.width > 0 { @@ -101,7 +100,7 @@ impl SimpleAsyncComponent for GamescopeApp { }, adw::EntryRow { - set_title: &tr("height"), + set_title: &tr!("height"), set_input_purpose: gtk::InputPurpose::Digits, set_text: &if CONFIG.game.enhancements.gamescope.gamescope.height > 0 { @@ -123,11 +122,11 @@ impl SimpleAsyncComponent for GamescopeApp { }, add = &adw::PreferencesGroup { - set_title: &tr("upscaling"), + set_title: &tr!("upscaling"), adw::ActionRow { - set_title: &tr("integer-scaling"), - set_subtitle: &tr("integer-scaling-description"), + set_title: &tr!("integer-scaling"), + set_subtitle: &tr!("integer-scaling-description"), add_suffix = >k::Switch { set_valign: gtk::Align::Center, @@ -147,7 +146,7 @@ impl SimpleAsyncComponent for GamescopeApp { adw::ActionRow { set_title: "FSR", - set_subtitle: &tr("gamescope-fsr-description"), + set_subtitle: &tr!("gamescope-fsr-description"), add_suffix = >k::Switch { set_valign: gtk::Align::Center, @@ -167,7 +166,7 @@ impl SimpleAsyncComponent for GamescopeApp { adw::ActionRow { set_title: "Nvidia Image Scaling", - set_subtitle: &tr("nis-description"), + set_subtitle: &tr!("nis-description"), add_suffix = >k::Switch { set_valign: gtk::Align::Center, @@ -187,12 +186,12 @@ impl SimpleAsyncComponent for GamescopeApp { }, add = &adw::PreferencesGroup { - set_title: &tr("other-settings"), + set_title: &tr!("other-settings"), // TODO: maybe use Fps enum like in fps unlocker settings adw::EntryRow { - set_title: &tr("framerate-limit"), + set_title: &tr!("framerate-limit"), set_input_purpose: gtk::InputPurpose::Digits, set_text: &if CONFIG.game.enhancements.gamescope.framerate.focused > 0 { @@ -213,7 +212,7 @@ impl SimpleAsyncComponent for GamescopeApp { }, adw::EntryRow { - set_title: &tr("unfocused-framerate-limit"), + set_title: &tr!("unfocused-framerate-limit"), set_input_purpose: gtk::InputPurpose::Digits, set_text: &if CONFIG.game.enhancements.gamescope.framerate.unfocused > 0 { @@ -234,12 +233,12 @@ impl SimpleAsyncComponent for GamescopeApp { }, adw::ComboRow { - set_title: &tr("window-mode"), + set_title: &tr!("window-mode"), #[wrap(Some)] set_model = >k::StringList::new(&[ - &tr("borderless"), - &tr("fullscreen") + &tr!("borderless"), + &tr!("fullscreen") ]), set_selected: CONFIG.game.enhancements.gamescope.window_type.ordinal() as u32, diff --git a/src/ui/preferences/general/components.rs b/src/ui/preferences/general/components.rs index 17a12a1..988085b 100644 --- a/src/ui/preferences/general/components.rs +++ b/src/ui/preferences/general/components.rs @@ -12,7 +12,6 @@ use anime_launcher_sdk::components::wine::UnifiedWine; use super::GeneralAppMsg; use crate::ui::components::*; -use crate::i18n::*; use crate::*; pub struct ComponentsPage { @@ -58,7 +57,7 @@ impl SimpleAsyncComponent for ComponentsPage { adw::HeaderBar { #[wrap(Some)] set_title_widget = &adw::WindowTitle { - set_title: &tr("components") + set_title: &tr!("components") }, pack_start = >k::Button { @@ -72,10 +71,10 @@ impl SimpleAsyncComponent for ComponentsPage { adw::PreferencesPage { add = &adw::PreferencesGroup { - set_title: &tr("wine-version"), + set_title: &tr!("wine-version"), adw::ComboRow { - set_title: &tr("selected-version"), + set_title: &tr!("selected-version"), #[watch] #[block_signal(wine_selected_notify)] @@ -103,8 +102,8 @@ impl SimpleAsyncComponent for ComponentsPage { }, adw::ActionRow { - set_title: &tr("recommended-only"), - set_subtitle: &tr("wine-recommended-description"), + set_title: &tr!("recommended-only"), + set_subtitle: &tr!("wine-recommended-description"), add_suffix = >k::Switch { set_valign: gtk::Align::Center, @@ -126,11 +125,11 @@ impl SimpleAsyncComponent for ComponentsPage { }, add = &adw::PreferencesGroup { - set_title: &tr("wine-options"), + set_title: &tr!("wine-options"), adw::ActionRow { - set_title: &tr("wine-use-shared-libraries"), - set_subtitle: &tr("wine-use-shared-libraries-description"), + set_title: &tr!("wine-use-shared-libraries"), + set_subtitle: &tr!("wine-use-shared-libraries-description"), add_suffix = >k::Switch { set_valign: gtk::Align::Center, @@ -151,8 +150,8 @@ impl SimpleAsyncComponent for ComponentsPage { }, adw::ActionRow { - set_title: &tr("gstreamer-use-shared-libraries"), - set_subtitle: &tr("gstreamer-use-shared-libraries-description"), + set_title: &tr!("gstreamer-use-shared-libraries"), + set_subtitle: &tr!("gstreamer-use-shared-libraries-description"), add_suffix = >k::Switch { set_valign: gtk::Align::Center, @@ -174,11 +173,11 @@ impl SimpleAsyncComponent for ComponentsPage { }, add = &adw::PreferencesGroup { - set_title: &tr("dxvk-version"), + set_title: &tr!("dxvk-version"), #[watch] set_description: Some(&if !model.allow_dxvk_selection { - tr("dxvk-selection-disabled") + tr!("dxvk-selection-disabled") } else { String::new() }), @@ -187,7 +186,7 @@ impl SimpleAsyncComponent for ComponentsPage { set_sensitive: model.allow_dxvk_selection, adw::ComboRow { - set_title: &tr("selected-version"), + set_title: &tr!("selected-version"), #[watch] #[block_signal(dxvk_selected_notify)] @@ -215,8 +214,8 @@ impl SimpleAsyncComponent for ComponentsPage { }, adw::ActionRow { - set_title: &tr("recommended-only"), - set_subtitle: &tr("dxvk-recommended-description"), + set_title: &tr!("recommended-only"), + set_subtitle: &tr!("dxvk-recommended-description"), add_suffix = >k::Switch { set_valign: gtk::Align::Center, @@ -433,7 +432,7 @@ impl SimpleAsyncComponent for ComponentsPage { Err(err) => { sender.output(GeneralAppMsg::Toast { - title: tr("wine-prefix-update-failed"), + title: tr!("wine-prefix-update-failed"), description: Some(err.to_string()) }).unwrap(); } @@ -476,7 +475,7 @@ impl SimpleAsyncComponent for ComponentsPage { std::thread::spawn(move || { if let Err(err) = Dxvk::install(&wine, dxvk_folder, InstallParams::default()) { sender.output(GeneralAppMsg::Toast { - title: tr("dxvk-install-failed"), + title: tr!("dxvk-install-failed"), description: Some(err.to_string()) }).unwrap(); } diff --git a/src/ui/preferences/general/mod.rs b/src/ui/preferences/general/mod.rs index f7f369d..00dac0f 100644 --- a/src/ui/preferences/general/mod.rs +++ b/src/ui/preferences/general/mod.rs @@ -13,7 +13,7 @@ use anime_launcher_sdk::wincompatlib::prelude::*; use anime_launcher_sdk::config::ConfigExt; use anime_launcher_sdk::genshin::config::Config; -use anime_launcher_sdk::genshin::config::schema::launcher::LauncherStyle; +use anime_launcher_sdk::genshin::config::schema::prelude::*; use anime_launcher_sdk::anime_game_core::genshin::consts::GameEdition; use anime_launcher_sdk::genshin::env_emulation::Environment; @@ -22,12 +22,12 @@ pub mod components; use components::*; -use super::main::PreferencesAppMsg; - use crate::ui::migrate_installation::MigrateInstallationApp; use crate::i18n::*; use crate::*; +use super::main::PreferencesAppMsg; + #[derive(Debug)] struct VoicePackageComponent { locale: VoiceLocale, @@ -46,7 +46,7 @@ impl AsyncFactoryComponent for VoicePackageComponent { view! { root = adw::ActionRow { - set_title: &tr(&self.locale.to_name().to_ascii_lowercase()), + set_title: &tr!(&self.locale.to_name().to_ascii_lowercase()), add_suffix = >k::Button { #[watch] @@ -163,11 +163,11 @@ impl SimpleAsyncComponent for GeneralApp { view! { #[root] adw::PreferencesPage { - set_title: &tr("general"), + set_title: &tr!("general"), set_icon_name: Some("applications-system-symbolic"), add = &adw::PreferencesGroup { - set_title: &tr("appearance"), + set_title: &tr!("appearance"), gtk::Box { set_orientation: gtk::Orientation::Horizontal, @@ -188,14 +188,14 @@ impl SimpleAsyncComponent for GeneralApp { set_active: model.style == LauncherStyle::Modern, gtk::Image { - set_from_resource: Some("/org/app/images/modern.svg") + set_resource: Some(&format!("{APP_RESOURCE_PATH}/images/modern.svg")) }, connect_clicked => GeneralAppMsg::UpdateLauncherStyle(LauncherStyle::Modern) }, gtk::Label { - set_text: &tr("modern"), + set_text: &tr!("modern"), set_margin_top: 16 } @@ -214,14 +214,14 @@ impl SimpleAsyncComponent for GeneralApp { set_active: model.style == LauncherStyle::Classic, gtk::Image { - set_from_resource: Some("/org/app/images/classic.svg") + set_resource: Some(&format!("{APP_RESOURCE_PATH}/images/classic.svg")) }, connect_clicked => GeneralAppMsg::UpdateLauncherStyle(LauncherStyle::Classic) }, gtk::Label { - set_text: &tr("classic"), + set_text: &tr!("classic"), set_margin_top: 16 } @@ -234,8 +234,8 @@ impl SimpleAsyncComponent for GeneralApp { set_visible: model.style == LauncherStyle::Classic, adw::ActionRow { - set_title: &tr("update-background"), - set_subtitle: &tr("update-background-description"), + set_title: &tr!("update-background"), + set_subtitle: &tr!("update-background-description"), add_suffix = >k::Switch { set_valign: gtk::Align::Center, @@ -254,11 +254,11 @@ impl SimpleAsyncComponent for GeneralApp { }, add = &adw::PreferencesGroup { - set_title: &tr("general"), + set_title: &tr!("general"), adw::ComboRow { - set_title: &tr("launcher-language"), - set_subtitle: &tr("launcher-language-description"), + set_title: &tr!("launcher-language"), + set_subtitle: &tr!("launcher-language-description"), set_model: Some(>k::StringList::new(&model.languages.iter().map(|lang| lang.as_str()).collect::>())), @@ -284,11 +284,11 @@ impl SimpleAsyncComponent for GeneralApp { }, adw::ComboRow { - set_title: &tr("game-edition"), + set_title: &tr!("game-edition"), set_model: Some(>k::StringList::new(&[ - &tr("global"), - &tr("china") + &tr!("global"), + &tr!("china") ])), set_selected: match CONFIG.launcher.edition { @@ -316,8 +316,8 @@ impl SimpleAsyncComponent for GeneralApp { }, adw::ComboRow { - set_title: &tr("game-environment"), - set_subtitle: &tr("game-environment-description"), + set_title: &tr!("game-environment"), + set_subtitle: &tr!("game-environment-description"), set_model: Some(>k::StringList::new(&[ "PC", @@ -349,8 +349,8 @@ impl SimpleAsyncComponent for GeneralApp { #[local_ref] voice_packages -> adw::ExpanderRow { - set_title: &tr("game-voiceovers"), - set_subtitle: &tr("game-voiceovers-description") + set_title: &tr!("game-voiceovers"), + set_subtitle: &tr!("game-voiceovers-description") }, gtk::Box { @@ -359,14 +359,14 @@ impl SimpleAsyncComponent for GeneralApp { set_margin_top: 16, gtk::Button { - set_label: &tr("migrate-installation"), - set_tooltip_text: Some(&tr("migrate-installation-description")), + set_label: &tr!("migrate-installation"), + set_tooltip_text: Some(&tr!("migrate-installation-description")), connect_clicked => GeneralAppMsg::OpenMigrateInstallation }, gtk::Button { - set_label: &tr("repair-game"), + set_label: &tr!("repair-game"), connect_clicked => GeneralAppMsg::RepairGame } @@ -374,10 +374,10 @@ impl SimpleAsyncComponent for GeneralApp { }, add = &adw::PreferencesGroup { - set_title: &tr("status"), + set_title: &tr!("status"), adw::ActionRow { - set_title: &tr("game-version"), + set_title: &tr!("game-version"), add_suffix = >k::Label { #[watch] @@ -388,7 +388,7 @@ impl SimpleAsyncComponent for GeneralApp { VersionDiff::Diff { current, .. } | VersionDiff::Outdated { current, .. } => current.to_string(), - VersionDiff::NotInstalled { .. } => tr("game-not-installed") + VersionDiff::NotInstalled { .. } => tr!("game-not-installed") } None => String::from("?") @@ -397,10 +397,10 @@ impl SimpleAsyncComponent for GeneralApp { #[watch] set_css_classes: match model.game_diff.as_ref() { Some(diff) => match diff { - VersionDiff::Latest { .. } => &["success"], - VersionDiff::Predownload { .. } => &["accent"], - VersionDiff::Diff { .. } => &["warning"], - VersionDiff::Outdated { .. } => &["error"], + VersionDiff::Latest { .. } => &["success"], + VersionDiff::Predownload { .. } => &["accent"], + VersionDiff::Diff { .. } => &["warning"], + VersionDiff::Outdated { .. } => &["error"], VersionDiff::NotInstalled { .. } => &[] } @@ -411,17 +411,21 @@ impl SimpleAsyncComponent for GeneralApp { set_tooltip_text: Some(&match model.game_diff.as_ref() { Some(diff) => match diff { VersionDiff::Latest { .. } => String::new(), - VersionDiff::Predownload { current, latest, .. } => tr_args("game-predownload-available", [ - ("old", current.to_string().into()), - ("new", latest.to_string().into()) - ]), - VersionDiff::Diff { current, latest, .. } => tr_args("game-update-available", [ - ("old", current.to_string().into()), - ("new", latest.to_string().into()) - ]), - VersionDiff::Outdated { latest, ..} => tr_args("game-outdated", [ - ("latest", latest.to_string().into()) - ]), + + VersionDiff::Predownload { current, latest, .. } => tr!("game-predownload-available", { + "old" = current.to_string(), + "new" = latest.to_string() + }), + + VersionDiff::Diff { current, latest, .. } => tr!("game-update-available", { + "old" = current.to_string(), + "new" = latest.to_string() + }), + + VersionDiff::Outdated { latest, ..} => tr!("game-outdated", { + "latest" = latest.to_string() + }), + VersionDiff::NotInstalled { .. } => String::new() } @@ -431,16 +435,21 @@ impl SimpleAsyncComponent for GeneralApp { }, adw::ActionRow { - set_title: &tr("player-patch-version"), - set_subtitle: &tr("player-patch-version-description"), + set_title: &tr!("player-patch-version"), + set_subtitle: &tr!("player-patch-version-description"), add_suffix = >k::Label { #[watch] set_text: &match model.player_patch.as_ref() { Some(patch) => match patch.status() { - PatchStatus::NotAvailable => tr("patch-not-available"), - PatchStatus::Outdated { current, .. } => tr_args("patch-outdated", [("current", current.to_string().into())]), - PatchStatus::Preparation { .. } => tr("patch-preparation"), + PatchStatus::NotAvailable => tr!("patch-not-available"), + + PatchStatus::Outdated { current, .. } => tr!("patch-outdated", { + "current" = current.to_string() + }), + + PatchStatus::Preparation { .. } => tr!("patch-preparation"), + PatchStatus::Testing { version, .. } | PatchStatus::Available { version, .. } => version.to_string() } @@ -452,9 +461,11 @@ impl SimpleAsyncComponent for GeneralApp { set_css_classes: match model.player_patch.as_ref() { Some(patch) => match patch.status() { PatchStatus::NotAvailable => &["error"], + PatchStatus::Outdated { .. } | PatchStatus::Preparation { .. } | PatchStatus::Testing { .. } => &["warning"], + PatchStatus::Available { .. } => unsafe { let path = match Config::get() { Ok(config) => config.game.path.for_edition(config.launcher.edition).to_path_buf(), @@ -475,13 +486,16 @@ impl SimpleAsyncComponent for GeneralApp { #[watch] set_tooltip_text: Some(&match model.player_patch.as_ref() { Some(patch) => match patch.status() { - PatchStatus::NotAvailable => tr("patch-not-available-tooltip"), - PatchStatus::Outdated { current, latest, .. } => tr_args("patch-outdated-tooltip", [ - ("current", current.to_string().into()), - ("latest", latest.to_string().into()) - ]), - PatchStatus::Preparation { .. } => tr("patch-preparation-tooltip"), - PatchStatus::Testing { .. } => tr("patch-testing-tooltip"), + PatchStatus::NotAvailable => tr!("patch-not-available-tooltip"), + + PatchStatus::Outdated { current, latest, .. } => tr!("patch-outdated-tooltip", { + "current" = current.to_string(), + "latest" = latest.to_string() + }), + + PatchStatus::Preparation { .. } => tr!("patch-preparation-tooltip"), + PatchStatus::Testing { .. } => tr!("patch-testing-tooltip"), + PatchStatus::Available { .. } => unsafe { let path = match Config::get() { Ok(config) => config.game.path.for_edition(config.launcher.edition).to_path_buf(), @@ -491,7 +505,7 @@ impl SimpleAsyncComponent for GeneralApp { if let Ok(true) = model.player_patch.as_ref().unwrap_unchecked().is_applied(path) { String::new() } else { - tr("patch-not-applied-tooltip") + tr!("patch-not-applied-tooltip") } } } @@ -504,8 +518,8 @@ impl SimpleAsyncComponent for GeneralApp { add = &adw::PreferencesGroup { adw::ActionRow { - set_title: &tr("apply-main-patch"), - set_subtitle: &tr("apply-main-patch-description"), + set_title: &tr!("apply-main-patch"), + set_subtitle: &tr!("apply-main-patch-description"), add_suffix = >k::Switch { set_valign: gtk::Align::Center, @@ -528,8 +542,8 @@ impl SimpleAsyncComponent for GeneralApp { }, adw::ActionRow { - set_title: &tr("disable-mhypbase"), - set_subtitle: &tr("disable-mhypbase-description"), + set_title: &tr!("disable-mhypbase"), + set_subtitle: &tr!("disable-mhypbase-description"), add_suffix = >k::Switch { set_valign: gtk::Align::Center, @@ -552,8 +566,8 @@ impl SimpleAsyncComponent for GeneralApp { }, adw::ActionRow { - set_title: &tr("ask-superuser-permissions"), - set_subtitle: &tr("ask-superuser-permissions-description"), + set_title: &tr!("ask-superuser-permissions"), + set_subtitle: &tr!("ask-superuser-permissions-description"), add_suffix = >k::Switch { set_valign: gtk::Align::Center, @@ -574,11 +588,44 @@ impl SimpleAsyncComponent for GeneralApp { }, add = &adw::PreferencesGroup { - set_title: &tr("options"), + set_title: &tr!("options"), + adw::ComboRow { + set_title: &tr!("launcher-behavior"), + set_subtitle: &tr!("launcher-behavior-description"), + + set_model: Some(>k::StringList::new(&[ + &tr!("nothing"), + &tr!("hide", { "form" = "verb" }), + &tr!("close", { "form" = "verb" }), + ])), + + set_selected: match CONFIG.launcher.behavior { + LauncherBehavior::Nothing => 0, + LauncherBehavior::Hide => 1, + LauncherBehavior::Close => 2 + }, + + connect_selected_notify => |row| { + if is_ready() { + if let Ok(mut config) = Config::get() { + config.launcher.behavior = [ + LauncherBehavior::Nothing, + LauncherBehavior::Hide, + LauncherBehavior::Close + ][row.selected() as usize]; + + Config::update(config); + } + } + } + } + }, + + add = &adw::PreferencesGroup { adw::ActionRow { - set_title: &tr("components"), - set_subtitle: &tr("components-description"), + set_title: &tr!("components"), + set_subtitle: &tr!("components-description"), add_suffix = >k::Image { set_icon_name: Some("go-next-symbolic") @@ -590,10 +637,10 @@ impl SimpleAsyncComponent for GeneralApp { }, adw::ExpanderRow { - set_title: &tr("wine-tools"), + set_title: &tr!("wine-tools"), add_row = &adw::ActionRow { - set_title: &tr("command-line"), + set_title: &tr!("command-line"), set_subtitle: "wineconsole", set_activatable: true, @@ -602,7 +649,7 @@ impl SimpleAsyncComponent for GeneralApp { }, add_row = &adw::ActionRow { - set_title: &tr("registry-editor"), + set_title: &tr!("registry-editor"), set_subtitle: "regedit", set_activatable: true, @@ -611,7 +658,7 @@ impl SimpleAsyncComponent for GeneralApp { }, add_row = &adw::ActionRow { - set_title: &tr("explorer"), + set_title: &tr!("explorer"), set_subtitle: "explorer", set_activatable: true, @@ -620,7 +667,7 @@ impl SimpleAsyncComponent for GeneralApp { }, add_row = &adw::ActionRow { - set_title: &tr("task-manager"), + set_title: &tr!("task-manager"), set_subtitle: "taskmgr", set_activatable: true, @@ -629,7 +676,7 @@ impl SimpleAsyncComponent for GeneralApp { }, add_row = &adw::ActionRow { - set_title: &tr("configuration"), + set_title: &tr!("configuration"), set_subtitle: "winecfg", set_activatable: true, @@ -638,7 +685,7 @@ impl SimpleAsyncComponent for GeneralApp { }, add_row = &adw::ActionRow { - set_title: &tr("debugger"), + set_title: &tr!("debugger"), set_subtitle: "start winedbg", set_activatable: true, @@ -676,7 +723,7 @@ impl SimpleAsyncComponent for GeneralApp { style: CONFIG.launcher.style, - languages: SUPPORTED_LANGUAGES.iter().map(|lang| tr(format_lang(lang).as_str())).collect() + languages: SUPPORTED_LANGUAGES.iter().map(|lang| tr!(format_lang(lang).as_str())).collect() }; for package in VoiceLocale::list() { @@ -740,7 +787,7 @@ impl SimpleAsyncComponent for GeneralApp { tracing::error!("Failed to delete voice package: {:?}", package.locale()); sender.input(GeneralAppMsg::Toast { - title: tr("voice-package-deletion-error"), + title: tr!("voice-package-deletion-error"), description: Some(err.to_string()) }); } @@ -808,7 +855,7 @@ impl SimpleAsyncComponent for GeneralApp { tracing::error!("Failed to download background picture"); sender.input(GeneralAppMsg::Toast { - title: tr("background-downloading-failed"), + title: tr!("background-downloading-failed"), description: Some(err.to_string()) }); @@ -840,9 +887,9 @@ impl SimpleAsyncComponent for GeneralApp { if let Err(err) = result { sender.input(GeneralAppMsg::Toast { - title: tr_args("wine-run-error", [ - ("executable", executable.join(" ").into()) - ]), + title: tr!("wine-run-error", { + "executable" = executable.join(" ") + }), description: Some(err.to_string()) }); diff --git a/src/ui/preferences/main.rs b/src/ui/preferences/main.rs index 2121fb2..23252b8 100644 --- a/src/ui/preferences/main.rs +++ b/src/ui/preferences/main.rs @@ -11,7 +11,7 @@ use anime_launcher_sdk::config::ConfigExt; use anime_launcher_sdk::genshin::config::Config; use anime_launcher_sdk::genshin::config::schema::launcher::LauncherStyle; -use crate::i18n::tr; +use crate::tr; use super::general::*; use super::enhancements::*; @@ -52,7 +52,7 @@ impl SimpleAsyncComponent for PreferencesApp { view! { preferences_window = adw::PreferencesWindow { - set_title: Some(&tr("preferences")), + set_title: Some(&tr!("preferences")), set_default_size: (700, 560), set_hide_on_close: true, @@ -65,7 +65,7 @@ impl SimpleAsyncComponent for PreferencesApp { connect_close_request[sender] => move |_| { if let Err(err) = Config::flush() { sender.input(PreferencesAppMsg::Toast { - title: tr("config-update-error"), + title: tr!("config-update-error"), description: Some(err.to_string()) }); } @@ -150,12 +150,12 @@ impl SimpleAsyncComponent for PreferencesApp { toast.set_timeout(4); if let Some(description) = description { - toast.set_button_label(Some(&tr("details"))); + toast.set_button_label(Some(&tr!("details"))); let dialog = adw::MessageDialog::new(PREFERENCES_WINDOW.as_ref(), Some(&title), Some(&description)); - dialog.add_response("close", &tr("close")); - dialog.add_response("save", &tr("save")); + dialog.add_response("close", &tr!("close", { "form" = "noun" })); + dialog.add_response("save", &tr!("save")); dialog.set_response_appearance("save", adw::ResponseAppearance::Suggested);