mirror of
https://github.com/hydralauncher/hydra.git
synced 2025-02-03 00:33:49 +03:00
feat: removing insert custom styles
This commit is contained in:
commit
cedb61cb38
@ -1,4 +1,3 @@
|
|||||||
MAIN_VITE_API_URL=API_URL
|
MAIN_VITE_API_URL=API_URL
|
||||||
MAIN_VITE_AUTH_URL=AUTH_URL
|
MAIN_VITE_AUTH_URL=AUTH_URL
|
||||||
MAIN_VITE_STEAMGRIDDB_API_KEY=YOUR_API_KEY
|
MAIN_VITE_STEAMGRIDDB_API_KEY=YOUR_API_KEY
|
||||||
RENDERER_VITE_INTERCOM_APP_ID=YOUR_APP_ID
|
|
||||||
|
5
.github/workflows/build.yml
vendored
5
.github/workflows/build.yml
vendored
@ -2,6 +2,9 @@ name: Build
|
|||||||
|
|
||||||
on: pull_request
|
on: pull_request
|
||||||
|
|
||||||
|
env:
|
||||||
|
AWS_REGION: us-east-1
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
strategy:
|
strategy:
|
||||||
@ -45,6 +48,7 @@ jobs:
|
|||||||
MAIN_VITE_CHECKOUT_URL: ${{ vars.MAIN_VITE_STAGING_CHECKOUT_URL }}
|
MAIN_VITE_CHECKOUT_URL: ${{ vars.MAIN_VITE_STAGING_CHECKOUT_URL }}
|
||||||
MAIN_VITE_ANALYTICS_API_URL: ${{ vars.MAIN_VITE_ANALYTICS_API_URL }}
|
MAIN_VITE_ANALYTICS_API_URL: ${{ vars.MAIN_VITE_ANALYTICS_API_URL }}
|
||||||
RENDERER_VITE_INTERCOM_APP_ID: ${{ vars.RENDERER_VITE_INTERCOM_APP_ID }}
|
RENDERER_VITE_INTERCOM_APP_ID: ${{ vars.RENDERER_VITE_INTERCOM_APP_ID }}
|
||||||
|
RENDERER_VITE_EXTERNAL_RESOURCES_URL: ${{ vars.RENDERER_VITE_EXTERNAL_RESOURCES_URL }}
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Build Windows
|
- name: Build Windows
|
||||||
@ -56,6 +60,7 @@ jobs:
|
|||||||
MAIN_VITE_CHECKOUT_URL: ${{ vars.MAIN_VITE_STAGING_CHECKOUT_URL }}
|
MAIN_VITE_CHECKOUT_URL: ${{ vars.MAIN_VITE_STAGING_CHECKOUT_URL }}
|
||||||
MAIN_VITE_ANALYTICS_API_URL: ${{ vars.MAIN_VITE_ANALYTICS_API_URL }}
|
MAIN_VITE_ANALYTICS_API_URL: ${{ vars.MAIN_VITE_ANALYTICS_API_URL }}
|
||||||
RENDERER_VITE_INTERCOM_APP_ID: ${{ vars.RENDERER_VITE_INTERCOM_APP_ID }}
|
RENDERER_VITE_INTERCOM_APP_ID: ${{ vars.RENDERER_VITE_INTERCOM_APP_ID }}
|
||||||
|
RENDERER_VITE_EXTERNAL_RESOURCES_URL: ${{ vars.RENDERER_VITE_EXTERNAL_RESOURCES_URL }}
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Create artifact
|
- name: Create artifact
|
||||||
|
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@ -47,6 +47,7 @@ jobs:
|
|||||||
MAIN_VITE_CHECKOUT_URL: ${{ vars.MAIN_VITE_CHECKOUT_URL }}
|
MAIN_VITE_CHECKOUT_URL: ${{ vars.MAIN_VITE_CHECKOUT_URL }}
|
||||||
MAIN_VITE_ANALYTICS_API_URL: ${{ vars.MAIN_VITE_ANALYTICS_API_URL }}
|
MAIN_VITE_ANALYTICS_API_URL: ${{ vars.MAIN_VITE_ANALYTICS_API_URL }}
|
||||||
RENDERER_VITE_INTERCOM_APP_ID: ${{ vars.RENDERER_VITE_INTERCOM_APP_ID }}
|
RENDERER_VITE_INTERCOM_APP_ID: ${{ vars.RENDERER_VITE_INTERCOM_APP_ID }}
|
||||||
|
RENDERER_VITE_EXTERNAL_RESOURCES_URL: ${{ vars.RENDERER_VITE_EXTERNAL_RESOURCES_URL }}
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: Build Windows
|
- name: Build Windows
|
||||||
if: matrix.os == 'windows-latest'
|
if: matrix.os == 'windows-latest'
|
||||||
@ -57,6 +58,7 @@ jobs:
|
|||||||
MAIN_VITE_CHECKOUT_URL: ${{ vars.MAIN_VITE_CHECKOUT_URL }}
|
MAIN_VITE_CHECKOUT_URL: ${{ vars.MAIN_VITE_CHECKOUT_URL }}
|
||||||
MAIN_VITE_ANALYTICS_API_URL: ${{ vars.MAIN_VITE_ANALYTICS_API_URL }}
|
MAIN_VITE_ANALYTICS_API_URL: ${{ vars.MAIN_VITE_ANALYTICS_API_URL }}
|
||||||
RENDERER_VITE_INTERCOM_APP_ID: ${{ vars.RENDERER_VITE_INTERCOM_APP_ID }}
|
RENDERER_VITE_INTERCOM_APP_ID: ${{ vars.RENDERER_VITE_INTERCOM_APP_ID }}
|
||||||
|
RENDERER_VITE_EXTERNAL_RESOURCES_URL: ${{ vars.RENDERER_VITE_EXTERNAL_RESOURCES_URL }}
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: Create artifact
|
- name: Create artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
|
1
.python-version
Normal file
1
.python-version
Normal file
@ -0,0 +1 @@
|
|||||||
|
3.9.20
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "hydralauncher",
|
"name": "hydralauncher",
|
||||||
"version": "3.0.5",
|
"version": "3.0.8",
|
||||||
"description": "Hydra",
|
"description": "Hydra",
|
||||||
"main": "./out/main/index.js",
|
"main": "./out/main/index.js",
|
||||||
"author": "Los Broxas",
|
"author": "Los Broxas",
|
||||||
@ -36,7 +36,6 @@
|
|||||||
"@electron-toolkit/utils": "^3.0.0",
|
"@electron-toolkit/utils": "^3.0.0",
|
||||||
"@fontsource/noto-sans": "^5.0.22",
|
"@fontsource/noto-sans": "^5.0.22",
|
||||||
"@hookform/resolvers": "^3.9.0",
|
"@hookform/resolvers": "^3.9.0",
|
||||||
"@intercom/messenger-js-sdk": "^0.0.14",
|
|
||||||
"@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",
|
||||||
|
381
src/locales/bg/translation.json
Normal file
381
src/locales/bg/translation.json
Normal file
@ -0,0 +1,381 @@
|
|||||||
|
{
|
||||||
|
"language_name": "Български",
|
||||||
|
"app": {
|
||||||
|
"successfully_signed_in": "Успешно вписване"
|
||||||
|
},
|
||||||
|
"home": {
|
||||||
|
"featured": "Препоръчани",
|
||||||
|
"surprise_me": "Изненадай ме",
|
||||||
|
"no_results": "Не са намерени резултати",
|
||||||
|
"start_typing": "Търсене...",
|
||||||
|
"hot": "Актуално сега",
|
||||||
|
"weekly": "📅 Най-доброто от седмицата",
|
||||||
|
"achievements": "🏆 Игри, които да победите"
|
||||||
|
},
|
||||||
|
"sidebar": {
|
||||||
|
"catalogue": "Каталог",
|
||||||
|
"downloads": "Изтегляния",
|
||||||
|
"settings": "Настройки",
|
||||||
|
"my_library": "Моята библиотека",
|
||||||
|
"downloading_metadata": "{{title}} (Сваляне на метаданни…)",
|
||||||
|
"paused": "{{title}} (Пауза)",
|
||||||
|
"downloading": "{{title}} ({{percentage}} - Изтегляне…)",
|
||||||
|
"filter": "Търсене по име",
|
||||||
|
"home": "Начало",
|
||||||
|
"queued": "{{title}} (Опашка)",
|
||||||
|
"game_has_no_executable": "Играта няма избран изпълним файл",
|
||||||
|
"sign_in": "Вписване",
|
||||||
|
"friends": "Приятели",
|
||||||
|
"need_help": "Имате нужда от помощ??"
|
||||||
|
},
|
||||||
|
"header": {
|
||||||
|
"search": "Търсене",
|
||||||
|
"home": "Начало",
|
||||||
|
"catalogue": "Каталог",
|
||||||
|
"downloads": "Изтегляния",
|
||||||
|
"search_results": "Резултати от търсене",
|
||||||
|
"settings": "Настройки",
|
||||||
|
"version_available_install": "Версия {{version}} е налична. Кликни тук, за да рестартирате и инсталирате.",
|
||||||
|
"version_available_download": "Версия {{version}} е налична. Кликни тук за изтегляне."
|
||||||
|
},
|
||||||
|
"bottom_panel": {
|
||||||
|
"no_downloads_in_progress": "Няма изтегляния в ход",
|
||||||
|
"downloading_metadata": "Сваляне на {{title}} метадата…",
|
||||||
|
"downloading": "Изтегляне на {{title}}… ({{percentage}} готово) - Остават {{eta}} - {{speed}}",
|
||||||
|
"calculating_eta": "Изтегляне на {{title}}… ({{percentage}} готово) - Изчисляване на оставащо време…",
|
||||||
|
"checking_files": "Проверка на {{title}} файловете… ({{percentage}} готово)"
|
||||||
|
},
|
||||||
|
"catalogue": {
|
||||||
|
"next_page": "Следваща страница",
|
||||||
|
"previous_page": "Предишна страница"
|
||||||
|
},
|
||||||
|
"game_details": {
|
||||||
|
"open_download_options": "Варианти за изтегляне",
|
||||||
|
"download_options_zero": "Няма варианти за изтегляне",
|
||||||
|
"download_options_one": "{{count}} варианти за изтегляне",
|
||||||
|
"download_options_other": "{{count}} варианти за изтегляне",
|
||||||
|
"updated_at": "Обновено на {{updated_at}}",
|
||||||
|
"install": "Инсталирай",
|
||||||
|
"resume": "Продължи",
|
||||||
|
"pause": "Пауза",
|
||||||
|
"cancel": "Отказ",
|
||||||
|
"remove": "Премахни",
|
||||||
|
"space_left_on_disk": "{{space}} място на диска",
|
||||||
|
"eta": "Заклчение {{eta}}",
|
||||||
|
"calculating_eta": "Калкулиране на оставащо време…",
|
||||||
|
"downloading_metadata": "Изтегляне на метадата…",
|
||||||
|
"filter": "Филтрирай repacks",
|
||||||
|
"requirements": "Системни изисквания",
|
||||||
|
"minimum": "Минимални",
|
||||||
|
"recommended": "Препоръчителни",
|
||||||
|
"paused": "Паузирано",
|
||||||
|
"release_date": "Издадено на {{date}}",
|
||||||
|
"publisher": "Публикувано от {{publisher}}",
|
||||||
|
"hours": "часове",
|
||||||
|
"minutes": "минути",
|
||||||
|
"amount_hours": "{{amount}} часа",
|
||||||
|
"amount_minutes": "{{amount}} минути",
|
||||||
|
"accuracy": "{{accuracy}}% точност",
|
||||||
|
"add_to_library": "Добави в библиотеката",
|
||||||
|
"remove_from_library": "Премахни от библиотеката",
|
||||||
|
"no_downloads": "Няма налични изтегляния",
|
||||||
|
"play_time": "Игрално време {{amount}}",
|
||||||
|
"last_time_played": "Последно пускане {{period}}",
|
||||||
|
"not_played_yet": "Не сте играли {{title}} все още",
|
||||||
|
"next_suggestion": "Следващо предложение",
|
||||||
|
"play": "Пускане",
|
||||||
|
"deleting": "Изтриване на инсталация…",
|
||||||
|
"close": "Затвори",
|
||||||
|
"playing_now": "Играй сега",
|
||||||
|
"change": "Промяна",
|
||||||
|
"repacks_modal_description": "Избери repack който искаш да изтеглиш",
|
||||||
|
"select_folder_hint": "За да промените стандартната папка отидете в <0>Настройки</0>",
|
||||||
|
"download_now": "Изтегли сега",
|
||||||
|
"no_shop_details": "Не може да се извлекат данни за магазина.",
|
||||||
|
"download_options": "Опции за сваляне",
|
||||||
|
"download_path": "Път за сваляне",
|
||||||
|
"previous_screenshot": "Предишна снимка",
|
||||||
|
"next_screenshot": "Следваща снимка",
|
||||||
|
"screenshot": "Снимка {{number}}",
|
||||||
|
"open_screenshot": "Отвори снимки {{number}}",
|
||||||
|
"download_settings": "Настройки за сваляне",
|
||||||
|
"downloader": "Downloader",
|
||||||
|
"select_executable": "Избери",
|
||||||
|
"no_executable_selected": "Няма избран стартиращ файл",
|
||||||
|
"open_folder": "Отвори папка",
|
||||||
|
"open_download_location": "Виж свалените файлове",
|
||||||
|
"create_shortcut": "Пряк път на Десктопа",
|
||||||
|
"remove_files": "Премахни файловете",
|
||||||
|
"remove_from_library_title": "Сигурен ли си?",
|
||||||
|
"remove_from_library_description": "Това ще премахне {{game}} от Библиотеката",
|
||||||
|
"options": "Опции",
|
||||||
|
"executable_section_title": "Стартиращ файл",
|
||||||
|
"executable_section_description": "Пътят на файла, който ще се изпълни, когато се щракне върху \"Пускане\"",
|
||||||
|
"downloads_secion_title": "Свалени",
|
||||||
|
"downloads_section_description": "Вижте актуализации или други версии на тази игра",
|
||||||
|
"danger_zone_section_title": "Опасна зона",
|
||||||
|
"danger_zone_section_description": "Премахнете тази игра от библиотеката си или от файловете, изтеглени от Hydra",
|
||||||
|
"download_in_progress": "Изтегляне в ход",
|
||||||
|
"download_paused": "Изтеглянето е паузирано",
|
||||||
|
"last_downloaded_option": "Опция от последно изтегляне",
|
||||||
|
"create_shortcut_success": "Прекият път е създаден успешно",
|
||||||
|
"create_shortcut_error": "Грешка при създаването на пряк път",
|
||||||
|
"nsfw_content_title": "Тази игра съдържа неподходящо съдържание",
|
||||||
|
"nsfw_content_description": "{{title}} съдържа съдържание, което може да не е подходящо за всички възрасти. Сигурни ли сте, че искате да продължите?",
|
||||||
|
"allow_nsfw_content": "Продължи",
|
||||||
|
"refuse_nsfw_content": "Назад",
|
||||||
|
"stats": "Статистики",
|
||||||
|
"download_count": "Сваляния",
|
||||||
|
"player_count": "Активни играчи",
|
||||||
|
"download_error": "Тази опция за изтегляне не е налична",
|
||||||
|
"download": "Свали",
|
||||||
|
"executable_path_in_use": "Изпълнимият файл вече се използва от \"{{game}}\"",
|
||||||
|
"warning": "Внимание:",
|
||||||
|
"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 prefix използван за тази игра",
|
||||||
|
"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": {
|
||||||
|
"title": "Активирай Hydra",
|
||||||
|
"installation_id": "Идентификатор на инсталацията:",
|
||||||
|
"enter_activation_code": "Въведете кода за активиране",
|
||||||
|
"message": "Ако не знаете къде да попитате за това, значи не трябва да го имате..",
|
||||||
|
"activate": "Активирай",
|
||||||
|
"loading": "Зареждане…"
|
||||||
|
},
|
||||||
|
"downloads": {
|
||||||
|
"resume": "Продължи",
|
||||||
|
"pause": "Пауза",
|
||||||
|
"eta": "Conclusion {{eta}}",
|
||||||
|
"paused": "Паузирано",
|
||||||
|
"verifying": "Проверка…",
|
||||||
|
"completed": "Готово",
|
||||||
|
"removed": "Не е изтеглен",
|
||||||
|
"cancel": "Отказ",
|
||||||
|
"filter": "Филтриране на изтеглени игри",
|
||||||
|
"remove": "Премахни",
|
||||||
|
"downloading_metadata": "Изтегляне на метаданни…",
|
||||||
|
"deleting": "Изтриване на инсталатора…",
|
||||||
|
"delete": "Премахване на инсталатора",
|
||||||
|
"delete_modal_title": "Сигурени ли сте?",
|
||||||
|
"delete_modal_description": "Това ще премахне всички инсталационни файлове от компютъра ви.",
|
||||||
|
"install": "Инсталирай",
|
||||||
|
"download_in_progress": "В процес на изпълнение",
|
||||||
|
"queued_downloads": "Изтеглени файлове в опашката",
|
||||||
|
"downloads_completed": "Приключени",
|
||||||
|
"queued": "В опашка",
|
||||||
|
"no_downloads_title": "Толкова е празно",
|
||||||
|
"no_downloads_description": "Все още не сте изтеглили нищо с Hydra, но никога не е късно да започнете...",
|
||||||
|
"checking_files": "Проверка на файлове…"
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"downloads_path": "Инсталационен път",
|
||||||
|
"change": "Актуализиране",
|
||||||
|
"notifications": "Известия",
|
||||||
|
"enable_download_notifications": "Когато изтеглянето е завършено",
|
||||||
|
"enable_repack_list_notifications": "Когато се добави нов repack",
|
||||||
|
"real_debrid_api_token_label": "Real-Debrid API токен",
|
||||||
|
"quit_app_instead_hiding": "Не скривайте Hydra при затваряне",
|
||||||
|
"launch_with_system": "Стартиране на Hydra при стартиране на системата",
|
||||||
|
"general": "Общ",
|
||||||
|
"behavior": "Поведение",
|
||||||
|
"download_sources": "Източници за изтегляне",
|
||||||
|
"language": "Език",
|
||||||
|
"real_debrid_api_token": "API Токен",
|
||||||
|
"enable_real_debrid": "Включи Real-Debrid",
|
||||||
|
"real_debrid_description": "Real-Debrid е неограничен даунлоудър, който ви позволява бързо да изтегляте файлове, ограничени само от скоростта на интернет..",
|
||||||
|
"real_debrid_invalid_token": "Невалиден API токен",
|
||||||
|
"real_debrid_api_token_hint": "Вземете своя API токен <0>тук</0>",
|
||||||
|
"real_debrid_free_account_error": "Акаунтът \"{{username}}\" е безплатен акаунт. Моля абонирай се за Real-Debrid",
|
||||||
|
"real_debrid_linked_message": "Акаунтът \"{{username}}\" е свързан",
|
||||||
|
"save_changes": "Запази промените",
|
||||||
|
"changes_saved": "Промените са успешно запазни",
|
||||||
|
"download_sources_description": "Hydra ще извлича връзките за изтегляне от тези източници. URL адресът на източника трябва да е директна връзка към .json файл, съдържащ връзките за изтегляне.",
|
||||||
|
"validate_download_source": "Валидиране",
|
||||||
|
"remove_download_source": "Премахни",
|
||||||
|
"add_download_source": "Добави източник",
|
||||||
|
"download_count_zero": "Няма опции за сваляне",
|
||||||
|
"download_count_one": "{{countFormatted}} опции за сваляне",
|
||||||
|
"download_count_other": "{{countFormatted}} опции за сваляне",
|
||||||
|
"download_source_url": "URL адрес на източника за изтегляне",
|
||||||
|
"add_download_source_description": "Вмъкнете URL адреса на файла .json",
|
||||||
|
"download_source_up_to_date": "Актуален",
|
||||||
|
"download_source_errored": "Сгрешен",
|
||||||
|
"sync_download_sources": "Синхронизирай източниците",
|
||||||
|
"removed_download_source": "Източника за сваляне е премахнат",
|
||||||
|
"added_download_source": "Добавен източник за сваляне",
|
||||||
|
"download_sources_synced": "Всички източници за сваляне са синхронизирани",
|
||||||
|
"insert_valid_json_url": "Добавете ваиден JSON линк",
|
||||||
|
"found_download_option_zero": "Няма намерени опции за сваляне",
|
||||||
|
"found_download_option_one": "Намерени {{countFormatted}} опции за сваляне",
|
||||||
|
"found_download_option_other": "Намерени {{countFormatted}} опции за сваляне",
|
||||||
|
"import": "Внеси",
|
||||||
|
"public": "Публичен",
|
||||||
|
"private": "Личен",
|
||||||
|
"friends_only": "Само за приятели",
|
||||||
|
"privacy": "Поверителност",
|
||||||
|
"profile_visibility": "Видимост на профила",
|
||||||
|
"profile_visibility_description": "Изберете кой може да вижда вашия профил и библиотека",
|
||||||
|
"required_field": "Това поле е задължително",
|
||||||
|
"source_already_exists": "Този източник вече е добавен",
|
||||||
|
"must_be_valid_url": "Източникът трябва да е валиден URL адрес.",
|
||||||
|
"blocked_users": "Блокирани потребители",
|
||||||
|
"user_unblocked": "Потребителят е бил деблокиран",
|
||||||
|
"enable_achievement_notifications": "Когато е отключено постижение",
|
||||||
|
"launch_minimized": "Стартиране на Hydra минимизирано",
|
||||||
|
"disable_nsfw_alert": "Деактивиране на предупреждението NSFW"
|
||||||
|
},
|
||||||
|
"notifications": {
|
||||||
|
"download_complete": "Изтеглянето е завършено",
|
||||||
|
"game_ready_to_install": "{{title}} е готово за инсталиране",
|
||||||
|
"repack_list_updated": "Repack лист е обновен",
|
||||||
|
"repack_count_one": "{{count}} repack е добавен",
|
||||||
|
"repack_count_other": "{{count}} repacks добавени",
|
||||||
|
"new_update_available": "Версия {{version}} е налична",
|
||||||
|
"restart_to_install_update": "Рестартирайте Hydra, за да инсталирате актуализацията",
|
||||||
|
"notification_achievement_unlocked_title": "Отключено постижение за {{game}}",
|
||||||
|
"notification_achievement_unlocked_body": "{{achievement}} и други {{count}} са отклщчени"
|
||||||
|
},
|
||||||
|
"system_tray": {
|
||||||
|
"open": "Отвори Hydra",
|
||||||
|
"quit": "Изход"
|
||||||
|
},
|
||||||
|
"game_card": {
|
||||||
|
"no_downloads": "Няма налични изтегляния"
|
||||||
|
},
|
||||||
|
"binary_not_found_modal": {
|
||||||
|
"title": "Не инсталирани програми",
|
||||||
|
"description": "Wine или Lutris изпълними файлове не бяха открити на вашата система",
|
||||||
|
"instructions": "Проверете правилния начин за инсталиране на някоя от тях на вашата дистрибуция на Linux, за да може играта да работи нормално"
|
||||||
|
},
|
||||||
|
"modal": {
|
||||||
|
"close": "Бутон за затваряне"
|
||||||
|
},
|
||||||
|
"forms": {
|
||||||
|
"toggle_password_visibility": "Превключване на видимостта на паролата"
|
||||||
|
},
|
||||||
|
"user_profile": {
|
||||||
|
"amount_hours": "{{amount}} часове",
|
||||||
|
"amount_minutes": "{{amount}} минути",
|
||||||
|
"last_time_played": "Последно играно {{period}}",
|
||||||
|
"activity": "Скорошна активност",
|
||||||
|
"library": "Библиотека",
|
||||||
|
"total_play_time": "Общо време за игра: {{amount}}",
|
||||||
|
"no_recent_activity_title": "Хмм… няма нищо тук",
|
||||||
|
"no_recent_activity_description": "Не сте играли игри напоследък. Време е да промените това.!",
|
||||||
|
"display_name": "Показване на името",
|
||||||
|
"saving": "Запазване",
|
||||||
|
"save": "Запис",
|
||||||
|
"edit_profile": "Редактиране на профила",
|
||||||
|
"saved_successfully": "Запазено успешно",
|
||||||
|
"try_again": "Моля, опитайте пак",
|
||||||
|
"sign_out_modal_title": "Сигурни ли сте?",
|
||||||
|
"cancel": "Отказ",
|
||||||
|
"successfully_signed_out": "Успешно се отписахте",
|
||||||
|
"sign_out": "Отписване",
|
||||||
|
"playing_for": "В игра от {{amount}}",
|
||||||
|
"sign_out_modal_text": "Вашата библиотека е свързана с текущата ви сметка. Когато се отпишете, библиотеката ви вече няма да е видима и напредъкът няма да бъде запазен. Продължете с отписването?",
|
||||||
|
"add_friends": "Добави приятели",
|
||||||
|
"add": "Добави",
|
||||||
|
"friend_code": "Приятелски код",
|
||||||
|
"see_profile": "Виж профила",
|
||||||
|
"sending": "Изпращане",
|
||||||
|
"friend_request_sent": "Изпратена покана за приятелство",
|
||||||
|
"friends": "Приятели",
|
||||||
|
"friends_list": "Списък с приятели",
|
||||||
|
"user_not_found": "Не е намерен потребител",
|
||||||
|
"block_user": "Блокирай потребител",
|
||||||
|
"add_friend": "Добави приятел",
|
||||||
|
"request_sent": "Изпратена покана",
|
||||||
|
"request_received": "Получена покана",
|
||||||
|
"accept_request": "Приеми поканата",
|
||||||
|
"ignore_request": "Игнирирай поканата",
|
||||||
|
"cancel_request": "Откажи поканата",
|
||||||
|
"undo_friendship": "Отмяна на приятелството",
|
||||||
|
"request_accepted": "Поканата е приета",
|
||||||
|
"user_blocked_successfully": "Потребителят е блокиран успешно",
|
||||||
|
"user_block_modal_text": "Това ще блокира {{displayName}}",
|
||||||
|
"blocked_users": "Блокирани потребители",
|
||||||
|
"unblock": "Отблокирай",
|
||||||
|
"no_friends_added": "Не сте добавили приятели",
|
||||||
|
"pending": "Чакащи",
|
||||||
|
"no_pending_invites": "Нямате чакащи покани",
|
||||||
|
"no_blocked_users": "Нямате блокирани потребители",
|
||||||
|
"friend_code_copied": "Приятелския код е копиран",
|
||||||
|
"undo_friendship_modal_text": "Това ще отмени приятелството ви с {{displayName}}",
|
||||||
|
"privacy_hint": "За да настроите кой може да вижда това, отидете в <0>Настройки</0>",
|
||||||
|
"locked_profile": "Този профил е личен",
|
||||||
|
"image_process_failure": "Грешка при обработката на изображението",
|
||||||
|
"required_field": "Това поле е задължително",
|
||||||
|
"displayname_min_length": "Името трябва да е дълго поне 3 символа",
|
||||||
|
"displayname_max_length": "Името трябва да е с дължина не повече от 50 символа.",
|
||||||
|
"report_profile": "Докладвай този профил",
|
||||||
|
"report_reason": "Защо докладвате този профил?",
|
||||||
|
"report_description": "Допълнителна информация",
|
||||||
|
"report_description_placeholder": "Допълнителна информация",
|
||||||
|
"report": "Докладвай",
|
||||||
|
"report_reason_hate": "Омразна реч",
|
||||||
|
"report_reason_sexual_content": "Сексуално съдържание",
|
||||||
|
"report_reason_violence": "Насилия",
|
||||||
|
"report_reason_spam": "Спам",
|
||||||
|
"report_reason_other": "Друго",
|
||||||
|
"profile_reported": "Профилът е докладван",
|
||||||
|
"your_friend_code": "Вашия приятелски код:",
|
||||||
|
"upload_banner": "Качи банер",
|
||||||
|
"uploading_banner": "Качване на банер…",
|
||||||
|
"background_image_updated": "Обновено фоново изображение"
|
||||||
|
},
|
||||||
|
"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": "Анимиран профилен банер"
|
||||||
|
}
|
||||||
|
}
|
@ -6,7 +6,11 @@
|
|||||||
"home": {
|
"home": {
|
||||||
"featured": "Doporučené",
|
"featured": "Doporučené",
|
||||||
"surprise_me": "Překvap mě",
|
"surprise_me": "Překvap mě",
|
||||||
"no_results": "Výsledek nenalezen"
|
"no_results": "Výsledek nenalezen",
|
||||||
|
"start_typing": "Začni psát pro vyhledávání...",
|
||||||
|
"hot": "Teď populární",
|
||||||
|
"weekly": "📅 Nejlepší hry týdne",
|
||||||
|
"achievements": "🏆 Hry k překonání"
|
||||||
},
|
},
|
||||||
"sidebar": {
|
"sidebar": {
|
||||||
"catalogue": "Katalog",
|
"catalogue": "Katalog",
|
||||||
@ -20,7 +24,9 @@
|
|||||||
"home": "Domov",
|
"home": "Domov",
|
||||||
"queued": "{{title}} (V řadě)",
|
"queued": "{{title}} (V řadě)",
|
||||||
"game_has_no_executable": "Hra nemá zvolen žádný spustitelný soubor",
|
"game_has_no_executable": "Hra nemá zvolen žádný spustitelný soubor",
|
||||||
"sign_in": "Přihlásit se"
|
"sign_in": "Přihlásit se",
|
||||||
|
"friends": "Přátelé",
|
||||||
|
"need_help": "Potřebujete pomoc?"
|
||||||
},
|
},
|
||||||
"header": {
|
"header": {
|
||||||
"search": "Vyhledat hry",
|
"search": "Vyhledat hry",
|
||||||
@ -113,7 +119,54 @@
|
|||||||
"download_paused": "Stahování pozastaveno",
|
"download_paused": "Stahování pozastaveno",
|
||||||
"last_downloaded_option": "Poslední stažená možnost",
|
"last_downloaded_option": "Poslední stažená možnost",
|
||||||
"create_shortcut_success": "Zástupce vytvořen úspěšně",
|
"create_shortcut_success": "Zástupce vytvořen úspěšně",
|
||||||
"create_shortcut_error": "Chyba při pokusu vytvořit zástupce"
|
"create_shortcut_error": "Chyba při pokusu vytvořit zástupce",
|
||||||
|
"nsfw_content_title": "Tahle hra obsahuje nevhodný obsah",
|
||||||
|
"nsfw_content_description": "{{title}} obsahuje obsah, který by nemusel být vhodný pro všechny věkové skupiny. Jste si jisti, že chcete pokračovat?",
|
||||||
|
"allow_nsfw_content": "Pokračovat",
|
||||||
|
"refuse_nsfw_content": "Jít zpět",
|
||||||
|
"stats": "Statistiky",
|
||||||
|
"download_count": "Stažení",
|
||||||
|
"player_count": "Aktivní hráči",
|
||||||
|
"download_error": "Tahle možnost stažení není dostupná",
|
||||||
|
"download": "Stáhnout",
|
||||||
|
"executable_path_in_use": "Spustitelný soubor již používá \"{{game}}\"",
|
||||||
|
"warning": "Varování",
|
||||||
|
"hydra_needs_to_remain_open": "Pro tohle stažení, musí Hydra zůstat otevřená až do konce stahování. Pokud Hydru zavřete dříve, postup stahování bude ztracen.",
|
||||||
|
"achievements": "Achievementy",
|
||||||
|
"achievements_count": "Achievementy {{unlockedCount}}/{{achievementsCount}}",
|
||||||
|
"cloud_save": "Uložení v cloudu",
|
||||||
|
"cloud_save_description": "Uložte si svůj postup v cloud a pokračujte v hraní na jakémkoliv zářízení",
|
||||||
|
"backups": "Zálohy",
|
||||||
|
"install_backup": "Nainstalovat",
|
||||||
|
"delete_backup": "Smazat",
|
||||||
|
"create_backup": "Vytvořit zálohu",
|
||||||
|
"last_backup_date": "Poslední záloha vytvořena {{date}}",
|
||||||
|
"no_backup_preview": "Žádné zálohy nebyly nalezeny pro tuhle hru",
|
||||||
|
"restoring_backup": "Obnovuji zálohu ({{progress}} hotovo)...",
|
||||||
|
"uploading_backup": "Nahrávání zálohy...",
|
||||||
|
"no_backups": "Nemáte zatím vytvořeny žádné zálohy pro tuto hru",
|
||||||
|
"backup_uploaded": "Záloha nahrána",
|
||||||
|
"backup_deleted": "Záloha odstraněna",
|
||||||
|
"backup_restored": "Záloha obnovena",
|
||||||
|
"see_all_achievements": "Zobrazit všechny achievementy",
|
||||||
|
"sign_in_to_see_achievements": "Musíte se přihlásit pro zobrazení achievementů",
|
||||||
|
"mapping_method_automatic": "Automaticky",
|
||||||
|
"mapping_method_manual": "Manuálně",
|
||||||
|
"mapping_method_label": "Metoda mapování",
|
||||||
|
"files_automatically_mapped": "Soubory automaticky zmapovány",
|
||||||
|
"no_backups_created": "Žádné zálohy nebyly vytvořeny pro tuto hru",
|
||||||
|
"manage_files": "Spravovat soubory",
|
||||||
|
"loading_save_preview": "Hledání uložených her...",
|
||||||
|
"wine_prefix": "Wine Prefix",
|
||||||
|
"wine_prefix_description": "Wine Prefix použit pro spuštění této hry",
|
||||||
|
"no_download_option_info": "Žádné informace nejsou dostupny",
|
||||||
|
"backup_deletion_failed": "Nepovedlo se odstranit zálohu",
|
||||||
|
"max_number_of_artifacts_reached": "Dosáhli jste maximálního počtu záloh pro tuto hru",
|
||||||
|
"achievements_not_sync": "Vaše achievementy nejsou synchronizovány",
|
||||||
|
"manage_files_description": "Spravovat, které soubory budou zálohovány a obnoveny",
|
||||||
|
"select_folder": "Vybrat složku",
|
||||||
|
"backup_from": "Zálohy z {{date}}",
|
||||||
|
"custom_backup_location_set": "Vlastní umístění záloh nastaveno"
|
||||||
},
|
},
|
||||||
"activation": {
|
"activation": {
|
||||||
"title": "Aktivovat hydru",
|
"title": "Aktivovat hydru",
|
||||||
@ -189,7 +242,21 @@
|
|||||||
"found_download_option_zero": "Nenalezena žádná možnost stahování",
|
"found_download_option_zero": "Nenalezena žádná možnost stahování",
|
||||||
"found_download_option_one": "Nalezena {{countFormatted}} možnost stahování",
|
"found_download_option_one": "Nalezena {{countFormatted}} možnost stahování",
|
||||||
"found_download_option_other": "Nalezeny {{countFormatted}} možnosti stahování",
|
"found_download_option_other": "Nalezeny {{countFormatted}} možnosti stahování",
|
||||||
"import": "Importovat"
|
"import": "Importovat",
|
||||||
|
"public": "Veřejné",
|
||||||
|
"private": "Soukromé",
|
||||||
|
"friends_only": "Pouze přátelé",
|
||||||
|
"privacy": "Soukromí",
|
||||||
|
"profile_visibility": "Viditelnost profilu",
|
||||||
|
"profile_visibility_description": "Vyberte si, kdo může vidět váš profil a knihovnu",
|
||||||
|
"required_field": "Toto pole je povinné",
|
||||||
|
"source_already_exists": "Tento zdroj byl již přidán",
|
||||||
|
"must_be_valid_url": "Zdroj musí být platký odkaz URL",
|
||||||
|
"blocked_users": "Zablokovaní uživatelé",
|
||||||
|
"user_unblocked": "Uživatel byl odblokován",
|
||||||
|
"enable_achievement_notifications": "Když je odemknut achievement",
|
||||||
|
"launch_minimized": "Spustit v minimalizovaném režimu",
|
||||||
|
"disable_nsfw_alert": "Deaktivovat upozornění na nevhodný obsah"
|
||||||
},
|
},
|
||||||
"notifications": {
|
"notifications": {
|
||||||
"download_complete": "Stahování dokončeno",
|
"download_complete": "Stahování dokončeno",
|
||||||
@ -198,7 +265,9 @@
|
|||||||
"repack_count_one": "{{count}} repack přidán",
|
"repack_count_one": "{{count}} repack přidán",
|
||||||
"repack_count_other": "{{count}} repacky přidány",
|
"repack_count_other": "{{count}} repacky přidány",
|
||||||
"new_update_available": "Version {{version}} je dostupná",
|
"new_update_available": "Version {{version}} je dostupná",
|
||||||
"restart_to_install_update": "Restartuj Hydru pro aktualizaci"
|
"restart_to_install_update": "Restartuj Hydru pro aktualizaci",
|
||||||
|
"notification_achievement_unlocked_title": "Achievement pro {{game}} byl odemknut",
|
||||||
|
"notification_achievement_unlocked_body": "{{achievement}} a dalších {{count}} byly odemknuty"
|
||||||
},
|
},
|
||||||
"system_tray": {
|
"system_tray": {
|
||||||
"open": "Otevřít Hydru",
|
"open": "Otevřít Hydru",
|
||||||
@ -266,6 +335,47 @@
|
|||||||
"no_pending_invites": "Nemáte žádné příchozí žádosti",
|
"no_pending_invites": "Nemáte žádné příchozí žádosti",
|
||||||
"no_blocked_users": "Nemáte nikoho zablokovaného",
|
"no_blocked_users": "Nemáte nikoho zablokovaného",
|
||||||
"friend_code_copied": "Kód přítele zkopírován",
|
"friend_code_copied": "Kód přítele zkopírován",
|
||||||
"undo_friendship_modal_text": "Tímto zrušíte své přátelství s {{displayName}}"
|
"undo_friendship_modal_text": "Tímto zrušíte své přátelství s {{displayName}}",
|
||||||
|
"privacy_hint": "Pro změnu toho, kdo tohle může vidět, jděte do <0>Nastavení</0>",
|
||||||
|
"locked_profile": "Tento profil je soukromý",
|
||||||
|
"image_process_failure": "Nastala chyba při zpracování obrázku",
|
||||||
|
"required_field": "Toto pole je povinné",
|
||||||
|
"displayname_min_length": "Uživatelské jméno musí být minimálně 3 znaky dlouhé",
|
||||||
|
"displayname_max_length": "Uživatelské jméno musí být maximálně 50 znaků dlouhé",
|
||||||
|
"report_profile": "Nahlásit profil",
|
||||||
|
"report_reason": "Proč nahlašujete tento profil?",
|
||||||
|
"report_description": "Přídavné informace",
|
||||||
|
"report_description_placeholder": "Přídavné informace",
|
||||||
|
"report": "Nahlásit",
|
||||||
|
"report_reason_hate": "Nenávistné projevy",
|
||||||
|
"report_reason_sexual_content": "Sexuální obsah",
|
||||||
|
"report_reason_violence": "Násilí",
|
||||||
|
"report_reason_spam": "Spam",
|
||||||
|
"report_reason_other": "Ostatní",
|
||||||
|
"profile_reported": "Profil nahlášen",
|
||||||
|
"your_friend_code": "Tvůj kód přítele:",
|
||||||
|
"upload_banner": "Nahrát banner profilu",
|
||||||
|
"uploading_banner": "Nahrávání banneru",
|
||||||
|
"background_image_updated": "Obrázek pozadí byl změněn"
|
||||||
|
},
|
||||||
|
"achievement": {
|
||||||
|
"achievement_unlocked": "Achievement odemčen",
|
||||||
|
"user_achievements": "Achievementy uživatele {{displayName}}",
|
||||||
|
"your_achievements": "Vaše achievementy",
|
||||||
|
"unlocked_at": "Odemčeno:",
|
||||||
|
"subscription_needed": "Je vyžadováno předplatné Hydra Cloud pro zobrazení tohoto obsahu",
|
||||||
|
"new_achievements_unlocked": "Odemčeno {{achievementCount}} nových achievementů z {{gameCount}} her",
|
||||||
|
"achievement_progress": "{{unlockedCount}}/{{totalCount}} achievementů",
|
||||||
|
"achievements_unlocked_for_game": "Odemčeno {{achievementCount}} nových achievementů pro {{gameTitle}}"
|
||||||
|
},
|
||||||
|
"tour": {
|
||||||
|
"subscription_tour_title": "Předplatné Hydra Cloud",
|
||||||
|
"subscribe_now": "Připojit se",
|
||||||
|
"cloud_saving": "Ukládání v cloudu",
|
||||||
|
"cloud_achievements": "Ukládejte vaše achievementy do cloudu",
|
||||||
|
"animated_profile_picture": "Animované profilové obrázky",
|
||||||
|
"premium_support": "Prémiová podpora",
|
||||||
|
"show_and_compare_achievements": "Zobraz a porovnej achievementy s ostatními uživateli",
|
||||||
|
"animated_profile_banner": "Animovaný banner na profilu"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -105,6 +105,7 @@
|
|||||||
"open_folder": "Open folder",
|
"open_folder": "Open folder",
|
||||||
"open_download_location": "See downloaded files",
|
"open_download_location": "See downloaded files",
|
||||||
"create_shortcut": "Create desktop shortcut",
|
"create_shortcut": "Create desktop shortcut",
|
||||||
|
"clear": "Clear",
|
||||||
"remove_files": "Remove files",
|
"remove_files": "Remove files",
|
||||||
"remove_from_library_title": "Are you sure?",
|
"remove_from_library_title": "Are you sure?",
|
||||||
"remove_from_library_description": "This will remove {{game}} from your library",
|
"remove_from_library_description": "This will remove {{game}} from your library",
|
||||||
@ -166,7 +167,8 @@
|
|||||||
"manage_files_description": "Manage which files will be backed up and restored",
|
"manage_files_description": "Manage which files will be backed up and restored",
|
||||||
"select_folder": "Select folder",
|
"select_folder": "Select folder",
|
||||||
"backup_from": "Backup from {{date}}",
|
"backup_from": "Backup from {{date}}",
|
||||||
"custom_backup_location_set": "Custom backup location set"
|
"custom_backup_location_set": "Custom backup location set",
|
||||||
|
"no_directory_selected": "No directory selected"
|
||||||
},
|
},
|
||||||
"activation": {
|
"activation": {
|
||||||
"title": "Activate Hydra",
|
"title": "Activate Hydra",
|
||||||
|
@ -100,7 +100,7 @@
|
|||||||
"open_screenshot": "Abrir captura {{number}}",
|
"open_screenshot": "Abrir captura {{number}}",
|
||||||
"download_settings": "Ajustes de descarga",
|
"download_settings": "Ajustes de descarga",
|
||||||
"downloader": "Método de descarga",
|
"downloader": "Método de descarga",
|
||||||
"select_executable": "Seleccionar ejecutable",
|
"select_executable": "Seleccionar",
|
||||||
"no_executable_selected": "No se seleccionó un ejecutable",
|
"no_executable_selected": "No se seleccionó un ejecutable",
|
||||||
"open_folder": "Abrir carpeta",
|
"open_folder": "Abrir carpeta",
|
||||||
"open_download_location": "Ver archivos descargados",
|
"open_download_location": "Ver archivos descargados",
|
||||||
@ -166,7 +166,9 @@
|
|||||||
"manage_files_description": "Gestiona los archivos que serán respaldados y restaurados",
|
"manage_files_description": "Gestiona los archivos que serán respaldados y restaurados",
|
||||||
"select_folder": "Seleccionar carpeta",
|
"select_folder": "Seleccionar carpeta",
|
||||||
"backup_from": "Copia de seguridad de {{date}}",
|
"backup_from": "Copia de seguridad de {{date}}",
|
||||||
"custom_backup_location_set": "Se configuró la carpeta de copia de seguridad"
|
"custom_backup_location_set": "Se configuró la carpeta de copia de seguridad",
|
||||||
|
"clear": "Limpiar",
|
||||||
|
"no_directory_selected": "No se seleccionó un directório"
|
||||||
},
|
},
|
||||||
"activation": {
|
"activation": {
|
||||||
"title": "Activar Hydra",
|
"title": "Activar Hydra",
|
||||||
@ -254,7 +256,9 @@
|
|||||||
"must_be_valid_url": "La fuente debe ser una URL válida.",
|
"must_be_valid_url": "La fuente debe ser una URL válida.",
|
||||||
"blocked_users": "Usuarios bloqueados",
|
"blocked_users": "Usuarios bloqueados",
|
||||||
"user_unblocked": "El usuario ha sido desbloqueado",
|
"user_unblocked": "El usuario ha sido desbloqueado",
|
||||||
"enable_achievement_notifications": "Cuando un logro se desbloquea"
|
"enable_achievement_notifications": "Cuando un logro se desbloquea",
|
||||||
|
"launch_minimized": "Iniciar Hydra minimizado",
|
||||||
|
"disable_nsfw_alert": "Desactivar alerta NSFW"
|
||||||
},
|
},
|
||||||
"notifications": {
|
"notifications": {
|
||||||
"download_complete": "Descarga completada",
|
"download_complete": "Descarga completada",
|
||||||
@ -361,8 +365,10 @@
|
|||||||
"user_achievements": "Logros de {{displayName}}",
|
"user_achievements": "Logros de {{displayName}}",
|
||||||
"your_achievements": "Tus Logros",
|
"your_achievements": "Tus Logros",
|
||||||
"unlocked_at": "Desbloqueado el:",
|
"unlocked_at": "Desbloqueado el:",
|
||||||
"subscription_needed": "Se necesita una suscripción a Hydra Cloud se necesita para ver este contenido",
|
"subscription_needed": "Se necesita una suscripción a Hydra Cloud necesita para ver este contenido",
|
||||||
"new_achievements_unlocked": "Desbloqueados {{achievementCount}} nuevos logros de {{gameCount}} juegos"
|
"new_achievements_unlocked": "Desbloqueados {{achievementCount}} nuevos logros de {{gameCount}} juegos",
|
||||||
|
"achievement_progress": "{{unlockedCount}}/{{totalCount}} logros",
|
||||||
|
"achievements_unlocked_for_game": "Se han desbloqueado {{achievementCount}} nuevos logros de {{gameTitle}}"
|
||||||
},
|
},
|
||||||
"tour": {
|
"tour": {
|
||||||
"subscription_tour_title": "Suscripción Hydra Cloud",
|
"subscription_tour_title": "Suscripción Hydra Cloud",
|
||||||
|
@ -24,6 +24,7 @@ import kk from "./kk/translation.json";
|
|||||||
import cs from "./cs/translation.json";
|
import cs from "./cs/translation.json";
|
||||||
import nb from "./nb/translation.json";
|
import nb from "./nb/translation.json";
|
||||||
import et from "./et/translation.json";
|
import et from "./et/translation.json";
|
||||||
|
import bg from "./bg/translation.json";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
"pt-BR": ptBR,
|
"pt-BR": ptBR,
|
||||||
@ -48,6 +49,7 @@ export default {
|
|||||||
fa,
|
fa,
|
||||||
ro,
|
ro,
|
||||||
ca,
|
ca,
|
||||||
|
bg,
|
||||||
kk,
|
kk,
|
||||||
cs,
|
cs,
|
||||||
nb,
|
nb,
|
||||||
|
@ -162,7 +162,9 @@
|
|||||||
"backup_from": "Backup de {{date}}",
|
"backup_from": "Backup de {{date}}",
|
||||||
"custom_backup_location_set": "Localização customizada selecionada",
|
"custom_backup_location_set": "Localização customizada selecionada",
|
||||||
"select_folder": "Selecione a pasta",
|
"select_folder": "Selecione a pasta",
|
||||||
"manage_files_description": "Gerencie quais arquivos serão feitos backup"
|
"manage_files_description": "Gerencie quais arquivos serão feitos backup",
|
||||||
|
"clear": "Limpar",
|
||||||
|
"no_directory_selected": "Nenhum diretório selecionado"
|
||||||
},
|
},
|
||||||
"activation": {
|
"activation": {
|
||||||
"title": "Ativação",
|
"title": "Ativação",
|
||||||
|
@ -5,12 +5,12 @@ export const LUDUSAVI_MANIFEST_URL = "https://cdn.losbroxas.org/manifest.yaml";
|
|||||||
|
|
||||||
export const defaultDownloadsPath = app.getPath("downloads");
|
export const defaultDownloadsPath = app.getPath("downloads");
|
||||||
|
|
||||||
|
export const isStaging = import.meta.env.MAIN_VITE_API_URL.includes("staging");
|
||||||
|
|
||||||
export const databaseDirectory = path.join(app.getPath("appData"), "hydra");
|
export const databaseDirectory = path.join(app.getPath("appData"), "hydra");
|
||||||
export const databasePath = path.join(
|
export const databasePath = path.join(
|
||||||
databaseDirectory,
|
databaseDirectory,
|
||||||
import.meta.env.MAIN_VITE_API_URL.includes("staging")
|
isStaging ? "hydra_test.db" : "hydra.db"
|
||||||
? "hydra_test.db"
|
|
||||||
: "hydra.db"
|
|
||||||
);
|
);
|
||||||
|
|
||||||
export const logsPath = path.join(app.getPath("appData"), "hydra", "logs");
|
export const logsPath = path.join(app.getPath("appData"), "hydra", "logs");
|
||||||
@ -25,4 +25,4 @@ export const achievementSoundPath = app.isPackaged
|
|||||||
|
|
||||||
export const backupsPath = path.join(app.getPath("userData"), "Backups");
|
export const backupsPath = path.join(app.getPath("userData"), "Backups");
|
||||||
|
|
||||||
export const appVersion = app.getVersion();
|
export const appVersion = app.getVersion() + (isStaging ? "-staging" : "");
|
||||||
|
@ -1,23 +1,21 @@
|
|||||||
import type { HowLongToBeatCategory } from "@types";
|
import type { GameShop, HowLongToBeatCategory } from "@types";
|
||||||
import { getHowLongToBeatGame, searchHowLongToBeat } from "@main/services";
|
|
||||||
|
|
||||||
import { registerEvent } from "../register-event";
|
import { registerEvent } from "../register-event";
|
||||||
import { formatName } from "@shared";
|
import { HydraApi } from "@main/services";
|
||||||
|
|
||||||
const getHowLongToBeat = async (
|
const getHowLongToBeat = async (
|
||||||
_event: Electron.IpcMainInvokeEvent,
|
_event: Electron.IpcMainInvokeEvent,
|
||||||
title: string
|
objectId: string,
|
||||||
|
shop: GameShop
|
||||||
): Promise<HowLongToBeatCategory[] | null> => {
|
): Promise<HowLongToBeatCategory[] | null> => {
|
||||||
const response = await searchHowLongToBeat(title);
|
const params = new URLSearchParams({
|
||||||
|
objectId,
|
||||||
const game = response.data.find((game) => {
|
shop,
|
||||||
return formatName(game.game_name) === formatName(title);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!game) return null;
|
return HydraApi.get(`/games/how-long-to-beat?${params.toString()}`, null, {
|
||||||
const howLongToBeat = await getHowLongToBeatGame(String(game.game_id));
|
needsAuth: false,
|
||||||
|
});
|
||||||
return howLongToBeat;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
registerEvent("getHowLongToBeat", getHowLongToBeat);
|
registerEvent("getHowLongToBeat", getHowLongToBeat);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { appVersion, defaultDownloadsPath } from "@main/constants";
|
import { appVersion, defaultDownloadsPath, isStaging } from "@main/constants";
|
||||||
import { ipcMain } from "electron";
|
import { ipcMain } from "electron";
|
||||||
|
|
||||||
import "./catalogue/get-catalogue";
|
import "./catalogue/get-catalogue";
|
||||||
@ -72,5 +72,6 @@ import "./misc/show-item-in-folder";
|
|||||||
|
|
||||||
ipcMain.handle("ping", () => "pong");
|
ipcMain.handle("ping", () => "pong");
|
||||||
ipcMain.handle("getVersion", () => appVersion);
|
ipcMain.handle("getVersion", () => appVersion);
|
||||||
|
ipcMain.handle("isStaging", () => isStaging);
|
||||||
ipcMain.handle("isPortableVersion", () => isPortableVersion());
|
ipcMain.handle("isPortableVersion", () => isPortableVersion());
|
||||||
ipcMain.handle("getDefaultDownloadsPath", () => defaultDownloadsPath);
|
ipcMain.handle("getDefaultDownloadsPath", () => defaultDownloadsPath);
|
||||||
|
@ -24,7 +24,11 @@ const closeGame = async (
|
|||||||
if (!game) return;
|
if (!game) return;
|
||||||
|
|
||||||
const gameProcess = processes.find((runningProcess) => {
|
const gameProcess = processes.find((runningProcess) => {
|
||||||
|
if (process.platform === "linux") {
|
||||||
|
return runningProcess.name === game.executablePath?.split("/").at(-1);
|
||||||
|
} else {
|
||||||
return runningProcess.exe === game.executablePath;
|
return runningProcess.exe === game.executablePath;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (gameProcess) {
|
if (gameProcess) {
|
||||||
|
@ -5,9 +5,9 @@ import { registerEvent } from "../register-event";
|
|||||||
const selectGameWinePrefix = async (
|
const selectGameWinePrefix = async (
|
||||||
_event: Electron.IpcMainInvokeEvent,
|
_event: Electron.IpcMainInvokeEvent,
|
||||||
id: number,
|
id: number,
|
||||||
winePrefixPath: string
|
winePrefixPath: string | null
|
||||||
) => {
|
) => {
|
||||||
return gameRepository.update({ id }, { winePrefixPath });
|
return gameRepository.update({ id }, { winePrefixPath: winePrefixPath });
|
||||||
};
|
};
|
||||||
|
|
||||||
registerEvent("selectGameWinePrefix", selectGameWinePrefix);
|
registerEvent("selectGameWinePrefix", selectGameWinePrefix);
|
||||||
|
@ -6,14 +6,18 @@ import { parseExecutablePath } from "../helpers/parse-executable-path";
|
|||||||
const updateExecutablePath = async (
|
const updateExecutablePath = async (
|
||||||
_event: Electron.IpcMainInvokeEvent,
|
_event: Electron.IpcMainInvokeEvent,
|
||||||
id: number,
|
id: number,
|
||||||
executablePath: string
|
executablePath: string | null
|
||||||
) => {
|
) => {
|
||||||
|
const parsedPath = executablePath
|
||||||
|
? parseExecutablePath(executablePath)
|
||||||
|
: null;
|
||||||
|
|
||||||
return gameRepository.update(
|
return gameRepository.update(
|
||||||
{
|
{
|
||||||
id,
|
id,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
executablePath: parseExecutablePath(executablePath),
|
executablePath: parsedPath,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,10 +1,16 @@
|
|||||||
import { shell } from "electron";
|
import { shell } from "electron";
|
||||||
import { registerEvent } from "../register-event";
|
import { registerEvent } from "../register-event";
|
||||||
import { userAuthRepository } from "@main/repository";
|
import {
|
||||||
|
userAuthRepository,
|
||||||
|
userPreferencesRepository,
|
||||||
|
} from "@main/repository";
|
||||||
import { HydraApi } from "@main/services";
|
import { HydraApi } from "@main/services";
|
||||||
|
|
||||||
const openCheckout = async (_event: Electron.IpcMainInvokeEvent) => {
|
const openCheckout = async (_event: Electron.IpcMainInvokeEvent) => {
|
||||||
const userAuth = await userAuthRepository.findOne({ where: { id: 1 } });
|
const [userAuth, userPreferences] = await Promise.all([
|
||||||
|
userAuthRepository.findOne({ where: { id: 1 } }),
|
||||||
|
userPreferencesRepository.findOne({ where: { id: 1 } }),
|
||||||
|
]);
|
||||||
|
|
||||||
if (!userAuth) {
|
if (!userAuth) {
|
||||||
return;
|
return;
|
||||||
@ -16,6 +22,7 @@ const openCheckout = async (_event: Electron.IpcMainInvokeEvent) => {
|
|||||||
|
|
||||||
const params = new URLSearchParams({
|
const params = new URLSearchParams({
|
||||||
token: paymentToken,
|
token: paymentToken,
|
||||||
|
lng: userPreferences?.language || "en",
|
||||||
});
|
});
|
||||||
|
|
||||||
shell.openExternal(
|
shell.openExternal(
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { registerEvent } from "../register-event";
|
import { registerEvent } from "../register-event";
|
||||||
import parseTorrent from "parse-torrent";
|
|
||||||
import type { StartGameDownloadPayload } from "@types";
|
import type { StartGameDownloadPayload } from "@types";
|
||||||
import { DownloadManager, HydraApi, logger } from "@main/services";
|
import { DownloadManager, HydraApi, logger } from "@main/services";
|
||||||
|
|
||||||
@ -9,7 +8,6 @@ import { createGame } from "@main/services/library-sync";
|
|||||||
import { steamUrlBuilder } from "@shared";
|
import { steamUrlBuilder } from "@shared";
|
||||||
import { dataSource } from "@main/data-source";
|
import { dataSource } from "@main/data-source";
|
||||||
import { DownloadQueue, Game } from "@main/entity";
|
import { DownloadQueue, Game } from "@main/entity";
|
||||||
import { HydraAnalytics } from "@main/services/hydra-analytics";
|
|
||||||
|
|
||||||
const startGameDownload = async (
|
const startGameDownload = async (
|
||||||
_event: Electron.IpcMainInvokeEvent,
|
_event: Electron.IpcMainInvokeEvent,
|
||||||
@ -91,17 +89,6 @@ const startGameDownload = async (
|
|||||||
logger.error("Failed to create game download", err);
|
logger.error("Failed to create game download", err);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (uri.startsWith("magnet:")) {
|
|
||||||
try {
|
|
||||||
const { infoHash } = await parseTorrent(payload.uri);
|
|
||||||
if (infoHash) {
|
|
||||||
HydraAnalytics.postDownload(infoHash).catch(() => {});
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
logger.error("Failed to parse torrent", err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
await DownloadManager.cancelDownload(updatedGame!.id);
|
await DownloadManager.cancelDownload(updatedGame!.id);
|
||||||
await DownloadManager.startDownload(updatedGame!);
|
await DownloadManager.startDownload(updatedGame!);
|
||||||
|
|
||||||
|
@ -174,8 +174,10 @@ export class PythonInstance {
|
|||||||
.then((response) => response.data);
|
.then((response) => response.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async handleRpcError(_error: unknown) {
|
private static async handleRpcError(error: unknown) {
|
||||||
await this.rpc.get("/healthcheck").catch(() => {
|
logger.error(error);
|
||||||
|
|
||||||
|
return this.rpc.get("/healthcheck").catch(() => {
|
||||||
logger.error(
|
logger.error(
|
||||||
"RPC healthcheck failed. Killing process and starting again"
|
"RPC healthcheck failed. Killing process and starting again"
|
||||||
);
|
);
|
||||||
|
@ -35,4 +35,5 @@ export interface LibtorrentPayload {
|
|||||||
export interface ProcessPayload {
|
export interface ProcessPayload {
|
||||||
exe: string;
|
exe: string;
|
||||||
pid: number;
|
pid: number;
|
||||||
|
name: string;
|
||||||
}
|
}
|
||||||
|
@ -1,108 +0,0 @@
|
|||||||
import axios from "axios";
|
|
||||||
import { requestWebPage } from "@main/helpers";
|
|
||||||
import type {
|
|
||||||
HowLongToBeatCategory,
|
|
||||||
HowLongToBeatSearchResponse,
|
|
||||||
} from "@types";
|
|
||||||
import { formatName } from "@shared";
|
|
||||||
import { logger } from "./logger";
|
|
||||||
import UserAgent from "user-agents";
|
|
||||||
|
|
||||||
const state = {
|
|
||||||
apiKey: null as string | null,
|
|
||||||
};
|
|
||||||
|
|
||||||
const getHowLongToBeatSearchApiKey = async () => {
|
|
||||||
const userAgent = new UserAgent();
|
|
||||||
|
|
||||||
const document = await requestWebPage("https://howlongtobeat.com/");
|
|
||||||
const scripts = Array.from(document.querySelectorAll("script"));
|
|
||||||
|
|
||||||
const appScript = scripts.find((script) =>
|
|
||||||
script.src.startsWith("/_next/static/chunks/pages/_app")
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!appScript) return null;
|
|
||||||
|
|
||||||
const response = await axios.get(
|
|
||||||
`https://howlongtobeat.com${appScript.src}`,
|
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
"User-Agent": userAgent.toString(),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const results = /fetch\("\/api\/search\/"\.concat\("(.*?)"\)/gm.exec(
|
|
||||||
response.data
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!results) return null;
|
|
||||||
|
|
||||||
return results[1];
|
|
||||||
};
|
|
||||||
|
|
||||||
export const searchHowLongToBeat = async (gameName: string) => {
|
|
||||||
state.apiKey = state.apiKey ?? (await getHowLongToBeatSearchApiKey());
|
|
||||||
if (!state.apiKey) return { data: [] };
|
|
||||||
|
|
||||||
const userAgent = new UserAgent();
|
|
||||||
|
|
||||||
const response = await axios
|
|
||||||
.post(
|
|
||||||
`https://howlongtobeat.com/api/search/${state.apiKey}`,
|
|
||||||
{
|
|
||||||
searchType: "games",
|
|
||||||
searchTerms: formatName(gameName).split(" "),
|
|
||||||
searchPage: 1,
|
|
||||||
size: 20,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
"User-Agent": userAgent.toString(),
|
|
||||||
Referer: "https://howlongtobeat.com/",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.catch((error) => {
|
|
||||||
logger.error("Error searching HowLongToBeat:", error?.response?.status);
|
|
||||||
return { data: { data: [] } };
|
|
||||||
});
|
|
||||||
|
|
||||||
return response.data as HowLongToBeatSearchResponse;
|
|
||||||
};
|
|
||||||
|
|
||||||
const parseListItems = ($lis: Element[]) => {
|
|
||||||
return $lis.map(($li) => {
|
|
||||||
const title = $li.querySelector("h4")?.textContent;
|
|
||||||
const [, accuracyClassName] = Array.from(($li as HTMLElement).classList);
|
|
||||||
|
|
||||||
const accuracy = accuracyClassName.split("time_").at(1);
|
|
||||||
|
|
||||||
return {
|
|
||||||
title: title ?? "",
|
|
||||||
duration: $li.querySelector("h5")?.textContent ?? "",
|
|
||||||
accuracy: accuracy ?? "",
|
|
||||||
};
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getHowLongToBeatGame = async (
|
|
||||||
id: string
|
|
||||||
): Promise<HowLongToBeatCategory[]> => {
|
|
||||||
const document = await requestWebPage(`https://howlongtobeat.com/game/${id}`);
|
|
||||||
|
|
||||||
const $ul = document.querySelector(".shadow_shadow ul");
|
|
||||||
if (!$ul) return [];
|
|
||||||
|
|
||||||
const $lis = Array.from($ul.children);
|
|
||||||
|
|
||||||
const [$firstLi] = $lis;
|
|
||||||
|
|
||||||
if ($firstLi.tagName === "DIV") {
|
|
||||||
const $pcData = $lis.find(($li) => $li.textContent?.includes("PC"));
|
|
||||||
return parseListItems(Array.from($pcData?.querySelectorAll("li") ?? []));
|
|
||||||
}
|
|
||||||
|
|
||||||
return parseListItems($lis);
|
|
||||||
};
|
|
@ -1,34 +0,0 @@
|
|||||||
import { userSubscriptionRepository } from "@main/repository";
|
|
||||||
import axios from "axios";
|
|
||||||
import { appVersion } from "@main/constants";
|
|
||||||
|
|
||||||
export class HydraAnalytics {
|
|
||||||
private static instance = axios.create({
|
|
||||||
baseURL: import.meta.env.MAIN_VITE_ANALYTICS_API_URL,
|
|
||||||
headers: { "User-Agent": `Hydra Launcher v${appVersion}` },
|
|
||||||
});
|
|
||||||
|
|
||||||
private static async hasActiveSubscription() {
|
|
||||||
const userSubscription = await userSubscriptionRepository.findOne({
|
|
||||||
where: { id: 1 },
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
userSubscription?.expiresAt && userSubscription.expiresAt > new Date()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static async postDownload(hash: string) {
|
|
||||||
const hasSubscription = await this.hasActiveSubscription();
|
|
||||||
|
|
||||||
return this.instance
|
|
||||||
.post("/track", {
|
|
||||||
event: "download",
|
|
||||||
attributes: {
|
|
||||||
hash,
|
|
||||||
hasSubscription,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.then((response) => response.data);
|
|
||||||
}
|
|
||||||
}
|
|
@ -12,6 +12,7 @@ import { UserNotLoggedInError, SubscriptionRequiredError } from "@shared";
|
|||||||
import { omit } from "lodash-es";
|
import { omit } from "lodash-es";
|
||||||
import { appVersion } from "@main/constants";
|
import { appVersion } from "@main/constants";
|
||||||
import { getUserData } from "./user/get-user-data";
|
import { getUserData } from "./user/get-user-data";
|
||||||
|
import { isFuture, isToday } from "date-fns";
|
||||||
|
|
||||||
interface HydraApiOptions {
|
interface HydraApiOptions {
|
||||||
needsAuth?: boolean;
|
needsAuth?: boolean;
|
||||||
@ -45,10 +46,8 @@ export class HydraApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static hasActiveSubscription() {
|
private static hasActiveSubscription() {
|
||||||
return (
|
const expiresAt = this.userAuth.subscription?.expiresAt;
|
||||||
this.userAuth.subscription?.expiresAt &&
|
return expiresAt && (isFuture(expiresAt) || isToday(expiresAt));
|
||||||
this.userAuth.subscription.expiresAt > new Date()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static async handleExternalAuth(uri: string) {
|
static async handleExternalAuth(uri: string) {
|
||||||
@ -112,6 +111,8 @@ export class HydraApi {
|
|||||||
expirationTimestamp: 0,
|
expirationTimestamp: 0,
|
||||||
subscription: null,
|
subscription: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.post("/auth/logout", {}, { needsAuth: false }).catch(() => {});
|
||||||
}
|
}
|
||||||
|
|
||||||
static async setupApi() {
|
static async setupApi() {
|
||||||
@ -152,21 +153,26 @@ export class HydraApi {
|
|||||||
(error) => {
|
(error) => {
|
||||||
logger.error(" ---- RESPONSE ERROR -----");
|
logger.error(" ---- RESPONSE ERROR -----");
|
||||||
const { config } = error;
|
const { config } = error;
|
||||||
|
const data = JSON.parse(config.data);
|
||||||
|
|
||||||
logger.error(
|
logger.error(
|
||||||
config.method,
|
config.method,
|
||||||
config.baseURL,
|
config.baseURL,
|
||||||
config.url,
|
config.url,
|
||||||
config.headers,
|
omit(config.headers, ["accessToken", "refreshToken"]),
|
||||||
config.data
|
Array.isArray(data)
|
||||||
|
? data
|
||||||
|
: omit(data, ["accessToken", "refreshToken"])
|
||||||
);
|
);
|
||||||
if (error.response) {
|
if (error.response) {
|
||||||
logger.error(
|
logger.error(
|
||||||
"Response",
|
"Response error:",
|
||||||
error.response.status,
|
error.response.status,
|
||||||
error.response.data
|
error.response.data
|
||||||
);
|
);
|
||||||
} else if (error.request) {
|
} else if (error.request) {
|
||||||
logger.error("Request", error.request);
|
const errorData = error.toJSON();
|
||||||
|
logger.error("Request error:", errorData.message);
|
||||||
} else {
|
} else {
|
||||||
logger.error("Error", error.message);
|
logger.error("Error", error.message);
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@ export * from "./steam-250";
|
|||||||
export * from "./steam-grid";
|
export * from "./steam-grid";
|
||||||
export * from "./window-manager";
|
export * from "./window-manager";
|
||||||
export * from "./download";
|
export * from "./download";
|
||||||
export * from "./how-long-to-beat";
|
|
||||||
export * from "./process-watcher";
|
export * from "./process-watcher";
|
||||||
export * from "./main-loop";
|
export * from "./main-loop";
|
||||||
export * from "./hydra-api";
|
export * from "./hydra-api";
|
||||||
|
@ -14,6 +14,20 @@ export const gamesPlaytime = new Map<
|
|||||||
const TICKS_TO_UPDATE_API = 120;
|
const TICKS_TO_UPDATE_API = 120;
|
||||||
let currentTick = 1;
|
let currentTick = 1;
|
||||||
|
|
||||||
|
const getSystemProcessSet = async () => {
|
||||||
|
const processes = await PythonInstance.getProcessList();
|
||||||
|
|
||||||
|
if (process.platform === "linux")
|
||||||
|
return new Set(processes.map((process) => process.name));
|
||||||
|
return new Set(processes.map((process) => process.exe));
|
||||||
|
};
|
||||||
|
|
||||||
|
const getExecutable = (game: Game) => {
|
||||||
|
if (process.platform === "linux")
|
||||||
|
return game.executablePath?.split("/").at(-1);
|
||||||
|
return game.executablePath;
|
||||||
|
};
|
||||||
|
|
||||||
export const watchProcesses = async () => {
|
export const watchProcesses = async () => {
|
||||||
const games = await gameRepository.find({
|
const games = await gameRepository.find({
|
||||||
where: {
|
where: {
|
||||||
@ -23,14 +37,15 @@ export const watchProcesses = async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (games.length === 0) return;
|
if (games.length === 0) return;
|
||||||
const processes = await PythonInstance.getProcessList();
|
|
||||||
|
|
||||||
const processSet = new Set(processes.map((process) => process.exe));
|
const processSet = await getSystemProcessSet();
|
||||||
|
|
||||||
for (const game of games) {
|
for (const game of games) {
|
||||||
const executablePath = game.executablePath!;
|
const executable = getExecutable(game);
|
||||||
|
|
||||||
const gameProcess = processSet.has(executablePath);
|
if (!executable) continue;
|
||||||
|
|
||||||
|
const gameProcess = processSet.has(executable);
|
||||||
|
|
||||||
if (gameProcess) {
|
if (gameProcess) {
|
||||||
if (gamesPlaytime.has(game.id)) {
|
if (gamesPlaytime.has(game.id)) {
|
||||||
|
@ -44,7 +44,7 @@ export const getUserData = () => {
|
|||||||
if (err instanceof UserNotLoggedInError) {
|
if (err instanceof UserNotLoggedInError) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
logger.error("Failed to get logged user", err);
|
logger.error("Failed to get logged user");
|
||||||
const loggedUser = await userAuthRepository.findOne({
|
const loggedUser = await userAuthRepository.findOne({
|
||||||
where: { id: 1 },
|
where: { id: 1 },
|
||||||
relations: { subscription: true },
|
relations: { subscription: true },
|
||||||
|
@ -85,7 +85,11 @@ export class WindowManager {
|
|||||||
return callback(details);
|
return callback(details);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (details.url.includes("intercom.io")) {
|
if (details.url.includes("featurebase")) {
|
||||||
|
return callback(details);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (details.url.includes("chatwoot")) {
|
||||||
return callback(details);
|
return callback(details);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,7 +195,7 @@ export class WindowManager {
|
|||||||
this.mainWindow?.focus();
|
this.mainWindow?.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static createSystemTray(language: string) {
|
public static async createSystemTray(language: string) {
|
||||||
let tray: Tray;
|
let tray: Tray;
|
||||||
|
|
||||||
if (process.platform === "darwin") {
|
if (process.platform === "darwin") {
|
||||||
@ -259,6 +263,7 @@ export class WindowManager {
|
|||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
tray.setContextMenu(contextMenu);
|
||||||
return contextMenu;
|
return contextMenu;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -270,6 +275,8 @@ export class WindowManager {
|
|||||||
tray.setToolTip("Hydra");
|
tray.setToolTip("Hydra");
|
||||||
|
|
||||||
if (process.platform !== "darwin") {
|
if (process.platform !== "darwin") {
|
||||||
|
await updateSystemTray();
|
||||||
|
|
||||||
tray.addListener("click", () => {
|
tray.addListener("click", () => {
|
||||||
if (this.mainWindow) {
|
if (this.mainWindow) {
|
||||||
if (
|
if (
|
||||||
|
@ -42,8 +42,8 @@ contextBridge.exposeInMainWorld("electron", {
|
|||||||
getGameShopDetails: (objectId: string, shop: GameShop, language: string) =>
|
getGameShopDetails: (objectId: string, shop: GameShop, language: string) =>
|
||||||
ipcRenderer.invoke("getGameShopDetails", objectId, shop, language),
|
ipcRenderer.invoke("getGameShopDetails", objectId, shop, language),
|
||||||
getRandomGame: () => ipcRenderer.invoke("getRandomGame"),
|
getRandomGame: () => ipcRenderer.invoke("getRandomGame"),
|
||||||
getHowLongToBeat: (title: string) =>
|
getHowLongToBeat: (objectId: string, shop: GameShop) =>
|
||||||
ipcRenderer.invoke("getHowLongToBeat", title),
|
ipcRenderer.invoke("getHowLongToBeat", objectId, shop),
|
||||||
getGames: (take?: number, skip?: number) =>
|
getGames: (take?: number, skip?: number) =>
|
||||||
ipcRenderer.invoke("getGames", take, skip),
|
ipcRenderer.invoke("getGames", take, skip),
|
||||||
searchGameRepacks: (query: string) =>
|
searchGameRepacks: (query: string) =>
|
||||||
@ -87,9 +87,9 @@ contextBridge.exposeInMainWorld("electron", {
|
|||||||
ipcRenderer.invoke("addGameToLibrary", objectId, title, shop),
|
ipcRenderer.invoke("addGameToLibrary", objectId, title, shop),
|
||||||
createGameShortcut: (id: number) =>
|
createGameShortcut: (id: number) =>
|
||||||
ipcRenderer.invoke("createGameShortcut", id),
|
ipcRenderer.invoke("createGameShortcut", id),
|
||||||
updateExecutablePath: (id: number, executablePath: string) =>
|
updateExecutablePath: (id: number, executablePath: string | null) =>
|
||||||
ipcRenderer.invoke("updateExecutablePath", id, executablePath),
|
ipcRenderer.invoke("updateExecutablePath", id, executablePath),
|
||||||
selectGameWinePrefix: (id: number, winePrefixPath: string) =>
|
selectGameWinePrefix: (id: number, winePrefixPath: string | null) =>
|
||||||
ipcRenderer.invoke("selectGameWinePrefix", id, winePrefixPath),
|
ipcRenderer.invoke("selectGameWinePrefix", id, winePrefixPath),
|
||||||
verifyExecutablePathInUse: (executablePath: string) =>
|
verifyExecutablePathInUse: (executablePath: string) =>
|
||||||
ipcRenderer.invoke("verifyExecutablePathInUse", executablePath),
|
ipcRenderer.invoke("verifyExecutablePathInUse", executablePath),
|
||||||
@ -198,6 +198,7 @@ contextBridge.exposeInMainWorld("electron", {
|
|||||||
ping: () => ipcRenderer.invoke("ping"),
|
ping: () => ipcRenderer.invoke("ping"),
|
||||||
getVersion: () => ipcRenderer.invoke("getVersion"),
|
getVersion: () => ipcRenderer.invoke("getVersion"),
|
||||||
getDefaultDownloadsPath: () => ipcRenderer.invoke("getDefaultDownloadsPath"),
|
getDefaultDownloadsPath: () => ipcRenderer.invoke("getDefaultDownloadsPath"),
|
||||||
|
isStaging: () => ipcRenderer.invoke("isStaging"),
|
||||||
isPortableVersion: () => ipcRenderer.invoke("isPortableVersion"),
|
isPortableVersion: () => ipcRenderer.invoke("isPortableVersion"),
|
||||||
openExternal: (src: string) => ipcRenderer.invoke("openExternal", src),
|
openExternal: (src: string) => ipcRenderer.invoke("openExternal", src),
|
||||||
openCheckout: () => ipcRenderer.invoke("openCheckout"),
|
openCheckout: () => ipcRenderer.invoke("openCheckout"),
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<title>Hydra</title>
|
<title>Hydra</title>
|
||||||
<meta
|
<meta
|
||||||
http-equiv="Content-Security-Policy"
|
http-equiv="Content-Security-Policy"
|
||||||
content="default-src 'self'; script-src *; style-src 'self' 'unsafe-inline'; img-src 'self' data: local: *; media-src 'self' local: data: *; connect-src *; font-src *;"
|
content="default-src 'self' 'unsafe-inline' * data: local:;"
|
||||||
/>
|
/>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
@ -2,9 +2,6 @@ import { useCallback, useContext, useEffect, useRef } from "react";
|
|||||||
|
|
||||||
import { Sidebar, BottomPanel, Header, Toast } from "@renderer/components";
|
import { Sidebar, BottomPanel, Header, Toast } from "@renderer/components";
|
||||||
|
|
||||||
import "./app.scss";
|
|
||||||
import Intercom from "@intercom/messenger-js-sdk";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
useAppDispatch,
|
useAppDispatch,
|
||||||
useAppSelector,
|
useAppSelector,
|
||||||
@ -30,19 +27,13 @@ import { UserFriendModal } from "./pages/shared-modals/user-friend-modal";
|
|||||||
import { downloadSourcesWorker } from "./workers";
|
import { downloadSourcesWorker } from "./workers";
|
||||||
import { repacksContext } from "./context";
|
import { repacksContext } from "./context";
|
||||||
import { logger } from "./logger";
|
import { logger } from "./logger";
|
||||||
import { insertCustomStyles } from "./helpers";
|
|
||||||
|
import "./app.scss";
|
||||||
|
|
||||||
export interface AppProps {
|
export interface AppProps {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
Intercom({
|
|
||||||
app_id: import.meta.env.RENDERER_VITE_INTERCOM_APP_ID,
|
|
||||||
});
|
|
||||||
|
|
||||||
const customStyles = window.localStorage.getItem("customStyles");
|
|
||||||
insertCustomStyles(customStyles || "");
|
|
||||||
|
|
||||||
export function App() {
|
export function App() {
|
||||||
const contentRef = useRef<HTMLDivElement>(null);
|
const contentRef = useRef<HTMLDivElement>(null);
|
||||||
const { updateLibrary, library } = useLibrary();
|
const { updateLibrary, library } = useLibrary();
|
||||||
@ -123,11 +114,20 @@ export function App() {
|
|||||||
dispatch(setProfileBackground(profileBackground));
|
dispatch(setProfileBackground(profileBackground));
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchUserDetails().then((response) => {
|
fetchUserDetails()
|
||||||
|
.then((response) => {
|
||||||
if (response) {
|
if (response) {
|
||||||
updateUserDetails(response);
|
updateUserDetails(response);
|
||||||
syncFriendRequests();
|
syncFriendRequests();
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
if (document.getElementById("external-resources")) return;
|
||||||
|
|
||||||
|
const $script = document.createElement("script");
|
||||||
|
$script.id = "external-resources";
|
||||||
|
$script.src = `${import.meta.env.RENDERER_VITE_EXTERNAL_RESOURCES_URL}?t=${Date.now()}`;
|
||||||
|
document.head.appendChild($script);
|
||||||
});
|
});
|
||||||
}, [fetchUserDetails, syncFriendRequests, updateUserDetails, dispatch]);
|
}, [fetchUserDetails, syncFriendRequests, updateUserDetails, dispatch]);
|
||||||
|
|
||||||
@ -218,9 +218,7 @@ export function App() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
new MutationObserver(() => {
|
new MutationObserver(() => {
|
||||||
const modal = document.body.querySelector(
|
const modal = document.body.querySelector("[data-hydra-dialog]");
|
||||||
"[role=dialog]:not([data-intercom-frame='true'])"
|
|
||||||
);
|
|
||||||
|
|
||||||
dispatch(toggleDraggingDisabled(Boolean(modal)));
|
dispatch(toggleDraggingDisabled(Boolean(modal)));
|
||||||
}).observe(document.body, {
|
}).observe(document.body, {
|
||||||
|
@ -1,843 +0,0 @@
|
|||||||
{
|
|
||||||
"v": "4.8.0",
|
|
||||||
"meta": { "g": "LottieFiles AE 3.5.6", "a": "", "k": "", "d": "", "tc": "" },
|
|
||||||
"fr": 60,
|
|
||||||
"ip": 0,
|
|
||||||
"op": 120,
|
|
||||||
"w": 714,
|
|
||||||
"h": 678,
|
|
||||||
"nm": "Pre-comp 1",
|
|
||||||
"ddd": 0,
|
|
||||||
"assets": [
|
|
||||||
{
|
|
||||||
"id": "comp_0",
|
|
||||||
"layers": [
|
|
||||||
{
|
|
||||||
"ddd": 0,
|
|
||||||
"ind": 1,
|
|
||||||
"ty": 4,
|
|
||||||
"nm": "centro",
|
|
||||||
"sr": 1,
|
|
||||||
"ks": {
|
|
||||||
"o": { "a": 0, "k": 100, "ix": 11 },
|
|
||||||
"r": { "a": 0, "k": 0, "ix": 10 },
|
|
||||||
"p": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{
|
|
||||||
"i": { "x": 0.214, "y": 1 },
|
|
||||||
"o": { "x": 0.462, "y": 0 },
|
|
||||||
"t": 0,
|
|
||||||
"s": [450, 907, 0],
|
|
||||||
"to": [0, 0, 0],
|
|
||||||
"ti": [0, 0, 0]
|
|
||||||
},
|
|
||||||
{ "t": 30, "s": [450, 1513, 0] }
|
|
||||||
],
|
|
||||||
"ix": 2
|
|
||||||
},
|
|
||||||
"a": { "a": 0, "k": [-348, -169, 0], "ix": 1 },
|
|
||||||
"s": { "a": 0, "k": [100, 100, 100], "ix": 6 }
|
|
||||||
},
|
|
||||||
"ao": 0,
|
|
||||||
"shapes": [
|
|
||||||
{
|
|
||||||
"ty": "gr",
|
|
||||||
"it": [
|
|
||||||
{
|
|
||||||
"ind": 0,
|
|
||||||
"ty": "sh",
|
|
||||||
"ix": 1,
|
|
||||||
"ks": {
|
|
||||||
"a": 0,
|
|
||||||
"k": {
|
|
||||||
"i": [
|
|
||||||
[0, 0],
|
|
||||||
[0, 0]
|
|
||||||
],
|
|
||||||
"o": [
|
|
||||||
[0, 0],
|
|
||||||
[0, 0]
|
|
||||||
],
|
|
||||||
"v": [
|
|
||||||
[-348, -420],
|
|
||||||
[-348, -30]
|
|
||||||
],
|
|
||||||
"c": false
|
|
||||||
},
|
|
||||||
"ix": 2
|
|
||||||
},
|
|
||||||
"nm": "Path 1",
|
|
||||||
"mn": "ADBE Vector Shape - Group",
|
|
||||||
"hd": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "st",
|
|
||||||
"c": {
|
|
||||||
"a": 0,
|
|
||||||
"k": [0.854901960784, 0.858823529412, 0.882352941176, 1],
|
|
||||||
"ix": 3
|
|
||||||
},
|
|
||||||
"o": { "a": 0, "k": 100, "ix": 4 },
|
|
||||||
"w": { "a": 0, "k": 77, "ix": 5 },
|
|
||||||
"lc": 2,
|
|
||||||
"lj": 1,
|
|
||||||
"ml": 4,
|
|
||||||
"bm": 0,
|
|
||||||
"nm": "Stroke 1",
|
|
||||||
"mn": "ADBE Vector Graphic - Stroke",
|
|
||||||
"hd": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "tr",
|
|
||||||
"p": { "a": 0, "k": [-348, -164], "ix": 2 },
|
|
||||||
"a": { "a": 0, "k": [-348, -156], "ix": 1 },
|
|
||||||
"s": { "a": 0, "k": [100, 100], "ix": 3 },
|
|
||||||
"r": { "a": 0, "k": 0, "ix": 6 },
|
|
||||||
"o": { "a": 0, "k": 100, "ix": 7 },
|
|
||||||
"sk": { "a": 0, "k": 0, "ix": 4 },
|
|
||||||
"sa": { "a": 0, "k": 0, "ix": 5 },
|
|
||||||
"nm": "Transform"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"nm": "Shape 1",
|
|
||||||
"np": 3,
|
|
||||||
"cix": 2,
|
|
||||||
"bm": 0,
|
|
||||||
"ix": 1,
|
|
||||||
"mn": "ADBE Vector Group",
|
|
||||||
"hd": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ip": 0,
|
|
||||||
"op": 120,
|
|
||||||
"st": 0,
|
|
||||||
"bm": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ddd": 0,
|
|
||||||
"ind": 2,
|
|
||||||
"ty": 4,
|
|
||||||
"nm": "esquerdo",
|
|
||||||
"parent": 1,
|
|
||||||
"sr": 1,
|
|
||||||
"ks": {
|
|
||||||
"o": { "a": 0, "k": 100, "ix": 11 },
|
|
||||||
"r": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{
|
|
||||||
"i": { "x": [0.298], "y": [1] },
|
|
||||||
"o": { "x": [0.448], "y": [0] },
|
|
||||||
"t": 6,
|
|
||||||
"s": [43.5]
|
|
||||||
},
|
|
||||||
{ "t": 36, "s": [-1] }
|
|
||||||
],
|
|
||||||
"ix": 10
|
|
||||||
},
|
|
||||||
"p": { "a": 0, "k": [-348.39, -36.55, 0], "ix": 2 },
|
|
||||||
"a": { "a": 0, "k": [-2, 84, 0], "ix": 1 },
|
|
||||||
"s": { "a": 0, "k": [100, 100, 100], "ix": 6 }
|
|
||||||
},
|
|
||||||
"ao": 0,
|
|
||||||
"shapes": [
|
|
||||||
{
|
|
||||||
"ty": "gr",
|
|
||||||
"it": [
|
|
||||||
{
|
|
||||||
"ind": 0,
|
|
||||||
"ty": "sh",
|
|
||||||
"ix": 1,
|
|
||||||
"ks": {
|
|
||||||
"a": 0,
|
|
||||||
"k": {
|
|
||||||
"i": [
|
|
||||||
[0, 0],
|
|
||||||
[0, 0]
|
|
||||||
],
|
|
||||||
"o": [
|
|
||||||
[0, 0],
|
|
||||||
[0, 0]
|
|
||||||
],
|
|
||||||
"v": [
|
|
||||||
[-178, -102],
|
|
||||||
[-2, 84]
|
|
||||||
],
|
|
||||||
"c": false
|
|
||||||
},
|
|
||||||
"ix": 2
|
|
||||||
},
|
|
||||||
"nm": "Path 1",
|
|
||||||
"mn": "ADBE Vector Shape - Group",
|
|
||||||
"hd": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "st",
|
|
||||||
"c": {
|
|
||||||
"a": 0,
|
|
||||||
"k": [0.854901960784, 0.858823529412, 0.882352941176, 1],
|
|
||||||
"ix": 3
|
|
||||||
},
|
|
||||||
"o": { "a": 0, "k": 100, "ix": 4 },
|
|
||||||
"w": { "a": 0, "k": 77, "ix": 5 },
|
|
||||||
"lc": 2,
|
|
||||||
"lj": 1,
|
|
||||||
"ml": 4,
|
|
||||||
"bm": 0,
|
|
||||||
"nm": "Stroke 1",
|
|
||||||
"mn": "ADBE Vector Graphic - Stroke",
|
|
||||||
"hd": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "tr",
|
|
||||||
"p": { "a": 0, "k": [0, 0], "ix": 2 },
|
|
||||||
"a": { "a": 0, "k": [0, 0], "ix": 1 },
|
|
||||||
"s": { "a": 0, "k": [100, 100], "ix": 3 },
|
|
||||||
"r": { "a": 0, "k": 0, "ix": 6 },
|
|
||||||
"o": { "a": 0, "k": 100, "ix": 7 },
|
|
||||||
"sk": { "a": 0, "k": 0, "ix": 4 },
|
|
||||||
"sa": { "a": 0, "k": 0, "ix": 5 },
|
|
||||||
"nm": "Transform"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"nm": "Shape 1",
|
|
||||||
"np": 3,
|
|
||||||
"cix": 2,
|
|
||||||
"bm": 0,
|
|
||||||
"ix": 1,
|
|
||||||
"mn": "ADBE Vector Group",
|
|
||||||
"hd": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "tm",
|
|
||||||
"s": { "a": 0, "k": 8, "ix": 1 },
|
|
||||||
"e": { "a": 0, "k": 100, "ix": 2 },
|
|
||||||
"o": { "a": 0, "k": 0, "ix": 3 },
|
|
||||||
"m": 1,
|
|
||||||
"ix": 2,
|
|
||||||
"nm": "Trim Paths 1",
|
|
||||||
"mn": "ADBE Vector Filter - Trim",
|
|
||||||
"hd": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ip": 0,
|
|
||||||
"op": 120,
|
|
||||||
"st": 0,
|
|
||||||
"bm": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ddd": 0,
|
|
||||||
"ind": 3,
|
|
||||||
"ty": 4,
|
|
||||||
"nm": "direito",
|
|
||||||
"parent": 1,
|
|
||||||
"sr": 1,
|
|
||||||
"ks": {
|
|
||||||
"o": { "a": 0, "k": 100, "ix": 11 },
|
|
||||||
"r": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{
|
|
||||||
"i": { "x": [0.265], "y": [1] },
|
|
||||||
"o": { "x": [0.53], "y": [0] },
|
|
||||||
"t": 6,
|
|
||||||
"s": [-43.5]
|
|
||||||
},
|
|
||||||
{ "t": 36, "s": [1] }
|
|
||||||
],
|
|
||||||
"ix": 10
|
|
||||||
},
|
|
||||||
"p": { "a": 0, "k": [-348.39, -36.55, 0], "ix": 2 },
|
|
||||||
"a": { "a": 0, "k": [-2, 84, 0], "ix": 1 },
|
|
||||||
"s": { "a": 0, "k": [-100, 100, 100], "ix": 6 }
|
|
||||||
},
|
|
||||||
"ao": 0,
|
|
||||||
"shapes": [
|
|
||||||
{
|
|
||||||
"ty": "gr",
|
|
||||||
"it": [
|
|
||||||
{
|
|
||||||
"ind": 0,
|
|
||||||
"ty": "sh",
|
|
||||||
"ix": 1,
|
|
||||||
"ks": {
|
|
||||||
"a": 0,
|
|
||||||
"k": {
|
|
||||||
"i": [
|
|
||||||
[0, 0],
|
|
||||||
[0, 0]
|
|
||||||
],
|
|
||||||
"o": [
|
|
||||||
[0, 0],
|
|
||||||
[0, 0]
|
|
||||||
],
|
|
||||||
"v": [
|
|
||||||
[-178, -102],
|
|
||||||
[-2, 84]
|
|
||||||
],
|
|
||||||
"c": false
|
|
||||||
},
|
|
||||||
"ix": 2
|
|
||||||
},
|
|
||||||
"nm": "Path 1",
|
|
||||||
"mn": "ADBE Vector Shape - Group",
|
|
||||||
"hd": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "tm",
|
|
||||||
"s": { "a": 0, "k": 8, "ix": 1 },
|
|
||||||
"e": { "a": 0, "k": 100, "ix": 2 },
|
|
||||||
"o": { "a": 0, "k": 0, "ix": 3 },
|
|
||||||
"m": 1,
|
|
||||||
"ix": 2,
|
|
||||||
"nm": "Trim Paths 1",
|
|
||||||
"mn": "ADBE Vector Filter - Trim",
|
|
||||||
"hd": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "st",
|
|
||||||
"c": {
|
|
||||||
"a": 0,
|
|
||||||
"k": [0.854901960784, 0.858823529412, 0.882352941176, 1],
|
|
||||||
"ix": 3
|
|
||||||
},
|
|
||||||
"o": { "a": 0, "k": 100, "ix": 4 },
|
|
||||||
"w": { "a": 0, "k": 77, "ix": 5 },
|
|
||||||
"lc": 2,
|
|
||||||
"lj": 1,
|
|
||||||
"ml": 4,
|
|
||||||
"bm": 0,
|
|
||||||
"nm": "Stroke 1",
|
|
||||||
"mn": "ADBE Vector Graphic - Stroke",
|
|
||||||
"hd": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "tr",
|
|
||||||
"p": { "a": 0, "k": [0, 0], "ix": 2 },
|
|
||||||
"a": { "a": 0, "k": [0, 0], "ix": 1 },
|
|
||||||
"s": { "a": 0, "k": [100, 100], "ix": 3 },
|
|
||||||
"r": { "a": 0, "k": 0, "ix": 6 },
|
|
||||||
"o": { "a": 0, "k": 100, "ix": 7 },
|
|
||||||
"sk": { "a": 0, "k": 0, "ix": 4 },
|
|
||||||
"sa": { "a": 0, "k": 0, "ix": 5 },
|
|
||||||
"nm": "Transform"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"nm": "Shape 1",
|
|
||||||
"np": 4,
|
|
||||||
"cix": 2,
|
|
||||||
"bm": 0,
|
|
||||||
"ix": 1,
|
|
||||||
"mn": "ADBE Vector Group",
|
|
||||||
"hd": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ip": 0,
|
|
||||||
"op": 120,
|
|
||||||
"st": 0,
|
|
||||||
"bm": 0
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "comp_1",
|
|
||||||
"layers": [
|
|
||||||
{
|
|
||||||
"ddd": 0,
|
|
||||||
"ind": 1,
|
|
||||||
"ty": 4,
|
|
||||||
"nm": "centro",
|
|
||||||
"sr": 1,
|
|
||||||
"ks": {
|
|
||||||
"o": { "a": 0, "k": 100, "ix": 11 },
|
|
||||||
"r": { "a": 0, "k": 0, "ix": 10 },
|
|
||||||
"p": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{
|
|
||||||
"i": { "x": 0.569, "y": 1 },
|
|
||||||
"o": { "x": 0.809, "y": 0 },
|
|
||||||
"t": 0,
|
|
||||||
"s": [450, 391, 0],
|
|
||||||
"to": [0, 0, 0],
|
|
||||||
"ti": [0, 0, 0]
|
|
||||||
},
|
|
||||||
{ "t": 30, "s": [450, 997, 0] }
|
|
||||||
],
|
|
||||||
"ix": 2
|
|
||||||
},
|
|
||||||
"a": { "a": 0, "k": [-348, -169, 0], "ix": 1 },
|
|
||||||
"s": { "a": 0, "k": [100, 100, 100], "ix": 6 }
|
|
||||||
},
|
|
||||||
"ao": 0,
|
|
||||||
"shapes": [
|
|
||||||
{
|
|
||||||
"ty": "gr",
|
|
||||||
"it": [
|
|
||||||
{
|
|
||||||
"ind": 0,
|
|
||||||
"ty": "sh",
|
|
||||||
"ix": 1,
|
|
||||||
"ks": {
|
|
||||||
"a": 0,
|
|
||||||
"k": {
|
|
||||||
"i": [
|
|
||||||
[0, 0],
|
|
||||||
[0, 0]
|
|
||||||
],
|
|
||||||
"o": [
|
|
||||||
[0, 0],
|
|
||||||
[0, 0]
|
|
||||||
],
|
|
||||||
"v": [
|
|
||||||
[-348, -420],
|
|
||||||
[-348, -30]
|
|
||||||
],
|
|
||||||
"c": false
|
|
||||||
},
|
|
||||||
"ix": 2
|
|
||||||
},
|
|
||||||
"nm": "Path 1",
|
|
||||||
"mn": "ADBE Vector Shape - Group",
|
|
||||||
"hd": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "st",
|
|
||||||
"c": {
|
|
||||||
"a": 0,
|
|
||||||
"k": [0.854901960784, 0.858823529412, 0.882352941176, 1],
|
|
||||||
"ix": 3
|
|
||||||
},
|
|
||||||
"o": { "a": 0, "k": 100, "ix": 4 },
|
|
||||||
"w": { "a": 0, "k": 77, "ix": 5 },
|
|
||||||
"lc": 2,
|
|
||||||
"lj": 1,
|
|
||||||
"ml": 4,
|
|
||||||
"bm": 0,
|
|
||||||
"nm": "Stroke 1",
|
|
||||||
"mn": "ADBE Vector Graphic - Stroke",
|
|
||||||
"hd": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "tr",
|
|
||||||
"p": { "a": 0, "k": [-348, -164], "ix": 2 },
|
|
||||||
"a": { "a": 0, "k": [-348, -156], "ix": 1 },
|
|
||||||
"s": { "a": 0, "k": [100, 100], "ix": 3 },
|
|
||||||
"r": { "a": 0, "k": 0, "ix": 6 },
|
|
||||||
"o": { "a": 0, "k": 100, "ix": 7 },
|
|
||||||
"sk": { "a": 0, "k": 0, "ix": 4 },
|
|
||||||
"sa": { "a": 0, "k": 0, "ix": 5 },
|
|
||||||
"nm": "Transform"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"nm": "Shape 1",
|
|
||||||
"np": 3,
|
|
||||||
"cix": 2,
|
|
||||||
"bm": 0,
|
|
||||||
"ix": 1,
|
|
||||||
"mn": "ADBE Vector Group",
|
|
||||||
"hd": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ip": 0,
|
|
||||||
"op": 120,
|
|
||||||
"st": 0,
|
|
||||||
"bm": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ddd": 0,
|
|
||||||
"ind": 2,
|
|
||||||
"ty": 4,
|
|
||||||
"nm": "esquerdo",
|
|
||||||
"parent": 1,
|
|
||||||
"sr": 1,
|
|
||||||
"ks": {
|
|
||||||
"o": { "a": 0, "k": 100, "ix": 11 },
|
|
||||||
"r": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{
|
|
||||||
"i": { "x": [0.552], "y": [1] },
|
|
||||||
"o": { "x": [0.702], "y": [0] },
|
|
||||||
"t": 0,
|
|
||||||
"s": [-1]
|
|
||||||
},
|
|
||||||
{ "t": 30, "s": [43.5] }
|
|
||||||
],
|
|
||||||
"ix": 10
|
|
||||||
},
|
|
||||||
"p": { "a": 0, "k": [-348.39, -36.55, 0], "ix": 2 },
|
|
||||||
"a": { "a": 0, "k": [-2, 84, 0], "ix": 1 },
|
|
||||||
"s": { "a": 0, "k": [100, 100, 100], "ix": 6 }
|
|
||||||
},
|
|
||||||
"ao": 0,
|
|
||||||
"shapes": [
|
|
||||||
{
|
|
||||||
"ty": "gr",
|
|
||||||
"it": [
|
|
||||||
{
|
|
||||||
"ind": 0,
|
|
||||||
"ty": "sh",
|
|
||||||
"ix": 1,
|
|
||||||
"ks": {
|
|
||||||
"a": 0,
|
|
||||||
"k": {
|
|
||||||
"i": [
|
|
||||||
[0, 0],
|
|
||||||
[0, 0]
|
|
||||||
],
|
|
||||||
"o": [
|
|
||||||
[0, 0],
|
|
||||||
[0, 0]
|
|
||||||
],
|
|
||||||
"v": [
|
|
||||||
[-178, -102],
|
|
||||||
[-2, 84]
|
|
||||||
],
|
|
||||||
"c": false
|
|
||||||
},
|
|
||||||
"ix": 2
|
|
||||||
},
|
|
||||||
"nm": "Path 1",
|
|
||||||
"mn": "ADBE Vector Shape - Group",
|
|
||||||
"hd": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "st",
|
|
||||||
"c": {
|
|
||||||
"a": 0,
|
|
||||||
"k": [0.854901960784, 0.858823529412, 0.882352941176, 1],
|
|
||||||
"ix": 3
|
|
||||||
},
|
|
||||||
"o": { "a": 0, "k": 100, "ix": 4 },
|
|
||||||
"w": { "a": 0, "k": 77, "ix": 5 },
|
|
||||||
"lc": 2,
|
|
||||||
"lj": 1,
|
|
||||||
"ml": 4,
|
|
||||||
"bm": 0,
|
|
||||||
"nm": "Stroke 1",
|
|
||||||
"mn": "ADBE Vector Graphic - Stroke",
|
|
||||||
"hd": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "tr",
|
|
||||||
"p": { "a": 0, "k": [0, 0], "ix": 2 },
|
|
||||||
"a": { "a": 0, "k": [0, 0], "ix": 1 },
|
|
||||||
"s": { "a": 0, "k": [100, 100], "ix": 3 },
|
|
||||||
"r": { "a": 0, "k": 0, "ix": 6 },
|
|
||||||
"o": { "a": 0, "k": 100, "ix": 7 },
|
|
||||||
"sk": { "a": 0, "k": 0, "ix": 4 },
|
|
||||||
"sa": { "a": 0, "k": 0, "ix": 5 },
|
|
||||||
"nm": "Transform"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"nm": "Shape 1",
|
|
||||||
"np": 3,
|
|
||||||
"cix": 2,
|
|
||||||
"bm": 0,
|
|
||||||
"ix": 1,
|
|
||||||
"mn": "ADBE Vector Group",
|
|
||||||
"hd": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "tm",
|
|
||||||
"s": { "a": 0, "k": 8, "ix": 1 },
|
|
||||||
"e": { "a": 0, "k": 100, "ix": 2 },
|
|
||||||
"o": { "a": 0, "k": 0, "ix": 3 },
|
|
||||||
"m": 1,
|
|
||||||
"ix": 2,
|
|
||||||
"nm": "Trim Paths 1",
|
|
||||||
"mn": "ADBE Vector Filter - Trim",
|
|
||||||
"hd": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ip": 0,
|
|
||||||
"op": 120,
|
|
||||||
"st": 0,
|
|
||||||
"bm": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ddd": 0,
|
|
||||||
"ind": 3,
|
|
||||||
"ty": 4,
|
|
||||||
"nm": "direito",
|
|
||||||
"parent": 1,
|
|
||||||
"sr": 1,
|
|
||||||
"ks": {
|
|
||||||
"o": { "a": 0, "k": 100, "ix": 11 },
|
|
||||||
"r": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{
|
|
||||||
"i": { "x": [0.47], "y": [1] },
|
|
||||||
"o": { "x": [0.735], "y": [0] },
|
|
||||||
"t": 0,
|
|
||||||
"s": [1]
|
|
||||||
},
|
|
||||||
{ "t": 30, "s": [-43.5] }
|
|
||||||
],
|
|
||||||
"ix": 10
|
|
||||||
},
|
|
||||||
"p": { "a": 0, "k": [-348.39, -36.55, 0], "ix": 2 },
|
|
||||||
"a": { "a": 0, "k": [-2, 84, 0], "ix": 1 },
|
|
||||||
"s": { "a": 0, "k": [-100, 100, 100], "ix": 6 }
|
|
||||||
},
|
|
||||||
"ao": 0,
|
|
||||||
"shapes": [
|
|
||||||
{
|
|
||||||
"ty": "gr",
|
|
||||||
"it": [
|
|
||||||
{
|
|
||||||
"ind": 0,
|
|
||||||
"ty": "sh",
|
|
||||||
"ix": 1,
|
|
||||||
"ks": {
|
|
||||||
"a": 0,
|
|
||||||
"k": {
|
|
||||||
"i": [
|
|
||||||
[0, 0],
|
|
||||||
[0, 0]
|
|
||||||
],
|
|
||||||
"o": [
|
|
||||||
[0, 0],
|
|
||||||
[0, 0]
|
|
||||||
],
|
|
||||||
"v": [
|
|
||||||
[-178, -102],
|
|
||||||
[-2, 84]
|
|
||||||
],
|
|
||||||
"c": false
|
|
||||||
},
|
|
||||||
"ix": 2
|
|
||||||
},
|
|
||||||
"nm": "Path 1",
|
|
||||||
"mn": "ADBE Vector Shape - Group",
|
|
||||||
"hd": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "tm",
|
|
||||||
"s": { "a": 0, "k": 8, "ix": 1 },
|
|
||||||
"e": { "a": 0, "k": 100, "ix": 2 },
|
|
||||||
"o": { "a": 0, "k": 0, "ix": 3 },
|
|
||||||
"m": 1,
|
|
||||||
"ix": 2,
|
|
||||||
"nm": "Trim Paths 1",
|
|
||||||
"mn": "ADBE Vector Filter - Trim",
|
|
||||||
"hd": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "st",
|
|
||||||
"c": {
|
|
||||||
"a": 0,
|
|
||||||
"k": [0.854901960784, 0.858823529412, 0.882352941176, 1],
|
|
||||||
"ix": 3
|
|
||||||
},
|
|
||||||
"o": { "a": 0, "k": 100, "ix": 4 },
|
|
||||||
"w": { "a": 0, "k": 77, "ix": 5 },
|
|
||||||
"lc": 2,
|
|
||||||
"lj": 1,
|
|
||||||
"ml": 4,
|
|
||||||
"bm": 0,
|
|
||||||
"nm": "Stroke 1",
|
|
||||||
"mn": "ADBE Vector Graphic - Stroke",
|
|
||||||
"hd": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "tr",
|
|
||||||
"p": { "a": 0, "k": [0, 0], "ix": 2 },
|
|
||||||
"a": { "a": 0, "k": [0, 0], "ix": 1 },
|
|
||||||
"s": { "a": 0, "k": [100, 100], "ix": 3 },
|
|
||||||
"r": { "a": 0, "k": 0, "ix": 6 },
|
|
||||||
"o": { "a": 0, "k": 100, "ix": 7 },
|
|
||||||
"sk": { "a": 0, "k": 0, "ix": 4 },
|
|
||||||
"sa": { "a": 0, "k": 0, "ix": 5 },
|
|
||||||
"nm": "Transform"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"nm": "Shape 1",
|
|
||||||
"np": 4,
|
|
||||||
"cix": 2,
|
|
||||||
"bm": 0,
|
|
||||||
"ix": 1,
|
|
||||||
"mn": "ADBE Vector Group",
|
|
||||||
"hd": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ip": 0,
|
|
||||||
"op": 120,
|
|
||||||
"st": 0,
|
|
||||||
"bm": 0
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"layers": [
|
|
||||||
{
|
|
||||||
"ddd": 0,
|
|
||||||
"ind": 1,
|
|
||||||
"ty": 0,
|
|
||||||
"nm": "seta 2",
|
|
||||||
"refId": "comp_0",
|
|
||||||
"sr": 1,
|
|
||||||
"ks": {
|
|
||||||
"o": { "a": 0, "k": 100, "ix": 11 },
|
|
||||||
"r": { "a": 0, "k": 0, "ix": 10 },
|
|
||||||
"p": { "a": 0, "k": [357, -247, 0], "ix": 2 },
|
|
||||||
"a": { "a": 0, "k": [450, 960, 0], "ix": 1 },
|
|
||||||
"s": { "a": 0, "k": [100, 100, 100], "ix": 6 }
|
|
||||||
},
|
|
||||||
"ao": 0,
|
|
||||||
"w": 900,
|
|
||||||
"h": 1920,
|
|
||||||
"ip": 30,
|
|
||||||
"op": 120,
|
|
||||||
"st": 30,
|
|
||||||
"bm": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ddd": 0,
|
|
||||||
"ind": 2,
|
|
||||||
"ty": 0,
|
|
||||||
"nm": "seta",
|
|
||||||
"refId": "comp_1",
|
|
||||||
"sr": 1,
|
|
||||||
"ks": {
|
|
||||||
"o": { "a": 0, "k": 100, "ix": 11 },
|
|
||||||
"r": { "a": 0, "k": 0, "ix": 10 },
|
|
||||||
"p": { "a": 0, "k": [357, 258, 0], "ix": 2 },
|
|
||||||
"a": { "a": 0, "k": [450, 345, 0], "ix": 1 },
|
|
||||||
"s": { "a": 0, "k": [100, 100, 100], "ix": 6 }
|
|
||||||
},
|
|
||||||
"ao": 0,
|
|
||||||
"w": 900,
|
|
||||||
"h": 690,
|
|
||||||
"ip": 0,
|
|
||||||
"op": 120,
|
|
||||||
"st": 0,
|
|
||||||
"bm": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ddd": 0,
|
|
||||||
"ind": 3,
|
|
||||||
"ty": 4,
|
|
||||||
"nm": "base Outlines",
|
|
||||||
"sr": 1,
|
|
||||||
"ks": {
|
|
||||||
"o": { "a": 0, "k": 100, "ix": 11 },
|
|
||||||
"r": { "a": 0, "k": 0, "ix": 10 },
|
|
||||||
"p": { "a": 0, "k": [357, 548.713, 0], "ix": 2 },
|
|
||||||
"a": { "a": 0, "k": [357.81, 129.934, 0], "ix": 1 },
|
|
||||||
"s": { "a": 0, "k": [100, 100, 100], "ix": 6 }
|
|
||||||
},
|
|
||||||
"ao": 0,
|
|
||||||
"shapes": [
|
|
||||||
{
|
|
||||||
"ty": "gr",
|
|
||||||
"it": [
|
|
||||||
{
|
|
||||||
"ind": 0,
|
|
||||||
"ty": "sh",
|
|
||||||
"ix": 1,
|
|
||||||
"ks": {
|
|
||||||
"a": 0,
|
|
||||||
"k": {
|
|
||||||
"i": [
|
|
||||||
[0, 0],
|
|
||||||
[0, 50.043],
|
|
||||||
[0, 0],
|
|
||||||
[-21.158, 0],
|
|
||||||
[0, -21.447],
|
|
||||||
[0, 0],
|
|
||||||
[-7.049, 0],
|
|
||||||
[0, 0],
|
|
||||||
[0, 7.149],
|
|
||||||
[0, 0],
|
|
||||||
[-21.158, 0],
|
|
||||||
[0, -21.447],
|
|
||||||
[0, 0],
|
|
||||||
[49.368, 0]
|
|
||||||
],
|
|
||||||
"o": [
|
|
||||||
[-49.369, 0],
|
|
||||||
[0, 0],
|
|
||||||
[0, -21.447],
|
|
||||||
[21.158, 0],
|
|
||||||
[0, 0],
|
|
||||||
[0, 7.145],
|
|
||||||
[0, 0],
|
|
||||||
[7.053, 0],
|
|
||||||
[0, 0],
|
|
||||||
[0, -21.447],
|
|
||||||
[21.158, 0],
|
|
||||||
[0, 0],
|
|
||||||
[0, 50.043],
|
|
||||||
[0, 0]
|
|
||||||
],
|
|
||||||
"v": [
|
|
||||||
[-268.169, 129.445],
|
|
||||||
[-357.559, 38.834],
|
|
||||||
[-357.559, -90.61],
|
|
||||||
[-319.249, -129.445],
|
|
||||||
[-280.939, -90.61],
|
|
||||||
[-280.939, 38.834],
|
|
||||||
[-268.169, 51.778],
|
|
||||||
[268.169, 51.778],
|
|
||||||
[280.939, 38.834],
|
|
||||||
[280.939, -90.61],
|
|
||||||
[319.249, -129.445],
|
|
||||||
[357.559, -90.61],
|
|
||||||
[357.559, 38.834],
|
|
||||||
[268.169, 129.445]
|
|
||||||
],
|
|
||||||
"c": true
|
|
||||||
},
|
|
||||||
"ix": 2
|
|
||||||
},
|
|
||||||
"nm": "Path 1",
|
|
||||||
"mn": "ADBE Vector Shape - Group",
|
|
||||||
"hd": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "fl",
|
|
||||||
"c": {
|
|
||||||
"a": 0,
|
|
||||||
"k": [0.865977448108, 0.86824388691, 0.890449075138, 1],
|
|
||||||
"ix": 4
|
|
||||||
},
|
|
||||||
"o": { "a": 0, "k": 100, "ix": 5 },
|
|
||||||
"r": 1,
|
|
||||||
"bm": 0,
|
|
||||||
"nm": "Fill 1",
|
|
||||||
"mn": "ADBE Vector Graphic - Fill",
|
|
||||||
"hd": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "tr",
|
|
||||||
"p": { "a": 0, "k": [357.809, 129.695], "ix": 2 },
|
|
||||||
"a": { "a": 0, "k": [0, 0], "ix": 1 },
|
|
||||||
"s": { "a": 0, "k": [100, 100], "ix": 3 },
|
|
||||||
"r": { "a": 0, "k": 0, "ix": 6 },
|
|
||||||
"o": { "a": 0, "k": 100, "ix": 7 },
|
|
||||||
"sk": { "a": 0, "k": 0, "ix": 4 },
|
|
||||||
"sa": { "a": 0, "k": 0, "ix": 5 },
|
|
||||||
"nm": "Transform"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"nm": "Group 1",
|
|
||||||
"np": 2,
|
|
||||||
"cix": 2,
|
|
||||||
"bm": 0,
|
|
||||||
"ix": 1,
|
|
||||||
"mn": "ADBE Vector Group",
|
|
||||||
"hd": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ip": 0,
|
|
||||||
"op": 120,
|
|
||||||
"st": 0,
|
|
||||||
"bm": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"markers": []
|
|
||||||
}
|
|
@ -1,7 +1,7 @@
|
|||||||
@use "../../scss/globals.scss";
|
@use "../../scss/globals.scss";
|
||||||
|
|
||||||
.bottom-panel {
|
.bottom-panel {
|
||||||
width: "100%";
|
width: 100%;
|
||||||
border-top: solid 1px globals.$border-color;
|
border-top: solid 1px globals.$border-color;
|
||||||
background-color: globals.$background-color;
|
background-color: globals.$background-color;
|
||||||
padding: calc(globals.$spacing-unit / 2) calc(globals.$spacing-unit * 2);
|
padding: calc(globals.$spacing-unit / 2) calc(globals.$spacing-unit * 2);
|
||||||
|
@ -111,6 +111,7 @@ export function Modal({
|
|||||||
aria-labelledby={title}
|
aria-labelledby={title}
|
||||||
aria-describedby={description}
|
aria-describedby={description}
|
||||||
ref={modalContentRef}
|
ref={modalContentRef}
|
||||||
|
data-hydra-dialog
|
||||||
>
|
>
|
||||||
<div className="modal__header">
|
<div className="modal__header">
|
||||||
<div style={{ display: "flex", gap: 4, flexDirection: "column" }}>
|
<div style={{ display: "flex", gap: 4, flexDirection: "column" }}>
|
||||||
|
@ -1,152 +0,0 @@
|
|||||||
import { style } from "@vanilla-extract/css";
|
|
||||||
import { recipe } from "@vanilla-extract/recipes";
|
|
||||||
|
|
||||||
import { SPACING_UNIT, vars } from "../../theme.css";
|
|
||||||
|
|
||||||
export const sidebar = recipe({
|
|
||||||
base: {
|
|
||||||
backgroundColor: vars.color.darkBackground,
|
|
||||||
color: vars.color.muted,
|
|
||||||
flexDirection: "column",
|
|
||||||
display: "flex",
|
|
||||||
transition: "opacity ease 0.2s",
|
|
||||||
borderRight: `solid 1px ${vars.color.border}`,
|
|
||||||
position: "relative",
|
|
||||||
overflow: "hidden",
|
|
||||||
justifyContent: "space-between",
|
|
||||||
},
|
|
||||||
variants: {
|
|
||||||
resizing: {
|
|
||||||
true: {
|
|
||||||
opacity: vars.opacity.active,
|
|
||||||
pointerEvents: "none",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
darwin: {
|
|
||||||
true: {
|
|
||||||
paddingTop: `${SPACING_UNIT * 6}px`,
|
|
||||||
},
|
|
||||||
false: {
|
|
||||||
paddingTop: `${SPACING_UNIT}px`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const content = style({
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
padding: `${SPACING_UNIT * 2}px`,
|
|
||||||
gap: `${SPACING_UNIT * 2}px`,
|
|
||||||
width: "100%",
|
|
||||||
overflow: "auto",
|
|
||||||
});
|
|
||||||
|
|
||||||
export const handle = style({
|
|
||||||
width: "5px",
|
|
||||||
height: "100%",
|
|
||||||
cursor: "col-resize",
|
|
||||||
position: "absolute",
|
|
||||||
right: "0",
|
|
||||||
});
|
|
||||||
|
|
||||||
export const menu = style({
|
|
||||||
listStyle: "none",
|
|
||||||
padding: "0",
|
|
||||||
margin: "0",
|
|
||||||
gap: `${SPACING_UNIT / 2}px`,
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
overflow: "hidden",
|
|
||||||
});
|
|
||||||
|
|
||||||
export const menuItem = recipe({
|
|
||||||
base: {
|
|
||||||
transition: "all ease 0.1s",
|
|
||||||
cursor: "pointer",
|
|
||||||
textWrap: "nowrap",
|
|
||||||
display: "flex",
|
|
||||||
color: vars.color.muted,
|
|
||||||
borderRadius: "4px",
|
|
||||||
":hover": {
|
|
||||||
backgroundColor: "rgba(255, 255, 255, 0.15)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
variants: {
|
|
||||||
active: {
|
|
||||||
true: {
|
|
||||||
backgroundColor: "rgba(255, 255, 255, 0.1)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
muted: {
|
|
||||||
true: {
|
|
||||||
opacity: vars.opacity.disabled,
|
|
||||||
":hover": {
|
|
||||||
opacity: "1",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const menuItemButton = style({
|
|
||||||
color: "inherit",
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
gap: `${SPACING_UNIT}px`,
|
|
||||||
cursor: "pointer",
|
|
||||||
overflow: "hidden",
|
|
||||||
width: "100%",
|
|
||||||
padding: `9px ${SPACING_UNIT}px`,
|
|
||||||
});
|
|
||||||
|
|
||||||
export const menuItemButtonLabel = style({
|
|
||||||
textOverflow: "ellipsis",
|
|
||||||
overflow: "hidden",
|
|
||||||
});
|
|
||||||
|
|
||||||
export const gameIcon = style({
|
|
||||||
width: "20px",
|
|
||||||
height: "20px",
|
|
||||||
minWidth: "20px",
|
|
||||||
minHeight: "20px",
|
|
||||||
borderRadius: "4px",
|
|
||||||
backgroundSize: "cover",
|
|
||||||
});
|
|
||||||
|
|
||||||
export const sectionTitle = style({
|
|
||||||
textTransform: "uppercase",
|
|
||||||
fontWeight: "bold",
|
|
||||||
});
|
|
||||||
|
|
||||||
export const section = style({
|
|
||||||
gap: `${SPACING_UNIT * 2}px`,
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
paddingBottom: `${SPACING_UNIT}px`,
|
|
||||||
});
|
|
||||||
|
|
||||||
export const helpButton = style({
|
|
||||||
color: vars.color.muted,
|
|
||||||
padding: `${SPACING_UNIT}px ${SPACING_UNIT * 2}px`,
|
|
||||||
gap: "9px",
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
cursor: "pointer",
|
|
||||||
borderTop: `solid 1px ${vars.color.border}`,
|
|
||||||
transition: "background-color ease 0.1s",
|
|
||||||
":hover": {
|
|
||||||
backgroundColor: "rgba(255, 255, 255, 0.15)",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const helpButtonIcon = style({
|
|
||||||
background: "linear-gradient(0deg, #16B195 50%, #3E62C0 100%)",
|
|
||||||
width: "24px",
|
|
||||||
height: "24px",
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "center",
|
|
||||||
color: "#fff",
|
|
||||||
borderRadius: "50%",
|
|
||||||
});
|
|
@ -24,8 +24,6 @@ import { sortBy } from "lodash-es";
|
|||||||
import cn from "classnames";
|
import cn from "classnames";
|
||||||
import { CommentDiscussionIcon } from "@primer/octicons-react";
|
import { CommentDiscussionIcon } from "@primer/octicons-react";
|
||||||
|
|
||||||
import { show, update } from "@intercom/messenger-js-sdk";
|
|
||||||
|
|
||||||
const SIDEBAR_MIN_WIDTH = 200;
|
const SIDEBAR_MIN_WIDTH = 200;
|
||||||
const SIDEBAR_INITIAL_WIDTH = 250;
|
const SIDEBAR_INITIAL_WIDTH = 250;
|
||||||
const SIDEBAR_MAX_WIDTH = 450;
|
const SIDEBAR_MAX_WIDTH = 450;
|
||||||
@ -52,19 +50,7 @@ export function Sidebar() {
|
|||||||
return sortBy(library, (game) => game.title);
|
return sortBy(library, (game) => game.title);
|
||||||
}, [library]);
|
}, [library]);
|
||||||
|
|
||||||
const { userDetails, hasActiveSubscription } = useUserDetails();
|
const { hasActiveSubscription } = useUserDetails();
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (userDetails) {
|
|
||||||
update({
|
|
||||||
name: userDetails.displayName,
|
|
||||||
Username: userDetails.username,
|
|
||||||
Email: userDetails.email,
|
|
||||||
"Subscription expiration date": userDetails?.subscription?.expiresAt,
|
|
||||||
"Payment status": userDetails?.subscription?.status,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, [userDetails, hasActiveSubscription]);
|
|
||||||
|
|
||||||
const { lastPacket, progress } = useDownload();
|
const { lastPacket, progress } = useDownload();
|
||||||
|
|
||||||
@ -267,7 +253,11 @@ export function Sidebar() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{hasActiveSubscription && (
|
{hasActiveSubscription && (
|
||||||
<button type="button" className="sidebar__help-button" onClick={show}>
|
<button
|
||||||
|
type="button"
|
||||||
|
className="sidebar__help-button"
|
||||||
|
data-open-support-chat
|
||||||
|
>
|
||||||
<div className="sidebar__help-button-icon">
|
<div className="sidebar__help-button-icon">
|
||||||
<CommentDiscussionIcon size={14} />
|
<CommentDiscussionIcon size={14} />
|
||||||
</div>
|
</div>
|
||||||
|
@ -181,6 +181,7 @@ export function GameDetailsContextProvider({
|
|||||||
shop,
|
shop,
|
||||||
i18n.language,
|
i18n.language,
|
||||||
userDetails,
|
userDetails,
|
||||||
|
userPreferences,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
46
src/renderer/src/cookies.ts
Normal file
46
src/renderer/src/cookies.ts
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
export function addCookieInterceptor(isStaging: boolean) {
|
||||||
|
const cookieKey = isStaging ? "cookies-staging" : "cookies";
|
||||||
|
|
||||||
|
Object.defineProperty(document, "cookie", {
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true,
|
||||||
|
get() {
|
||||||
|
return localStorage.getItem(cookieKey) || "";
|
||||||
|
},
|
||||||
|
set(cookieString) {
|
||||||
|
try {
|
||||||
|
const [cookieName, cookieValue] = cookieString.split(";")[0].split("=");
|
||||||
|
|
||||||
|
const currentCookies = localStorage.getItem(cookieKey) || "";
|
||||||
|
|
||||||
|
const cookiesObject = parseCookieStringsToObjects(currentCookies);
|
||||||
|
cookiesObject[cookieName] = cookieValue;
|
||||||
|
|
||||||
|
const newString = Object.entries(cookiesObject)
|
||||||
|
.map(([key, value]) => {
|
||||||
|
return key + "=" + value;
|
||||||
|
})
|
||||||
|
.join("; ");
|
||||||
|
|
||||||
|
localStorage.setItem(cookieKey, newString);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const parseCookieStringsToObjects = (
|
||||||
|
cookieStrings: string
|
||||||
|
): { [key: string]: string } => {
|
||||||
|
const result = {};
|
||||||
|
|
||||||
|
if (cookieStrings === "") return result;
|
||||||
|
|
||||||
|
cookieStrings.split(";").forEach((cookieString) => {
|
||||||
|
const [name, value] = cookieString.split("=");
|
||||||
|
result[name.trim()] = value.trim();
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
14
src/renderer/src/declaration.d.ts
vendored
14
src/renderer/src/declaration.d.ts
vendored
@ -60,7 +60,8 @@ declare global {
|
|||||||
) => Promise<ShopDetails | null>;
|
) => Promise<ShopDetails | null>;
|
||||||
getRandomGame: () => Promise<Steam250Game>;
|
getRandomGame: () => Promise<Steam250Game>;
|
||||||
getHowLongToBeat: (
|
getHowLongToBeat: (
|
||||||
title: string
|
objectId: string,
|
||||||
|
shop: GameShop
|
||||||
) => Promise<HowLongToBeatCategory[] | null>;
|
) => Promise<HowLongToBeatCategory[] | null>;
|
||||||
getGames: (take?: number, skip?: number) => Promise<CatalogueEntry[]>;
|
getGames: (take?: number, skip?: number) => Promise<CatalogueEntry[]>;
|
||||||
searchGameRepacks: (query: string) => Promise<GameRepack[]>;
|
searchGameRepacks: (query: string) => Promise<GameRepack[]>;
|
||||||
@ -79,8 +80,14 @@ declare global {
|
|||||||
shop: GameShop
|
shop: GameShop
|
||||||
) => Promise<void>;
|
) => Promise<void>;
|
||||||
createGameShortcut: (id: number) => Promise<boolean>;
|
createGameShortcut: (id: number) => Promise<boolean>;
|
||||||
updateExecutablePath: (id: number, executablePath: string) => Promise<void>;
|
updateExecutablePath: (
|
||||||
selectGameWinePrefix: (id: number, winePrefixPath: string) => Promise<void>;
|
id: number,
|
||||||
|
executablePath: string | null
|
||||||
|
) => Promise<void>;
|
||||||
|
selectGameWinePrefix: (
|
||||||
|
id: number,
|
||||||
|
winePrefixPath: string | null
|
||||||
|
) => Promise<void>;
|
||||||
verifyExecutablePathInUse: (executablePath: string) => Promise<Game>;
|
verifyExecutablePathInUse: (executablePath: string) => Promise<Game>;
|
||||||
getLibrary: () => Promise<LibraryGame[]>;
|
getLibrary: () => Promise<LibraryGame[]>;
|
||||||
openGameInstaller: (gameId: number) => Promise<boolean>;
|
openGameInstaller: (gameId: number) => Promise<boolean>;
|
||||||
@ -162,6 +169,7 @@ declare global {
|
|||||||
openExternal: (src: string) => Promise<void>;
|
openExternal: (src: string) => Promise<void>;
|
||||||
openCheckout: () => Promise<void>;
|
openCheckout: () => Promise<void>;
|
||||||
getVersion: () => Promise<string>;
|
getVersion: () => Promise<string>;
|
||||||
|
isStaging: () => Promise<boolean>;
|
||||||
ping: () => string;
|
ping: () => string;
|
||||||
getDefaultDownloadsPath: () => Promise<string>;
|
getDefaultDownloadsPath: () => Promise<string>;
|
||||||
isPortableVersion: () => Promise<boolean>;
|
isPortableVersion: () => Promise<boolean>;
|
||||||
|
@ -50,16 +50,3 @@ export const buildGameAchievementPath = (
|
|||||||
|
|
||||||
export const darkenColor = (color: string, amount: number, alpha: number = 1) =>
|
export const darkenColor = (color: string, amount: number, alpha: number = 1) =>
|
||||||
new Color(color).darken(amount).alpha(alpha).toString();
|
new Color(color).darken(amount).alpha(alpha).toString();
|
||||||
|
|
||||||
export const insertCustomStyles = (styles: string) => {
|
|
||||||
const existingStyles = document.getElementById("custom-styles");
|
|
||||||
|
|
||||||
if (existingStyles) {
|
|
||||||
existingStyles.innerHTML = styles;
|
|
||||||
} else {
|
|
||||||
const style = document.createElement("style");
|
|
||||||
style.id = "custom-styles";
|
|
||||||
style.innerHTML = styles;
|
|
||||||
document.head.appendChild(style);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
@ -14,6 +14,7 @@ import type {
|
|||||||
UserDetails,
|
UserDetails,
|
||||||
} from "@types";
|
} from "@types";
|
||||||
import { UserFriendModalTab } from "@renderer/pages/shared-modals/user-friend-modal";
|
import { UserFriendModalTab } from "@renderer/pages/shared-modals/user-friend-modal";
|
||||||
|
import { isFuture, isToday } from "date-fns";
|
||||||
|
|
||||||
export function useUserDetails() {
|
export function useUserDetails() {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
@ -55,6 +56,8 @@ export function useUserDetails() {
|
|||||||
clearUserDetails();
|
clearUserDetails();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
window["userDetails"] = userDetails;
|
||||||
|
|
||||||
return userDetails;
|
return userDetails;
|
||||||
});
|
});
|
||||||
}, [clearUserDetails]);
|
}, [clearUserDetails]);
|
||||||
@ -128,10 +131,8 @@ export function useUserDetails() {
|
|||||||
const unblockUser = (userId: string) => window.electron.unblockUser(userId);
|
const unblockUser = (userId: string) => window.electron.unblockUser(userId);
|
||||||
|
|
||||||
const hasActiveSubscription = useMemo(() => {
|
const hasActiveSubscription = useMemo(() => {
|
||||||
return (
|
const expiresAt = userDetails?.subscription?.expiresAt;
|
||||||
userDetails?.subscription?.expiresAt &&
|
return expiresAt && (isFuture(expiresAt) || isToday(expiresAt));
|
||||||
new Date(userDetails.subscription.expiresAt) > new Date()
|
|
||||||
);
|
|
||||||
}, [userDetails]);
|
}, [userDetails]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -20,6 +20,8 @@ import resources from "@locales";
|
|||||||
|
|
||||||
import { RepacksContextProvider } from "./context";
|
import { RepacksContextProvider } from "./context";
|
||||||
import { SuspenseWrapper } from "./components";
|
import { SuspenseWrapper } from "./components";
|
||||||
|
import { logger } from "./logger";
|
||||||
|
import { addCookieInterceptor } from "./cookies";
|
||||||
|
|
||||||
const Home = React.lazy(() => import("./pages/home/home"));
|
const Home = React.lazy(() => import("./pages/home/home"));
|
||||||
const GameDetails = React.lazy(
|
const GameDetails = React.lazy(
|
||||||
@ -34,6 +36,11 @@ const Achievements = React.lazy(
|
|||||||
() => import("./pages/achievements/achievements")
|
() => import("./pages/achievements/achievements")
|
||||||
);
|
);
|
||||||
|
|
||||||
|
console.log = logger.log;
|
||||||
|
|
||||||
|
const isStaging = await window.electron.isStaging();
|
||||||
|
addCookieInterceptor(isStaging);
|
||||||
|
|
||||||
i18n
|
i18n
|
||||||
.use(LanguageDetector)
|
.use(LanguageDetector)
|
||||||
.use(initReactI18next)
|
.use(initReactI18next)
|
||||||
|
@ -75,7 +75,7 @@ export function CloudSyncFilesModal({
|
|||||||
showSuccessToast(t("custom_backup_location_set"));
|
showSuccessToast(t("custom_backup_location_set"));
|
||||||
getGameBackupPreview();
|
getGameBackupPreview();
|
||||||
}
|
}
|
||||||
}, [objectId, setValue, shop, showSuccessToast, getGameBackupPreview]);
|
}, [objectId, setValue, shop, showSuccessToast, getGameBackupPreview, t]);
|
||||||
|
|
||||||
const handleFileMappingMethodClick = useCallback(
|
const handleFileMappingMethodClick = useCallback(
|
||||||
(mappingOption: FileMappingMethod) => {
|
(mappingOption: FileMappingMethod) => {
|
||||||
|
@ -95,6 +95,11 @@ export function GameOptionsModal({
|
|||||||
await window.electron.openGameExecutablePath(game.id);
|
await window.electron.openGameExecutablePath(game.id);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleClearExecutablePath = async () => {
|
||||||
|
await window.electron.updateExecutablePath(game.id, null);
|
||||||
|
updateGame();
|
||||||
|
};
|
||||||
|
|
||||||
const handleChangeWinePrefixPath = async () => {
|
const handleChangeWinePrefixPath = async () => {
|
||||||
const { filePaths } = await window.electron.showOpenDialog({
|
const { filePaths } = await window.electron.showOpenDialog({
|
||||||
properties: ["openDirectory"],
|
properties: ["openDirectory"],
|
||||||
@ -106,6 +111,11 @@ export function GameOptionsModal({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleClearWinePrefixPath = async () => {
|
||||||
|
await window.electron.selectGameWinePrefix(game.id, null);
|
||||||
|
updateGame();
|
||||||
|
};
|
||||||
|
|
||||||
const shouldShowWinePrefixConfiguration =
|
const shouldShowWinePrefixConfiguration =
|
||||||
window.electron.platform === "linux";
|
window.electron.platform === "linux";
|
||||||
|
|
||||||
@ -145,6 +155,7 @@ export function GameOptionsModal({
|
|||||||
disabled
|
disabled
|
||||||
placeholder={t("no_executable_selected")}
|
placeholder={t("no_executable_selected")}
|
||||||
rightContent={
|
rightContent={
|
||||||
|
<>
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
theme="outline"
|
theme="outline"
|
||||||
@ -153,6 +164,12 @@ export function GameOptionsModal({
|
|||||||
<FileIcon />
|
<FileIcon />
|
||||||
{t("select_executable")}
|
{t("select_executable")}
|
||||||
</Button>
|
</Button>
|
||||||
|
{game.executablePath && (
|
||||||
|
<Button onClick={handleClearExecutablePath} theme="outline">
|
||||||
|
{t("clear")}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@ -186,6 +203,7 @@ export function GameOptionsModal({
|
|||||||
disabled
|
disabled
|
||||||
placeholder={t("no_directory_selected")}
|
placeholder={t("no_directory_selected")}
|
||||||
rightContent={
|
rightContent={
|
||||||
|
<>
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
theme="outline"
|
theme="outline"
|
||||||
@ -194,6 +212,15 @@ export function GameOptionsModal({
|
|||||||
<FileDirectoryIcon />
|
<FileDirectoryIcon />
|
||||||
{t("select_executable")}
|
{t("select_executable")}
|
||||||
</Button>
|
</Button>
|
||||||
|
{game.winePrefixPath && (
|
||||||
|
<Button
|
||||||
|
onClick={handleClearWinePrefixPath}
|
||||||
|
theme="outline"
|
||||||
|
>
|
||||||
|
{t("clear")}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -97,8 +97,10 @@ export function Sidebar() {
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
const howLongToBeat =
|
const howLongToBeat = await window.electron.getHowLongToBeat(
|
||||||
await window.electron.getHowLongToBeat(gameTitle);
|
objectId,
|
||||||
|
shop
|
||||||
|
);
|
||||||
|
|
||||||
if (howLongToBeat) {
|
if (howLongToBeat) {
|
||||||
howLongToBeatEntriesTable.add({
|
howLongToBeatEntriesTable.add({
|
||||||
|
@ -45,7 +45,8 @@ export function ProfileContent() {
|
|||||||
return userProfile?.relation?.status === "ACCEPTED";
|
return userProfile?.relation?.status === "ACCEPTED";
|
||||||
}, [userProfile]);
|
}, [userProfile]);
|
||||||
|
|
||||||
const buildUserGameDetailsPath = (game: UserGame) => {
|
const buildUserGameDetailsPath = useCallback(
|
||||||
|
(game: UserGame) => {
|
||||||
if (!userProfile?.hasActiveSubscription || game.achievementCount === 0) {
|
if (!userProfile?.hasActiveSubscription || game.achievementCount === 0) {
|
||||||
return buildGameDetailsPath({
|
return buildGameDetailsPath({
|
||||||
...game,
|
...game,
|
||||||
@ -60,7 +61,9 @@ export function ProfileContent() {
|
|||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
return buildGameAchievementPath({ ...game }, userParams);
|
return buildGameAchievementPath({ ...game }, userParams);
|
||||||
};
|
},
|
||||||
|
[userProfile]
|
||||||
|
);
|
||||||
|
|
||||||
const formatPlayTime = useCallback(
|
const formatPlayTime = useCallback(
|
||||||
(playTimeInSeconds = 0) => {
|
(playTimeInSeconds = 0) => {
|
||||||
@ -259,6 +262,7 @@ export function ProfileContent() {
|
|||||||
userStats,
|
userStats,
|
||||||
numberFormatter,
|
numberFormatter,
|
||||||
t,
|
t,
|
||||||
|
buildUserGameDetailsPath,
|
||||||
formatPlayTime,
|
formatPlayTime,
|
||||||
navigate,
|
navigate,
|
||||||
]);
|
]);
|
||||||
|
@ -11,7 +11,6 @@ import { changeLanguage } from "i18next";
|
|||||||
import languageResources from "@locales";
|
import languageResources from "@locales";
|
||||||
import { orderBy } from "lodash-es";
|
import { orderBy } from "lodash-es";
|
||||||
import { settingsContext } from "@renderer/context";
|
import { settingsContext } from "@renderer/context";
|
||||||
import { insertCustomStyles } from "@renderer/helpers";
|
|
||||||
|
|
||||||
interface LanguageOption {
|
interface LanguageOption {
|
||||||
option: string;
|
option: string;
|
||||||
@ -114,19 +113,6 @@ export function SettingsGeneral() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleSaveStylesClick = () => {
|
|
||||||
const existingStyles = document.getElementById("custom-styles");
|
|
||||||
if (existingStyles) {
|
|
||||||
existingStyles.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
const css = document.querySelector("textarea")?.value;
|
|
||||||
if (css) {
|
|
||||||
insertCustomStyles(css);
|
|
||||||
window.localStorage.setItem("customStyles", css);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<TextField
|
<TextField
|
||||||
@ -185,11 +171,6 @@ export function SettingsGeneral() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<textarea defaultValue={form.customStyles} placeholder="CSS goes here" />
|
|
||||||
<Button theme="primary" onClick={handleSaveStylesClick}>
|
|
||||||
Save CSS
|
|
||||||
</Button>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
2
src/renderer/src/vite-env.d.ts
vendored
2
src/renderer/src/vite-env.d.ts
vendored
@ -2,7 +2,7 @@
|
|||||||
/// <reference types="vite-plugin-svgr/client" />
|
/// <reference types="vite-plugin-svgr/client" />
|
||||||
|
|
||||||
interface ImportMetaEnv {
|
interface ImportMetaEnv {
|
||||||
readonly RENDERER_VITE_INTERCOM_APP_ID: string;
|
readonly RENDERER_VITE_EXTERNAL_RESOURCES_URL: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ImportMeta {
|
interface ImportMeta {
|
||||||
|
@ -46,7 +46,7 @@ export const removeSymbolsFromName = (name: string) =>
|
|||||||
|
|
||||||
export const removeSpecialEditionFromName = (name: string) =>
|
export const removeSpecialEditionFromName = (name: string) =>
|
||||||
name.replace(
|
name.replace(
|
||||||
/(The |Digital )?(GOTY|Deluxe|Standard|Ultimate|Definitive|Enhanced|Collector's|Premium|Digital|Limited|Game of the Year|Reloaded|[0-9]{4}) Edition/g,
|
/(The |Digital )?(GOTY|Deluxe|Standard|Ultimate|Definitive|Enhanced|Collector's|Premium|Digital|Limited|Game of the Year|Reloaded|[0-9]{4}) Edition/gi,
|
||||||
""
|
""
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -73,7 +73,8 @@ export const formatName = pipe<string>(
|
|||||||
replaceUnderscoreWithSpace,
|
replaceUnderscoreWithSpace,
|
||||||
replaceDotsWithSpace,
|
replaceDotsWithSpace,
|
||||||
replaceNbspWithSpace,
|
replaceNbspWithSpace,
|
||||||
(str) => str.replace(/DIRECTOR'S CUT/g, ""),
|
(str) => str.replace(/DIRECTOR'S CUT/gi, ""),
|
||||||
|
(str) => str.replace(/Friend's Pass/gi, ""),
|
||||||
removeSymbolsFromName,
|
removeSymbolsFromName,
|
||||||
removeDuplicateSpaces,
|
removeDuplicateSpaces,
|
||||||
(str) => str.trim()
|
(str) => str.trim()
|
||||||
|
@ -241,6 +241,7 @@ export interface Subscription {
|
|||||||
status: SubscriptionStatus;
|
status: SubscriptionStatus;
|
||||||
plan: { id: string; name: string };
|
plan: { id: string; name: string };
|
||||||
expiresAt: string | null;
|
expiresAt: string | null;
|
||||||
|
paymentMethod: "pix" | "paypal";
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UserDetails {
|
export interface UserDetails {
|
||||||
|
@ -60,7 +60,7 @@ class Handler(BaseHTTPRequestHandler):
|
|||||||
self.end_headers()
|
self.end_headers()
|
||||||
return
|
return
|
||||||
|
|
||||||
process_list = [proc.info for proc in psutil.process_iter(['exe', 'pid', 'username'])]
|
process_list = [proc.info for proc in psutil.process_iter(['exe', 'pid', 'name'])]
|
||||||
|
|
||||||
self.send_response(200)
|
self.send_response(200)
|
||||||
self.send_header("Content-type", "application/json")
|
self.send_header("Content-type", "application/json")
|
||||||
|
@ -1066,11 +1066,6 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3"
|
resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3"
|
||||||
integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==
|
integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==
|
||||||
|
|
||||||
"@intercom/messenger-js-sdk@^0.0.14":
|
|
||||||
version "0.0.14"
|
|
||||||
resolved "https://registry.yarnpkg.com/@intercom/messenger-js-sdk/-/messenger-js-sdk-0.0.14.tgz#a27999370cc0a82a2a57a779426df25a57891863"
|
|
||||||
integrity sha512-2dH4BDAh9EI90K7hUkAdZ76W79LM45Sd1OBX7t6Vzy8twpNiQ5X+7sH9G5hlJlkSGnf+vFWlFcy9TOYAyEs1hA==
|
|
||||||
|
|
||||||
"@isaacs/cliui@^8.0.2":
|
"@isaacs/cliui@^8.0.2":
|
||||||
version "8.0.2"
|
version "8.0.2"
|
||||||
resolved "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz"
|
resolved "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz"
|
||||||
|
Loading…
Reference in New Issue
Block a user