mirror of
https://github.com/hydralauncher/hydra.git
synced 2025-03-09 15:40:26 +00:00
Merge branch 'main' into feat/hidden-achievement-description
This commit is contained in:
commit
e5f575705f
11 changed files with 630 additions and 406 deletions
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
|
|
||||||
[<img src="./resources/icon.png" width="144"/>](https://hydralauncher.site)
|
[<img src="../resources/icon.png" width="144"/>](https://help.hydralauncher.gg)
|
||||||
|
|
||||||
<h1 align="center">Hydra Launcher</h1>
|
<h1 align="center">Hydra Launcher</h1>
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
|
|
||||||
[<img src="./resources/icon.png" width="144"/>](https://hydralauncher.site)
|
[<img src="../resources/icon.png" width="144"/>](https://help.hydralauncher.gg)
|
||||||
|
|
||||||
<h1 align="center">Hydra Launcher</h1>
|
<h1 align="center">Hydra Launcher</h1>
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
|
|
||||||
[<img src="./resources/icon.png" width="144"/>](https://hydralauncher.site)
|
[<img src="../resources/icon.png" width="144"/>](https://help.hydralauncher.gg)
|
||||||
|
|
||||||
<h1 align="center">Hydra Launcher</h1>
|
<h1 align="center">Hydra Launcher</h1>
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
|
|
||||||
[<img src="./resources/icon.png" width="144"/>](https://hydralauncher.site)
|
[<img src="./resources/icon.png" width="144"/>](https://help.hydralauncher.gg)
|
||||||
|
|
||||||
<h1 align="center">Hydra Launcher</h1>
|
<h1 align="center">Hydra Launcher</h1>
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
|
|
||||||
[<img src="./resources/icon.png" width="144"/>](https://hydralauncher.site)
|
[<img src="../resources/icon.png" width="144"/>](https://help.hydralauncher.gg)
|
||||||
|
|
||||||
<h1 align="center">Hydra Launcher</h1>
|
<h1 align="center">Hydra Launcher</h1>
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
|
|
||||||
[<img src="./resources/icon.png" width="144"/>](https://hydralauncher.site)
|
[<img src="../resources/icon.png" width="144"/>](https://help.hydralauncher.gg)
|
||||||
|
|
||||||
<h1 align="center">Hydra Launcher</h1>
|
<h1 align="center">Hydra Launcher</h1>
|
||||||
|
|
||||||
|
|
40
package.json
40
package.json
|
@ -34,24 +34,24 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@electron-toolkit/preload": "^3.0.0",
|
"@electron-toolkit/preload": "^3.0.0",
|
||||||
"@electron-toolkit/utils": "^3.0.0",
|
"@electron-toolkit/utils": "^3.0.0",
|
||||||
"@fontsource/noto-sans": "^5.0.22",
|
"@fontsource/noto-sans": "^5.1.0",
|
||||||
"@hookform/resolvers": "^3.9.0",
|
"@hookform/resolvers": "^3.9.1",
|
||||||
"@primer/octicons-react": "^19.9.0",
|
"@primer/octicons-react": "^19.9.0",
|
||||||
"@reduxjs/toolkit": "^2.2.3",
|
"@reduxjs/toolkit": "^2.2.3",
|
||||||
"@vanilla-extract/css": "^1.14.2",
|
"@vanilla-extract/css": "^1.14.2",
|
||||||
"@vanilla-extract/dynamic": "^2.1.1",
|
"@vanilla-extract/dynamic": "^2.1.2",
|
||||||
"@vanilla-extract/recipes": "^0.5.2",
|
"@vanilla-extract/recipes": "^0.5.2",
|
||||||
"auto-launch": "^5.0.6",
|
"auto-launch": "^5.0.6",
|
||||||
"axios": "^1.7.7",
|
"axios": "^1.7.9",
|
||||||
"better-sqlite3": "^11.3.0",
|
"better-sqlite3": "^11.7.0",
|
||||||
"check-disk-space": "^3.4.0",
|
"check-disk-space": "^3.4.0",
|
||||||
"classnames": "^2.5.1",
|
"classnames": "^2.5.1",
|
||||||
"color": "^4.2.3",
|
"color": "^4.2.3",
|
||||||
"color.js": "^1.2.0",
|
"color.js": "^1.2.0",
|
||||||
"create-desktop-shortcuts": "^1.11.0",
|
"create-desktop-shortcuts": "^1.11.0",
|
||||||
"date-fns": "^3.6.0",
|
"date-fns": "^3.6.0",
|
||||||
"dexie": "^4.0.9",
|
"dexie": "^4.0.10",
|
||||||
"electron-log": "^5.2.0",
|
"electron-log": "^5.2.4",
|
||||||
"electron-updater": "^6.3.9",
|
"electron-updater": "^6.3.9",
|
||||||
"file-type": "^19.6.0",
|
"file-type": "^19.6.0",
|
||||||
"flexsearch": "^0.7.43",
|
"flexsearch": "^0.7.43",
|
||||||
|
@ -72,14 +72,14 @@
|
||||||
"sudo-prompt": "^9.2.1",
|
"sudo-prompt": "^9.2.1",
|
||||||
"tar": "^7.4.3",
|
"tar": "^7.4.3",
|
||||||
"typeorm": "^0.3.20",
|
"typeorm": "^0.3.20",
|
||||||
"user-agents": "^1.1.193",
|
"user-agents": "^1.1.387",
|
||||||
"yaml": "^2.4.1",
|
"yaml": "^2.6.1",
|
||||||
"yup": "^1.4.0",
|
"yup": "^1.5.0",
|
||||||
"zod": "^3.23.8"
|
"zod": "^3.24.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@commitlint/cli": "^19.5.0",
|
"@commitlint/cli": "^19.6.0",
|
||||||
"@commitlint/config-conventional": "^19.5.0",
|
"@commitlint/config-conventional": "^19.6.0",
|
||||||
"@electron-toolkit/eslint-config-prettier": "^2.0.0",
|
"@electron-toolkit/eslint-config-prettier": "^2.0.0",
|
||||||
"@electron-toolkit/eslint-config-ts": "^2.0.0",
|
"@electron-toolkit/eslint-config-ts": "^2.0.0",
|
||||||
"@electron-toolkit/tsconfig": "^1.0.1",
|
"@electron-toolkit/tsconfig": "^1.0.1",
|
||||||
|
@ -87,8 +87,8 @@
|
||||||
"@types/auto-launch": "^5.0.5",
|
"@types/auto-launch": "^5.0.5",
|
||||||
"@types/color": "^3.0.6",
|
"@types/color": "^3.0.6",
|
||||||
"@types/folder-hash": "^4.0.4",
|
"@types/folder-hash": "^4.0.4",
|
||||||
"@types/jsdom": "^21.1.6",
|
"@types/jsdom": "^21.1.7",
|
||||||
"@types/jsonwebtoken": "^9.0.6",
|
"@types/jsonwebtoken": "^9.0.7",
|
||||||
"@types/lodash-es": "^4.17.12",
|
"@types/lodash-es": "^4.17.12",
|
||||||
"@types/node": "^20.12.7",
|
"@types/node": "^20.12.7",
|
||||||
"@types/parse-torrent": "^5.8.7",
|
"@types/parse-torrent": "^5.8.7",
|
||||||
|
@ -98,15 +98,15 @@
|
||||||
"@types/user-agents": "^1.0.4",
|
"@types/user-agents": "^1.0.4",
|
||||||
"@vanilla-extract/vite-plugin": "^4.0.7",
|
"@vanilla-extract/vite-plugin": "^4.0.7",
|
||||||
"@vitejs/plugin-react": "^4.2.1",
|
"@vitejs/plugin-react": "^4.2.1",
|
||||||
"electron": "^30.3.0",
|
"electron": "^31.7.6",
|
||||||
"electron-builder": "^25.1.8",
|
"electron-builder": "^25.1.8",
|
||||||
"electron-vite": "^2.0.0",
|
"electron-vite": "^2.0.0",
|
||||||
"eslint": "^8.56.0",
|
"eslint": "^8.56.0",
|
||||||
"eslint-plugin-jsx-a11y": "^6.8.0",
|
"eslint-plugin-jsx-a11y": "^6.10.2",
|
||||||
"eslint-plugin-react": "^7.33.2",
|
"eslint-plugin-react": "^7.37.2",
|
||||||
"eslint-plugin-react-hooks": "^4.6.0",
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
"husky": "^9.0.11",
|
"husky": "^9.1.7",
|
||||||
"prettier": "^3.2.4",
|
"prettier": "^3.4.2",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"sass-embedded": "^1.80.6",
|
"sass-embedded": "^1.80.6",
|
||||||
|
|
|
@ -4,12 +4,13 @@
|
||||||
"successfully_signed_in": "Успешный вход"
|
"successfully_signed_in": "Успешный вход"
|
||||||
},
|
},
|
||||||
"home": {
|
"home": {
|
||||||
"featured": "Рекомендованное",
|
"featured": "Рекомендации",
|
||||||
"surprise_me": "Удиви меня",
|
"surprise_me": "Удиви меня",
|
||||||
"no_results": "Ничего не найдено",
|
"no_results": "Ничего не найдено",
|
||||||
"hot": "Сейчас в топе",
|
"hot": "Сейчас в топе",
|
||||||
"start_typing": "Начинаю вводить текст для поиска...",
|
"start_typing": "Начинаю вводить текст для поиска...",
|
||||||
"weekly": "📅 Лучшие игры недели"
|
"weekly": "📅 Лучшие игры недели",
|
||||||
|
"achievements": "🏆 Игры, в которых нужно победить"
|
||||||
},
|
},
|
||||||
"sidebar": {
|
"sidebar": {
|
||||||
"catalogue": "Каталог",
|
"catalogue": "Каталог",
|
||||||
|
@ -19,7 +20,7 @@
|
||||||
"downloading_metadata": "{{title}} (Загрузка метаданных…)",
|
"downloading_metadata": "{{title}} (Загрузка метаданных…)",
|
||||||
"paused": "{{title}} (Приостановлено)",
|
"paused": "{{title}} (Приостановлено)",
|
||||||
"downloading": "{{title}} ({{percentage}} - Загрузка…)",
|
"downloading": "{{title}} ({{percentage}} - Загрузка…)",
|
||||||
"filter": "Фильтр библиотеки",
|
"filter": "Поиск",
|
||||||
"home": "Главная",
|
"home": "Главная",
|
||||||
"queued": "{{title}} (В очереди)",
|
"queued": "{{title}} (В очереди)",
|
||||||
"game_has_no_executable": "Файл запуска игры не выбран",
|
"game_has_no_executable": "Файл запуска игры не выбран",
|
||||||
|
@ -49,10 +50,10 @@
|
||||||
"previous_page": "Предыдущая страница"
|
"previous_page": "Предыдущая страница"
|
||||||
},
|
},
|
||||||
"game_details": {
|
"game_details": {
|
||||||
"open_download_options": "Открыть варианты загрузки",
|
"open_download_options": "Открыть источники",
|
||||||
"download_options_zero": "Нет вариантов загрузки",
|
"download_options_zero": "Нет источников",
|
||||||
"download_options_one": "{{count}} вариант загрузки",
|
"download_options_one": "{{count}} источник",
|
||||||
"download_options_other": "{{count}} вариантов загрузки",
|
"download_options_other": "{{count}} источников",
|
||||||
"updated_at": "Обновлено {{updated_at}}",
|
"updated_at": "Обновлено {{updated_at}}",
|
||||||
"install": "Установить",
|
"install": "Установить",
|
||||||
"resume": "Возобновить",
|
"resume": "Возобновить",
|
||||||
|
@ -63,7 +64,7 @@
|
||||||
"eta": "Окончание {{eta}}",
|
"eta": "Окончание {{eta}}",
|
||||||
"calculating_eta": "Подсчёт оставшегося времени…",
|
"calculating_eta": "Подсчёт оставшегося времени…",
|
||||||
"downloading_metadata": "Загрузка метаданных…",
|
"downloading_metadata": "Загрузка метаданных…",
|
||||||
"filter": "Фильтр репаков",
|
"filter": "Поиск репаков",
|
||||||
"requirements": "Системные требования",
|
"requirements": "Системные требования",
|
||||||
"minimum": "Минимальные",
|
"minimum": "Минимальные",
|
||||||
"recommended": "Рекомендуемые",
|
"recommended": "Рекомендуемые",
|
||||||
|
@ -77,7 +78,7 @@
|
||||||
"accuracy": "точность {{accuracy}}%",
|
"accuracy": "точность {{accuracy}}%",
|
||||||
"add_to_library": "Добавить в библиотеку",
|
"add_to_library": "Добавить в библиотеку",
|
||||||
"remove_from_library": "Удалить из библиотеки",
|
"remove_from_library": "Удалить из библиотеки",
|
||||||
"no_downloads": "Нет доступных загрузок",
|
"no_downloads": "Нет доступных источников",
|
||||||
"play_time": "Сыграно {{amount}}",
|
"play_time": "Сыграно {{amount}}",
|
||||||
"last_time_played": "Последний запуск {{period}}",
|
"last_time_played": "Последний запуск {{period}}",
|
||||||
"not_played_yet": "Вы ещё не играли в {{title}}",
|
"not_played_yet": "Вы ещё не играли в {{title}}",
|
||||||
|
@ -91,7 +92,7 @@
|
||||||
"select_folder_hint": "Чтобы изменить папку загрузок по умолчанию, откройте <0>Настройки</0>",
|
"select_folder_hint": "Чтобы изменить папку загрузок по умолчанию, откройте <0>Настройки</0>",
|
||||||
"download_now": "Загрузить сейчас",
|
"download_now": "Загрузить сейчас",
|
||||||
"no_shop_details": "Не удалось получить описание",
|
"no_shop_details": "Не удалось получить описание",
|
||||||
"download_options": "Вариантов загрузки",
|
"download_options": "Источники",
|
||||||
"download_path": "Путь для загрузок",
|
"download_path": "Путь для загрузок",
|
||||||
"previous_screenshot": "Предыдущий скриншот",
|
"previous_screenshot": "Предыдущий скриншот",
|
||||||
"next_screenshot": "Следующий скриншот",
|
"next_screenshot": "Следующий скриншот",
|
||||||
|
@ -119,16 +120,53 @@
|
||||||
"last_downloaded_option": "Последний вариант загрузки",
|
"last_downloaded_option": "Последний вариант загрузки",
|
||||||
"create_shortcut_success": "Ярлык создан",
|
"create_shortcut_success": "Ярлык создан",
|
||||||
"create_shortcut_error": "Не удалось создать ярлык",
|
"create_shortcut_error": "Не удалось создать ярлык",
|
||||||
"allow_nsfw_content": "Продолжать",
|
"allow_nsfw_content": "Продолжить",
|
||||||
"download": "Скачать",
|
"download": "Скачать",
|
||||||
"download_count": "Загрузки",
|
"download_count": "Загрузки",
|
||||||
"download_error": "Этот вариант загрузки недоступен",
|
"download_error": "Этот вариант загрузки недоступен",
|
||||||
"executable_path_in_use": "Исполняемый файл уже используется \"{{game}}\"",
|
"executable_path_in_use": "Исполняемый файл уже используется \"{{game}}\"",
|
||||||
"nsfw_content_description": "{{title}} содержит контент, который может не подходить для всех возрастов. \nВы уверены, что хотите продолжить?",
|
"nsfw_content_description": "{{title}} содержит контент, который может не подходить для всех возрастов. \nВы уверены, что хотите продолжить?",
|
||||||
"nsfw_content_title": "Эта игра содержит неприемлемый контент",
|
"nsfw_content_title": "Эта игра содержит неприемлемый контент",
|
||||||
|
"refuse_nsfw_content": "Назад",
|
||||||
|
"stats": "Статистика",
|
||||||
"player_count": "Активные игроки",
|
"player_count": "Активные игроки",
|
||||||
"refuse_nsfw_content": "Возвращаться",
|
"warning": "Внимание:",
|
||||||
"stats": "Статистика"
|
"hydra_needs_to_remain_open": "Для этой загрузки Hydra должна оставаться открытой до завершения. Если Hydra закроется до завершения, вы потеряете прогресс.",
|
||||||
|
"achievements": "Достижения",
|
||||||
|
"achievements_count": "Достижения {{unlockedCount}}/{{achievementsCount}}",
|
||||||
|
"cloud_save": "Облачное сохранение",
|
||||||
|
"cloud_save_description": "Сохраняйте ваш прогресс в облаке и продолжайте играть на любом устройстве",
|
||||||
|
"backups": "Резервные копии",
|
||||||
|
"install_backup": "Установить",
|
||||||
|
"delete_backup": "Удалить",
|
||||||
|
"create_backup": "Создать новую резервную копию",
|
||||||
|
"last_backup_date": "Последняя резервная копия от {{date}}",
|
||||||
|
"no_backup_preview": "Сохранения для этого заголовка не найдены",
|
||||||
|
"restoring_backup": "Восстановление резервной копии ({{progress}} завершено)…",
|
||||||
|
"uploading_backup": "Загрузка резервной копии…",
|
||||||
|
"no_backups": "Вы еще не создали резервных копий для этой игры",
|
||||||
|
"backup_uploaded": "Резервная копия загружена",
|
||||||
|
"backup_deleted": "Резервная копия удалена",
|
||||||
|
"backup_restored": "Резервная копия восстановлена",
|
||||||
|
"see_all_achievements": "Просмотреть все достижения",
|
||||||
|
"sign_in_to_see_achievements": "Войдите, чтобы увидеть достижения",
|
||||||
|
"mapping_method_automatic": "Автоматическая",
|
||||||
|
"mapping_method_manual": "Ручная",
|
||||||
|
"mapping_method_label": "Метод сопоставления",
|
||||||
|
"files_automatically_mapped": "Файлы автоматически сопоставлены",
|
||||||
|
"no_backups_created": "Для этой игры не создано резервных копий",
|
||||||
|
"manage_files": "Управление файлами",
|
||||||
|
"loading_save_preview": "Поиск сохранений…",
|
||||||
|
"wine_prefix": "Префикс Wine",
|
||||||
|
"wine_prefix_description": "Префикс Wine, используемый для запуска этой игры",
|
||||||
|
"no_download_option_info": "Информация недоступна",
|
||||||
|
"backup_deletion_failed": "Не удалось удалить резервную копию",
|
||||||
|
"max_number_of_artifacts_reached": "Достигнуто максимальное количество резервных копий для этой игры",
|
||||||
|
"achievements_not_sync": "Ваши достижения не синхронизированы",
|
||||||
|
"manage_files_description": "Управляйте файлами, которые будут сохраняться и восстанавливаться",
|
||||||
|
"select_folder": "Выбрать папку",
|
||||||
|
"backup_from": "Резервная копия от {{date}}",
|
||||||
|
"custom_backup_location_set": "Установлено настраиваемое местоположение резервной копии"
|
||||||
},
|
},
|
||||||
"activation": {
|
"activation": {
|
||||||
"title": "Активировать Hydra",
|
"title": "Активировать Hydra",
|
||||||
|
@ -147,7 +185,7 @@
|
||||||
"completed": "Завершено",
|
"completed": "Завершено",
|
||||||
"removed": "Не скачано",
|
"removed": "Не скачано",
|
||||||
"cancel": "Отмена",
|
"cancel": "Отмена",
|
||||||
"filter": "Фильтр загруженных игр",
|
"filter": "Поиск загруженных игр",
|
||||||
"remove": "Удалить",
|
"remove": "Удалить",
|
||||||
"downloading_metadata": "Загрузка метаданных…",
|
"downloading_metadata": "Загрузка метаданных…",
|
||||||
"deleting": "Удаление установщика…",
|
"deleting": "Удаление установщика…",
|
||||||
|
@ -168,10 +206,13 @@
|
||||||
"change": "Изменить",
|
"change": "Изменить",
|
||||||
"notifications": "Уведомления",
|
"notifications": "Уведомления",
|
||||||
"enable_download_notifications": "По завершении загрузки",
|
"enable_download_notifications": "По завершении загрузки",
|
||||||
|
"enable_achievement_notifications": "Когда достижение разблокировано",
|
||||||
"enable_repack_list_notifications": "При добавлении нового репака",
|
"enable_repack_list_notifications": "При добавлении нового репака",
|
||||||
"real_debrid_api_token_label": "Real-Debrid API-токен",
|
"real_debrid_api_token_label": "Real-Debrid API-токен",
|
||||||
"quit_app_instead_hiding": "Закрывать приложение вместо сворачивания в трей",
|
"quit_app_instead_hiding": "Закрывать приложение вместо сворачивания в трей",
|
||||||
"launch_with_system": "Запускать Hydra вместе с системой",
|
"launch_with_system": "Запускать Hydra вместе с системой",
|
||||||
|
"launch_minimized": "Запустить Hydra в свернутом виде",
|
||||||
|
"disable_nsfw_alert": "Отключить предупреждение о непристойном контенте",
|
||||||
"general": "Основные",
|
"general": "Основные",
|
||||||
"behavior": "Поведение",
|
"behavior": "Поведение",
|
||||||
"download_sources": "Источники загрузки",
|
"download_sources": "Источники загрузки",
|
||||||
|
@ -196,7 +237,7 @@
|
||||||
"add_download_source_description": "Вставьте ссылку на .json-файл",
|
"add_download_source_description": "Вставьте ссылку на .json-файл",
|
||||||
"download_source_up_to_date": "Обновлён",
|
"download_source_up_to_date": "Обновлён",
|
||||||
"download_source_errored": "Ошибка",
|
"download_source_errored": "Ошибка",
|
||||||
"sync_download_sources": "Синхронизировать источники",
|
"sync_download_sources": "Обновить источники",
|
||||||
"removed_download_source": "Источник загрузок удален",
|
"removed_download_source": "Источник загрузок удален",
|
||||||
"added_download_source": "Источник загрузок добавлен",
|
"added_download_source": "Источник загрузок добавлен",
|
||||||
"download_sources_synced": "Все источники загрузок синхронизированы",
|
"download_sources_synced": "Все источники загрузок синхронизированы",
|
||||||
|
@ -206,13 +247,13 @@
|
||||||
"found_download_option_other": "Найдено {{countFormatted}} вариантов загрузки",
|
"found_download_option_other": "Найдено {{countFormatted}} вариантов загрузки",
|
||||||
"import": "Импортировать",
|
"import": "Импортировать",
|
||||||
"blocked_users": "Заблокированные пользователи",
|
"blocked_users": "Заблокированные пользователи",
|
||||||
"friends_only": "Только друзья",
|
"friends_only": "Только для друзей",
|
||||||
"must_be_valid_url": "Источник должен быть действительным URL-адресом.",
|
"must_be_valid_url": "Источник должен быть действительным URL-адресом.",
|
||||||
"privacy": "Конфиденциальность",
|
"privacy": "Конфиденциальность",
|
||||||
"private": "Частный",
|
"private": "Частный",
|
||||||
"profile_visibility": "Видимость профиля",
|
"profile_visibility": "Видимость профиля",
|
||||||
"profile_visibility_description": "Выберите, кто может видеть ваш профиль и библиотеку",
|
"profile_visibility_description": "Выберите, кто может видеть ваш профиль и библиотеку",
|
||||||
"public": "Общественный",
|
"public": "Публичный",
|
||||||
"required_field": "Это поле обязательно к заполнению",
|
"required_field": "Это поле обязательно к заполнению",
|
||||||
"source_already_exists": "Этот источник уже добавлен",
|
"source_already_exists": "Этот источник уже добавлен",
|
||||||
"user_unblocked": "Пользователь разблокирован"
|
"user_unblocked": "Пользователь разблокирован"
|
||||||
|
@ -223,15 +264,17 @@
|
||||||
"repack_list_updated": "Список репаков обновлен",
|
"repack_list_updated": "Список репаков обновлен",
|
||||||
"repack_count_one": "{{count}} репак добавлен",
|
"repack_count_one": "{{count}} репак добавлен",
|
||||||
"repack_count_other": "{{count}} репаков добавлено",
|
"repack_count_other": "{{count}} репаков добавлено",
|
||||||
"new_update_available": "Доступна версия {{version}}",
|
"new_update_available": "Доступна новая версия {{version}}",
|
||||||
"restart_to_install_update": "Перезапустите Hydra для установки обновления"
|
"restart_to_install_update": "Перезапустите Hydra для установки обновления",
|
||||||
|
"notification_achievement_unlocked_title": "Достижение разблокировано для {{game}}",
|
||||||
|
"notification_achievement_unlocked_body": "были разблокированы {{achievement}} и другие {{count}}"
|
||||||
},
|
},
|
||||||
"system_tray": {
|
"system_tray": {
|
||||||
"open": "Открыть Hydra",
|
"open": "Открыть Hydra",
|
||||||
"quit": "Выйти"
|
"quit": "Выйти"
|
||||||
},
|
},
|
||||||
"game_card": {
|
"game_card": {
|
||||||
"no_downloads": "Нет доступных загрузок"
|
"no_downloads": "Нет доступных источников"
|
||||||
},
|
},
|
||||||
"binary_not_found_modal": {
|
"binary_not_found_modal": {
|
||||||
"title": "Программы не установлены",
|
"title": "Программы не установлены",
|
||||||
|
@ -310,5 +353,25 @@
|
||||||
"report_reason_violence": "Насилие",
|
"report_reason_violence": "Насилие",
|
||||||
"required_field": "Это поле обязательно к заполнению",
|
"required_field": "Это поле обязательно к заполнению",
|
||||||
"undo_friendship_modal_text": "Это отменит вашу дружбу с {{displayName}}."
|
"undo_friendship_modal_text": "Это отменит вашу дружбу с {{displayName}}."
|
||||||
|
},
|
||||||
|
"achievement": {
|
||||||
|
"achievement_unlocked": "Достижение разблокировано",
|
||||||
|
"user_achievements": "Достижения {{displayName}}",
|
||||||
|
"your_achievements": "Ваши достижения",
|
||||||
|
"unlocked_at": "Разблокировано:",
|
||||||
|
"subscription_needed": "Для просмотра этого содержимого необходима подписка на Hydra Cloud",
|
||||||
|
"new_achievements_unlocked": "Разблокировано {{achievementCount}} новых достижений из {{gameCount}} игр",
|
||||||
|
"achievement_progress": "{{unlockedCount}}/{{totalCount}} достижений",
|
||||||
|
"achievements_unlocked_for_game": "Разблокировано {{achievementCount}} новых достижений для {{gameTitle}}"
|
||||||
|
},
|
||||||
|
"tour": {
|
||||||
|
"subscription_tour_title": "Подписка Hydra Cloud",
|
||||||
|
"subscribe_now": "Подпишитесь прямо сейчас",
|
||||||
|
"cloud_saving": "Сохранение в облаке",
|
||||||
|
"cloud_achievements": "Сохраняйте свои достижения в облаке",
|
||||||
|
"animated_profile_picture": "Анимированные фотографии профиля",
|
||||||
|
"premium_support": "Премиальная поддержка",
|
||||||
|
"show_and_compare_achievements": "Показывайте и сравнивайте свои достижения с достижениями других пользователей",
|
||||||
|
"animated_profile_banner": "Анимированный баннер профиля"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -236,24 +236,28 @@ export class AchievementWatcherManager {
|
||||||
};
|
};
|
||||||
|
|
||||||
public static preSearchAchievements = async () => {
|
public static preSearchAchievements = async () => {
|
||||||
const newAchievementsCount =
|
try {
|
||||||
process.platform === "win32"
|
const newAchievementsCount =
|
||||||
? await this.preSearchAchievementsWindows()
|
process.platform === "win32"
|
||||||
: await this.preSearchAchievementsWithWine();
|
? await this.preSearchAchievementsWindows()
|
||||||
|
: await this.preSearchAchievementsWithWine();
|
||||||
|
|
||||||
const totalNewGamesWithAchievements = newAchievementsCount.filter(
|
const totalNewGamesWithAchievements = newAchievementsCount.filter(
|
||||||
(achievements) => achievements
|
(achievements) => achievements
|
||||||
).length;
|
).length;
|
||||||
const totalNewAchievements = newAchievementsCount.reduce(
|
const totalNewAchievements = newAchievementsCount.reduce(
|
||||||
(acc, val) => acc + val,
|
(acc, val) => acc + val,
|
||||||
0
|
0
|
||||||
);
|
|
||||||
|
|
||||||
if (totalNewAchievements > 0) {
|
|
||||||
publishCombinedNewAchievementNotification(
|
|
||||||
totalNewAchievements,
|
|
||||||
totalNewGamesWithAchievements
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (totalNewAchievements > 0) {
|
||||||
|
publishCombinedNewAchievementNotification(
|
||||||
|
totalNewAchievements,
|
||||||
|
totalNewGamesWithAchievements
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
achievementsLogger.error("Error on preSearchAchievements", err);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.hasFinishedMergingWithRemote = true;
|
this.hasFinishedMergingWithRemote = true;
|
||||||
|
|
|
@ -9,144 +9,134 @@ export const parseAchievementFile = (
|
||||||
): UnlockedAchievement[] => {
|
): UnlockedAchievement[] => {
|
||||||
if (!existsSync(filePath)) return [];
|
if (!existsSync(filePath)) return [];
|
||||||
|
|
||||||
if (type == Cracker.codex) {
|
try {
|
||||||
const parsed = iniParse(filePath);
|
if (type == Cracker.codex) {
|
||||||
return processDefault(parsed);
|
const parsed = iniParse(filePath);
|
||||||
|
return processDefault(parsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == Cracker.rune) {
|
||||||
|
const parsed = iniParse(filePath);
|
||||||
|
return processDefault(parsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === Cracker.onlineFix) {
|
||||||
|
const parsed = iniParse(filePath);
|
||||||
|
return processOnlineFix(parsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === Cracker.goldberg) {
|
||||||
|
const parsed = jsonParse(filePath);
|
||||||
|
return processGoldberg(parsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == Cracker.userstats) {
|
||||||
|
const parsed = iniParse(filePath);
|
||||||
|
return processUserStats(parsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == Cracker.rld) {
|
||||||
|
const parsed = iniParse(filePath);
|
||||||
|
return processRld(parsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === Cracker.skidrow) {
|
||||||
|
const parsed = iniParse(filePath);
|
||||||
|
return processSkidrow(parsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === Cracker._3dm) {
|
||||||
|
const parsed = iniParse(filePath);
|
||||||
|
return process3DM(parsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === Cracker.flt) {
|
||||||
|
const achievements = readdirSync(filePath);
|
||||||
|
|
||||||
|
return achievements.map((achievement) => {
|
||||||
|
return {
|
||||||
|
name: achievement,
|
||||||
|
unlockTime: Date.now(),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === Cracker.creamAPI) {
|
||||||
|
const parsed = iniParse(filePath);
|
||||||
|
return processCreamAPI(parsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === Cracker.empress) {
|
||||||
|
const parsed = jsonParse(filePath);
|
||||||
|
return processGoldberg(parsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === Cracker.razor1911) {
|
||||||
|
return processRazor1911(filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
achievementsLogger.log(
|
||||||
|
`Unprocessed ${type} achievements found on ${filePath}`
|
||||||
|
);
|
||||||
|
return [];
|
||||||
|
} catch (err) {
|
||||||
|
achievementsLogger.error(`Error parsing ${type} - ${filePath}`, err);
|
||||||
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == Cracker.rune) {
|
|
||||||
const parsed = iniParse(filePath);
|
|
||||||
return processDefault(parsed);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === Cracker.onlineFix) {
|
|
||||||
const parsed = iniParse(filePath);
|
|
||||||
return processOnlineFix(parsed);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === Cracker.goldberg) {
|
|
||||||
const parsed = jsonParse(filePath);
|
|
||||||
return processGoldberg(parsed);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == Cracker.userstats) {
|
|
||||||
const parsed = iniParse(filePath);
|
|
||||||
return processUserStats(parsed);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == Cracker.rld) {
|
|
||||||
const parsed = iniParse(filePath);
|
|
||||||
return processRld(parsed);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === Cracker.skidrow) {
|
|
||||||
const parsed = iniParse(filePath);
|
|
||||||
return processSkidrow(parsed);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === Cracker._3dm) {
|
|
||||||
const parsed = iniParse(filePath);
|
|
||||||
return process3DM(parsed);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === Cracker.flt) {
|
|
||||||
const achievements = readdirSync(filePath);
|
|
||||||
|
|
||||||
return achievements.map((achievement) => {
|
|
||||||
return {
|
|
||||||
name: achievement,
|
|
||||||
unlockTime: Date.now(),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === Cracker.creamAPI) {
|
|
||||||
const parsed = iniParse(filePath);
|
|
||||||
return processCreamAPI(parsed);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === Cracker.empress) {
|
|
||||||
const parsed = jsonParse(filePath);
|
|
||||||
return processGoldberg(parsed);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === Cracker.razor1911) {
|
|
||||||
return processRazor1911(filePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
achievementsLogger.log(
|
|
||||||
`Unprocessed ${type} achievements found on ${filePath}`
|
|
||||||
);
|
|
||||||
return [];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const iniParse = (filePath: string) => {
|
const iniParse = (filePath: string) => {
|
||||||
try {
|
const fileContent = readFileSync(filePath, "utf-8");
|
||||||
const fileContent = readFileSync(filePath, "utf-8");
|
|
||||||
|
|
||||||
const lines =
|
const lines =
|
||||||
fileContent.charCodeAt(0) === 0xfeff
|
fileContent.charCodeAt(0) === 0xfeff
|
||||||
? fileContent.slice(1).split(/[\r\n]+/)
|
? fileContent.slice(1).split(/[\r\n]+/)
|
||||||
: fileContent.split(/[\r\n]+/);
|
: fileContent.split(/[\r\n]+/);
|
||||||
|
|
||||||
let objectName = "";
|
let objectName = "";
|
||||||
const object: Record<string, Record<string, string | number>> = {};
|
const object: Record<string, Record<string, string | number>> = {};
|
||||||
|
|
||||||
for (const line of lines) {
|
for (const line of lines) {
|
||||||
if (line.startsWith("###") || !line.length) continue;
|
if (line.startsWith("###") || !line.length) continue;
|
||||||
|
|
||||||
if (line.startsWith("[") && line.endsWith("]")) {
|
if (line.startsWith("[") && line.endsWith("]")) {
|
||||||
objectName = line.slice(1, -1);
|
objectName = line.slice(1, -1);
|
||||||
object[objectName] = {};
|
object[objectName] = {};
|
||||||
} else {
|
} else {
|
||||||
const [name, ...value] = line.split("=");
|
const [name, ...value] = line.split("=");
|
||||||
object[objectName][name.trim()] = value.join("=").trim();
|
object[objectName][name.trim()] = value.join("=").trim();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return object;
|
|
||||||
} catch (err) {
|
|
||||||
achievementsLogger.error(`Error parsing ${filePath}`, err);
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return object;
|
||||||
};
|
};
|
||||||
|
|
||||||
const jsonParse = (filePath: string) => {
|
const jsonParse = (filePath: string) => {
|
||||||
try {
|
return JSON.parse(readFileSync(filePath, "utf-8"));
|
||||||
return JSON.parse(readFileSync(filePath, "utf-8"));
|
|
||||||
} catch (err) {
|
|
||||||
achievementsLogger.error(`Error parsing ${filePath}`, err);
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const processRazor1911 = (filePath: string): UnlockedAchievement[] => {
|
const processRazor1911 = (filePath: string): UnlockedAchievement[] => {
|
||||||
try {
|
const fileContent = readFileSync(filePath, "utf-8");
|
||||||
const fileContent = readFileSync(filePath, "utf-8");
|
|
||||||
|
|
||||||
const lines =
|
const lines =
|
||||||
fileContent.charCodeAt(0) === 0xfeff
|
fileContent.charCodeAt(0) === 0xfeff
|
||||||
? fileContent.slice(1).split(/[\r\n]+/)
|
? fileContent.slice(1).split(/[\r\n]+/)
|
||||||
: fileContent.split(/[\r\n]+/);
|
: fileContent.split(/[\r\n]+/);
|
||||||
|
|
||||||
const achievements: UnlockedAchievement[] = [];
|
const achievements: UnlockedAchievement[] = [];
|
||||||
for (const line of lines) {
|
for (const line of lines) {
|
||||||
if (!line.length) continue;
|
if (!line.length) continue;
|
||||||
|
|
||||||
const [name, unlocked, unlockTime] = line.split(" ");
|
const [name, unlocked, unlockTime] = line.split(" ");
|
||||||
if (unlocked === "1") {
|
if (unlocked === "1") {
|
||||||
achievements.push({
|
achievements.push({
|
||||||
name,
|
name,
|
||||||
unlockTime: Number(unlockTime) * 1000,
|
unlockTime: Number(unlockTime) * 1000,
|
||||||
});
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return achievements;
|
|
||||||
} catch (err) {
|
|
||||||
achievementsLogger.error(`Error processing ${filePath}`, err);
|
|
||||||
return [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return achievements;
|
||||||
};
|
};
|
||||||
|
|
||||||
const processOnlineFix = (unlockedAchievements: any): UnlockedAchievement[] => {
|
const processOnlineFix = (unlockedAchievements: any): UnlockedAchievement[] => {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue