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

Release 3.6.0
This commit is contained in:
Observer KRypt0n_ 2023-05-06 14:11:29 +02:00 committed by GitHub
commit c2208070ef
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
52 changed files with 889 additions and 265 deletions

26
.vscode/launch.json vendored Normal file
View file

@ -0,0 +1,26 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "lldb",
"request": "launch",
"name": "Debug",
"cargo": {
"args": [
"build",
"--bin=anime-game-launcher",
"--package=anime-game-launcher"
],
"filter": {
"name": "anime-game-launcher",
"kind": "bin"
}
},
"args": [],
"cwd": "${workspaceFolder}"
}
]
}

View file

@ -11,6 +11,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added ### Added
- Added rules approving dialog to the first run window
- Added game settings section
- Added game sessions manager
- Added `LAUNCHER_FOLDER` variable support.
Using this you can specify root path where the launcher stores `config.json` and other files
- Added patch repository mirror
### Changed
- Improved launcher logo rendering quality
- Reworked entry rows in the settings
### Fixed
- Fixed wine tools running using proton builds
- Fixed sandboxed game running (sounds are broken for now)
## [3.5.2] - 17.04.2023
### Added
- Added arguments and symlinks editor to sandbox settings - Added arguments and symlinks editor to sandbox settings
### Fixed ### Fixed
@ -203,7 +224,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
<br> <br>
[unreleased]: https://github.com/an-anime-team/an-anime-game-launcher/compare/3.5.1...next [unreleased]: https://github.com/an-anime-team/an-anime-game-launcher/compare/3.5.2...next
[3.5.2]: https://github.com/an-anime-team/an-anime-game-launcher/compare/3.5.1...3.5.2
[3.5.1]: https://github.com/an-anime-team/an-anime-game-launcher/compare/3.5.0...3.5.1 [3.5.1]: https://github.com/an-anime-team/an-anime-game-launcher/compare/3.5.0...3.5.1
[3.5.0]: https://github.com/an-anime-team/an-anime-game-launcher/compare/3.4.1...3.5.0 [3.5.0]: https://github.com/an-anime-team/an-anime-game-launcher/compare/3.4.1...3.5.0
[3.4.1]: https://github.com/an-anime-team/an-anime-game-launcher/compare/3.4.0...3.4.1 [3.4.1]: https://github.com/an-anime-team/an-anime-game-launcher/compare/3.4.0...3.4.1

18
Cargo.lock generated
View file

