diff --git a/CHANGELOG.md b/CHANGELOG.md index 489793a..c5e2966 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,14 +10,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Added game repairing function +- Added french translations (#81) +- Used `open` library for xdg (#84) +- Added dynamic components loading ### Fixed - Forced `format_lang` to return regions for language codes +- Fixed titlebar behavior on some DEs ### Changed - Changed default language from en to en-us +- Moved integer scaling, fsr and nis into separate group in gamescope settings ## 3.0.1 diff --git a/Cargo.lock b/Cargo.lock index 99e4778..5c2c625 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -31,7 +31,7 @@ dependencies = [ [[package]] name = "anime-game-core" -version = "1.3.6" +version = "1.3.8" dependencies = [ "anyhow", "bzip2", @@ -46,6 +46,7 @@ dependencies = [ "serde_json", "sysinfo", "tar", + "thiserror", "tracing", "xz", "zip", @@ -64,6 +65,7 @@ dependencies = [ "lazy_static", "libadwaita", "md-5", + "open", "relm4", "rfd", "serde_json", @@ -74,7 +76,7 @@ dependencies = [ [[package]] name = "anime-launcher-sdk" -version = "0.2.5" +version = "0.3.0" dependencies = [ "anime-game-core", "anyhow", @@ -862,9 +864,9 @@ checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa" [[package]] name = "fs_extra" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" [[package]] name = "futures" @@ -1684,6 +1686,16 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" 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]] name = "openssl-probe" version = "0.1.5" @@ -1785,6 +1797,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "pathdiff" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" + [[package]] name = "pbkdf2" version = "0.11.0" diff --git a/Cargo.toml b/Cargo.toml index bd2d8b3..c23c9d3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ relm4 = { version = "0.5", features = ["macros", "libadwaita"] } gtk = { package = "gtk4", version = "0.5", features = ["v4_8"] } adw = { package = "libadwaita", version = "0.2", features = ["v1_2"] } rfd = { version = "0.11", features = ["xdg-portal"], default-features = false } +open = "3.2.0" anime-launcher-sdk = { path = "anime-launcher-sdk" } diff --git a/anime-launcher-sdk b/anime-launcher-sdk index ca8d649..42b738d 160000 --- a/anime-launcher-sdk +++ b/anime-launcher-sdk @@ -1 +1 @@ -Subproject commit ca8d64906a8c8e21edb512552bbd89460ce37836 +Subproject commit 42b738dc1ec5be8e6ced48501604622b8d0ab91e diff --git a/assets/locales/common.ftl b/assets/locales/common.ftl index 395fc3c..52550dd 100644 --- a/assets/locales/common.ftl +++ b/assets/locales/common.ftl @@ -17,4 +17,5 @@ game-name = {-game-name-1}{-game-name-2} {-game-name-3}{-game-name-4} en-us = English ru-ru = Русский de-de = Deutsch +fr-fr = Français zh-cn = 简体中文 diff --git a/assets/locales/de/errors.ftl b/assets/locales/de/errors.ftl index 36cacfb..9127488 100644 --- a/assets/locales/de/errors.ftl +++ b/assets/locales/de/errors.ftl @@ -8,10 +8,12 @@ failed-get-selected-wine = Die ausgewählte Wine version konnte nicht abgerufen downloading-failed = Herunterladen fehlgeschlagen unpacking-failed = Entpacken fehlgeschlagen -game-file-repairing-error = Failed to repair game file -integrity-files-getting-error = Failed to get integrity files +game-file-repairing-error = Reparieren der Spieldatei fehlgeschlagen +integrity-files-getting-error = Integritätsdateien konnten nicht abgerufen werden 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 wine-prefix-update-failed = Aktualisierung des wine prefix fehlgeschlagen dxvk-install-failed = DXVK konnte nicht installiert werden diff --git a/assets/locales/de/gamescope.ftl b/assets/locales/de/gamescope.ftl index 1e29710..f222a66 100644 --- a/assets/locales/de/gamescope.ftl +++ b/assets/locales/de/gamescope.ftl @@ -1,6 +1,13 @@ game-resolution = Spiel-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 framerate-limit = Framerate-Limit unfocused-framerate-limit = Unfokussiert Framerate-Limit -integer-scaling = Integer-Skalierung diff --git a/assets/locales/de/main.ftl b/assets/locales/de/main.ftl index e46dce3..cb4bfa4 100644 --- a/assets/locales/de/main.ftl +++ b/assets/locales/de/main.ftl @@ -24,6 +24,7 @@ restart = Neustarten loading-data = Laden Daten downloading-background-picture = Hintergrundbild am Herunterladen +updating-components-index = Updating components index loading-game-version = Lade version des Spiels loading-patch-status = Lade version des Patch 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 downloading = Lade Herunter unpacking = Entpacken -verifying-files = Verifying files -repairing-files = Repairing files +verifying-files = Verifiziere Dateien +repairing-files = Repariere Dateien launch = Starten diff --git a/assets/locales/en/errors.ftl b/assets/locales/en/errors.ftl index 94bf473..a6a1663 100644 --- a/assets/locales/en/errors.ftl +++ b/assets/locales/en/errors.ftl @@ -12,6 +12,8 @@ game-file-repairing-error = Failed to repair game file integrity-files-getting-error = Failed to get integrity files 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 wine-prefix-update-failed = Failed to update wine prefix dxvk-install-failed = Failed to install DXVK diff --git a/assets/locales/en/gamescope.ftl b/assets/locales/en/gamescope.ftl index c5d96fe..6fbb639 100644 --- a/assets/locales/en/gamescope.ftl +++ b/assets/locales/en/gamescope.ftl @@ -1,6 +1,13 @@ game-resolution = Game 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 framerate-limit = Framerate limit unfocused-framerate-limit = Unfocused framerate limit -integer-scaling = Integer scaling diff --git a/assets/locales/en/main.ftl b/assets/locales/en/main.ftl index ee3c5f8..85a6bbe 100644 --- a/assets/locales/en/main.ftl +++ b/assets/locales/en/main.ftl @@ -24,6 +24,7 @@ restart = Restart loading-data = Loading data downloading-background-picture = Downloading background picture +updating-components-index = Updating components index loading-game-version = Loading game version loading-patch-status = Loading patch status loading-launcher-state = Loading launcher state diff --git a/assets/locales/fr/enhancements.ftl b/assets/locales/fr/enhancements.ftl new file mode 100644 index 0000000..b4531bc --- /dev/null +++ b/assets/locales/fr/enhancements.ftl @@ -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 diff --git a/assets/locales/fr/environment.ftl b/assets/locales/fr/environment.ftl new file mode 100644 index 0000000..878895c --- /dev/null +++ b/assets/locales/fr/environment.ftl @@ -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 diff --git a/assets/locales/fr/errors.ftl b/assets/locales/fr/errors.ftl new file mode 100644 index 0000000..8969e3a --- /dev/null +++ b/assets/locales/fr/errors.ftl @@ -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é diff --git a/assets/locales/fr/first_run.ftl b/assets/locales/fr/first_run.ftl new file mode 100644 index 0000000..f5a079f --- /dev/null +++ b/assets/locales/fr/first_run.ftl @@ -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 ! diff --git a/assets/locales/fr/gamescope.ftl b/assets/locales/fr/gamescope.ftl new file mode 100644 index 0000000..2df9d55 --- /dev/null +++ b/assets/locales/fr/gamescope.ftl @@ -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 diff --git a/assets/locales/fr/general.ftl b/assets/locales/fr/general.ftl new file mode 100644 index 0000000..1d7a5fa --- /dev/null +++ b/assets/locales/fr/general.ftl @@ -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 diff --git a/assets/locales/fr/main.ftl b/assets/locales/fr/main.ftl new file mode 100644 index 0000000..7e92780 --- /dev/null +++ b/assets/locales/fr/main.ftl @@ -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 diff --git a/assets/locales/ru/errors.ftl b/assets/locales/ru/errors.ftl index a487a0a..af6486e 100644 --- a/assets/locales/ru/errors.ftl +++ b/assets/locales/ru/errors.ftl @@ -12,6 +12,8 @@ game-file-repairing-error = Не удалось починить игровой integrity-files-getting-error = Не удалось получить верные данные о файлах игры background-downloading-failed = Не удалось загрузить фоновое изображение +components-index-sync-failed = Не удалось синхронизировать индекс компонентов +components-index-verify-failed = Не удалось проверить индекс компонентов config-update-error = Ошибка сохранения настроек wine-prefix-update-failed = Ошибка обновления префикса Wine dxvk-install-failed = Ошибка установки DXVK diff --git a/assets/locales/ru/gamescope.ftl b/assets/locales/ru/gamescope.ftl index 95d6ee3..478608e 100644 --- a/assets/locales/ru/gamescope.ftl +++ b/assets/locales/ru/gamescope.ftl @@ -1,6 +1,13 @@ game-resolution = Разрешение игры 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 = Другие настройки framerate-limit = Лимит числа кадров unfocused-framerate-limit = Лимит числа кадров вне фокуса -integer-scaling = Целочисленное масштабирование diff --git a/assets/locales/ru/main.ftl b/assets/locales/ru/main.ftl index 6d1efe9..7a2ba5f 100644 --- a/assets/locales/ru/main.ftl +++ b/assets/locales/ru/main.ftl @@ -25,6 +25,7 @@ restart = Перезапустить loading-data = Загрузка данных downloading-background-picture = Загрузка фонового изображения +updating-components-index = Обновление индекса компонентов loading-game-version = Загрузка версии игры loading-patch-status = Загрузка статуса патча loading-launcher-state = Загрузка статуса лаунчера diff --git a/src/background.rs b/src/background.rs index 6562c46..5c334b8 100644 --- a/src/background.rs +++ b/src/background.rs @@ -61,8 +61,6 @@ pub fn download_background() -> anyhow::Result<()> { downloader.continue_downloading = false; if let Err(err) = downloader.download_to(crate::BACKGROUND_FILE.as_path(), |_, _| {}) { - let err: std::io::Error = err.into(); - anyhow::bail!(err); } diff --git a/src/i18n.rs b/src/i18n.rs index 9a44434..b28ac4e 100644 --- a/src/i18n.rs +++ b/src/i18n.rs @@ -14,6 +14,7 @@ pub const SUPPORTED_LANGUAGES: &[LanguageIdentifier] = &[ langid!("en-us"), langid!("ru-ru"), langid!("de-de"), + langid!("fr-fr"), langid!("zh-cn"), ]; diff --git a/src/ui/about.rs b/src/ui/about.rs index cd80435..e5be900 100644 --- a/src/ui/about.rs +++ b/src/ui/about.rs @@ -55,7 +55,8 @@ impl SimpleComponent for AboutDialog { add_credit_section: (Some("An Anime Team"), &[ "@Marie https://github.com/Mar0xy", "@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: &[ @@ -64,7 +65,8 @@ impl SimpleComponent for AboutDialog { set_translator_credits: &[ "Русский, 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"), set_debug_info: &[ diff --git a/src/ui/components/mod.rs b/src/ui/components/mod.rs index 6e93fc5..8daae2f 100644 --- a/src/ui/components/mod.rs +++ b/src/ui/components/mod.rs @@ -27,7 +27,7 @@ pub struct ComponentsListGroup { impl From for ComponentsListGroup { fn from(group: wine::Group) -> Self { Self { - title: group.name, + title: group.title, versions: group.versions.into_iter().map(|version| version.into()).collect() } } @@ -36,7 +36,7 @@ impl From for ComponentsListGroup { impl From for ComponentsListGroup { fn from(group: dxvk::Group) -> Self { Self { - title: group.name, + title: group.title, versions: group.versions.into_iter().map(|version| version.into()).collect() } } @@ -56,7 +56,7 @@ impl From for ComponentsListVersion { name: version.name, title: version.title, uri: version.uri, - recommended: version.recommended + recommended: true // FIXME } } } @@ -67,7 +67,7 @@ impl From for ComponentsListVersion { name: version.name.clone(), title: version.name, uri: version.uri, - recommended: version.recommended + recommended: true // FIXME } } } diff --git a/src/ui/first_run/download_components.rs b/src/ui/first_run/download_components.rs index 16246ce..ca1cec7 100644 --- a/src/ui/first_run/download_components.rs +++ b/src/ui/first_run/download_components.rs @@ -13,7 +13,7 @@ use std::path::PathBuf; use super::main::FirstRunAppMsg; use crate::ui::components::*; use crate::i18n::*; -use crate::FIRST_RUN_FILE; +use crate::*; fn get_installer(uri: &str, temp: Option<&PathBuf>, speed_limit: u64) -> anyhow::Result { let mut installer = Installer::new(uri)?; @@ -264,8 +264,9 @@ impl SimpleAsyncComponent for DownloadComponentsApp { wine_combo: adw::ComboRow::new(), dxvk_combo: adw::ComboRow::new(), - wine_versions: wine::get_groups()[0].versions.clone().into_iter().filter(|version| version.recommended).collect(), - dxvk_versions: dxvk::get_groups()[0].versions.clone().into_iter().filter(|version| version.recommended).collect(), + // FIXME: .filter(|version| version.recommended) + 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, creating_prefix: None, @@ -312,8 +313,6 @@ impl SimpleAsyncComponent for DownloadComponentsApp { installer.install(&config.game.wine.builds, move |update| { match &update { InstallerUpdate::DownloadingError(err) => { - let err: std::io::Error = err.clone().into(); - tracing::error!("Failed to download wine: {err}"); sender.output(Self::Output::Toast { @@ -427,8 +426,6 @@ impl SimpleAsyncComponent for DownloadComponentsApp { installer.install(&config.game.dxvk.builds, move |update| { match &update { InstallerUpdate::DownloadingError(err) => { - let err: std::io::Error = err.clone().into(); - tracing::error!("Failed to download dxvk: {err}"); sender.output(Self::Output::Toast { diff --git a/src/ui/first_run/main.rs b/src/ui/first_run/main.rs index da8dd0c..dd5e083 100644 --- a/src/ui/first_run/main.rs +++ b/src/ui/first_run/main.rs @@ -206,14 +206,9 @@ impl SimpleComponent for FirstRunApp { dialog.set_response_appearance("save", adw::ResponseAppearance::Suggested); - #[allow(unused_must_use)] dialog.connect_response(Some("save"), |_, _| { - let result = std::process::Command::new("xdg-open") - .arg(crate::DEBUG_FILE.as_os_str()) - .output(); - - if let Err(err) = result { - tracing::error!("Failed to open debug file: {}", err); + if let Err(err) = open::that(crate::DEBUG_FILE.as_os_str()) { + tracing::error!("Failed to open debug file: {err}"); } }); diff --git a/src/ui/main.rs b/src/ui/main.rs index d8dd26a..11b732e 100644 --- a/src/ui/main.rs +++ b/src/ui/main.rs @@ -13,6 +13,7 @@ use gtk::glib::clone; use anime_launcher_sdk::config::launcher::LauncherStyle; use anime_launcher_sdk::states::LauncherState; use anime_launcher_sdk::wincompatlib::prelude::*; +use anime_launcher_sdk::components::loader::ComponentsLoader; use anime_launcher_sdk::components::wine; use std::path::Path; @@ -33,7 +34,7 @@ relm4::new_stateless_action!(DebugFile, WindowActionGroup, "debug_file"); relm4::new_stateless_action!(About, WindowActionGroup, "about"); -static mut MAIN_WINDOW: Option = None; +static mut MAIN_WINDOW: Option = None; static mut PREFERENCES_WINDOW: Option> = None; static mut ABOUT_DIALOG: Option> = None; @@ -116,12 +117,8 @@ impl SimpleComponent for App { } view! { - main_window = adw::Window { - #[watch] - set_title: match model.style { - LauncherStyle::Modern => Some("An Anime Game Launcher"), - LauncherStyle::Classic => Some("") - }, + main_window = adw::ApplicationWindow { + set_icon_name: Some(APP_ID), #[watch] set_default_size: ( @@ -167,6 +164,15 @@ impl SimpleComponent for App { 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 = >k::MenuButton { set_icon_name: "open-menu-symbolic", set_menu_model: Some(&main_menu) @@ -521,7 +527,7 @@ impl SimpleComponent for App { // TODO: reduce code somehow group.add_action::(&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 { title: tr("launcher-folder-opening-error"), description: Some(err.to_string()) @@ -532,7 +538,7 @@ impl SimpleComponent for App { }))); group.add_action::(&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 { title: tr("game-folder-opening-error"), description: Some(err.to_string()) @@ -544,7 +550,7 @@ impl SimpleComponent for App { group.add_action::(&RelmAction::new_stateless(clone!(@strong sender => move |_| { 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 { title: tr("config-file-opening-error"), description: Some(err.to_string()) @@ -556,7 +562,7 @@ impl SimpleComponent for App { }))); group.add_action::(&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 { title: tr("debug-file-opening-error"), 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 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()); if let Err(err) = file.repair(&config.game.path) { - let err: std::io::Error = err.into(); - sender.input(AppMsg::Toast { title: tr("game-file-repairing-error"), description: Some(err.to_string()) @@ -928,8 +969,6 @@ impl SimpleComponent for App { })); if let Err(err) = result { - let err: std::io::Error = err.into(); - sender.input(AppMsg::Toast { title: tr("downloading-failed"), description: Some(err.to_string()) @@ -1049,16 +1088,17 @@ impl SimpleComponent for App { LauncherState::WineNotInstalled => { 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) => { - if let Some(version) = list.into_iter().find(|version| version.recommended) { - config.game.wine.selected = Some(version.name); + // FIXME: .find(|version| version.recommended) + if !list.is_empty() { + config.game.wine.selected = Some(list[0].name.clone()); config::update(config.clone()); } 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) { Ok(mut installer) => { @@ -1079,28 +1119,26 @@ impl SimpleComponent for App { installer.install(&config.game.wine.builds, clone!(@strong sender => move |state| { match &state { InstallerUpdate::DownloadingError(err) => { - let err: std::io::Error = err.clone().into(); - tracing::error!("Downloading failed: {err}"); - + sender.input(AppMsg::Toast { title: tr("downloading-failed"), description: Some(err.to_string()) }); } - + InstallerUpdate::UnpackingError(err) => { tracing::error!("Unpacking failed: {err}"); - + sender.input(AppMsg::Toast { title: tr("unpacking-failed"), description: Some(err.clone()) }); } - + _ => () } - + progress_bar_input.send(ProgressBarMsg::UpdateFromState(state)); })); @@ -1135,12 +1173,13 @@ impl SimpleComponent for App { LauncherState::PrefixNotExists => { let config = config::get().unwrap(); - match config.try_get_wine_executable() { - Some(wine) => { + match config.try_get_selected_wine_info() { + Ok(Some(wine)) => { sender.input(AppMsg::DisableButtons(true)); 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_arch(WineArch::Win64); @@ -1161,7 +1200,7 @@ impl SimpleComponent for App { }); } - None => { + Ok(None) => { tracing::error!("Failed to get selected wine executable"); sender.input(AppMsg::Toast { @@ -1169,6 +1208,15 @@ impl SimpleComponent for App { 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| { match &state { InstallerUpdate::DownloadingError(err) => { - let err: std::io::Error = err.clone().into(); - tracing::error!("Downloading failed: {err}"); sender.input(AppMsg::Toast { @@ -1214,8 +1260,6 @@ impl SimpleComponent for App { })); if let Err(err) = result { - let err: std::io::Error = err.into(); - tracing::error!("Downloading failed: {err}"); sender.input(AppMsg::Toast { @@ -1270,14 +1314,9 @@ impl App { dialog.set_response_appearance("save", adw::ResponseAppearance::Suggested); - #[allow(unused_must_use)] dialog.connect_response(Some("save"), |_, _| { - let result = std::process::Command::new("xdg-open") - .arg(crate::DEBUG_FILE.as_os_str()) - .output(); - - if let Err(err) = result { - tracing::error!("Failed to open debug file: {}", err); + if let Err(err) = open::that(crate::DEBUG_FILE.as_os_str()) { + tracing::error!("Failed to open debug file: {err}"); } }); diff --git a/src/ui/preferences/gamescope.rs b/src/ui/preferences/gamescope.rs index 520d517..9770c27 100644 --- a/src/ui/preferences/gamescope.rs +++ b/src/ui/preferences/gamescope.rs @@ -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 = >k::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 = >k::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 = >k::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 { set_title: &tr("other-settings"), @@ -167,63 +231,6 @@ impl SimpleAsyncComponent for GamescopeApp { } }, - adw::ActionRow { - set_title: &tr("integer-scaling"), - - add_suffix = >k::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 = >k::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 = >k::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 { set_title: &tr("window-mode"), diff --git a/src/ui/preferences/general.rs b/src/ui/preferences/general.rs index 16c26d7..e95a572 100644 --- a/src/ui/preferences/general.rs +++ b/src/ui/preferences/general.rs @@ -542,7 +542,22 @@ impl SimpleAsyncComponent for GeneralApp { .launch(ComponentsListInit { pattern: ComponentsListPattern { 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_deleted: Some(GeneralAppMsg::UpdateDownloadedWine) @@ -553,7 +568,22 @@ impl SimpleAsyncComponent for GeneralApp { .launch(ComponentsListInit { pattern: ComponentsListPattern { 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_deleted: Some(GeneralAppMsg::UpdateDownloadedDxvk) @@ -701,7 +731,7 @@ impl SimpleAsyncComponent for GeneralApp { } 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 { let mut index = 0; @@ -723,7 +753,7 @@ impl SimpleAsyncComponent for GeneralApp { } 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() { let mut index = 0; @@ -789,8 +819,8 @@ impl SimpleAsyncComponent for GeneralApp { self.selecting_dxvk_version = true; let mut wine = match config.try_get_selected_wine_info() { - Some(version) => version.to_wine(Some(config.game.wine.builds.join(&version.name))), - None => Wine::default() + Ok(Some(version)) => version.to_wine(Some(config.game.wine.builds.join(&version.name))), + _ => Wine::default() }; wine = wine.with_prefix(config.game.wine.prefix); diff --git a/src/ui/preferences/main.rs b/src/ui/preferences/main.rs index ec641d6..1eef4fc 100644 --- a/src/ui/preferences/main.rs +++ b/src/ui/preferences/main.rs @@ -164,14 +164,9 @@ impl SimpleAsyncComponent for PreferencesApp { dialog.set_response_appearance("save", adw::ResponseAppearance::Suggested); - #[allow(unused_must_use)] dialog.connect_response(Some("save"), |_, _| { - let result = std::process::Command::new("xdg-open") - .arg(crate::DEBUG_FILE.as_os_str()) - .output(); - - if let Err(err) = result { - tracing::error!("Failed to open debug file: {}", err); + if let Err(err) = open::that(crate::DEBUG_FILE.as_os_str()) { + tracing::error!("Failed to open debug file: {err}"); } });