Merge remote-tracking branch 'upstream/main' into zh-translation

This commit is contained in:
Tiger Soldier 2023-03-06 09:52:40 -08:00
commit f46ae89dca
31 changed files with 538 additions and 145 deletions

View file

@ -10,14 +10,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added ### Added
- Added game repairing function - Added game repairing function
- Added french translations (#81)
- Used `open` library for xdg (#84)
- Added dynamic components loading
### Fixed ### Fixed
- Forced `format_lang` to return regions for language codes - Forced `format_lang` to return regions for language codes
- Fixed titlebar behavior on some DEs
### Changed ### Changed
- Changed default language from en to en-us - Changed default language from en to en-us
- Moved integer scaling, fsr and nis into separate group in gamescope settings
## 3.0.1 ## 3.0.1

26
Cargo.lock generated
View file

@ -31,7 +31,7 @@ dependencies = [
[[package]] [[package]]
name = "anime-game-core" name = "anime-game-core"
version = "1.3.6" version = "1.3.8"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bzip2", "bzip2",
@ -46,6 +46,7 @@ dependencies = [
"serde_json", "serde_json",
"sysinfo", "sysinfo",
"tar", "tar",
"thiserror",
"tracing", "tracing",
"xz", "xz",
"zip", "zip",
@ -64,6 +65,7 @@ dependencies = [
"lazy_static", "lazy_static",
"libadwaita", "libadwaita",
"md-5", "md-5",
"open",
"relm4", "relm4",
"rfd", "rfd",
"serde_json", "serde_json",
@ -74,7 +76,7 @@ dependencies = [
[[package]] [[package]]
name = "anime-launcher-sdk" name = "anime-launcher-sdk"
version = "0.2.5" version = "0.3.0"
dependencies = [ dependencies = [
"anime-game-core", "anime-game-core",
"anyhow", "anyhow",
@ -862,9 +864,9 @@ checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa"
[[package]] [[package]]
name = "fs_extra" name = "fs_extra"
version = "1.2.0" version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394" checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
[[package]] [[package]]
name = "futures" name = "futures"
@ -1684,6 +1686,16 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]]
name = "open"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2078c0039e6a54a0c42c28faa984e115fb4c2d5bf2208f77d1961002df8576f8"
dependencies = [
"pathdiff",
"windows-sys 0.42.0",
]
[[package]] [[package]]
name = "openssl-probe" name = "openssl-probe"
version = "0.1.5" version = "0.1.5"
@ -1785,6 +1797,12 @@ dependencies = [
"subtle", "subtle",
] ]
[[package]]
name = "pathdiff"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
[[package]] [[package]]
name = "pbkdf2" name = "pbkdf2"
version = "0.11.0" version = "0.11.0"

View file

@ -20,6 +20,7 @@ relm4 = { version = "0.5", features = ["macros", "libadwaita"] }
gtk = { package = "gtk4", version = "0.5", features = ["v4_8"] } gtk = { package = "gtk4", version = "0.5", features = ["v4_8"] }
adw = { package = "libadwaita", version = "0.2", features = ["v1_2"] } adw = { package = "libadwaita", version = "0.2", features = ["v1_2"] }
rfd = { version = "0.11", features = ["xdg-portal"], default-features = false } rfd = { version = "0.11", features = ["xdg-portal"], default-features = false }
open = "3.2.0"
anime-launcher-sdk = { path = "anime-launcher-sdk" } anime-launcher-sdk = { path = "anime-launcher-sdk" }

@ -1 +1 @@
Subproject commit ca8d64906a8c8e21edb512552bbd89460ce37836 Subproject commit 42b738dc1ec5be8e6ced48501604622b8d0ab91e

View file

@ -17,4 +17,5 @@ game-name = {-game-name-1}{-game-name-2} {-game-name-3}{-game-name-4}
en-us = English en-us = English
ru-ru = Русский ru-ru = Русский
de-de = Deutsch de-de = Deutsch
fr-fr = Français
zh-cn = 简体中文 zh-cn = 简体中文

View file

@ -8,10 +8,12 @@ failed-get-selected-wine = Die ausgewählte Wine version konnte nicht abgerufen
downloading-failed = Herunterladen fehlgeschlagen downloading-failed = Herunterladen fehlgeschlagen
unpacking-failed = Entpacken fehlgeschlagen unpacking-failed = Entpacken fehlgeschlagen
game-file-repairing-error = Failed to repair game file game-file-repairing-error = Reparieren der Spieldatei fehlgeschlagen
integrity-files-getting-error = Failed to get integrity files integrity-files-getting-error = Integritätsdateien konnten nicht abgerufen werden
background-downloading-failed = Download des Hintergrundbildes fehlgeschlagen background-downloading-failed = Download des Hintergrundbildes fehlgeschlagen
components-index-sync-failed = Failed to sync components index
components-index-verify-failed = Failed to verify components index
config-update-error = Speichern der Konfiguration fehlgeschlagen config-update-error = Speichern der Konfiguration fehlgeschlagen
wine-prefix-update-failed = Aktualisierung des wine prefix fehlgeschlagen wine-prefix-update-failed = Aktualisierung des wine prefix fehlgeschlagen
dxvk-install-failed = DXVK konnte nicht installiert werden dxvk-install-failed = DXVK konnte nicht installiert werden

View file

@ -1,6 +1,13 @@
game-resolution = Spiel-Auflösung game-resolution = Spiel-Auflösung
gamescope-resolution = Gamescope-Auflösung gamescope-resolution = Gamescope-Auflösung
upscaling = Upscaling
integer-scaling = Integer-Skalierung
integer-scaling-description = Verwandelt jeden Pixel in eine quadratische oder rechteckige Gruppe mit einer ganzzahligen Anzahl gleichfarbiger Pixel. Verhindert Schärfeverluste bei der Skalierung von Full HD auf 4K
gamescope-fsr-description = Eine von AMD entwickelte Open-Source-Upscaling-Technik für bessere Upscaling-Qualität
nis-description = Eine Open-Source-Upscaling-Technik, die von Nvidia als herstellerübergreifende, kostengünstige Alternative zu ihrer proprietären DLSS-Lösung entwickelt wurde, d. h. sie funktioniert sowohl auf AMD- und Intel-GPUs als auch auf Nvidia-GPUs
other-settings = Andere Einstellungen other-settings = Andere Einstellungen
framerate-limit = Framerate-Limit framerate-limit = Framerate-Limit
unfocused-framerate-limit = Unfokussiert Framerate-Limit unfocused-framerate-limit = Unfokussiert Framerate-Limit
integer-scaling = Integer-Skalierung

View file

@ -24,6 +24,7 @@ restart = Neustarten
loading-data = Laden Daten loading-data = Laden Daten
downloading-background-picture = Hintergrundbild am Herunterladen downloading-background-picture = Hintergrundbild am Herunterladen
updating-components-index = Updating components index
loading-game-version = Lade version des Spiels loading-game-version = Lade version des Spiels
loading-patch-status = Lade version des Patch loading-patch-status = Lade version des Patch
loading-launcher-state = Lade Launcher status loading-launcher-state = Lade Launcher status
@ -35,8 +36,8 @@ loading-launcher-state--patch = Launcher status am laden: Verifizierung des inst
checking-free-space = Überprüfe Freien Speicherplatz checking-free-space = Überprüfe Freien Speicherplatz
downloading = Lade Herunter downloading = Lade Herunter
unpacking = Entpacken unpacking = Entpacken
verifying-files = Verifying files verifying-files = Verifiziere Dateien
repairing-files = Repairing files repairing-files = Repariere Dateien
launch = Starten launch = Starten

View file

@ -12,6 +12,8 @@ game-file-repairing-error = Failed to repair game file
integrity-files-getting-error = Failed to get integrity files integrity-files-getting-error = Failed to get integrity files
background-downloading-failed = Failed to download background picture background-downloading-failed = Failed to download background picture
components-index-sync-failed = Failed to sync components index
components-index-verify-failed = Failed to verify components index
config-update-error = Failed to save config config-update-error = Failed to save config
wine-prefix-update-failed = Failed to update wine prefix wine-prefix-update-failed = Failed to update wine prefix
dxvk-install-failed = Failed to install DXVK dxvk-install-failed = Failed to install DXVK

View file

@ -1,6 +1,13 @@
game-resolution = Game resolution game-resolution = Game resolution
gamescope-resolution = Gamescope resolution gamescope-resolution = Gamescope resolution
upscaling = Upscaling
integer-scaling = Integer scaling
integer-scaling-description = Turns each pixel into a square or rectangular group of integer number of same-color pixels. Prevents sharpness loss when scaling Full HD to 4K
gamescope-fsr-description = An open-source upscaling technique developed by AMD for better upscaling quality
nis-description = An open source upscaling technique developed by Nvidia as a cross-vendor, low-overhead alternative to their proprietary DLSS solution, meaning it works on AMD and Intel GPUs as well as Nvidia GPUs
other-settings = Other settings other-settings = Other settings
framerate-limit = Framerate limit framerate-limit = Framerate limit
unfocused-framerate-limit = Unfocused framerate limit unfocused-framerate-limit = Unfocused framerate limit
integer-scaling = Integer scaling

View file

@ -24,6 +24,7 @@ restart = Restart
loading-data = Loading data loading-data = Loading data
downloading-background-picture = Downloading background picture downloading-background-picture = Downloading background picture
updating-components-index = Updating components index
loading-game-version = Loading game version loading-game-version = Loading game version
loading-patch-status = Loading patch status loading-patch-status = Loading patch status
loading-launcher-state = Loading launcher state loading-launcher-state = Loading launcher state

View file

@ -0,0 +1,58 @@
wine = Wine
synchronization = Synchronisation
wine-sync-description = Technologie utilisé pour synchroniser les évènements wine internes
language = Langue
wine-lang-description = Langue utilisé dans l'environnement wine. Peut résoudre des problèmes de clavier
system = Système
borderless-window = Utiliser une fenêtre sans bordure
virtual-desktop = Bureau virtuel
game = Jeu
hud = HUD
fsr = FSR
fsr-description = Permet d'upscale le jeu à la taille de l'écran. Pour l'utiliser, sélectionnez une résolution plus basse en jeu, et appuyez sur Alt+Entrée
ultra-quality = Qualité ultra
quality = Qualité
balanced = Équilibré
performance = Performances
gamemode = Gamemode
gamemode-description = Donne la priorité au jeu sur le reste des processus du système
gamescope = Gamescope
gamescope-description = Gamescope est un outil fait par Valve qui permet aux jeux de se lancer dans une instance Xwayland isolée, et qui est compatible avec les cartes graphiques AMD, Intel et NVidia
discord-rpc = Activité Discord
discord-rpc-description = Permet à Discord d'afficher à vos amis des informations sur le jeu auquel vous jouez actuellement
title = Titre
description = Description
fps-unlocker = Déblocage des FPS
enabled = Activer
fps-unlocker-description = Enlève les limitations de FPS en modifiant la mémoire du jeu. Peut être détecté par l'anticheat
power-saving = Économie d'énergie
power-saving-description = Limite automatiquement les FPS à 10 et baisse la priorité du processus quand le jeu n'est plus focus (lors d'un alt+tab par exemple)
monitor = Écran
monitor-description = Écran sur lequel le jeu se lancera
window-mode = Type de fenêtre
borderless = Sans bordure
popup = Popup
fullscreen = Plein écran
priority = Priorité
priority-description = Priorité du processus du jeu
realtime = Temps réel
high = Haut
above-normal = Au dessus de la normale
normal = Normale
below-normal = En dessous de la normal
low = Bas

View file

@ -0,0 +1,7 @@
environment = Environnement
game-command = Commande du jeu
game-command-description = Commande utilisée pour lancer le jeu. %command% est remplacé par la commande générée automatiquement par le launcher. Vous pouvez utiliser par exemple : gamemoderun '%command%'
new-variable = Nouvelle variable
name = Nom
value = Valeur
add = Ajouter

View file

@ -0,0 +1,38 @@
launcher-folder-opening-error = Impossible d'ouvrir l'emplacement du launcher
game-folder-opening-error = Impossible d'ouvrir l'emplacement du jeu
config-file-opening-error = Impossible d'ouvrir le fichier de configuration
debug-file-opening-error = Impossible d'ouvrir le fichier débug
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é
unpacking-failed = L'extraction a échoué
game-file-repairing-error = Impossible de réparer les fichiers du jeu
integrity-files-getting-error = Impossible de récupérer les fichiers d'intégrité du jeu
background-downloading-failed = Impossible de télécharger l'image de fond
components-index-sync-failed = Failed to sync components index
components-index-verify-failed = Failed to verify components index
config-update-error = Impossible d'enregistrer la configuration
wine-prefix-update-failed = Impossible de mettre à jour le préfix wine
dxvk-install-failed = Impossible d'installer DXVK
voice-package-deletion-error = La suppression des pack de voix a échoué
game-diff-finding-error = Impossible de trouver la diff du jeu
patch-info-fetching-error = Impossible de récupérer les informations du patch
launcher-state-updating-error = Impossible de mettre à jour l'état du launcher
package-not-available = Le packet {$package} n'est pas disponible
wine-download-error = Le téléchargement de wine a échoué
wine-unpack-errror = L'extraction de wine a échoué
wine-install-failed = L'installation de wine a échoué
dxvk-download-error = Le téléchargement de DXVK a échoué
dxvk-unpack-error = L'extraction de DXVK a échoué
dxvk-apply-error = L'application de DXVK a échoué
downloaded-wine-list-failed = Impossible de lister les versions de wine téléchargées
patch-sync-failed = Impossible de synchroniser le patch
patch-state-check-failed = Impossible de déterminer l'état du patch
game-patching-error = Le patch du jeu a échoué

View file

@ -0,0 +1,54 @@
welcome = Bienvenu
welcome-page-message =
Bonjour ! Bienvenu dans An Anime Game Launcher
Nous devons préparer quelques choses et télécharger les composants par défaut avant que vous ne puissiez démarrer le jeu
tos-violation-warning = Avertissement : Non-respect des CGU
tos-violation-warning-message =
Ce launcher est un outil non-officiel, il n'est associé ni à {company-name}, ni à {company-alter-name}.
Cet outil est conçu pour faciliter l'accès au jeu {game-name} sur Linux, et a été créé dans le seul but d'installer et de lancer le jeu plus facilement.
L'outil utilise pour cela des composants existant pour fournir à l'utilisateur une expérience simple.
Cependant, certains composants utilisés ne respectent pas les Conditions Générales d'Utilisation de {company-name} pour {game-name}.
Ainsi, si vous utilisez ce launcher, votre compte joueur peut être identifié comme non conformes aux CGU par {company-name}/{company-alter-name}.
Si c'est le cas, étant donné que votre compte n'est pas conforme aux CGU, {company-name}/{company-alter-name} se réservent le droit d'agir comme bon leur semble. Leurs actions peuvent notamment inclure le bannissement de votre compte.
Si vous comprenez ces risques, appuyez sur "Continuer" pour venir explorer le monde de Teyvat !
dependencies = Dépendances
missing-dependencies-title = Il vous manque des dépendances !
missing-dependencies-message = Vous devez installer certain packets sur votre système avant de continuer la procédure d'installation
default-paths = Emplacements par défaut
choose-default-paths = Choisissez les emplacements par défaut
show-all-folders = Je sais ce que je fait
show-all-folders-subtitle = Afficher plus de paramètres de sélection d'emplacement. « Do as I say »...
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
patch-folder = Emplacement du patch
temp-folder = Dossier temporaire
select-voice-packages = Sélectionnez les packs de voix
download-components = Téléchargement des composants
download-dxvk = Téléchargement de DXVK
apply-dxvk = Application de DXVK
finish = Terminer
finish-title = Tout est bon !
finish-message = Tous les composants ont été téléchargé. Vous pouvez désormais redémarrer le launcher et télécharger le jeu. Bienvenu au club !

View file

@ -0,0 +1,13 @@
game-resolution = Résolution du jeu
gamescope-resolution = Résolution de Gamescope
upscaling = Upscaling (mise à l'échelle intelligente)
integer-scaling = Mise à l'échelle à l'entier
integer-scaling-description = Transforme chaque pixel en un nombre entier de pixel de même couleur, sous la forme d'un carré ou d'un rectangle. Permet d'éviter l'effet de flou lors de la mise à l'échelle entre la Full-HD et la 4K par exemple
gamescope-fsr-description = Une technique de mise à l'échelle Open Source développée par AMD pour avoir une meilleur qualité de mise à l'échelle
nis-description = Une technologie de mise à l'échelle Open Source développée par NVidia comme alternative compatible avec les autres marques à leur solution DLSS qui est propriétaire. Ainsi, cette option foctionne non seulement sur les cartes graphiques NVidia, mais aussi sur celles d'Intel et d'AMD.
other-settings = Autres paramètres
framerate-limit = Limitation des FPS
unfocused-framerate-limit = Limitation des FPS hors focus

View file

@ -0,0 +1,47 @@
appearance = Apparence
modern = Moderne
classic = Classique
update-background = Mise à jour automatique de l'image de fond
update-background-description = Télécharger l'image de fond du launcher officiel. Vous pouvez la désactiver pour utiliser une image personnalisée à la place
launcher-language = Langue du launcher
launcher-language-description = S'applique après un redémarrage
game-voiceovers = Voiceover en jeu
english = Anglais
japanese = Japonais
korean = Coréen
chinese = Chinois
repair-game = Réparer le jeu
status = Statut
game-version = Version du jeu
game-not-installed = le jeu n'est pas installé
game-predownload-available = Mise à jour du jeu disponible en pré-téléchargement : {$old} -> {$new}
game-update-available = Mise à jour du jeu disponible : {$old} -> {$new}
game-outdated = La version du jeu installée est trop ancienne et ne peut pas être mise à jour. Dernière version : {$latest}
patch-version = Version du patch
patch-not-available = patch non disponible
patch-not-available-tooltip = Impossible d'accéder aux serveurs de patch
patch-outdated = pas à jour ({$current})
patch-outdated-tooltip = Le patch n'est pas à jour : {$current} -> {$latest}
patch-preparation = préparation
patch-preparation-tooltip = Le patch est en développement
patch-testing-tooltip = Patch de test disponible
selected-version = Version sélectionnée
recommended-only = Versions recommandées uniquement
wine-version = Version de wine
wine-recommended-description = N'afficher que les versions recommandées de wine
dxvk-version = Version de DXVK
dxvk-recommended-description = N'afficher que les versions recommandées de DXVK

View file

@ -0,0 +1,57 @@
custom = Personalisé
none = Auccun
default = Par défaut
details = Détails
width = Largeur
height = Hauteur
# Menu items
launcher-folder = Dossier du launcher
game-folder = Dossier du jeu
config-file = Fichier de configuration
debug-file = Fichier débug
about = À propos
close = Fermer
save = Sauvegarder
continue = Continuer
exit = Quitter
check = Vérifier
restart = Redémarer
loading-data = Chargement des données
downloading-background-picture = Téléchargement de l'image de fond
updating-components-index = Updating components index
loading-game-version = Chargement de la version du jeu
loading-patch-status = Chargement du statut du patch
loading-launcher-state = Chargement de l'état du launcher
loading-launcher-state--game = Chargement de l'état du launcher : vérification de la version du jeu
loading-launcher-state--voice = Chargement de l'état du launcher : vérification des voiceover en {$locale}
loading-launcher-state--patch = Chargement de l'état du launcher : vérification des patch installés
checking-free-space = Vérification de l'espace disque disponible
downloading = Téléchargement
unpacking = Décompression
verifying-files = Vérification des fichiers
repairing-files = Réparation des fichiers
launch = Lancer
apply-patch = Appliquer le patch
download-wine = Télécharger wine
create-prefix = Créer le préfix wine
update = Mettre à jour
download = Télécharger
predownload-update = Pré-télécharger la mise à jour {$version} ({$size})
main-window--patch-unavailable-tooltip = Les serveurs de patch ne sont pas disponible, et le launcher ne peut pas vérifier l'état de patch du jeu. Lancez le jeu à vos risques et périls
main-window--patch-outdated-tooltip = Le patch n'est pas à jour ou encore en train d'être préparé. Il n'est donc pas encore disponible. Revenez plus tard pour voir son état
main-window--version-outdated-tooltip = La version du jeu est trop ancienne et ne peut pas être mise à jour
preferences = Préférences
general = Général
enhancements = Améliorations

View file

@ -12,6 +12,8 @@ game-file-repairing-error = Не удалось починить игровой
integrity-files-getting-error = Не удалось получить верные данные о файлах игры integrity-files-getting-error = Не удалось получить верные данные о файлах игры
background-downloading-failed = Не удалось загрузить фоновое изображение background-downloading-failed = Не удалось загрузить фоновое изображение
components-index-sync-failed = Не удалось синхронизировать индекс компонентов
components-index-verify-failed = Не удалось проверить индекс компонентов
config-update-error = Ошибка сохранения настроек config-update-error = Ошибка сохранения настроек
wine-prefix-update-failed = Ошибка обновления префикса Wine wine-prefix-update-failed = Ошибка обновления префикса Wine
dxvk-install-failed = Ошибка установки DXVK dxvk-install-failed = Ошибка установки DXVK

View file

@ -1,6 +1,13 @@
game-resolution = Разрешение игры game-resolution = Разрешение игры
gamescope-resolution = Разрешение Gamescope gamescope-resolution = Разрешение Gamescope
upscaling = Масштабирование
integer-scaling = Целочисленное масштабирование
integer-scaling-description = Переводит каждый пиксель в квадрат или прямоугольник из целого числа пикселей одного цвета. Предотвращает потерю резкости при масштабировании Full HD до 4K
gamescope-fsr-description = Открытая техника масштабирования с сохранением хорошего качества изображения, разработанная AMD
nis-description = Открытая техника масштабирования с сохранением хорошего качества изображения, разработанная Nvidia для замены DLSS и работающая на видеокартах AMD, Intel и Nvidia
other-settings = Другие настройки other-settings = Другие настройки
framerate-limit = Лимит числа кадров framerate-limit = Лимит числа кадров
unfocused-framerate-limit = Лимит числа кадров вне фокуса unfocused-framerate-limit = Лимит числа кадров вне фокуса
integer-scaling = Целочисленное масштабирование

View file

@ -25,6 +25,7 @@ restart = Перезапустить
loading-data = Загрузка данных loading-data = Загрузка данных
downloading-background-picture = Загрузка фонового изображения downloading-background-picture = Загрузка фонового изображения
updating-components-index = Обновление индекса компонентов
loading-game-version = Загрузка версии игры loading-game-version = Загрузка версии игры
loading-patch-status = Загрузка статуса патча loading-patch-status = Загрузка статуса патча
loading-launcher-state = Загрузка статуса лаунчера loading-launcher-state = Загрузка статуса лаунчера

View file

@ -61,8 +61,6 @@ pub fn download_background() -> anyhow::Result<()> {
downloader.continue_downloading = false; downloader.continue_downloading = false;
if let Err(err) = downloader.download_to(crate::BACKGROUND_FILE.as_path(), |_, _| {}) { if let Err(err) = downloader.download_to(crate::BACKGROUND_FILE.as_path(), |_, _| {}) {
let err: std::io::Error = err.into();
anyhow::bail!(err); anyhow::bail!(err);
} }

View file

@ -14,6 +14,7 @@ pub const SUPPORTED_LANGUAGES: &[LanguageIdentifier] = &[
langid!("en-us"), langid!("en-us"),
langid!("ru-ru"), langid!("ru-ru"),
langid!("de-de"), langid!("de-de"),
langid!("fr-fr"),
langid!("zh-cn"), langid!("zh-cn"),
]; ];

View file

@ -55,7 +55,8 @@ impl SimpleComponent for AboutDialog {
add_credit_section: (Some("An Anime Team"), &[ add_credit_section: (Some("An Anime Team"), &[
"@Marie https://github.com/Mar0xy", "@Marie https://github.com/Mar0xy",
"@lane https://github.com/laurinneff", "@lane https://github.com/laurinneff",
"@jiro-too https://github.com/jiro-too" "@jiro-too https://github.com/jiro-too",
"@cybik https://github.com/cybik"
]), ]),
set_artists: &[ set_artists: &[
@ -64,7 +65,8 @@ impl SimpleComponent for AboutDialog {
set_translator_credits: &[ set_translator_credits: &[
"Русский, English — Nikita Podvirnyy https://github.com/krypt0nn", "Русский, English — Nikita Podvirnyy https://github.com/krypt0nn",
"Deutsch — @Marie https://github.com/Mar0xy" "Deutsch — @Marie https://github.com/Mar0xy",
"Français — @zeGolem https://github.com/zeGolem"
].join("\n"), ].join("\n"),
set_debug_info: &[ set_debug_info: &[

View file

@ -27,7 +27,7 @@ pub struct ComponentsListGroup {
impl From<wine::Group> for ComponentsListGroup { impl From<wine::Group> for ComponentsListGroup {
fn from(group: wine::Group) -> Self { fn from(group: wine::Group) -> Self {
Self { Self {
title: group.name, title: group.title,
versions: group.versions.into_iter().map(|version| version.into()).collect() versions: group.versions.into_iter().map(|version| version.into()).collect()
} }
} }
@ -36,7 +36,7 @@ impl From<wine::Group> for ComponentsListGroup {
impl From<dxvk::Group> for ComponentsListGroup { impl From<dxvk::Group> for ComponentsListGroup {
fn from(group: dxvk::Group) -> Self { fn from(group: dxvk::Group) -> Self {
Self { Self {
title: group.name, title: group.title,
versions: group.versions.into_iter().map(|version| version.into()).collect() versions: group.versions.into_iter().map(|version| version.into()).collect()
} }
} }
@ -56,7 +56,7 @@ impl From<wine::Version> for ComponentsListVersion {
name: version.name, name: version.name,
title: version.title, title: version.title,
uri: version.uri, uri: version.uri,
recommended: version.recommended recommended: true // FIXME
} }
} }
} }
@ -67,7 +67,7 @@ impl From<dxvk::Version> for ComponentsListVersion {
name: version.name.clone(), name: version.name.clone(),
title: version.name, title: version.name,
uri: version.uri, uri: version.uri,
recommended: version.recommended recommended: true // FIXME
} }
} }
} }

View file

@ -13,7 +13,7 @@ use std::path::PathBuf;
use super::main::FirstRunAppMsg; use super::main::FirstRunAppMsg;
use crate::ui::components::*; use crate::ui::components::*;
use crate::i18n::*; use crate::i18n::*;
use crate::FIRST_RUN_FILE; use crate::*;
fn get_installer(uri: &str, temp: Option<&PathBuf>, speed_limit: u64) -> anyhow::Result<Installer> { fn get_installer(uri: &str, temp: Option<&PathBuf>, speed_limit: u64) -> anyhow::Result<Installer> {
let mut installer = Installer::new(uri)?; let mut installer = Installer::new(uri)?;
@ -264,8 +264,9 @@ impl SimpleAsyncComponent for DownloadComponentsApp {
wine_combo: adw::ComboRow::new(), wine_combo: adw::ComboRow::new(),
dxvk_combo: adw::ComboRow::new(), dxvk_combo: adw::ComboRow::new(),
wine_versions: wine::get_groups()[0].versions.clone().into_iter().filter(|version| version.recommended).collect(), // FIXME: .filter(|version| version.recommended)
dxvk_versions: dxvk::get_groups()[0].versions.clone().into_iter().filter(|version| version.recommended).collect(), wine_versions: wine::get_groups(&CONFIG.components.path).unwrap_or_default()[0].versions.clone().into_iter().collect(),
dxvk_versions: dxvk::get_groups(&CONFIG.components.path).unwrap_or_default()[0].versions.clone().into_iter().collect(),
downloading_wine: None, downloading_wine: None,
creating_prefix: None, creating_prefix: None,
@ -312,8 +313,6 @@ impl SimpleAsyncComponent for DownloadComponentsApp {
installer.install(&config.game.wine.builds, move |update| { installer.install(&config.game.wine.builds, move |update| {
match &update { match &update {
InstallerUpdate::DownloadingError(err) => { InstallerUpdate::DownloadingError(err) => {
let err: std::io::Error = err.clone().into();
tracing::error!("Failed to download wine: {err}"); tracing::error!("Failed to download wine: {err}");
sender.output(Self::Output::Toast { sender.output(Self::Output::Toast {
@ -427,8 +426,6 @@ impl SimpleAsyncComponent for DownloadComponentsApp {
installer.install(&config.game.dxvk.builds, move |update| { installer.install(&config.game.dxvk.builds, move |update| {
match &update { match &update {
InstallerUpdate::DownloadingError(err) => { InstallerUpdate::DownloadingError(err) => {
let err: std::io::Error = err.clone().into();
tracing::error!("Failed to download dxvk: {err}"); tracing::error!("Failed to download dxvk: {err}");
sender.output(Self::Output::Toast { sender.output(Self::Output::Toast {

View file

@ -206,14 +206,9 @@ impl SimpleComponent for FirstRunApp {
dialog.set_response_appearance("save", adw::ResponseAppearance::Suggested); dialog.set_response_appearance("save", adw::ResponseAppearance::Suggested);
#[allow(unused_must_use)]
dialog.connect_response(Some("save"), |_, _| { dialog.connect_response(Some("save"), |_, _| {
let result = std::process::Command::new("xdg-open") if let Err(err) = open::that(crate::DEBUG_FILE.as_os_str()) {
.arg(crate::DEBUG_FILE.as_os_str()) tracing::error!("Failed to open debug file: {err}");
.output();
if let Err(err) = result {
tracing::error!("Failed to open debug file: {}", err);
} }
}); });

View file

@ -13,6 +13,7 @@ use gtk::glib::clone;
use anime_launcher_sdk::config::launcher::LauncherStyle; use anime_launcher_sdk::config::launcher::LauncherStyle;
use anime_launcher_sdk::states::LauncherState; use anime_launcher_sdk::states::LauncherState;
use anime_launcher_sdk::wincompatlib::prelude::*; use anime_launcher_sdk::wincompatlib::prelude::*;
use anime_launcher_sdk::components::loader::ComponentsLoader;
use anime_launcher_sdk::components::wine; use anime_launcher_sdk::components::wine;
use std::path::Path; use std::path::Path;
@ -33,7 +34,7 @@ relm4::new_stateless_action!(DebugFile, WindowActionGroup, "debug_file");
relm4::new_stateless_action!(About, WindowActionGroup, "about"); relm4::new_stateless_action!(About, WindowActionGroup, "about");
static mut MAIN_WINDOW: Option<adw::Window> = None; static mut MAIN_WINDOW: Option<adw::ApplicationWindow> = None;
static mut PREFERENCES_WINDOW: Option<AsyncController<PreferencesApp>> = None; static mut PREFERENCES_WINDOW: Option<AsyncController<PreferencesApp>> = None;
static mut ABOUT_DIALOG: Option<Controller<AboutDialog>> = None; static mut ABOUT_DIALOG: Option<Controller<AboutDialog>> = None;
@ -116,12 +117,8 @@ impl SimpleComponent for App {
} }
view! { view! {
main_window = adw::Window { main_window = adw::ApplicationWindow {
#[watch] set_icon_name: Some(APP_ID),
set_title: match model.style {
LauncherStyle::Modern => Some("An Anime Game Launcher"),
LauncherStyle::Classic => Some("")
},
#[watch] #[watch]
set_default_size: ( set_default_size: (
@ -167,6 +164,15 @@ impl SimpleComponent for App {
LauncherStyle::Classic => &["flat"] LauncherStyle::Classic => &["flat"]
}, },
#[wrap(Some)]
set_title_widget = &adw::WindowTitle {
#[watch]
set_title: match model.style {
LauncherStyle::Modern => "An Anime Game Launcher",
LauncherStyle::Classic => ""
}
},
pack_end = &gtk::MenuButton { pack_end = &gtk::MenuButton {
set_icon_name: "open-menu-symbolic", set_icon_name: "open-menu-symbolic",
set_menu_model: Some(&main_menu) set_menu_model: Some(&main_menu)
@ -521,7 +527,7 @@ impl SimpleComponent for App {
// TODO: reduce code somehow // TODO: reduce code somehow
group.add_action::<LauncherFolder>(&RelmAction::new_stateless(clone!(@strong sender => move |_| { group.add_action::<LauncherFolder>(&RelmAction::new_stateless(clone!(@strong sender => move |_| {
if let Err(err) = std::process::Command::new("xdg-open").arg(LAUNCHER_FOLDER.as_path()).spawn() { if let Err(err) = open::that(LAUNCHER_FOLDER.as_path()) {
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
title: tr("launcher-folder-opening-error"), title: tr("launcher-folder-opening-error"),
description: Some(err.to_string()) description: Some(err.to_string())
@ -532,7 +538,7 @@ impl SimpleComponent for App {
}))); })));
group.add_action::<GameFolder>(&RelmAction::new_stateless(clone!(@strong sender => move |_| { group.add_action::<GameFolder>(&RelmAction::new_stateless(clone!(@strong sender => move |_| {
if let Err(err) = std::process::Command::new("xdg-open").arg(&CONFIG.game.path).spawn() { if let Err(err) = open::that(&CONFIG.game.path) {
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
title: tr("game-folder-opening-error"), title: tr("game-folder-opening-error"),
description: Some(err.to_string()) description: Some(err.to_string())
@ -544,7 +550,7 @@ impl SimpleComponent for App {
group.add_action::<ConfigFile>(&RelmAction::new_stateless(clone!(@strong sender => move |_| { group.add_action::<ConfigFile>(&RelmAction::new_stateless(clone!(@strong sender => move |_| {
if let Some(file) = anime_launcher_sdk::consts::config_file() { if let Some(file) = anime_launcher_sdk::consts::config_file() {
if let Err(err) = std::process::Command::new("xdg-open").arg(file).spawn() { if let Err(err) = open::that(file) {
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
title: tr("config-file-opening-error"), title: tr("config-file-opening-error"),
description: Some(err.to_string()) description: Some(err.to_string())
@ -556,7 +562,7 @@ impl SimpleComponent for App {
}))); })));
group.add_action::<DebugFile>(&RelmAction::new_stateless(clone!(@strong sender => move |_| { group.add_action::<DebugFile>(&RelmAction::new_stateless(clone!(@strong sender => move |_| {
if let Err(err) = std::process::Command::new("xdg-open").arg(DEBUG_FILE.as_os_str()).spawn() { if let Err(err) = open::that(crate::DEBUG_FILE.as_os_str()) {
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
title: tr("debug-file-opening-error"), title: tr("debug-file-opening-error"),
description: Some(err.to_string()) description: Some(err.to_string())
@ -595,6 +601,43 @@ impl SimpleComponent for App {
} }
} }
// Update components index
sender.input(AppMsg::SetLoadingStatus(Some(Some(tr("updating-components-index")))));
let components = ComponentsLoader::new(&CONFIG.components.path);
match components.is_sync(&CONFIG.components.servers) {
Ok(true) => (),
Ok(false) => {
for host in &CONFIG.components.servers {
match components.sync(host) {
Ok(true) => break,
Ok(false) => continue,
Err(err) => {
tracing::error!("Failed to sync components index");
sender.input(AppMsg::Toast {
title: tr("components-index-sync-failed"),
description: Some(err.to_string())
});
}
}
}
}
Err(err) => {
tracing::error!("Failed to verify that components index synced");
sender.input(AppMsg::Toast {
title: tr("components-index-verify-failed"),
description: Some(err.to_string())
});
}
}
// Update initial game version status // Update initial game version status
sender.input(AppMsg::SetLoadingStatus(Some(Some(tr("loading-game-version"))))); sender.input(AppMsg::SetLoadingStatus(Some(Some(tr("loading-game-version")))));
@ -876,8 +919,6 @@ impl SimpleComponent for App {
tracing::debug!("Repairing: {}", file.path.to_string_lossy()); tracing::debug!("Repairing: {}", file.path.to_string_lossy());
if let Err(err) = file.repair(&config.game.path) { if let Err(err) = file.repair(&config.game.path) {
let err: std::io::Error = err.into();
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
title: tr("game-file-repairing-error"), title: tr("game-file-repairing-error"),
description: Some(err.to_string()) description: Some(err.to_string())
@ -928,8 +969,6 @@ impl SimpleComponent for App {
})); }));
if let Err(err) = result { if let Err(err) = result {
let err: std::io::Error = err.into();
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
title: tr("downloading-failed"), title: tr("downloading-failed"),
description: Some(err.to_string()) description: Some(err.to_string())
@ -1049,16 +1088,17 @@ impl SimpleComponent for App {
LauncherState::WineNotInstalled => { LauncherState::WineNotInstalled => {
let mut config = config::get().unwrap(); let mut config = config::get().unwrap();
match wine::get_downloaded(&config.game.wine.builds) { match wine::get_downloaded(&CONFIG.components.path, &config.game.wine.builds) {
Ok(list) => { Ok(list) => {
if let Some(version) = list.into_iter().find(|version| version.recommended) { // FIXME: .find(|version| version.recommended)
config.game.wine.selected = Some(version.name); if !list.is_empty() {
config.game.wine.selected = Some(list[0].name.clone());
config::update(config.clone()); config::update(config.clone());
} }
if config.game.wine.selected.is_none() { if config.game.wine.selected.is_none() {
let wine = wine::Version::latest(); let wine = wine::Version::latest(&CONFIG.components.path).expect("Failed to get latest wine version");
match Installer::new(wine.uri) { match Installer::new(wine.uri) {
Ok(mut installer) => { Ok(mut installer) => {
@ -1079,8 +1119,6 @@ impl SimpleComponent for App {
installer.install(&config.game.wine.builds, clone!(@strong sender => move |state| { installer.install(&config.game.wine.builds, clone!(@strong sender => move |state| {
match &state { match &state {
InstallerUpdate::DownloadingError(err) => { InstallerUpdate::DownloadingError(err) => {
let err: std::io::Error = err.clone().into();
tracing::error!("Downloading failed: {err}"); tracing::error!("Downloading failed: {err}");
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
@ -1135,12 +1173,13 @@ impl SimpleComponent for App {
LauncherState::PrefixNotExists => { LauncherState::PrefixNotExists => {
let config = config::get().unwrap(); let config = config::get().unwrap();
match config.try_get_wine_executable() { match config.try_get_selected_wine_info() {
Some(wine) => { Ok(Some(wine)) => {
sender.input(AppMsg::DisableButtons(true)); sender.input(AppMsg::DisableButtons(true));
std::thread::spawn(move || { std::thread::spawn(move || {
let wine = Wine::from_binary(wine) let wine = wine
.to_wine(Some(config.game.wine.builds.join(&wine.name)))
.with_loader(WineLoader::Current) .with_loader(WineLoader::Current)
.with_arch(WineArch::Win64); .with_arch(WineArch::Win64);
@ -1161,7 +1200,7 @@ impl SimpleComponent for App {
}); });
} }
None => { Ok(None) => {
tracing::error!("Failed to get selected wine executable"); tracing::error!("Failed to get selected wine executable");
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
@ -1169,6 +1208,15 @@ impl SimpleComponent for App {
description: None description: None
}); });
} }
Err(err) => {
tracing::error!("Failed to get selected wine executable: {err}");
sender.input(AppMsg::Toast {
title: tr("failed-get-selected-wine"),
description: Some(err.to_string())
});
}
} }
} }
@ -1188,8 +1236,6 @@ impl SimpleComponent for App {
let result = diff.install_to_by(config.game.path, config.launcher.temp, clone!(@strong sender => move |state| { let result = diff.install_to_by(config.game.path, config.launcher.temp, clone!(@strong sender => move |state| {
match &state { match &state {
InstallerUpdate::DownloadingError(err) => { InstallerUpdate::DownloadingError(err) => {
let err: std::io::Error = err.clone().into();
tracing::error!("Downloading failed: {err}"); tracing::error!("Downloading failed: {err}");
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
@ -1214,8 +1260,6 @@ impl SimpleComponent for App {
})); }));
if let Err(err) = result { if let Err(err) = result {
let err: std::io::Error = err.into();
tracing::error!("Downloading failed: {err}"); tracing::error!("Downloading failed: {err}");
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
@ -1270,14 +1314,9 @@ impl App {
dialog.set_response_appearance("save", adw::ResponseAppearance::Suggested); dialog.set_response_appearance("save", adw::ResponseAppearance::Suggested);
#[allow(unused_must_use)]
dialog.connect_response(Some("save"), |_, _| { dialog.connect_response(Some("save"), |_, _| {
let result = std::process::Command::new("xdg-open") if let Err(err) = open::that(crate::DEBUG_FILE.as_os_str()) {
.arg(crate::DEBUG_FILE.as_os_str()) tracing::error!("Failed to open debug file: {err}");
.output();
if let Err(err) = result {
tracing::error!("Failed to open debug file: {}", err);
} }
}); });

View file

@ -120,6 +120,70 @@ impl SimpleAsyncComponent for GamescopeApp {
} }
}, },
add = &adw::PreferencesGroup {
set_title: &tr("upscaling"),
adw::ActionRow {
set_title: &tr("integer-scaling"),
set_subtitle: &tr("integer-scaling-description"),
add_suffix = &gtk::Switch {
set_valign: gtk::Align::Center,
set_state: CONFIG.game.enhancements.gamescope.integer_scaling,
connect_state_notify => |switch| {
if is_ready() {
if let Ok(mut config) = config::get() {
config.game.enhancements.gamescope.integer_scaling = switch.state();
config::update(config);
}
}
}
}
},
adw::ActionRow {
set_title: "FSR",
set_subtitle: &tr("gamescope-fsr-description"),
add_suffix = &gtk::Switch {
set_valign: gtk::Align::Center,
set_state: CONFIG.game.enhancements.gamescope.fsr,
connect_state_notify => |switch| {
if is_ready() {
if let Ok(mut config) = config::get() {
config.game.enhancements.gamescope.fsr = switch.state();
config::update(config);
}
}
}
}
},
adw::ActionRow {
set_title: "Nvidia Image Scaling",
set_subtitle: &tr("nis-description"),
add_suffix = &gtk::Switch {
set_valign: gtk::Align::Center,
set_state: CONFIG.game.enhancements.gamescope.nis,
connect_state_notify => |switch| {
if is_ready() {
if let Ok(mut config) = config::get() {
config.game.enhancements.gamescope.nis = switch.state();
config::update(config);
}
}
}
}
}
},
add = &adw::PreferencesGroup { add = &adw::PreferencesGroup {
set_title: &tr("other-settings"), set_title: &tr("other-settings"),
@ -167,63 +231,6 @@ impl SimpleAsyncComponent for GamescopeApp {
} }
}, },
adw::ActionRow {
set_title: &tr("integer-scaling"),
add_suffix = &gtk::Switch {
set_valign: gtk::Align::Center,
set_state: CONFIG.game.enhancements.gamescope.integer_scaling,
connect_state_notify => |switch| {
if is_ready() {
if let Ok(mut config) = config::get() {
config.game.enhancements.gamescope.integer_scaling = switch.state();
config::update(config);
}
}
}
}
},
adw::ActionRow {
set_title: "FSR",
add_suffix = &gtk::Switch {
set_valign: gtk::Align::Center,
set_state: CONFIG.game.enhancements.gamescope.fsr,
connect_state_notify => |switch| {
if is_ready() {
if let Ok(mut config) = config::get() {
config.game.enhancements.gamescope.fsr = switch.state();
config::update(config);
}
}
}
}
},
adw::ActionRow {
set_title: "Nvidia Image Scaling",
add_suffix = &gtk::Switch {
set_valign: gtk::Align::Center,
set_state: CONFIG.game.enhancements.gamescope.nis,
connect_state_notify => |switch| {
if is_ready() {
if let Ok(mut config) = config::get() {
config.game.enhancements.gamescope.nis = switch.state();
config::update(config);
}
}
}
}
},
adw::ComboRow { adw::ComboRow {
set_title: &tr("window-mode"), set_title: &tr("window-mode"),

View file

@ -542,7 +542,22 @@ impl SimpleAsyncComponent for GeneralApp {
.launch(ComponentsListInit { .launch(ComponentsListInit {
pattern: ComponentsListPattern { pattern: ComponentsListPattern {
download_folder: CONFIG.game.wine.builds.clone(), download_folder: CONFIG.game.wine.builds.clone(),
groups: wine::get_groups().into_iter().map(|group| group.into()).collect() groups: wine::get_groups(&CONFIG.components.path).unwrap_or_default()
.into_iter()
.map(|mut group| {
group.versions = group.versions.into_iter().take(12).collect();
let mut group: ComponentsListGroup = group.into();
if group.versions.len() > 6 {
for i in 6..group.versions.len() {
group.versions[i].recommended = false;
}
}
group
})
.collect()
}, },
on_downloaded: Some(GeneralAppMsg::UpdateDownloadedWine), on_downloaded: Some(GeneralAppMsg::UpdateDownloadedWine),
on_deleted: Some(GeneralAppMsg::UpdateDownloadedWine) on_deleted: Some(GeneralAppMsg::UpdateDownloadedWine)
@ -553,7 +568,22 @@ impl SimpleAsyncComponent for GeneralApp {
.launch(ComponentsListInit { .launch(ComponentsListInit {
pattern: ComponentsListPattern { pattern: ComponentsListPattern {
download_folder: CONFIG.game.dxvk.builds.clone(), download_folder: CONFIG.game.dxvk.builds.clone(),
groups: dxvk::get_groups().into_iter().map(|group| group.into()).collect() groups: dxvk::get_groups(&CONFIG.components.path).unwrap_or_default()
.into_iter()
.map(|mut group| {
group.versions = group.versions.into_iter().take(12).collect();
let mut group: ComponentsListGroup = group.into();
if group.versions.len() > 6 {
for i in 6..group.versions.len() {
group.versions[i].recommended = false;
}
}
group
})
.collect()
}, },
on_downloaded: Some(GeneralAppMsg::UpdateDownloadedDxvk), on_downloaded: Some(GeneralAppMsg::UpdateDownloadedDxvk),
on_deleted: Some(GeneralAppMsg::UpdateDownloadedDxvk) on_deleted: Some(GeneralAppMsg::UpdateDownloadedDxvk)
@ -701,7 +731,7 @@ impl SimpleAsyncComponent for GeneralApp {
} }
GeneralAppMsg::UpdateDownloadedWine => { GeneralAppMsg::UpdateDownloadedWine => {
self.downloaded_wine_versions = wine::get_downloaded(&CONFIG.game.wine.builds).unwrap_or_default(); self.downloaded_wine_versions = wine::get_downloaded(&CONFIG.components.path, &CONFIG.game.wine.builds).unwrap_or_default();
self.selected_wine_version = if let Some(selected) = &CONFIG.game.wine.selected { self.selected_wine_version = if let Some(selected) = &CONFIG.game.wine.selected {
let mut index = 0; let mut index = 0;
@ -723,7 +753,7 @@ impl SimpleAsyncComponent for GeneralApp {
} }
GeneralAppMsg::UpdateDownloadedDxvk => { GeneralAppMsg::UpdateDownloadedDxvk => {
self.downloaded_dxvk_versions = dxvk::get_downloaded(&CONFIG.game.dxvk.builds).unwrap_or_default(); self.downloaded_dxvk_versions = dxvk::get_downloaded(&CONFIG.components.path, &CONFIG.game.dxvk.builds).unwrap_or_default();
self.selected_dxvk_version = if let Ok(Some(selected)) = CONFIG.try_get_selected_dxvk_info() { self.selected_dxvk_version = if let Ok(Some(selected)) = CONFIG.try_get_selected_dxvk_info() {
let mut index = 0; let mut index = 0;
@ -789,8 +819,8 @@ impl SimpleAsyncComponent for GeneralApp {
self.selecting_dxvk_version = true; self.selecting_dxvk_version = true;
let mut wine = match config.try_get_selected_wine_info() { let mut wine = match config.try_get_selected_wine_info() {
Some(version) => version.to_wine(Some(config.game.wine.builds.join(&version.name))), Ok(Some(version)) => version.to_wine(Some(config.game.wine.builds.join(&version.name))),
None => Wine::default() _ => Wine::default()
}; };
wine = wine.with_prefix(config.game.wine.prefix); wine = wine.with_prefix(config.game.wine.prefix);

View file

@ -164,14 +164,9 @@ impl SimpleAsyncComponent for PreferencesApp {
dialog.set_response_appearance("save", adw::ResponseAppearance::Suggested); dialog.set_response_appearance("save", adw::ResponseAppearance::Suggested);
#[allow(unused_must_use)]
dialog.connect_response(Some("save"), |_, _| { dialog.connect_response(Some("save"), |_, _| {
let result = std::process::Command::new("xdg-open") if let Err(err) = open::that(crate::DEBUG_FILE.as_os_str()) {
.arg(crate::DEBUG_FILE.as_os_str()) tracing::error!("Failed to open debug file: {err}");
.output();
if let Err(err) = result {
tracing::error!("Failed to open debug file: {}", err);
} }
}); });