Merge pull request #226 from an-anime-team/next

Release 3.8.0
This commit is contained in:
Observer KRypt0n_ 2023-08-02 16:25:51 +02:00 committed by GitHub
commit ff55ef0e4f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
89 changed files with 1308 additions and 627 deletions

View file

@ -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

40
.github/workflows/check_source_code.yml vendored Normal file
View file

@ -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

View file

@ -6,7 +6,7 @@ on:
types: [opened, edited] types: [opened, edited]
jobs: jobs:
check-branch: check_target_branch:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: Vankka/pr-target-branch-action@v2 - uses: Vankka/pr-target-branch-action@v2

View file

@ -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

View file

@ -7,6 +7,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [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 ## [3.7.6] - 15.07.2023
### Fixed ### Fixed

364
Cargo.lock generated
View file

@ -39,8 +39,8 @@ dependencies = [
[[package]] [[package]]
name = "anime-game-core" name = "anime-game-core"
version = "1.13.2" version = "1.13.5"
source = "git+https://github.com/an-anime-team/anime-game-core?tag=1.13.2#a15b8162adcefcc9d99eacbd55ae5cfe1e1fddfe" source = "git+https://github.com/an-anime-team/anime-game-core?tag=1.13.5#11e48e47563acf97a6885d3cc369875031dc5f61"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bzip2", "bzip2",
@ -72,6 +72,7 @@ dependencies = [
"fluent-templates", "fluent-templates",
"glib-build-tools", "glib-build-tools",
"gtk4", "gtk4",
"human-panic",
"lazy_static", "lazy_static",
"libadwaita", "libadwaita",
"md-5", "md-5",
@ -87,8 +88,8 @@ dependencies = [
[[package]] [[package]]
name = "anime-launcher-sdk" name = "anime-launcher-sdk"
version = "1.8.6" version = "1.8.13"
source = "git+https://github.com/an-anime-team/anime-launcher-sdk?tag=1.8.6#2740eae5b5832b371e2a2919e33c0decfbe6b8a1" source = "git+https://github.com/an-anime-team/anime-launcher-sdk?tag=1.8.13#1669dceafce3eaa3e9332fb4ac6ff78ea9fb1639"
dependencies = [ dependencies = [
"anime-game-core", "anime-game-core",
"anyhow", "anyhow",
@ -104,10 +105,59 @@ dependencies = [
] ]
[[package]] [[package]]
name = "anyhow" name = "anstream"
version = "1.0.71" version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" 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 = [ dependencies = [
"backtrace", "backtrace",
] ]
@ -166,7 +216,7 @@ dependencies = [
"async-lock", "async-lock",
"async-task", "async-task",
"concurrent-queue", "concurrent-queue",
"fastrand", "fastrand 1.9.0",
"futures-lite", "futures-lite",
"slab", "slab",
] ]
@ -212,7 +262,7 @@ dependencies = [
"log", "log",
"parking", "parking",
"polling", "polling",
"rustix", "rustix 0.37.23",
"slab", "slab",
"socket2 0.4.9", "socket2 0.4.9",
"waker-fn", "waker-fn",
@ -240,7 +290,7 @@ dependencies = [
"cfg-if", "cfg-if",
"event-listener", "event-listener",
"futures-lite", "futures-lite",
"rustix", "rustix 0.37.23",
"signal-hook", "signal-hook",
"windows-sys", "windows-sys",
] ]
@ -253,7 +303,7 @@ checksum = "0e97ce7de6cf12de5d7226c73f5ba9811622f4db3a5b91b55c53e987e5f91cba"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.25", "syn 2.0.28",
] ]
[[package]] [[package]]
@ -290,13 +340,13 @@ checksum = "ecc7ab41815b3c653ccd2978ec3255c81349336702dfdf62ee6f7069b12a3aae"
[[package]] [[package]]
name = "async-trait" name = "async-trait"
version = "0.1.71" version = "0.1.72"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a564d521dd56509c4c47480d00b80ee55f7e385ae48db5744c67ad50c92d2ebf" checksum = "cc6dde6e4ed435a4c1ee4e73592f5ba9da2151af10076cc04858746af9352d09"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.25", "syn 2.0.28",
] ]
[[package]] [[package]]
@ -350,6 +400,12 @@ version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42"
[[package]] [[package]]
name = "block" name = "block"
version = "0.1.6" version = "0.1.6"
@ -375,7 +431,7 @@ dependencies = [
"async-lock", "async-lock",
"async-task", "async-task",
"atomic-waker", "atomic-waker",
"fastrand", "fastrand 1.9.0",
"futures-lite", "futures-lite",
"log", "log",
] ]
@ -465,7 +521,7 @@ version = "0.17.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab3603c4028a5e368d09b51c8b624b9a46edcd7c3778284077a6125af73c9f0a" checksum = "ab3603c4028a5e368d09b51c8b624b9a46edcd7c3778284077a6125af73c9f0a"
dependencies = [ dependencies = [
"bitflags", "bitflags 1.3.2",
"cairo-sys-rs", "cairo-sys-rs",
"glib", "glib",
"libc", "libc",
@ -495,9 +551,9 @@ dependencies = [
[[package]] [[package]]
name = "cfg-expr" name = "cfg-expr"
version = "0.15.3" version = "0.15.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "215c0072ecc28f92eeb0eea38ba63ddfcb65c2828c46311d646f1a3ff5f9841c" checksum = "b40ccee03b5175c18cde8f37e7d2a33bcef6f8ec8f7cc0d81090d1bb380949c9"
dependencies = [ dependencies = [
"smallvec", "smallvec",
"target-lexicon", "target-lexicon",
@ -519,6 +575,12 @@ dependencies = [
"inout", "inout",
] ]
[[package]]
name = "colorchoice"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]] [[package]]
name = "concurrent-queue" name = "concurrent-queue"
version = "2.2.0" version = "2.2.0"
@ -656,6 +718,12 @@ dependencies = [
"syn 1.0.109", "syn 1.0.109",
] ]
[[package]]
name = "deranged"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8810e7e2cf385b1e9b50d68264908ec367ba642c96d02edfe61c39e88e2a3c01"
[[package]] [[package]]
name = "derivative" name = "derivative"
version = "2.2.0" version = "2.2.0"
@ -687,7 +755,7 @@ dependencies = [
"serde", "serde",
"serde_derive", "serde_derive",
"serde_json", "serde_json",
"uuid", "uuid 0.8.2",
] ]
[[package]] [[package]]
@ -704,7 +772,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.25", "syn 2.0.28",
] ]
[[package]] [[package]]
@ -727,9 +795,9 @@ checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
[[package]] [[package]]
name = "either" name = "either"
version = "1.8.1" version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
[[package]] [[package]]
name = "enum-ordinalize" name = "enum-ordinalize"
@ -741,7 +809,7 @@ dependencies = [
"num-traits", "num-traits",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.25", "syn 2.0.28",
] ]
[[package]] [[package]]
@ -762,7 +830,7 @@ checksum = "5e9a1f9f7d83e59740248a6e14ecf93929ade55027844dfcea78beafccc15745"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.25", "syn 2.0.28",
] ]
[[package]] [[package]]
@ -773,9 +841,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]] [[package]]
name = "errno" name = "errno"
version = "0.3.1" version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f"
dependencies = [ dependencies = [
"errno-dragonfly", "errno-dragonfly",
"libc", "libc",
@ -807,6 +875,12 @@ dependencies = [
"instant", "instant",
] ]
[[package]]
name = "fastrand"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764"
[[package]] [[package]]
name = "field-offset" name = "field-offset"
version = "0.3.6" version = "0.3.6"
@ -1016,7 +1090,7 @@ version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce"
dependencies = [ dependencies = [
"fastrand", "fastrand 1.9.0",
"futures-core", "futures-core",
"futures-io", "futures-io",
"memchr", "memchr",
@ -1033,7 +1107,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.25", "syn 2.0.28",
] ]
[[package]] [[package]]
@ -1072,7 +1146,7 @@ version = "0.17.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "695d6bc846438c5708b07007537b9274d883373dd30858ca881d7d71b5540717" checksum = "695d6bc846438c5708b07007537b9274d883373dd30858ca881d7d71b5540717"
dependencies = [ dependencies = [
"bitflags", "bitflags 1.3.2",
"gdk-pixbuf-sys", "gdk-pixbuf-sys",
"gio", "gio",
"glib", "glib",
@ -1099,7 +1173,7 @@ version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3abf96408a26e3eddf881a7f893a1e111767137136e347745e8ea6ed12731ff" checksum = "c3abf96408a26e3eddf881a7f893a1e111767137136e347745e8ea6ed12731ff"
dependencies = [ dependencies = [
"bitflags", "bitflags 1.3.2",
"cairo-rs", "cairo-rs",
"gdk-pixbuf", "gdk-pixbuf",
"gdk4-sys", "gdk4-sys",
@ -1161,7 +1235,7 @@ version = "0.17.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6973e92937cf98689b6a054a9e56c657ed4ff76de925e36fc331a15f0c5d30a" checksum = "a6973e92937cf98689b6a054a9e56c657ed4ff76de925e36fc331a15f0c5d30a"
dependencies = [ dependencies = [
"bitflags", "bitflags 1.3.2",
"futures-channel", "futures-channel",
"futures-core", "futures-core",
"futures-io", "futures-io",
@ -1194,7 +1268,7 @@ version = "0.17.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3fad45ba8d4d2cea612b432717e834f48031cd8853c8aaf43b2c79fec8d144b" checksum = "d3fad45ba8d4d2cea612b432717e834f48031cd8853c8aaf43b2c79fec8d144b"
dependencies = [ dependencies = [
"bitflags", "bitflags 1.3.2",
"futures-channel", "futures-channel",
"futures-core", "futures-core",
"futures-executor", "futures-executor",
@ -1244,9 +1318,9 @@ dependencies = [
[[package]] [[package]]
name = "globset" name = "globset"
version = "0.4.11" version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1391ab1f92ffcc08911957149833e682aa3fe252b9f45f966d2ef972274c97df" checksum = "aca8bbd8e0707c1887a8bbb7e6b40e228f251ff5d62c8220a4a7a53c73aff006"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick",
"bstr", "bstr",
@ -1307,7 +1381,7 @@ version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f01ef44fa7cac15e2da9978529383e6bee03e570ba5bf7036b4c10a15cc3a3c" checksum = "6f01ef44fa7cac15e2da9978529383e6bee03e570ba5bf7036b4c10a15cc3a3c"
dependencies = [ dependencies = [
"bitflags", "bitflags 1.3.2",
"cairo-rs", "cairo-rs",
"gdk4", "gdk4",
"glib", "glib",
@ -1339,7 +1413,7 @@ version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b28a32a04cd75cef14a0983f8b0c669e0fe152a0a7725accdeb594e2c764c88b" checksum = "b28a32a04cd75cef14a0983f8b0c669e0fe152a0a7725accdeb594e2c764c88b"
dependencies = [ dependencies = [
"bitflags", "bitflags 1.3.2",
"cairo-rs", "cairo-rs",
"field-offset", "field-offset",
"futures-channel", "futures-channel",
@ -1428,6 +1502,22 @@ dependencies = [
"digest", "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]] [[package]]
name = "ident_case" name = "ident_case"
version = "1.0.1" version = "1.0.1"
@ -1528,6 +1618,17 @@ dependencies = [
"once_cell", "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]] [[package]]
name = "is-wsl" name = "is-wsl"
version = "0.4.0" version = "0.4.0"
@ -1540,9 +1641,9 @@ dependencies = [
[[package]] [[package]]
name = "itoa" name = "itoa"
version = "1.0.8" version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b02a5381cc465bd3041d84623d0fa3b66738b52b8e2fc3bab8ad63ab032f4a" checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
[[package]] [[package]]
name = "jobserver" name = "jobserver"
@ -1589,7 +1690,7 @@ version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ab9c0843f9f23ff25634df2743690c3a1faffe0a190e60c490878517eb81abf" checksum = "1ab9c0843f9f23ff25634df2743690c3a1faffe0a190e60c490878517eb81abf"
dependencies = [ dependencies = [
"bitflags", "bitflags 1.3.2",
"gdk-pixbuf", "gdk-pixbuf",
"gdk4", "gdk4",
"gio", "gio",
@ -1628,6 +1729,12 @@ version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
[[package]]
name = "linux-raw-sys"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0"
[[package]] [[package]]
name = "lock_api" name = "lock_api"
version = "0.4.10" version = "0.4.10"
@ -1751,7 +1858,7 @@ version = "0.26.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a"
dependencies = [ dependencies = [
"bitflags", "bitflags 1.3.2",
"cfg-if", "cfg-if",
"libc", "libc",
"memoffset 0.7.1", "memoffset 0.7.1",
@ -1800,9 +1907,9 @@ dependencies = [
[[package]] [[package]]
name = "num-traits" name = "num-traits"
version = "0.2.15" version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2"
dependencies = [ dependencies = [
"autocfg", "autocfg",
] ]
@ -1888,6 +1995,17 @@ dependencies = [
"pin-project-lite", "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]] [[package]]
name = "overload" name = "overload"
version = "0.1.1" version = "0.1.1"
@ -1900,7 +2018,7 @@ version = "0.17.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35be456fc620e61f62dff7ff70fbd54dcbaf0a4b920c0f16de1107c47d921d48" checksum = "35be456fc620e61f62dff7ff70fbd54dcbaf0a4b920c0f16de1107c47d921d48"
dependencies = [ dependencies = [
"bitflags", "bitflags 1.3.2",
"gio", "gio",
"glib", "glib",
"libc", "libc",
@ -2001,7 +2119,7 @@ checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.25", "syn 2.0.28",
] ]
[[package]] [[package]]
@ -2029,7 +2147,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"bitflags", "bitflags 1.3.2",
"cfg-if", "cfg-if",
"concurrent-queue", "concurrent-queue",
"libc", "libc",
@ -2092,18 +2210,18 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.64" version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78803b62cbf1f46fde80d7c0e803111524b9877184cfe7c3033659490ac7a7da" checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.29" version = "1.0.32"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@ -2172,7 +2290,7 @@ version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
dependencies = [ dependencies = [
"bitflags", "bitflags 1.3.2",
] ]
[[package]] [[package]]
@ -2181,7 +2299,7 @@ version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
dependencies = [ dependencies = [
"bitflags", "bitflags 1.3.2",
] ]
[[package]] [[package]]
@ -2198,9 +2316,9 @@ dependencies = [
[[package]] [[package]]
name = "regex-automata" name = "regex-automata"
version = "0.3.3" version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310" checksum = "b7b6d6190b7594385f61bd3911cd1be99dfddcfc365a4160cc2ab5bff4aed294"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick",
"memchr", "memchr",
@ -2239,7 +2357,7 @@ checksum = "848a6e1b4954b7aa8155d4a234516d46ed543a614666adc1ea73a922bc841e2a"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.25", "syn 2.0.28",
] ]
[[package]] [[package]]
@ -2309,11 +2427,24 @@ version = "0.37.23"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06"
dependencies = [ dependencies = [
"bitflags", "bitflags 1.3.2",
"errno", "errno",
"io-lifetimes", "io-lifetimes",
"libc", "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", "windows-sys",
] ]
@ -2352,9 +2483,9 @@ dependencies = [
[[package]] [[package]]
name = "ryu" name = "ryu"
version = "1.0.14" version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe232bdf6be8c8de797b22184ee71118d63780ea42ac85b61d1baa6d3b782ae9" checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
[[package]] [[package]]
name = "same-file" name = "same-file"
@ -2376,9 +2507,9 @@ dependencies = [
[[package]] [[package]]
name = "scopeguard" name = "scopeguard"
version = "1.1.0" version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]] [[package]]
name = "sct" name = "sct"
@ -2392,11 +2523,11 @@ dependencies = [
[[package]] [[package]]
name = "security-framework" name = "security-framework"
version = "2.9.1" version = "2.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8" checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de"
dependencies = [ dependencies = [
"bitflags", "bitflags 1.3.2",
"core-foundation", "core-foundation",
"core-foundation-sys", "core-foundation-sys",
"libc", "libc",
@ -2405,9 +2536,9 @@ dependencies = [
[[package]] [[package]]
name = "security-framework-sys" name = "security-framework-sys"
version = "2.9.0" version = "2.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7" checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a"
dependencies = [ dependencies = [
"core-foundation-sys", "core-foundation-sys",
"libc", "libc",
@ -2421,35 +2552,35 @@ checksum = "1ef965a420fe14fdac7dd018862966a4c14094f900e1650bbc71ddd7d580c8af"
[[package]] [[package]]
name = "semver" name = "semver"
version = "1.0.17" version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.171" version = "1.0.179"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30e27d1e4fd7659406c492fd6cfaf2066ba8773de45ca75e855590f856dc34a9" checksum = "0a5bf42b8d227d4abf38a1ddb08602e229108a517cd4e5bb28f9c7eaafdce5c0"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.171" version = "1.0.179"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "389894603bd18c46fa56231694f8d827779c0951a667087194cf9de94ed24682" checksum = "741e124f5485c7e60c03b043f79f320bff3527f4bbf12cf3831750dc46a0ec2c"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.25", "syn 2.0.28",
] ]
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.102" version = "1.0.104"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5062a995d481b2308b6064e9af76011f2921c35f97b0468811ed9f6cd91dfed" checksum = "076066c5f1078eac5b722a31827a8832fe108bed65dfa75e233c89f8206e976c"
dependencies = [ dependencies = [
"itoa", "itoa",
"ryu", "ryu",
@ -2458,13 +2589,13 @@ dependencies = [
[[package]] [[package]]
name = "serde_repr" name = "serde_repr"
version = "0.1.14" version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d89a8107374290037607734c0b73a85db7ed80cae314b3c5791f192a496e731" checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.25", "syn 2.0.28",
] ]
[[package]] [[package]]
@ -2509,9 +2640,9 @@ dependencies = [
[[package]] [[package]]
name = "signal-hook" name = "signal-hook"
version = "0.3.15" version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "732768f1176d21d09e076c23a93123d40bba92d50c4058da34d45c8de8e682b9" checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801"
dependencies = [ dependencies = [
"libc", "libc",
"signal-hook-registry", "signal-hook-registry",
@ -2629,9 +2760,9 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.25" version = "2.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15e3fc8c0c74267e2df136e5e5fb656a464158aa57624053375eb9c8c6e25ae2" checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -2640,9 +2771,9 @@ dependencies = [
[[package]] [[package]]
name = "sysinfo" name = "sysinfo"
version = "0.29.4" version = "0.29.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "751e810399bba86e9326f5762b7f32ac5a085542df78da6a78d94e07d14d7c11" checksum = "165d6d8539689e3d3bc8b98ac59541e1f21c7de7c85d60dc80e43ae0ed2113db"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"core-foundation-sys", "core-foundation-sys",
@ -2679,42 +2810,41 @@ dependencies = [
[[package]] [[package]]
name = "target-lexicon" name = "target-lexicon"
version = "0.12.9" version = "0.12.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df8e77cb757a61f51b947ec4a7e3646efd825b73561db1c232a8ccb639e611a0" checksum = "1d2faeef5759ab89935255b1a4cd98e0baf99d1085e37d36599c625dac49ae8e"
[[package]] [[package]]
name = "tempfile" name = "tempfile"
version = "3.6.0" version = "3.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" checksum = "5486094ee78b2e5038a6382ed7645bc084dc2ec433426ca4c3cb61e2007b8998"
dependencies = [ dependencies = [
"autocfg",
"cfg-if", "cfg-if",
"fastrand", "fastrand 2.0.0",
"redox_syscall 0.3.5", "redox_syscall 0.3.5",
"rustix", "rustix 0.38.4",
"windows-sys", "windows-sys",
] ]
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.43" version = "1.0.44"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a35fc5b8971143ca348fa6df4f024d4d55264f3468c71ad1c2f365b0a4d58c42" checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "1.0.43" version = "1.0.44"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f" checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.25", "syn 2.0.28",
] ]
[[package]] [[package]]
@ -2729,10 +2859,11 @@ dependencies = [
[[package]] [[package]]
name = "time" name = "time"
version = "0.3.23" version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59e399c068f43a5d116fedaf73b203fa4f9c519f17e2b34f63221d3792f81446" checksum = "b79eabcd964882a646b3584543ccabeae7869e9ac32a46f6f22b7a5bd405308b"
dependencies = [ dependencies = [
"deranged",
"serde", "serde",
"time-core", "time-core",
] ]
@ -2789,7 +2920,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.25", "syn 2.0.28",
] ]
[[package]] [[package]]
@ -2815,9 +2946,9 @@ dependencies = [
[[package]] [[package]]
name = "toml_edit" name = "toml_edit"
version = "0.19.13" version = "0.19.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f8751d9c1b03c6500c387e96f81f815a4f8e72d142d2d4a9ffa6fedd51ddee7" checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a"
dependencies = [ dependencies = [
"indexmap", "indexmap",
"serde", "serde",
@ -2846,7 +2977,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.25", "syn 2.0.28",
] ]
[[package]] [[package]]
@ -2960,9 +3091,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.10" version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22049a19f4a68748a168c0fc439f9516686aa045927ff767eca0a85101fb6e73" checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
[[package]] [[package]]
name = "unicode-normalization" name = "unicode-normalization"
@ -2993,9 +3124,15 @@ dependencies = [
[[package]] [[package]]
name = "urlencoding" name = "urlencoding"
version = "2.1.2" version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index" 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]] [[package]]
name = "uuid" name = "uuid"
@ -3006,6 +3143,15 @@ dependencies = [
"getrandom", "getrandom",
] ]
[[package]]
name = "uuid"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d"
dependencies = [
"getrandom",
]
[[package]] [[package]]
name = "valuable" name = "valuable"
version = "0.1.0" version = "0.1.0"
@ -3073,7 +3219,7 @@ dependencies = [
"once_cell", "once_cell",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.25", "syn 2.0.28",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -3107,7 +3253,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.25", "syn 2.0.28",
"wasm-bindgen-backend", "wasm-bindgen-backend",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -3328,9 +3474,9 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
[[package]] [[package]]
name = "winnow" name = "winnow"
version = "0.5.0" version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81fac9742fd1ad1bd9643b991319f72dd031016d44b77039a26977eb667141e7" checksum = "8bd122eb777186e60c3fdf765a58ac76e41c582f1f535fbf3314434c6b58f3f7"
dependencies = [ dependencies = [
"memchr", "memchr",
] ]

View file

@ -3,6 +3,8 @@ name = "anime-game-launcher"
version = "3.7.6" version = "3.7.6"
description = "Anime Game launcher" description = "Anime Game launcher"
authors = ["Nikita Podvirnyy <suimin.tu.mu.ga.mi@gmail.com>"] authors = ["Nikita Podvirnyy <suimin.tu.mu.ga.mi@gmail.com>"]
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" license = "GPL-3.0"
edition = "2021" edition = "2021"
build = "build.rs" build = "build.rs"
@ -17,7 +19,7 @@ glib-build-tools = "0.17"
[dependencies.anime-launcher-sdk] [dependencies.anime-launcher-sdk]
git = "https://github.com/an-anime-team/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"] features = ["all", "genshin", "genshin-patch"]
# path = "../anime-launcher-sdk" # ! for dev purposes only # path = "../anime-launcher-sdk" # ! for dev purposes only
@ -42,3 +44,5 @@ tracing-subscriber = "0.3"
fluent-templates = "0.8" fluent-templates = "0.8"
unic-langid = "0.9" unic-langid = "0.9"
human-panic = "1.1.5"

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
<g fill="#2e3436">
<path d="m 0 11 v 2.5 c 0 1.378906 1.121094 2.5 2.5 2.5 h 0.5 c 1.105469 0 2 -0.894531 2 -2 s 0.894531 -2 2 -2 s 2 0.894531 2 2 c 0.136719 1.242188 1.257812 2.136719 2.5 2 c 1.378906 0 2.5 -1.117188 2.5 -2.5 v -2.5 c 0 -2.210938 -1.789062 -4 -4 -4 h -6 c -2.210938 0 -4 1.789062 -4 4 z m 3.25 -2 h 0.5 c 0.136719 0 0.25 0.113281 0.25 0.25 v 0.75 h 0.75 c 0.136719 0 0.25 0.113281 0.25 0.25 v 0.5 c 0 0.140625 -0.113281 0.25 -0.25 0.25 h -0.75 v 0.75 c 0 0.140625 -0.113281 0.25 -0.25 0.25 h -0.5 c -0.140625 0 -0.25 -0.109375 -0.25 -0.25 v -0.75 h -0.75 c -0.140625 0 -0.25 -0.109375 -0.25 -0.25 v -0.5 c 0 -0.136719 0.109375 -0.25 0.25 -0.25 h 0.75 v -0.75 c 0 -0.136719 0.109375 -0.25 0.25 -0.25 z m 6.25 0.75 c 0.414062 0 0.75 0.335938 0.75 0.75 s -0.335938 0.75 -0.75 0.75 s -0.75 -0.335938 -0.75 -0.75 s 0.335938 -0.75 0.75 -0.75 z m 2 1 c 0.414062 0 0.75 0.335938 0.75 0.75 s -0.335938 0.75 -0.75 0.75 s -0.75 -0.335938 -0.75 -0.75 s 0.335938 -0.75 0.75 -0.75 z m 0 0"/>
<path d="m 2 3.015625 c 0.007812 1.65625 1.359375 2.992187 3.015625 2.984375 h 7.96875 c 1.664063 0 3.015625 -1.351562 3.015625 -3.015625 c -0.007812 -1.65625 -1.359375 -2.9921875 -3.015625 -2.984375 h -7.96875 c -1.664063 0 -3.015625 1.351562 -3.015625 3.015625 z m 3.21875 -2.015625 h 0.5 c 0.136719 0 0.25 0.113281 0.25 0.25 v 0.75 h 0.75 c 0.136719 0 0.25 0.113281 0.25 0.25 v 0.5 c 0 0.140625 -0.113281 0.25 -0.25 0.25 h -0.75 v 0.75 c 0 0.140625 -0.113281 0.25 -0.25 0.25 h -0.5 c -0.140625 0 -0.25 -0.109375 -0.25 -0.25 v -0.75 h -0.75 c -0.140625 0 -0.25 -0.109375 -0.25 -0.25 v -0.5 c 0 -0.136719 0.109375 -0.25 0.25 -0.25 h 0.75 v -0.75 c 0 -0.136719 0.109375 -0.25 0.25 -0.25 z m 6.25 0.75 c 0.414062 0 0.75 0.335938 0.75 0.75 s -0.335938 0.75 -0.75 0.75 s -0.75 -0.335938 -0.75 -0.75 s 0.335938 -0.75 0.75 -0.75 z m 2 0.03125 c 0.414062 0 0.75 0.335938 0.75 0.75 s -0.335938 0.75 -0.75 0.75 s -0.75 -0.335938 -0.75 -0.75 s 0.335938 -0.75 0.75 -0.75 z m 0 0"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
<path d="m 7.886719 0.00390625 c -2.109375 0.03124995 -4.945313 0.80078175 -4.898438 3.27734375 c 0.050781 2.589844 2.921875 1.664062 3.15625 2.71875 c 0.035157 -0.042969 0.085938 -0.082031 0.121094 -0.125 c 0.199219 -0.210938 0.394531 -0.386719 0.59375 -0.59375 c 0.3125 -0.351562 0.636719 -0.675781 0.964844 -1.03125 c 1.109375 -1.175781 1.15625 -1.25 3.800781 -3.25 c -1.035156 -0.617188 -2.261719 -0.9609375 -3.300781 -0.99609375 c -0.132813 -0.00390625 -0.292969 -0.00390625 -0.4375 0 z m 6.144531 0 c -1.796875 1.29687475 -4.203125 3.30078175 -6.113281 5.33203175 c -0.171875 0.183593 -0.339844 0.363281 -0.503907 0.546874 c -0.101562 0.109376 -0.210937 0.195313 -0.3125 0.308594 c -0.066406 0.078125 -0.128906 0.160156 -0.191406 0.238282 c -1.300781 1.4375 -2.582031 3.128906 -3.648437 4.683593 c -0.308594 -0.15625 -0.699219 -0.171875 -1.117188 0.101563 c -0.753906 0.496094 -0.597656 2.285156 -2.14843725 2.285156 c 0.14843725 0.601562 1.73437525 0.59375 2.80859425 0.324219 c 1.011718 -0.253907 1.324218 -1.140625 1.132812 -1.886719 c -0.03125 -0.105469 -0.078125 -0.210938 -0.144531 -0.320312 c 1.984375 -1.640626 3.386719 -3.003907 4.34375 -4.023438 c 0.242187 -0.246094 0.53125 -0.566406 0.851562 -0.925781 c 1.207031 -1.332031 2.925781 -3.433594 5.042969 -6.66406275 z m -8.042969 1.52734375 c 0.824219 0 1.492188 0.671875 1.492188 1.5 c 0 0.832031 -0.667969 1.5 -1.492188 1.5 c -0.828125 0 -1.5 -0.667969 -1.5 -1.5 c 0 -0.828125 0.671875 -1.5 1.5 -1.5 z m 7.265625 0.664062 c -1.417968 2.234376 -2.367187 3.554688 -3.367187 4.585938 c -0.640625 0.660156 -1.164063 1.3125 -1.625 1.78125 c -0.835938 0.890625 -1.9375 1.941406 -3.148438 3.09375 c 0.0625 1.46875 0.808594 2.746094 3.242188 3.21875 c 3.898437 0.757812 8.027343 -1.824219 7.613281 -7.0625 c -0.179688 -2.246094 -1.40625 -4.28125 -2.714844 -5.617188 z m 0.34375 3.804688 c 0.546875 0 0.996094 0.449219 0.996094 1 c 0 0.554688 -0.449219 1 -0.996094 1 s -0.996094 -0.445312 -0.996094 -1 c 0 -0.550781 0.449219 -1 0.996094 -1 z m -0.625 3 c 0.546875 0 0.996094 0.449219 0.996094 1 c 0 0.554688 -0.449219 1 -0.996094 1 s -0.996094 -0.445312 -0.996094 -1 c 0 -0.550781 0.449219 -1 0.996094 -1 z m -4.992187 2 c 0.550781 0 1 0.449219 1 1 s -0.449219 1 -1 1 c -0.546875 0 -0.996094 -0.449219 -0.996094 -1 s 0.449219 -1 0.996094 -1 z m 2.996093 0 c 0.546876 0 1 0.449219 1 1 s -0.453124 1 -1 1 c -0.546874 0 -0.996093 -0.449219 -0.996093 -1 s 0.449219 -1 0.996093 -1 z m 0 0" fill="#2e3436"/>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
<g fill="#2e3436">
<path d="m 7.996094 0 c -2.835938 0 -5.292969 2 -5.871094 4.777344 c -0.527344 2.535156 0.6875 5.035156 2.875 6.328125 v 0.894531 c 0 0.554688 0.449219 1 1 1 h 4 c 0.550781 0 1 -0.445312 1 -1 l 0.003906 -0.898438 c 2.179688 -1.292968 3.398438 -3.796874 2.867188 -6.332031 c -0.582032 -2.773437 -3.039063 -4.769531 -5.875 -4.769531 z m 0 2 c 1.898437 0 3.527344 1.320312 3.917968 3.179688 c 0.390626 1.863281 -0.570312 3.726562 -2.3125 4.488281 c -0.363281 0.15625 -0.597656 0.515625 -0.601562 0.914062 v 0.417969 h -2 v -0.417969 c -0.003906 -0.398437 -0.238281 -0.753906 -0.601562 -0.914062 c -1.742188 -0.761719 -2.703126 -2.625 -2.316407 -4.484375 s 2.015625 -3.183594 3.914063 -3.183594 z m -1.996094 12 v 1 c 0 0.554688 0.445312 1 1 1 h 2 c 0.554688 0 1 -0.445312 1 -1 v -1 z m 0 0"/>
<path d="m 6.644531 6.144531 c -0.195312 0.195313 -0.195312 0.515625 0 0.707031 l 1 1 c 0.195313 0.195313 0.511719 0.195313 0.707031 0 l 1 -1 c 0.195313 -0.191406 0.195313 -0.511718 0 -0.707031 c -0.195312 -0.191406 -0.511718 -0.191406 -0.707031 0 l -0.648437 0.648438 l -0.644532 -0.648438 c -0.195312 -0.191406 -0.511718 -0.191406 -0.707031 0 z m 0 0" fill-opacity="0.34902"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
<path d="m 4 0 c -1.644531 0 -3 1.355469 -3 3 v 10 c 0 1.644531 1.355469 3 3 3 h 3 c 0.550781 0 1 -0.449219 1 -1 s -0.449219 -1 -1 -1 h -3 c -0.570312 0 -1 -0.429688 -1 -1 v -10 c 0 -0.570312 0.429688 -1 1 -1 h 5.585938 l 3.414062 3.414062 v 6.585938 c 0 0.550781 0.449219 1 1 1 s 1 -0.449219 1 -1 v -7 c 0 -0.265625 -0.105469 -0.519531 -0.292969 -0.707031 l -4 -4 c -0.1875 -0.1875 -0.441406 -0.292969 -0.707031 -0.292969 z m 4.640625 6.167969 c -0.199219 0.003906 -0.402344 0.019531 -0.597656 0.046875 l 1.171875 2.074218 c 0.242187 0.425782 -0.027344 0.914063 -0.539063 1.210938 l -0.925781 0.53125 c -0.515625 0.289062 -1.089844 0.25 -1.332031 -0.175781 l -1.171875 -2.074219 c -0.25 0.308594 -0.476563 0.648438 -0.617188 1.019531 c -0.679687 1.761719 0.285156 3.46875 2.152344 3.804688 c 0.386719 0.074219 0.800781 0.054687 1.191406 0.007812 c 0.03125 -0.007812 1.859375 3.386719 1.859375 3.386719 l 4.167969 0.003906 l -3.199219 -4.957031 c 0.246094 -0.308594 0.445313 -0.652344 0.585938 -1.019531 c 0.679687 -1.765625 -0.285157 -3.472656 -2.148438 -3.808594 c -0.195312 -0.039062 -0.398437 -0.050781 -0.597656 -0.046875 z m 0 0" fill="#2e3436"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
<path d="m 8 0 c -0.550781 0 -1 0.449219 -1 1 v 8.585938 l -1.292969 -1.292969 c -0.1875 -0.1875 -0.441406 -0.292969 -0.707031 -0.292969 s -0.519531 0.105469 -0.707031 0.292969 c -0.390625 0.390625 -0.390625 1.023437 0 1.414062 l 3 3 c 0.390625 0.390625 1.023437 0.390625 1.414062 0 l 3 -3 c 0.390625 -0.390625 0.390625 -1.023437 0 -1.414062 s -1.023437 -0.390625 -1.414062 0 l -1.292969 1.292969 v -8.585938 c 0 -0.550781 -0.449219 -1 -1 -1 z m -7 14 v 2 h 14 v -2 z m 0 0" fill="#2e3436"/>
</svg>

After

Width:  |  Height:  |  Size: 630 B

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
<path d="m 13.753906 4.660156 c 0.175782 -0.199218 0.261719 -0.460937 0.246094 -0.726562 c -0.019531 -0.265625 -0.140625 -0.511719 -0.339844 -0.6875 c -0.199218 -0.175782 -0.460937 -0.261719 -0.726562 -0.246094 c -0.265625 0.019531 -0.511719 0.140625 -0.6875 0.339844 l -6.296875 7.195312 l -2.242188 -2.242187 c -0.390625 -0.390625 -1.023437 -0.390625 -1.414062 0 c -0.1875 0.1875 -0.292969 0.441406 -0.292969 0.707031 s 0.105469 0.519531 0.292969 0.707031 l 3 3 c 0.195312 0.195313 0.464843 0.304688 0.738281 0.292969 c 0.277344 -0.007812 0.539062 -0.132812 0.722656 -0.339844 z m 0 0" fill="#2e3436"/>
</svg>

After

Width:  |  Height:  |  Size: 743 B

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
<path d="m 8 0 c -0.550781 0 -1 0.449219 -1 1 v 0.238281 c 0 0.464844 -0.378906 0.902344 -0.820312 1.046875 c -0.023438 0.007813 -0.042969 0.011719 -0.0625 0.019532 c -0.445313 0.148437 -1.007813 0.015624 -1.28125 -0.359376 l -0.140626 -0.195312 c -0.15625 -0.214844 -0.390624 -0.359375 -0.652343 -0.398438 c -0.261719 -0.042968 -0.53125 0.019532 -0.742188 0.175782 c -0.449219 0.324218 -0.550781 0.949218 -0.222656 1.398437 l 0.140625 0.199219 c 0.277344 0.375 0.226562 0.953125 -0.050781 1.328125 c -0.011719 0.015625 -0.023438 0.035156 -0.035157 0.050781 c -0.273437 0.378906 -0.804687 0.601563 -1.25 0.457032 l -0.230468 -0.074219 c -0.523438 -0.171875 -1.089844 0.117187 -1.257813 0.640625 c -0.171875 0.527344 0.113281 1.089844 0.640625 1.261718 l 0.222656 0.074219 c 0.445313 0.144531 0.738282 0.636719 0.75 1.101563 v 0.070312 c 0.015626 0.464844 -0.304687 0.960938 -0.746093 1.105469 l -0.226563 0.070313 c -0.527344 0.171874 -0.8125 0.738281 -0.640625 1.261718 c 0.167969 0.523438 0.734375 0.8125 1.257813 0.640625 l 0.230468 -0.074219 c 0.445313 -0.144531 0.976563 0.078126 1.25 0.457032 c 0.011719 0.015625 0.027344 0.035156 0.039063 0.050781 c 0.277344 0.375 0.324219 0.953125 0.050781 1.328125 l -0.144531 0.203125 c -0.324219 0.445313 -0.226563 1.070313 0.222656 1.394531 c 0.445313 0.324219 1.070313 0.226563 1.394531 -0.21875 l 0.144532 -0.199218 c 0.273437 -0.378907 0.835937 -0.507813 1.277344 -0.359376 c 0.019531 0.007813 0.042968 0.011719 0.0625 0.019532 c 0.445312 0.140625 0.820312 0.578125 0.820312 1.046875 v 0.238281 c 0 0.550781 0.449219 1 1 1 s 1 -0.449219 1 -1 v -0.238281 c 0 -0.46875 0.378906 -0.90625 0.820312 -1.046875 c 0.023438 -0.007813 0.042969 -0.015625 0.066407 -0.023438 c 0.441406 -0.144531 1.003906 -0.015625 1.277343 0.363282 l 0.144532 0.199218 c 0.324218 0.445313 0.949218 0.542969 1.394531 0.21875 c 0.445313 -0.324218 0.546875 -0.949218 0.222656 -1.394531 l -0.148437 -0.203125 c -0.273438 -0.375 -0.226563 -0.953125 0.050781 -1.328125 c 0.015625 -0.015625 0.027344 -0.035156 0.039063 -0.050781 c 0.273437 -0.378906 0.804687 -0.601563 1.25 -0.457032 l 0.234374 0.078126 c 0.523438 0.167968 1.085938 -0.121094 1.257813 -0.644532 c 0.171875 -0.523437 -0.117187 -1.089844 -0.640625 -1.257812 l -0.230469 -0.074219 c -0.445312 -0.144531 -0.734375 -0.640625 -0.746093 -1.105469 c 0 -0.023437 0 -0.046875 0 -0.070312 c -0.015626 -0.464844 0.300781 -0.957032 0.746093 -1.101563 l 0.230469 -0.074219 c 0.523438 -0.171874 0.8125 -0.734374 0.640625 -1.261718 c -0.171875 -0.523438 -0.734375 -0.8125 -1.257813 -0.640625 l -0.230468 0.074219 c -0.445313 0.144531 -0.980469 -0.078126 -1.253906 -0.457032 c -0.011719 -0.015625 -0.023438 -0.035156 -0.035157 -0.050781 c -0.277343 -0.375 -0.324219 -0.953125 -0.050781 -1.328125 l 0.144531 -0.199219 c 0.324219 -0.445312 0.226563 -1.074219 -0.222656 -1.398437 c -0.214844 -0.15625 -0.480469 -0.21875 -0.742187 -0.179688 c -0.265626 0.042969 -0.5 0.1875 -0.652344 0.402344 l -0.144532 0.195312 c -0.273437 0.378907 -0.835937 0.507813 -1.28125 0.363282 c -0.019531 -0.007813 -0.039062 -0.015625 -0.0625 -0.023438 c -0.441406 -0.140625 -0.820312 -0.578125 -0.820312 -1.046875 v -0.238281 c 0 -0.550781 -0.449219 -1 -1 -1 z m 0 4 c 0.871094 0 1.675781 0.273438 2.332031 0.742188 c 0.003907 0.007812 0.011719 0.015624 0.019531 0.023437 c 0.011719 0.003906 0.019532 0.007813 0.03125 0.015625 c 0.660157 0.484375 1.160157 1.171875 1.421876 1.976562 v 0.007813 s 0.003906 0.003906 0.003906 0.007813 c 0.292968 0.851562 0.15625 1.65625 0 2.457031 c 0 0 -0.003906 0.003906 -0.003906 0.007812 v 0.003907 c -0.261719 0.800781 -0.757813 1.488281 -1.414063 1.976562 c -0.015625 0.003906 -0.027344 0.011719 -0.039063 0.019531 c -0.007812 0.003907 -0.015624 0.011719 -0.019531 0.019531 c -0.65625 0.46875 -1.460937 0.742188 -2.332031 0.742188 c -0.855469 0 -1.644531 -0.265625 -2.289062 -0.714844 c -0.019532 -0.015625 -0.042969 -0.035156 -0.0625 -0.046875 c -0.011719 -0.007812 -0.023438 -0.015625 -0.035157 -0.019531 c -0.652343 -0.484375 -1.148437 -1.160156 -1.40625 -1.945312 c -0.003906 -0.015626 -0.007812 -0.023438 -0.011719 -0.035157 c -0.003906 -0.007812 -0.007812 -0.015625 -0.011718 -0.019531 c -0.285156 -0.847656 -0.148438 -1.644531 0 -2.4375 c 0.003906 -0.007812 0.007812 -0.011719 0.011718 -0.019531 c 0.003907 -0.011719 0.007813 -0.023438 0.011719 -0.039063 c 0.261719 -0.785156 0.757813 -1.460937 1.414063 -1.945312 c 0.007812 -0.003906 0.019531 -0.007813 0.027344 -0.015625 c 0.019531 -0.011719 0.042968 -0.03125 0.058593 -0.046875 c 0.648438 -0.449219 1.4375 -0.714844 2.292969 -0.714844 z m 0 0" fill="#2e3436"/>
</svg>

After

Width:  |  Height:  |  Size: 4.6 KiB

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
<g fill="#2e3436">
<path d="m 1 4 v 1 h 8 v -1 z m 0 0"/>
<path d="m 3 1 c -1.644531 0 -3 1.355469 -3 3 v 8 c 0 1.644531 1.355469 3 3 3 h 10 c 1.644531 0 3 -1.355469 3 -3 v -6 c 0 -1.644531 -1.355469 -3 -3 -3 h -3.585938 l -1.707031 -1.707031 c -0.1875 -0.1875 -0.441406 -0.292969 -0.707031 -0.292969 z m 0 2 h 3.585938 l 1.707031 1.707031 c 0.1875 0.1875 0.441406 0.292969 0.707031 0.292969 h 4 c 0.5625 0 1 0.4375 1 1 v 6 c 0 0.566406 -0.4375 1 -1 1 h -10 c -0.5625 0 -1 -0.433594 -1 -1 v -8 c 0 -0.5625 0.4375 -1 1 -1 z m 0 0"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 695 B

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
<path d="m 4 2 c 0 -0.265625 0.105469 -0.519531 0.292969 -0.707031 c 0.390625 -0.390625 1.023437 -0.390625 1.414062 0 l 6 6 c 0.1875 0.1875 0.292969 0.441406 0.292969 0.707031 s -0.105469 0.519531 -0.292969 0.707031 l -6 6 c -0.390625 0.390625 -1.023437 0.390625 -1.414062 0 c -0.1875 -0.1875 -0.292969 -0.441406 -0.292969 -0.707031 s 0.105469 -0.519531 0.292969 -0.707031 l 5.292969 -5.292969 l -5.292969 -5.292969 c -0.1875 -0.1875 -0.292969 -0.441406 -0.292969 -0.707031 z m 0 0" fill="#2e3436"/>
</svg>

After

Width:  |  Height:  |  Size: 638 B

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
<path d="m 12 2 c 0 -0.265625 -0.105469 -0.519531 -0.292969 -0.707031 c -0.390625 -0.390625 -1.023437 -0.390625 -1.414062 0 l -6 6 c -0.1875 0.1875 -0.292969 0.441406 -0.292969 0.707031 s 0.105469 0.519531 0.292969 0.707031 l 6 6 c 0.390625 0.390625 1.023437 0.390625 1.414062 0 c 0.1875 -0.1875 0.292969 -0.441406 0.292969 -0.707031 s -0.105469 -0.519531 -0.292969 -0.707031 l -5.292969 -5.292969 l 5.292969 -5.292969 c 0.1875 -0.1875 0.292969 -0.441406 0.292969 -0.707031 z m 0 0" fill="#2e3436"/>
</svg>

After

Width:  |  Height:  |  Size: 638 B

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
<path d="m 7 1 v 6 h -6 v 2 h 6 v 6 h 2 v -6 h 6 v -2 h -6 v -6 z m 0 0" fill="#2e3436"/>
</svg>

After

Width:  |  Height:  |  Size: 228 B

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
<path d="m 2 2.5 v 11 c 0 1.5 1.269531 1.492188 1.269531 1.492188 h 0.128907 c 0.246093 0.003906 0.488281 -0.050782 0.699218 -0.171876 l 9.796875 -5.597656 c 0.433594 -0.242187 0.65625 -0.734375 0.65625 -1.226562 c 0 -0.492188 -0.222656 -0.984375 -0.65625 -1.222656 l -9.796875 -5.597657 c -0.210937 -0.121093 -0.453125 -0.175781 -0.699218 -0.175781 h -0.128907 s -1.269531 0 -1.269531 1.5 z m 0 0" fill="#2e3436"/>
</svg>

After

Width:  |  Height:  |  Size: 554 B

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
<g fill="#2e3436">
<path d="m 1 2 h 14 v 2 h -14 z m 0 0"/>
<path d="m 1 7 h 14 v 2 h -14 z m 0 0"/>
<path d="m 1 12 h 14 v 2 h -14 z m 0 0"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 314 B

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
<path d="m 2 0 c -0.550781 0 -1 0.449219 -1 1 v 8 c 0 2.5 1.816406 4.246094 3.445312 5.332031 c 1.628907 1.085938 3.238282 1.617188 3.238282 1.617188 c 0.207031 0.070312 0.425781 0.070312 0.632812 0 c 0 0 1.609375 -0.53125 3.238282 -1.617188 c 1.628906 -1.085937 3.445312 -2.832031 3.445312 -5.332031 v -8 c 0 -0.550781 -0.449219 -1 -1 -1 z m 1 2 h 10 v 7 c 0 1.5 -1.183594 2.753906 -2.554688 3.667969 c -1.214843 0.808593 -2.179687 1.128906 -2.445312 1.226562 c -0.265625 -0.097656 -1.230469 -0.417969 -2.445312 -1.226562 c -1.371094 -0.914063 -2.554688 -2.167969 -2.554688 -3.667969 z m 1 1 v 6 c 0 1 0.867188 2.007812 2.109375 2.835938 c 0.933594 0.621093 1.472656 0.785156 1.890625 0.949218 c 0.417969 -0.164062 0.957031 -0.328125 1.890625 -0.949218 c 1.242187 -0.828126 2.109375 -1.835938 2.109375 -2.835938 v -6 z m 0 0" fill="#2e3436"/>
</svg>

After

Width:  |  Height:  |  Size: 982 B

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
<g fill="#2e3436">
<path d="m 1 3 h 14 c 0.550781 0 1 0.449219 1 1 s -0.449219 1 -1 1 h -14 c -0.550781 0 -1 -0.449219 -1 -1 s 0.449219 -1 1 -1 z m 0 0"/>
<path d="m 4 4 v -1.5 c 0 -1.386719 1.113281 -2.5 2.5 -2.5 h 2.980469 c 1.382812 0 2.5 1.113281 2.5 2.5 v 1.5 h -2 v -1.5 c 0 -0.269531 -0.230469 -0.5 -0.5 -0.5 h -2.980469 c -0.269531 0 -0.5 0.230469 -0.5 0.5 v 1.5 z m 0 0"/>
<path d="m 4 4 v 9 c 0 0.546875 0.453125 1 1 1 h 6 c 0.546875 0 1 -0.453125 1 -1 v -9 h 2 v 9 c 0 1.660156 -1.339844 3 -3 3 h -6 c -1.660156 0 -3 -1.339844 -3 -3 v -9 z m 0 0"/>
<path d="m 7 7 v 5 c 0 0.277344 -0.222656 0.5 -0.5 0.5 s -0.5 -0.222656 -0.5 -0.5 v -5 c 0 -0.277344 0.222656 -0.5 0.5 -0.5 s 0.5 0.222656 0.5 0.5 z m 0 0"/>
<path d="m 10 7 v 5 c 0 0.277344 -0.222656 0.5 -0.5 0.5 s -0.5 -0.222656 -0.5 -0.5 v -5 c 0 -0.277344 0.222656 -0.5 0.5 -0.5 s 0.5 0.222656 0.5 0.5 z m 0 0"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1 KiB

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
<path d="m 7.40625 1 c -0.613281 0.007812 -1.234375 0.089844 -1.847656 0.253906 c -3.273438 0.878906 -5.558594 3.855469 -5.558594 7.246094 s 2.285156 6.367188 5.558594 7.242188 c 3.273437 0.878906 6.742187 -0.558594 8.4375 -3.492188 c 0.277344 -0.480469 0.109375 -1.089844 -0.367188 -1.367188 c -0.476562 -0.273437 -1.089844 -0.109374 -1.367187 0.367188 c -1.246094 2.160156 -3.777344 3.207031 -6.1875 2.5625 c -2.40625 -0.644531 -4.074219 -2.820312 -4.074219 -5.3125 c 0 -2.496094 1.667969 -4.667969 4.074219 -5.3125 c 2.410156 -0.644531 4.941406 0.402344 6.1875 2.5625 c 0.058593 0.085938 0.125 0.164062 0.203125 0.226562 l -0.019532 0.015626 l -0.007812 0.007812 h -1.4375 c -0.550781 0 -1 0.449219 -1 1 c 0 0 0 1 1 1 h 5 v -5 s 0.003906 -1 -1 -1 c -0.550781 0 -1 0.449219 -1 1 v 1.6875 l -0.015625 0.011719 l -0.011719 0.011719 c -1.277344 -2.179688 -3.53125 -3.519532 -5.953125 -3.691407 c -0.203125 -0.015625 -0.40625 -0.019531 -0.613281 -0.019531 z m 0 0" fill="#2e3436"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" height="16px" viewBox="0 0 16 16" width="16px"><path d="m 14.285156 0.59375 c -0.382812 0.011719 -0.746094 0.171875 -1.015625 0.441406 l -3.535156 3.535156 l 1.414063 1.414063 l 2.535156 -2.535156 c 0.574218 0.273437 1.257812 0.15625 1.707031 -0.292969 c 0.585937 -0.585938 0.585937 -1.535156 0 -2.121094 c -0.292969 -0.292968 -0.691406 -0.453125 -1.105469 -0.441406 z m -5.257812 4.683594 l -8.484375 8.488281 c 0.707031 0.703125 5.65625 1.410156 12.019531 -4.953125 z m 0 0"/></svg>

After

Width:  |  Height:  |  Size: 564 B

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
<path d="m 4 4 h 1 h 0.03125 c 0.253906 0.011719 0.511719 0.128906 0.6875 0.3125 l 2.28125 2.28125 l 2.3125 -2.28125 c 0.265625 -0.230469 0.445312 -0.304688 0.6875 -0.3125 h 1 v 1 c 0 0.285156 -0.035156 0.550781 -0.25 0.75 l -2.28125 2.28125 l 2.25 2.25 c 0.1875 0.1875 0.28125 0.453125 0.28125 0.71875 v 1 h -1 c -0.265625 0 -0.53125 -0.09375 -0.71875 -0.28125 l -2.28125 -2.28125 l -2.28125 2.28125 c -0.1875 0.1875 -0.453125 0.28125 -0.71875 0.28125 h -1 v -1 c 0 -0.265625 0.09375 -0.53125 0.28125 -0.71875 l 2.28125 -2.25 l -2.28125 -2.28125 c -0.210938 -0.195312 -0.304688 -0.46875 -0.28125 -0.75 z m 0 0" fill="#2e3436"/>
</svg>

After

Width:  |  Height:  |  Size: 767 B

View file

@ -13,6 +13,8 @@ failed-get-selected-wine = Die ausgewählte Wine-Version konnte nicht abgerufen
downloading-failed = Herunterladen fehlgeschlagen downloading-failed = Herunterladen fehlgeschlagen
unpacking-failed = Entpacken fehlgeschlagen unpacking-failed = Entpacken fehlgeschlagen
kill-game-process-failed = Die Spielprozesse konnten nicht terminiert werden
game-file-repairing-error = Reparieren der Spieldatei fehlgeschlagen game-file-repairing-error = Reparieren der Spieldatei fehlgeschlagen
integrity-files-getting-error = Integritätsdateien konnten nicht abgerufen werden integrity-files-getting-error = Integritätsdateien konnten nicht abgerufen werden

View file

@ -58,6 +58,9 @@ disable-mhypbase-description = Experimentell. Wenn sie diese option aktivieren,
ask-superuser-permissions = Superuser-Berechtigungen anfordern 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 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 wine-tools = Wine-Tools
command-line = Befehlszeile command-line = Befehlszeile
registry-editor = Registrierungs-Editor registry-editor = Registrierungs-Editor

View file

@ -18,6 +18,8 @@ about = Über
close = Schließen close = Schließen
hide = Verstecken
nothing = Nichts
save = Speichern save = Speichern
continue = Weiter continue = Weiter
resume = Fortsetzen resume = Fortsetzen
@ -62,6 +64,8 @@ update = Updaten
download = Herunterladen download = Herunterladen
predownload-update = Vorab-Update von Version {$version} herunterladen ({$size}) 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-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--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 main-window--version-outdated-tooltip = Die Version ist zu veraltet und kann nicht aktualisiert werden

View file

@ -13,6 +13,8 @@ failed-get-selected-wine = Failed to get selected wine version
downloading-failed = Downloading failed downloading-failed = Downloading failed
unpacking-failed = Unpacking 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 game-file-repairing-error = Failed to repair game file
integrity-files-getting-error = Failed to get integrity files integrity-files-getting-error = Failed to get integrity files

View file

@ -58,6 +58,9 @@ disable-mhypbase-description = Experimental. If enabled, launcher will disable m
ask-superuser-permissions = Ask superuser permissions 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 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 wine-tools = Wine tools
command-line = Command line command-line = Command line
registry-editor = Registry editor registry-editor = Registry editor

View file

@ -18,6 +18,8 @@ about = About
close = Close close = Close
hide = Hide
nothing = Nothing
save = Save save = Save
continue = Continue continue = Continue
resume = Resume resume = Resume
@ -62,6 +64,8 @@ update = Update
download = Download download = Download
predownload-update = Pre-download {$version} update ({$size}) 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-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--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 main-window--version-outdated-tooltip = Version is too outdated and can't be updated

View file

@ -13,6 +13,8 @@ failed-get-selected-wine = Fallo al buscar la versión elegida de Wine
downloading-failed = Descarga fallida downloading-failed = Descarga fallida
unpacking-failed = Descompresión 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 game-file-repairing-error = Fallo al reparar archivo del juego
integrity-files-getting-error = Fallo al buscar archivos de integridad integrity-files-getting-error = Fallo al buscar archivos de integridad

View file

@ -58,6 +58,9 @@ disable-mhypbase-description = Experimental. Si se activa, el launcher desactiva
ask-superuser-permissions = Pedir permisos de superusuario 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 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 wine-tools = Herramientas de Wine
command-line = Línea de Comandos command-line = Línea de Comandos
registry-editor = Editor del Registro registry-editor = Editor del Registro

View file

@ -18,6 +18,8 @@ about = Acerca de
close = Cerrar close = Cerrar
hide = Hide
nothing = Nothing
save = Guardar save = Guardar
continue = Continuar continue = Continuar
resume = Reanudar resume = Reanudar
@ -62,6 +64,8 @@ update = Actualizar
download = Descargar download = Descargar
predownload-update = Pre-descargar actualización {$version} ({$size}) 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-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--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. main-window--version-outdated-tooltip = La versión es demasiado vieja y no puede actualizarse.

View file

@ -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é downloading-failed = Le téléchargement a échoué
unpacking-failed = L'extraction 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 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 integrity-files-getting-error = Impossible de récupérer les fichiers d'intégrité du jeu

View file

@ -58,6 +58,9 @@ disable-mhypbase-description = Experimental. If enabled, launcher will disable m
ask-superuser-permissions = Ask superuser permissions 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 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 wine-tools = Wine tools
command-line = Command line command-line = Command line
registry-editor = Registry editor registry-editor = Registry editor

View file

@ -18,6 +18,8 @@ about = À propos
close = Fermer close = Fermer
hide = Hide
nothing = Nothing
save = Sauvegarder save = Sauvegarder
continue = Continuer continue = Continuer
resume = Reprendre resume = Reprendre
@ -62,6 +64,8 @@ update = Mettre à jour
download = Télécharger download = Télécharger
predownload-update = Pré-télécharger la mise à jour {$version} ({$size}) 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-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--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 main-window--version-outdated-tooltip = La version du jeu est trop ancienne et ne peut pas être mise à jour

View file

@ -13,6 +13,8 @@ failed-get-selected-wine = Kiválasztott wine verzió beszerzése sikertelen
downloading-failed = Sikertelen letöltés downloading-failed = Sikertelen letöltés
unpacking-failed = Sikertelen kicsomagolá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 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 integrity-files-getting-error = Integritásfájlok beszerzése sikertelen

View file

@ -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 = 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 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 wine-tools = Wine eszközök
command-line = Parancssor command-line = Parancssor
registry-editor = Registry szerksztő registry-editor = Registry szerksztő

View file

@ -18,6 +18,8 @@ about = Részletek
close = Bezárás close = Bezárás
hide = Hide
nothing = Nothing
save = Mentés save = Mentés
continue = Folytatás continue = Folytatás
resume = Resume resume = Resume
@ -62,6 +64,8 @@ update = Frissítés
download = Letöltés download = Letöltés
predownload-update = {$version} verzió előtöltése ({$size}) 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-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--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 main-window--version-outdated-tooltip = Ez a verzió túl elavult és nem lehet frissíteni

View file

@ -13,6 +13,8 @@ failed-get-selected-wine = Gagal mendapatkan versi wine yang dipilih
downloading-failed = Gagal mengunduh downloading-failed = Gagal mengunduh
unpacking-failed = Gagal mengekstrak berkas unpacking-failed = Gagal mengekstrak berkas
kill-game-process-failed = Gagal menghentikan paksa proses game
game-file-repairing-error = Gagal memperbaiki file game game-file-repairing-error = Gagal memperbaiki file game
integrity-files-getting-error = Gagal mendapatkan integritas file integrity-files-getting-error = Gagal mendapatkan integritas file

View file

@ -58,6 +58,9 @@ disable-mhypbase-description = Masih dalam pengujicobaan. Jika diaktifkan, launc
ask-superuser-permissions = Minta izin dari admin 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 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 wine-tools = Peralatan wine
command-line = Command line command-line = Command line
registry-editor = Editor registry registry-editor = Editor registry

View file

@ -16,8 +16,17 @@ debug-file = File debug
wish-url = Buka wishes wish-url = Buka wishes
about = Tentang about = Tentang
close = { $form ->
[verb] Menutup
*[noun] Tutup
}
close = Tutup hide = { $form ->
[verb] Sembunyikan
*[noun] Sembunyi
}
nothing = Tidak berubah
save = Simpan save = Simpan
continue = Lanjutkan continue = Lanjutkan
resume = Lanjutkan resume = Lanjutkan
@ -62,6 +71,8 @@ update = Perbarui
download = Unduh download = Unduh
predownload-update = Pra-unduh pembaruan versi {$version} ({$size}) 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-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--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 main-window--version-outdated-tooltip = Versi terlalu kadaluarsa dan tidak bisa diperbarui

View file

@ -13,6 +13,8 @@ failed-get-selected-wine = Ottenimento della versione selezionata di wine non ri
downloading-failed = Scaricamento non riuscito downloading-failed = Scaricamento non riuscito
unpacking-failed = Unpacking 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 game-file-repairing-error = Riparazione del file di gioco non riuscita
integrity-files-getting-error = Ottenimento dei file di integrità non riuscito integrity-files-getting-error = Ottenimento dei file di integrità non riuscito

View file

@ -58,6 +58,9 @@ disable-mhypbase-description = Sperimentale. Se abiliata, il launcher disabilite
ask-superuser-permissions = Chiedi permessi di amministratore 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 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 wine-tools = Strumenti di Wine
command-line = Linea di comando command-line = Linea di comando
registry-editor = Editor del Registro registry-editor = Editor del Registro

View file

@ -18,6 +18,8 @@ about = Informazioni
close = Chiudi close = Chiudi
hide = Hide
nothing = Nothing
save = Salva save = Salva
continue = Continua continue = Continua
resume = Riprendi resume = Riprendi
@ -62,6 +64,8 @@ update = Aggiorna
download = Scarica download = Scarica
predownload-update = Prescarica {$version} aggiornamento ({$size}) 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-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--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. main-window--version-outdated-tooltip = La versione è troppo vecchia e non può essere aggiornata.

View file

@ -13,6 +13,8 @@ failed-get-selected-wine = 選択されたwineバージョンを入手できま
downloading-failed = ダウンロードに失敗。 downloading-failed = ダウンロードに失敗。
unpacking-failed = 展開失敗 unpacking-failed = 展開失敗
kill-game-process-failed = Failed to kill the game's process
game-file-repairing-error = ゲームファイルの修正に失敗しました。 game-file-repairing-error = ゲームファイルの修正に失敗しました。
integrity-files-getting-error = 整合性ファイルの取得に失敗しました integrity-files-getting-error = 整合性ファイルの取得に失敗しました

View file

@ -58,6 +58,9 @@ disable-mhypbase-description = 試験的です。有効にすると、ランチ
ask-superuser-permissions = スーパーユーザーを尋ねる。 ask-superuser-permissions = スーパーユーザーを尋ねる。
ask-superuser-permissions-description = あなたのホストのファイルを自動更新するために、 これらを利用します。flatpak版では必要ありません。 ask-superuser-permissions-description = あなたのホストのファイルを自動更新するために、 これらを利用します。flatpak版では必要ありません。
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 = レジストリエディタ

View file

@ -18,6 +18,8 @@ about = "An anime Game launcher"について
close = 閉じる close = 閉じる
hide = Hide
nothing = Nothing
save = 保存 save = 保存
continue = 続行 continue = 続行
resume = 一時停止 resume = 一時停止
@ -62,6 +64,8 @@ update = 更新
download = ダウンロード download = ダウンロード
predownload-update = {$version} の早期アップデート({$size}) predownload-update = {$version} の早期アップデート({$size})
kill-game-process = Kill game process
main-window--patch-unavailable-tooltip = パッチサーバーが利用できないため、パッチの状態を確認することができません。リスクを理解した上で実行することができます。 main-window--patch-unavailable-tooltip = パッチサーバーが利用できないため、パッチの状態を確認することができません。リスクを理解した上で実行することができます。
main-window--patch-outdated-tooltip = パッチは期限切れか準備中のため利用できません。しばらく立ってからパッチステータスを確認してください。 main-window--patch-outdated-tooltip = パッチは期限切れか準備中のため利用できません。しばらく立ってからパッチステータスを確認してください。
main-window--version-outdated-tooltip = バージョンが古すぎるため、更新できませんでした。 main-window--version-outdated-tooltip = バージョンが古すぎるため、更新できませんでした。

View file

@ -13,6 +13,8 @@ failed-get-selected-wine = Не удалось найти выбранную в
downloading-failed = Ошибка загрузки downloading-failed = Ошибка загрузки
unpacking-failed = Ошибка распаковки unpacking-failed = Ошибка распаковки
kill-game-process-failed = Не удалось убить процесс игры
game-file-repairing-error = Не удалось починить игровой файл game-file-repairing-error = Не удалось починить игровой файл
integrity-files-getting-error = Не удалось получить верные данные о файлах игры integrity-files-getting-error = Не удалось получить верные данные о файлах игры

View file

@ -58,6 +58,9 @@ disable-mhypbase-description = Экспериментально. Когда вк
ask-superuser-permissions = Запрашивать права суперпользователя ask-superuser-permissions = Запрашивать права суперпользователя
ask-superuser-permissions-description = Лаунчер будет использовать их чтобы автоматически обновлять ваш hosts файл для отключения телеметрии игры. Не требуется при использовании flatpak ask-superuser-permissions-description = Лаунчер будет использовать их чтобы автоматически обновлять ваш hosts файл для отключения телеметрии игры. Не требуется при использовании flatpak
launcher-behavior = Поведение лаунчера
launcher-behavior-description = Что должно делать окно лаунчера когда оно запускает игру
wine-tools = Инструменты Wine wine-tools = Инструменты Wine
command-line = Коммандная строка command-line = Коммандная строка
registry-editor = Редактор реестра registry-editor = Редактор реестра

View file

@ -17,7 +17,17 @@ wish-url = История молитв
about = О программе about = О программе
close = Закрыть close = { $form ->
[verb] Закрываться
*[noun] Закрыть
}
hide = { $form ->
[verb] Скрываться
*[noun] Скрыть
}
nothing = Ничего
save = Сохранить save = Сохранить
continue = Продолжить continue = Продолжить
resume = Возобновить resume = Возобновить
@ -68,6 +78,8 @@ update = Обновить
download = Установить download = Установить
predownload-update = Предустановить обновление {$version} ({$size}) predownload-update = Предустановить обновление {$version} ({$size})
kill-game-process = Убить процесс игры
main-window--patch-unavailable-tooltip = Серверы патча недоступны и лаунчер не может проверить статус патча игры. Вам разрешено запустить игру на ваш страх и риск main-window--patch-unavailable-tooltip = Серверы патча недоступны и лаунчер не может проверить статус патча игры. Вам разрешено запустить игру на ваш страх и риск
main-window--patch-outdated-tooltip = Патч устарел или находится в процессе разработки, поэтому не может быть применен. Возвращайтесь позже чтобы проверить его статус main-window--patch-outdated-tooltip = Патч устарел или находится в процессе разработки, поэтому не может быть применен. Возвращайтесь позже чтобы проверить его статус
main-window--version-outdated-tooltip = Версия слишком стара и не может быть обновлена main-window--version-outdated-tooltip = Версия слишком стара и не может быть обновлена

View file

@ -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 downloading-failed = İndirme başarısız oldu
unpacking-failed = Oyun dosyalarını çıkarma 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 game-file-repairing-error = Oyun dosyaları tamir edilemedi
integrity-files-getting-error = Dosyaların bütünlüğü kontrol edilemedi integrity-files-getting-error = Dosyaların bütünlüğü kontrol edilemedi

View file

@ -58,6 +58,9 @@ disable-mhypbase-description = Deneysel. Etkinleştirilirse, istemci ana yamayı
ask-superuser-permissions = Yönetici izinlerini sor 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 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ı wine-tools = Wine araçları
command-line = Komut istemi command-line = Komut istemi
registry-editor = Girdi düzenleyicisi registry-editor = Girdi düzenleyicisi

View file

@ -18,6 +18,8 @@ about = Hakkında
close = Kapat close = Kapat
hide = Hide
nothing = Nothing
save = Kaydet save = Kaydet
continue = Devam et continue = Devam et
resume = Sürdürmek resume = Sürdürmek
@ -62,6 +64,8 @@ update = Güncelle
download = İndir download = İndir
predownload-update = Güncellemeyi önceden indir{$version} ({$size}) 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-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--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 main-window--version-outdated-tooltip = Sürüm çok eski ve güncellenemez

View file

@ -13,6 +13,8 @@ failed-get-selected-wine = 选择 Wine 版本失败
downloading-failed = 下载失败 downloading-failed = 下载失败
unpacking-failed = 解压缩失败 unpacking-failed = 解压缩失败
kill-game-process-failed = Failed to kill the game's process
game-file-repairing-error = 修复游戏文件失败 game-file-repairing-error = 修复游戏文件失败
integrity-files-getting-error = 获取一致性文件失败 integrity-files-getting-error = 获取一致性文件失败

View file

@ -58,6 +58,9 @@ disable-mhypbase-description = 实验性功能。启用此选项后,启动器
ask-superuser-permissions = 请求超级用户权限 ask-superuser-permissions = 请求超级用户权限
ask-superuser-permissions-description = 启动器需要超级用户权限来修改 hosts 文件。Flatpak 版无需此权限 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 工具 wine-tools = Wine 工具
command-line = 命令行 command-line = 命令行
registry-editor = 注册表编辑器 registry-editor = 注册表编辑器

View file

@ -18,6 +18,8 @@ about = 关于
close = 关闭 close = 关闭
hide = Hide
nothing = Nothing
save = 保存 save = 保存
continue = 继续 continue = 继续
resume = 恢复 resume = 恢复
@ -62,6 +64,8 @@ update = 更新
download = 下载 download = 下载
predownload-update = 预下载版本更新 {$version} ({$size}) predownload-update = 预下载版本更新 {$version} ({$size})
kill-game-process = Kill game process
main-window--patch-unavailable-tooltip = 补丁服务器不可用,启动器无法验证游戏补丁状态。你可以运行游戏,但是有出问题的风险 main-window--patch-unavailable-tooltip = 补丁服务器不可用,启动器无法验证游戏补丁状态。你可以运行游戏,但是有出问题的风险
main-window--patch-outdated-tooltip = 补丁版本太旧,新版补丁可能还没制作完成,无法使用。请过段时间再回来查看最新状态 main-window--patch-outdated-tooltip = 补丁版本太旧,新版补丁可能还没制作完成,无法使用。请过段时间再回来查看最新状态
main-window--version-outdated-tooltip = 版本太旧,无法更新 main-window--version-outdated-tooltip = 版本太旧,无法更新

View file

@ -1,12 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<gresources> <gresources>
<gresource prefix="/org/app"> <gresource prefix="/moe/launcher/an-anime-game-launcher">
<file compressed="true">images/icon.png</file> <file preprocess="xml-stripblanks">images/modern.svg</file>
<file preprocess="xml-stripblanks">images/classic.svg</file>
</gresource> </gresource>
<gresource prefix="/org/app">
<file compressed="true">images/modern.svg</file> <gresource prefix="/moe/launcher/an-anime-game-launcher/icons/hicolor/scalable/apps">
<file alias="moe.launcher.an-anime-game-launcher.png">images/icon.png</file>
</gresource> </gresource>
<gresource prefix="/org/app">
<file compressed="true">images/classic.svg</file> <gresource prefix="/moe/launcher/an-anime-game-launcher/icons/scalable/actions">
<!-- Standard icons -->
<file preprocess="xml-stripblanks" alias="document-save-symbolic.svg">images/icons/document-save-symbolic.svg</file>
<file preprocess="xml-stripblanks" alias="folder-symbolic.svg">images/icons/folder-symbolic.svg</file>
<file preprocess="xml-stripblanks" alias="emblem-ok-symbolic.svg">images/icons/emblem-ok-symbolic.svg</file>
<file preprocess="xml-stripblanks" alias="open-menu-symbolic.svg">images/icons/open-menu-symbolic.svg</file>
<file preprocess="xml-stripblanks" alias="media-playback-start-symbolic.svg">images/icons/media-playback-start-symbolic.svg</file>
<file preprocess="xml-stripblanks" alias="window-close-symbolic.svg">images/icons/window-close-symbolic.svg</file>
<file preprocess="xml-stripblanks" alias="security-high-symbolic.svg">images/icons/security-high-symbolic.svg</file>
<file preprocess="xml-stripblanks" alias="emblem-system-symbolic.svg">images/icons/emblem-system-symbolic.svg</file>
<file preprocess="xml-stripblanks" alias="user-trash-symbolic.svg">images/icons/user-trash-symbolic.svg</file>
<file preprocess="xml-stripblanks" alias="go-previous-symbolic.svg">images/icons/go-previous-symbolic.svg</file>
<file preprocess="xml-stripblanks" alias="document-properties-symbolic.svg">images/icons/document-properties-symbolic.svg</file>
<file preprocess="xml-stripblanks" alias="list-add-symbolic.svg">images/icons/list-add-symbolic.svg</file>
<file preprocess="xml-stripblanks" alias="view-refresh-symbolic.svg">images/icons/view-refresh-symbolic.svg</file>
<file preprocess="xml-stripblanks" alias="applications-games-symbolic.svg">images/icons/applications-games-symbolic.svg</file>
<file preprocess="xml-stripblanks" alias="applications-graphics-symbolic.svg">images/icons/applications-graphics-symbolic.svg</file>
<file preprocess="xml-stripblanks" alias="go-next-symbolic.svg">images/icons/go-next-symbolic.svg</file>
<file preprocess="xml-stripblanks" alias="dialog-information-symbolic.svg">images/icons/dialog-information-symbolic.svg</file>
<!-- Additional icons icons -->
<file preprocess="xml-stripblanks" alias="violence-symbolic.svg">images/icons/violence-symbolic.svg</file>
</gresource> </gresource>
</gresources> </gresources>

View file

@ -148,9 +148,9 @@ for filename in os.listdir("assets/locales/en"):
# FIXME: it only indexes the first match # FIXME: it only indexes the first match
for line in script.read().split("\n"): for line in script.read().split("\n"):
if ("tr(\"" in line) and ("#" not in line): if ("tr(\"" in line) and ("#" not in line):
index = line.find('tr("') index = line.find('tr!("')
indexLast = line.find('")',index) 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)] script_entries[var_name] = [script.name, get_line_num(script, var_name)]

View file

@ -1,8 +1,7 @@
use fluent_templates::Loader;
use unic_langid::{langid, LanguageIdentifier}; use unic_langid::{langid, LanguageIdentifier};
fluent_templates::static_loader! { fluent_templates::static_loader! {
static LOCALES = { pub static LOCALES = {
locales: "./assets/locales", locales: "./assets/locales",
core_locales: "./assets/locales/common.ftl", core_locales: "./assets/locales/common.ftl",
fallback_language: "en" fallback_language: "en"
@ -24,7 +23,7 @@ pub const SUPPORTED_LANGUAGES: &[LanguageIdentifier] = &[
langid!("hu-hu") langid!("hu-hu")
]; ];
static mut LANG: LanguageIdentifier = langid!("en-us"); pub static mut LANG: LanguageIdentifier = langid!("en-us");
/// Set launcher language /// Set launcher language
pub fn set_lang(lang: LanguageIdentifier) -> anyhow::Result<()> { 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 /// ```no_run
/// println!("Translated message: {}", tr("launch")); /// println!("Translated message: {}", tr!("launch"));
/// ``` /// ```
#[allow(clippy::expect_fun_call)] ///
pub fn tr(id: &str) -> String { /// With parameters:
unsafe { ///
LOCALES /// ```no_run
.lookup(&LANG, id) /// println!("Translated message: {}", tr!("game-outdated", {
.expect(&format!("Failed to find message with given id: {id}")) /// "latest" = "3.3.0"
} /// }));
} /// ```
macro_rules! tr {
($id:expr) => {
{
use fluent_templates::Loader;
/// Get translated message by key with filled arguments #[allow(unused_unsafe)]
/// $crate::i18n::LOCALES
/// ```no_run .lookup(unsafe { &$crate::i18n::LANG }, $id)
/// println!("Translated message: {}", tr_args("game-outdated", [ .expect(&format!("Failed to find a message with given id: {}", stringify!($id)))
/// ("latest", "3.3.0".into())
/// ]));
/// ```
#[allow(clippy::expect_fun_call)]
pub fn tr_args<I, T>(id: &str, args: I) -> String
where
I: IntoIterator<Item = (T, fluent_templates::fluent_bundle::FluentValue<'static>)>,
T: AsRef<str> + 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}"))
} }
};
($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)))
}
};
} }

View file

@ -1,3 +1,6 @@
use std::path::PathBuf;
use std::sync::atomic::{AtomicBool, Ordering};
use relm4::prelude::*; use relm4::prelude::*;
use anime_launcher_sdk::config::ConfigExt; 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::prelude::*;
use tracing_subscriber::filter::*; use tracing_subscriber::filter::*;
use std::path::PathBuf;
use std::sync::atomic::{AtomicBool, Ordering};
pub mod move_folder; pub mod move_folder;
pub mod i18n; pub mod i18n;
pub mod background; pub mod background;
@ -24,6 +24,8 @@ use ui::main::*;
use ui::first_run::main::*; use ui::first_run::main::*;
pub const APP_ID: &str = "moe.launcher.an-anime-game-launcher"; 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_VERSION: &str = env!("CARGO_PKG_VERSION");
pub const APP_DEBUG: bool = cfg!(debug_assertions); pub const APP_DEBUG: bool = cfg!(debug_assertions);
@ -68,6 +70,9 @@ lazy_static::lazy_static! {
} }
fn main() { fn main() {
// Setup custom panic handler
human_panic::setup_panic!(human_panic::metadata!());
// Create launcher folder if it isn't // Create launcher folder if it isn't
if !LAUNCHER_FOLDER.exists() { if !LAUNCHER_FOLDER.exists() {
std::fs::create_dir_all(LAUNCHER_FOLDER.as_path()).expect("Failed to create launcher folder"); 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 // Forcely run the game
let just_run_game = std::env::args().any(|arg| &arg == "--just-run-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 // Prepare stdout logger
let stdout = tracing_subscriber::fmt::layer() let stdout = tracing_subscriber::fmt::layer()
.pretty() .pretty()
@ -103,8 +111,8 @@ fn main() {
LevelFilter::WARN LevelFilter::WARN
} }
}) })
.with_filter(filter_fn(|metadata| { .with_filter(filter_fn(move |metadata| {
!metadata.target().contains("rustls") !metadata.target().contains("rustls") && !no_verbose_tracing
})); }));
// Prepare debug file logger // Prepare debug file logger
@ -134,6 +142,10 @@ fn main() {
gtk::gio::resources_register_include!("resources.gresource") gtk::gio::resources_register_include!("resources.gresource")
.expect("Failed to register resources"); .expect("Failed to register resources");
// Set icons search path
gtk::IconTheme::for_display(&gtk::gdk::Display::default().unwrap())
.add_resource_path(&format!("{APP_RESOURCE_PATH}/icons"));
// Set application's title // Set application's title
gtk::glib::set_application_name("An Anime Game Launcher"); gtk::glib::set_application_name("An Anime Game Launcher");
gtk::glib::set_program_name(Some("An Anime Game Launcher")); gtk::glib::set_program_name(Some("An Anime Game Launcher"));

View file

@ -96,18 +96,37 @@ impl SimpleComponent for AboutDialog {
format!("Anime Launcher SDK: {SDK_VERSION}"), format!("Anime Launcher SDK: {SDK_VERSION}"),
format!("Anime Game Core: {CORE_VERSION}"), format!("Anime Game Core: {CORE_VERSION}"),
String::new(), 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!("libadwaita: {}.{}.{}", adw::major_version(), adw::minor_version(), adw::micro_version()),
format!("pango: {}", gtk::pango::version_string()), format!("pango: {}", gtk::pango::version_string()),
format!("cairo: {}", gtk::cairo::version_string()), format!("cairo: {}", gtk::cairo::version_string())
].join("\n"), ].join("\n"),
set_release_notes_version: &APP_VERSION, set_release_notes_version: &APP_VERSION,
set_release_notes: &[ set_release_notes: &[
"<p>Added</p>",
"<ul>",
"<li>Added new gamescope version compatibility</li>",
"<li>Added \"launcher behavior\" option</li>",
"<li>Added \"kill game process\" button when chosen behavior keeps launcher window open</li>",
"<li>Bundled some icons into the app for consistency across the systems</li>",
"<li>Added better panics handler</li>",
"</ul>",
"<p>Fixed</p>", "<p>Fixed</p>",
"<ul>", "<ul>",
"<li>Fixed game launching on installs without `launcher.bat` file</li>", "<li>Fixed predownload button sensitivity</li>",
"</ul>",
"<p>Changed</p>",
"<ul>",
"<li>Improved pre-downloads state checking</li>",
"<li>Replaced translation functions by `tr!` macro</li>",
"<li>Reworked app resources structure</li>",
"<li>Improved game running status check (wasn't working properly with Chinese client)</li>",
"</ul>", "</ul>",
].join("\n"), ].join("\n"),

View file

@ -6,7 +6,7 @@ use adw::prelude::*;
use anime_launcher_sdk::anime_game_core::prelude::*; use anime_launcher_sdk::anime_game_core::prelude::*;
use anime_launcher_sdk::anime_game_core::genshin::prelude::*; use anime_launcher_sdk::anime_game_core::genshin::prelude::*;
use crate::i18n::*; use crate::*;
pub struct ProgressBarInit { pub struct ProgressBarInit {
pub caption: Option<String>, pub caption: Option<String>,
@ -133,19 +133,19 @@ impl SimpleAsyncComponent for ProgressBar {
ProgressBarMsg::UpdateFromState(state) => { ProgressBarMsg::UpdateFromState(state) => {
match state { match state {
DiffUpdate::CheckingFreeSpace(_) | 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::DownloadingStarted(_)) => self.caption = Some(tr!("downloading")),
DiffUpdate::InstallerUpdate(InstallerUpdate::UnpackingStarted(_)) => self.caption = Some(tr("unpacking")), DiffUpdate::InstallerUpdate(InstallerUpdate::UnpackingStarted(_)) => self.caption = Some(tr!("unpacking")),
DiffUpdate::ApplyingHdiffStarted => { DiffUpdate::ApplyingHdiffStarted => {
self.caption = Some(tr("applying-hdiff")); self.caption = Some(tr!("applying-hdiff"));
self.display_fraction = false; self.display_fraction = false;
}, },
DiffUpdate::RemovingOutdatedStarted => { DiffUpdate::RemovingOutdatedStarted => {
self.caption = Some(tr("removing-outdated")); self.caption = Some(tr!("removing-outdated"));
self.display_fraction = false; self.display_fraction = false;
}, },

View file

@ -6,7 +6,6 @@ use relm4::component::*;
use adw::prelude::*; use adw::prelude::*;
use crate::*; use crate::*;
use crate::i18n::*;
use crate::ui::components::progress_bar::*; use crate::ui::components::progress_bar::*;
use super::main::*; use super::main::*;
@ -68,7 +67,7 @@ impl SimpleAsyncComponent for DefaultPathsApp {
set_vexpand: true, set_vexpand: true,
gtk::Label { gtk::Label {
set_label: &tr("choose-default-paths"), set_label: &tr!("choose-default-paths"),
add_css_class: "title-1" add_css_class: "title-1"
} }
}, },
@ -81,7 +80,7 @@ impl SimpleAsyncComponent for DefaultPathsApp {
set_sensitive: !model.show_progress, set_sensitive: !model.show_progress,
adw::ActionRow { adw::ActionRow {
set_title: &tr("launcher-folder"), set_title: &tr!("launcher-folder"),
set_icon_name: Some("folder-symbolic"), set_icon_name: Some("folder-symbolic"),
set_activatable: true, set_activatable: true,
@ -97,8 +96,8 @@ impl SimpleAsyncComponent for DefaultPathsApp {
set_vexpand: true, set_vexpand: true,
adw::ActionRow { adw::ActionRow {
set_title: &tr("show-all-folders"), set_title: &tr!("show-all-folders"),
set_subtitle: &tr("show-all-folders-subtitle"), set_subtitle: &tr!("show-all-folders-subtitle"),
add_suffix = &gtk::Switch { add_suffix = &gtk::Switch {
set_valign: gtk::Align::Center, set_valign: gtk::Align::Center,
@ -119,7 +118,7 @@ impl SimpleAsyncComponent for DefaultPathsApp {
set_sensitive: !model.show_progress, set_sensitive: !model.show_progress,
adw::ActionRow { adw::ActionRow {
set_title: &tr("runners-folder"), set_title: &tr!("runners-folder"),
set_icon_name: Some("folder-symbolic"), set_icon_name: Some("folder-symbolic"),
set_activatable: true, set_activatable: true,
@ -130,7 +129,7 @@ impl SimpleAsyncComponent for DefaultPathsApp {
}, },
adw::ActionRow { adw::ActionRow {
set_title: &tr("dxvks-folder"), set_title: &tr!("dxvks-folder"),
set_icon_name: Some("folder-symbolic"), set_icon_name: Some("folder-symbolic"),
set_activatable: true, set_activatable: true,
@ -141,7 +140,7 @@ impl SimpleAsyncComponent for DefaultPathsApp {
}, },
adw::ActionRow { adw::ActionRow {
set_title: &tr("wine-prefix-folder"), set_title: &tr!("wine-prefix-folder"),
set_icon_name: Some("folder-symbolic"), set_icon_name: Some("folder-symbolic"),
set_activatable: true, set_activatable: true,
@ -152,7 +151,7 @@ impl SimpleAsyncComponent for DefaultPathsApp {
}, },
adw::ActionRow { adw::ActionRow {
set_title: &tr("global-game-installation-folder"), set_title: &tr!("global-game-installation-folder"),
set_icon_name: Some("folder-symbolic"), set_icon_name: Some("folder-symbolic"),
set_activatable: true, set_activatable: true,
@ -163,7 +162,7 @@ impl SimpleAsyncComponent for DefaultPathsApp {
}, },
adw::ActionRow { adw::ActionRow {
set_title: &tr("chinese-game-installation-folder"), set_title: &tr!("chinese-game-installation-folder"),
set_icon_name: Some("folder-symbolic"), set_icon_name: Some("folder-symbolic"),
set_activatable: true, set_activatable: true,
@ -174,7 +173,7 @@ impl SimpleAsyncComponent for DefaultPathsApp {
}, },
adw::ActionRow { adw::ActionRow {
set_title: &tr("fps-unlocker-folder"), set_title: &tr!("fps-unlocker-folder"),
set_icon_name: Some("folder-symbolic"), set_icon_name: Some("folder-symbolic"),
set_activatable: true, set_activatable: true,
@ -185,7 +184,7 @@ impl SimpleAsyncComponent for DefaultPathsApp {
}, },
adw::ActionRow { adw::ActionRow {
set_title: &tr("components-index"), set_title: &tr!("components-index"),
set_icon_name: Some("folder-symbolic"), set_icon_name: Some("folder-symbolic"),
set_activatable: true, set_activatable: true,
@ -196,7 +195,7 @@ impl SimpleAsyncComponent for DefaultPathsApp {
}, },
adw::ActionRow { adw::ActionRow {
set_title: &tr("patch-folder"), set_title: &tr!("patch-folder"),
set_icon_name: Some("folder-symbolic"), set_icon_name: Some("folder-symbolic"),
set_activatable: true, set_activatable: true,
@ -207,7 +206,7 @@ impl SimpleAsyncComponent for DefaultPathsApp {
}, },
adw::ActionRow { adw::ActionRow {
set_title: &tr("temp-folder"), set_title: &tr!("temp-folder"),
set_icon_name: Some("folder-symbolic"), set_icon_name: Some("folder-symbolic"),
set_activatable: true, set_activatable: true,
@ -232,9 +231,9 @@ impl SimpleAsyncComponent for DefaultPathsApp {
gtk::Button { gtk::Button {
set_label: &if model.migrate_installation { set_label: &if model.migrate_installation {
tr("migrate") tr!("migrate")
} else { } else {
tr("continue") tr!("continue")
}, },
set_css_classes: &["suggested-action", "pill"], set_css_classes: &["suggested-action", "pill"],
@ -244,9 +243,9 @@ impl SimpleAsyncComponent for DefaultPathsApp {
gtk::Button { gtk::Button {
set_label: &if model.migrate_installation { set_label: &if model.migrate_installation {
tr("close") tr!("close", { "form" = "noun" })
} else { } else {
tr("exit") tr!("exit")
}, },
add_css_class: "pill", add_css_class: "pill",
@ -407,7 +406,7 @@ impl SimpleAsyncComponent for DefaultPathsApp {
Err(err) => { Err(err) => {
sender.output(Self::Output::Toast { sender.output(Self::Output::Toast {
title: tr("config-update-error"), title: tr!("config-update-error"),
description: Some(err.to_string()) description: Some(err.to_string())
}); });
} }

View file

@ -5,7 +5,7 @@ use adw::prelude::*;
use anime_launcher_sdk::is_available; use anime_launcher_sdk::is_available;
use crate::i18n::*; use crate::*;
use super::main::FirstRunAppMsg; use super::main::FirstRunAppMsg;
@ -36,12 +36,12 @@ impl SimpleAsyncComponent for DependenciesApp {
set_vexpand: true, set_vexpand: true,
gtk::Label { gtk::Label {
set_label: &tr("missing-dependencies-title"), set_label: &tr!("missing-dependencies-title"),
add_css_class: "title-1" add_css_class: "title-1"
}, },
gtk::Label { gtk::Label {
set_label: &tr("missing-dependencies-message"), set_label: &tr!("missing-dependencies-message"),
set_justify: gtk::Justification::Center, set_justify: gtk::Justification::Center,
set_wrap: true, set_wrap: true,
@ -120,14 +120,14 @@ impl SimpleAsyncComponent for DependenciesApp {
set_spacing: 8, set_spacing: 8,
gtk::Button { gtk::Button {
set_label: &tr("check"), set_label: &tr!("check"),
set_css_classes: &["suggested-action", "pill"], set_css_classes: &["suggested-action", "pill"],
connect_clicked => DependenciesAppMsg::Continue connect_clicked => DependenciesAppMsg::Continue
}, },
gtk::Button { gtk::Button {
set_label: &tr("exit"), set_label: &tr!("exit"),
add_css_class: "pill", add_css_class: "pill",
connect_clicked => DependenciesAppMsg::Exit connect_clicked => DependenciesAppMsg::Exit
@ -175,7 +175,9 @@ impl SimpleAsyncComponent for DependenciesApp {
for package in packages { for package in packages {
if !is_available(package) { if !is_available(package) {
sender.output(Self::Output::Toast { sender.output(Self::Output::Toast {
title: tr_args("package-not-available", [("package", package.into())]), title: tr!("package-not-available", {
"package" = package
}),
description: None description: None
}); });

View file

@ -17,7 +17,6 @@ use anime_launcher_sdk::genshin::config::Config;
use super::main::FirstRunAppMsg; use super::main::FirstRunAppMsg;
use crate::ui::components::*; use crate::ui::components::*;
use crate::i18n::*;
use crate::*; use crate::*;
fn get_installer(uri: &str, temp: Option<PathBuf>) -> anyhow::Result<Installer> { fn get_installer(uri: &str, temp: Option<PathBuf>) -> anyhow::Result<Installer> {
@ -88,7 +87,7 @@ impl SimpleAsyncComponent for DownloadComponentsApp {
set_vexpand: true, set_vexpand: true,
gtk::Label { gtk::Label {
set_label: &tr("download-components"), set_label: &tr!("download-components"),
add_css_class: "title-1" add_css_class: "title-1"
} }
}, },
@ -102,7 +101,7 @@ impl SimpleAsyncComponent for DownloadComponentsApp {
#[local_ref] #[local_ref]
wine_combo -> adw::ComboRow { wine_combo -> adw::ComboRow {
set_title: &tr("wine-version"), set_title: &tr!("wine-version"),
#[watch] #[watch]
set_model: Some(&gtk::StringList::new(model.wine_versions.iter() set_model: Some(&gtk::StringList::new(model.wine_versions.iter()
@ -113,7 +112,7 @@ impl SimpleAsyncComponent for DownloadComponentsApp {
#[local_ref] #[local_ref]
dxvk_combo -> adw::ComboRow { dxvk_combo -> adw::ComboRow {
set_title: &tr("dxvk-version"), set_title: &tr!("dxvk-version"),
#[watch] #[watch]
set_model: Some(&gtk::StringList::new(model.dxvk_versions.iter() set_model: Some(&gtk::StringList::new(model.dxvk_versions.iter()
@ -136,14 +135,14 @@ impl SimpleAsyncComponent for DownloadComponentsApp {
set_spacing: 8, set_spacing: 8,
gtk::Button { gtk::Button {
set_label: &tr("download"), set_label: &tr!("download"),
set_css_classes: &["suggested-action", "pill"], set_css_classes: &["suggested-action", "pill"],
connect_clicked => DownloadComponentsAppMsg::DownloadWine connect_clicked => DownloadComponentsAppMsg::DownloadWine
}, },
gtk::Button { gtk::Button {
set_label: &tr("exit"), set_label: &tr!("exit"),
add_css_class: "pill", add_css_class: "pill",
connect_clicked => DownloadComponentsAppMsg::Exit connect_clicked => DownloadComponentsAppMsg::Exit
@ -159,7 +158,7 @@ impl SimpleAsyncComponent for DownloadComponentsApp {
set_visible: model.downloading, set_visible: model.downloading,
adw::ActionRow { adw::ActionRow {
set_title: &tr("download-wine"), set_title: &tr!("download-wine"),
#[watch] #[watch]
set_subtitle: &model.downloading_wine_version, set_subtitle: &model.downloading_wine_version,
@ -180,7 +179,7 @@ impl SimpleAsyncComponent for DownloadComponentsApp {
}, },
adw::ActionRow { adw::ActionRow {
set_title: &tr("create-prefix"), set_title: &tr!("create-prefix"),
#[watch] #[watch]
set_subtitle: &model.creating_prefix_path, set_subtitle: &model.creating_prefix_path,
@ -201,7 +200,7 @@ impl SimpleAsyncComponent for DownloadComponentsApp {
}, },
adw::ActionRow { adw::ActionRow {
set_title: &tr("download-dxvk"), set_title: &tr!("download-dxvk"),
#[watch] #[watch]
set_subtitle: &model.downloading_dxvk_version, set_subtitle: &model.downloading_dxvk_version,
@ -222,7 +221,7 @@ impl SimpleAsyncComponent for DownloadComponentsApp {
}, },
adw::ActionRow { adw::ActionRow {
set_title: &tr("apply-dxvk"), set_title: &tr!("apply-dxvk"),
#[watch] #[watch]
set_icon_name: match model.applying_dxvk { set_icon_name: match model.applying_dxvk {
@ -356,7 +355,7 @@ impl SimpleAsyncComponent for DownloadComponentsApp {
tracing::error!("Failed to update config: {err}"); tracing::error!("Failed to update config: {err}");
sender.output(Self::Output::Toast { sender.output(Self::Output::Toast {
title: tr("config-update-error"), title: tr!("config-update-error"),
description: Some(err.to_string()) description: Some(err.to_string())
}); });
} }
@ -384,7 +383,7 @@ impl SimpleAsyncComponent for DownloadComponentsApp {
tracing::error!("Failed to download wine: {err}"); tracing::error!("Failed to download wine: {err}");
sender.output(Self::Output::Toast { sender.output(Self::Output::Toast {
title: tr("wine-download-error"), title: tr!("wine-download-error"),
description: Some(err.to_string()) description: Some(err.to_string())
}); });
} }
@ -393,7 +392,7 @@ impl SimpleAsyncComponent for DownloadComponentsApp {
tracing::error!("Failed to unpack wine: {err}"); tracing::error!("Failed to unpack wine: {err}");
sender.output(Self::Output::Toast { sender.output(Self::Output::Toast {
title: tr("wine-unpack-errror"), title: tr!("wine-unpack-errror"),
description: Some(err.clone()) description: Some(err.clone())
}); });
} }
@ -408,7 +407,7 @@ impl SimpleAsyncComponent for DownloadComponentsApp {
tracing::error!("Failed to update config: {err}"); tracing::error!("Failed to update config: {err}");
sender.output(Self::Output::Toast { sender.output(Self::Output::Toast {
title: tr("config-update-error"), title: tr!("config-update-error"),
description: Some(err.to_string()) description: Some(err.to_string())
}); });
} }
@ -427,7 +426,7 @@ impl SimpleAsyncComponent for DownloadComponentsApp {
tracing::error!("Failed to initialize wine installer: {err}"); tracing::error!("Failed to initialize wine installer: {err}");
sender.output(Self::Output::Toast { sender.output(Self::Output::Toast {
title: tr("wine-install-failed"), title: tr!("wine-install-failed"),
description: Some(err.to_string()) description: Some(err.to_string())
}); });
} }
@ -464,7 +463,7 @@ impl SimpleAsyncComponent for DownloadComponentsApp {
tracing::error!("Failed to create prefix: {err}"); tracing::error!("Failed to create prefix: {err}");
sender.output(Self::Output::Toast { sender.output(Self::Output::Toast {
title: tr("wine-prefix-update-failed"), title: tr!("wine-prefix-update-failed"),
description: Some(err.to_string()) description: Some(err.to_string())
}); });
} }
@ -510,7 +509,7 @@ impl SimpleAsyncComponent for DownloadComponentsApp {
tracing::error!("Failed to download dxvk: {err}"); tracing::error!("Failed to download dxvk: {err}");
sender.output(Self::Output::Toast { sender.output(Self::Output::Toast {
title: tr("dxvk-download-error"), title: tr!("dxvk-download-error"),
description: Some(err.to_string()) description: Some(err.to_string())
}); });
} }
@ -519,7 +518,7 @@ impl SimpleAsyncComponent for DownloadComponentsApp {
tracing::error!("Failed to unpack dxvk: {err}"); tracing::error!("Failed to unpack dxvk: {err}");
sender.output(Self::Output::Toast { sender.output(Self::Output::Toast {
title: tr("dxvk-unpack-error"), title: tr!("dxvk-unpack-error"),
description: Some(err.clone()) description: Some(err.clone())
}); });
} }
@ -540,7 +539,7 @@ impl SimpleAsyncComponent for DownloadComponentsApp {
tracing::error!("Failed to initialize dxvk installer: {err}"); tracing::error!("Failed to initialize dxvk installer: {err}");
sender.output(Self::Output::Toast { sender.output(Self::Output::Toast {
title: tr("dxvk-install-failed"), title: tr!("dxvk-install-failed"),
description: Some(err.to_string()) description: Some(err.to_string())
}); });
} }
@ -593,7 +592,7 @@ impl SimpleAsyncComponent for DownloadComponentsApp {
tracing::error!("Failed to apply DXVK: {err}"); tracing::error!("Failed to apply DXVK: {err}");
sender.output(Self::Output::Toast { sender.output(Self::Output::Toast {
title: tr("dxvk-apply-error"), title: tr!("dxvk-apply-error"),
description: Some(err.to_string()) description: Some(err.to_string())
}); });
} }

View file

@ -3,7 +3,7 @@ use relm4::component::*;
use adw::prelude::*; use adw::prelude::*;
use crate::i18n::*; use crate::*;
use super::main::*; use super::main::*;
@ -30,12 +30,12 @@ impl SimpleAsyncComponent for FinishApp {
set_vexpand: true, set_vexpand: true,
gtk::Label { gtk::Label {
set_label: &tr("finish-title"), set_label: &tr!("finish-title"),
add_css_class: "title-1" add_css_class: "title-1"
}, },
gtk::Label { gtk::Label {
set_label: &tr("finish-message"), set_label: &tr!("finish-message"),
set_justify: gtk::Justification::Center, set_justify: gtk::Justification::Center,
set_wrap: true, set_wrap: true,
@ -53,14 +53,14 @@ impl SimpleAsyncComponent for FinishApp {
set_spacing: 8, set_spacing: 8,
gtk::Button { gtk::Button {
set_label: &tr("restart"), set_label: &tr!("restart"),
set_css_classes: &["suggested-action", "pill"], set_css_classes: &["suggested-action", "pill"],
connect_clicked => FinishAppMsg::Restart connect_clicked => FinishAppMsg::Restart
}, },
gtk::Button { gtk::Button {
set_label: &tr("exit"), set_label: &tr!("exit"),
add_css_class: "pill", add_css_class: "pill",
connect_clicked => FinishAppMsg::Exit connect_clicked => FinishAppMsg::Exit

View file

@ -6,7 +6,6 @@ use adw::prelude::*;
use anime_launcher_sdk::components::loader::ComponentsLoader; use anime_launcher_sdk::components::loader::ComponentsLoader;
use crate::i18n::tr;
use crate::*; use crate::*;
use super::welcome::*; use super::welcome::*;
@ -77,7 +76,7 @@ impl SimpleComponent for FirstRunApp {
}, },
adw::StatusPage { adw::StatusPage {
set_title: &tr("loading-data"), set_title: &tr!("loading-data"),
set_icon_name: Some(APP_ID), set_icon_name: Some(APP_ID),
set_vexpand: true, set_vexpand: true,
@ -164,7 +163,7 @@ impl SimpleComponent for FirstRunApp {
carousel, carousel,
loading: None, loading: None,
title: tr("welcome") title: tr!("welcome")
}; };
let toast_overlay = &model.toast_overlay; let toast_overlay = &model.toast_overlay;
@ -192,32 +191,32 @@ impl SimpleComponent for FirstRunApp {
} }
FirstRunAppMsg::ScrollToTosWarning => { FirstRunAppMsg::ScrollToTosWarning => {
self.title = tr("tos-violation-warning"); self.title = tr!("tos-violation-warning");
self.carousel.scroll_to(self.tos_warning.widget(), true); self.carousel.scroll_to(self.tos_warning.widget(), true);
} }
FirstRunAppMsg::ScrollToDependencies => { FirstRunAppMsg::ScrollToDependencies => {
self.title = tr("dependencies"); self.title = tr!("dependencies");
self.carousel.scroll_to(self.dependencies.widget(), true); self.carousel.scroll_to(self.dependencies.widget(), true);
} }
FirstRunAppMsg::ScrollToDefaultPaths => { FirstRunAppMsg::ScrollToDefaultPaths => {
self.title = tr("default-paths"); self.title = tr!("default-paths");
self.carousel.scroll_to(self.default_paths.widget(), true); self.carousel.scroll_to(self.default_paths.widget(), true);
} }
FirstRunAppMsg::ScrollToSelectVoiceovers => { FirstRunAppMsg::ScrollToSelectVoiceovers => {
self.title = tr("select-voice-packages"); self.title = tr!("select-voice-packages");
self.carousel.scroll_to(self.select_voiceovers.widget(), true); self.carousel.scroll_to(self.select_voiceovers.widget(), true);
} }
FirstRunAppMsg::ScrollToDownloadComponents => { FirstRunAppMsg::ScrollToDownloadComponents => {
// Update components index // 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()); let config = Config::get().unwrap_or_else(|_| CONFIG.clone());
@ -238,7 +237,7 @@ impl SimpleComponent for FirstRunApp {
tracing::error!("Failed to sync components index"); tracing::error!("Failed to sync components index");
sender.input(FirstRunAppMsg::Toast { sender.input(FirstRunAppMsg::Toast {
title: tr("components-index-sync-failed"), title: tr!("components-index-sync-failed"),
description: Some(err.to_string()) description: Some(err.to_string())
}); });
} }
@ -250,7 +249,7 @@ impl SimpleComponent for FirstRunApp {
tracing::error!("Failed to verify that components index synced"); tracing::error!("Failed to verify that components index synced");
sender.input(FirstRunAppMsg::Toast { sender.input(FirstRunAppMsg::Toast {
title: tr("components-index-verify-failed"), title: tr!("components-index-verify-failed"),
description: Some(err.to_string()) description: Some(err.to_string())
}); });
} }
@ -265,13 +264,13 @@ impl SimpleComponent for FirstRunApp {
// Scroll to download components page // Scroll to download components page
// This will happen in background behind StatusPage // 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); self.carousel.scroll_to(self.download_components.widget(), true);
} }
FirstRunAppMsg::ScrollToFinish => { FirstRunAppMsg::ScrollToFinish => {
self.title = tr("finish"); self.title = tr!("finish");
self.carousel.scroll_to(self.finish.widget(), true); self.carousel.scroll_to(self.finish.widget(), true);
} }
@ -282,12 +281,12 @@ impl SimpleComponent for FirstRunApp {
toast.set_timeout(4); toast.set_timeout(4);
if let Some(description) = description { 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)); let dialog = adw::MessageDialog::new(MAIN_WINDOW.as_ref(), Some(&title), Some(&description));
dialog.add_response("close", &tr("close")); dialog.add_response("close", &tr!("close", { "form" = "noun" }));
dialog.add_response("save", &tr("save")); dialog.add_response("save", &tr!("save"));
dialog.set_response_appearance("save", adw::ResponseAppearance::Suggested); dialog.set_response_appearance("save", adw::ResponseAppearance::Suggested);

View file

@ -6,7 +6,7 @@ use adw::prelude::*;
use anime_launcher_sdk::config::ConfigExt; use anime_launcher_sdk::config::ConfigExt;
use anime_launcher_sdk::genshin::config::Config; use anime_launcher_sdk::genshin::config::Config;
use crate::i18n::*; use crate::*;
use super::main::*; use super::main::*;
@ -38,7 +38,7 @@ impl SimpleAsyncComponent for SelectVoiceoversApp {
set_vexpand: true, set_vexpand: true,
gtk::Label { gtk::Label {
set_label: &tr("select-voice-packages"), set_label: &tr!("select-voice-packages"),
add_css_class: "title-1" add_css_class: "title-1"
} }
}, },
@ -48,7 +48,7 @@ impl SimpleAsyncComponent for SelectVoiceoversApp {
set_vexpand: true, set_vexpand: true,
adw::ActionRow { adw::ActionRow {
set_title: &tr("english"), set_title: &tr!("english"),
#[local_ref] #[local_ref]
add_suffix = english -> gtk::Switch { add_suffix = english -> gtk::Switch {
@ -58,7 +58,7 @@ impl SimpleAsyncComponent for SelectVoiceoversApp {
}, },
adw::ActionRow { adw::ActionRow {
set_title: &tr("japanese"), set_title: &tr!("japanese"),
#[local_ref] #[local_ref]
add_suffix = japanese -> gtk::Switch { add_suffix = japanese -> gtk::Switch {
@ -67,7 +67,7 @@ impl SimpleAsyncComponent for SelectVoiceoversApp {
}, },
adw::ActionRow { adw::ActionRow {
set_title: &tr("korean"), set_title: &tr!("korean"),
#[local_ref] #[local_ref]
add_suffix = korean -> gtk::Switch { add_suffix = korean -> gtk::Switch {
@ -76,7 +76,7 @@ impl SimpleAsyncComponent for SelectVoiceoversApp {
}, },
adw::ActionRow { adw::ActionRow {
set_title: &tr("chinese"), set_title: &tr!("chinese"),
#[local_ref] #[local_ref]
add_suffix = chinese -> gtk::Switch { add_suffix = chinese -> gtk::Switch {
@ -95,14 +95,14 @@ impl SimpleAsyncComponent for SelectVoiceoversApp {
set_spacing: 8, set_spacing: 8,
gtk::Button { gtk::Button {
set_label: &tr("continue"), set_label: &tr!("continue"),
set_css_classes: &["suggested-action", "pill"], set_css_classes: &["suggested-action", "pill"],
connect_clicked => SelectVoiceoversAppMsg::Continue connect_clicked => SelectVoiceoversAppMsg::Continue
}, },
gtk::Button { gtk::Button {
set_label: &tr("exit"), set_label: &tr!("exit"),
add_css_class: "pill", add_css_class: "pill",
connect_clicked => SelectVoiceoversAppMsg::Exit connect_clicked => SelectVoiceoversAppMsg::Exit
@ -142,7 +142,7 @@ impl SimpleAsyncComponent for SelectVoiceoversApp {
Ok(_) => sender.output(Self::Output::ScrollToDownloadComponents), Ok(_) => sender.output(Self::Output::ScrollToDownloadComponents),
Err(err) => sender.output(Self::Output::Toast { Err(err) => sender.output(Self::Output::Toast {
title: tr("config-update-error"), title: tr!("config-update-error"),
description: Some(err.to_string()) description: Some(err.to_string())
}) })
}; };

View file

@ -5,7 +5,7 @@ use adw::prelude::*;
use anime_launcher_sdk::is_available; use anime_launcher_sdk::is_available;
use crate::i18n::*; use crate::*;
use super::main::FirstRunAppMsg; use super::main::FirstRunAppMsg;
@ -34,14 +34,14 @@ impl SimpleAsyncComponent for TosWarningApp {
set_vexpand: true, set_vexpand: true,
gtk::Label { gtk::Label {
set_label: &tr("tos-violation-warning"), set_label: &tr!("tos-violation-warning"),
add_css_class: "title-1" add_css_class: "title-1"
} }
}, },
add = &adw::PreferencesGroup { add = &adw::PreferencesGroup {
gtk::Label { gtk::Label {
set_label: &tr("tos-violation-warning-message"), set_label: &tr!("tos-violation-warning-message"),
set_wrap: true, set_wrap: true,
set_selectable: true set_selectable: true
} }
@ -57,14 +57,14 @@ impl SimpleAsyncComponent for TosWarningApp {
set_spacing: 8, set_spacing: 8,
gtk::Button { gtk::Button {
set_label: &tr("continue"), set_label: &tr!("continue"),
set_css_classes: &["suggested-action", "pill"], set_css_classes: &["suggested-action", "pill"],
connect_clicked => TosWarningAppMsg::Continue connect_clicked => TosWarningAppMsg::Continue
}, },
gtk::Button { gtk::Button {
set_label: &tr("exit"), set_label: &tr!("exit"),
add_css_class: "pill", add_css_class: "pill",
connect_clicked => TosWarningAppMsg::Exit connect_clicked => TosWarningAppMsg::Exit
@ -91,13 +91,13 @@ impl SimpleAsyncComponent for TosWarningApp {
TosWarningAppMsg::Continue => { TosWarningAppMsg::Continue => {
let dialog = adw::MessageDialog::new( let dialog = adw::MessageDialog::new(
unsafe { MAIN_WINDOW.as_ref() }, unsafe { MAIN_WINDOW.as_ref() },
Some(&tr("tos-dialog-title")), Some(&tr!("tos-dialog-title")),
Some(&tr("tos-dialog-message")) Some(&tr!("tos-dialog-message"))
); );
dialog.add_responses(&[ dialog.add_responses(&[
("exit", &tr("exit")), ("exit", &tr!("exit")),
("continue", &tr("agree")) ("continue", &tr!("agree"))
]); ]);
dialog.connect_response(None, move |_, response| { dialog.connect_response(None, move |_, response| {

View file

@ -3,7 +3,7 @@ use relm4::component::*;
use adw::prelude::*; use adw::prelude::*;
use crate::i18n::*; use crate::*;
use super::main::FirstRunAppMsg; use super::main::FirstRunAppMsg;
@ -29,7 +29,7 @@ impl SimpleAsyncComponent for WelcomeApp {
set_vexpand: true, set_vexpand: true,
gtk::Image { gtk::Image {
set_resource: Some("/org/app/images/icon.png"), set_icon_name: Some(APP_ID),
set_height_request: 128 set_height_request: 128
}, },
@ -40,7 +40,7 @@ impl SimpleAsyncComponent for WelcomeApp {
}, },
gtk::Label { gtk::Label {
set_label: &tr("welcome-page-message"), set_label: &tr!("welcome-page-message"),
set_justify: gtk::Justification::Center, set_justify: gtk::Justification::Center,
set_wrap: true, set_wrap: true,
@ -58,7 +58,7 @@ impl SimpleAsyncComponent for WelcomeApp {
set_spacing: 8, set_spacing: 8,
gtk::Button { gtk::Button {
set_label: &tr("continue"), set_label: &tr!("continue"),
set_css_classes: &["suggested-action", "pill"], set_css_classes: &["suggested-action", "pill"],
connect_clicked => WelcomeAppMsg::Continue connect_clicked => WelcomeAppMsg::Continue

View file

@ -1,7 +1,6 @@
use relm4::prelude::*; use relm4::prelude::*;
use crate::*; use crate::*;
use crate::i18n::*;
use super::{App, AppMsg}; use super::{App, AppMsg};
@ -22,7 +21,7 @@ pub fn apply_patch(sender: ComponentSender<App>, patch: PlayerPatch, rename_mhyp
tracing::error!("Failed to patch the game"); tracing::error!("Failed to patch the game");
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
title: tr("game-patching-error"), title: tr!("game-patching-error"),
description: Some(err.to_string()) description: Some(err.to_string())
}); });
} }
@ -38,7 +37,7 @@ pub fn apply_patch(sender: ComponentSender<App>, patch: PlayerPatch, rename_mhyp
tracing::error!("Failed to rename mhypbase file"); tracing::error!("Failed to rename mhypbase file");
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
title: tr("game-patching-error"), title: tr!("game-patching-error"),
description: Some(err.to_string()) description: Some(err.to_string())
}); });
} }

View file

@ -5,7 +5,7 @@ use anime_launcher_sdk::wincompatlib::prelude::*;
use anime_launcher_sdk::config::ConfigExt; use anime_launcher_sdk::config::ConfigExt;
use anime_launcher_sdk::genshin::config::Config; use anime_launcher_sdk::genshin::config::Config;
use crate::i18n::*; use crate::*;
use super::{App, AppMsg}; use super::{App, AppMsg};
@ -27,7 +27,7 @@ pub fn create_prefix(sender: ComponentSender<App>) {
tracing::error!("Failed to create wine prefix"); tracing::error!("Failed to create wine prefix");
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
title: tr("wine-prefix-update-failed"), title: tr!("wine-prefix-update-failed"),
description: Some(err.to_string()) description: Some(err.to_string())
}); });
} }
@ -44,7 +44,7 @@ pub fn create_prefix(sender: ComponentSender<App>) {
tracing::error!("Failed to get selected wine executable"); tracing::error!("Failed to get selected wine executable");
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
title: tr("failed-get-selected-wine"), title: tr!("failed-get-selected-wine"),
description: None description: None
}); });
} }
@ -53,7 +53,7 @@ pub fn create_prefix(sender: ComponentSender<App>) {
tracing::error!("Failed to get selected wine executable: {err}"); tracing::error!("Failed to get selected wine executable: {err}");
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
title: tr("failed-get-selected-wine"), title: tr!("failed-get-selected-wine"),
description: Some(err.to_string()) description: Some(err.to_string())
}); });
} }

View file

@ -3,7 +3,6 @@ use std::process::Command;
use relm4::prelude::*; use relm4::prelude::*;
use crate::*; use crate::*;
use crate::i18n::*;
use super::{App, AppMsg}; use super::{App, AppMsg};
@ -40,7 +39,7 @@ pub fn disable_telemetry(sender: ComponentSender<App>) {
tracing::error!("Failed to update /etc/hosts file"); tracing::error!("Failed to update /etc/hosts file");
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
title: tr("telemetry-servers-disabling-error"), title: tr!("telemetry-servers-disabling-error"),
description: None // stdout/err is empty description: None // stdout/err is empty
}); });
} }
@ -49,7 +48,7 @@ pub fn disable_telemetry(sender: ComponentSender<App>) {
tracing::error!("Failed to update /etc/hosts file"); tracing::error!("Failed to update /etc/hosts file");
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
title: tr("telemetry-servers-disabling-error"), title: tr!("telemetry-servers-disabling-error"),
description: Some(err.to_string()) description: Some(err.to_string())
}); });
} }

View file

@ -6,7 +6,6 @@ use relm4::{
use gtk::glib::clone; use gtk::glib::clone;
use crate::*; use crate::*;
use crate::i18n::*;
use crate::ui::components::*; use crate::ui::components::*;
use super::{App, AppMsg}; use super::{App, AppMsg};
@ -28,7 +27,7 @@ pub fn download_diff(sender: ComponentSender<App>, progress_bar_input: Sender<Pr
tracing::error!("Downloading failed: {err}"); tracing::error!("Downloading failed: {err}");
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
title: tr("downloading-failed"), title: tr!("downloading-failed"),
description: Some(err.to_string()) description: Some(err.to_string())
}); });
} }
@ -37,7 +36,7 @@ pub fn download_diff(sender: ComponentSender<App>, progress_bar_input: Sender<Pr
tracing::error!("Unpacking failed: {err}"); tracing::error!("Unpacking failed: {err}");
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
title: tr("unpacking-failed"), title: tr!("unpacking-failed"),
description: Some(err.clone()) description: Some(err.clone())
}); });
} }
@ -56,7 +55,7 @@ pub fn download_diff(sender: ComponentSender<App>, progress_bar_input: Sender<Pr
tracing::error!("Downloading failed: {err}"); tracing::error!("Downloading failed: {err}");
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
title: tr("downloading-failed"), title: tr!("downloading-failed"),
description: Some(err.to_string()) description: Some(err.to_string())
}); });

View file

@ -8,7 +8,6 @@ use gtk::glib::clone;
use anime_launcher_sdk::components::wine; use anime_launcher_sdk::components::wine;
use crate::*; use crate::*;
use crate::i18n::*;
use crate::ui::components::*; use crate::ui::components::*;
use super::{App, AppMsg}; use super::{App, AppMsg};
@ -60,7 +59,7 @@ pub fn download_wine(sender: ComponentSender<App>, progress_bar_input: Sender<Pr
tracing::error!("Downloading failed: {err}"); tracing::error!("Downloading failed: {err}");
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
title: tr("downloading-failed"), title: tr!("downloading-failed"),
description: Some(err.to_string()) description: Some(err.to_string())
}); });
} }
@ -69,7 +68,7 @@ pub fn download_wine(sender: ComponentSender<App>, progress_bar_input: Sender<Pr
tracing::error!("Unpacking failed: {err}"); tracing::error!("Unpacking failed: {err}");
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
title: tr("unpacking-failed"), title: tr!("unpacking-failed"),
description: Some(err.clone()) description: Some(err.clone())
}); });
} }
@ -95,7 +94,7 @@ pub fn download_wine(sender: ComponentSender<App>, progress_bar_input: Sender<Pr
} }
Err(err) => sender.input(AppMsg::Toast { Err(err) => sender.input(AppMsg::Toast {
title: tr("wine-install-failed"), title: tr!("wine-install-failed"),
description: Some(err.to_string()) description: Some(err.to_string())
}) })
} }
@ -103,7 +102,7 @@ pub fn download_wine(sender: ComponentSender<App>, progress_bar_input: Sender<Pr
} }
Err(err) => sender.input(AppMsg::Toast { Err(err) => sender.input(AppMsg::Toast {
title: tr("downloaded-wine-list-failed"), title: tr!("downloaded-wine-list-failed"),
description: Some(err.to_string()) description: Some(err.to_string())
}) })
} }

View file

@ -1,22 +1,51 @@
use relm4::prelude::*; use relm4::prelude::*;
use gtk::prelude::*;
use crate::i18n::*; use anime_launcher_sdk::genshin::config::schema::prelude::LauncherBehavior;
use crate::*;
use super::{App, AppMsg}; use super::{App, AppMsg};
pub fn launch(sender: ComponentSender<App>) { pub fn launch(sender: ComponentSender<App>) {
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 || { std::thread::spawn(move || {
if let Err(err) = anime_launcher_sdk::genshin::game::run() { if let Err(err) = anime_launcher_sdk::genshin::game::run() {
tracing::error!("Failed to launch game: {err}"); tracing::error!("Failed to launch game: {err}");
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
title: tr("game-launching-failed"), title: tr!("game-launching-failed"),
description: Some(err.to_string()) 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();
})
}
}); });
} }

View file

@ -30,7 +30,6 @@ use anime_launcher_sdk::genshin::states::*;
use anime_launcher_sdk::genshin::consts::*; use anime_launcher_sdk::genshin::consts::*;
use crate::*; use crate::*;
use crate::i18n::*;
use crate::ui::components::*; use crate::ui::components::*;
use super::preferences::main::*; use super::preferences::main::*;
@ -60,7 +59,9 @@ pub struct App {
state: Option<LauncherState>, state: Option<LauncherState>,
downloading: bool, downloading: bool,
disabled_buttons: bool disabled_buttons: bool,
kill_game_button: bool,
disabled_kill_game_button: bool
} }
#[derive(Debug)] #[derive(Debug)]
@ -90,6 +91,8 @@ pub enum AppMsg {
SetDownloading(bool), SetDownloading(bool),
DisableButtons(bool), DisableButtons(bool),
SetKillGameButton(bool),
DisableKillGameButton(bool),
OpenPreferences, OpenPreferences,
RepairGame, RepairGame,
@ -115,18 +118,18 @@ impl SimpleComponent for App {
menu! { menu! {
main_menu: { main_menu: {
section! { section! {
&tr("launcher-folder") => LauncherFolder, &tr!("launcher-folder") => LauncherFolder,
&tr("game-folder") => GameFolder, &tr!("game-folder") => GameFolder,
&tr("config-file") => ConfigFile, &tr!("config-file") => ConfigFile,
&tr("debug-file") => DebugFile, &tr!("debug-file") => DebugFile,
}, },
section! { section! {
&tr("wish-url") => WishUrl &tr!("wish-url") => WishUrl
}, },
section! { section! {
&tr("about") => About &tr!("about") => About
} }
} }
} }
@ -195,7 +198,7 @@ impl SimpleComponent for App {
}, },
adw::StatusPage { adw::StatusPage {
set_title: &tr("loading-data"), set_title: &tr!("loading-data"),
set_icon_name: Some(APP_ID), set_icon_name: Some(APP_ID),
set_vexpand: true, set_vexpand: true,
@ -220,7 +223,7 @@ impl SimpleComponent for App {
set_visible: model.style == LauncherStyle::Modern, set_visible: model.style == LauncherStyle::Modern,
gtk::Picture { 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_vexpand: true,
set_content_fit: gtk::ContentFit::ScaleDown set_content_fit: gtk::ContentFit::ScaleDown
}, },
@ -302,13 +305,13 @@ impl SimpleComponent for App {
set_width_request: 44, set_width_request: 44,
#[watch] #[watch]
set_tooltip_text: Some(&tr_args("predownload-update", [ set_tooltip_text: Some(&tr!("predownload-update", {
("version", match model.state.as_ref() { "version" = match model.state.as_ref() {
Some(LauncherState::PredownloadAvailable { game, .. }) => game.latest().to_string(), Some(LauncherState::PredownloadAvailable { game, .. }) => game.latest().to_string(),
_ => String::from("?") _ => String::from("?")
}.into()), },
("size", match model.state.as_ref() { "size" = match model.state.as_ref() {
Some(LauncherState::PredownloadAvailable { game, voices }) => { Some(LauncherState::PredownloadAvailable { game, voices }) => {
let mut size = game.downloaded_size().unwrap_or(0); let mut size = game.downloaded_size().unwrap_or(0);
@ -320,8 +323,8 @@ impl SimpleComponent for App {
} }
_ => String::from("?") _ => String::from("?")
}.into()) }
])), })),
#[watch] #[watch]
set_visible: matches!(model.state.as_ref(), Some(LauncherState::PredownloadAvailable { .. })), set_visible: matches!(model.state.as_ref(), Some(LauncherState::PredownloadAvailable { .. })),
@ -332,8 +335,21 @@ impl SimpleComponent for App {
let config = Config::get().unwrap(); let config = Config::get().unwrap();
let temp = config.launcher.temp.unwrap_or_else(std::env::temp_dir); let temp = config.launcher.temp.unwrap_or_else(std::env::temp_dir);
let downloaded = temp.join(game.file_name().unwrap()).exists() && let mut downloaded = temp.join(game.file_name().unwrap()).metadata()
voices.iter().all(|voice| temp.join(voice.file_name().unwrap()).exists()); .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 !downloaded
} }
@ -347,8 +363,21 @@ impl SimpleComponent for App {
let config = Config::get().unwrap(); let config = Config::get().unwrap();
let temp = config.launcher.temp.unwrap_or_else(std::env::temp_dir); let temp = config.launcher.temp.unwrap_or_else(std::env::temp_dir);
let downloaded = temp.join(game.file_name().unwrap()).exists() && let mut downloaded = temp.join(game.file_name().unwrap()).metadata()
voices.iter().all(|voice| temp.join(voice.file_name().unwrap()).exists()); .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 { if downloaded {
&["success", "circular"] &["success", "circular"]
@ -370,6 +399,9 @@ impl SimpleComponent for App {
adw::Bin { adw::Bin {
set_css_classes: &["background", "round-bin"], set_css_classes: &["background", "round-bin"],
#[watch]
set_visible: !model.kill_game_button,
gtk::Button { gtk::Button {
adw::ButtonContent { adw::ButtonContent {
#[watch] #[watch]
@ -405,15 +437,15 @@ impl SimpleComponent for App {
#[watch] #[watch]
set_label: &match &model.state { set_label: &match &model.state {
Some(LauncherState::Launch) | Some(LauncherState::Launch) |
Some(LauncherState::PredownloadAvailable { .. }) => tr("launch"), Some(LauncherState::PredownloadAvailable { .. }) => tr!("launch"),
Some(LauncherState::FolderMigrationRequired { .. }) => tr("migrate-folders"), Some(LauncherState::FolderMigrationRequired { .. }) => tr!("migrate-folders"),
Some(LauncherState::PlayerPatchAvailable { .. }) => tr("apply-patch"), 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::WineNotInstalled) => tr!("download-wine"),
Some(LauncherState::PrefixNotExists) => tr("create-prefix"), Some(LauncherState::PrefixNotExists) => tr!("create-prefix"),
Some(LauncherState::GameUpdateAvailable(diff)) | Some(LauncherState::GameUpdateAvailable(diff)) |
Some(LauncherState::GameOutdated(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); let temp = config.launcher.temp.unwrap_or_else(std::env::temp_dir);
if temp.join(filename).exists() { if temp.join(filename).exists() {
tr("resume") tr!("resume")
} }
else { else {
tr("update") tr!("update")
} }
} }
_ => tr("update") _ => tr!("update")
} }
}, },
Some(LauncherState::GameNotInstalled(_)) | Some(LauncherState::GameNotInstalled(_)) |
Some(LauncherState::VoiceNotInstalled(_)) => tr("download"), Some(LauncherState::VoiceNotInstalled(_)) => tr!("download"),
None => String::from("...") None => String::from("...")
} }
@ -484,15 +516,15 @@ impl SimpleComponent for App {
#[watch] #[watch]
set_tooltip_text: Some(&match &model.state { set_tooltip_text: Some(&match &model.state {
Some(LauncherState::GameOutdated { .. }) | 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 { 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::Outdated { .. } |
PatchStatus::Preparation { .. } => tr("main-window--patch-outdated-tooltip"), PatchStatus::Preparation { .. } => tr!("main-window--patch-outdated-tooltip"),
_ => String::new() _ => 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 { adw::Bin {
set_css_classes: &["background", "round-bin"], set_css_classes: &["background", "round-bin"],
@ -531,7 +654,7 @@ impl SimpleComponent for App {
connect_close_request[sender] => move |_| { connect_close_request[sender] => move |_| {
if let Err(err) = Config::flush() { if let Err(err) = Config::flush() {
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
title: tr("config-update-error"), title: tr!("config-update-error"),
description: Some(err.to_string()) description: Some(err.to_string())
}); });
} }
@ -565,7 +688,9 @@ impl SimpleComponent for App {
state: None, state: None,
downloading: false, 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); model.progress_bar.widget().set_halign(gtk::Align::Center);
@ -597,7 +722,7 @@ impl SimpleComponent for App {
group.add_action::<LauncherFolder>(RelmAction::new_stateless(clone!(@strong sender => move |_| { group.add_action::<LauncherFolder>(RelmAction::new_stateless(clone!(@strong sender => move |_| {
if let Err(err) = open::that(LAUNCHER_FOLDER.as_path()) { if let Err(err) = open::that(LAUNCHER_FOLDER.as_path()) {
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
title: tr("launcher-folder-opening-error"), title: tr!("launcher-folder-opening-error"),
description: Some(err.to_string()) description: Some(err.to_string())
}); });
@ -613,7 +738,7 @@ impl SimpleComponent for App {
if let Err(err) = open::that(path) { if let Err(err) = open::that(path) {
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
title: tr("game-folder-opening-error"), title: tr!("game-folder-opening-error"),
description: Some(err.to_string()) description: Some(err.to_string())
}); });
@ -625,7 +750,7 @@ impl SimpleComponent for App {
if let Ok(file) = config_file() { if let Ok(file) = config_file() {
if let Err(err) = open::that(file) { if let Err(err) = open::that(file) {
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
title: tr("config-file-opening-error"), title: tr!("config-file-opening-error"),
description: Some(err.to_string()) description: Some(err.to_string())
}); });
@ -637,7 +762,7 @@ impl SimpleComponent for App {
group.add_action::<DebugFile>(RelmAction::new_stateless(clone!(@strong sender => move |_| { group.add_action::<DebugFile>(RelmAction::new_stateless(clone!(@strong sender => move |_| {
if let Err(err) = open::that(crate::DEBUG_FILE.as_os_str()) { if let Err(err) = open::that(crate::DEBUG_FILE.as_os_str()) {
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
title: tr("debug-file-opening-error"), title: tr!("debug-file-opening-error"),
description: Some(err.to_string()) description: Some(err.to_string())
}); });
@ -685,7 +810,7 @@ impl SimpleComponent for App {
tracing::error!("Failed to open wishes URL: {err}"); tracing::error!("Failed to open wishes URL: {err}");
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
title: tr("wish-url-opening-error"), title: tr!("wish-url-opening-error"),
description: Some(err.to_string()) description: Some(err.to_string())
}); });
} }
@ -695,7 +820,7 @@ impl SimpleComponent for App {
tracing::error!("Couldn't find wishes URL: no url found"); tracing::error!("Couldn't find wishes URL: no url found");
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
title: tr("wish-url-search-failed"), title: tr!("wish-url-search-failed"),
description: None description: None
}); });
} }
@ -705,7 +830,7 @@ impl SimpleComponent for App {
tracing::error!("Couldn't find wishes URL: failed to open cache file: {err}"); tracing::error!("Couldn't find wishes URL: failed to open cache file: {err}");
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
title: tr("wish-url-search-failed"), title: tr!("wish-url-search-failed"),
description: Some(err.to_string()) 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"); tracing::error!("Couldn't find wishes URL: cache file doesn't exist");
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
title: tr("wish-url-search-failed"), title: tr!("wish-url-search-failed"),
description: None description: None
}); });
} }
@ -747,7 +872,7 @@ impl SimpleComponent for App {
tracing::error!("Failed to download background picture: {err}"); tracing::error!("Failed to download background picture: {err}");
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
title: tr("background-downloading-failed"), title: tr!("background-downloading-failed"),
description: Some(err.to_string()) description: Some(err.to_string())
}); });
} }
@ -767,7 +892,7 @@ impl SimpleComponent for App {
match components.sync(host) { match components.sync(host) {
Ok(changes) => { Ok(changes) => {
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
title: tr("components-index-updated"), title: tr!("components-index-updated"),
description: if changes.is_empty() { description: if changes.is_empty() {
None None
} else { } else {
@ -785,7 +910,7 @@ impl SimpleComponent for App {
tracing::error!("Failed to sync components index"); tracing::error!("Failed to sync components index");
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
title: tr("components-index-sync-failed"), title: tr!("components-index-sync-failed"),
description: Some(err.to_string()) description: Some(err.to_string())
}); });
} }
@ -797,7 +922,7 @@ impl SimpleComponent for App {
tracing::error!("Failed to verify that components index synced"); tracing::error!("Failed to verify that components index synced");
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
title: tr("components-index-verify-failed"), title: tr!("components-index-verify-failed"),
description: Some(err.to_string()) description: Some(err.to_string())
}); });
} }
@ -822,7 +947,7 @@ impl SimpleComponent for App {
tracing::error!("Failed to sync patch folder with remote: {server}: {err}"); tracing::error!("Failed to sync patch folder with remote: {server}: {err}");
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
title: tr("patch-sync-failed"), title: tr!("patch-sync-failed"),
description: Some(err.to_string()) description: Some(err.to_string())
}); });
} }
@ -834,7 +959,7 @@ impl SimpleComponent for App {
tracing::error!("Failed to compare local patch folder with remote: {err}"); tracing::error!("Failed to compare local patch folder with remote: {err}");
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
title: tr("patch-state-check-failed"), title: tr!("patch-state-check-failed"),
description: Some(err.to_string()) description: Some(err.to_string())
}); });
} }
@ -848,7 +973,7 @@ impl SimpleComponent for App {
tracing::error!("Failed to fetch player patch info: {err}"); tracing::error!("Failed to fetch player patch info: {err}");
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
title: tr("patch-info-fetching-error"), title: tr!("patch-info-fetching-error"),
description: Some(err.to_string()) description: Some(err.to_string())
}); });
@ -868,7 +993,7 @@ impl SimpleComponent for App {
tracing::error!("Failed to find game diff: {err}"); tracing::error!("Failed to find game diff: {err}");
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
title: tr("game-diff-finding-error"), title: tr!("game-diff-finding-error"),
description: Some(err.to_string()) description: Some(err.to_string())
}); });
@ -906,7 +1031,7 @@ impl SimpleComponent for App {
// TODO: make function from this message like with toast // TODO: make function from this message like with toast
AppMsg::UpdateLauncherState { perform_on_download_needed, show_status_page } => { AppMsg::UpdateLauncherState { perform_on_download_needed, show_status_page } => {
if 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 { } else {
self.disabled_buttons = true; self.disabled_buttons = true;
} }
@ -915,17 +1040,17 @@ impl SimpleComponent for App {
if show_status_page { if show_status_page {
match state { match state {
StateUpdating::Game => { 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) => { StateUpdating::Voice(locale) => {
sender.input(AppMsg::SetLoadingStatus(Some(Some(tr_args("loading-launcher-state--voice", [ sender.input(AppMsg::SetLoadingStatus(Some(Some(tr!("loading-launcher-state--voice", {
("locale", locale.to_name().to_owned().into()) "locale" = locale.to_name()
]))))); })))));
} }
StateUpdating::Patch => { 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) => { Err(err) => {
tracing::error!("Failed to update launcher state: {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 None
} }
@ -994,6 +1119,14 @@ impl SimpleComponent for App {
self.disabled_buttons = state; self.disabled_buttons = state;
} }
AppMsg::SetKillGameButton(state) => {
self.kill_game_button = state;
}
AppMsg::DisableKillGameButton(state) => {
self.disabled_kill_game_button = state;
}
AppMsg::OpenPreferences => unsafe { AppMsg::OpenPreferences => unsafe {
PREFERENCES_WINDOW.as_ref().unwrap_unchecked().widget().present(); 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(); 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<VersionDiff> = vec![game]; let mut diffs: Vec<VersionDiff> = vec![game];
@ -1023,7 +1156,7 @@ impl SimpleComponent for App {
if let Err(err) = result { if let Err(err) = result {
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
title: tr("downloading-failed"), title: tr!("downloading-failed"),
description: Some(err.to_string()) description: Some(err.to_string())
}); });
@ -1090,7 +1223,7 @@ impl App {
toast.set_timeout(4); toast.set_timeout(4);
if let Some(description) = description { if let Some(description) = description {
toast.set_button_label(Some(&tr("details"))); toast.set_button_label(Some(&tr!("details")));
let dialog = adw::MessageDialog::new( let dialog = adw::MessageDialog::new(
Some(unsafe { MAIN_WINDOW.as_ref().unwrap_unchecked() }), Some(unsafe { MAIN_WINDOW.as_ref().unwrap_unchecked() }),
@ -1098,8 +1231,8 @@ impl App {
Some(description.as_ref()) Some(description.as_ref())
); );
dialog.add_response("close", &tr("close")); dialog.add_response("close", &tr!("close", { "form" = "noun" }));
dialog.add_response("save", &tr("save")); dialog.add_response("save", &tr!("save"));
dialog.set_response_appearance("save", adw::ResponseAppearance::Suggested); dialog.set_response_appearance("save", adw::ResponseAppearance::Suggested);

View file

@ -8,7 +8,6 @@ use relm4::{
use gtk::glib::clone; use gtk::glib::clone;
use crate::*; use crate::*;
use crate::i18n::*;
use crate::ui::components::*; use crate::ui::components::*;
use super::{App, AppMsg}; use super::{App, AppMsg};
@ -17,7 +16,7 @@ use super::{App, AppMsg};
pub fn repair_game(sender: ComponentSender<App>, progress_bar_input: Sender<ProgressBarMsg>) { pub fn repair_game(sender: ComponentSender<App>, progress_bar_input: Sender<ProgressBarMsg>) {
let config = Config::get().unwrap(); 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)); sender.input(AppMsg::SetDownloading(true));
std::thread::spawn(move || { std::thread::spawn(move || {
@ -100,7 +99,7 @@ pub fn repair_game(sender: ComponentSender<App>, progress_bar_input: Sender<Prog
if !broken.is_empty() { if !broken.is_empty() {
let total = broken.len() as u64; let total = broken.len() as u64;
progress_bar_input.send(ProgressBarMsg::UpdateCaption(Some(tr("repairing-files")))); progress_bar_input.send(ProgressBarMsg::UpdateCaption(Some(tr!("repairing-files"))));
progress_bar_input.send(ProgressBarMsg::DisplayFraction(false)); progress_bar_input.send(ProgressBarMsg::DisplayFraction(false));
progress_bar_input.send(ProgressBarMsg::UpdateProgress(0, total)); progress_bar_input.send(ProgressBarMsg::UpdateProgress(0, total));
@ -149,7 +148,7 @@ pub fn repair_game(sender: ComponentSender<App>, progress_bar_input: Sender<Prog
if let Err(err) = file.repair(&game_path) { if let Err(err) = file.repair(&game_path) {
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
title: tr("game-file-repairing-error"), title: tr!("game-file-repairing-error"),
description: Some(err.to_string()) description: Some(err.to_string())
}); });
@ -172,7 +171,7 @@ pub fn repair_game(sender: ComponentSender<App>, progress_bar_input: Sender<Prog
tracing::error!("Failed to get inregrity failes: {err}"); tracing::error!("Failed to get inregrity failes: {err}");
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
title: tr("integrity-files-getting-error"), title: tr!("integrity-files-getting-error"),
description: Some(err.to_string()) description: Some(err.to_string())
}); });
} }

View file

@ -3,7 +3,8 @@ use relm4::component::*;
use gtk::prelude::*; use gtk::prelude::*;
use crate::i18n::*; use crate::tr;
use super::first_run::default_paths::DefaultPathsApp; use super::first_run::default_paths::DefaultPathsApp;
pub struct MigrateInstallationApp { pub struct MigrateInstallationApp {
@ -23,7 +24,7 @@ impl SimpleComponent for MigrateInstallationApp {
set_hide_on_close: true, set_hide_on_close: true,
#[watch] #[watch]
set_title: Some(&tr("migrate-installation")), set_title: Some(&tr!("migrate-installation")),
gtk::Box { gtk::Box {
set_orientation: gtk::Orientation::Vertical, set_orientation: gtk::Orientation::Vertical,

View file

@ -4,11 +4,10 @@ use relm4::factory::*;
use adw::prelude::*; use adw::prelude::*;
use super::EnhancementsAppMsg;
use crate::i18n::tr;
use crate::*; use crate::*;
use super::EnhancementsAppMsg;
#[derive(Debug)] #[derive(Debug)]
struct Variable { struct Variable {
key: String, key: String,
@ -83,7 +82,7 @@ impl SimpleAsyncComponent for EnvironmentPage {
adw::HeaderBar { adw::HeaderBar {
#[wrap(Some)] #[wrap(Some)]
set_title_widget = &adw::WindowTitle { set_title_widget = &adw::WindowTitle {
set_title: &tr("environment") set_title: &tr!("environment")
}, },
pack_start = &gtk::Button { pack_start = &gtk::Button {
@ -96,12 +95,12 @@ impl SimpleAsyncComponent for EnvironmentPage {
}, },
adw::PreferencesPage { adw::PreferencesPage {
set_title: &tr("environment"), set_title: &tr!("environment"),
set_icon_name: Some("document-properties-symbolic"), set_icon_name: Some("document-properties-symbolic"),
add = &adw::PreferencesGroup { add = &adw::PreferencesGroup {
set_title: &tr("game-command"), set_title: &tr!("game-command"),
set_description: Some(&tr("game-command-description")), set_description: Some(&tr!("game-command-description")),
adw::EntryRow { adw::EntryRow {
set_title: "%command%", set_title: "%command%",
@ -124,7 +123,7 @@ impl SimpleAsyncComponent for EnvironmentPage {
}, },
add = &adw::PreferencesGroup { add = &adw::PreferencesGroup {
set_title: &tr("new-variable"), set_title: &tr!("new-variable"),
#[wrap(Some)] #[wrap(Some)]
set_header_suffix = &gtk::Button { set_header_suffix = &gtk::Button {
@ -134,7 +133,7 @@ impl SimpleAsyncComponent for EnvironmentPage {
adw::ButtonContent { adw::ButtonContent {
set_icon_name: "list-add-symbolic", set_icon_name: "list-add-symbolic",
set_label: &tr("add") set_label: &tr!("add")
}, },
connect_clicked => EnvironmentPageMsg::Add connect_clicked => EnvironmentPageMsg::Add
@ -142,12 +141,12 @@ impl SimpleAsyncComponent for EnvironmentPage {
#[local_ref] #[local_ref]
name_entry -> adw::EntryRow { name_entry -> adw::EntryRow {
set_title: &tr("name") set_title: &tr!("name")
}, },
#[local_ref] #[local_ref]
value_entry -> adw::EntryRow { value_entry -> adw::EntryRow {
set_title: &tr("value") set_title: &tr!("value")
} }
}, },

View file

@ -7,11 +7,10 @@ use adw::prelude::*;
use anime_launcher_sdk::sessions::SessionsExt; use anime_launcher_sdk::sessions::SessionsExt;
use anime_launcher_sdk::genshin::sessions::Sessions; use anime_launcher_sdk::genshin::sessions::Sessions;
use super::EnhancementsAppMsg;
use crate::i18n::tr;
use crate::*; use crate::*;
use super::EnhancementsAppMsg;
#[derive(Debug)] #[derive(Debug)]
struct GameSession { struct GameSession {
name: String, name: String,
@ -44,7 +43,7 @@ impl AsyncFactoryComponent for GameSession {
set_icon_name: "view-refresh-symbolic", set_icon_name: "view-refresh-symbolic",
add_css_class: "flat", add_css_class: "flat",
set_tooltip_text: Some(&tr("update-session")), set_tooltip_text: Some(&tr!("update-session")),
set_valign: gtk::Align::Center, set_valign: gtk::Align::Center,
@ -57,7 +56,7 @@ impl AsyncFactoryComponent for GameSession {
set_icon_name: "user-trash-symbolic", set_icon_name: "user-trash-symbolic",
add_css_class: "flat", add_css_class: "flat",
set_tooltip_text: Some(&tr("delete-session")), set_tooltip_text: Some(&tr!("delete-session")),
set_valign: gtk::Align::Center, set_valign: gtk::Align::Center,
@ -115,7 +114,7 @@ impl SimpleAsyncComponent for GamePage {
adw::HeaderBar { adw::HeaderBar {
#[wrap(Some)] #[wrap(Some)]
set_title_widget = &adw::WindowTitle { set_title_widget = &adw::WindowTitle {
set_title: &tr("game") set_title: &tr!("game")
}, },
pack_start = &gtk::Button { pack_start = &gtk::Button {
@ -128,15 +127,15 @@ impl SimpleAsyncComponent for GamePage {
}, },
adw::PreferencesPage { adw::PreferencesPage {
set_title: &tr("game"), set_title: &tr!("game"),
set_icon_name: Some("applications-games-symbolic"), set_icon_name: Some("applications-games-symbolic"),
add = &adw::PreferencesGroup { add = &adw::PreferencesGroup {
set_title: &tr("game-sessions"), set_title: &tr!("game-sessions"),
#[local_ref] #[local_ref]
session_name_entry -> adw::EntryRow { session_name_entry -> adw::EntryRow {
set_title: &tr("name"), set_title: &tr!("name"),
add_suffix = &gtk::Button { add_suffix = &gtk::Button {
set_icon_name: "list-add-symbolic", set_icon_name: "list-add-symbolic",
@ -220,7 +219,7 @@ impl SimpleAsyncComponent for GamePage {
Err(err) => { Err(err) => {
sender.output(EnhancementsAppMsg::Toast { sender.output(EnhancementsAppMsg::Toast {
title: tr("game-session-add-failed"), title: tr!("game-session-add-failed"),
description: Some(err.to_string()) description: Some(err.to_string())
}).unwrap(); }).unwrap();
} }
@ -234,7 +233,7 @@ impl SimpleAsyncComponent for GamePage {
if let Ok(config) = Config::get() { if let Ok(config) = Config::get() {
if let Err(err) = Sessions::update(session.name.clone(), config.get_wine_prefix_path()) { if let Err(err) = Sessions::update(session.name.clone(), config.get_wine_prefix_path()) {
sender.output(EnhancementsAppMsg::Toast { sender.output(EnhancementsAppMsg::Toast {
title: tr("game-session-update-failed"), title: tr!("game-session-update-failed"),
description: Some(err.to_string()) description: Some(err.to_string())
}).unwrap(); }).unwrap();
} }
@ -246,7 +245,7 @@ impl SimpleAsyncComponent for GamePage {
if let Some(session) = self.sessions.guard().get(index) { if let Some(session) = self.sessions.guard().get(index) {
if let Err(err) = Sessions::remove(&session.name) { if let Err(err) = Sessions::remove(&session.name) {
sender.output(EnhancementsAppMsg::Toast { sender.output(EnhancementsAppMsg::Toast {
title: tr("game-session-remove-failed"), title: tr!("game-session-remove-failed"),
description: Some(err.to_string()) description: Some(err.to_string())
}).unwrap(); }).unwrap();
@ -266,7 +265,7 @@ impl SimpleAsyncComponent for GamePage {
if let Ok(config) = Config::get() { if let Ok(config) = Config::get() {
if let Err(err) = Sessions::set_current(session.name.clone()) { if let Err(err) = Sessions::set_current(session.name.clone()) {
sender.output(EnhancementsAppMsg::Toast { sender.output(EnhancementsAppMsg::Toast {
title: tr("game-session-set-current-failed"), title: tr!("game-session-set-current-failed"),
description: Some(err.to_string()) description: Some(err.to_string())
}).unwrap(); }).unwrap();
@ -276,7 +275,7 @@ impl SimpleAsyncComponent for GamePage {
if let Err(err) = Sessions::apply(session.name.clone(), config.get_wine_prefix_path()) { if let Err(err) = Sessions::apply(session.name.clone(), config.get_wine_prefix_path()) {
sender.output(EnhancementsAppMsg::Toast { sender.output(EnhancementsAppMsg::Toast {
title: tr("game-session-apply-failed"), title: tr!("game-session-apply-failed"),
description: Some(err.to_string()) description: Some(err.to_string())
}).unwrap(); }).unwrap();

View file

@ -21,7 +21,6 @@ use game::*;
use sandbox::*; use sandbox::*;
use environment::*; use environment::*;
use crate::i18n::tr;
use crate::*; use crate::*;
use super::gamescope::*; use super::gamescope::*;
@ -123,15 +122,15 @@ impl SimpleAsyncComponent for EnhancementsApp {
view! { view! {
#[root] #[root]
adw::PreferencesPage { adw::PreferencesPage {
set_title: &tr("enhancements"), set_title: &tr!("enhancements"),
set_icon_name: Some("applications-graphics-symbolic"), set_icon_name: Some("applications-graphics-symbolic"),
add = &adw::PreferencesGroup { add = &adw::PreferencesGroup {
set_title: &tr("options"), set_title: &tr!("options"),
adw::ActionRow { adw::ActionRow {
set_title: &tr("game"), set_title: &tr!("game"),
set_subtitle: &tr("game-settings-description"), set_subtitle: &tr!("game-settings-description"),
add_suffix = &gtk::Image { add_suffix = &gtk::Image {
set_icon_name: Some("go-next-symbolic") set_icon_name: Some("go-next-symbolic")
@ -143,8 +142,8 @@ impl SimpleAsyncComponent for EnhancementsApp {
}, },
adw::ActionRow { adw::ActionRow {
set_title: &tr("sandbox"), set_title: &tr!("sandbox"),
set_subtitle: &tr("sandbox-settings-description"), set_subtitle: &tr!("sandbox-settings-description"),
add_suffix = &gtk::Image { add_suffix = &gtk::Image {
set_icon_name: Some("go-next-symbolic") set_icon_name: Some("go-next-symbolic")
@ -156,8 +155,8 @@ impl SimpleAsyncComponent for EnhancementsApp {
}, },
adw::ActionRow { adw::ActionRow {
set_title: &tr("environment"), set_title: &tr!("environment"),
set_subtitle: &tr("environment-settings-description"), set_subtitle: &tr!("environment-settings-description"),
add_suffix = &gtk::Image { add_suffix = &gtk::Image {
set_icon_name: Some("go-next-symbolic") set_icon_name: Some("go-next-symbolic")
@ -170,15 +169,15 @@ impl SimpleAsyncComponent for EnhancementsApp {
}, },
add = &adw::PreferencesGroup { add = &adw::PreferencesGroup {
set_title: &tr("wine"), set_title: &tr!("wine"),
adw::ComboRow { adw::ComboRow {
set_title: &tr("synchronization"), set_title: &tr!("synchronization"),
set_subtitle: &tr("wine-sync-description"), set_subtitle: &tr!("wine-sync-description"),
#[wrap(Some)] #[wrap(Some)]
set_model = &gtk::StringList::new(&[ set_model = &gtk::StringList::new(&[
&tr("none"), &tr!("none"),
"ESync", "ESync",
"FSync" "FSync"
]), ]),
@ -197,12 +196,12 @@ impl SimpleAsyncComponent for EnhancementsApp {
}, },
adw::ComboRow { adw::ComboRow {
set_title: &tr("language"), set_title: &tr!("language"),
set_subtitle: &tr("wine-lang-description"), set_subtitle: &tr!("wine-lang-description"),
#[wrap(Some)] #[wrap(Some)]
set_model = &gtk::StringList::new(&[ set_model = &gtk::StringList::new(&[
&tr("system"), &tr!("system"),
"English", "English",
"Русский", "Русский",
"Deutsch", "Deutsch",
@ -229,7 +228,7 @@ impl SimpleAsyncComponent for EnhancementsApp {
}, },
adw::ActionRow { adw::ActionRow {
set_title: &tr("borderless-window"), set_title: &tr!("borderless-window"),
add_suffix = &gtk::Switch { add_suffix = &gtk::Switch {
set_valign: gtk::Align::Center, set_valign: gtk::Align::Center,
@ -249,7 +248,7 @@ impl SimpleAsyncComponent for EnhancementsApp {
}, },
adw::ComboRow { adw::ComboRow {
set_title: &tr("virtual-desktop"), set_title: &tr!("virtual-desktop"),
#[wrap(Some)] #[wrap(Some)]
set_model = &gtk::StringList::new(&[ set_model = &gtk::StringList::new(&[
@ -258,7 +257,7 @@ impl SimpleAsyncComponent for EnhancementsApp {
"1920x1080", "1920x1080",
"2560x1440", "2560x1440",
"3840x2160", "3840x2160",
&tr("custom") &tr!("custom")
]), ]),
set_selected: CONFIG.game.wine.virtual_desktop.get_resolution().into(), set_selected: CONFIG.game.wine.virtual_desktop.get_resolution().into(),
@ -295,14 +294,14 @@ impl SimpleAsyncComponent for EnhancementsApp {
}, },
add = &adw::PreferencesGroup { add = &adw::PreferencesGroup {
set_title: &tr("game"), set_title: &tr!("game"),
adw::ComboRow { adw::ComboRow {
set_title: &tr("hud"), set_title: &tr!("hud"),
#[wrap(Some)] #[wrap(Some)]
set_model = &gtk::StringList::new(&[ set_model = &gtk::StringList::new(&[
&tr("none"), &tr!("none"),
"DXVK", "DXVK",
"MangoHud" "MangoHud"
]), ]),
@ -321,15 +320,15 @@ impl SimpleAsyncComponent for EnhancementsApp {
}, },
adw::ComboRow { adw::ComboRow {
set_title: &tr("fsr"), set_title: &tr!("fsr"),
set_subtitle: &tr("fsr-description"), set_subtitle: &tr!("fsr-description"),
#[wrap(Some)] #[wrap(Some)]
set_model = &gtk::StringList::new(&[ set_model = &gtk::StringList::new(&[
&tr("ultra-quality"), &tr!("ultra-quality"),
&tr("quality"), &tr!("quality"),
&tr("balanced"), &tr!("balanced"),
&tr("performance") &tr!("performance")
]), ]),
set_selected: CONFIG.game.enhancements.fsr.quality.ordinal() as u32, set_selected: CONFIG.game.enhancements.fsr.quality.ordinal() as u32,
@ -362,8 +361,8 @@ impl SimpleAsyncComponent for EnhancementsApp {
}, },
adw::ActionRow { adw::ActionRow {
set_title: &tr("gamemode"), set_title: &tr!("gamemode"),
set_subtitle: &tr("gamemode-description"), set_subtitle: &tr!("gamemode-description"),
set_sensitive: is_available("gamemoderun"), set_sensitive: is_available("gamemoderun"),
@ -385,8 +384,8 @@ impl SimpleAsyncComponent for EnhancementsApp {
}, },
adw::ActionRow { adw::ActionRow {
set_title: &tr("gamescope"), set_title: &tr!("gamescope"),
set_subtitle: &tr("gamescope-description"), set_subtitle: &tr!("gamescope-description"),
set_sensitive: is_available("gamescope"), set_sensitive: is_available("gamescope"),
@ -418,11 +417,11 @@ impl SimpleAsyncComponent for EnhancementsApp {
}, },
add = &adw::PreferencesGroup { add = &adw::PreferencesGroup {
set_title: &tr("discord-rpc"), set_title: &tr!("discord-rpc"),
adw::ActionRow { adw::ActionRow {
set_title: &tr("enabled"), set_title: &tr!("enabled"),
set_subtitle: &tr("discord-rpc-description"), set_subtitle: &tr!("discord-rpc-description"),
add_suffix = &gtk::Switch { add_suffix = &gtk::Switch {
set_valign: gtk::Align::Center, set_valign: gtk::Align::Center,
@ -442,11 +441,11 @@ impl SimpleAsyncComponent for EnhancementsApp {
#[local_ref] #[local_ref]
discord_rpc_icons -> adw::ExpanderRow { discord_rpc_icons -> adw::ExpanderRow {
set_title: &tr("icon") set_title: &tr!("icon")
}, },
adw::EntryRow { adw::EntryRow {
set_title: &tr("title"), set_title: &tr!("title"),
set_text: &CONFIG.launcher.discord_rpc.title, set_text: &CONFIG.launcher.discord_rpc.title,
connect_changed: |row| { connect_changed: |row| {
@ -461,7 +460,7 @@ impl SimpleAsyncComponent for EnhancementsApp {
}, },
adw::EntryRow { adw::EntryRow {
set_title: &tr("description"), set_title: &tr!("description"),
set_text: &CONFIG.launcher.discord_rpc.subtitle, set_text: &CONFIG.launcher.discord_rpc.subtitle,
connect_changed: |row| { connect_changed: |row| {
@ -477,11 +476,11 @@ impl SimpleAsyncComponent for EnhancementsApp {
}, },
add = &adw::PreferencesGroup { add = &adw::PreferencesGroup {
set_title: &tr("fps-unlocker"), set_title: &tr!("fps-unlocker"),
adw::ComboRow { adw::ComboRow {
set_title: &tr("enabled"), set_title: &tr!("enabled"),
set_subtitle: &tr("fps-unlocker-description"), set_subtitle: &tr!("fps-unlocker-description"),
#[wrap(Some)] #[wrap(Some)]
set_model = &gtk::StringList::new(&[ set_model = &gtk::StringList::new(&[
@ -492,7 +491,7 @@ impl SimpleAsyncComponent for EnhancementsApp {
"180", "180",
"200", "200",
"240", "240",
&tr("custom") &tr!("custom")
]), ]),
set_selected: match Fps::from_num(CONFIG.game.enhancements.fps_unlocker.config.fps) { set_selected: match Fps::from_num(CONFIG.game.enhancements.fps_unlocker.config.fps) {
@ -535,8 +534,8 @@ impl SimpleAsyncComponent for EnhancementsApp {
}, },
adw::ActionRow { adw::ActionRow {
set_title: &tr("power-saving"), set_title: &tr!("power-saving"),
set_subtitle: &tr("power-saving-description"), set_subtitle: &tr!("power-saving-description"),
add_suffix = &gtk::Switch { add_suffix = &gtk::Switch {
set_valign: gtk::Align::Center, set_valign: gtk::Align::Center,
@ -556,8 +555,8 @@ impl SimpleAsyncComponent for EnhancementsApp {
}, },
adw::ActionRow { adw::ActionRow {
set_title: &tr("monitor"), set_title: &tr!("monitor"),
set_subtitle: &tr("monitor-description"), set_subtitle: &tr!("monitor-description"),
add_suffix = &gtk::SpinButton { add_suffix = &gtk::SpinButton {
set_valign: gtk::Align::Center, set_valign: gtk::Align::Center,
@ -578,13 +577,13 @@ impl SimpleAsyncComponent for EnhancementsApp {
}, },
adw::ComboRow { adw::ComboRow {
set_title: &tr("window-mode"), set_title: &tr!("window-mode"),
#[wrap(Some)] #[wrap(Some)]
set_model = &gtk::StringList::new(&[ set_model = &gtk::StringList::new(&[
&tr("default"), &tr!("default"),
&tr("popup"), &tr!("popup"),
&tr("fullscreen") &tr!("fullscreen")
]), ]),
set_selected: CONFIG.game.enhancements.fps_unlocker.config.window_mode.ordinal() as u32, set_selected: CONFIG.game.enhancements.fps_unlocker.config.window_mode.ordinal() as u32,
@ -601,17 +600,17 @@ impl SimpleAsyncComponent for EnhancementsApp {
}, },
adw::ComboRow { adw::ComboRow {
set_title: &tr("priority"), set_title: &tr!("priority"),
set_subtitle: &tr("priority-description"), set_subtitle: &tr!("priority-description"),
#[wrap(Some)] #[wrap(Some)]
set_model = &gtk::StringList::new(&[ set_model = &gtk::StringList::new(&[
&tr("realtime"), &tr!("realtime"),
&tr("high"), &tr!("high"),
&tr("above-normal"), &tr!("above-normal"),
&tr("normal"), &tr!("normal"),
&tr("below-normal"), &tr!("below-normal"),
&tr("low") &tr!("low")
]), ]),
set_selected: CONFIG.game.enhancements.fps_unlocker.config.priority as u32, set_selected: CONFIG.game.enhancements.fps_unlocker.config.priority as u32,
@ -699,7 +698,7 @@ impl SimpleAsyncComponent for EnhancementsApp {
/*if let Err(err) = result { /*if let Err(err) = result {
sender.input(EnhancementsAppMsg::Toast { sender.input(EnhancementsAppMsg::Toast {
title: tr("discord-rpc-icon-download-failed"), title: tr!("discord-rpc-icon-download-failed"),
description: Some(err.to_string()) description: Some(err.to_string())
}); });
}*/ }*/
@ -726,7 +725,7 @@ impl SimpleAsyncComponent for EnhancementsApp {
} }
Err(err) => sender.input(EnhancementsAppMsg::Toast { 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()) description: Some(err.to_string())
}) })
} }

View file

@ -8,7 +8,6 @@ use anime_launcher_sdk::is_available;
use super::EnhancementsAppMsg; use super::EnhancementsAppMsg;
use crate::i18n::tr;
use crate::*; use crate::*;
macro_rules! impl_directory { macro_rules! impl_directory {
@ -110,7 +109,7 @@ impl SimpleAsyncComponent for SandboxPage {
adw::HeaderBar { adw::HeaderBar {
#[wrap(Some)] #[wrap(Some)]
set_title_widget = &adw::WindowTitle { set_title_widget = &adw::WindowTitle {
set_title: &tr("sandbox") set_title: &tr!("sandbox")
}, },
pack_start = &gtk::Button { pack_start = &gtk::Button {
@ -123,18 +122,18 @@ impl SimpleAsyncComponent for SandboxPage {
}, },
adw::PreferencesPage { adw::PreferencesPage {
set_title: &tr("sandbox"), set_title: &tr!("sandbox"),
set_icon_name: Some("folder-symbolic"), set_icon_name: Some("folder-symbolic"),
set_sensitive: is_available("bwrap"), set_sensitive: is_available("bwrap"),
add = &adw::PreferencesGroup { add = &adw::PreferencesGroup {
set_title: &tr("sandbox"), set_title: &tr!("sandbox"),
set_description: Some(&tr("sandbox-description")), set_description: Some(&tr!("sandbox-description")),
adw::ActionRow { adw::ActionRow {
set_title: &tr("enable-sandboxing"), set_title: &tr!("enable-sandboxing"),
set_subtitle: &tr("enable-sandboxing-description"), set_subtitle: &tr!("enable-sandboxing-description"),
add_suffix = &gtk::Switch { add_suffix = &gtk::Switch {
set_valign: gtk::Align::Center, set_valign: gtk::Align::Center,
@ -154,8 +153,8 @@ impl SimpleAsyncComponent for SandboxPage {
}, },
adw::ActionRow { adw::ActionRow {
set_title: &tr("hide-home-directory"), set_title: &tr!("hide-home-directory"),
set_subtitle: &tr("hide-home-directory-description"), set_subtitle: &tr!("hide-home-directory-description"),
add_suffix = &gtk::Switch { add_suffix = &gtk::Switch {
set_valign: gtk::Align::Center, set_valign: gtk::Align::Center,
@ -175,7 +174,7 @@ impl SimpleAsyncComponent for SandboxPage {
}, },
adw::EntryRow { adw::EntryRow {
set_title: &tr("hostname"), set_title: &tr!("hostname"),
set_text: CONFIG.sandbox.hostname.as_ref().unwrap_or(&String::new()).trim(), set_text: CONFIG.sandbox.hostname.as_ref().unwrap_or(&String::new()).trim(),
connect_changed => |entry| { connect_changed => |entry| {
@ -194,7 +193,7 @@ impl SimpleAsyncComponent for SandboxPage {
}, },
adw::EntryRow { adw::EntryRow {
set_title: &tr("additional-arguments"), set_title: &tr!("additional-arguments"),
set_text: CONFIG.sandbox.args.as_ref().unwrap_or(&String::new()).trim(), set_text: CONFIG.sandbox.args.as_ref().unwrap_or(&String::new()).trim(),
connect_changed => |entry| { connect_changed => |entry| {
@ -220,7 +219,7 @@ impl SimpleAsyncComponent for SandboxPage {
connect_clicked[sender] => move |_| { connect_clicked[sender] => move |_| {
if let Err(err) = open::that("https://man.archlinux.org/man/bwrap.1") { if let Err(err) = open::that("https://man.archlinux.org/man/bwrap.1") {
sender.output(EnhancementsAppMsg::Toast { sender.output(EnhancementsAppMsg::Toast {
title: tr("documentation-url-open-failed"), title: tr!("documentation-url-open-failed"),
description: Some(err.to_string()) description: Some(err.to_string())
}).unwrap(); }).unwrap();
} }
@ -230,12 +229,12 @@ impl SimpleAsyncComponent for SandboxPage {
}, },
add = &adw::PreferencesGroup { add = &adw::PreferencesGroup {
set_title: &tr("private-directories"), set_title: &tr!("private-directories"),
set_description: Some(&tr("private-directories-description")), set_description: Some(&tr!("private-directories-description")),
#[local_ref] #[local_ref]
private_path_entry -> adw::EntryRow { private_path_entry -> adw::EntryRow {
set_title: &tr("path"), set_title: &tr!("path"),
add_suffix = &gtk::Button { add_suffix = &gtk::Button {
set_icon_name: "list-add-symbolic", set_icon_name: "list-add-symbolic",
@ -252,8 +251,8 @@ impl SimpleAsyncComponent for SandboxPage {
add = private_paths -> adw::PreferencesGroup {}, add = private_paths -> adw::PreferencesGroup {},
add = &adw::PreferencesGroup { add = &adw::PreferencesGroup {
set_title: &tr("shared-directories"), set_title: &tr!("shared-directories"),
set_description: Some(&tr("shared-directories-description")), set_description: Some(&tr!("shared-directories-description")),
#[wrap(Some)] #[wrap(Some)]
set_header_suffix = &gtk::Button { set_header_suffix = &gtk::Button {
@ -263,7 +262,7 @@ impl SimpleAsyncComponent for SandboxPage {
adw::ButtonContent { adw::ButtonContent {
set_icon_name: "list-add-symbolic", set_icon_name: "list-add-symbolic",
set_label: &tr("add") set_label: &tr!("add")
}, },
connect_clicked => SandboxPageMsg::AddShared connect_clicked => SandboxPageMsg::AddShared
@ -271,17 +270,17 @@ impl SimpleAsyncComponent for SandboxPage {
#[local_ref] #[local_ref]
shared_path_from_entry -> adw::EntryRow { shared_path_from_entry -> adw::EntryRow {
set_title: &tr("original-path") set_title: &tr!("original-path")
}, },
#[local_ref] #[local_ref]
shared_path_to_entry -> adw::EntryRow { shared_path_to_entry -> adw::EntryRow {
set_title: &tr("new-path") set_title: &tr!("new-path")
}, },
adw::ActionRow { adw::ActionRow {
set_title: &tr("read-only"), set_title: &tr!("read-only"),
set_subtitle: &tr("read-only-description"), set_subtitle: &tr!("read-only-description"),
#[local_ref] #[local_ref]
add_suffix = read_only_switch -> gtk::Switch { add_suffix = read_only_switch -> gtk::Switch {
@ -294,8 +293,8 @@ impl SimpleAsyncComponent for SandboxPage {
add = shared_paths -> adw::PreferencesGroup {}, add = shared_paths -> adw::PreferencesGroup {},
add = &adw::PreferencesGroup { add = &adw::PreferencesGroup {
set_title: &tr("symlinks"), set_title: &tr!("symlinks"),
set_description: Some(&tr("symlinks-description")), set_description: Some(&tr!("symlinks-description")),
#[wrap(Some)] #[wrap(Some)]
set_header_suffix = &gtk::Button { set_header_suffix = &gtk::Button {
@ -305,7 +304,7 @@ impl SimpleAsyncComponent for SandboxPage {
adw::ButtonContent { adw::ButtonContent {
set_icon_name: "list-add-symbolic", set_icon_name: "list-add-symbolic",
set_label: &tr("add") set_label: &tr!("add")
}, },
connect_clicked => SandboxPageMsg::AddSymlink connect_clicked => SandboxPageMsg::AddSymlink
@ -313,12 +312,12 @@ impl SimpleAsyncComponent for SandboxPage {
#[local_ref] #[local_ref]
symlink_path_from_entry -> adw::EntryRow { symlink_path_from_entry -> adw::EntryRow {
set_title: &tr("original-path") set_title: &tr!("original-path")
}, },
#[local_ref] #[local_ref]
symlink_path_to_entry -> adw::EntryRow { symlink_path_to_entry -> adw::EntryRow {
set_title: &tr("new-path") set_title: &tr!("new-path")
} }
}, },

View file

@ -8,7 +8,6 @@ use anime_launcher_sdk::genshin::config::Config;
use anime_launcher_sdk::config::schema_blanks::prelude::*; use anime_launcher_sdk::config::schema_blanks::prelude::*;
use crate::i18n::tr;
use crate::*; use crate::*;
pub struct GamescopeApp; pub struct GamescopeApp;
@ -21,7 +20,7 @@ impl SimpleAsyncComponent for GamescopeApp {
view! { view! {
adw::PreferencesWindow { adw::PreferencesWindow {
set_title: Some(&tr("gamescope")), set_title: Some(&tr!("gamescope")),
set_modal: true, set_modal: true,
set_hide_on_close: true, set_hide_on_close: true,
@ -31,10 +30,10 @@ impl SimpleAsyncComponent for GamescopeApp {
add = &adw::PreferencesPage { add = &adw::PreferencesPage {
add = &adw::PreferencesGroup { add = &adw::PreferencesGroup {
set_title: &tr("game-resolution"), set_title: &tr!("game-resolution"),
adw::EntryRow { adw::EntryRow {
set_title: &tr("width"), set_title: &tr!("width"),
set_input_purpose: gtk::InputPurpose::Digits, set_input_purpose: gtk::InputPurpose::Digits,
set_text: &if CONFIG.game.enhancements.gamescope.game.width > 0 { set_text: &if CONFIG.game.enhancements.gamescope.game.width > 0 {
@ -55,7 +54,7 @@ impl SimpleAsyncComponent for GamescopeApp {
}, },
adw::EntryRow { adw::EntryRow {
set_title: &tr("height"), set_title: &tr!("height"),
set_input_purpose: gtk::InputPurpose::Digits, set_input_purpose: gtk::InputPurpose::Digits,
set_text: &if CONFIG.game.enhancements.gamescope.game.height > 0 { set_text: &if CONFIG.game.enhancements.gamescope.game.height > 0 {
@ -77,10 +76,10 @@ impl SimpleAsyncComponent for GamescopeApp {
}, },
add = &adw::PreferencesGroup { add = &adw::PreferencesGroup {
set_title: &tr("gamescope-resolution"), set_title: &tr!("gamescope-resolution"),
adw::EntryRow { adw::EntryRow {
set_title: &tr("width"), set_title: &tr!("width"),
set_input_purpose: gtk::InputPurpose::Digits, set_input_purpose: gtk::InputPurpose::Digits,
set_text: &if CONFIG.game.enhancements.gamescope.gamescope.width > 0 { set_text: &if CONFIG.game.enhancements.gamescope.gamescope.width > 0 {
@ -101,7 +100,7 @@ impl SimpleAsyncComponent for GamescopeApp {
}, },
adw::EntryRow { adw::EntryRow {
set_title: &tr("height"), set_title: &tr!("height"),
set_input_purpose: gtk::InputPurpose::Digits, set_input_purpose: gtk::InputPurpose::Digits,
set_text: &if CONFIG.game.enhancements.gamescope.gamescope.height > 0 { set_text: &if CONFIG.game.enhancements.gamescope.gamescope.height > 0 {
@ -123,11 +122,11 @@ impl SimpleAsyncComponent for GamescopeApp {
}, },
add = &adw::PreferencesGroup { add = &adw::PreferencesGroup {
set_title: &tr("upscaling"), set_title: &tr!("upscaling"),
adw::ActionRow { adw::ActionRow {
set_title: &tr("integer-scaling"), set_title: &tr!("integer-scaling"),
set_subtitle: &tr("integer-scaling-description"), set_subtitle: &tr!("integer-scaling-description"),
add_suffix = &gtk::Switch { add_suffix = &gtk::Switch {
set_valign: gtk::Align::Center, set_valign: gtk::Align::Center,
@ -147,7 +146,7 @@ impl SimpleAsyncComponent for GamescopeApp {
adw::ActionRow { adw::ActionRow {
set_title: "FSR", set_title: "FSR",
set_subtitle: &tr("gamescope-fsr-description"), set_subtitle: &tr!("gamescope-fsr-description"),
add_suffix = &gtk::Switch { add_suffix = &gtk::Switch {
set_valign: gtk::Align::Center, set_valign: gtk::Align::Center,
@ -167,7 +166,7 @@ impl SimpleAsyncComponent for GamescopeApp {
adw::ActionRow { adw::ActionRow {
set_title: "Nvidia Image Scaling", set_title: "Nvidia Image Scaling",
set_subtitle: &tr("nis-description"), set_subtitle: &tr!("nis-description"),
add_suffix = &gtk::Switch { add_suffix = &gtk::Switch {
set_valign: gtk::Align::Center, set_valign: gtk::Align::Center,
@ -187,12 +186,12 @@ impl SimpleAsyncComponent for GamescopeApp {
}, },
add = &adw::PreferencesGroup { add = &adw::PreferencesGroup {
set_title: &tr("other-settings"), set_title: &tr!("other-settings"),
// TODO: maybe use Fps enum like in fps unlocker settings // TODO: maybe use Fps enum like in fps unlocker settings
adw::EntryRow { adw::EntryRow {
set_title: &tr("framerate-limit"), set_title: &tr!("framerate-limit"),
set_input_purpose: gtk::InputPurpose::Digits, set_input_purpose: gtk::InputPurpose::Digits,
set_text: &if CONFIG.game.enhancements.gamescope.framerate.focused > 0 { set_text: &if CONFIG.game.enhancements.gamescope.framerate.focused > 0 {
@ -213,7 +212,7 @@ impl SimpleAsyncComponent for GamescopeApp {
}, },
adw::EntryRow { adw::EntryRow {
set_title: &tr("unfocused-framerate-limit"), set_title: &tr!("unfocused-framerate-limit"),
set_input_purpose: gtk::InputPurpose::Digits, set_input_purpose: gtk::InputPurpose::Digits,
set_text: &if CONFIG.game.enhancements.gamescope.framerate.unfocused > 0 { set_text: &if CONFIG.game.enhancements.gamescope.framerate.unfocused > 0 {
@ -234,12 +233,12 @@ impl SimpleAsyncComponent for GamescopeApp {
}, },
adw::ComboRow { adw::ComboRow {
set_title: &tr("window-mode"), set_title: &tr!("window-mode"),
#[wrap(Some)] #[wrap(Some)]
set_model = &gtk::StringList::new(&[ set_model = &gtk::StringList::new(&[
&tr("borderless"), &tr!("borderless"),
&tr("fullscreen") &tr!("fullscreen")
]), ]),
set_selected: CONFIG.game.enhancements.gamescope.window_type.ordinal() as u32, set_selected: CONFIG.game.enhancements.gamescope.window_type.ordinal() as u32,

View file

@ -12,7 +12,6 @@ use anime_launcher_sdk::components::wine::UnifiedWine;
use super::GeneralAppMsg; use super::GeneralAppMsg;
use crate::ui::components::*; use crate::ui::components::*;
use crate::i18n::*;
use crate::*; use crate::*;
pub struct ComponentsPage { pub struct ComponentsPage {
@ -58,7 +57,7 @@ impl SimpleAsyncComponent for ComponentsPage {
adw::HeaderBar { adw::HeaderBar {
#[wrap(Some)] #[wrap(Some)]
set_title_widget = &adw::WindowTitle { set_title_widget = &adw::WindowTitle {
set_title: &tr("components") set_title: &tr!("components")
}, },
pack_start = &gtk::Button { pack_start = &gtk::Button {
@ -72,10 +71,10 @@ impl SimpleAsyncComponent for ComponentsPage {
adw::PreferencesPage { adw::PreferencesPage {
add = &adw::PreferencesGroup { add = &adw::PreferencesGroup {
set_title: &tr("wine-version"), set_title: &tr!("wine-version"),
adw::ComboRow { adw::ComboRow {
set_title: &tr("selected-version"), set_title: &tr!("selected-version"),
#[watch] #[watch]
#[block_signal(wine_selected_notify)] #[block_signal(wine_selected_notify)]
@ -103,8 +102,8 @@ impl SimpleAsyncComponent for ComponentsPage {
}, },
adw::ActionRow { adw::ActionRow {
set_title: &tr("recommended-only"), set_title: &tr!("recommended-only"),
set_subtitle: &tr("wine-recommended-description"), set_subtitle: &tr!("wine-recommended-description"),
add_suffix = &gtk::Switch { add_suffix = &gtk::Switch {
set_valign: gtk::Align::Center, set_valign: gtk::Align::Center,
@ -126,11 +125,11 @@ impl SimpleAsyncComponent for ComponentsPage {
}, },
add = &adw::PreferencesGroup { add = &adw::PreferencesGroup {
set_title: &tr("wine-options"), set_title: &tr!("wine-options"),
adw::ActionRow { adw::ActionRow {
set_title: &tr("wine-use-shared-libraries"), set_title: &tr!("wine-use-shared-libraries"),
set_subtitle: &tr("wine-use-shared-libraries-description"), set_subtitle: &tr!("wine-use-shared-libraries-description"),
add_suffix = &gtk::Switch { add_suffix = &gtk::Switch {
set_valign: gtk::Align::Center, set_valign: gtk::Align::Center,
@ -151,8 +150,8 @@ impl SimpleAsyncComponent for ComponentsPage {
}, },
adw::ActionRow { adw::ActionRow {
set_title: &tr("gstreamer-use-shared-libraries"), set_title: &tr!("gstreamer-use-shared-libraries"),
set_subtitle: &tr("gstreamer-use-shared-libraries-description"), set_subtitle: &tr!("gstreamer-use-shared-libraries-description"),
add_suffix = &gtk::Switch { add_suffix = &gtk::Switch {
set_valign: gtk::Align::Center, set_valign: gtk::Align::Center,
@ -174,11 +173,11 @@ impl SimpleAsyncComponent for ComponentsPage {
}, },
add = &adw::PreferencesGroup { add = &adw::PreferencesGroup {
set_title: &tr("dxvk-version"), set_title: &tr!("dxvk-version"),
#[watch] #[watch]
set_description: Some(&if !model.allow_dxvk_selection { set_description: Some(&if !model.allow_dxvk_selection {
tr("dxvk-selection-disabled") tr!("dxvk-selection-disabled")
} else { } else {
String::new() String::new()
}), }),
@ -187,7 +186,7 @@ impl SimpleAsyncComponent for ComponentsPage {
set_sensitive: model.allow_dxvk_selection, set_sensitive: model.allow_dxvk_selection,
adw::ComboRow { adw::ComboRow {
set_title: &tr("selected-version"), set_title: &tr!("selected-version"),
#[watch] #[watch]
#[block_signal(dxvk_selected_notify)] #[block_signal(dxvk_selected_notify)]
@ -215,8 +214,8 @@ impl SimpleAsyncComponent for ComponentsPage {
}, },
adw::ActionRow { adw::ActionRow {
set_title: &tr("recommended-only"), set_title: &tr!("recommended-only"),
set_subtitle: &tr("dxvk-recommended-description"), set_subtitle: &tr!("dxvk-recommended-description"),
add_suffix = &gtk::Switch { add_suffix = &gtk::Switch {
set_valign: gtk::Align::Center, set_valign: gtk::Align::Center,
@ -433,7 +432,7 @@ impl SimpleAsyncComponent for ComponentsPage {
Err(err) => { Err(err) => {
sender.output(GeneralAppMsg::Toast { sender.output(GeneralAppMsg::Toast {
title: tr("wine-prefix-update-failed"), title: tr!("wine-prefix-update-failed"),
description: Some(err.to_string()) description: Some(err.to_string())
}).unwrap(); }).unwrap();
} }
@ -476,7 +475,7 @@ impl SimpleAsyncComponent for ComponentsPage {
std::thread::spawn(move || { std::thread::spawn(move || {
if let Err(err) = Dxvk::install(&wine, dxvk_folder, InstallParams::default()) { if let Err(err) = Dxvk::install(&wine, dxvk_folder, InstallParams::default()) {
sender.output(GeneralAppMsg::Toast { sender.output(GeneralAppMsg::Toast {
title: tr("dxvk-install-failed"), title: tr!("dxvk-install-failed"),
description: Some(err.to_string()) description: Some(err.to_string())
}).unwrap(); }).unwrap();
} }

View file

@ -13,7 +13,7 @@ use anime_launcher_sdk::wincompatlib::prelude::*;
use anime_launcher_sdk::config::ConfigExt; use anime_launcher_sdk::config::ConfigExt;
use anime_launcher_sdk::genshin::config::Config; 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::anime_game_core::genshin::consts::GameEdition;
use anime_launcher_sdk::genshin::env_emulation::Environment; use anime_launcher_sdk::genshin::env_emulation::Environment;
@ -22,12 +22,12 @@ pub mod components;
use components::*; use components::*;
use super::main::PreferencesAppMsg;
use crate::ui::migrate_installation::MigrateInstallationApp; use crate::ui::migrate_installation::MigrateInstallationApp;
use crate::i18n::*; use crate::i18n::*;
use crate::*; use crate::*;
use super::main::PreferencesAppMsg;
#[derive(Debug)] #[derive(Debug)]
struct VoicePackageComponent { struct VoicePackageComponent {
locale: VoiceLocale, locale: VoiceLocale,
@ -46,7 +46,7 @@ impl AsyncFactoryComponent for VoicePackageComponent {
view! { view! {
root = adw::ActionRow { 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 = &gtk::Button { add_suffix = &gtk::Button {
#[watch] #[watch]
@ -163,11 +163,11 @@ impl SimpleAsyncComponent for GeneralApp {
view! { view! {
#[root] #[root]
adw::PreferencesPage { adw::PreferencesPage {
set_title: &tr("general"), set_title: &tr!("general"),
set_icon_name: Some("applications-system-symbolic"), set_icon_name: Some("applications-system-symbolic"),
add = &adw::PreferencesGroup { add = &adw::PreferencesGroup {
set_title: &tr("appearance"), set_title: &tr!("appearance"),
gtk::Box { gtk::Box {
set_orientation: gtk::Orientation::Horizontal, set_orientation: gtk::Orientation::Horizontal,
@ -188,14 +188,14 @@ impl SimpleAsyncComponent for GeneralApp {
set_active: model.style == LauncherStyle::Modern, set_active: model.style == LauncherStyle::Modern,
gtk::Image { 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) connect_clicked => GeneralAppMsg::UpdateLauncherStyle(LauncherStyle::Modern)
}, },
gtk::Label { gtk::Label {
set_text: &tr("modern"), set_text: &tr!("modern"),
set_margin_top: 16 set_margin_top: 16
} }
@ -214,14 +214,14 @@ impl SimpleAsyncComponent for GeneralApp {
set_active: model.style == LauncherStyle::Classic, set_active: model.style == LauncherStyle::Classic,
gtk::Image { 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) connect_clicked => GeneralAppMsg::UpdateLauncherStyle(LauncherStyle::Classic)
}, },
gtk::Label { gtk::Label {
set_text: &tr("classic"), set_text: &tr!("classic"),
set_margin_top: 16 set_margin_top: 16
} }
@ -234,8 +234,8 @@ impl SimpleAsyncComponent for GeneralApp {
set_visible: model.style == LauncherStyle::Classic, set_visible: model.style == LauncherStyle::Classic,
adw::ActionRow { adw::ActionRow {
set_title: &tr("update-background"), set_title: &tr!("update-background"),
set_subtitle: &tr("update-background-description"), set_subtitle: &tr!("update-background-description"),
add_suffix = &gtk::Switch { add_suffix = &gtk::Switch {
set_valign: gtk::Align::Center, set_valign: gtk::Align::Center,
@ -254,11 +254,11 @@ impl SimpleAsyncComponent for GeneralApp {
}, },
add = &adw::PreferencesGroup { add = &adw::PreferencesGroup {
set_title: &tr("general"), set_title: &tr!("general"),
adw::ComboRow { adw::ComboRow {
set_title: &tr("launcher-language"), set_title: &tr!("launcher-language"),
set_subtitle: &tr("launcher-language-description"), set_subtitle: &tr!("launcher-language-description"),
set_model: Some(&gtk::StringList::new(&model.languages.iter().map(|lang| lang.as_str()).collect::<Vec<&str>>())), set_model: Some(&gtk::StringList::new(&model.languages.iter().map(|lang| lang.as_str()).collect::<Vec<&str>>())),
@ -284,11 +284,11 @@ impl SimpleAsyncComponent for GeneralApp {
}, },
adw::ComboRow { adw::ComboRow {
set_title: &tr("game-edition"), set_title: &tr!("game-edition"),
set_model: Some(&gtk::StringList::new(&[ set_model: Some(&gtk::StringList::new(&[
&tr("global"), &tr!("global"),
&tr("china") &tr!("china")
])), ])),
set_selected: match CONFIG.launcher.edition { set_selected: match CONFIG.launcher.edition {
@ -316,8 +316,8 @@ impl SimpleAsyncComponent for GeneralApp {
}, },
adw::ComboRow { adw::ComboRow {
set_title: &tr("game-environment"), set_title: &tr!("game-environment"),
set_subtitle: &tr("game-environment-description"), set_subtitle: &tr!("game-environment-description"),
set_model: Some(&gtk::StringList::new(&[ set_model: Some(&gtk::StringList::new(&[
"PC", "PC",
@ -349,8 +349,8 @@ impl SimpleAsyncComponent for GeneralApp {
#[local_ref] #[local_ref]
voice_packages -> adw::ExpanderRow { voice_packages -> adw::ExpanderRow {
set_title: &tr("game-voiceovers"), set_title: &tr!("game-voiceovers"),
set_subtitle: &tr("game-voiceovers-description") set_subtitle: &tr!("game-voiceovers-description")
}, },
gtk::Box { gtk::Box {
@ -359,14 +359,14 @@ impl SimpleAsyncComponent for GeneralApp {
set_margin_top: 16, set_margin_top: 16,
gtk::Button { gtk::Button {
set_label: &tr("migrate-installation"), set_label: &tr!("migrate-installation"),
set_tooltip_text: Some(&tr("migrate-installation-description")), set_tooltip_text: Some(&tr!("migrate-installation-description")),
connect_clicked => GeneralAppMsg::OpenMigrateInstallation connect_clicked => GeneralAppMsg::OpenMigrateInstallation
}, },
gtk::Button { gtk::Button {
set_label: &tr("repair-game"), set_label: &tr!("repair-game"),
connect_clicked => GeneralAppMsg::RepairGame connect_clicked => GeneralAppMsg::RepairGame
} }
@ -374,10 +374,10 @@ impl SimpleAsyncComponent for GeneralApp {
}, },
add = &adw::PreferencesGroup { add = &adw::PreferencesGroup {
set_title: &tr("status"), set_title: &tr!("status"),
adw::ActionRow { adw::ActionRow {
set_title: &tr("game-version"), set_title: &tr!("game-version"),
add_suffix = &gtk::Label { add_suffix = &gtk::Label {
#[watch] #[watch]
@ -388,7 +388,7 @@ impl SimpleAsyncComponent for GeneralApp {
VersionDiff::Diff { current, .. } | VersionDiff::Diff { current, .. } |
VersionDiff::Outdated { current, .. } => current.to_string(), VersionDiff::Outdated { current, .. } => current.to_string(),
VersionDiff::NotInstalled { .. } => tr("game-not-installed") VersionDiff::NotInstalled { .. } => tr!("game-not-installed")
} }
None => String::from("?") None => String::from("?")
@ -411,17 +411,21 @@ impl SimpleAsyncComponent for GeneralApp {
set_tooltip_text: Some(&match model.game_diff.as_ref() { set_tooltip_text: Some(&match model.game_diff.as_ref() {
Some(diff) => match diff { Some(diff) => match diff {
VersionDiff::Latest { .. } => String::new(), VersionDiff::Latest { .. } => String::new(),
VersionDiff::Predownload { current, latest, .. } => tr_args("game-predownload-available", [
("old", current.to_string().into()), VersionDiff::Predownload { current, latest, .. } => tr!("game-predownload-available", {
("new", latest.to_string().into()) "old" = current.to_string(),
]), "new" = latest.to_string()
VersionDiff::Diff { current, latest, .. } => tr_args("game-update-available", [ }),
("old", current.to_string().into()),
("new", latest.to_string().into()) VersionDiff::Diff { current, latest, .. } => tr!("game-update-available", {
]), "old" = current.to_string(),
VersionDiff::Outdated { latest, ..} => tr_args("game-outdated", [ "new" = latest.to_string()
("latest", latest.to_string().into()) }),
]),
VersionDiff::Outdated { latest, ..} => tr!("game-outdated", {
"latest" = latest.to_string()
}),
VersionDiff::NotInstalled { .. } => String::new() VersionDiff::NotInstalled { .. } => String::new()
} }
@ -431,16 +435,21 @@ impl SimpleAsyncComponent for GeneralApp {
}, },
adw::ActionRow { adw::ActionRow {
set_title: &tr("player-patch-version"), set_title: &tr!("player-patch-version"),
set_subtitle: &tr("player-patch-version-description"), set_subtitle: &tr!("player-patch-version-description"),
add_suffix = &gtk::Label { add_suffix = &gtk::Label {
#[watch] #[watch]
set_text: &match model.player_patch.as_ref() { set_text: &match model.player_patch.as_ref() {
Some(patch) => match patch.status() { Some(patch) => match patch.status() {
PatchStatus::NotAvailable => tr("patch-not-available"), PatchStatus::NotAvailable => tr!("patch-not-available"),
PatchStatus::Outdated { current, .. } => tr_args("patch-outdated", [("current", current.to_string().into())]),
PatchStatus::Preparation { .. } => tr("patch-preparation"), PatchStatus::Outdated { current, .. } => tr!("patch-outdated", {
"current" = current.to_string()
}),
PatchStatus::Preparation { .. } => tr!("patch-preparation"),
PatchStatus::Testing { version, .. } | PatchStatus::Testing { version, .. } |
PatchStatus::Available { version, .. } => version.to_string() PatchStatus::Available { version, .. } => version.to_string()
} }
@ -452,9 +461,11 @@ impl SimpleAsyncComponent for GeneralApp {
set_css_classes: match model.player_patch.as_ref() { set_css_classes: match model.player_patch.as_ref() {
Some(patch) => match patch.status() { Some(patch) => match patch.status() {
PatchStatus::NotAvailable => &["error"], PatchStatus::NotAvailable => &["error"],
PatchStatus::Outdated { .. } | PatchStatus::Outdated { .. } |
PatchStatus::Preparation { .. } | PatchStatus::Preparation { .. } |
PatchStatus::Testing { .. } => &["warning"], PatchStatus::Testing { .. } => &["warning"],
PatchStatus::Available { .. } => unsafe { PatchStatus::Available { .. } => unsafe {
let path = match Config::get() { let path = match Config::get() {
Ok(config) => config.game.path.for_edition(config.launcher.edition).to_path_buf(), Ok(config) => config.game.path.for_edition(config.launcher.edition).to_path_buf(),
@ -475,13 +486,16 @@ impl SimpleAsyncComponent for GeneralApp {
#[watch] #[watch]
set_tooltip_text: Some(&match model.player_patch.as_ref() { set_tooltip_text: Some(&match model.player_patch.as_ref() {
Some(patch) => match patch.status() { Some(patch) => match patch.status() {
PatchStatus::NotAvailable => tr("patch-not-available-tooltip"), PatchStatus::NotAvailable => tr!("patch-not-available-tooltip"),
PatchStatus::Outdated { current, latest, .. } => tr_args("patch-outdated-tooltip", [
("current", current.to_string().into()), PatchStatus::Outdated { current, latest, .. } => tr!("patch-outdated-tooltip", {
("latest", latest.to_string().into()) "current" = current.to_string(),
]), "latest" = latest.to_string()
PatchStatus::Preparation { .. } => tr("patch-preparation-tooltip"), }),
PatchStatus::Testing { .. } => tr("patch-testing-tooltip"),
PatchStatus::Preparation { .. } => tr!("patch-preparation-tooltip"),
PatchStatus::Testing { .. } => tr!("patch-testing-tooltip"),
PatchStatus::Available { .. } => unsafe { PatchStatus::Available { .. } => unsafe {
let path = match Config::get() { let path = match Config::get() {
Ok(config) => config.game.path.for_edition(config.launcher.edition).to_path_buf(), 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) { if let Ok(true) = model.player_patch.as_ref().unwrap_unchecked().is_applied(path) {
String::new() String::new()
} else { } else {
tr("patch-not-applied-tooltip") tr!("patch-not-applied-tooltip")
} }
} }
} }
@ -504,8 +518,8 @@ impl SimpleAsyncComponent for GeneralApp {
add = &adw::PreferencesGroup { add = &adw::PreferencesGroup {
adw::ActionRow { adw::ActionRow {
set_title: &tr("apply-main-patch"), set_title: &tr!("apply-main-patch"),
set_subtitle: &tr("apply-main-patch-description"), set_subtitle: &tr!("apply-main-patch-description"),
add_suffix = &gtk::Switch { add_suffix = &gtk::Switch {
set_valign: gtk::Align::Center, set_valign: gtk::Align::Center,
@ -528,8 +542,8 @@ impl SimpleAsyncComponent for GeneralApp {
}, },
adw::ActionRow { adw::ActionRow {
set_title: &tr("disable-mhypbase"), set_title: &tr!("disable-mhypbase"),
set_subtitle: &tr("disable-mhypbase-description"), set_subtitle: &tr!("disable-mhypbase-description"),
add_suffix = &gtk::Switch { add_suffix = &gtk::Switch {
set_valign: gtk::Align::Center, set_valign: gtk::Align::Center,
@ -552,8 +566,8 @@ impl SimpleAsyncComponent for GeneralApp {
}, },
adw::ActionRow { adw::ActionRow {
set_title: &tr("ask-superuser-permissions"), set_title: &tr!("ask-superuser-permissions"),
set_subtitle: &tr("ask-superuser-permissions-description"), set_subtitle: &tr!("ask-superuser-permissions-description"),
add_suffix = &gtk::Switch { add_suffix = &gtk::Switch {
set_valign: gtk::Align::Center, set_valign: gtk::Align::Center,
@ -574,11 +588,44 @@ impl SimpleAsyncComponent for GeneralApp {
}, },
add = &adw::PreferencesGroup { 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(&gtk::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 { adw::ActionRow {
set_title: &tr("components"), set_title: &tr!("components"),
set_subtitle: &tr("components-description"), set_subtitle: &tr!("components-description"),
add_suffix = &gtk::Image { add_suffix = &gtk::Image {
set_icon_name: Some("go-next-symbolic") set_icon_name: Some("go-next-symbolic")
@ -590,10 +637,10 @@ impl SimpleAsyncComponent for GeneralApp {
}, },
adw::ExpanderRow { adw::ExpanderRow {
set_title: &tr("wine-tools"), set_title: &tr!("wine-tools"),
add_row = &adw::ActionRow { add_row = &adw::ActionRow {
set_title: &tr("command-line"), set_title: &tr!("command-line"),
set_subtitle: "wineconsole", set_subtitle: "wineconsole",
set_activatable: true, set_activatable: true,
@ -602,7 +649,7 @@ impl SimpleAsyncComponent for GeneralApp {
}, },
add_row = &adw::ActionRow { add_row = &adw::ActionRow {
set_title: &tr("registry-editor"), set_title: &tr!("registry-editor"),
set_subtitle: "regedit", set_subtitle: "regedit",
set_activatable: true, set_activatable: true,
@ -611,7 +658,7 @@ impl SimpleAsyncComponent for GeneralApp {
}, },
add_row = &adw::ActionRow { add_row = &adw::ActionRow {
set_title: &tr("explorer"), set_title: &tr!("explorer"),
set_subtitle: "explorer", set_subtitle: "explorer",
set_activatable: true, set_activatable: true,
@ -620,7 +667,7 @@ impl SimpleAsyncComponent for GeneralApp {
}, },
add_row = &adw::ActionRow { add_row = &adw::ActionRow {
set_title: &tr("task-manager"), set_title: &tr!("task-manager"),
set_subtitle: "taskmgr", set_subtitle: "taskmgr",
set_activatable: true, set_activatable: true,
@ -629,7 +676,7 @@ impl SimpleAsyncComponent for GeneralApp {
}, },
add_row = &adw::ActionRow { add_row = &adw::ActionRow {
set_title: &tr("configuration"), set_title: &tr!("configuration"),
set_subtitle: "winecfg", set_subtitle: "winecfg",
set_activatable: true, set_activatable: true,
@ -638,7 +685,7 @@ impl SimpleAsyncComponent for GeneralApp {
}, },
add_row = &adw::ActionRow { add_row = &adw::ActionRow {
set_title: &tr("debugger"), set_title: &tr!("debugger"),
set_subtitle: "start winedbg", set_subtitle: "start winedbg",
set_activatable: true, set_activatable: true,
@ -676,7 +723,7 @@ impl SimpleAsyncComponent for GeneralApp {
style: CONFIG.launcher.style, 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() { for package in VoiceLocale::list() {
@ -740,7 +787,7 @@ impl SimpleAsyncComponent for GeneralApp {
tracing::error!("Failed to delete voice package: {:?}", package.locale()); tracing::error!("Failed to delete voice package: {:?}", package.locale());
sender.input(GeneralAppMsg::Toast { sender.input(GeneralAppMsg::Toast {
title: tr("voice-package-deletion-error"), title: tr!("voice-package-deletion-error"),
description: Some(err.to_string()) description: Some(err.to_string())
}); });
} }
@ -808,7 +855,7 @@ impl SimpleAsyncComponent for GeneralApp {
tracing::error!("Failed to download background picture"); tracing::error!("Failed to download background picture");
sender.input(GeneralAppMsg::Toast { sender.input(GeneralAppMsg::Toast {
title: tr("background-downloading-failed"), title: tr!("background-downloading-failed"),
description: Some(err.to_string()) description: Some(err.to_string())
}); });
@ -840,9 +887,9 @@ impl SimpleAsyncComponent for GeneralApp {
if let Err(err) = result { if let Err(err) = result {
sender.input(GeneralAppMsg::Toast { sender.input(GeneralAppMsg::Toast {
title: tr_args("wine-run-error", [ title: tr!("wine-run-error", {
("executable", executable.join(" ").into()) "executable" = executable.join(" ")
]), }),
description: Some(err.to_string()) description: Some(err.to_string())
}); });

View file

@ -11,7 +11,7 @@ use anime_launcher_sdk::config::ConfigExt;
use anime_launcher_sdk::genshin::config::Config; use anime_launcher_sdk::genshin::config::Config;
use anime_launcher_sdk::genshin::config::schema::launcher::LauncherStyle; use anime_launcher_sdk::genshin::config::schema::launcher::LauncherStyle;
use crate::i18n::tr; use crate::tr;
use super::general::*; use super::general::*;
use super::enhancements::*; use super::enhancements::*;
@ -52,7 +52,7 @@ impl SimpleAsyncComponent for PreferencesApp {
view! { view! {
preferences_window = adw::PreferencesWindow { preferences_window = adw::PreferencesWindow {
set_title: Some(&tr("preferences")), set_title: Some(&tr!("preferences")),
set_default_size: (700, 560), set_default_size: (700, 560),
set_hide_on_close: true, set_hide_on_close: true,
@ -65,7 +65,7 @@ impl SimpleAsyncComponent for PreferencesApp {
connect_close_request[sender] => move |_| { connect_close_request[sender] => move |_| {
if let Err(err) = Config::flush() { if let Err(err) = Config::flush() {
sender.input(PreferencesAppMsg::Toast { sender.input(PreferencesAppMsg::Toast {
title: tr("config-update-error"), title: tr!("config-update-error"),
description: Some(err.to_string()) description: Some(err.to_string())
}); });
} }
@ -150,12 +150,12 @@ impl SimpleAsyncComponent for PreferencesApp {
toast.set_timeout(4); toast.set_timeout(4);
if let Some(description) = description { 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)); let dialog = adw::MessageDialog::new(PREFERENCES_WINDOW.as_ref(), Some(&title), Some(&description));
dialog.add_response("close", &tr("close")); dialog.add_response("close", &tr!("close", { "form" = "noun" }));
dialog.add_response("save", &tr("save")); dialog.add_response("save", &tr!("save"));
dialog.set_response_appearance("save", adw::ResponseAppearance::Suggested); dialog.set_response_appearance("save", adw::ResponseAppearance::Suggested);