mirror of
https://github.com/an-anime-team/an-anime-game-launcher.git
synced 2025-02-16 23:31:29 +03:00
commit
b7718d411c
55 changed files with 1093 additions and 355 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -1,3 +0,0 @@
|
|||
[submodule "anime-launcher-sdk"]
|
||||
path = anime-launcher-sdk
|
||||
url = https://github.com/an-anime-team/anime-launcher-sdk
|
24
CHANGELOG.md
24
CHANGELOG.md
|
@ -9,6 +9,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
### Added
|
||||
|
||||
- Added installation migration feature
|
||||
- Added game environment switcher
|
||||
- Added game edition switcher
|
||||
- Added changelog to updated components toast
|
||||
- Added wine tools to settings
|
||||
- Added preferences search
|
||||
- Added new progress bar statuses for applyign hdiff patches and removing outdated files
|
||||
- Added automatic 3.5 -> 3.6 voiceover files migration related to changed files structure
|
||||
|
||||
### Fixed
|
||||
|
||||
- Added whitespaces removing from environment values
|
||||
|
||||
### Changed
|
||||
|
||||
- Improved game repairing feature
|
||||
- Replaced `curl` dependency by native code
|
||||
- Replaced static image by spinner in wine / dxvk version selection
|
||||
- Made wine / dxvk versions always visible if they're downloaded
|
||||
|
||||
## [3.3.0] - 24.03.2023
|
||||
|
||||
### Added
|
||||
|
||||
- Added option to use additional xlua patch
|
||||
- Added menu option to open wishes history url
|
||||
|
||||
|
|
253
Cargo.lock
generated
253
Cargo.lock
generated
|
@ -2,6 +2,15 @@
|
|||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97"
|
||||
dependencies = [
|
||||
"gimli",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "adler"
|
||||
version = "1.0.2"
|
||||
|
@ -31,17 +40,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "anime-game-core"
|
||||
version = "1.4.5"
|
||||
version = "1.6.1"
|
||||
source = "git+https://github.com/an-anime-team/anime-game-core?tag=1.6.1#2396d1e6538523c0ea1da2f9e75469fff035e44e"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bzip2",
|
||||
"cached",
|
||||
"curl",
|
||||
"flate2",
|
||||
"fs_extra",
|
||||
"kinda-virtual-fs",
|
||||
"lazy_static",
|
||||
"md-5",
|
||||
"minreq",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sysinfo",
|
||||
|
@ -54,7 +64,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "anime-game-launcher"
|
||||
version = "3.3.0"
|
||||
version = "3.4.0"
|
||||
dependencies = [
|
||||
"anime-launcher-sdk",
|
||||
"anyhow",
|
||||
|
@ -76,12 +86,12 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "anime-launcher-sdk"
|
||||
version = "0.5.7"
|
||||
version = "0.5.16"
|
||||
source = "git+https://github.com/an-anime-team/anime-launcher-sdk?tag=0.5.16#a36215db4613ba284d8b2215ec822df64ce73404"
|
||||
dependencies = [
|
||||
"anime-game-core",
|
||||
"anyhow",
|
||||
"cached",
|
||||
"dirs 5.0.0",
|
||||
"discord-rich-presence",
|
||||
"enum-ordinalize",
|
||||
"lazy_static",
|
||||
|
@ -97,6 +107,9 @@ name = "anyhow"
|
|||
version = "1.0.70"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arc-swap"
|
||||
|
@ -224,10 +237,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.13.1"
|
||||
name = "backtrace"
|
||||
version = "0.3.67"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
|
||||
checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca"
|
||||
dependencies = [
|
||||
"addr2line",
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"miniz_oxide",
|
||||
"object",
|
||||
"rustc-demangle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.21.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a"
|
||||
|
||||
[[package]]
|
||||
name = "base64ct"
|
||||
|
@ -410,6 +438,16 @@ version = "0.1.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.3"
|
||||
|
@ -487,37 +525,6 @@ dependencies = [
|
|||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "curl"
|
||||
version = "0.4.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "509bd11746c7ac09ebd19f0b17782eae80aadee26237658a6b4808afb5c11a22"
|
||||
dependencies = [
|
||||
"curl-sys",
|
||||
"libc",
|
||||
"openssl-probe",
|
||||
"openssl-sys",
|
||||
"schannel",
|
||||
"socket2",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "curl-sys"
|
||||
version = "0.4.60+curl-7.88.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "717abe2cb465a5da6ce06617388a3980c9a2844196734bec8ccb8e575250f13f"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"libz-sys",
|
||||
"openssl-sys",
|
||||
"pkg-config",
|
||||
"rustls-ffi",
|
||||
"vcpkg",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.14.4"
|
||||
|
@ -581,16 +588,7 @@ version = "4.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059"
|
||||
dependencies = [
|
||||
"dirs-sys 0.3.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs"
|
||||
version = "5.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dece029acd3353e3a58ac2e3eb3c8d6c35827a892edc6cc4138ef9c33df46ecd"
|
||||
dependencies = [
|
||||
"dirs-sys 0.4.0",
|
||||
"dirs-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -604,17 +602,6 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-sys"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04414300db88f70d74c5ff54e50f9e1d1737d9a5b90f53fcf2e95ca2a9ab554b"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"redox_users",
|
||||
"windows-sys 0.45.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "discord-rich-presence"
|
||||
version = "0.2.3"
|
||||
|
@ -1060,6 +1047,12 @@ dependencies = [
|
|||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.27.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4"
|
||||
|
||||
[[package]]
|
||||
name = "gio"
|
||||
version = "0.17.4"
|
||||
|
@ -1479,18 +1472,6 @@ version = "0.2.140"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
|
||||
|
||||
[[package]]
|
||||
name = "libz-sys"
|
||||
version = "1.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9702761c3935f8cc2f101793272e202c72b99da8f4224a19ddcf1279a6450bbf"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.1.4"
|
||||
|
@ -1588,6 +1569,22 @@ dependencies = [
|
|||
"adler",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "minreq"
|
||||
version = "2.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41979ac2a5aa373c6e294b4a67fbe5e428e91a4cd0524376681f2bc6d872399b"
|
||||
dependencies = [
|
||||
"log",
|
||||
"once_cell",
|
||||
"rustls",
|
||||
"rustls-native-certs",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"webpki",
|
||||
"webpki-roots",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nanorand"
|
||||
version = "0.7.0"
|
||||
|
@ -1669,27 +1666,6 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_enum"
|
||||
version = "0.5.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9"
|
||||
dependencies = [
|
||||
"num_enum_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_enum_derive"
|
||||
version = "0.5.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799"
|
||||
dependencies = [
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc"
|
||||
version = "0.2.7"
|
||||
|
@ -1719,6 +1695,15 @@ dependencies = [
|
|||
"objc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.30.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.17.1"
|
||||
|
@ -1733,9 +1718,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
|||
|
||||
[[package]]
|
||||
name = "open"
|
||||
version = "4.0.0"
|
||||
version = "4.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd61e3bf9d78956c72ee864bba52431f7f43994b21a17e9e72596a81bd61075b"
|
||||
checksum = "075c5203b3a2b698bc72c6c10b1f6263182135751d5013ea66e8a4b3d0562a43"
|
||||
dependencies = [
|
||||
"pathdiff",
|
||||
]
|
||||
|
@ -1746,19 +1731,6 @@ version = "0.1.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
|
||||
|
||||
[[package]]
|
||||
name = "openssl-sys"
|
||||
version = "0.9.81"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "176be2629957c157240f68f61f2d0053ad3a4ecfdd9ebf1e6521d18d9635cf67"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cc",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ordered-stream"
|
||||
version = "0.0.1"
|
||||
|
@ -2145,6 +2117,12 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4a36c42d1873f9a77c53bde094f9664d9891bc604a45b4798fd2c389ed12e5b"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "1.1.0"
|
||||
|
@ -2187,25 +2165,22 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-ffi"
|
||||
version = "0.8.2"
|
||||
name = "rustls-native-certs"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9da52707cca59e6eef8a78f3ad8d04024254a168ed1b41eb4dfa9616eace781a"
|
||||
checksum = "0167bac7a9f490495f3c33013e7722b53cb087ecbe082fb0c6387c96f634ea50"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"num_enum",
|
||||
"rustls",
|
||||
"openssl-probe",
|
||||
"rustls-pemfile",
|
||||
"sct",
|
||||
"webpki",
|
||||
"schannel",
|
||||
"security-framework",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-pemfile"
|
||||
version = "0.2.1"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5eebeaeb360c87bfb72e84abdb3447159c0eaececf1bef2aecd65a8be949d1c9"
|
||||
checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b"
|
||||
dependencies = [
|
||||
"base64",
|
||||
]
|
||||
|
@ -2250,6 +2225,29 @@ dependencies = [
|
|||
"untrusted",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "security-framework"
|
||||
version = "2.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"core-foundation",
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
"security-framework-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "security-framework-sys"
|
||||
version = "2.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "self_cell"
|
||||
version = "0.10.2"
|
||||
|
@ -2768,12 +2766,6 @@ version = "0.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
||||
|
||||
[[package]]
|
||||
name = "version-compare"
|
||||
version = "0.1.1"
|
||||
|
@ -2894,6 +2886,15 @@ dependencies = [
|
|||
"untrusted",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webpki-roots"
|
||||
version = "0.22.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87"
|
||||
dependencies = [
|
||||
"webpki",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
|
@ -3073,7 +3074,7 @@ dependencies = [
|
|||
"async-trait",
|
||||
"byteorder",
|
||||
"derivative",
|
||||
"dirs 4.0.0",
|
||||
"dirs",
|
||||
"enumflags2",
|
||||
"event-listener",
|
||||
"futures-core",
|
||||
|
|
13
Cargo.toml
13
Cargo.toml
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "anime-game-launcher"
|
||||
version = "3.3.0"
|
||||
version = "3.4.0"
|
||||
description = "Anime Game launcher"
|
||||
authors = ["Nikita Podvirnyy <suimin.tu.mu.ga.mi@gmail.com>"]
|
||||
license = "GPL-3.0"
|
||||
|
@ -15,14 +15,19 @@ opt-level = "s"
|
|||
[build-dependencies]
|
||||
glib-build-tools = "0.17"
|
||||
|
||||
[dependencies.anime-launcher-sdk]
|
||||
git = "https://github.com/an-anime-team/anime-launcher-sdk"
|
||||
tag = "0.5.16"
|
||||
|
||||
# path = "../anime-launcher-sdk" # ! for dev purposes only
|
||||
|
||||
[dependencies]
|
||||
relm4 = { version = "0.6.0-alpha.2", features = ["macros", "libadwaita"] }
|
||||
gtk = { package = "gtk4", version = "0.6", features = ["v4_8"] }
|
||||
adw = { package = "libadwaita", version = "0.3", features = ["v1_2"] }
|
||||
rfd = { version = "0.11", features = ["xdg-portal"], default-features = false }
|
||||
open = "4.0.0"
|
||||
|
||||
anime-launcher-sdk = { path = "anime-launcher-sdk" }
|
||||
rfd = { version = "0.11", features = ["xdg-portal"], default-features = false }
|
||||
open = "4.0"
|
||||
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = "0.3"
|
||||
|
|
|
@ -55,7 +55,6 @@ This should be automatically enabled if you're using zh_cn (Chinese) as your sys
|
|||
|
||||
| Folder | Description |
|
||||
| - | - |
|
||||
| anime-launcher-sdk | Unified core functionality for the launcher |
|
||||
| src | Rust source code |
|
||||
| assets | App assets folder |
|
||||
| assets/locales | App localizations |
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
Subproject commit 19ceddca82367514b5c806cfbc94f527ccd75167
|
|
@ -6,6 +6,8 @@ debug-file-opening-error = Debug-Datei konnte nicht geöffnet werden
|
|||
wish-url-search-failed = Kein Wünsche URL gefunden
|
||||
wish-url-opening-error = Wünsche URL konnte nicht geöffnet werden
|
||||
|
||||
wine-run-error = Failed to run {$executable} executable using wine
|
||||
|
||||
game-launching-failed = Spiel konnte nicht gestartet werden
|
||||
failed-get-selected-wine = Die ausgewählte Wine version konnte nicht abgerufen werden.
|
||||
downloading-failed = Herunterladen fehlgeschlagen
|
||||
|
|
|
@ -36,12 +36,15 @@ show-all-folders-subtitle = Zusätzliche Pfadauswahl-Einstellungen anzeigen. Tu
|
|||
runners-folder = Runners-Ordner
|
||||
dxvks-folder = DXVKs-Ordner
|
||||
wine-prefix-folder = Wine prefix-Ordner
|
||||
game-installation-folder = Spiel-Installationsordner
|
||||
global-game-installation-folder = Global game version installation folder
|
||||
chinese-game-installation-folder = Chinese game version installation folder
|
||||
fps-unlocker-folder = FPS Unlocker Ordner
|
||||
components-index = Komponentenverzeichnis
|
||||
patch-folder = Patch-Ordner
|
||||
temp-folder = Temp-Ordner
|
||||
|
||||
migrate = Migrate
|
||||
|
||||
|
||||
select-voice-packages = Sprachpakete auswählen
|
||||
|
||||
|
|
|
@ -7,12 +7,22 @@ update-background-description = Lädt das offizielle Hintergrundbild herunter f
|
|||
launcher-language = Launcher Sprache
|
||||
launcher-language-description = Gilt nach Neustart
|
||||
|
||||
game-edition = Game edition
|
||||
global = Global
|
||||
china = China
|
||||
|
||||
game-environment = Game environment
|
||||
game-environment-description = Get specific features like additional payment methods
|
||||
|
||||
game-voiceovers = Spiel Sprachen
|
||||
game-voiceovers-description = List of downloaded game voiceovers. You can select them in the game settings
|
||||
english = Englisch
|
||||
japanese = Japanisch
|
||||
korean = Koreanisch
|
||||
chinese = Chinesisch
|
||||
|
||||
migrate-installation = Migrate installation
|
||||
migrate-installation-description = Open special window where you can change your game installation folder
|
||||
repair-game = Spiel Reparieren
|
||||
|
||||
status = Status
|
||||
|
@ -53,6 +63,13 @@ recommended-only = Nur empfohlene
|
|||
wine-version = Wine version
|
||||
wine-recommended-description = Nur empfohlene wine versionen anzeigen
|
||||
|
||||
wine-tools = Wine tools
|
||||
command-line = Command line
|
||||
registry-editor = Registry editor
|
||||
explorer = Explorer
|
||||
task-manager = Task manager
|
||||
configuration = Configuration
|
||||
|
||||
dxvk-version = DXVK version
|
||||
dxvk-selection-disabled = DXVK auswahl ist durch ihre Wine auswahl deaktiviert
|
||||
dxvk-recommended-description = Nur empfohlene dxvk versionen anzeigen
|
||||
|
|
|
@ -40,12 +40,17 @@ downloading = Lade Herunter
|
|||
unpacking = Entpacken
|
||||
verifying-files = Verifiziere Dateien
|
||||
repairing-files = Repariere Dateien
|
||||
migrating-folders = Migrating folders
|
||||
applying-hdiff = Applying hdiff patches
|
||||
removing-outdated = Removing outdated files
|
||||
|
||||
|
||||
components-index-updated = Kompontentenverzeichnis würde aktualisiert
|
||||
|
||||
|
||||
launch = Starten
|
||||
migrate-folders = Migrate folders
|
||||
migrate-folders-tooltip = Update game folders structure
|
||||
apply-patch = Patch anwenden
|
||||
download-wine = Wine Herunterladen
|
||||
create-prefix = Prefix erstellen
|
||||
|
|
|
@ -6,6 +6,8 @@ debug-file-opening-error = Failed to open debug file
|
|||
wish-url-search-failed = No wishes url found
|
||||
wish-url-opening-error = Could not open wishes url
|
||||
|
||||
wine-run-error = Failed to run {$executable} executable using wine
|
||||
|
||||
game-launching-failed = Failed to launch game
|
||||
failed-get-selected-wine = Failed to get selected wine version
|
||||
downloading-failed = Downloading failed
|
||||
|
|
|
@ -36,12 +36,15 @@ show-all-folders-subtitle = Show additional path selection settings. Do as I say
|
|||
runners-folder = Runners folder
|
||||
dxvks-folder = DXVKs folder
|
||||
wine-prefix-folder = Wine prefix folder
|
||||
game-installation-folder = Game installation folder
|
||||
global-game-installation-folder = Global game version installation folder
|
||||
chinese-game-installation-folder = Chinese game version installation folder
|
||||
fps-unlocker-folder = FPS Unlocker folder
|
||||
components-index = Components index
|
||||
patch-folder = Patch folder
|
||||
temp-folder = Temp folder
|
||||
|
||||
migrate = Migrate
|
||||
|
||||
|
||||
select-voice-packages = Select voice packages
|
||||
|
||||
|
|
|
@ -7,12 +7,22 @@ update-background-description = Download official background picture for the lau
|
|||
launcher-language = Launcher language
|
||||
launcher-language-description = Applies after restart
|
||||
|
||||
game-edition = Game edition
|
||||
global = Global
|
||||
china = China
|
||||
|
||||
game-environment = Game environment
|
||||
game-environment-description = Get specific features like additional payment methods
|
||||
|
||||
game-voiceovers = Game voiceovers
|
||||
game-voiceovers-description = List of downloaded game voiceovers. You can select them in the game settings
|
||||
english = English
|
||||
japanese = Japanese
|
||||
korean = Korean
|
||||
chinese = Chinese
|
||||
|
||||
migrate-installation = Migrate installation
|
||||
migrate-installation-description = Open special window where you can change your game installation folder
|
||||
repair-game = Repair game
|
||||
|
||||
status = Status
|
||||
|
@ -53,6 +63,13 @@ recommended-only = Recommended only
|
|||
wine-version = Wine version
|
||||
wine-recommended-description = Show only recommended wine versions
|
||||
|
||||
wine-tools = Wine tools
|
||||
command-line = Command line
|
||||
registry-editor = Registry editor
|
||||
explorer = Explorer
|
||||
task-manager = Task manager
|
||||
configuration = Configuration
|
||||
|
||||
dxvk-version = DXVK version
|
||||
dxvk-selection-disabled = DXVK selection is disabled by your wine group preferences
|
||||
dxvk-recommended-description = Show only recommended dxvk versions
|
||||
|
|
|
@ -40,12 +40,17 @@ downloading = Downloading
|
|||
unpacking = Unpacking
|
||||
verifying-files = Verifying files
|
||||
repairing-files = Repairing files
|
||||
migrating-folders = Migrating folders
|
||||
applying-hdiff = Applying hdiff patches
|
||||
removing-outdated = Removing outdated files
|
||||
|
||||
|
||||
components-index-updated = Components index was updated
|
||||
|
||||
|
||||
launch = Launch
|
||||
migrate-folders = Migrate folders
|
||||
migrate-folders-tooltip = Update game folders structure
|
||||
apply-patch = Apply patch
|
||||
download-wine = Download wine
|
||||
create-prefix = Create prefix
|
||||
|
|
|
@ -6,6 +6,8 @@ debug-file-opening-error = Fallo al abrir el archivo de debug
|
|||
wish-url-search-failed = No se encontró la URL del historial de deseos
|
||||
wish-url-opening-error = No se pudo abrir la URL del historial de deseos
|
||||
|
||||
wine-run-error = Fallo al correr el ejecutable {$executable} usando Wine
|
||||
|
||||
game-launching-failed = Fallo al iniciar el juego
|
||||
failed-get-selected-wine = Fallo al buscar la versión elegida de Wine
|
||||
downloading-failed = Descarga fallida
|
||||
|
|
|
@ -36,12 +36,15 @@ show-all-folders-subtitle = Muestra opciones de selección de rutas adicionales.
|
|||
runners-folder = Carpeta de runners
|
||||
dxvks-folder = Carpeta de DXVKs
|
||||
wine-prefix-folder = Carpeta de prefijo de Wine
|
||||
game-installation-folder = Carpeta de instalación del juego
|
||||
global-game-installation-folder = Carpeta de instalación de la edición Global
|
||||
chinese-game-installation-folder = Carpeta de instalación de la edición China
|
||||
fps-unlocker-folder = Carpeta del liberador de FPS
|
||||
components-index = Índice de componentes
|
||||
patch-folder = Carpeta del parche
|
||||
temp-folder = Carpeta temporal
|
||||
|
||||
migrate = Migrar
|
||||
|
||||
|
||||
select-voice-packages = Elegir paquetes de voz
|
||||
|
||||
|
|
|
@ -7,12 +7,22 @@ update-background-description = Descarga la imagen de fondo oficial para el laun
|
|||
launcher-language = Idioma del launcher
|
||||
launcher-language-description = Se aplica tras un reinicio.
|
||||
|
||||
game-edition = Edición del Juego
|
||||
global = Global
|
||||
china = China
|
||||
|
||||
game-environment = Entorno del juego
|
||||
game-environment-description = Da acceso a funciones específicas como medios de pago adicionales
|
||||
|
||||
game-voiceovers = Voces del juego
|
||||
game-voiceovers-description = Lista de voces del juego descargadas. Puedes elegirlas en las opciones del juego
|
||||
english = Inglés
|
||||
japanese = Japonés
|
||||
korean = Coreano
|
||||
chinese = Chino
|
||||
|
||||
migrate-installation = Migrar instalación
|
||||
migrate-installation-description = Abre una ventana especial donde puedes cambiar tu carpeta de instalación del juego
|
||||
repair-game = Reparar juego
|
||||
|
||||
status = Estado
|
||||
|
@ -53,6 +63,13 @@ recommended-only = Sólo recomendadas
|
|||
wine-version = Versión de Wine
|
||||
wine-recommended-description = Mostrar sólo versiones recomendadas de Wine
|
||||
|
||||
wine-tools = Herramientas de Wine
|
||||
command-line = Línea de Comandos
|
||||
registry-editor = Editor del Registro
|
||||
explorer = Explorador
|
||||
task-manager = Administrador de Tareas
|
||||
configuration = Configuración
|
||||
|
||||
dxvk-version = Versión de DXVK
|
||||
dxvk-selection-disabled = La selección de DXVK está deshabilitada por las preferencias de su grupo de vinos
|
||||
dxvk-recommended-description = Mostrar sólo versiones recomendadas de DXVK
|
||||
|
|
|
@ -40,12 +40,17 @@ downloading = Descargando
|
|||
unpacking = Descomprimiendo
|
||||
verifying-files = Verificación de archivos
|
||||
repairing-files = Reparación de archivos
|
||||
migrating-folders = Migrating folders
|
||||
applying-hdiff = Applying hdiff patches
|
||||
removing-outdated = Removing outdated files
|
||||
|
||||
|
||||
components-index-updated = Se actualizó el índice de componentes
|
||||
|
||||
|
||||
launch = Iniciar
|
||||
migrate-folders = Migrate folders
|
||||
migrate-folders-tooltip = Update game folders structure
|
||||
apply-patch = Aplicar parche
|
||||
download-wine = Descargar wine
|
||||
create-prefix = Crear prefijo
|
||||
|
|
|
@ -6,6 +6,8 @@ debug-file-opening-error = Impossible d'ouvrir le fichier débug
|
|||
wish-url-search-failed = No wishes url found
|
||||
wish-url-opening-error = Could not open wishes url
|
||||
|
||||
wine-run-error = Failed to run {$executable} executable using wine
|
||||
|
||||
game-launching-failed = Impossible de lancer le jeu
|
||||
failed-get-selected-wine = Impossible de récupérer la version de wine sélectionnée
|
||||
downloading-failed = Le téléchargement a échoué
|
||||
|
|
|
@ -36,12 +36,15 @@ show-all-folders-subtitle = Afficher plus de paramètres de sélection d'emplace
|
|||
runners-folder = Emplacement des runners
|
||||
dxvks-folder = Emplacement des versions de DXVK
|
||||
wine-prefix-folder = Emplacement du préfix wine
|
||||
game-installation-folder = Emplacement d'installation du jeu
|
||||
global-game-installation-folder = Global game version installation folder
|
||||
chinese-game-installation-folder = Chinese game version installation folder
|
||||
fps-unlocker-folder = Emplacement des fichiers du débloqueur de FPS
|
||||
components-index = Indice des composants
|
||||
patch-folder = Emplacement du patch
|
||||
temp-folder = Dossier temporaire
|
||||
|
||||
migrate = Migrate
|
||||
|
||||
|
||||
select-voice-packages = Sélectionnez les packs de voix
|
||||
|
||||
|
|
|
@ -7,12 +7,22 @@ update-background-description = Télécharger l'image de fond du launcher offici
|
|||
launcher-language = Langue du launcher
|
||||
launcher-language-description = S'applique après un redémarrage
|
||||
|
||||
game-edition = Game edition
|
||||
global = Global
|
||||
china = China
|
||||
|
||||
game-environment = Game environment
|
||||
game-environment-description = Get specific features like additional payment methods
|
||||
|
||||
game-voiceovers = Voiceover en jeu
|
||||
game-voiceovers-description = List of downloaded game voiceovers. You can select them in the game settings
|
||||
english = Anglais
|
||||
japanese = Japonais
|
||||
korean = Coréen
|
||||
chinese = Chinois
|
||||
|
||||
migrate-installation = Migrate installation
|
||||
migrate-installation-description = Open special window where you can change your game installation folder
|
||||
repair-game = Réparer le jeu
|
||||
|
||||
status = Statut
|
||||
|
@ -53,6 +63,13 @@ recommended-only = Versions recommandées uniquement
|
|||
wine-version = Version de wine
|
||||
wine-recommended-description = N'afficher que les versions recommandées de wine
|
||||
|
||||
wine-tools = Wine tools
|
||||
command-line = Command line
|
||||
registry-editor = Registry editor
|
||||
explorer = Explorer
|
||||
task-manager = Task manager
|
||||
configuration = Configuration
|
||||
|
||||
dxvk-version = Version de DXVK
|
||||
dxvk-selection-disabled = La sélection de versions DXVK est désactivé par vos préférences de groupe wine
|
||||
dxvk-recommended-description = N'afficher que les versions recommandées de DXVK
|
||||
|
|
|
@ -40,12 +40,17 @@ downloading = Téléchargement
|
|||
unpacking = Décompression
|
||||
verifying-files = Vérification des fichiers
|
||||
repairing-files = Réparation des fichiers
|
||||
migrating-folders = Migrating folders
|
||||
applying-hdiff = Applying hdiff patches
|
||||
removing-outdated = Removing outdated files
|
||||
|
||||
|
||||
components-index-updated = L'index des composants a été mis à jour
|
||||
|
||||
|
||||
launch = Lancer
|
||||
migrate-folders = Migrate folders
|
||||
migrate-folders-tooltip = Update game folders structure
|
||||
apply-patch = Appliquer le patch
|
||||
download-wine = Télécharger wine
|
||||
create-prefix = Créer le préfix wine
|
||||
|
|
|
@ -6,6 +6,8 @@ debug-file-opening-error = Не удалось открыть файл отла
|
|||
wish-url-search-failed = Ссылка на историю молитв не найдена
|
||||
wish-url-opening-error = Не удалось открыть ссылку с историей молитв
|
||||
|
||||
wine-run-error = Не удалось запустить {$executable} используя Wine
|
||||
|
||||
game-launching-failed = Не удалось запустить игру
|
||||
failed-get-selected-wine = Не удалось найти выбранную версию Wine
|
||||
downloading-failed = Ошибка загрузки
|
||||
|
|
|
@ -38,12 +38,15 @@ show-all-folders-subtitle = Отобразить дополнительные о
|
|||
runners-folder = Папка версий Wine
|
||||
dxvks-folder = Папка версий DXVK
|
||||
wine-prefix-folder = Папка префикса Wine
|
||||
game-installation-folder = Путь установки игры
|
||||
global-game-installation-folder = Путь установки глобальной версии игры
|
||||
chinese-game-installation-folder = Путь установки китайской версии игры
|
||||
fps-unlocker-folder = Папка FPS Unlocker
|
||||
components-index = Индекс компонентов
|
||||
patch-folder = Папка скачивания патча
|
||||
temp-folder = Временная папка
|
||||
|
||||
migrate = Перенести
|
||||
|
||||
|
||||
select-voice-packages = Выбрать языковые пакеты
|
||||
|
||||
|
|
|
@ -7,12 +7,22 @@ update-background-description = Скачивать фоновое изображ
|
|||
launcher-language = Язык лаунчера
|
||||
launcher-language-description = Применяется после перезапуска
|
||||
|
||||
game-edition = Редакция игры
|
||||
global = Глобальная
|
||||
china = Китайская
|
||||
|
||||
game-environment = Окружение игры
|
||||
game-environment-description = Получить особые функции такие как дополнительные методы оплаты
|
||||
|
||||
game-voiceovers = Язык озвучки
|
||||
game-voiceovers-description = Список установленных озвучек игры. Вы можете выбрать их в настройках игры
|
||||
english = Английский
|
||||
japanese = Японский
|
||||
korean = Корейский
|
||||
chinese = Китайский
|
||||
|
||||
migrate-installation = Перенести лаунчер
|
||||
migrate-installation-description = Открыть специальное окно в котором вы сможете перенести установленную игру
|
||||
repair-game = Починить игру
|
||||
|
||||
status = Статус
|
||||
|
@ -45,7 +55,7 @@ patch-not-applied-tooltip = Патч не применен
|
|||
apply-xlua-patch = Применить патч xlua
|
||||
|
||||
ask-superuser-permissions = Запрашивать права суперпользователя
|
||||
ask-superuser-permissions-description = Лаунчер будет использовать их чтобы автоматически обновлять ваш hosts файл. Это не требуется при использовании Flatpak
|
||||
ask-superuser-permissions-description = Лаунчер будет использовать их чтобы автоматически обновлять ваш hosts файл. Это не требуется при использовании flatpak
|
||||
|
||||
selected-version = Выбранная версия
|
||||
recommended-only = Только рекомендуемое
|
||||
|
@ -53,6 +63,13 @@ recommended-only = Только рекомендуемое
|
|||
wine-version = Версия Wine
|
||||
wine-recommended-description = Показывать только рекомендуемые версии Wine
|
||||
|
||||
wine-tools = Инструменты Wine
|
||||
command-line = Коммандная строка
|
||||
registry-editor = Редактор реестра
|
||||
explorer = Проводник
|
||||
task-manager = Диспетчер задач
|
||||
configuration = Настройки
|
||||
|
||||
dxvk-version = Версия DXVK
|
||||
dxvk-selection-disabled = Выбор версии DXVK отключен настройками выбранного вами Wine
|
||||
dxvk-recommended-description = Показывать только рекомендуемые версии DXVK
|
||||
|
|
|
@ -46,12 +46,17 @@ downloading = Загрузка
|
|||
unpacking = Распаковка
|
||||
verifying-files = Проверка файлов
|
||||
repairing-files = Починка файлов
|
||||
migrating-folders = Перемещение папок
|
||||
applying-hdiff = Применение патчей hdiff
|
||||
removing-outdated = Удаление устаревших файлов
|
||||
|
||||
|
||||
components-index-updated = Индекс компонентов был обновлен
|
||||
|
||||
|
||||
launch = Запустить
|
||||
migrate-folders = Переместить папки
|
||||
migrate-folders-tooltip = Обновить структуру файлов игры
|
||||
apply-patch = Применить патч
|
||||
download-wine = Установить Wine
|
||||
create-prefix = Создать префикс
|
||||
|
|
|
@ -6,6 +6,8 @@ debug-file-opening-error = Debug dosyasını açma başarısız oldu
|
|||
wish-url-search-failed = Dilekler urlsi bulunamadı
|
||||
wish-url-opening-error = Dilekler urlsi açılamadı
|
||||
|
||||
wine-run-error = Failed to run {$executable} executable using wine
|
||||
|
||||
game-launching-failed = Oyunu açma başarısız oldu
|
||||
failed-get-selected-wine = Seçilen Wine versiyonunu alma başarısız oldu
|
||||
downloading-failed = İndirme başarısız oldu
|
||||
|
|
|
@ -36,12 +36,15 @@ show-all-folders-subtitle = Ek yol seçimi ayarlarını göster. Dediğimi yap..
|
|||
runners-folder = Başlatıcılar(Runnerlar) klasörü
|
||||
dxvks-folder = DXVKnın klasörü
|
||||
wine-prefix-folder = Wine prefixnin klasörü
|
||||
game-installation-folder = Oyunun indrildiği klasör
|
||||
global-game-installation-folder = Global game version installation folder
|
||||
chinese-game-installation-folder = Chinese game version installation folder
|
||||
fps-unlocker-folder = FPS Unlocker folder
|
||||
components-index = Bileşenlerin dizini
|
||||
patch-folder = Yama klasörü
|
||||
temp-folder = "Geçici" klasörü
|
||||
|
||||
migrate = Migrate
|
||||
|
||||
|
||||
select-voice-packages = Ses paketlerini seç
|
||||
|
||||
|
|
|
@ -7,12 +7,22 @@ update-background-description = İstemci için resmi arka plan resmini indirin.
|
|||
launcher-language = İstemci dili
|
||||
launcher-language-description = Restart attıktan sonra uygulanır
|
||||
|
||||
game-edition = Game edition
|
||||
global = Global
|
||||
china = China
|
||||
|
||||
game-environment = Game environment
|
||||
game-environment-description = Get specific features like additional payment methods
|
||||
|
||||
game-voiceovers = Oyun içi sesler
|
||||
game-voiceovers-description = List of downloaded game voiceovers. You can select them in the game settings
|
||||
english = İngilizce
|
||||
japanese = Japonca
|
||||
korean = Korece
|
||||
chinese = Çince
|
||||
|
||||
migrate-installation = Migrate installation
|
||||
migrate-installation-description = Open special window where you can change your game installation folder
|
||||
repair-game = Oyunu tamir et
|
||||
|
||||
status = Durum
|
||||
|
@ -53,6 +63,13 @@ recommended-only = Sadece önerilenler
|
|||
wine-version = Wine versiyonu
|
||||
wine-recommended-description = Sadece önerilen wine versiyonlarını göster
|
||||
|
||||
wine-tools = Wine tools
|
||||
command-line = Command line
|
||||
registry-editor = Registry editor
|
||||
explorer = Explorer
|
||||
task-manager = Task manager
|
||||
configuration = Configuration
|
||||
|
||||
dxvk-version = DXVK versiyonu
|
||||
dxvk-selection-disabled = DXVK özelliği Wine grup tercihleriniz yüzünden devre dışı
|
||||
dxvk-recommended-description = Sadece önerilen dxvk versiyonlarını göster
|
||||
|
|
|
@ -40,12 +40,17 @@ downloading = İndiriliyor
|
|||
unpacking = Paketten çıkartılıyor
|
||||
verifying-files = Dosyalar Doğrulanıyor
|
||||
repairing-files = Dosyalar tamir ediliyor
|
||||
migrating-folders = Migrating folders
|
||||
applying-hdiff = Applying hdiff patches
|
||||
removing-outdated = Removing outdated files
|
||||
|
||||
|
||||
components-index-updated = Components index was updated
|
||||
|
||||
|
||||
launch = Çalıştır
|
||||
migrate-folders = Migrate folders
|
||||
migrate-folders-tooltip = Update game folders structure
|
||||
apply-patch = Yamayı uygula
|
||||
download-wine = Wine indir
|
||||
create-prefix = Prefix oluştur
|
||||
|
|
|
@ -3,8 +3,10 @@ game-folder-opening-error = 打开游戏文件夹失败
|
|||
config-file-opening-error = 打开配置文件失败
|
||||
debug-file-opening-error = 打开调试文件失败
|
||||
|
||||
wish-url-search-failed = No wishes url found
|
||||
wish-url-opening-error = Could not open wishes url
|
||||
wish-url-search-failed = 找不到祈愿 URL
|
||||
wish-url-opening-error = 无法转到祈愿 URL
|
||||
|
||||
wine-run-error = Failed to run {$executable} executable using wine
|
||||
|
||||
game-launching-failed = 启动游戏失败
|
||||
failed-get-selected-wine = 选择 Wine 版本失败
|
||||
|
|
|
@ -36,12 +36,15 @@ show-all-folders-subtitle = 显示额外的路径选项。按我说的做...
|
|||
runners-folder = 运行程序文件夹
|
||||
dxvks-folder = DXVK 文件夹
|
||||
wine-prefix-folder = Wine prefix 文件夹
|
||||
game-installation-folder = 游戏安装文件夹
|
||||
fps-unlocker-folder = FPS Unlocker folder
|
||||
global-game-installation-folder = Global game version installation folder
|
||||
chinese-game-installation-folder = Chinese game version installation folder
|
||||
fps-unlocker-folder = FPS Unlocker 文件夹
|
||||
components-index = 成分指数
|
||||
patch-folder = 补丁文件夹
|
||||
temp-folder = 临时文件夹
|
||||
|
||||
migrate = Migrate
|
||||
|
||||
|
||||
select-voice-packages = 选择语音包
|
||||
|
||||
|
|
|
@ -7,12 +7,22 @@ update-background-description = 下载官方启动器背景图片。你可以关
|
|||
launcher-language = 启动器语言
|
||||
launcher-language-description = 重启后生效
|
||||
|
||||
game-edition = Game edition
|
||||
global = Global
|
||||
china = China
|
||||
|
||||
game-environment = Game environment
|
||||
game-environment-description = Get specific features like additional payment methods
|
||||
|
||||
game-voiceovers = 游戏语音
|
||||
game-voiceovers-description = List of downloaded game voiceovers. You can select them in the game settings
|
||||
english = 英语
|
||||
japanese = 日语
|
||||
korean = 韩语
|
||||
chinese = 汉语
|
||||
|
||||
migrate-installation = Migrate installation
|
||||
migrate-installation-description = Open special window where you can change your game installation folder
|
||||
repair-game = 修复游戏
|
||||
|
||||
status = 状态
|
||||
|
@ -24,11 +34,11 @@ game-predownload-available = 可以预下载游戏更新: {$old} -> {$new}
|
|||
game-update-available = 游戏版本更新: {$old} -> {$new}
|
||||
game-outdated = 游戏版本过旧,无法更新。最新版本: {$latest}
|
||||
|
||||
player-patch-version = Player patch version
|
||||
player-patch-version-description = Main patch that lets you play the game on Linux
|
||||
player-patch-version = 主补丁版本
|
||||
player-patch-version-description = UnitPlayer.dll 的补丁,在 Linux 上运行游戏必备
|
||||
|
||||
xlua-patch-version = Xlua patch version
|
||||
xlua-patch-version-description = Additional patch that fixes some issues and improves performance on low-end PCs
|
||||
xlua-patch-version = xLua 补丁版本
|
||||
xlua-patch-version-description = 额外的补丁,用于修复某些问题以及改善低端 PC 的游戏性能
|
||||
|
||||
patch-not-available = 不可用
|
||||
patch-not-available-tooltip = 无法连接补丁服务器
|
||||
|
@ -40,12 +50,12 @@ patch-preparation = 开发中
|
|||
patch-preparation-tooltip = 补丁还在开发中
|
||||
|
||||
patch-testing-tooltip = 有测试版补丁可用
|
||||
patch-not-applied-tooltip = Patch is not applied
|
||||
patch-not-applied-tooltip = 补丁未应用
|
||||
|
||||
apply-xlua-patch = Apply xlua patch
|
||||
apply-xlua-patch = 应用 xLua 补丁
|
||||
|
||||
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 = 请求超级用户权限
|
||||
ask-superuser-permissions-description = 启动器需要超级用户权限来修改 hosts 文件。flatpak 版无需此权限
|
||||
|
||||
selected-version = 选择版本
|
||||
recommended-only = 仅显示推荐版本
|
||||
|
@ -53,6 +63,13 @@ recommended-only = 仅显示推荐版本
|
|||
wine-version = Wine 版本
|
||||
wine-recommended-description = 仅显示推荐的 Wine 版本
|
||||
|
||||
wine-tools = Wine tools
|
||||
command-line = Command line
|
||||
registry-editor = Registry editor
|
||||
explorer = Explorer
|
||||
task-manager = Task manager
|
||||
configuration = Configuration
|
||||
|
||||
dxvk-version = DXVK 版本
|
||||
dxvk-selection-disabled = 您的葡萄酒组首选项禁用 DXVK 选择
|
||||
dxvk-recommended-description = 仅显示推荐的 DXVK 版本
|
||||
|
|
|
@ -12,7 +12,7 @@ launcher-folder = 启动器文件夹
|
|||
game-folder = 游戏文件夹
|
||||
config-file = 配置文件
|
||||
debug-file = 调试文件
|
||||
wish-url = Open wishes
|
||||
wish-url = 转到祈愿 URL
|
||||
about = 关于
|
||||
|
||||
|
||||
|
@ -40,12 +40,17 @@ downloading = 正在下载
|
|||
unpacking = 正在解压缩
|
||||
verifying-files = 正在检验文件
|
||||
repairing-files = 正在修复文件
|
||||
migrating-folders = Migrating folders
|
||||
applying-hdiff = Applying hdiff patches
|
||||
removing-outdated = Removing outdated files
|
||||
|
||||
|
||||
components-index-updated = Components index was updated
|
||||
components-index-updated = 组件索引已更新
|
||||
|
||||
|
||||
launch = 启动
|
||||
migrate-folders = Migrate folders
|
||||
migrate-folders-tooltip = Update game folders structure
|
||||
apply-patch = 安装补丁
|
||||
download-wine = 下载 Wine
|
||||
create-prefix = 创建 Wine prefix
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use anime_launcher_sdk::anime_game_core::installer::downloader::Downloader;
|
||||
use anime_launcher_sdk::anime_game_core::curl::fetch;
|
||||
use anime_launcher_sdk::anime_game_core::minreq;
|
||||
|
||||
use md5::{Md5, Digest};
|
||||
|
||||
|
@ -17,7 +17,7 @@ pub fn get_uri() -> String {
|
|||
|
||||
#[cached::proc_macro::cached(result)]
|
||||
pub fn get_background_info() -> anyhow::Result<Background> {
|
||||
let json = serde_json::from_slice::<serde_json::Value>(&fetch(get_uri(), None)?.get_body()?)?;
|
||||
let json = serde_json::from_slice::<serde_json::Value>(minreq::get(get_uri()).send()?.as_bytes())?;
|
||||
|
||||
let uri = match json["data"]["adv"]["background"].as_str() {
|
||||
Some(uri) => uri.to_owned(),
|
||||
|
@ -60,7 +60,7 @@ pub fn download_background() -> anyhow::Result<()> {
|
|||
|
||||
downloader.continue_downloading = false;
|
||||
|
||||
if let Err(err) = downloader.download_to(crate::BACKGROUND_FILE.as_path(), |_, _| {}) {
|
||||
if let Err(err) = downloader.download(crate::BACKGROUND_FILE.as_path(), |_, _| {}) {
|
||||
anyhow::bail!(err);
|
||||
}
|
||||
|
||||
|
|
|
@ -12,9 +12,10 @@ use tracing_subscriber::filter::*;
|
|||
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub mod move_folder;
|
||||
pub mod i18n;
|
||||
pub mod ui;
|
||||
pub mod background;
|
||||
pub mod ui;
|
||||
|
||||
use ui::main::*;
|
||||
use ui::first_run::main::*;
|
||||
|
@ -37,10 +38,10 @@ lazy_static::lazy_static! {
|
|||
/// This one is used to prepare some launcher UI components on start
|
||||
pub static ref CONFIG: config::Config = config::get().expect("Failed to load config");
|
||||
|
||||
pub static ref GAME: Game = Game::new(&CONFIG.game.path);
|
||||
pub static ref GAME: Game = Game::new(CONFIG.game.path.for_edition(CONFIG.launcher.edition));
|
||||
|
||||
/// Path to launcher folder. Standard is `$HOME/.local/share/anime-game-launcher`
|
||||
pub static ref LAUNCHER_FOLDER: PathBuf = launcher_dir().unwrap_or_default();
|
||||
pub static ref LAUNCHER_FOLDER: PathBuf = launcher_dir().expect("Failed to get launcher folder");
|
||||
|
||||
/// Path to `debug.log` file. Standard is `$HOME/.local/share/anime-game-launcher/debug.log`
|
||||
pub static ref DEBUG_FILE: PathBuf = LAUNCHER_FOLDER.join("debug.log");
|
||||
|
@ -160,7 +161,7 @@ fn main() {
|
|||
", BACKGROUND_FILE.to_string_lossy()));
|
||||
|
||||
// Set game edition
|
||||
genshin::set_game_edition(CONFIG.launcher.edition.into());
|
||||
GameEdition::from(CONFIG.launcher.edition).select();
|
||||
|
||||
// Set UI language
|
||||
let lang = CONFIG.launcher.language.parse().expect("Wrong language format used in config");
|
||||
|
|
26
src/move_folder.rs
Normal file
26
src/move_folder.rs
Normal file
|
@ -0,0 +1,26 @@
|
|||
use std::path::Path;
|
||||
|
||||
pub fn move_folder(from: &Path, to: &Path) -> std::io::Result<()> {
|
||||
if !to.exists() {
|
||||
std::fs::create_dir_all(to)?;
|
||||
}
|
||||
|
||||
for entry in from.read_dir()?.flatten() {
|
||||
let to_path = to.join(entry.file_name());
|
||||
|
||||
if entry.metadata()?.is_dir() {
|
||||
move_folder(&entry.path(), &to_path)?;
|
||||
}
|
||||
|
||||
else if entry.metadata()?.is_file() {
|
||||
std::fs::copy(entry.path(), to_path)?;
|
||||
std::fs::remove_file(entry.path())?;
|
||||
}
|
||||
|
||||
// TODO: symlinks?
|
||||
}
|
||||
|
||||
std::fs::remove_dir_all(from)?;
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -1,18 +1,17 @@
|
|||
use relm4::prelude::*;
|
||||
|
||||
use gtk::prelude::*;
|
||||
|
||||
use anime_launcher_sdk::VERSION as SDK_VERSION;
|
||||
|
||||
use anime_launcher_sdk::anime_game_core::{
|
||||
VERSION as CORE_VERSION,
|
||||
curl_sys
|
||||
};
|
||||
use anime_launcher_sdk::anime_game_core::VERSION as CORE_VERSION;
|
||||
|
||||
use crate::*;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref CURL_INFO: curl_sys::Version = curl_sys::Version::get();
|
||||
pub static ref APP_VERSION: String = if crate::APP_DEBUG && !crate::APP_VERSION.contains('-') {
|
||||
format!("{}-dev", crate::APP_VERSION)
|
||||
} else {
|
||||
crate::APP_VERSION.to_string()
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -41,17 +40,7 @@ impl SimpleComponent for AboutDialog {
|
|||
set_issue_url: "https://github.com/an-anime-team/an-anime-game-launcher/issues",
|
||||
|
||||
set_license_type: gtk::License::Gpl30,
|
||||
|
||||
set_version: &{
|
||||
// Debug build & build's version doesn't contain any suffix (-dev, -beta, etc)
|
||||
if crate::APP_DEBUG && !crate::APP_VERSION.contains('-') {
|
||||
format!("{}-dev", crate::APP_VERSION)
|
||||
}
|
||||
|
||||
else {
|
||||
crate::APP_VERSION.to_string()
|
||||
}
|
||||
},
|
||||
set_version: &APP_VERSION,
|
||||
|
||||
set_developers: &[
|
||||
"Nikita Podvirnyy https://github.com/krypt0nn"
|
||||
|
@ -81,15 +70,43 @@ impl SimpleComponent for AboutDialog {
|
|||
format!("Anime Launcher SDK: {SDK_VERSION}"),
|
||||
format!("Anime Game Core: {CORE_VERSION}"),
|
||||
String::new(),
|
||||
format!("curl: {}", CURL_INFO.version()),
|
||||
format!("SSL: {}", CURL_INFO.ssl_version().unwrap_or("?")),
|
||||
String::new(),
|
||||
format!("GTK: {}.{}.{}", gtk::major_version(), gtk::minor_version(), gtk::micro_version()),
|
||||
format!("libadwaita: {}.{}.{}", adw::major_version(), adw::minor_version(), adw::micro_version()),
|
||||
format!("pango: {}", gtk::pango::version_string()),
|
||||
format!("cairo: {}", gtk::cairo::version_string()),
|
||||
].join("\n"),
|
||||
|
||||
set_release_notes_version: &APP_VERSION,
|
||||
set_release_notes: &[
|
||||
"<p>Added</p>",
|
||||
|
||||
"<ul>",
|
||||
"<li>Added installation migration feature</li>",
|
||||
"<li>Added game environment switcher</li>",
|
||||
"<li>Added game edition switcher</li>",
|
||||
"<li>Added changelog to updated components toast</li>",
|
||||
"<li>Added wine tools to settings</li>",
|
||||
"<li>Added preferences search</li>",
|
||||
"<li>Added new progress bar statuses for applyign hdiff patches and removing outdated files</li>",
|
||||
"<li>Added automatic 3.5 -> 3.6 voiceover files migration related to changed files structure</li>",
|
||||
"</ul>",
|
||||
|
||||
"<p>Fixed</p>",
|
||||
|
||||
"<ul>",
|
||||
"<li>Added whitespaces removing from environment values</li>",
|
||||
"</ul>",
|
||||
|
||||
"<p>Changed</p>",
|
||||
|
||||
"<ul>",
|
||||
"<li>Improved game repairing feature</li>",
|
||||
"<li>Replaced curl dependency by native code</li>",
|
||||
"<li>Replaced static image by spinner in wine / dxvk version selection</li>",
|
||||
"<li>Made wine / dxvk versions always visible if they're downloaded</li>",
|
||||
"</ul>",
|
||||
].join("\n"),
|
||||
|
||||
set_modal: true,
|
||||
set_hide_on_close: true,
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ pub struct ComponentsListGroup {
|
|||
}
|
||||
|
||||
impl From<wine::Group> for ComponentsListGroup {
|
||||
#[inline]
|
||||
fn from(group: wine::Group) -> Self {
|
||||
Self {
|
||||
title: group.title,
|
||||
|
@ -34,6 +35,7 @@ impl From<wine::Group> for ComponentsListGroup {
|
|||
}
|
||||
|
||||
impl From<dxvk::Group> for ComponentsListGroup {
|
||||
#[inline]
|
||||
fn from(group: dxvk::Group) -> Self {
|
||||
Self {
|
||||
title: group.title,
|
||||
|
@ -51,23 +53,33 @@ pub struct ComponentsListVersion {
|
|||
}
|
||||
|
||||
impl From<wine::Version> for ComponentsListVersion {
|
||||
#[inline]
|
||||
fn from(version: wine::Version) -> Self {
|
||||
Self {
|
||||
recommended: match version.version_features() {
|
||||
Some(features) => features.recommended,
|
||||
None => true
|
||||
},
|
||||
|
||||
name: version.name,
|
||||
title: version.title,
|
||||
uri: version.uri,
|
||||
recommended: true // FIXME
|
||||
uri: version.uri
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<dxvk::Version> for ComponentsListVersion {
|
||||
#[inline]
|
||||
fn from(version: dxvk::Version) -> Self {
|
||||
Self {
|
||||
name: version.name.clone(),
|
||||
title: version.name,
|
||||
uri: version.uri,
|
||||
recommended: true // FIXME
|
||||
recommended: match version.version_features() {
|
||||
Some(features) => features.recommended,
|
||||
None => true
|
||||
},
|
||||
|
||||
name: version.name,
|
||||
title: version.title,
|
||||
uri: version.uri
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,8 +3,7 @@ use relm4::component::*;
|
|||
|
||||
use adw::prelude::*;
|
||||
|
||||
use anime_launcher_sdk::anime_game_core::installer::installer::Update as InstallerUpdate;
|
||||
use anime_launcher_sdk::anime_game_core::prettify_bytes::prettify_bytes;
|
||||
use anime_launcher_sdk::anime_game_core::prelude::*;
|
||||
|
||||
use crate::i18n::*;
|
||||
|
||||
|
@ -44,7 +43,7 @@ pub enum ProgressBarMsg {
|
|||
/// (current bytes, total bytes)
|
||||
UpdateProgress(u64, u64),
|
||||
|
||||
UpdateFromState(InstallerUpdate),
|
||||
UpdateFromState(DiffUpdate),
|
||||
SetVisible(bool)
|
||||
}
|
||||
|
||||
|
@ -128,12 +127,36 @@ impl SimpleAsyncComponent for ProgressBar {
|
|||
|
||||
ProgressBarMsg::UpdateFromState(state) => {
|
||||
match state {
|
||||
InstallerUpdate::CheckingFreeSpace(_) => self.caption = Some(tr("checking-free-space")),
|
||||
InstallerUpdate::DownloadingStarted(_) => self.caption = Some(tr("downloading")),
|
||||
InstallerUpdate::UnpackingStarted(_) => self.caption = Some(tr("unpacking")),
|
||||
DiffUpdate::InstallerUpdate(InstallerUpdate::CheckingFreeSpace(_)) => self.caption = Some(tr("checking-free-space")),
|
||||
|
||||
InstallerUpdate::DownloadingProgress(curr, total) |
|
||||
InstallerUpdate::UnpackingProgress(curr, total) => {
|
||||
DiffUpdate::InstallerUpdate(InstallerUpdate::DownloadingStarted(_)) => {
|
||||
self.caption = Some(tr("downloading"));
|
||||
|
||||
self.display_fraction = true;
|
||||
}
|
||||
|
||||
DiffUpdate::InstallerUpdate(InstallerUpdate::UnpackingStarted(_)) => {
|
||||
self.caption = Some(tr("unpacking"));
|
||||
|
||||
self.display_fraction = true;
|
||||
}
|
||||
|
||||
DiffUpdate::ApplyingHdiffStarted => {
|
||||
self.caption = Some(tr("applying-hdiff"));
|
||||
|
||||
self.display_fraction = false;
|
||||
}
|
||||
|
||||
DiffUpdate::RemovingOutdatedStarted => {
|
||||
self.caption = Some(tr("removing-outdated"));
|
||||
|
||||
self.display_fraction = false;
|
||||
}
|
||||
|
||||
DiffUpdate::InstallerUpdate(InstallerUpdate::DownloadingProgress(curr, total)) |
|
||||
DiffUpdate::InstallerUpdate(InstallerUpdate::UnpackingProgress(curr, total)) |
|
||||
DiffUpdate::ApplyingHdiffProgress(curr, total) |
|
||||
DiffUpdate::RemovingOutdatedProgress(curr, total) => {
|
||||
self.fraction = curr as f64 / total as f64;
|
||||
|
||||
self.downloaded = Some((
|
||||
|
@ -142,11 +165,14 @@ impl SimpleAsyncComponent for ProgressBar {
|
|||
));
|
||||
}
|
||||
|
||||
InstallerUpdate::DownloadingFinished => tracing::info!("Downloading finished"),
|
||||
InstallerUpdate::UnpackingFinished => tracing::info!("Unpacking finished"),
|
||||
DiffUpdate::InstallerUpdate(InstallerUpdate::DownloadingFinished) => tracing::info!("Downloading finished"),
|
||||
DiffUpdate::InstallerUpdate(InstallerUpdate::UnpackingFinished) => tracing::info!("Unpacking finished"),
|
||||
|
||||
InstallerUpdate::DownloadingError(err) => tracing::error!("Downloading error: {:?}", err),
|
||||
InstallerUpdate::UnpackingError(err) => tracing::error!("Unpacking error: {:?}", err)
|
||||
DiffUpdate::ApplyingHdiffFinished => tracing::info!("Applying hdiffs finished"),
|
||||
DiffUpdate::RemovingOutdatedFinished => tracing::info!("Removing outdated files finished"),
|
||||
|
||||
DiffUpdate::InstallerUpdate(InstallerUpdate::DownloadingError(err)) => tracing::error!("Downloading error: {:?}", err),
|
||||
DiffUpdate::InstallerUpdate(InstallerUpdate::UnpackingError(err)) => tracing::error!("Unpacking error: {:?}", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ use gtk::glib::clone;
|
|||
use super::progress_bar::ProgressBarMsg;
|
||||
|
||||
use anime_launcher_sdk::config;
|
||||
use anime_launcher_sdk::anime_game_core::installer::installer::*;
|
||||
use anime_launcher_sdk::anime_game_core::prelude::*;
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
|
@ -52,7 +52,7 @@ impl SimpleAsyncComponent for ComponentVersion {
|
|||
set_title: &model.title,
|
||||
|
||||
#[watch]
|
||||
set_visible: !model.show_recommended_only || model.recommended,
|
||||
set_visible: !model.show_recommended_only || model.recommended || model.state != VersionState::NotDownloaded,
|
||||
|
||||
add_suffix = >k::Button {
|
||||
#[watch]
|
||||
|
@ -162,12 +162,12 @@ impl SimpleAsyncComponent for ComponentVersion {
|
|||
|
||||
installer.install(download_folder, move |state| {
|
||||
match &state {
|
||||
Update::UnpackingFinished |
|
||||
Update::DownloadingError(_) |
|
||||
Update::UnpackingError(_) => {
|
||||
InstallerUpdate::UnpackingFinished |
|
||||
InstallerUpdate::DownloadingError(_) |
|
||||
InstallerUpdate::UnpackingError(_) => {
|
||||
progress_bar_sender.send(ProgressBarMsg::SetVisible(false));
|
||||
|
||||
if let Update::UnpackingFinished = &state {
|
||||
if let InstallerUpdate::UnpackingFinished = &state {
|
||||
sender.input(AppMsg::SetState(VersionState::Downloaded));
|
||||
sender.output(super::group::AppMsg::CallOnDownloaded);
|
||||
}
|
||||
|
@ -180,7 +180,7 @@ impl SimpleAsyncComponent for ComponentVersion {
|
|||
_ => ()
|
||||
}
|
||||
|
||||
progress_bar_sender.send(ProgressBarMsg::UpdateFromState(state));
|
||||
progress_bar_sender.send(ProgressBarMsg::UpdateFromState(DiffUpdate::InstallerUpdate(state)));
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
|
|
@ -10,15 +10,21 @@ use std::path::PathBuf;
|
|||
use crate::*;
|
||||
use crate::i18n::*;
|
||||
use super::main::*;
|
||||
use crate::ui::components::progress_bar::*;
|
||||
|
||||
pub struct DefaultPathsApp {
|
||||
progress_bar: AsyncController<ProgressBar>,
|
||||
|
||||
show_additional: bool,
|
||||
migrate_installation: bool,
|
||||
show_progress: bool,
|
||||
|
||||
launcher: PathBuf,
|
||||
runners: PathBuf,
|
||||
dxvks: PathBuf,
|
||||
prefix: PathBuf,
|
||||
game: PathBuf,
|
||||
game_global: PathBuf,
|
||||
game_china: PathBuf,
|
||||
fps_unlocker: PathBuf,
|
||||
components: PathBuf,
|
||||
patch: PathBuf,
|
||||
|
@ -31,7 +37,8 @@ pub enum Folders {
|
|||
Runners,
|
||||
DXVK,
|
||||
Prefix,
|
||||
Game,
|
||||
GameGlobal,
|
||||
GameChina,
|
||||
FpsUnlocker,
|
||||
Components,
|
||||
Patch,
|
||||
|
@ -48,7 +55,8 @@ pub enum DefaultPathsAppMsg {
|
|||
|
||||
#[relm4::component(async, pub)]
|
||||
impl SimpleAsyncComponent for DefaultPathsApp {
|
||||
type Init = ();
|
||||
/// If `true`, then use migrate installation mode
|
||||
type Init = bool;
|
||||
type Input = DefaultPathsAppMsg;
|
||||
type Output = FirstRunAppMsg;
|
||||
|
||||
|
@ -70,6 +78,9 @@ impl SimpleAsyncComponent for DefaultPathsApp {
|
|||
set_valign: gtk::Align::End,
|
||||
set_vexpand: true,
|
||||
|
||||
#[watch]
|
||||
set_sensitive: !model.show_progress,
|
||||
|
||||
adw::ActionRow {
|
||||
set_title: &tr("launcher-folder"),
|
||||
set_icon_name: Some("folder-symbolic"),
|
||||
|
@ -105,6 +116,9 @@ impl SimpleAsyncComponent for DefaultPathsApp {
|
|||
#[watch]
|
||||
set_visible: model.show_additional,
|
||||
|
||||
#[watch]
|
||||
set_sensitive: !model.show_progress,
|
||||
|
||||
adw::ActionRow {
|
||||
set_title: &tr("runners-folder"),
|
||||
set_icon_name: Some("folder-symbolic"),
|
||||
|
@ -139,14 +153,25 @@ impl SimpleAsyncComponent for DefaultPathsApp {
|
|||
},
|
||||
|
||||
adw::ActionRow {
|
||||
set_title: &tr("game-installation-folder"),
|
||||
set_title: &tr("global-game-installation-folder"),
|
||||
set_icon_name: Some("folder-symbolic"),
|
||||
set_activatable: true,
|
||||
|
||||
#[watch]
|
||||
set_subtitle: model.game.to_str().unwrap(),
|
||||
set_subtitle: model.game_global.to_str().unwrap(),
|
||||
|
||||
connect_activated => DefaultPathsAppMsg::ChoosePath(Folders::Game)
|
||||
connect_activated => DefaultPathsAppMsg::ChoosePath(Folders::GameGlobal)
|
||||
},
|
||||
|
||||
adw::ActionRow {
|
||||
set_title: &tr("chinese-game-installation-folder"),
|
||||
set_icon_name: Some("folder-symbolic"),
|
||||
set_activatable: true,
|
||||
|
||||
#[watch]
|
||||
set_subtitle: model.game_china.to_str().unwrap(),
|
||||
|
||||
connect_activated => DefaultPathsAppMsg::ChoosePath(Folders::GameChina)
|
||||
},
|
||||
|
||||
adw::ActionRow {
|
||||
|
@ -197,43 +222,86 @@ impl SimpleAsyncComponent for DefaultPathsApp {
|
|||
add = &adw::PreferencesGroup {
|
||||
set_valign: gtk::Align::Center,
|
||||
set_vexpand: true,
|
||||
|
||||
|
||||
#[watch]
|
||||
set_visible: !model.show_progress,
|
||||
|
||||
gtk::Box {
|
||||
set_orientation: gtk::Orientation::Horizontal,
|
||||
set_halign: gtk::Align::Center,
|
||||
set_spacing: 8,
|
||||
|
||||
|
||||
gtk::Button {
|
||||
set_label: &tr("continue"),
|
||||
set_label: &if model.migrate_installation {
|
||||
tr("migrate")
|
||||
} else {
|
||||
tr("continue")
|
||||
},
|
||||
|
||||
set_css_classes: &["suggested-action", "pill"],
|
||||
|
||||
connect_clicked => DefaultPathsAppMsg::Continue
|
||||
},
|
||||
|
||||
gtk::Button {
|
||||
set_label: &tr("exit"),
|
||||
set_label: &if model.migrate_installation {
|
||||
tr("close")
|
||||
} else {
|
||||
tr("exit")
|
||||
},
|
||||
|
||||
add_css_class: "pill",
|
||||
|
||||
#[watch]
|
||||
set_visible: !model.migrate_installation,
|
||||
|
||||
connect_clicked => DefaultPathsAppMsg::Exit
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
add = &adw::PreferencesGroup {
|
||||
set_valign: gtk::Align::Center,
|
||||
set_vexpand: true,
|
||||
|
||||
#[watch]
|
||||
set_visible: model.show_progress,
|
||||
|
||||
gtk::Box {
|
||||
set_orientation: gtk::Orientation::Horizontal,
|
||||
set_halign: gtk::Align::Center,
|
||||
|
||||
append = model.progress_bar.widget(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn init(
|
||||
_init: Self::Init,
|
||||
init: Self::Init,
|
||||
root: Self::Root,
|
||||
_sender: AsyncComponentSender<Self>,
|
||||
) -> AsyncComponentParts<Self> {
|
||||
let model = Self {
|
||||
progress_bar: ProgressBar::builder()
|
||||
.launch(ProgressBarInit {
|
||||
caption: None,
|
||||
display_progress: true,
|
||||
display_fraction: false,
|
||||
visible: false
|
||||
})
|
||||
.detach(),
|
||||
|
||||
show_additional: false,
|
||||
migrate_installation: init,
|
||||
show_progress: false,
|
||||
|
||||
launcher: LAUNCHER_FOLDER.to_path_buf(),
|
||||
runners: CONFIG.game.wine.builds.clone(),
|
||||
dxvks: CONFIG.game.dxvk.builds.clone(),
|
||||
prefix: CONFIG.game.wine.prefix.clone(),
|
||||
game: CONFIG.game.path.clone(),
|
||||
game_global: CONFIG.game.path.global.clone(),
|
||||
game_china: CONFIG.game.path.china.clone(),
|
||||
fps_unlocker: CONFIG.game.enhancements.fps_unlocker.path.clone(),
|
||||
components: CONFIG.components.path.clone(),
|
||||
patch: CONFIG.patch.path.clone(),
|
||||
|
@ -242,6 +310,9 @@ impl SimpleAsyncComponent for DefaultPathsApp {
|
|||
temp: CONFIG.launcher.temp.clone().unwrap_or(std::env::temp_dir())
|
||||
};
|
||||
|
||||
// Set progress bar width
|
||||
model.progress_bar.widget().set_width_request(400);
|
||||
|
||||
let widgets = view_output!();
|
||||
|
||||
AsyncComponentParts { model, widgets }
|
||||
|
@ -264,7 +335,8 @@ impl SimpleAsyncComponent for DefaultPathsApp {
|
|||
self.runners = result.join("runners");
|
||||
self.dxvks = result.join("dxvks");
|
||||
self.prefix = result.join("prefix");
|
||||
self.game = result.join("Genshin Impact"); // TODO: change it based on GameEdition
|
||||
self.game_global = result.join(concat!("Ge", "nshi", "n Imp", "act"));
|
||||
self.game_china = result.join(concat!("Yu", "anS", "hen"));
|
||||
self.fps_unlocker = result.join("fps-unlocker");
|
||||
self.components = result.join("components");
|
||||
self.patch = result.join("patch");
|
||||
|
@ -276,7 +348,8 @@ impl SimpleAsyncComponent for DefaultPathsApp {
|
|||
Folders::Runners => self.runners = result,
|
||||
Folders::DXVK => self.dxvks = result,
|
||||
Folders::Prefix => self.prefix = result,
|
||||
Folders::Game => self.game = result,
|
||||
Folders::GameGlobal => self.game_global = result,
|
||||
Folders::GameChina => self.game_china = result,
|
||||
Folders::FpsUnlocker => self.fps_unlocker = result,
|
||||
Folders::Components => self.components = result,
|
||||
Folders::Patch => self.patch = result,
|
||||
|
@ -287,17 +360,71 @@ impl SimpleAsyncComponent for DefaultPathsApp {
|
|||
|
||||
#[allow(unused_must_use)]
|
||||
DefaultPathsAppMsg::Continue => {
|
||||
let old_config = config::get().unwrap_or_else(|_| CONFIG.clone());
|
||||
|
||||
match self.update_config() {
|
||||
Ok(_) => sender.output(Self::Output::ScrollToSelectVoiceovers),
|
||||
|
||||
Err(err) => sender.output(Self::Output::Toast {
|
||||
title: tr("config-update-error"),
|
||||
description: Some(err.to_string())
|
||||
})
|
||||
};
|
||||
Ok(_) => {
|
||||
if self.migrate_installation {
|
||||
self.progress_bar.sender().send(ProgressBarMsg::SetVisible(true));
|
||||
|
||||
self.show_progress = true;
|
||||
|
||||
let folders = [
|
||||
(old_config.game.wine.builds, &self.runners),
|
||||
(old_config.game.dxvk.builds, &self.dxvks),
|
||||
(old_config.game.wine.prefix, &self.prefix),
|
||||
(old_config.game.path.global, &self.game_global),
|
||||
(old_config.game.path.china, &self.game_china),
|
||||
(old_config.components.path, &self.components),
|
||||
(old_config.patch.path, &self.patch),
|
||||
|
||||
(old_config.game.enhancements.fps_unlocker.path, &self.fps_unlocker)
|
||||
];
|
||||
|
||||
#[allow(clippy::expect_fun_call)]
|
||||
for (i, (from, to)) in folders.iter().enumerate() {
|
||||
self.progress_bar.sender().send(ProgressBarMsg::UpdateCaption(Some(
|
||||
from.to_str().map(|str| str.to_string()).unwrap_or_else(|| format!("{:?}", from))
|
||||
)));
|
||||
|
||||
if &from != to && from.exists() {
|
||||
move_folder::move_folder(from, to).expect(&format!("Failed to move folder: {:?} -> {:?}", from, to));
|
||||
}
|
||||
|
||||
self.progress_bar.sender().send(ProgressBarMsg::UpdateProgress(i as u64 + 1, folders.len() as u64));
|
||||
}
|
||||
|
||||
// Restart the app
|
||||
|
||||
std::process::Command::new(std::env::current_exe().unwrap()).spawn().unwrap();
|
||||
|
||||
relm4::main_application().quit();
|
||||
}
|
||||
|
||||
else {
|
||||
sender.output(Self::Output::ScrollToSelectVoiceovers);
|
||||
}
|
||||
}
|
||||
|
||||
Err(err) => {
|
||||
sender.output(Self::Output::Toast {
|
||||
title: tr("config-update-error"),
|
||||
description: Some(err.to_string())
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DefaultPathsAppMsg::Exit => relm4::main_application().quit()
|
||||
DefaultPathsAppMsg::Exit => {
|
||||
if self.migrate_installation {
|
||||
// TODO: this shit should return message to general preferences component somehow to close MigrateInstallation window
|
||||
todo!();
|
||||
}
|
||||
|
||||
else {
|
||||
relm4::main_application().quit();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -309,7 +436,8 @@ impl DefaultPathsApp {
|
|||
config.game.wine.builds = self.runners.clone();
|
||||
config.game.dxvk.builds = self.dxvks.clone();
|
||||
config.game.wine.prefix = self.prefix.clone();
|
||||
config.game.path = self.game.clone();
|
||||
config.game.path.global = self.game_global.clone();
|
||||
config.game.path.china = self.game_china.clone();
|
||||
config.components.path = self.components.clone();
|
||||
config.patch.path = self.patch.clone();
|
||||
config.launcher.temp = Some(self.temp.clone());
|
||||
|
|
|
@ -3,9 +3,9 @@ use relm4::component::*;
|
|||
|
||||
use adw::prelude::*;
|
||||
|
||||
use anime_launcher_sdk::anime_game_core::prelude::*;
|
||||
use anime_launcher_sdk::components::*;
|
||||
use anime_launcher_sdk::components::wine::WincompatlibWine;
|
||||
use anime_launcher_sdk::anime_game_core::installer::prelude::*;
|
||||
use anime_launcher_sdk::config;
|
||||
use anime_launcher_sdk::wincompatlib::prelude::*;
|
||||
|
||||
|
@ -421,7 +421,7 @@ impl SimpleAsyncComponent for DownloadComponentsApp {
|
|||
_ => ()
|
||||
}
|
||||
|
||||
progress_bar_input.send(ProgressBarMsg::UpdateFromState(update));
|
||||
progress_bar_input.send(ProgressBarMsg::UpdateFromState(DiffUpdate::InstallerUpdate(update)));
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -532,7 +532,7 @@ impl SimpleAsyncComponent for DownloadComponentsApp {
|
|||
_ => ()
|
||||
}
|
||||
|
||||
progress_bar_input.send(ProgressBarMsg::UpdateFromState(update));
|
||||
progress_bar_input.send(ProgressBarMsg::UpdateFromState(DiffUpdate::InstallerUpdate(update)));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ use super::select_voiceovers::*;
|
|||
use super::download_components::*;
|
||||
use super::finish::*;
|
||||
|
||||
pub static mut MAIN_WINDOW: Option<adw::Window> = None;
|
||||
pub static mut MAIN_WINDOW: Option<adw::ApplicationWindow> = None;
|
||||
|
||||
// TODO: add special page for launcher style selection
|
||||
|
||||
|
@ -61,7 +61,7 @@ impl SimpleComponent for FirstRunApp {
|
|||
type Output = ();
|
||||
|
||||
view! {
|
||||
window = adw::Window {
|
||||
window = adw::ApplicationWindow {
|
||||
set_default_size: (780, 560),
|
||||
|
||||
#[watch]
|
||||
|
@ -145,7 +145,7 @@ impl SimpleComponent for FirstRunApp {
|
|||
.forward(sender.input_sender(), std::convert::identity),
|
||||
|
||||
default_paths: DefaultPathsApp::builder()
|
||||
.launch(())
|
||||
.launch(false)
|
||||
.forward(sender.input_sender(), std::convert::identity),
|
||||
|
||||
select_voiceovers: SelectVoiceoversApp::builder()
|
||||
|
@ -232,8 +232,7 @@ impl SimpleComponent for FirstRunApp {
|
|||
Ok(None) => {
|
||||
for host in &CONFIG.components.servers {
|
||||
match components.sync(host) {
|
||||
Ok(true) => break,
|
||||
Ok(false) => continue,
|
||||
Ok(_) => break,
|
||||
|
||||
Err(err) => {
|
||||
tracing::error!("Failed to sync components index");
|
||||
|
|
|
@ -21,7 +21,7 @@ pub fn apply_patch<T: PatchExt + Send + Sync + 'static>(sender: ComponentSender<
|
|||
std::thread::spawn(move || {
|
||||
let mut apply_patch_if_needed = true;
|
||||
|
||||
if let Err(err) = patch.apply(&config.game.path, config.patch.root) {
|
||||
if let Err(err) = patch.apply(config.game.path.for_edition(config.launcher.edition), config.patch.root) {
|
||||
tracing::error!("Failed to patch the game");
|
||||
|
||||
sender.input(AppMsg::Toast {
|
||||
|
|
|
@ -18,11 +18,11 @@ pub fn download_diff(sender: ComponentSender<App>, progress_bar_input: Sender<Pr
|
|||
|
||||
std::thread::spawn(move || {
|
||||
let config = config::get().unwrap();
|
||||
let game_path = config.game.path.for_edition(config.launcher.edition).to_path_buf();
|
||||
|
||||
#[allow(unused_must_use)]
|
||||
let result = diff.install_to_by(config.game.path, config.launcher.temp, clone!(@strong sender => move |state| {
|
||||
let result = diff.install_to_by(game_path, config.launcher.temp, clone!(@strong sender => move |state| {
|
||||
match &state {
|
||||
InstallerUpdate::DownloadingError(err) => {
|
||||
DiffUpdate::InstallerUpdate(InstallerUpdate::DownloadingError(err)) => {
|
||||
tracing::error!("Downloading failed: {err}");
|
||||
|
||||
sender.input(AppMsg::Toast {
|
||||
|
@ -31,7 +31,7 @@ pub fn download_diff(sender: ComponentSender<App>, progress_bar_input: Sender<Pr
|
|||
});
|
||||
}
|
||||
|
||||
InstallerUpdate::UnpackingError(err) => {
|
||||
DiffUpdate::InstallerUpdate(InstallerUpdate::UnpackingError(err)) => {
|
||||
tracing::error!("Unpacking failed: {err}");
|
||||
|
||||
sender.input(AppMsg::Toast {
|
||||
|
@ -43,7 +43,9 @@ pub fn download_diff(sender: ComponentSender<App>, progress_bar_input: Sender<Pr
|
|||
_ => ()
|
||||
}
|
||||
|
||||
progress_bar_input.send(ProgressBarMsg::UpdateFromState(state));
|
||||
#[allow(unused_must_use)] {
|
||||
progress_bar_input.send(ProgressBarMsg::UpdateFromState(state));
|
||||
}
|
||||
}));
|
||||
|
||||
let mut perform_on_download_needed = true;
|
||||
|
|
|
@ -55,7 +55,6 @@ pub fn download_wine(sender: ComponentSender<App>, progress_bar_input: Sender<Pr
|
|||
sender.input(AppMsg::SetDownloading(true));
|
||||
|
||||
std::thread::spawn(clone!(@strong sender => move || {
|
||||
#[allow(unused_must_use)]
|
||||
installer.install(&config.game.wine.builds, clone!(@strong sender => move |state| {
|
||||
match &state {
|
||||
InstallerUpdate::DownloadingError(err) => {
|
||||
|
@ -79,7 +78,9 @@ pub fn download_wine(sender: ComponentSender<App>, progress_bar_input: Sender<Pr
|
|||
_ => ()
|
||||
}
|
||||
|
||||
progress_bar_input.send(ProgressBarMsg::UpdateFromState(state));
|
||||
#[allow(unused_must_use)] {
|
||||
progress_bar_input.send(ProgressBarMsg::UpdateFromState(DiffUpdate::InstallerUpdate(state)));
|
||||
}
|
||||
}));
|
||||
|
||||
config.game.wine.selected = Some(wine.name.clone());
|
||||
|
|
25
src/ui/main/migrate_folder.rs
Normal file
25
src/ui/main/migrate_folder.rs
Normal file
|
@ -0,0 +1,25 @@
|
|||
use relm4::prelude::*;
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::*;
|
||||
use super::{App, AppMsg};
|
||||
|
||||
pub fn migrate_folder(sender: ComponentSender<App>, from: PathBuf, to: PathBuf, cleanup_folder: Option<PathBuf>) {
|
||||
sender.input(AppMsg::DisableButtons(true));
|
||||
|
||||
std::thread::spawn(move || {
|
||||
move_folder::move_folder(&from, &to).expect("Failed to perform migration");
|
||||
|
||||
if let Some(cleanup_folder) = cleanup_folder {
|
||||
std::fs::remove_dir_all(cleanup_folder).expect("Failed to remove cleanup folder");
|
||||
}
|
||||
|
||||
sender.input(AppMsg::DisableButtons(false));
|
||||
sender.input(AppMsg::UpdateLauncherState {
|
||||
perform_on_download_needed: false,
|
||||
apply_patch_if_needed: false,
|
||||
show_status_page: true
|
||||
});
|
||||
});
|
||||
}
|
|
@ -15,11 +15,13 @@ mod apply_patch;
|
|||
mod download_wine;
|
||||
mod create_prefix;
|
||||
mod download_diff;
|
||||
mod migrate_folder;
|
||||
mod launch;
|
||||
|
||||
use anime_launcher_sdk::config::launcher::LauncherStyle;
|
||||
use anime_launcher_sdk::states::LauncherState;
|
||||
use anime_launcher_sdk::components::loader::ComponentsLoader;
|
||||
use anime_launcher_sdk::anime_game_core::genshin::consts::GameEdition;
|
||||
|
||||
use crate::*;
|
||||
use crate::i18n::*;
|
||||
|
@ -38,9 +40,9 @@ relm4::new_stateless_action!(WishUrl, WindowActionGroup, "wish_url");
|
|||
|
||||
relm4::new_stateless_action!(About, WindowActionGroup, "about");
|
||||
|
||||
static mut MAIN_WINDOW: Option<adw::ApplicationWindow> = None;
|
||||
static mut PREFERENCES_WINDOW: Option<AsyncController<PreferencesApp>> = None;
|
||||
static mut ABOUT_DIALOG: Option<Controller<AboutDialog>> = None;
|
||||
pub static mut MAIN_WINDOW: Option<adw::ApplicationWindow> = None;
|
||||
pub static mut PREFERENCES_WINDOW: Option<AsyncController<PreferencesApp>> = None;
|
||||
pub static mut ABOUT_DIALOG: Option<Controller<AboutDialog>> = None;
|
||||
|
||||
pub struct App {
|
||||
progress_bar: AsyncController<ProgressBar>,
|
||||
|
@ -370,24 +372,25 @@ impl SimpleComponent for App {
|
|||
gtk::Button {
|
||||
#[watch]
|
||||
set_label: &match model.state {
|
||||
Some(LauncherState::Launch) => tr("launch"),
|
||||
Some(LauncherState::PredownloadAvailable { .. }) => tr("launch"),
|
||||
Some(LauncherState::UnityPlayerPatchAvailable(_)) => tr("apply-patch"),
|
||||
Some(LauncherState::XluaPatchAvailable(_)) => tr("apply-patch"),
|
||||
Some(LauncherState::WineNotInstalled) => tr("download-wine"),
|
||||
Some(LauncherState::PrefixNotExists) => tr("create-prefix"),
|
||||
Some(LauncherState::VoiceUpdateAvailable(_)) => tr("update"),
|
||||
Some(LauncherState::VoiceOutdated(_)) => tr("update"),
|
||||
Some(LauncherState::VoiceNotInstalled(_)) => tr("download"),
|
||||
Some(LauncherState::GameUpdateAvailable(_)) => tr("update"),
|
||||
Some(LauncherState::GameOutdated(_)) => tr("update"),
|
||||
Some(LauncherState::GameNotInstalled(_)) => tr("download"),
|
||||
Some(LauncherState::Launch) => tr("launch"),
|
||||
Some(LauncherState::PredownloadAvailable { .. }) => tr("launch"),
|
||||
Some(LauncherState::FolderMigrationRequired { .. }) => tr("migrate-folders"),
|
||||
Some(LauncherState::UnityPlayerPatchAvailable(_)) => tr("apply-patch"),
|
||||
Some(LauncherState::XluaPatchAvailable(_)) => tr("apply-patch"),
|
||||
Some(LauncherState::WineNotInstalled) => tr("download-wine"),
|
||||
Some(LauncherState::PrefixNotExists) => tr("create-prefix"),
|
||||
Some(LauncherState::VoiceUpdateAvailable(_)) => tr("update"),
|
||||
Some(LauncherState::VoiceOutdated(_)) => tr("update"),
|
||||
Some(LauncherState::VoiceNotInstalled(_)) => tr("download"),
|
||||
Some(LauncherState::GameUpdateAvailable(_)) => tr("update"),
|
||||
Some(LauncherState::GameOutdated(_)) => tr("update"),
|
||||
Some(LauncherState::GameNotInstalled(_)) => tr("download"),
|
||||
|
||||
None => String::from("...")
|
||||
},
|
||||
|
||||
#[watch]
|
||||
set_sensitive: match model.state.as_ref() {
|
||||
set_sensitive: !model.disabled_buttons && match &model.state {
|
||||
Some(LauncherState::GameOutdated { .. }) |
|
||||
Some(LauncherState::VoiceOutdated(_)) => false,
|
||||
|
||||
|
@ -407,7 +410,7 @@ impl SimpleComponent for App {
|
|||
},
|
||||
|
||||
#[watch]
|
||||
set_css_classes: match model.state.as_ref() {
|
||||
set_css_classes: match &model.state {
|
||||
Some(LauncherState::GameOutdated { .. }) |
|
||||
Some(LauncherState::VoiceOutdated(_)) => &["warning"],
|
||||
|
||||
|
@ -427,10 +430,12 @@ impl SimpleComponent for App {
|
|||
},
|
||||
|
||||
#[watch]
|
||||
set_tooltip_text: Some(&match model.state.as_ref() {
|
||||
set_tooltip_text: Some(&match &model.state {
|
||||
Some(LauncherState::GameOutdated { .. }) |
|
||||
Some(LauncherState::VoiceOutdated(_)) => tr("main-window--version-outdated-tooltip"),
|
||||
|
||||
Some(LauncherState::FolderMigrationRequired { .. }) => tr("migrate-folders-tooltip"),
|
||||
|
||||
Some(LauncherState::UnityPlayerPatchAvailable(UnityPlayerPatch { status, .. })) |
|
||||
Some(LauncherState::XluaPatchAvailable(XluaPatch { status, .. })) => match status {
|
||||
PatchStatus::NotAvailable => tr("main-window--patch-unavailable-tooltip"),
|
||||
|
@ -444,9 +449,6 @@ impl SimpleComponent for App {
|
|||
_ => String::new()
|
||||
}),
|
||||
|
||||
#[watch]
|
||||
set_sensitive: !model.disabled_buttons,
|
||||
|
||||
set_hexpand: false,
|
||||
set_width_request: 200,
|
||||
|
||||
|
@ -556,7 +558,12 @@ impl SimpleComponent for App {
|
|||
})));
|
||||
|
||||
group.add_action::<GameFolder>(&RelmAction::new_stateless(clone!(@strong sender => move |_| {
|
||||
if let Err(err) = open::that(&CONFIG.game.path) {
|
||||
let path = match config::get() {
|
||||
Ok(config) => config.game.path.for_edition(config.launcher.edition).to_path_buf(),
|
||||
Err(_) => CONFIG.game.path.for_edition(CONFIG.launcher.edition).to_path_buf(),
|
||||
};
|
||||
|
||||
if let Err(err) = open::that(path) {
|
||||
sender.input(AppMsg::Toast {
|
||||
title: tr("game-folder-opening-error"),
|
||||
description: Some(err.to_string())
|
||||
|
@ -567,7 +574,7 @@ impl SimpleComponent for App {
|
|||
})));
|
||||
|
||||
group.add_action::<ConfigFile>(&RelmAction::new_stateless(clone!(@strong sender => move |_| {
|
||||
if let Some(file) = anime_launcher_sdk::consts::config_file() {
|
||||
if let Ok(file) = anime_launcher_sdk::consts::config_file() {
|
||||
if let Err(err) = open::that(file) {
|
||||
sender.input(AppMsg::Toast {
|
||||
title: tr("config-file-opening-error"),
|
||||
|
@ -592,8 +599,10 @@ impl SimpleComponent for App {
|
|||
|
||||
group.add_action::<WishUrl>(&RelmAction::new_stateless(clone!(@strong sender => move |_| {
|
||||
std::thread::spawn(clone!(@strong sender => move || {
|
||||
let web_cache = CONFIG.game.path
|
||||
.join(unsafe { anime_launcher_sdk::anime_game_core::genshin::consts::DATA_FOLDER_NAME })
|
||||
let config = config::get().unwrap_or_else(|_| CONFIG.clone());
|
||||
|
||||
let web_cache = config.game.path.for_edition(config.launcher.edition)
|
||||
.join(GameEdition::from(config.launcher.edition).data_folder())
|
||||
.join("webCaches/Cache/Cache_Data/data_2");
|
||||
|
||||
if !web_cache.exists() {
|
||||
|
@ -668,7 +677,7 @@ impl SimpleComponent for App {
|
|||
sender.input(AppMsg::SetLoadingStatus(Some(Some(tr("downloading-background-picture")))));
|
||||
|
||||
if let Err(err) = crate::background::download_background() {
|
||||
tracing::error!("Failed to download background picture");
|
||||
tracing::error!("Failed to download background picture: {err}");
|
||||
|
||||
sender.input(AppMsg::Toast {
|
||||
title: tr("background-downloading-failed"),
|
||||
|
@ -689,19 +698,24 @@ impl SimpleComponent for App {
|
|||
Ok(None) => {
|
||||
for host in &CONFIG.components.servers {
|
||||
match components.sync(host) {
|
||||
Ok(true) => {
|
||||
// TODO: add changelog log here
|
||||
|
||||
Ok(changes) => {
|
||||
sender.input(AppMsg::Toast {
|
||||
title: tr("components-index-updated"),
|
||||
description: None
|
||||
description: if changes.is_empty() {
|
||||
None
|
||||
} else {
|
||||
let max_len = changes.iter().map(|line| line.len()).max().unwrap_or(80);
|
||||
|
||||
Some(changes.into_iter()
|
||||
.map(|line| format!("- {line}{}", " ".repeat(max_len - line.len())))
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n"))
|
||||
}
|
||||
});
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
Ok(false) => continue,
|
||||
|
||||
Err(err) => {
|
||||
tracing::error!("Failed to sync components index");
|
||||
|
||||
|
@ -737,16 +751,7 @@ impl SimpleComponent for App {
|
|||
Ok(None) => {
|
||||
for server in &CONFIG.patch.servers {
|
||||
match patch.sync(server) {
|
||||
Ok(true) => break,
|
||||
|
||||
Ok(false) => {
|
||||
tracing::error!("Failed to sync patch folder with remote: {server}");
|
||||
|
||||
sender.input(AppMsg::Toast {
|
||||
title: tr("patch-sync-failed"),
|
||||
description: None
|
||||
});
|
||||
}
|
||||
Ok(_) => break,
|
||||
|
||||
Err(err) => {
|
||||
tracing::error!("Failed to sync patch folder with remote: {server}: {err}");
|
||||
|
@ -1005,6 +1010,9 @@ impl SimpleComponent for App {
|
|||
LauncherState::PredownloadAvailable { .. } |
|
||||
LauncherState::Launch => launch::launch(sender),
|
||||
|
||||
LauncherState::FolderMigrationRequired { from, to, cleanup_folder } =>
|
||||
migrate_folder::migrate_folder(sender, from.to_owned(), to.to_owned(), cleanup_folder.to_owned()),
|
||||
|
||||
LauncherState::UnityPlayerPatchAvailable(patch) => apply_patch::apply_patch(sender, patch.to_owned()),
|
||||
LauncherState::XluaPatchAvailable(patch) => apply_patch::apply_patch(sender, patch.to_owned()),
|
||||
|
||||
|
@ -1015,7 +1023,8 @@ impl SimpleComponent for App {
|
|||
LauncherState::VoiceUpdateAvailable(diff) |
|
||||
LauncherState::VoiceNotInstalled(diff) |
|
||||
LauncherState::GameUpdateAvailable(diff) |
|
||||
LauncherState::GameNotInstalled(diff) => download_diff::download_diff(sender, self.progress_bar.sender().to_owned(), diff.to_owned()),
|
||||
LauncherState::GameNotInstalled(diff) =>
|
||||
download_diff::download_diff(sender, self.progress_bar.sender().to_owned(), diff.to_owned()),
|
||||
|
||||
LauncherState::VoiceOutdated(_) |
|
||||
LauncherState::GameOutdated(_) => ()
|
||||
|
|
|
@ -3,6 +3,8 @@ use relm4::{
|
|||
Sender
|
||||
};
|
||||
|
||||
use gtk::glib::clone;
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
use anime_launcher_sdk::config;
|
||||
|
@ -23,7 +25,8 @@ pub fn repair_game(sender: ComponentSender<App>, progress_bar_input: Sender<Prog
|
|||
match repairer::try_get_integrity_files(None) {
|
||||
Ok(mut files) => {
|
||||
// Add voiceovers files
|
||||
let game = Game::new(&config.game.path);
|
||||
let game_path = config.game.path.for_edition(config.launcher.edition).to_path_buf();
|
||||
let game = Game::new(&game_path);
|
||||
|
||||
if let Ok(voiceovers) = game.get_voice_packages() {
|
||||
for package in voiceovers {
|
||||
|
@ -61,10 +64,9 @@ pub fn repair_game(sender: ComponentSender<App>, progress_bar_input: Sender<Prog
|
|||
}
|
||||
}
|
||||
|
||||
let game_path = config.game.path.clone();
|
||||
let thread_sender = verify_sender.clone();
|
||||
|
||||
std::thread::spawn(move || {
|
||||
std::thread::spawn(clone!(@strong game_path => move || {
|
||||
for file in thread_files {
|
||||
let status = if config.launcher.repairer.fast {
|
||||
file.fast_verify(&game_path)
|
||||
|
@ -74,7 +76,7 @@ pub fn repair_game(sender: ComponentSender<App>, progress_bar_input: Sender<Prog
|
|||
|
||||
thread_sender.send((file, status)).unwrap();
|
||||
}
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
// We have [config.launcher.repairer.threads] copies of this sender + the original one
|
||||
|
@ -104,27 +106,48 @@ pub fn repair_game(sender: ComponentSender<App>, progress_bar_input: Sender<Prog
|
|||
|
||||
let total = broken.len() as f64;
|
||||
|
||||
// TODO: properly handle xlua patch
|
||||
let is_patch_applied = UnityPlayerPatch::from_folder(&config.patch.path).unwrap()
|
||||
.is_applied(&config.game.path).unwrap();
|
||||
let player_patch = UnityPlayerPatch::from_folder(&config.patch.path).unwrap()
|
||||
.is_applied(&game_path).unwrap();
|
||||
|
||||
tracing::debug!("Patch status: {}", is_patch_applied);
|
||||
let xlua_patch = XluaPatch::from_folder(&config.patch.path).unwrap()
|
||||
.is_applied(&game_path).unwrap();
|
||||
|
||||
fn should_ignore(path: &Path) -> bool {
|
||||
for part in ["UnityPlayer.dll", "xlua.dll", "crashreport.exe", "upload_crash.exe", "vulkan-1.dll"] {
|
||||
tracing::debug!("Patches status: player({player_patch}), xlua({xlua_patch})");
|
||||
|
||||
fn should_ignore(path: &Path, player_patch: bool, xlua_patch: bool) -> bool {
|
||||
// Files managed by launch.bat file
|
||||
for part in ["crashreport.exe", "upload_crash.exe"] {
|
||||
if path.ends_with(part) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// UnityPlayer patch related files
|
||||
if player_patch {
|
||||
for part in ["UnityPlayer.dll", "vulkan-1.dll"] {
|
||||
if path.ends_with(part) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Xlua patch related files
|
||||
if xlua_patch {
|
||||
for part in ["xlua.dll", "mhypbase.dll"] {
|
||||
if path.ends_with(part) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
for (i, file) in broken.into_iter().enumerate() {
|
||||
if !is_patch_applied || !should_ignore(&file.path) {
|
||||
tracing::debug!("Repairing: {}", file.path.to_string_lossy());
|
||||
if !should_ignore(&file.path, player_patch, xlua_patch) {
|
||||
tracing::debug!("Repairing file: {}", file.path.to_string_lossy());
|
||||
|
||||
if let Err(err) = file.repair(&config.game.path) {
|
||||
if let Err(err) = file.repair(&game_path) {
|
||||
sender.input(AppMsg::Toast {
|
||||
title: tr("game-file-repairing-error"),
|
||||
description: Some(err.to_string())
|
||||
|
@ -134,6 +157,10 @@ pub fn repair_game(sender: ComponentSender<App>, progress_bar_input: Sender<Prog
|
|||
}
|
||||
}
|
||||
|
||||
else {
|
||||
tracing::debug!("Skipped file: {}", file.path.to_string_lossy());
|
||||
}
|
||||
|
||||
progress_bar_input.send(ProgressBarMsg::UpdateProgress(i as u64, total as u64));
|
||||
}
|
||||
}
|
||||
|
|
57
src/ui/migrate_installation.rs
Normal file
57
src/ui/migrate_installation.rs
Normal file
|
@ -0,0 +1,57 @@
|
|||
use relm4::prelude::*;
|
||||
use relm4::component::*;
|
||||
|
||||
use gtk::prelude::*;
|
||||
|
||||
use crate::i18n::*;
|
||||
use super::first_run::default_paths::DefaultPathsApp;
|
||||
|
||||
pub struct MigrateInstallationApp {
|
||||
default_paths: AsyncController<DefaultPathsApp>,
|
||||
}
|
||||
|
||||
#[relm4::component(pub)]
|
||||
impl SimpleComponent for MigrateInstallationApp {
|
||||
type Init = ();
|
||||
type Input = ();
|
||||
type Output = ();
|
||||
|
||||
view! {
|
||||
adw::Window {
|
||||
set_default_size: (780, 560),
|
||||
set_modal: true,
|
||||
set_hide_on_close: true,
|
||||
|
||||
#[watch]
|
||||
set_title: Some(&tr("migrate-installation")),
|
||||
|
||||
gtk::Box {
|
||||
set_orientation: gtk::Orientation::Vertical,
|
||||
|
||||
adw::HeaderBar {
|
||||
add_css_class: "flat"
|
||||
},
|
||||
|
||||
append = model.default_paths.widget(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn init(
|
||||
_init: Self::Init,
|
||||
root: &Self::Root,
|
||||
_sender: ComponentSender<Self>,
|
||||
) -> ComponentParts<Self> {
|
||||
tracing::info!("Initializing migration window");
|
||||
|
||||
let model = Self {
|
||||
default_paths: DefaultPathsApp::builder()
|
||||
.launch(true)
|
||||
.detach()
|
||||
};
|
||||
|
||||
let widgets = view_output!();
|
||||
|
||||
ComponentParts { model, widgets }
|
||||
}
|
||||
}
|
|
@ -3,3 +3,4 @@ pub mod about;
|
|||
pub mod preferences;
|
||||
pub mod components;
|
||||
pub mod first_run;
|
||||
pub mod migrate_installation;
|
||||
|
|
|
@ -91,11 +91,11 @@ impl SimpleAsyncComponent for EnvironmentApp {
|
|||
|
||||
adw::EntryRow {
|
||||
set_title: "%command%",
|
||||
set_text: CONFIG.game.command.as_ref().unwrap_or(&String::new()),
|
||||
set_text: CONFIG.game.command.as_ref().unwrap_or(&String::new()).trim(),
|
||||
|
||||
connect_changed => |entry| {
|
||||
if let Ok(mut config) = config::get() {
|
||||
let command = entry.text().to_string();
|
||||
let command = entry.text().trim().to_string();
|
||||
|
||||
config.game.command = if command.is_empty() {
|
||||
None
|
||||
|
@ -158,7 +158,7 @@ impl SimpleAsyncComponent for EnvironmentApp {
|
|||
};
|
||||
|
||||
for (name, value) in &CONFIG.game.environment {
|
||||
model.variables.guard().push_back((name.clone(), value.clone()));
|
||||
model.variables.guard().push_back((name.trim().to_string(), value.trim().to_string()));
|
||||
}
|
||||
|
||||
let variables = model.variables.widget();
|
||||
|
@ -175,8 +175,8 @@ impl SimpleAsyncComponent for EnvironmentApp {
|
|||
match msg {
|
||||
EnvironmentMsg::Add => {
|
||||
if let Ok(mut config) = config::get() {
|
||||
let name = self.name.text().to_string();
|
||||
let value = self.value.text().to_string();
|
||||
let name = self.name.text().trim().to_string();
|
||||
let value = self.value.text().trim().to_string();
|
||||
|
||||
config.game.environment.insert(name.clone(), value.clone());
|
||||
|
||||
|
|
|
@ -9,14 +9,18 @@ use relm4::factory::{
|
|||
use gtk::prelude::*;
|
||||
use adw::prelude::*;
|
||||
|
||||
use anime_launcher_sdk::anime_game_core::prelude::*;
|
||||
use anime_launcher_sdk::wincompatlib::prelude::*;
|
||||
use anime_launcher_sdk::config;
|
||||
use anime_launcher_sdk::config::launcher::LauncherStyle;
|
||||
use anime_launcher_sdk::anime_game_core::prelude::*;
|
||||
use anime_launcher_sdk::components::*;
|
||||
use anime_launcher_sdk::components::wine::WincompatlibWine;
|
||||
use anime_launcher_sdk::wincompatlib::prelude::*;
|
||||
use anime_launcher_sdk::env_emulation::Environment;
|
||||
use anime_launcher_sdk::config::launcher::GameEdition;
|
||||
use anime_launcher_sdk::anime_game_core::genshin::consts::GameEdition as CoreGameEdition;
|
||||
|
||||
use super::main::PreferencesAppMsg;
|
||||
use crate::ui::migrate_installation::MigrateInstallationApp;
|
||||
use crate::ui::components;
|
||||
use crate::ui::components::*;
|
||||
use crate::i18n::*;
|
||||
|
@ -102,6 +106,7 @@ impl AsyncFactoryComponent for VoicePackageComponent {
|
|||
pub struct GeneralApp {
|
||||
voice_packages: AsyncFactoryVecDeque<VoicePackageComponent>,
|
||||
|
||||
migrate_installation: Controller<MigrateInstallationApp>,
|
||||
wine_components: AsyncController<ComponentsList<GeneralAppMsg>>,
|
||||
dxvk_components: AsyncController<ComponentsList<GeneralAppMsg>>,
|
||||
|
||||
|
@ -145,7 +150,9 @@ pub enum GeneralAppMsg {
|
|||
RemoveVoicePackage(DynamicIndex),
|
||||
SetVoicePackageSensitivity(DynamicIndex, bool),
|
||||
|
||||
OpenMigrateInstallation,
|
||||
RepairGame,
|
||||
WineOpen(&'static [&'static str]),
|
||||
|
||||
UpdateLauncherStyle(LauncherStyle),
|
||||
|
||||
|
@ -272,8 +279,6 @@ impl SimpleAsyncComponent for GeneralApp {
|
|||
set_title: &tr("launcher-language"),
|
||||
set_subtitle: &tr("launcher-language-description"),
|
||||
|
||||
// TODO: maybe simplify it by some way? e.g. specify such stuff in i18n mod
|
||||
|
||||
set_model: Some(>k::StringList::new(&model.languages.iter().map(|lang| lang.as_str()).collect::<Vec<&str>>())),
|
||||
|
||||
set_selected: {
|
||||
|
@ -297,9 +302,77 @@ impl SimpleAsyncComponent for GeneralApp {
|
|||
}
|
||||
},
|
||||
|
||||
adw::ComboRow {
|
||||
set_title: &tr("game-edition"),
|
||||
|
||||
set_model: Some(>k::StringList::new(&[
|
||||
&tr("global"),
|
||||
&tr("china")
|
||||
])),
|
||||
|
||||
set_selected: match CONFIG.launcher.edition {
|
||||
GameEdition::Global => 0,
|
||||
GameEdition::China => 1
|
||||
},
|
||||
|
||||
connect_selected_notify[sender] => move |row| {
|
||||
if is_ready() {
|
||||
#[allow(unused_must_use)]
|
||||
if let Ok(mut config) = config::get() {
|
||||
config.launcher.edition = match row.selected() {
|
||||
0 => GameEdition::Global,
|
||||
1 => GameEdition::China,
|
||||
|
||||
_ => unreachable!()
|
||||
};
|
||||
|
||||
// Select new game edition
|
||||
CoreGameEdition::from(config.launcher.edition).select();
|
||||
|
||||
config::update(config);
|
||||
|
||||
sender.output(PreferencesAppMsg::UpdateLauncherState);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
adw::ComboRow {
|
||||
set_title: &tr("game-environment"),
|
||||
set_subtitle: &tr("game-environment-description"),
|
||||
|
||||
set_model: Some(>k::StringList::new(&[
|
||||
"PC",
|
||||
"Android"
|
||||
])),
|
||||
|
||||
set_selected: match CONFIG.launcher.environment {
|
||||
Environment::PC => 0,
|
||||
Environment::Android => 1,
|
||||
|
||||
_ => unreachable!()
|
||||
},
|
||||
|
||||
connect_selected_notify => |row| {
|
||||
if is_ready() {
|
||||
if let Ok(mut config) = config::get() {
|
||||
config.launcher.environment = match row.selected() {
|
||||
0 => Environment::PC,
|
||||
1 => Environment::Android,
|
||||
|
||||
_ => unreachable!()
|
||||
};
|
||||
|
||||
config::update(config);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
#[local_ref]
|
||||
voice_packages -> adw::ExpanderRow {
|
||||
set_title: &tr("game-voiceovers")
|
||||
set_title: &tr("game-voiceovers"),
|
||||
set_subtitle: &tr("game-voiceovers-description")
|
||||
},
|
||||
|
||||
gtk::Box {
|
||||
|
@ -307,6 +380,13 @@ impl SimpleAsyncComponent for GeneralApp {
|
|||
set_spacing: 8,
|
||||
set_margin_top: 16,
|
||||
|
||||
gtk::Button {
|
||||
set_label: &tr("migrate-installation"),
|
||||
set_tooltip_text: Some(&tr("migrate-installation-description")),
|
||||
|
||||
connect_clicked => GeneralAppMsg::OpenMigrateInstallation
|
||||
},
|
||||
|
||||
gtk::Button {
|
||||
set_label: &tr("repair-game"),
|
||||
|
||||
|
@ -346,7 +426,7 @@ impl SimpleAsyncComponent for GeneralApp {
|
|||
VersionDiff::NotInstalled { .. } => &[]
|
||||
}
|
||||
|
||||
None => &["success"]
|
||||
None => &[]
|
||||
},
|
||||
|
||||
#[watch]
|
||||
|
@ -398,7 +478,12 @@ impl SimpleAsyncComponent for GeneralApp {
|
|||
PatchStatus::Preparation { .. } |
|
||||
PatchStatus::Testing { .. } => &["warning"],
|
||||
PatchStatus::Available { .. } => unsafe {
|
||||
if let Ok(true) = model.unity_player_patch.as_ref().unwrap_unchecked().is_applied(&CONFIG.game.path) {
|
||||
let path = match config::get() {
|
||||
Ok(config) => config.game.path.for_edition(config.launcher.edition).to_path_buf(),
|
||||
Err(_) => CONFIG.game.path.for_edition(CONFIG.launcher.edition).to_path_buf(),
|
||||
};
|
||||
|
||||
if let Ok(true) = model.unity_player_patch.as_ref().unwrap_unchecked().is_applied(path) {
|
||||
&["success"]
|
||||
} else {
|
||||
&["warning"]
|
||||
|
@ -420,7 +505,12 @@ impl SimpleAsyncComponent for GeneralApp {
|
|||
PatchStatus::Preparation { .. } => tr("patch-preparation-tooltip"),
|
||||
PatchStatus::Testing { .. } => tr("patch-testing-tooltip"),
|
||||
PatchStatus::Available { .. } => unsafe {
|
||||
if let Ok(true) = model.unity_player_patch.as_ref().unwrap_unchecked().is_applied(&CONFIG.game.path) {
|
||||
let path = match config::get() {
|
||||
Ok(config) => config.game.path.for_edition(config.launcher.edition).to_path_buf(),
|
||||
Err(_) => CONFIG.game.path.for_edition(CONFIG.launcher.edition).to_path_buf(),
|
||||
};
|
||||
|
||||
if let Ok(true) = model.unity_player_patch.as_ref().unwrap_unchecked().is_applied(path) {
|
||||
String::new()
|
||||
} else {
|
||||
tr("patch-not-applied-tooltip")
|
||||
|
@ -459,7 +549,12 @@ impl SimpleAsyncComponent for GeneralApp {
|
|||
PatchStatus::Preparation { .. } |
|
||||
PatchStatus::Testing { .. } => &["warning"],
|
||||
PatchStatus::Available { .. } => unsafe {
|
||||
if let Ok(true) = model.xlua_patch.as_ref().unwrap_unchecked().is_applied(&CONFIG.game.path) {
|
||||
let path = match config::get() {
|
||||
Ok(config) => config.game.path.for_edition(config.launcher.edition).to_path_buf(),
|
||||
Err(_) => CONFIG.game.path.for_edition(CONFIG.launcher.edition).to_path_buf(),
|
||||
};
|
||||
|
||||
if let Ok(true) = model.xlua_patch.as_ref().unwrap_unchecked().is_applied(path) {
|
||||
&["success"]
|
||||
} else {
|
||||
&["warning"]
|
||||
|
@ -481,7 +576,12 @@ impl SimpleAsyncComponent for GeneralApp {
|
|||
PatchStatus::Preparation { .. } => tr("patch-preparation-tooltip"),
|
||||
PatchStatus::Testing { .. } => tr("patch-testing-tooltip"),
|
||||
PatchStatus::Available { .. } => unsafe {
|
||||
if let Ok(true) = model.xlua_patch.as_ref().unwrap_unchecked().is_applied(&CONFIG.game.path) {
|
||||
let path = match config::get() {
|
||||
Ok(config) => config.game.path.for_edition(config.launcher.edition).to_path_buf(),
|
||||
Err(_) => CONFIG.game.path.for_edition(CONFIG.launcher.edition).to_path_buf(),
|
||||
};
|
||||
|
||||
if let Ok(true) = model.xlua_patch.as_ref().unwrap_unchecked().is_applied(path) {
|
||||
String::new()
|
||||
} else {
|
||||
tr("patch-not-applied-tooltip")
|
||||
|
@ -558,18 +658,18 @@ impl SimpleAsyncComponent for GeneralApp {
|
|||
#[watch]
|
||||
set_activatable: !model.selecting_wine_version,
|
||||
|
||||
#[watch]
|
||||
set_icon_name: if model.selecting_wine_version {
|
||||
Some("process-working-symbolic")
|
||||
} else {
|
||||
None
|
||||
},
|
||||
|
||||
connect_selected_notify[sender] => move |row| {
|
||||
if is_ready() {
|
||||
sender.input(GeneralAppMsg::SelectWine(row.selected() as usize));
|
||||
}
|
||||
} @wine_selected_notify
|
||||
} @wine_selected_notify,
|
||||
|
||||
add_suffix = >k::Spinner {
|
||||
set_spinning: true,
|
||||
|
||||
#[watch]
|
||||
set_visible: model.selecting_wine_version
|
||||
}
|
||||
},
|
||||
|
||||
adw::ActionRow {
|
||||
|
@ -595,6 +695,57 @@ impl SimpleAsyncComponent for GeneralApp {
|
|||
add = model.wine_components.widget(),
|
||||
},
|
||||
|
||||
add = &adw::PreferencesGroup {
|
||||
adw::ExpanderRow {
|
||||
set_title: &tr("wine-tools"),
|
||||
|
||||
add_row = &adw::ActionRow {
|
||||
set_title: &tr("command-line"),
|
||||
set_subtitle: "start cmd",
|
||||
|
||||
set_activatable: true,
|
||||
|
||||
connect_activated => GeneralAppMsg::WineOpen(&["start", "cmd"])
|
||||
},
|
||||
|
||||
add_row = &adw::ActionRow {
|
||||
set_title: &tr("registry-editor"),
|
||||
set_subtitle: "regedit",
|
||||
|
||||
set_activatable: true,
|
||||
|
||||
connect_activated => GeneralAppMsg::WineOpen(&["regedit"])
|
||||
},
|
||||
|
||||
add_row = &adw::ActionRow {
|
||||
set_title: &tr("explorer"),
|
||||
set_subtitle: "explorer",
|
||||
|
||||
set_activatable: true,
|
||||
|
||||
connect_activated => GeneralAppMsg::WineOpen(&["explorer"])
|
||||
},
|
||||
|
||||
add_row = &adw::ActionRow {
|
||||
set_title: &tr("task-manager"),
|
||||
set_subtitle: "taskmgr",
|
||||
|
||||
set_activatable: true,
|
||||
|
||||
connect_activated => GeneralAppMsg::WineOpen(&["taskmgr"])
|
||||
},
|
||||
|
||||
add_row = &adw::ActionRow {
|
||||
set_title: &tr("configuration"),
|
||||
set_subtitle: "winecfg",
|
||||
|
||||
set_activatable: true,
|
||||
|
||||
connect_activated => GeneralAppMsg::WineOpen(&["winecfg"])
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
add = &adw::PreferencesGroup {
|
||||
set_title: &tr("dxvk-version"),
|
||||
|
||||
|
@ -622,18 +773,18 @@ impl SimpleAsyncComponent for GeneralApp {
|
|||
#[watch]
|
||||
set_activatable: !model.selecting_dxvk_version,
|
||||
|
||||
#[watch]
|
||||
set_icon_name: if model.selecting_dxvk_version {
|
||||
Some("process-working-symbolic")
|
||||
} else {
|
||||
None
|
||||
},
|
||||
|
||||
connect_selected_notify[sender] => move |row| {
|
||||
if is_ready() {
|
||||
sender.input(GeneralAppMsg::SelectDxvk(row.selected() as usize));
|
||||
}
|
||||
} @dxvk_selected_notify
|
||||
} @dxvk_selected_notify,
|
||||
|
||||
add_suffix = >k::Spinner {
|
||||
set_spinning: true,
|
||||
|
||||
#[watch]
|
||||
set_visible: model.selecting_dxvk_version
|
||||
}
|
||||
},
|
||||
|
||||
adw::ActionRow {
|
||||
|
@ -674,6 +825,10 @@ impl SimpleAsyncComponent for GeneralApp {
|
|||
let mut model = Self {
|
||||
voice_packages: AsyncFactoryVecDeque::new(adw::ExpanderRow::new(), sender.input_sender()),
|
||||
|
||||
migrate_installation: MigrateInstallationApp::builder()
|
||||
.launch(())
|
||||
.detach(),
|
||||
|
||||
wine_components: ComponentsList::builder()
|
||||
.launch(ComponentsListInit {
|
||||
pattern: ComponentsListPattern {
|
||||
|
@ -684,9 +839,14 @@ impl SimpleAsyncComponent for GeneralApp {
|
|||
group.versions = group.versions.into_iter().take(12).collect();
|
||||
|
||||
let mut group: ComponentsListGroup = group.into();
|
||||
let mut recommended = 6;
|
||||
|
||||
if group.versions.len() > 6 {
|
||||
for i in 6..group.versions.len() {
|
||||
for i in 0..group.versions.len() {
|
||||
if recommended > 0 && group.versions[i].recommended {
|
||||
recommended -= 1;
|
||||
}
|
||||
|
||||
else {
|
||||
group.versions[i].recommended = false;
|
||||
}
|
||||
}
|
||||
|
@ -710,9 +870,14 @@ impl SimpleAsyncComponent for GeneralApp {
|
|||
group.versions = group.versions.into_iter().take(12).collect();
|
||||
|
||||
let mut group: ComponentsListGroup = group.into();
|
||||
let mut recommended = 6;
|
||||
|
||||
if group.versions.len() > 6 {
|
||||
for i in 6..group.versions.len() {
|
||||
for i in 0..group.versions.len() {
|
||||
if recommended > 0 && group.versions[i].recommended {
|
||||
recommended -= 1;
|
||||
}
|
||||
|
||||
else {
|
||||
group.versions[i].recommended = false;
|
||||
}
|
||||
}
|
||||
|
@ -809,10 +974,11 @@ impl SimpleAsyncComponent for GeneralApp {
|
|||
config::update(config.clone());
|
||||
|
||||
let package = VoicePackage::with_locale(package.locale).unwrap();
|
||||
let game_path = config.game.path.for_edition(config.launcher.edition).to_path_buf();
|
||||
|
||||
if package.is_installed_in(&config.game.path) {
|
||||
if package.is_installed_in(&game_path) {
|
||||
std::thread::spawn(move || {
|
||||
if let Err(err) = package.delete_in(&config.game.path) {
|
||||
if let Err(err) = package.delete_in(game_path) {
|
||||
tracing::error!("Failed to delete voice package: {:?}", package.locale());
|
||||
|
||||
sender.input(GeneralAppMsg::Toast {
|
||||
|
@ -839,17 +1005,48 @@ impl SimpleAsyncComponent for GeneralApp {
|
|||
}
|
||||
}
|
||||
|
||||
GeneralAppMsg::OpenMigrateInstallation => unsafe {
|
||||
if let Some(window) = crate::ui::main::PREFERENCES_WINDOW.as_ref() {
|
||||
self.migrate_installation.widget().set_transient_for(Some(window.widget()));
|
||||
}
|
||||
|
||||
self.migrate_installation.widget().show();
|
||||
}
|
||||
|
||||
#[allow(unused_must_use)]
|
||||
GeneralAppMsg::RepairGame => {
|
||||
sender.output(Self::Output::RepairGame);
|
||||
}
|
||||
|
||||
GeneralAppMsg::WineOpen(executable) => {
|
||||
let config = config::get().unwrap_or_else(|_| CONFIG.clone());
|
||||
|
||||
if let Ok(Some(wine)) = config.get_selected_wine() {
|
||||
let result = wine.to_wine(config.components.path, Some(config.game.wine.builds.join(&wine.name)))
|
||||
.with_prefix(config.game.wine.prefix)
|
||||
.with_loader(WineLoader::Current)
|
||||
.with_arch(WineArch::Win64)
|
||||
.run_args(executable);
|
||||
|
||||
if let Err(err) = result {
|
||||
sender.input(GeneralAppMsg::Toast {
|
||||
title: tr_args("wine-run-error", [
|
||||
("executable", executable.join(" ").into())
|
||||
]),
|
||||
description: Some(err.to_string())
|
||||
});
|
||||
|
||||
tracing::error!("Failed to run {:?} using wine: {err}", executable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused_must_use)]
|
||||
GeneralAppMsg::UpdateLauncherStyle(style) => {
|
||||
if style == LauncherStyle::Classic && !KEEP_BACKGROUND_FILE.exists() {
|
||||
if let Err(err) = crate::background::download_background() {
|
||||
tracing::error!("Failed to download background picture");
|
||||
|
||||
|
||||
sender.input(GeneralAppMsg::Toast {
|
||||
title: tr("background-downloading-failed"),
|
||||
description: Some(err.to_string())
|
||||
|
@ -884,16 +1081,13 @@ impl SimpleAsyncComponent for GeneralApp {
|
|||
self.downloaded_wine_versions = wine::get_downloaded(&CONFIG.components.path, &CONFIG.game.wine.builds)
|
||||
.unwrap_or_default()
|
||||
.into_iter()
|
||||
.flat_map(|group| group.versions
|
||||
.into_iter()
|
||||
.map(move |version| (
|
||||
version.clone(),
|
||||
version.features.unwrap_or_else(
|
||||
|| group.features.to_owned().unwrap_or_default()
|
||||
))
|
||||
)
|
||||
)
|
||||
.collect();
|
||||
.flat_map(|group| group.versions.clone().into_iter()
|
||||
.map(move |version| {
|
||||
let features = version.features_in(&group).unwrap_or_default();
|
||||
|
||||
(version, features)
|
||||
})
|
||||
).collect();
|
||||
|
||||
self.selected_wine_version = if let Some(selected) = &CONFIG.game.wine.selected {
|
||||
let mut index = 0;
|
||||
|
|
|
@ -57,11 +57,10 @@ impl SimpleAsyncComponent for PreferencesApp {
|
|||
preferences_window = adw::PreferencesWindow {
|
||||
set_title: Some(&tr("preferences")),
|
||||
set_default_size: (700, 560),
|
||||
|
||||
set_hide_on_close: true,
|
||||
set_modal: true,
|
||||
|
||||
// FIXME: doesn't work for any reason
|
||||
set_search_enabled: false,
|
||||
set_search_enabled: true,
|
||||
|
||||
add = model.general.widget(),
|
||||
add = model.enhancements.widget(),
|
||||
|
|
Loading…
Add table
Reference in a new issue