@ -40,8 +40,8 @@ dependencies = [
[[package]] [[package]]
name = "anime-game-core" name = "anime-game-core"
version = "1.7.1" version = "1.8.0"
source = "git+https://github.com/an-anime-team/anime-game-core?tag=1.7.1#8978728ce5d94aec5c6aecfe470e45fc43d5b522" source = "git+https://github.com/an-anime-team/anime-game-core?tag=1.8.0#dbb9008bcdd6a7b8026567ff35417671a77c740e"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bzip2", "bzip2",
@ -65,7 +65,7 @@ dependencies = [
[[package]] [[package]]
name = "anime-game-launcher" name = "anime-game-launcher"
version = "3.5.2" version = "3.6.0"
dependencies = [ dependencies = [
"anime-launcher-sdk", "anime-launcher-sdk",
"anyhow", "anyhow",
@ -87,8 +87,8 @@ dependencies = [
[[package]] [[package]]
name = "anime-launcher-sdk" name = "anime-launcher-sdk"
version = "1.0.6" version = "1.2.1"
source = "git+https://github.com/an-anime-team/anime-launcher-sdk?tag=1.0.6#2a8272c1afdd006925c150ac480a82be645f4b52" source = "git+https://github.com/an-anime-team/anime-launcher-sdk?tag=1.2.1#f7bddd1d2fde4dcc7d04bda9e4d9160a5bc88218"
dependencies = [ dependencies = [
"anime-game-core", "anime-game-core",
"anyhow", "anyhow",
@ -2065,9 +2065,9 @@ checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
[[package]] [[package]]
name = "relm4" name = "relm4"
version = "0.6.0-alpha.2" version = "0.6.0-beta.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7acc5e3ddd682eeb0ca33da36b821fc907017c6d7758b09ce280247b0b0ea8cd" checksum = "f169f698ce2e487eed2306898fcf262224a287d0e81480db4190e74cfec412cf"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"flume", "flume",
@ -2083,9 +2083,9 @@ dependencies = [
[[package]] [[package]]
name = "relm4-macros" name = "relm4-macros"
version = "0.6.0-alpha.2" version = "0.6.0-beta.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8525ce12dcd7d2a9e9070d84b8b885600eccd0a143df6712ce34a87d001a8b7" checksum = "7fa06febb3685960e7c1c44e21e44a3829325940b31d1e91391a43c32020c201"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",

View file

@ -1,6 +1,6 @@
[package] [package]
name = "anime-game-launcher" name = "anime-game-launcher"
version = "3.5.2" version = "3.6.0"
description = "Anime Game launcher" description = "Anime Game launcher"
authors = ["Nikita Podvirnyy <suimin.tu.mu.ga.mi@gmail.com>"] authors = ["Nikita Podvirnyy <suimin.tu.mu.ga.mi@gmail.com>"]
license = "GPL-3.0" license = "GPL-3.0"
@ -17,13 +17,13 @@ glib-build-tools = "0.17"
[dependencies.anime-launcher-sdk] [dependencies.anime-launcher-sdk]
git = "https://github.com/an-anime-team/anime-launcher-sdk" git = "https://github.com/an-anime-team/anime-launcher-sdk"
tag = "1.0.6" tag = "1.2.1"
features = ["all", "genshin"] features = ["all", "genshin"]
# path = "../anime-launcher-sdk" # ! for dev purposes only # path = "../anime-launcher-sdk" # ! for dev purposes only
[dependencies] [dependencies]
relm4 = { version = "0.6.0-alpha.2", features = ["macros", "libadwaita"] } relm4 = { version = "0.6.0-beta.1", features = ["macros", "libadwaita"] }
gtk = { package = "gtk4", version = "0.6", features = ["v4_8"] } gtk = { package = "gtk4", version = "0.6", features = ["v4_8"] }
adw = { package = "libadwaita", version = "0.3", features = ["v1_2"] } adw = { package = "libadwaita", version = "0.3", features = ["v1_2"] }

View file

@ -57,6 +57,8 @@ instead of the actual name of the game, to avoid search engine parsing.
To see the installation guides, please visit the wiki page [here](https://github.com/an-anime-team/an-anime-game-launcher/wiki/Installation) To see the installation guides, please visit the wiki page [here](https://github.com/an-anime-team/an-anime-game-launcher/wiki/Installation)
Lutris integration described [here](https://github.com/an-anime-team/an-anime-game-launcher/wiki/Installation#-lutris)
## Chinese version support ## Chinese version support
This should be automatically enabled if you're using zh_cn (Chinese) as your system language. If you're not using it - you can change the game edition in the launcher settings This should be automatically enabled if you're using zh_cn (Chinese) as your system language. If you're not using it - you can change the game edition in the launcher settings

View file

@ -19,5 +19,5 @@ ru-ru = Русский
de-de = Deutsch de-de = Deutsch
es-es = Español es-es = Español
fr-fr = Français fr-fr = Français
tr-tr = Türk tr-tr = Türkçe
zh-cn = 简体中文 zh-cn = 简体中文

View file

@ -6,7 +6,7 @@ debug-file-opening-error = Debug-Datei konnte nicht geöffnet werden
wish-url-search-failed = Kein Wünsche URL gefunden wish-url-search-failed = Kein Wünsche URL gefunden
wish-url-opening-error = Wünsche URL konnte nicht geöffnet werden wish-url-opening-error = Wünsche URL konnte nicht geöffnet werden
wine-run-error = Failed to run {$executable} executable using wine wine-run-error = Ausführung von {$executable} mit wine fehlgeschlagen
game-launching-failed = Spiel konnte nicht gestartet werden game-launching-failed = Spiel konnte nicht gestartet werden
failed-get-selected-wine = Die ausgewählte Wine version konnte nicht abgerufen werden. failed-get-selected-wine = Die ausgewählte Wine version konnte nicht abgerufen werden.
@ -44,4 +44,12 @@ game-patching-error = Spiel konnte nicht gepatcht werden
# Sandbox # Sandbox
documentation-url-open-failed = Failed to open documentation URL documentation-url-open-failed = Dokumentations-URL kann nicht geöffnet werden
# Game
game-session-add-failed = Spielsitzung konnte nicht hinzugefügt werden
game-session-update-failed = Spielsitzung konnte nicht aktualisiert werden
game-session-remove-failed = Spielsitzung konnte nicht entfernt werden
game-session-set-current-failed = Aktuelle Spielsitzung konnte nicht eingestellt werden
game-session-apply-failed = Spielsitzung konnte nicht angewendet werden

View file

@ -21,8 +21,13 @@ tos-violation-warning-message =
Sollte dies der Fall sein, würde Ihr Konto gegen die TOS verstoßen, {company-name}/{company-alter-name} sind frei zu tun, was sie wollen. Inklusive Ban. Sollte dies der Fall sein, würde Ihr Konto gegen die TOS verstoßen, {company-name}/{company-alter-name} sind frei zu tun, was sie wollen. Inklusive Ban.
Wenn Sie sich des Risikos bewusst sind, das mit dem Versuch, das Spiel inoffiziell zu spielen, verbunden ist, drücken Sie auf OK und lassen Sie uns die Welt von Teyvat erforschen! Wenn Sie sich über das Risiko bewusst sind das mit dem versuchen des Spiels spielen in inoffizieller Weise verbunden ist dann drücken Sie OK um fortzufahren.
tos-dialog-title = Sind Sie sicher, dass Sie verstehen, was wir sagen?
tos-dialog-message =
1. Veröffentlichen Sie keine Informationen über dieses Projekt
2. Missbrauchen Sie es nicht durch die Verwendung von Mods
3. Stellen Sie Fragen nur in unserem Discord oder auf dem Matrix-Server
dependencies = Abhängigkeiten dependencies = Abhängigkeiten
missing-dependencies-title = Sie vermissen einige Abhängigkeiten! missing-dependencies-title = Sie vermissen einige Abhängigkeiten!
@ -36,14 +41,14 @@ show-all-folders-subtitle = Zusätzliche Pfadauswahl-Einstellungen anzeigen. Tu
runners-folder = Runners-Ordner runners-folder = Runners-Ordner
dxvks-folder = DXVKs-Ordner dxvks-folder = DXVKs-Ordner
wine-prefix-folder = Wine prefix-Ordner wine-prefix-folder = Wine prefix-Ordner
global-game-installation-folder = Global game version installation folder global-game-installation-folder = Installationsordner der globalen Spielversion
chinese-game-installation-folder = Chinese game version installation folder chinese-game-installation-folder = Installationsordner der chinesischen Spielversion
fps-unlocker-folder = FPS Unlocker Ordner fps-unlocker-folder = FPS Unlocker Ordner
components-index = Komponentenverzeichnis components-index = Komponentenverzeichnis
patch-folder = Patch-Ordner patch-folder = Patch-Ordner
temp-folder = Temp-Ordner temp-folder = Temp-Ordner
migrate = Migrate migrate = Migrieren
select-voice-packages = Sprachpakete auswählen select-voice-packages = Sprachpakete auswählen

View file

@ -0,0 +1,7 @@
game-sessions = Spielsitzungen
active-sessions = Aktive Sitzung
active-session-description = Derzeit ausgewählte Spielsitzung. Aktualisiert nach jedem Spielstart
update-session = Sitzung mit aktuellen Wine prefix Registrierungswerten aktualisieren
delete-session = Sitzung löschen

View file

@ -7,22 +7,22 @@ update-background-description = Lädt das offizielle Hintergrundbild herunter f
launcher-language = Launcher Sprache launcher-language = Launcher Sprache
launcher-language-description = Gilt nach Neustart launcher-language-description = Gilt nach Neustart
game-edition = Game edition game-edition = Spiel-Edition
global = Global global = Global
china = China china = China
game-environment = Game environment game-environment = Spielumgebung
game-environment-description = Get specific features like additional payment methods game-environment-description = Spezielle Funktionen wie zusätzliche Zahlungsmöglichkeiten
game-voiceovers = Spiel Sprachen game-voiceovers = Spiel Sprachen
game-voiceovers-description = List of downloaded game voiceovers. You can select them in the game settings game-voiceovers-description = Liste der heruntergeladenen Sprachausgabe für das Spiel. Sie können diese in den Spieleinstellungen auswählen
english = Englisch english = Englisch
japanese = Japanisch japanese = Japanisch
korean = Koreanisch korean = Koreanisch
chinese = Chinesisch chinese = Chinesisch
migrate-installation = Migrate installation migrate-installation = Installation migrieren
migrate-installation-description = Open special window where you can change your game installation folder migrate-installation-description = Öffnet ein spezielles Fenster, in dem Sie den Installationsordner Ihres Spiels ändern können
repair-game = Spiel Reparieren repair-game = Spiel Reparieren
status = Status status = Status
@ -64,11 +64,11 @@ wine-version = Wine version
wine-recommended-description = Nur empfohlene wine versionen anzeigen wine-recommended-description = Nur empfohlene wine versionen anzeigen
wine-tools = Wine tools wine-tools = Wine tools
command-line = Command line command-line = Befehlszeile
registry-editor = Registry editor registry-editor = Registrierungs-Editor
explorer = Explorer explorer = Explorer
task-manager = Task manager task-manager = Task manager
configuration = Configuration configuration = Konfiguration
debugger = Debugger debugger = Debugger
dxvk-version = DXVK version dxvk-version = DXVK version

View file

@ -22,6 +22,7 @@ continue = Weiter
exit = Beenden exit = Beenden
check = Überprüfen check = Überprüfen
restart = Neustarten restart = Neustarten
agree = Einverstanden
loading-data = Laden Daten loading-data = Laden Daten
@ -49,8 +50,8 @@ components-index-updated = Kompontentenverzeichnis würde aktualisiert
launch = Starten launch = Starten
migrate-folders = Migrate folders migrate-folders = Ordner migrieren
migrate-folders-tooltip = Update game folders structure migrate-folders-tooltip = Spielordnerstruktur aktualisieren
apply-patch = Patch anwenden apply-patch = Patch anwenden
download-wine = Wine Herunterladen download-wine = Wine Herunterladen
create-prefix = Prefix erstellen create-prefix = Prefix erstellen

View file

@ -1,28 +1,28 @@
sandbox = Sandbox sandbox = Sandbox
sandbox-description = Run the game in isolated environment, preventing it from accessing your personal data sandbox-description = Führen Sie das Spiel in einer isolierten Umgebung aus, damit es nicht auf Ihre persönlichen Daten zugreifen kann.
enable-sandboxing = Enable sandboxing enable-sandboxing = Sandboxing aktivieren
enable-sandboxing-description = Run the game in read-only copy of your root filesystem enable-sandboxing-description = Starten Sie das Spiel in einer schreibgeschützten Kopie Ihres Root-Dateisystems
hide-home-directory = Hide home directory hide-home-directory = Home-Verzeichnis ausblenden
hide-home-directory-description = Isolate your /home, /var/home/$USER, and $HOME folders from the game hide-home-directory-description = Isolieren Sie Ihre Ordner /home, /var/home/$USER und $HOME vom Spiel
hostname = Hostname hostname = Hostname
additional-arguments = Additional arguments additional-arguments = Zusätzliche Argumente
private-directories = Private directories private-directories = Private Verzeichnisse
private-directories-description = These folders will be replaced by an empty virtual filesystem (tmpfs), and their original content will not be available to sandboxed game private-directories-description = Diese Ordner werden durch ein leeres virtuelles Dateisystem (tmpfs) ersetzt, und ihr ursprünglicher Inhalt ist für das Spiel in der Sandbox nicht verfügbar.
path = Path path = Pfad
shared-directories = Shared directories shared-directories = Geteilte Verzeichnisse
shared-directories-description = These directories will be symlinked to directories in your host system shared-directories-description = Diese Verzeichnisse werden mit Verzeichnissen in Ihrem Host-System verlinkt
original-path = Original path original-path = Ursprünglicher Pfad
new-path = New path new-path = Neuer Pfad
read-only = Read-only read-only = Schreibgeschützt
read-only-description = Forbid game to write any data to this directory read-only-description = Dem Spiel verbieten, Daten in dieses Verzeichnis zu schreiben
symlinks = Symlinks symlinks = Symlinks
symlinks-description = Symlink original path to the new one inside of your sandbox symlinks-description = Verknüpfen Sie den ursprünglichen Pfad mit dem neuen Pfad innerhalb Ihrer Sandbox

View file

@ -45,3 +45,11 @@ game-patching-error = Failed to patch game
# Sandbox # Sandbox
documentation-url-open-failed = Failed to open documentation URL documentation-url-open-failed = Failed to open documentation URL
# Game
game-session-add-failed = Failed to add game session
game-session-update-failed = Failed to update game session
game-session-remove-failed = Failed to remove game session
game-session-set-current-failed = Failed to set current game session
game-session-apply-failed = Failed to apply game session

View file

@ -21,7 +21,13 @@ tos-violation-warning-message =
If this happens, as your account would be disobeying TOS, {company-name}/{company-alter-name} are free to do what they want. Including banning. If this happens, as your account would be disobeying TOS, {company-name}/{company-alter-name} are free to do what they want. Including banning.
If you understand the risk of trying to play the game in an unofficial capacity, press OK and let's go researching the world of Teyvat! If you understand the risk of trying to play the game in an unofficial capacity, press OK to continue
tos-dialog-title = Are you sure you understand what we want to say?
tos-dialog-message =
1. Don't publish any information about this project
2. Don't abuse it by using some modded clients and so
3. Ask questions exceptionally in our discord or matrix server
dependencies = Dependencies dependencies = Dependencies

View file

@ -0,0 +1,7 @@
game-sessions = Game sessions
active-sessions = Active session
active-session-description = Currently selected game session. Updates after each game launch
update-session = Update session using current wine prefix registry values
delete-session = Delete session

View file

@ -22,6 +22,7 @@ continue = Continue
exit = Exit exit = Exit
check = Check check = Check
restart = Restart restart = Restart
agree = Agree
loading-data = Loading data loading-data = Loading data

View file

@ -45,3 +45,11 @@ game-patching-error = Fallo al parchear el juego
# Sandbox # Sandbox
documentation-url-open-failed = Failed to open documentation URL documentation-url-open-failed = Failed to open documentation URL
# Game
game-session-add-failed = Fallo al añadir sesión de juego
game-session-update-failed = Fallo al actualizar sesión de juego
game-session-remove-failed = Fallo al eliminar sesión de juego
game-session-set-current-failed = Fallo al establecer sesión de juego actual
game-session-apply-failed = Fallo al aplicar sesión de juego

View file

@ -23,6 +23,11 @@ tos-violation-warning-message =
Si entiendes los riesgos de intentar jugar el juego de manera extraoficial, presiona OK y ¡exploremos el vasto mundo de Teyvat! Si entiendes los riesgos de intentar jugar el juego de manera extraoficial, presiona OK y ¡exploremos el vasto mundo de Teyvat!
tos-dialog-title = ¿Estás seguro de entender lo que queremos decir?
tos-dialog-message =
1. No publiques información sobre este proyecto
2. No abuses de él usando clientes modificados o cosas similares
3. Haz preguntas exclusivamente en nuestro canal de Discord o de Matrix
dependencies = Dependencias dependencies = Dependencias
missing-dependencies-title = ¡Te faltan algunas dependencias! missing-dependencies-title = ¡Te faltan algunas dependencias!

View file

@ -0,0 +1,7 @@
game-sessions = Sesiones de juego
active-sessions = Sesión activa
active-session-description = La sesión de juego actualmente seleccionada. Se actualiza cada vez que se lanza el juego.
update-session = Actualizar la sesión con los valores actuales del registro del prefijo de Wine
delete-session = Eliminar sesión

View file

@ -22,6 +22,7 @@ continue = Continuar
exit = Salir exit = Salir
check = Comprobar check = Comprobar
restart = Reiniciar restart = Reiniciar
agree = Aceptar
loading-data = Cargando datos loading-data = Cargando datos

View file

@ -8,7 +8,7 @@ hide-home-directory = Esconder el directorio home
hide-home-directory-description = Aisla las carpetas /home, /var/home/$USER, y $HOME del juego hide-home-directory-description = Aisla las carpetas /home, /var/home/$USER, y $HOME del juego
hostname = Nombre del host hostname = Nombre del host
additional-arguments = Additional arguments additional-arguments = Argumentos adicionales
private-directories = Directorios privados private-directories = Directorios privados
private-directories-description = Estas carpetas serán reemplazadas por un sistema de archivos virtual (tmpfs) vacío, y su contenido real no será accesible al juego aislado private-directories-description = Estas carpetas serán reemplazadas por un sistema de archivos virtual (tmpfs) vacío, y su contenido real no será accesible al juego aislado
@ -24,5 +24,5 @@ new-path = Nueva ruta
read-only = Sólo lectura read-only = Sólo lectura
read-only-description = Le prohibe al juego escribir datos en este directorio read-only-description = Le prohibe al juego escribir datos en este directorio
symlinks = Symlinks symlinks = Enlaces simbólicos
symlinks-description = Symlink original path to the new one inside of your sandbox symlinks-description = Enlaza la ruta original a la nueva dentro de tu entorno aislado

View file

@ -45,3 +45,11 @@ game-patching-error = Le patch du jeu a échoué
# Sandbox # Sandbox
documentation-url-open-failed = Failed to open documentation URL documentation-url-open-failed = Failed to open documentation URL
# Game
game-session-add-failed = Imposible d'ajouter la session de jeu
game-session-update-failed = Imposible de mettre à jour la session de jeu
game-session-remove-failed = Imposible de supprimer la session de jeu
game-session-set-current-failed = Imposible de sélectionner la session de jeu par défaut
game-session-apply-failed = Imposible d'appliquer la session de jeu

View file

@ -23,6 +23,11 @@ tos-violation-warning-message =
Si vous comprenez ces risques, appuyez sur "Continuer" pour venir explorer le monde de Teyvat ! Si vous comprenez ces risques, appuyez sur "Continuer" pour venir explorer le monde de Teyvat !
tos-dialog-title = Are you sure you understand what we want to say?
tos-dialog-message =
1. Don't publish any information about this project
2. Don't abuse it by using some modded clients and so
3. Ask questions exceptionally in our discord or matrix server
dependencies = Dépendances dependencies = Dépendances
missing-dependencies-title = Il vous manque des dépendances ! missing-dependencies-title = Il vous manque des dépendances !

View file

@ -0,0 +1,7 @@
game-sessions = Sessions de jeu
active-sessions = Session active
active-session-description = Session actuellement sélectionnée en jeu. Mis à jour à chaque lancement du jeu
update-session = Mettre à jour la session depuis les valeurs du registre du préfixe wine
delete-session = Supprimer la session

View file

@ -22,6 +22,7 @@ continue = Continuer
exit = Quitter exit = Quitter
check = Vérifier check = Vérifier
restart = Redémarer restart = Redémarer
agree = Agree
loading-data = Chargement des données loading-data = Chargement des données

View file

@ -45,3 +45,11 @@ game-patching-error = Не удалось установить патч игры
# Sandbox # Sandbox
documentation-url-open-failed = Не удалось открыть ссылку с документацией documentation-url-open-failed = Не удалось открыть ссылку с документацией
# Game
game-session-add-failed = Не удалось добавить игровую сессию
game-session-update-failed = Не удалось обновить игровую сессию
game-session-remove-failed = Не удалось удалить игровую сессию
game-session-set-current-failed = Не удалось выбрать игровую сессию
game-session-apply-failed = Не удалось применить игровую сессию

View file

@ -23,8 +23,13 @@ tos-violation-warning-message =
Если это произойдёт - поскольку ваша учетная запись будет нарушать правила, {company-name}/{company-alter-name} будут свободы делать то, что захотят, включая блокировку вашего аккаунта. Если это произойдёт - поскольку ваша учетная запись будет нарушать правила, {company-name}/{company-alter-name} будут свободы делать то, что захотят, включая блокировку вашего аккаунта.
Если вы осознаёте риск использования неофициальных средств игры - нажмите "Продолжить" и отправляйтесь исследовать мир Тейвата! Если вы осознаёте риск использования неофициальных средств игры - нажмите "Продолжить"
tos-dialog-title = Вы точно уверены что понимаете что мы хотим сказать?
tos-dialog-message =
1. Не публикуйте никакой информации о проекте
2. Не используйте его совместно с модифицированными клиентами и тому подобным
3. Задавайте вопросы исключительно на нашем discord или matrix сервере
dependencies = Зависимости dependencies = Зависимости
missing-dependencies-title = У вас не установлены некоторые компоненты! missing-dependencies-title = У вас не установлены некоторые компоненты!

View file

@ -0,0 +1,7 @@
game-sessions = Игровые сессии
active-sessions = Активная сессия
active-session-description = Выбранная игровая сессия. Обновляется после каждого запуска игры
update-session = Обновить сессию используя значения реестра из префикса Wine
delete-session = Удалить сессию

View file

@ -22,6 +22,7 @@ continue = Продолжить
exit = Выйти exit = Выйти
check = Проверить check = Проверить
restart = Перезапустить restart = Перезапустить
agree = Подтвердить
loading-data = Загрузка данных loading-data = Загрузка данных

View file

@ -1,13 +1,13 @@
wine = Wine wine = Wine
synchronization = Senkronizasyon synchronization = Senkronizasyon
wine-sync-description = içerde dönen Wine eventleri senkronize etmek için kullanılan teknoloji wine-sync-description = Arkaplanda gerçekleşen Wine olaylarını senkronize etmek için kullanılan teknoloji
language = dil language = Dil
wine-lang-description = Wine için kullanılan dil klavye sorunlarını çözmek için kullanılabilir wine-lang-description = Wine için kullanılan dil, klavye sorunlarını çözmek için kullanılabilir
system = Sistem system = Sistem
borderless-window = Köşesiz pencere borderless-window = Köşesiz Pencere
virtual-desktop = Sanal Masaüstü virtual-desktop = Sanal Masaüstü
game = Oyun game = Oyun
@ -15,30 +15,30 @@ game = Oyun
hud = HUD hud = HUD
fsr = FSR fsr = FSR
fsr-description = Oyunu mönitör boyutunuza büyütür daha düşük bir çözünürlük seçmek için oyun içinde alt + enter tuşlarına basın fsr-description = Oyunu monitör boyutunuza büyütür. Daha düşük bir çözünürlük seçmek için oyun içinde alt + enter tuşlarına basın
ultra-quality = Ultra kalite ultra-quality = Ultra kalite
quality = Kalite quality = Kalite
balanced = Dengeli balanced = Dengeli
performance = Performans performance = Performans
gamemode = Oyunmodu gamemode = Oyun modu
gamemode-description = Oyunu diğer işlemlerden daha öne koyarak performansı arttırır gamemode-description = Oyunun işlem önceliğini arttırarak performansı arttırır
gamescope = Gamescope gamescope = Gamescope
gamescope-description = Gamescope Valve tarafından geliştirilmiş bir araçtır oyunları izole edilmiş bir Xwayland içinde açmanıza yarar gamescope-description = Gamescope, oyunları izole edilmiş bir Xwayland içinde açmanıza yarayan Valve tarafından geliştirilmiş araçtır.
discord-rpc = Discord RPC discord-rpc = Discord RPC
discord-rpc-description = Discord RPC Discorda şuanda oyun oynadığınızın bilgisini vermenize yarar bu sayede arkadaşlarınıza şuanda oyun oynadığınızı gösterebilirsiniz discord-rpc-description = Discord RPC, Discord'a şu anda oyun oynadığınızı bildirmenizi sağlar. Bu sayede arkadaşlarınıza şu anda oyun oynadığınızı gösterebilirsiniz
title = Başlık title = Başlık
description = Açıklama description = Açıklama
fps-unlocker = FPS kilidi açıcı fps-unlocker = FPS kilidi açıcı
enabled = Açık enabled = Açık
fps-unlocker-description = kare renderlama limitasyonunu kaldırır fakat oyunun anti hile sistemi tarafından tespit edilebilir fps-unlocker-description = Kare işleme sınırlamasını kaldırır, fakat oyunun anti-hile sistemi tarafından tespit edilebilir
power-saving = Güç tasarrufu power-saving = Güç tasarrufu
power-saving-description = Alt tab attığınızda oyunun fps limitini 10 a çeker ve oyuna verilen işlem önceliğini azaltır power-saving-description = Pencere değiştirdiğinizde oyunun kare sınırını 10'a indirir ve oyuna verilen işlem önceliğini azaltır
monitor = Monitör monitor = Monitör
monitor-description = Oyunu çalıştırmak istediğiniz monitör sayısı monitor-description = Oyunu çalıştırmak istediğiniz monitör sayısı

View file

@ -1,12 +1,12 @@
launcher-folder-opening-error = Failed to open launcher folder launcher-folder-opening-error = İstemci dosyasını açma başarısız oldu
game-folder-opening-error = Oyun dosyasını açma başarısız oldu game-folder-opening-error = Oyun dosyasını açma başarısız oldu
config-file-opening-error = Config dosyasını açma başarısız oldu config-file-opening-error = Config dosyasını açma başarısız oldu
debug-file-opening-error = Debug dosyasını açma başarısız oldu debug-file-opening-error = Debug dosyasını açma başarısız oldu
wish-url-search-failed = Dilekler urlsi bulunamadı wish-url-search-failed = Dileklerin URL'si bulunamadı
wish-url-opening-error = Dilekler urlsi açılamadı wish-url-opening-error = Dileklerin URL'si açılamadı
wine-run-error = Failed to run {$executable} executable using wine wine-run-error = Wine kullanarak {$executable} programı çalıştırılamadı
game-launching-failed = Oyunu açma başarısız oldu 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 failed-get-selected-wine = Seçilen Wine versiyonunu alma başarısız oldu
@ -19,18 +19,18 @@ integrity-files-getting-error = Dosyaların bütünlüğü kontrol edilemedi
background-downloading-failed = Arkaplan fotoğrafını indirme başarısız oldu background-downloading-failed = Arkaplan fotoğrafını indirme başarısız oldu
components-index-sync-failed = Bileşenler dizini senkronizasyonu başarısız oldu components-index-sync-failed = Bileşenler dizini senkronizasyonu başarısız oldu
components-index-verify-failed = Bileşenler dizini doğrulanamadı components-index-verify-failed = Bileşenler dizini doğrulanamadı
config-update-error = Configi kaydetme başarısız oldu config-update-error = Config'i kaydetme başarısız oldu
wine-prefix-update-failed = Wine prefixini güncelleme başarısız oldu wine-prefix-update-failed = Wine prefixini güncelleme başarısız oldu
dxvk-install-failed = DXVK indirilemedi dxvk-install-failed = DXVK indirilemedi
voice-package-deletion-error = Ses dosyasını silme başarısız oldu voice-package-deletion-error = Ses dosyasını silme başarısız oldu
game-diff-finding-error = Oyun diffini bulma başarısız oldu game-diff-finding-error = Oyun diff'ini bulma başarısız oldu
patch-info-fetching-error = Yama bilgilerini toplama başarısız oldu patch-info-fetching-error = Yama bilgilerini toplama başarısız oldu
launcher-state-updating-error = İstemci durumunu güncelleme başarısız oldu launcher-state-updating-error = İstemci durumunu güncelleme başarısız oldu
package-not-available = Paket mevcut değil: {$package} package-not-available = Paket mevcut değil: {$package}
wine-download-error = Wine indirme başarısız oldu wine-download-error = Wine indirme başarısız oldu
wine-unpack-errror = Wine dosyadan çıkarmak başarısız oldu wine-unpack-errror = Wine dosyadan çıkarma başarısız oldu
wine-install-failed = Wine kurma başarısız oldu wine-install-failed = Wine kurma başarısız oldu
dxvk-download-error = DXVK indirilemedi dxvk-download-error = DXVK indirilemedi
dxvk-unpack-error = DXVK paketten çıkarılamadı dxvk-unpack-error = DXVK paketten çıkarılamadı
@ -44,4 +44,12 @@ game-patching-error = Yamayı uygulamada sorun çıktı
# Sandbox # Sandbox
documentation-url-open-failed = Failed to open documentation URL documentation-url-open-failed = Belgelemenin URL'si açılamadı
# Game
game-session-add-failed = Oyun oturumu eklenemedi
game-session-update-failed = Oyun oturumu güncellenemedi
game-session-remove-failed = Oyun oturumu kaldırılamadı
game-session-set-current-failed = Oyun oturumu seçilemedi
game-session-apply-failed = Oyun oturumu uygulanamadı

View file

@ -1,31 +1,36 @@
welcome = Merhaba welcome = Merhaba
welcome-page-message = welcome-page-message =
Merhaba bir anime oyunu istemcisine hoş geldiniz Merhaba, bir anime oyunu istemcisine hoş geldiniz
Oyunu çalıştırmadan önce bazı şeyler hazırlamamız ve varsayılan bileşenleri indirmemiz gerekiyor. Oyunu çalıştırmadan önce bazı şeyleri hazırlamamız ve varsayılan bileşenleri indirmemiz gerekiyor.
tos-violation-warning = Kullanım şartlarının ihlali uyarısı tos-violation-warning = Kullanım şartlarının ihlali uyarısı
tos-violation-warning-message = tos-violation-warning-message =
Bu başlatıcı, resmi olmayan bir araçtır ve hiçbir şekilde {company-name} veya {company-alter-name} ile ilgili değildir. Bu başlatıcı, resmi olmayan bir araçtır ve hiçbir şekilde {company-name} veya {company-alter-name} ile ilgili değildir.
Bu araç, Linux'ta {game-name} oynamayı kolaylaştırmak için tasarlanmıştır ve yalnızca oyunu daha az güçlükle yüklemek ve çalıştırmak amacıyla oluşturulmuştur. Bu araç, Linux'ta {game-name} oynamayı kolaylaştırmak için tasarlanmıştır ve yalnızca oyunu daha az güçlükle yüklemek ve çalıştırmak amacıyla oluşturulmuştur.
Bunu, mevcut bileşenleri kullanarak ve deneyimi kullanıcı için basit hale getirerek yapar. Bunu, mevcut bileşenleri kullanarak ve deneyimi kullanıcı için basit hale getirerek yapar.
Ancak burada kullanılan bazı bileşenler, {game-name} için {company-name} Hizmet Şartlarını ihlal ediyor olabilir. Ancak burada kullanılan bazı bileşenler, {game-name} için {company-name} Hizmet Şartlarını ihlal ediyor olabilir.
Bu başlatıcıyı kullanıyorsanız, {game-name} hesabınız {company-name}/{company-alter-name} tarafından TOS uyumlu değil olarak tanımlanacaktır. Bu başlatıcıyı kullanıyorsanız, {game-name} hesabınız {company-name}/{company-alter-name} tarafından TOS uyumlu değil olarak tanımlanacaktır.
Böyle bir durumda, hesabınız Hizmet Koşullarına uymayacağından, {company-name}/{company-alter-name} istediğini yapmakta özgürdür. Banlamak dahil. Böyle bir durumda, hesabınız Hizmet Koşullarına uymayacağından, {company-name}/{company-alter-name} istediğini yapmakta özgürdür. Banlamak dahil.
Oyunu gayri resmi bir sıfatla oynamaya çalışmanın riskini anlıyorsanız, Tamam'a basın ve Haydi Teyvat dünyasını araştırmaya başlayalım! Eğer oyunu illegal yollarla oynamanın riskini anlıyorsanız, Tamam'a tıklayın
tos-dialog-title = Ne demek istediğimizi anlayabildiniz mi?
tos-dialog-message =
1. Bu proje hakkında herhangi bir bilgi paylaşmayın.
2. Modlanmış istemciler vb. ile suistimal etmeyin.
3. Sorularınızı sadece Discord veya Matrix sunucumuzda sorun.
dependencies = Bağlılıklar dependencies = Bağımlılıklar
missing-dependencies-title = Bazı bağlılıklar bulunamadı! missing-dependencies-title = Bazı bağımlılıklar bulunamadı!
missing-dependencies-message = Kurulum işlemine devam etmeden önce bazı paketleri sisteminize kurmalısınız. missing-dependencies-message = Kurulum işlemine devam etmeden önce bazı paketleri sisteminize kurmalısınız.
@ -34,24 +39,24 @@ choose-default-paths = Varsayılan yolları seç
show-all-folders = Ne yaptığımı biliyorum show-all-folders = Ne yaptığımı biliyorum
show-all-folders-subtitle = Ek yol seçimi ayarlarını göster. Dediğimi yap... show-all-folders-subtitle = Ek yol seçimi ayarlarını göster. Dediğimi yap...
runners-folder = Başlatıcılar(Runnerlar) klasörü runners-folder = Başlatıcılar(Runnerlar) klasörü
dxvks-folder = DXVKnın klasörü dxvks-folder = DXVK'nin klasörü
wine-prefix-folder = Wine prefixnin klasörü wine-prefix-folder = Wine prefix'inin klasörü
global-game-installation-folder = Global game version installation folder global-game-installation-folder = Evrensel oyun sürümünü yükleme klasörü
chinese-game-installation-folder = Chinese game version installation folder chinese-game-installation-folder = Oyun'un Çin sürümünü yükleme klasörü
fps-unlocker-folder = FPS Unlocker folder fps-unlocker-folder = FPS Unlocker klasörü
components-index = Bileşenlerin dizini components-index = Bileşenlerin dizini
patch-folder = Yama klasörü patch-folder = Yama klasörü
temp-folder = "Geçici" klasörü temp-folder = "Geçici" klasörü
migrate = Migrate migrate = Aktarma
select-voice-packages = Ses paketlerini seç select-voice-packages = Ses paketlerini seç
download-components = Bileşenleri indir download-components = Bileşenleri indir
download-dxvk = DXVKyı İndir download-dxvk = DXVK'yi İndir
apply-dxvk = DXVKyı uygula apply-dxvk = DXVK'yi uygula
finish = Bitir finish = Bitir

View file

@ -0,0 +1,7 @@
game-sessions = Oyun oturumları
active-sessions = Geçerli oturum
active-session-description = Şu anda geçerli oyun oturumu. Oyunu her açtığınızda güncellenir
update-session = Oturumu, geçerli wine prefix'inin girdi değerleriyle güncelleyin
delete-session = Oturumu kaldır

View file

@ -10,4 +10,4 @@ nis-description = DLSS teknolojisine düşük maliyetli bir alternatif olarak Nv
other-settings = Diğer ayarlar other-settings = Diğer ayarlar
framerate-limit = Kare hızı limiti framerate-limit = Kare hızı limiti
unfocused-framerate-limit = Odakta değilken ki Kare hızı limiti unfocused-framerate-limit = Odakta değilken kare hızı limiti

View file

@ -5,43 +5,43 @@ update-background = Arkaplan imajını güncelle
update-background-description = İstemci için resmi arka plan resmini indirin. Bunun yerine özel resminizi kullanmak için devre dışı bırakabilirsiniz. update-background-description = İstemci için resmi arka plan resmini indirin. Bunun yerine özel resminizi kullanmak için devre dışı bırakabilirsiniz.
launcher-language = İstemci dili launcher-language = İstemci dili
launcher-language-description = Restart attıktan sonra uygulanır launcher-language-description = Yeniden başlattıktan sonra uygulanır
game-edition = Game edition game-edition = Oyun Sürümü
global = Global global = Evrensel
china = China china = Çin
game-environment = Game environment game-environment = Oyun ortamı
game-environment-description = Get specific features like additional payment methods game-environment-description = Ek ödeme yöntemleri gibi özelliklere erişin
game-voiceovers = Oyun içi sesler game-voiceovers = Oyun içi sesler
game-voiceovers-description = List of downloaded game voiceovers. You can select them in the game settings game-voiceovers-description = İndirilmiş oyun seslendirmeleri listesi. Oyun içi ayarlardan seçebilirsiniz
english = İngilizce english = İngilizce
japanese = Japonca japanese = Japonca
korean = Korece korean = Korece
chinese = Çince chinese = Çince
migrate-installation = Migrate installation migrate-installation = Yüklemeyi aktar
migrate-installation-description = Open special window where you can change your game installation folder migrate-installation-description = Oyun yükleme yerini değiştirebileceğiniz özel pencereyi açın
repair-game = Oyunu tamir et repair-game = Oyunu tamir et
status = Durum status = Durum
game-version = Oyun versiyonu game-version = Oyun versiyonu
game-not-installed = inik değil game-not-installed = Yüklü değil
game-predownload-available = Güncelleme önceden indirilebilir: {$old} -> {$new} game-predownload-available = Güncelleme önceden indirilebilir: {$old} -> {$new}
game-update-available = Güncelleme mevcut: {$old} -> {$new} game-update-available = Güncelleme mevcut: {$old} -> {$new}
game-outdated = Oyun çok eski bu yüzden güncellenemez. En son sürüm: {$latest} game-outdated = Oyun çok eski, bu yüzden güncellenemez. En son sürüm: {$latest}
player-patch-version = Ana yama versiyonu player-patch-version = Ana yama versiyonu
player-patch-version-description = Oyunu linuxda oynamanıza izin veren ana yama player-patch-version-description = Oyunu Linux'ta oynamanıza izin veren ana yama
xlua-patch-version = Xlua yama versiyonu xlua-patch-version = Xlua yama versiyonu
xlua-patch-version-description = Eski bilgisayarlarda performansı arttıran ve bir kaç sorunu düzelten ekstra yama xlua-patch-version-description = Eski bilgisayarlarda performansı arttıran ve birkaç sorunu düzelten ekstra yama
patch-not-available = Mevcut değil patch-not-available = Mevcut değil
patch-not-available-tooltip = Yama sunucularına erişelemiyor patch-not-available-tooltip = Yama sunucularına erişilemiyor
patch-outdated = zamanı geçmiş ({$current}) patch-outdated = zamanı geçmiş ({$current})
patch-outdated-tooltip = Yamanın zamanı geçmiş: {$current} -> {$latest} patch-outdated-tooltip = Yamanın zamanı geçmiş: {$current} -> {$latest}
@ -55,7 +55,7 @@ patch-not-applied-tooltip = Yama uygulanmamış
apply-xlua-patch = Xlua yamasını uygula apply-xlua-patch = Xlua yamasını uygula
ask-superuser-permissions = Yönetici izinlerini sor ask-superuser-permissions = Yönetici izinlerini sor
ask-superuser-permissions-description = İstemci yöneticini iznini hostunuzun dosyalarını güncellemek için otomatik olarak kullanıcaktır. Buna flatpak versiyonunda gerek yoktur ask-superuser-permissions-description = İstemci yönetici iznini hostunuzun dosyalarını güncellemek için otomatik olarak kullanacaktır. Buna flatpak versiyonunda gerek yoktur
selected-version = Seçilmiş versiyon selected-version = Seçilmiş versiyon
recommended-only = Sadece önerilenler recommended-only = Sadece önerilenler
@ -63,14 +63,14 @@ recommended-only = Sadece önerilenler
wine-version = Wine versiyonu wine-version = Wine versiyonu
wine-recommended-description = Sadece önerilen wine versiyonlarını göster wine-recommended-description = Sadece önerilen wine versiyonlarını göster
wine-tools = Wine tools wine-tools = Wine araçları
command-line = Command line command-line = Komut istemi
registry-editor = Registry editor registry-editor = Girdi düzenleyicisi
explorer = Explorer explorer = Dosya gezgini
task-manager = Task manager task-manager = Görev yöneticisi
configuration = Configuration configuration = Konfigürasyon
debugger = Debugger debugger = Debug aracı
dxvk-version = DXVK versiyonu dxvk-version = DXVK versiyonu
dxvk-selection-disabled = DXVK özelliği Wine grup tercihleriniz yüzünden devre dışı dxvk-selection-disabled = DXVK özelliği Wine grup tercihlerinizden dolayı devre dışı
dxvk-recommended-description = Sadece önerilen dxvk versiyonlarını göster dxvk-recommended-description = Sadece önerilen dxvk versiyonlarını göster

View file

@ -4,13 +4,13 @@ default = Varsayılan
details = Detaylar details = Detaylar
width = Genişlik width = Genişlik
height = Uzunlul height = Uzunluk
# Menu items # Menu items
launcher-folder = İstemci dosyası launcher-folder = İstemci dosyası
game-folder = Oyun dosyası game-folder = Oyun dosyası
config-file = Config dosyaso config-file = Config dosyası
debug-file = Debug dosyası debug-file = Debug dosyası
wish-url = Dilekleri aç wish-url = Dilekleri aç
about = Hakkında about = Hakkında
@ -21,17 +21,18 @@ save = Kaydet
continue = Devam et continue = Devam et
exit = Çıkış yap exit = Çıkış yap
check = Kontrol et check = Kontrol et
restart = Tekrardan başlat restart = Tekrardan başlat
agree = Onayla
loading-data = Bilgiler yükleniyor loading-data = Bilgiler yükleniyor
downloading-background-picture = Arkaplan dosyasi indiriliyor downloading-background-picture = Arkaplan dosyası indiriliyor
updating-components-index = Bileşenlerin dizini güncelleniyor updating-components-index = Bileşenlerin dizini güncelleniyor
loading-game-version = Oyun sürümü yükleniyor loading-game-version = Oyun sürümü yükleniyor
loading-patch-status = Yama durumu yükleniyor loading-patch-status = Yama durumu yükleniyor
loading-launcher-state = İstemci durumu yükleniyor loading-launcher-state = İstemci durumu yükleniyor
loading-launcher-state--game = Loading launcher state: oyun versiyonu doğrulanıyor loading-launcher-state--game = Loading launcher state: oyun versiyonu doğrulanıyor
loading-launcher-state--voice = Loading launcher state: {$locale} dublaj doğrulanıyor loading-launcher-state--voice = Loading launcher state: {$locale} seslendirme doğrulanıyor
loading-launcher-state--patch = Loading launcher state: indirilmiş yamanın durumu yükleniyor loading-launcher-state--patch = Loading launcher state: indirilmiş yamanın durumu yükleniyor
@ -40,17 +41,17 @@ downloading = İndiriliyor
unpacking = Paketten çıkartılıyor unpacking = Paketten çıkartılıyor
verifying-files = Dosyalar Doğrulanıyor verifying-files = Dosyalar Doğrulanıyor
repairing-files = Dosyalar tamir ediliyor repairing-files = Dosyalar tamir ediliyor
migrating-folders = Migrating folders migrating-folders = Dosyalar aktarılıyor
applying-hdiff = Applying hdiff patches applying-hdiff = Hdiff yamaları uygulanıyor
removing-outdated = Removing outdated files removing-outdated = Eskimiş dosyalar kaldırılıyor
components-index-updated = Components index was updated components-index-updated = Bileşenlerin dizini güncellendi
launch = Çalıştır launch = Çalıştır
migrate-folders = Migrate folders migrate-folders = Dosyaları aktar
migrate-folders-tooltip = Update game folders structure migrate-folders-tooltip = Oyun dosyaları yapısını güncelle
apply-patch = Yamayı uygula apply-patch = Yamayı uygula
download-wine = Wine indir download-wine = Wine indir
create-prefix = Prefix oluştur create-prefix = Prefix oluştur

View file

@ -1,28 +1,28 @@
sandbox = Sandbox sandbox = Sanallaştırma
sandbox-description = Run the game in isolated environment, preventing it from accessing your personal data sandbox-description = Oyunu kişisel verilerinize erişemeyeceği, izole bir ortamda çalıştırın
enable-sandboxing = Enable sandboxing enable-sandboxing = Sanallaştırmayı aktifleştir
enable-sandboxing-description = Run the game in read-only copy of your root filesystem enable-sandboxing-description = Oyunu root dosya sisteminizin salt-okunur kopyasında çalıştırın
hide-home-directory = Hide home directory hide-home-directory = Home dizinini gizle
hide-home-directory-description = Isolate your /home, /var/home/$USER, and $HOME folders from the game hide-home-directory-description = /home, /var/home/$USER, ve $HOME klasörlerini oyundan gizle
hostname = Hostname hostname = Host adı
additional-arguments = Additional arguments additional-arguments = Ek argümanlar
private-directories = Private directories private-directories = Özel dizinler
private-directories-description = These folders will be replaced by an empty virtual filesystem (tmpfs), and their original content will not be available to sandboxed game private-directories-description = Bu klasörler boş bir sanal dosya sistemiyle değiştirilecektir (tmpfs), ve orijinal içeriklerine sanallaştırılmış oyun erişemeyecektir
path = Path path = Yol
shared-directories = Shared directories shared-directories = Paylaşılmış dizinler
shared-directories-description = These directories will be symlinked to directories in your host system shared-directories-description = Bu dizinlerden host sisteminizin dizinlerine kısayol oluşturulacaktır
original-path = Original path original-path = Orijinal yol
new-path = New path new-path = Yeni yol
read-only = Read-only read-only = Salt-okunur
read-only-description = Forbid game to write any data to this directory read-only-description = Oyunun bu dizinde veri oluşturmasını yasakla
symlinks = Symlinks symlinks = Kısayollar
symlinks-description = Symlink original path to the new one inside of your sandbox symlinks-description = Orijinal yoldan sanal ortamın içindeki yenisine kısayol oluştur

View file

@ -45,3 +45,11 @@ game-patching-error = 应用游戏补丁失败
# Sandbox # Sandbox
documentation-url-open-failed = Failed to open documentation URL documentation-url-open-failed = Failed to open documentation URL
# Game
game-session-add-failed = Failed to add game session
game-session-update-failed = Failed to update game session
game-session-remove-failed = Failed to remove game session
game-session-set-current-failed = Failed to set current game session
game-session-apply-failed = Failed to apply game session

View file

@ -23,6 +23,11 @@ tos-violation-warning-message =
如果你了解并接受通过非官方许可方式玩这款游戏所带来的风险,请单击“确定”。让我们一直抢过提瓦特大陆吧! 如果你了解并接受通过非官方许可方式玩这款游戏所带来的风险,请单击“确定”。让我们一直抢过提瓦特大陆吧!
tos-dialog-title = Are you sure you understand what we want to say?
tos-dialog-message =
1. Don't publish any information about this project
2. Don't abuse it by using some modded clients and so
3. Ask questions exceptionally in our discord or matrix server
dependencies = 依赖 dependencies = 依赖
missing-dependencies-title = 你缺少某些依赖组件 missing-dependencies-title = 你缺少某些依赖组件

View file

@ -0,0 +1,7 @@
game-sessions = Game sessions
active-sessions = Active session
active-session-description = Currently selected game session. Updates after each game launch
update-session = Update session using current wine prefix registry values
delete-session = Delete session

View file

@ -22,6 +22,7 @@ continue = 继续
exit = 退出 exit = 退出
check = 检查 check = 检查
restart = 重启 restart = 重启
agree = Agree
loading-data = 正在加载数据 loading-data = 正在加载数据

View file

@ -8,7 +8,7 @@ hide-home-directory = 隐藏家目录
hide-home-directory-description = 将 /home、 /var/home/$USER 和 $HOME 目录与游戏隔离 hide-home-directory-description = 将 /home、 /var/home/$USER 和 $HOME 目录与游戏隔离
hostname = 主机名 hostname = 主机名
additional-arguments = Additional arguments additional-arguments = 额外参数
private-directories = 隐私目录 private-directories = 隐私目录
private-directories-description = 这些目录将会被空的虚拟文件系统tmpfs替代其中的原始内容不可被沙盒中的游戏访问 private-directories-description = 这些目录将会被空的虚拟文件系统tmpfs替代其中的原始内容不可被沙盒中的游戏访问
@ -24,5 +24,5 @@ new-path = 新路径
read-only = 只读 read-only = 只读
read-only-description = 禁止游戏向此目录写入任何数据 read-only-description = 禁止游戏向此目录写入任何数据
symlinks = Symlinks symlinks = 软链接
symlinks-description = Symlink original path to the new one inside of your sandbox symlinks-description = 软链接原始路径到沙盒里的新路径

132
fluentscan.py Normal file → Executable file
View file

@ -5,51 +5,118 @@
import os import os
import sys import sys
import glob
import re
path = "assets/locales/" + sys.argv[1] + "/" valid_commands = ["diff", "unused", "missing"]
if len(sys.argv) < 3:
print(f"Command format: ./fluentscan.py [command] [locale]\nAvailable commands: {valid_commands}")
sys.exit()
if sys.argv[1] not in valid_commands:
print(f"Invalid command \"{sys.argv[1]}\". Available commands: {valid_commands}")
sys.exit()
path = "assets/locales/" + sys.argv[2] + "/"
try:
open(path + "/main.ftl", "r").close()
except:
print(f"{path} does not exist")
sys.exit()
all_entries = {}
def dict_compare(d1, d2):
d1_keys = set(d1.keys())
d2_keys = set(d2.keys())
shared_keys = d1_keys.intersection(d2_keys)
added = d1_keys - d2_keys
removed = d2_keys - d1_keys
same = set(o for o in shared_keys if d1[o] == d2[o])
return added, removed, same
def to_dict(text):
result={}
for i in text:
if " =" in i:
try:
result[i.split()[0]] = ' '.join(i.split()[2:])
except:
pass
elif i:
result[list(result.keys())[-1]] += i
return result
def get_line_num(text,pattern):
line = 1
for i in text.split("\n"):
if pattern in i:
return line
line += 1
for filename in os.listdir("assets/locales/en"): for filename in os.listdir("assets/locales/en"):
with open(os.path.join("assets/locales/en", filename), 'r') as locale_file: with open(os.path.join("assets/locales/en", filename), 'r') as locale_file:
created_locale = open(path + filename) created_locale = open(path + filename)
def to_dict(text): expected = to_dict(locale_file)
result={} expected2 = to_dict(created_locale)
for i in text: all_entries.update(expected)
if " = " in i:
try:
result[i.split()[0]] = ' '.join(i.split()[2:])
except: added, removed, same = dict_compare(expected, expected2)
pass
elif i: if sys.argv[1] == "unused" or sys.argv[1] == "missing":
result[list(result.keys())[-1]] += i files = glob.glob("src/**/*.rs", recursive=True)
return result used = []
vars = {}
def dict_compare(d1, d2): for i in files:
d1_keys = set(d1.keys()) with open(i, "r") as script:
d2_keys = set(d2.keys()) text = script.read()
shared_keys = d1_keys.intersection(d2_keys) if sys.argv[1] == "unused":
for j in expected:
if f"\"{j}\"" in text:
used.append(j)
added = d1_keys - d2_keys elif sys.argv[1] == "missing":
removed = d2_keys - d1_keys for j in text.split():
# TODO: ignore comments
if 'tr("' in j:
index = j.find('tr("')
modified = {o : (d1[o], d2[o]) for o in shared_keys if d1[o] != d2[o]} var_name = re.sub('[^\\w-]+', '', j[index:].replace('tr("', '').replace("Some", ""))
same = set(o for o in shared_keys if d1[o] == d2[o]) # TODO: index multiple matches
vars[var_name] = [script.name, get_line_num(text,var_name)]
return added, removed, modified, same if sys.argv[1] == "unused":
for i in expected:
if i not in used:
print(f"[{locale_file.name}]\n"
" [Unused]\n"
f" {i}")
expected=to_dict(locale_file) continue
expected2=to_dict(created_locale)
# TODO: why modified is not used? if (added or removed or same) and sys.argv[1] == "diff":
added, removed, modified, same = dict_compare(expected, expected2)
if added or removed or same:
print(f"[{created_locale.name[15:]}]") print(f"[{created_locale.name[15:]}]")
if added: if added:
@ -72,3 +139,14 @@ for filename in os.listdir("assets/locales/en"):
print(f" {i} = {expected[i]}") print(f" {i} = {expected[i]}")
print("") print("")
if sys.argv[1] == "missing":
added, removed, same = dict_compare(vars, all_entries)
if not added:
print("Nothing is missing")
for i in added:
print(f"[{vars[i][0]}, line {vars[i][1]}]\n"
" [Missing]\n"
f" {i}")

View file

@ -51,10 +51,12 @@ impl SimpleComponent for AboutDialog {
]), ]),
add_credit_section: (Some("An Anime Team"), &[ add_credit_section: (Some("An Anime Team"), &[
"Nikita Podvirnyy https://github.com/krypt0nn",
"@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" "@cybik https://github.com/cybik",
"@mkrsym1 https://github.com/mkrsym1"
]), ]),
set_artists: &[ set_artists: &[
@ -66,7 +68,8 @@ impl SimpleComponent for AboutDialog {
"Deutsch — @Marie https://github.com/Mar0xy", "Deutsch — @Marie https://github.com/Mar0xy",
"Español — Lautaro Garavano https://github.com/Rattlehead15", "Español — Lautaro Garavano https://github.com/Rattlehead15",
"Français — @zeGolem https://github.com/zeGolem", "Français — @zeGolem https://github.com/zeGolem",
"Türk — @Kaozix https://github.com/Kaozix1776", "Türkçe — @Kaozix https://github.com/Kaozix1776",
"Türkçe — Kayra Nachfolger https://github.com/kayranachfolger",
"简体中文 — Caibin Chen https://github.com/tigersoldier" "简体中文 — Caibin Chen https://github.com/tigersoldier"
].join("\n"), ].join("\n"),
@ -85,13 +88,25 @@ impl SimpleComponent for AboutDialog {
"<p>Added</p>", "<p>Added</p>",
"<ul>", "<ul>",
"<li>Added arguments and symlinks editor to sandbox settings</li>", "<li>Added rules approving dialog to the first run window</li>",
"<li>Added game settings section</li>",
"<li>Added game sessions manager</li>",
"<li>Added `LAUNCHER_FOLDER` variable support</li>",
"<li>Added patch repository mirror</li>",
"</ul>",
"<p>Changed</p>",
"<ul>",
"<li>Improved launcher logo rendering quality</li>",
"<li>Reworked entry rows in the settings</li>",
"</ul>", "</ul>",
"<p>Fixed</p>", "<p>Fixed</p>",
"<ul>", "<ul>",
"<li>Fixed game running issue if you have spaces in paths</li>", "<li>Fixed wine tools running using proton builds</li>",
"<li>Fixed sandboxed game running (sounds are broken for now)</li>",
"</ul>", "</ul>",
].join("\n"), ].join("\n"),

View file

@ -8,6 +8,8 @@ use anime_launcher_sdk::is_available;
use crate::i18n::*; use crate::i18n::*;
use super::main::FirstRunAppMsg; use super::main::FirstRunAppMsg;
use super::main::MAIN_WINDOW;
pub struct TosWarningApp; pub struct TosWarningApp;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -86,11 +88,34 @@ impl SimpleAsyncComponent for TosWarningApp {
match msg { match msg {
#[allow(unused_must_use)] #[allow(unused_must_use)]
TosWarningAppMsg::Continue => { TosWarningAppMsg::Continue => {
if is_available("git") && is_available("xdelta3") { let dialog = adw::MessageDialog::new(
sender.output(Self::Output::ScrollToDefaultPaths); unsafe { MAIN_WINDOW.as_ref() },
} else { Some(&tr("tos-dialog-title")),
sender.output(Self::Output::ScrollToDependencies); Some(&tr("tos-dialog-message"))
} );
dialog.add_responses(&[
("exit", &tr("exit")),
("continue", &tr("agree"))
]);
dialog.connect_response(None, move |_, response| {
match response {
"exit" => relm4::main_application().quit(),
"continue" => {
if is_available("git") && is_available("xdelta3") {
sender.output(Self::Output::ScrollToDefaultPaths);
} else {
sender.output(Self::Output::ScrollToDependencies);
}
}
_ => unreachable!()
}
});
dialog.show();
} }
TosWarningAppMsg::Exit => relm4::main_application().quit() TosWarningAppMsg::Exit => relm4::main_application().quit()

View file

@ -220,13 +220,15 @@ impl SimpleComponent for App {
set_visible: model.loading.is_none(), set_visible: model.loading.is_none(),
add = &adw::PreferencesGroup { add = &adw::PreferencesGroup {
set_margin_top: 48,
#[watch] #[watch]
set_visible: model.style == LauncherStyle::Modern, set_visible: model.style == LauncherStyle::Modern,
gtk::Image { gtk::Picture {
set_resource: Some("/org/app/images/icon.png"), set_resource: Some("/org/app/images/icon.png"),
set_vexpand: true, set_vexpand: true,
set_margin_top: 48 set_content_fit: gtk::ContentFit::ScaleDown
}, },
gtk::Label { gtk::Label {
@ -253,6 +255,8 @@ impl SimpleComponent for App {
set_visible: model.downloading, set_visible: model.downloading,
set_vexpand: true, set_vexpand: true,
set_margin_top: 48,
set_margin_bottom: 48,
add = model.progress_bar.widget(), add = model.progress_bar.widget(),
}, },
@ -273,6 +277,12 @@ impl SimpleComponent for App {
#[watch] #[watch]
set_visible: !model.downloading, set_visible: !model.downloading,
#[watch]
set_margin_bottom: match model.style {
LauncherStyle::Modern => 48,
LauncherStyle::Classic => 0
},
set_vexpand: true, set_vexpand: true,
gtk::Box { gtk::Box {
@ -547,11 +557,11 @@ impl SimpleComponent for App {
.detach()); .detach());
} }
let group = RelmActionGroup::<WindowActionGroup>::new(); let mut group = RelmActionGroup::<WindowActionGroup>::new();
// 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) = open::that(LAUNCHER_FOLDER.as_path()) { if let Err(err) = open::that(LAUNCHER_FOLDER.as_path()) {
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
title: tr("launcher-folder-opening-error"), title: tr("launcher-folder-opening-error"),
@ -562,7 +572,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 |_| {
let path = match Config::get() { let path = match Config::get() {
Ok(config) => config.game.path.for_edition(config.launcher.edition).to_path_buf(), Ok(config) => config.game.path.for_edition(config.launcher.edition).to_path_buf(),
Err(_) => CONFIG.game.path.for_edition(CONFIG.launcher.edition).to_path_buf(), Err(_) => CONFIG.game.path.for_edition(CONFIG.launcher.edition).to_path_buf(),
@ -578,7 +588,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 Ok(file) = config_file() { if let Ok(file) = config_file() {
if let Err(err) = open::that(file) { if let Err(err) = open::that(file) {
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
@ -591,7 +601,7 @@ impl SimpleComponent for App {
} }
}))); })));
group.add_action::<DebugFile>(&RelmAction::new_stateless(clone!(@strong sender => move |_| { group.add_action::<DebugFile>(RelmAction::new_stateless(clone!(@strong sender => move |_| {
if let Err(err) = open::that(crate::DEBUG_FILE.as_os_str()) { if let Err(err) = open::that(crate::DEBUG_FILE.as_os_str()) {
sender.input(AppMsg::Toast { sender.input(AppMsg::Toast {
title: tr("debug-file-opening-error"), title: tr("debug-file-opening-error"),
@ -602,7 +612,7 @@ impl SimpleComponent for App {
} }
}))); })));
group.add_action::<WishUrl>(&RelmAction::new_stateless(clone!(@strong sender => move |_| { group.add_action::<WishUrl>(RelmAction::new_stateless(clone!(@strong sender => move |_| {
std::thread::spawn(clone!(@strong sender => move || { std::thread::spawn(clone!(@strong sender => move || {
let config = Config::get().unwrap_or_else(|_| CONFIG.clone()); let config = Config::get().unwrap_or_else(|_| CONFIG.clone());
@ -662,7 +672,7 @@ impl SimpleComponent for App {
})); }));
}))); })));
group.add_action::<About>(&RelmAction::new_stateless(move |_| { group.add_action::<About>(RelmAction::new_stateless(move |_| {
about_dialog_broker.send(AboutDialogMsg::Show); about_dialog_broker.send(AboutDialogMsg::Show);
})); }));
@ -709,10 +719,8 @@ impl SimpleComponent for App {
description: if changes.is_empty() { description: if changes.is_empty() {
None None
} else { } else {
let max_len = changes.iter().map(|line| line.len()).max().unwrap_or(80);
Some(changes.into_iter() Some(changes.into_iter()
.map(|line| format!("- {line}{}", " ".repeat(max_len - line.len()))) .map(|line| format!("- {line}"))
.collect::<Vec<_>>() .collect::<Vec<_>>()
.join("\n")) .join("\n"))
} }

View file

@ -16,10 +16,10 @@ struct Variable {
#[relm4::factory(async)] #[relm4::factory(async)]
impl AsyncFactoryComponent for Variable { impl AsyncFactoryComponent for Variable {
type Init = (String, String); type Init = (String, String);
type Input = EnvironmentMsg; type Input = EnvironmentAppMsg;
type Output = EnvironmentMsg; type Output = EnvironmentAppMsg;
type CommandOutput = (); type CommandOutput = ();
type ParentInput = EnvironmentMsg; type ParentInput = EnvironmentAppMsg;
type ParentWidget = adw::PreferencesGroup; type ParentWidget = adw::PreferencesGroup;
view! { view! {
@ -33,16 +33,12 @@ impl AsyncFactoryComponent for Variable {
set_valign: gtk::Align::Center, set_valign: gtk::Align::Center,
connect_clicked[sender, index] => move |_| { connect_clicked[sender, index] => move |_| {
sender.input(EnvironmentMsg::Remove(index.clone())); sender.output(EnvironmentAppMsg::Remove(index.clone()));
} }
} }
} }
} }
fn output_to_parent_input(output: Self::Output) -> Option<Self::ParentInput> {
Some(output)
}
async fn init_model( async fn init_model(
init: Self::Init, init: Self::Init,
_index: &DynamicIndex, _index: &DynamicIndex,
@ -54,8 +50,8 @@ impl AsyncFactoryComponent for Variable {
} }
} }
async fn update(&mut self, msg: Self::Input, sender: AsyncFactorySender<Self>) { fn forward_to_parent(output: Self::Output) -> Option<Self::ParentInput> {
sender.output(msg); Some(output)
} }
} }
@ -67,7 +63,7 @@ pub struct EnvironmentApp {
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum EnvironmentMsg { pub enum EnvironmentAppMsg {
Add, Add,
Remove(DynamicIndex) Remove(DynamicIndex)
} }
@ -75,7 +71,7 @@ pub enum EnvironmentMsg {
#[relm4::component(async, pub)] #[relm4::component(async, pub)]
impl SimpleAsyncComponent for EnvironmentApp { impl SimpleAsyncComponent for EnvironmentApp {
type Init = (); type Init = ();
type Input = EnvironmentMsg; type Input = EnvironmentAppMsg;
type Output = (); type Output = ();
view! { view! {
@ -110,6 +106,20 @@ impl SimpleAsyncComponent for EnvironmentApp {
add = &adw::PreferencesGroup { add = &adw::PreferencesGroup {
set_title: &tr("new-variable"), set_title: &tr("new-variable"),
#[wrap(Some)]
set_header_suffix = &gtk::Button {
add_css_class: "flat",
set_valign: gtk::Align::Center,
adw::ButtonContent {
set_icon_name: "list-add-symbolic",
set_label: &tr("add")
},
connect_clicked => EnvironmentAppMsg::Add
},
#[local_ref] #[local_ref]
name_entry -> adw::EntryRow { name_entry -> adw::EntryRow {
set_title: &tr("name") set_title: &tr("name")
@ -118,16 +128,6 @@ impl SimpleAsyncComponent for EnvironmentApp {
#[local_ref] #[local_ref]
value_entry -> adw::EntryRow { value_entry -> adw::EntryRow {
set_title: &tr("value") set_title: &tr("value")
},
gtk::Button {
set_label: &tr("add"),
add_css_class: "pill",
set_margin_top: 8,
set_halign: gtk::Align::Start,
connect_clicked => EnvironmentMsg::Add
} }
}, },
@ -166,12 +166,12 @@ impl SimpleAsyncComponent for EnvironmentApp {
async fn update(&mut self, msg: Self::Input, _sender: AsyncComponentSender<Self>) { async fn update(&mut self, msg: Self::Input, _sender: AsyncComponentSender<Self>) {
match msg { match msg {
EnvironmentMsg::Add => { EnvironmentAppMsg::Add => {
if let Ok(mut config) = Config::get() { let name = self.name_entry.text().trim().to_string();
let name = self.name_entry.text().trim().to_string(); let value = self.value_entry.text().trim().to_string();
let value = self.value_entry.text().trim().to_string();
if !name.is_empty() && !value.is_empty() { if !name.is_empty() && !value.is_empty() {
if let Ok(mut config) = Config::get() {
self.name_entry.set_text(""); self.name_entry.set_text("");
self.value_entry.set_text(""); self.value_entry.set_text("");
@ -184,7 +184,7 @@ impl SimpleAsyncComponent for EnvironmentApp {
} }
} }
EnvironmentMsg::Remove(index) => { EnvironmentAppMsg::Remove(index) => {
if let Ok(mut config) = Config::get() { if let Ok(mut config) = Config::get() {
if let Some(var) = self.variables.guard().get(index.current_index()) { if let Some(var) = self.variables.guard().get(index.current_index()) {
config.game.environment.remove(&var.key); config.game.environment.remove(&var.key);

285
src/ui/preferences/game.rs Normal file
View file

@ -0,0 +1,285 @@
use relm4::prelude::*;
use relm4::component::*;
use relm4::factory::*;
use adw::prelude::*;
use anime_launcher_sdk::sessions::SessionsExt;
use anime_launcher_sdk::genshin::sessions::Sessions;
use super::main::PreferencesAppMsg;
use crate::i18n::tr;
use crate::*;
#[derive(Debug)]
struct GameSession {
name: String,
description: Option<String>
}
#[relm4::factory(async)]
impl AsyncFactoryComponent for GameSession {
type Init = GameSession;
type Input = GameAppMsg;
type Output = GameAppMsg;
type CommandOutput = ();
type ParentInput = GameAppMsg;
type ParentWidget = adw::PreferencesGroup;
view! {
root = adw::ActionRow {
set_title: &self.name,
set_subtitle: match &self.description {
Some(description) => description.as_str(),
None => ""
},
add_suffix = &gtk::Button {
set_icon_name: "view-refresh-symbolic-symbolic",
add_css_class: "flat",
set_tooltip_text: Some(&tr("update-session")),
set_valign: gtk::Align::Center,
connect_clicked[sender, index] => move |_| {
sender.output(GameAppMsg::UpdateSession(index.clone()));
}
},
add_suffix = &gtk::Button {
set_icon_name: "user-trash-symbolic",
add_css_class: "flat",
set_tooltip_text: Some(&tr("delete-session")),
set_valign: gtk::Align::Center,
connect_clicked[sender, index] => move |_| {
sender.output(GameAppMsg::RemoveSession(index.clone()));
}
}
}
}
async fn init_model(
init: Self::Init,
_index: &DynamicIndex,
_sender: AsyncFactorySender<Self>,
) -> Self {
init
}
fn forward_to_parent(output: Self::Output) -> Option<Self::ParentInput> {
Some(output)
}
}
pub struct GameApp {
sessions: AsyncFactoryVecDeque<GameSession>,
sessions_names: Vec<String>,
sessions_combo: adw::ComboRow,
session_name_entry: adw::EntryRow
}
#[derive(Debug, Clone)]
pub enum GameAppMsg {
AddSession,
UpdateSession(DynamicIndex),
RemoveSession(DynamicIndex),
SetCurrent(u32),
UpdateCombo
}
#[relm4::component(async, pub)]
impl SimpleAsyncComponent for GameApp {
type Init = ();
type Input = GameAppMsg;
type Output = PreferencesAppMsg;
view! {
adw::PreferencesPage {
set_title: &tr("game"),
set_icon_name: Some("applications-games-symbolic"),
add = &adw::PreferencesGroup {
set_title: &tr("game-sessions"),
#[local_ref]
sessions_combo -> adw::ComboRow {
set_title: &tr("active-sessions"),
set_subtitle: &tr("active-session-description"),
connect_selected_notify[sender] => move |row| sender.input(GameAppMsg::SetCurrent(row.selected()))
}
},
add = &adw::PreferencesGroup {
#[local_ref]
session_name_entry -> adw::EntryRow {
set_title: &tr("name"),
add_suffix = &gtk::Button {
set_icon_name: "list-add-symbolic",
add_css_class: "flat",
set_valign: gtk::Align::Center,
connect_clicked => GameAppMsg::AddSession
}
}
},
#[local_ref]
add = sessions -> adw::PreferencesGroup {},
}
}
async fn init(
_init: Self::Init,
root: Self::Root,
sender: AsyncComponentSender<Self>,
) -> AsyncComponentParts<Self> {
tracing::info!("Initializing game settings");
let mut model = Self {
sessions: AsyncFactoryVecDeque::new(adw::PreferencesGroup::new(), sender.input_sender()),
sessions_names: Vec::new(),
sessions_combo: adw::ComboRow::new(),
session_name_entry: adw::EntryRow::new()
};
for (name, _) in Sessions::list().unwrap_or_default() {
model.sessions.guard().push_back(GameSession {
name: name.clone(),
description: None
});
}
let sessions = model.sessions.widget();
let sessions_combo = &model.sessions_combo;
let session_name_entry = &model.session_name_entry;
let widgets = view_output!();
sender.input(GameAppMsg::UpdateCombo);
AsyncComponentParts { model, widgets }
}
async fn update(&mut self, msg: Self::Input, sender: AsyncComponentSender<Self>) {
match msg {
GameAppMsg::AddSession => {
let name = self.session_name_entry.text().trim().to_string();
if !name.is_empty() {
if let Ok(config) = Config::get() {
self.session_name_entry.set_text("");
match Sessions::update(name.clone(), config.get_wine_prefix_path()) {
Ok(()) => {
self.sessions.guard().push_back(GameSession {
name,
description: None
});
sender.input(GameAppMsg::UpdateCombo);
}
#[allow(unused_must_use)]
Err(err) => {
sender.output(PreferencesAppMsg::Toast {
title: tr("game-session-add-failed"),
description: Some(err.to_string())
});
}
}
}
}
}
GameAppMsg::UpdateSession(index) => {
if let Some(session) = self.sessions.guard().get(index.current_index()) {
if let Ok(config) = Config::get() {
#[allow(unused_must_use)]
if let Err(err) = Sessions::update(session.name.clone(), config.get_wine_prefix_path()) {
sender.output(PreferencesAppMsg::Toast {
title: tr("game-session-update-failed"),
description: Some(err.to_string())
});
}
}
}
}
GameAppMsg::RemoveSession(index) => {
if let Some(session) = self.sessions.guard().get(index.current_index()) {
match Sessions::remove(&session.name) {
Ok(()) => sender.input(GameAppMsg::UpdateCombo),
#[allow(unused_must_use)]
Err(err) => {
sender.output(PreferencesAppMsg::Toast {
title: tr("game-session-remove-failed"),
description: Some(err.to_string())
});
return;
}
}
}
self.sessions.guard().remove(index.current_index());
}
GameAppMsg::SetCurrent(id) => {
if let Some(name) = self.sessions_names.get(id as usize) {
if let Ok(config) = Config::get() {
#[allow(unused_must_use)]
if let Err(err) = Sessions::set_current(name.to_owned()) {
sender.output(PreferencesAppMsg::Toast {
title: tr("game-session-set-current-failed"),
description: Some(err.to_string())
});
// Prevent session applying
return;
}
#[allow(unused_must_use)]
if let Err(err) = Sessions::apply(name.to_owned(), config.get_wine_prefix_path()) {
sender.output(PreferencesAppMsg::Toast {
title: tr("game-session-apply-failed"),
description: Some(err.to_string())
});
}
}
}
}
GameAppMsg::UpdateCombo => {
let sessions = Sessions::get_sessions().unwrap_or_default();
self.sessions_names = sessions.sessions.into_keys().collect::<Vec<String>>();
let mut selected = 0;
for (i, name) in self.sessions_names.iter().enumerate() {
if sessions.current.as_ref() == Some(name) {
selected = i as u32;
}
}
self.sessions_combo.set_model(Some(&gtk::StringList::new(&self.sessions_names.iter().map(|name: &String| name.as_str()).collect::<Vec<&str>>())));
self.sessions_combo.set_selected(selected);
}
}
}
}

View file

@ -84,10 +84,6 @@ impl AsyncFactoryComponent for VoicePackageComponent {
} }
} }
fn output_to_parent_input(output: Self::Output) -> Option<Self::ParentInput> {
Some(output)
}
async fn init_model( async fn init_model(
init: Self::Init, init: Self::Init,
_index: &DynamicIndex, _index: &DynamicIndex,
@ -105,6 +101,10 @@ impl AsyncFactoryComponent for VoicePackageComponent {
sender.output(msg); sender.output(msg);
} }
fn forward_to_parent(output: Self::Output) -> Option<Self::ParentInput> {
Some(output)
}
} }
pub struct GeneralApp { pub struct GeneralApp {
@ -1035,7 +1035,8 @@ impl SimpleAsyncComponent for GeneralApp {
let config = Config::get().unwrap_or_else(|_| CONFIG.clone()); let config = Config::get().unwrap_or_else(|_| CONFIG.clone());
if let Ok(Some(wine)) = config.get_selected_wine() { 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))) let result = wine
.to_wine(config.components.path, Some(config.game.wine.builds.join(&wine.name)))
.with_prefix(config.game.wine.prefix) .with_prefix(config.game.wine.prefix)
.with_loader(WineLoader::Current) .with_loader(WineLoader::Current)
.with_arch(WineArch::Win64) .with_arch(WineArch::Win64)

View file

@ -15,6 +15,7 @@ use crate::i18n::tr;
use super::general::*; use super::general::*;
use super::enhancements::*; use super::enhancements::*;
use super::game::*;
use super::sandbox::*; use super::sandbox::*;
use super::environment::*; use super::environment::*;
@ -23,6 +24,7 @@ pub static mut PREFERENCES_WINDOW: Option<adw::PreferencesWindow> = None;
pub struct PreferencesApp { pub struct PreferencesApp {
general: AsyncController<GeneralApp>, general: AsyncController<GeneralApp>,
enhancements: AsyncController<EnhancementsApp>, enhancements: AsyncController<EnhancementsApp>,
game: AsyncController<GameApp>,
sandbox: AsyncController<SandboxApp>, sandbox: AsyncController<SandboxApp>,
environment: AsyncController<EnvironmentApp> environment: AsyncController<EnvironmentApp>
} }
@ -69,6 +71,7 @@ impl SimpleAsyncComponent for PreferencesApp {
add = model.general.widget(), add = model.general.widget(),
add = model.enhancements.widget(), add = model.enhancements.widget(),
add = model.game.widget(),
add = model.sandbox.widget(), add = model.sandbox.widget(),
add = model.environment.widget(), add = model.environment.widget(),
@ -101,6 +104,10 @@ impl SimpleAsyncComponent for PreferencesApp {
.launch(()) .launch(())
.detach(), .detach(),
game: GameApp::builder()
.launch(())
.detach(),
sandbox: SandboxApp::builder() sandbox: SandboxApp::builder()
.launch(()) .launch(())
.forward(sender.input_sender(), std::convert::identity), .forward(sender.input_sender(), std::convert::identity),

View file

@ -1,6 +1,7 @@
pub mod main; pub mod main;
pub mod general; pub mod general;
pub mod enhancements; pub mod enhancements;
pub mod game;
pub mod sandbox; pub mod sandbox;
pub mod environment; pub mod environment;
pub mod gamescope; pub mod gamescope;

View file

@ -7,6 +7,7 @@ use adw::prelude::*;
use anime_launcher_sdk::is_available; use anime_launcher_sdk::is_available;
use super::main::PreferencesAppMsg; use super::main::PreferencesAppMsg;
use crate::i18n::tr; use crate::i18n::tr;
use crate::*; use crate::*;
@ -41,16 +42,12 @@ macro_rules! impl_directory {
set_valign: gtk::Align::Center, set_valign: gtk::Align::Center,
connect_clicked[sender, index] => move |_| { connect_clicked[sender, index] => move |_| {
sender.input($msg(index.clone())); sender.output($msg(index.clone()));
} }
} }
} }
} }
fn output_to_parent_input(output: Self::Output) -> Option<Self::ParentInput> {
Some(output)
}
async fn init_model( async fn init_model(
init: Self::Init, init: Self::Init,
_index: &DynamicIndex, _index: &DynamicIndex,
@ -62,8 +59,8 @@ macro_rules! impl_directory {
} }
} }
async fn update(&mut self, msg: Self::Input, sender: AsyncFactorySender<Self>) { fn forward_to_parent(output: Self::Output) -> Option<Self::ParentInput> {
sender.output(msg); Some(output)
} }
} }
} }
@ -197,8 +194,10 @@ impl SimpleAsyncComponent for SandboxApp {
}, },
add_suffix = &gtk::Button { add_suffix = &gtk::Button {
set_valign: gtk::Align::Center,
set_icon_name: "dialog-information-symbolic", set_icon_name: "dialog-information-symbolic",
add_css_class: "flat",
set_valign: gtk::Align::Center,
connect_clicked[sender] => move |_| { connect_clicked[sender] => move |_| {
if let Err(err) = open::that("https://man.archlinux.org/man/bwrap.1") { if let Err(err) = open::that("https://man.archlinux.org/man/bwrap.1") {
@ -218,17 +217,16 @@ impl SimpleAsyncComponent for SandboxApp {
#[local_ref] #[local_ref]
private_path_entry -> adw::EntryRow { private_path_entry -> adw::EntryRow {
set_title: &tr("path") set_title: &tr("path"),
},
gtk::Button { add_suffix = &gtk::Button {
set_label: &tr("add"), set_icon_name: "list-add-symbolic",
add_css_class: "pill", add_css_class: "flat",
set_margin_top: 8, set_valign: gtk::Align::Center,
set_halign: gtk::Align::Start,
connect_clicked => SandboxAppMsg::AddPrivate
connect_clicked => SandboxAppMsg::AddPrivate }
} }
}, },
@ -239,6 +237,20 @@ impl SimpleAsyncComponent for SandboxApp {
set_title: &tr("shared-directories"), set_title: &tr("shared-directories"),
set_description: Some(&tr("shared-directories-description")), set_description: Some(&tr("shared-directories-description")),
#[wrap(Some)]
set_header_suffix = &gtk::Button {
add_css_class: "flat",
set_valign: gtk::Align::Center,
adw::ButtonContent {
set_icon_name: "list-add-symbolic",
set_label: &tr("add")
},
connect_clicked => SandboxAppMsg::AddShared
},
#[local_ref] #[local_ref]
shared_path_from_entry -> adw::EntryRow { shared_path_from_entry -> adw::EntryRow {
set_title: &tr("original-path") set_title: &tr("original-path")
@ -257,16 +269,6 @@ impl SimpleAsyncComponent for SandboxApp {
add_suffix = read_only_switch -> gtk::Switch { add_suffix = read_only_switch -> gtk::Switch {
set_valign: gtk::Align::Center set_valign: gtk::Align::Center
} }
},
gtk::Button {
set_label: &tr("add"),
add_css_class: "pill",
set_margin_top: 8,
set_halign: gtk::Align::Start,
connect_clicked => SandboxAppMsg::AddShared
} }
}, },
@ -277,6 +279,20 @@ impl SimpleAsyncComponent for SandboxApp {
set_title: &tr("symlinks"), set_title: &tr("symlinks"),
set_description: Some(&tr("symlinks-description")), set_description: Some(&tr("symlinks-description")),
#[wrap(Some)]
set_header_suffix = &gtk::Button {
add_css_class: "flat",
set_valign: gtk::Align::Center,
adw::ButtonContent {
set_icon_name: "list-add-symbolic",
set_label: &tr("add")
},
connect_clicked => SandboxAppMsg::AddSymlink
},
#[local_ref] #[local_ref]
symlink_path_from_entry -> adw::EntryRow { symlink_path_from_entry -> adw::EntryRow {
set_title: &tr("original-path") set_title: &tr("original-path")
@ -285,16 +301,6 @@ impl SimpleAsyncComponent for SandboxApp {
#[local_ref] #[local_ref]
symlink_path_to_entry -> adw::EntryRow { symlink_path_to_entry -> adw::EntryRow {
set_title: &tr("new-path") set_title: &tr("new-path")
},
gtk::Button {
set_label: &tr("add"),
add_css_class: "pill",
set_margin_top: 8,
set_halign: gtk::Align::Start,
connect_clicked => SandboxAppMsg::AddSymlink
} }
}, },