diff --git a/README.md b/README.md index 1012c05d..a07414dc 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ [![cs](https://img.shields.io/badge/lang-cs-purple)](./README.cs.md) [![da](https://img.shields.io/badge/lang-da-red)](./README.da.md) [![nb](https://img.shields.io/badge/lang-nb-blue)](./README.nb.md) +[![ee](https://img.shields.io/badge/lang-et-blue.svg)](./README.et.md) ![Hydra Catalogue](./docs/screenshot.png) diff --git a/docs/README.be.md b/docs/README.be.md index b861d582..2bdde26d 100644 --- a/docs/README.be.md +++ b/docs/README.be.md @@ -25,6 +25,7 @@ [![cs](https://img.shields.io/badge/lang-cs-purple)](README.cs.md) [![da](https://img.shields.io/badge/lang-da-red)](README.da.md) [![nb](https://img.shields.io/badge/lang-nb-blue)](README.nb.md) +[![et](https://img.shields.io/badge/lang-et-blue.svg)](README.et.md) ![Hydra Catalogue](./screenshot.png) diff --git a/docs/README.cs.md b/docs/README.cs.md index 866a841c..30bb39b7 100644 --- a/docs/README.cs.md +++ b/docs/README.cs.md @@ -25,6 +25,7 @@ [![cs](https://img.shields.io/badge/lang-cs-purple)](README.cs.md) [![da](https://img.shields.io/badge/lang-da-red)](README.da.md) [![nb](https://img.shields.io/badge/lang-nb-blue)](README.nb.md) +[![et](https://img.shields.io/badge/lang-et-blue.svg)](README.et.md) ![Hydra Katalog](./screenshot.png) diff --git a/docs/README.da.md b/docs/README.da.md index abfe7817..79513fe3 100644 --- a/docs/README.da.md +++ b/docs/README.da.md @@ -24,6 +24,7 @@ [![ita](https://img.shields.io/badge/lang-it-red)](README.it.md) [![cs](https://img.shields.io/badge/lang-cs-purple)](README.cs.md) [![da](https://img.shields.io/badge/lang-da-red)](README.da.md) +[![et](https://img.shields.io/badge/lang-et-blue.svg)](README.et.md) ![Hydra Catalogue](./screenshot.png) diff --git a/docs/README.de.md b/docs/README.de.md index a1629fbb..45ef0fec 100644 --- a/docs/README.de.md +++ b/docs/README.de.md @@ -25,6 +25,7 @@ [![cs](https://img.shields.io/badge/lang-cs-purple)](README.cs.md) [![da](https://img.shields.io/badge/lang-da-red)](README.da.md) [![nb](https://img.shields.io/badge/lang-nb-blue)](README.nb.md) +[![et](https://img.shields.io/badge/lang-et-blue.svg)](README.et.md) ![Hydra Katalog](./screenshot.png) diff --git a/docs/README.es.md b/docs/README.es.md index 525d3e02..4209e94f 100644 --- a/docs/README.es.md +++ b/docs/README.es.md @@ -25,6 +25,7 @@ [![cs](https://img.shields.io/badge/lang-cs-purple)](README.cs.md) [![da](https://img.shields.io/badge/lang-da-red)](README.da.md) [![nb](https://img.shields.io/badge/lang-nb-blue)](README.nb.md) +[![et](https://img.shields.io/badge/lang-et-blue.svg)](README.et.md) ![Hydra Catalogue](./screenshot.png) diff --git a/docs/README.et.md b/docs/README.et.md new file mode 100644 index 00000000..c54c5b71 --- /dev/null +++ b/docs/README.et.md @@ -0,0 +1,186 @@ +
+ +[](https://hydralauncher.site) + +

Hydra Launcher

+ +

+ Hydra on mängulauncher oma sisseehitatud bittorrenti kliendiga. +

+ +[![build](https://img.shields.io/github/actions/workflow/status/hydralauncher/hydra/build.yml)](https://github.com/hydralauncher/hydra/actions) +[![release](https://img.shields.io/github/package-json/v/hydralauncher/hydra)](https://github.com/hydralauncher/hydra/releases) + +[![pt-BR](https://img.shields.io/badge/lang-pt--BR-green.svg)](./README.pt-BR.md) +[![en](https://img.shields.io/badge/lang-en-red.svg)](./README.md) +[![ru](https://img.shields.io/badge/lang-ru-yellow.svg)](./README.ru.md) +[![uk-UA](https://img.shields.io/badge/lang-uk--UA-blue)](./README.uk-UA.md) +[![be](https://img.shields.io/badge/lang-be-orange)](./README.be.md) +[![es](https://img.shields.io/badge/lang-es-red)](./README.es.md) +[![fr](https://img.shields.io/badge/lang-fr-blue)](./README.fr.md) +[![de](https://img.shields.io/badge/lang-de-black)](./README.de.md) +[![ita](https://img.shields.io/badge/lang-it-red)](./README.it.md) +[![cs](https://img.shields.io/badge/lang-cs-purple)](./README.cs.md) +[![da](https://img.shields.io/badge/lang-da-red)](./README.da.md) +[![nb](https://img.shields.io/badge/lang-nb-blue)](./README.nb.md) +[![ee](https://img.shields.io/badge/lang-et-blue.svg)](./README.et.md) + +![Hydra Kataloog](./screenshot.png) + +
+ +## Sisukord + +- [Sisukord](#sisukord) +- [Tutvustus](#tutvustus) +- [Funktsioonid](#funktsioonid) +- [Paigaldamine](#paigaldamine) +- [Panustamine](#panustamine) + - [Liitu meie Telegramiga](#liitu-meie-telegramiga) + - [Forki ja klooni oma repositoorium](#forki-ja-klooni-oma-repositoorium) + - [Viisid panustamiseks](#viisid-panustamiseks) + - [Projekti Struktuur](#projekti-struktuur) +- [Lähtekoodi kompileerimine](#lähtekoodi-kompileerimine) + - [Node.js paigaldamine](#nodejs-paigaldamine) + - [Yarn'i paigaldamine](#yarni-paigaldamine) + - [Node sõltuvuste paigaldamine](#node-sõltuvuste-paigaldamine) + - [Python 3.9 paigaldamine](#python-39-paigaldamine) + - [Python'i sõltuvuste paigaldamine](#pythoni-sõltuvuste-paigaldamine) +- [Keskkonna muutujad](#keskkonna-muutujad) +- [Käivitamine](#käivitamine) +- [Kompileerimine](#kompileerimine) + - [Bittorrenti kliendi kompileerimine](#bittorrenti-kliendi-kompileerimine) + - [Electron rakenduse kompileerimine](#electron-rakenduse-kompileerimine) +- [Panustajad](#panustajad) +- [Litsents](#litsents) + +## Tutvustus + +**Hydra** on **Mängulauncher** oma sisseehitatud **BitTorrent Kliendiga**. +
+Launcher on kirjutatud TypeScriptis (Electron) ja Pythonis, mis haldab torrentide süsteemi kasutades libtorrenti. + +## Funktsioonid + +- Sisseehitatud bittorrenti klient +- How Long To Beat (HLTB) integratsioon mängu lehel +- Allalaadimiste kausta kohandamine +- Windowsi ja Linuxi tugi +- Pidevad uuendused +- Ja palju muud ... + +## Paigaldamine + +Järgi paigaldamiseks järgmisi samme: + +1. Lae alla Hydra uusim versioon [Releases](https://github.com/hydralauncher/hydra/releases/latest) lehelt. + - Lae alla ainult .exe fail, kui soovid paigaldada Hydrat Windowsile. + - Lae alla .deb või .rpm või .zip fail, kui soovid paigaldada Hydrat Linuxile. (sõltub sinu Linuxi distrost) +2. Käivita allalaaditud fail. +3. Naudi Hydrat! + +## Panustamine + +### Liitu meie Telegramiga + +Me keskendume aruteludele meie [Telegrami](https://t.me/hydralauncher) kanalis. + +### Forki ja klooni oma repositoorium + +1. Forki repositoorium [(klõpsa siia forkimiseks)](https://github.com/hydralauncher/hydra/fork) +2. Klooni oma forkitud kood `git clone https://github.com/your_username/hydra` +3. Loo uus haru +4. Pushi oma commitid +5. Esita uus Pull Request + +### Viisid panustamiseks + +- Tõlkimine: Me soovime, et Hydra oleks kättesaadav võimalikult paljudele inimestele. Võid aidata tõlkida uutesse keeltesse või uuendada ja parandada juba olemasolevaid tõlkeid Hydras. +- Kood: Hydra on ehitatud kasutades TypeScripti, Electroni ja natuke Pythonit. Kui soovid panustada, liitu meie [Telegramiga](https://t.me/hydralauncher)! + +### Projekti Struktuur + +- torrent-client: Kasutame libtorrenti, Pythoni teeki, torrentide allalaadimiste haldamiseks +- src/renderer: rakenduse kasutajaliides +- src/main: kogu loogika asub siin. + +## Lähtekoodi kompileerimine + +### Node.js paigaldamine + +Veendu, et Node.js on sinu arvutisse paigaldatud. Kui ei ole, lae alla ja paigalda see [nodejs.org](https://nodejs.org/) lehelt. + +### Yarn'i paigaldamine + +Yarn on Node.js paketihaldur. Kui sa pole Yarni veel paigaldanud, saad seda teha järgides juhiseid [yarnpkg.com](https://classic.yarnpkg.com/lang/en/docs/install/) lehel. + +### Node sõltuvuste paigaldamine + +Liigu projekti kausta ja paigalda Node sõltuvused kasutades Yarni: + +```bash +cd hydra +yarn +``` + +### Python 3.9 paigaldamine + +Veendu, et Python 3.9 on sinu arvutisse paigaldatud. Saad selle alla laadida ja paigaldada [python.org](https://www.python.org/downloads/release/python-3913/) lehelt. + +### Python'i sõltuvuste paigaldamine + +Paigalda vajalikud Pythoni sõltuvused kasutades pip'i: + +```bash +pip install -r requirements.txt +``` + +## Keskkonna muutujad + +Sul on vaja SteamGridDB API võtit, et laadida alla mängude ikoone paigaldamisel. + +Kui sul on see olemas, saad kopeerida või ümber nimetada `.env.example` faili `.env` failiks ja lisada sinna `STEAMGRIDDB_API_KEY`. + +## Käivitamine + +Kui kõik on seadistatud, saad käivitada järgmise käsu, et käivitada nii Electroni protsess kui ka bittorrenti klient: + +```bash +yarn dev +``` + +## Kompileerimine + +### Bittorrenti kliendi kompileerimine + +Kompileeri bittorrenti klient kasutades järgmist käsku: + +```bash +python torrent-client/setup.py build +``` + +### Electron rakenduse kompileerimine + +Kompileeri Electron rakendus kasutades järgmist käsku: + +Windowsil: + +```bash +yarn build:win +``` + +Linuxil: + +```bash +yarn build:linux +``` + +## Panustajad + + + + + +## Litsents + +Hydra on litsentseeritud [MIT Litsentsi](LICENSE) all. diff --git a/docs/README.fr.md b/docs/README.fr.md index 648c30ea..0c35e059 100644 --- a/docs/README.fr.md +++ b/docs/README.fr.md @@ -25,6 +25,7 @@ [![cs](https://img.shields.io/badge/lang-cs-purple)](README.cs.md) [![da](https://img.shields.io/badge/lang-da-red)](README.da.md) [![nb](https://img.shields.io/badge/lang-nb-blue)](README.nb.md) +[![et](https://img.shields.io/badge/lang-et-blue.svg)](README.et.md) ![Catalogue Hydra](./screenshot.png) diff --git a/docs/README.it.md b/docs/README.it.md index 656a9aac..e87cf28e 100644 --- a/docs/README.it.md +++ b/docs/README.it.md @@ -25,6 +25,7 @@ [![cs](https://img.shields.io/badge/lang-cs-purple)](README.cs.md) [![da](https://img.shields.io/badge/lang-da-red)](README.da.md) [![nb](https://img.shields.io/badge/lang-nb-blue)](README.nb.md) +[![et](https://img.shields.io/badge/lang-et-blue.svg)](README.et.md) ![Hydra Catalogue](./screenshot.png) diff --git a/docs/README.nb.md b/docs/README.nb.md index 62f04781..1ec4744b 100644 --- a/docs/README.nb.md +++ b/docs/README.nb.md @@ -24,6 +24,7 @@ [![ita](https://img.shields.io/badge/lang-it-red)](README.it.md) [![cs](https://img.shields.io/badge/lang-cs-purple)](README.cs.md) [![nb](https://img.shields.io/badge/lang-nb-blue)](README.nb.md) +[![et](https://img.shields.io/badge/lang-et-blue.svg)](README.et.md) ![Hydra Catalogue](./screenshot.png) diff --git a/docs/README.pl.md b/docs/README.pl.md index 2ee4e847..2fb31a6d 100644 --- a/docs/README.pl.md +++ b/docs/README.pl.md @@ -25,6 +25,7 @@ [![cs](https://img.shields.io/badge/lang-cs-purple)](README.cs.md) [![da](https://img.shields.io/badge/lang-da-red)](README.da.md) [![nb](https://img.shields.io/badge/lang-nb-blue)](README.nb.md) +[![et](https://img.shields.io/badge/lang-et-blue.svg)](README.et.md) ![Hydra Catalogue](./screenshot.png) diff --git a/docs/README.pt-BR.md b/docs/README.pt-BR.md index 83f0c420..7a2971c8 100644 --- a/docs/README.pt-BR.md +++ b/docs/README.pt-BR.md @@ -25,6 +25,7 @@ [![cs](https://img.shields.io/badge/lang-cs-purple)](README.cs.md) [![da](https://img.shields.io/badge/lang-da-red)](README.da.md) [![nb](https://img.shields.io/badge/lang-nb-blue)](README.nb.md) +[![et](https://img.shields.io/badge/lang-et-blue.svg)](README.et.md) ![Hydra Catalogue](./screenshot.png) diff --git a/docs/README.ru.md b/docs/README.ru.md index 6c0a6a0f..1ce831f7 100644 --- a/docs/README.ru.md +++ b/docs/README.ru.md @@ -25,6 +25,7 @@ [![cs](https://img.shields.io/badge/lang-cs-purple)](README.cs.md) [![da](https://img.shields.io/badge/lang-da-red)](README.da.md) [![nb](https://img.shields.io/badge/lang-nb-blue)](README.nb.md) +[![et](https://img.shields.io/badge/lang-et-blue.svg)](README.et.md) ![Hydra Catalogue](./screenshot.png) diff --git a/docs/README.uk-UA.md b/docs/README.uk-UA.md index db2f2c12..8fec8508 100644 --- a/docs/README.uk-UA.md +++ b/docs/README.uk-UA.md @@ -25,6 +25,7 @@ [![cs](https://img.shields.io/badge/lang-cs-purple)](README.cs.md) [![da](https://img.shields.io/badge/lang-da-red)](README.da.md) [![nb](https://img.shields.io/badge/lang-nb-blue)](README.nb.md) +[![et](https://img.shields.io/badge/lang-et-blue.svg)](README.et.md) ![Hydra Catalogue](./screenshot.png) diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 3ce8b3af..21082e59 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -41,7 +41,7 @@ "bottom_panel": { "no_downloads_in_progress": "No downloads in progress", "downloading_metadata": "Downloading {{title}} metadata…", - "downloading": "Downloading {{title}}… ({{percentage}} complete) - Conclusion {{eta}} - {{speed}}", + "downloading": "Downloading {{title}}… ({{percentage}} complete) - Completion {{eta}} - {{speed}}", "calculating_eta": "Downloading {{title}}… ({{percentage}} complete) - Calculating remaining time…", "checking_files": "Checking {{title}} files… ({{percentage}} complete)" }, @@ -358,7 +358,7 @@ "user_achievements": "{{displayName}}'s Achievements", "your_achievements": "Your Achievements", "unlocked_at": "Unlocked at:", - "subscription_needed": "A Hydra Cloud subscription is needed to see this content", + "subscription_needed": "A Hydra Cloud subscription is required to see this content", "new_achievements_unlocked": "Unlocked {{achievementCount}} new achievements from {{gameCount}} games" }, "tour": { diff --git a/src/locales/et/translation.json b/src/locales/et/translation.json new file mode 100644 index 00000000..04a47e30 --- /dev/null +++ b/src/locales/et/translation.json @@ -0,0 +1,459 @@ +{ + "language_name": "Eesti", + "app": { + "successfully_signed_in": "Edukalt sisse logitud" + }, + "home": { + "featured": "Esile toodud", + "trending": "Populaarne", + "surprise_me": "Üllata mind", + "no_results": "Tulemusi ei leitud", + "start_typing": "Alusta otsimiseks kirjutamist...", + "hot": "Praegu kuum", + "weekly": "📅 Nädala top mängud" + }, + "sidebar": { + "catalogue": "Kataloog", + "downloads": "Allalaadimised", + "settings": "Seaded", + "my_library": "Minu kogu", + "downloading_metadata": "{{title}} (Metaandmete allalaadimine…)", + "paused": "{{title}} (Peatatud)", + "downloading": "{{title}} ({{percentage}} - Allalaadimine…)", + "filter": "Filtreeri kogu", + "home": "Avaleht", + "queued": "{{title}} (Järjekorras)", + "game_has_no_executable": "Mängul pole käivitusfaili valitud", + "sign_in": "Logi sisse", + "friends": "Sõbrad" + }, + "header": { + "search": "Otsi mänge", + "home": "Avaleht", + "catalogue": "Kataloog", + "downloads": "Allalaadimised", + "search_results": "Otsingutulemused", + "settings": "Seaded", + "version_available_install": "Versioon {{version}} on saadaval. Klõpsa siia taaskäivitamiseks ja installimiseks.", + "version_available_download": "Versioon {{version}} on saadaval. Klõpsa siia allalaadimiseks." + }, + "bottom_panel": { + "no_downloads_in_progress": "Allalaadimisi pole pooleli", + "downloading_metadata": "{{title}} metaandmete allalaadimine…", + "downloading": "{{title}} allalaadimine… ({{percentage}} valmis) - Lõpp {{eta}} - {{speed}}", + "calculating_eta": "{{title}} allalaadimine… ({{percentage}} valmis) - Järelejäänud aja arvutamine…", + "checking_files": "{{title}} failide kontrollimine… ({{percentage}} valmis)" + }, + "catalogue": { + "next_page": "Järgmine leht", + "previous_page": "Eelmine leht" + }, + "game_details": { + "open_download_options": "Ava allalaadimise valikud", + "download_options_zero": "Allalaadimise valikuid pole", + "download_options_one": "{{count}} allalaadimise valik", + "download_options_other": "{{count}} allalaadimise valikut", + "updated_at": "Uuendatud {{updated_at}}", + "install": "Installi", + "resume": "Jätka", + "pause": "Peata", + "cancel": "Tühista", + "remove": "Eemalda", + "space_left_on_disk": "{{space}} kettaruumi järel", + "eta": "Lõpp {{eta}}", + "calculating_eta": "Järelejäänud aja arvutamine…", + "downloading_metadata": "Metaandmete allalaadimine…", + "filter": "Filtreeri repacke", + "requirements": "Süsteeminõuded", + "minimum": "Miinimum", + "recommended": "Soovitatav", + "paused": "Peatatud", + "release_date": "Välja antud {{date}}", + "publisher": "Avaldaja {{publisher}}", + "hours": "tundi", + "minutes": "minutit", + "amount_hours": "{{amount}} tundi", + "amount_minutes": "{{amount}} minutit", + "accuracy": "{{accuracy}}% täpsus", + "add_to_library": "Lisa kogusse", + "remove_from_library": "Eemalda kogust", + "no_downloads": "Allalaadimisi pole saadaval", + "play_time": "Mängitud {{amount}}", + "last_time_played": "Viimati mängitud {{period}}", + "not_played_yet": "Sa pole veel {{title}} mänginud", + "next_suggestion": "Järgmine soovitus", + "play": "Mängi", + "deleting": "Installeri kustutamine…", + "close": "Sulge", + "playing_now": "Mängib praegu", + "change": "Muuda", + "repacks_modal_description": "Vali repack, mida soovid alla laadida", + "select_folder_hint": "Vaikimisi kausta muutmiseks mine <0>Seadetesse", + "download_now": "Laadi alla kohe", + "no_shop_details": "Poe andmeid ei õnnestunud laadida.", + "download_options": "Allalaadimise valikud", + "download_path": "Allalaadimise tee", + "previous_screenshot": "Eelmine kuvatõmmis", + "next_screenshot": "Järgmine kuvatõmmis", + "screenshot": "Kuvatõmmis {{number}}", + "open_screenshot": "Ava kuvatõmmis {{number}}", + "download_settings": "Allalaadimise seaded", + "downloader": "Allalaadija", + "select_executable": "Vali", + "no_executable_selected": "Käivitusfaili pole valitud", + "open_folder": "Ava kaust", + "open_download_location": "Vaata allalaaditud faile", + "create_shortcut": "Loo töölaua otsetee", + "remove_files": "Eemalda failid", + "remove_from_library_title": "Oled sa kindel?", + "remove_from_library_description": "See eemaldab {{game}} sinu kogust", + "options": "Valikud", + "executable_section_title": "Käivitusfail", + "executable_section_description": "Faili tee, mida käivitatakse \"Mängi\" nupule vajutades", + "downloads_secion_title": "Allalaadimised", + "downloads_section_description": "Vaata uuendusi või selle mängu teisi versioone", + "danger_zone_section_title": "Ohutsoon", + "danger_zone_section_description": "Eemalda see mäng oma kogust või Hydra poolt allalaaditud failid", + "download_in_progress": "Allalaadimine käimas", + "download_paused": "Allalaadimine peatatud", + "last_downloaded_option": "Viimane allalaaditud variant", + "create_shortcut_success": "Otsetee edukalt loodud", + "create_shortcut_error": "Viga otsetee loomisel", + "nsfw_content_title": "See mäng sisaldab sobimatut sisu", + "nsfw_content_description": "{{title}} sisaldab sisu, mis ei pruugi sobida kõigile vanusegruppidele. Kas soovid kindlasti jätkata?", + "allow_nsfw_content": "Jätka", + "refuse_nsfw_content": "Mine tagasi", + "stats": "Statistika", + "download_count": "Allalaadimised", + "player_count": "Aktiivsed mängijad", + "download_error": "See allalaadimise valik pole saadaval", + "download": "Laadi alla", + "executable_path_in_use": "Käivitusfail on juba kasutusel mängus \"{{game}}\"", + "warning": "Hoiatus:", + "hydra_needs_to_remain_open": "selle allalaadimise jaoks peab Hydra jääma avatuks kuni lõpuni. Kui Hydra sulgub enne lõppu, kaotad oma progressi.", + "achievements": "Saavutused", + "achievements_count": "Saavutused {{unlockedCount}}/{{achievementsCount}}", + "cloud_save": "Pilvesalvestus", + "cloud_save_description": "Salvesta oma progress pilve ja jätka mängimist mistahes seadmes", + "backups": "Varundused", + "install_backup": "Installi", + "delete_backup": "Kustuta", + "create_backup": "Uus varundus", + "last_backup_date": "Viimane varundus {{date}}", + "no_backup_preview": "Selle mängu jaoks ei leitud salvestusi", + "restoring_backup": "Varunduse taastamine ({{progress}} valmis)…", + "uploading_backup": "Varunduse üleslaadimine…", + "no_backups": "Sa pole veel selle mängu jaoks varundusi loonud", + "backup_uploaded": "Varundus üles laaditud", + "backup_deleted": "Varundus kustutatud", + "backup_restored": "Varundus taastatud", + "see_all_achievements": "Vaata kõiki saavutusi", + "sign_in_to_see_achievements": "Logi sisse, et näha saavutusi", + "mapping_method_automatic": "Automaatne", + "mapping_method_manual": "Käsitsi", + "mapping_method_label": "Kaardistamise meetod", + "files_automatically_mapped": "Failid automaatselt kaardistatud", + "no_backups_created": "Selle mängu jaoks pole varundusi loodud", + "manage_files": "Halda faile", + "loading_save_preview": "Salvestuste otsimine…", + "wine_prefix": "Wine Prefix", + "wine_prefix_description": "Wine prefix, mida kasutatakse selle mängu käivitamiseks", + "no_download_option_info": "Info pole saadaval", + "backup_deletion_failed": "Varunduse kustutamine ebaõnnestus", + "max_number_of_artifacts_reached": "Selle mängu varunduste maksimaalne arv on saavutatud", + "achievements_not_sync": "Sinu saavutused pole sünkroniseeritud" + }, + "activation": { + "title": "Aktiveeri Hydra", + "installation_id": "Installatsiooni ID:", + "enter_activation_code": "Sisesta oma aktiveerimiskood", + "message": "Kui sa ei tea, kust seda küsida, siis sa ei peaks seda omama.", + "activate": "Aktiveeri", + "loading": "Laadimine…" + }, + "downloads": { + "resume": "Jätka", + "pause": "Peata", + "eta": "Lõpp {{eta}}", + "paused": "Peatatud", + "verifying": "Kontrollimine…", + "completed": "Lõpetatud", + "removed": "Pole alla laaditud", + "cancel": "Tühista", + "filter": "Filtreeri allalaaditud mänge", + "remove": "Eemalda", + "downloading_metadata": "Metaandmete allalaadimine…", + "deleting": "Installeri kustutamine…", + "delete": "Eemalda installer", + "delete_modal_title": "Oled sa kindel?", + "delete_modal_description": "See eemaldab kõik installifailid sinu arvutist", + "install": "Installi", + "download_in_progress": "Töös", + "queued_downloads": "Järjekorras allalaadimised", + "downloads_completed": "Lõpetatud", + "queued": "Järjekorras", + "no_downloads_title": "Nii tühi", + "no_downloads_description": "Sa pole veel Hydraga midagi alla laadinud, aga pole kunagi hilja alustada.", + "checking_files": "Failide kontrollimine…" + }, + "settings": { + "downloads_path": "Allalaadimiste tee", + "change": "Uuenda", + "notifications": "Teavitused", + "enable_download_notifications": "Kui allalaadimine on lõpetatud", + "enable_repack_list_notifications": "Kui uus repack on lisatud", + "real_debrid_api_token_label": "Real-Debrid API võti", + "quit_app_instead_hiding": "Ära peida Hydrat sulgemisel", + "launch_with_system": "Käivita Hydra süsteemi käivitamisel", + "general": "Üldine", + "behavior": "Käitumine", + "download_sources": "Allalaadimise allikad", + "language": "Keel", + "real_debrid_api_token": "API Võti", + "enable_real_debrid": "Luba Real-Debrid", + "real_debrid_description": "Real-Debrid on piiranguteta allalaadija, mis võimaldab sul faile alla laadida koheselt ja sinu internetiühenduse parima kiirusega.", + "real_debrid_invalid_token": "Vigane API võti", + "real_debrid_api_token_hint": "Sa saad oma API võtme <0>siit", + "real_debrid_free_account_error": "Konto \"{{username}}\" on tasuta konto. Palun telli Real-Debrid", + "real_debrid_linked_message": "Konto \"{{username}}\" ühendatud", + "save_changes": "Salvesta muudatused", + "changes_saved": "Muudatused edukalt salvestatud", + "download_sources_description": "Hydra laeb allalaadimise lingid nendest allikatest. Allika URL peab olema otsene link .json failile, mis sisaldab allalaadimise linke.", + "validate_download_source": "Valideeri", + "remove_download_source": "Eemalda", + "add_download_source": "Lisa allikas", + "download_count_zero": "Allalaadimise valikuid pole", + "download_count_one": "{{countFormatted}} allalaadimise valik", + "download_count_other": "{{countFormatted}} allalaadimise valikut", + "download_source_url": "Allalaadimise allika URL", + "add_download_source_description": "Sisesta URL, mis sisaldab .json faili", + "download_source_up_to_date": "Ajakohane", + "download_source_errored": "Vigane", + "sync_download_sources": "Sünkroniseeri allikad", + "removed_download_source": "Allalaadimise allikas eemaldatud", + "added_download_source": "Allalaadimise allikas lisatud", + "download_sources_synced": "Kõik allalaadimise allikad on sünkroniseeritud", + "insert_valid_json_url": "Sisesta kehtiv JSON url", + "found_download_option_zero": "Allalaadimise valikuid ei leitud", + "found_download_option_one": "Leitud {{countFormatted}} allalaadimise valik", + "found_download_option_other": "Leitud {{countFormatted}} allalaadimise valikut", + "import": "Impordi", + "public": "Avalik", + "private": "Privaatne", + "friends_only": "Ainult sõpradele", + "privacy": "Privaatsus", + "profile_visibility": "Profiili nähtavus", + "profile_visibility_description": "Vali, kes saavad näha sinu profiili ja kogu", + "required_field": "See väli on kohustuslik", + "source_already_exists": "See allikas on juba lisatud", + "must_be_valid_url": "Allikas peab olema kehtiv URL", + "blocked_users": "Blokeeritud kasutajad", + "user_unblocked": "Kasutaja blokeering on eemaldatud", + "enable_achievement_notifications": "Kui saavutus avatakse" + }, + "activation": { + "title": "Aktiveeri Hydra", + "installation_id": "Installatsiooni ID:", + "enter_activation_code": "Sisesta oma aktiveerimiskood", + "message": "Kui sa ei tea, kust seda küsida, siis sa ei peaks seda omama.", + "activate": "Aktiveeri", + "loading": "Laadimine…" + }, + "downloads": { + "resume": "Jätka", + "pause": "Peata", + "eta": "Lõpp {{eta}}", + "paused": "Peatatud", + "verifying": "Kontrollimine…", + "completed": "Lõpetatud", + "removed": "Pole alla laaditud", + "cancel": "Tühista", + "filter": "Filtreeri allalaaditud mänge", + "remove": "Eemalda", + "downloading_metadata": "Metaandmete allalaadimine…", + "deleting": "Installeri kustutamine…", + "delete": "Eemalda installer", + "delete_modal_title": "Oled sa kindel?", + "delete_modal_description": "See eemaldab kõik installifailid sinu arvutist", + "install": "Installi", + "download_in_progress": "Töös", + "queued_downloads": "Järjekorras allalaadimised", + "downloads_completed": "Lõpetatud", + "queued": "Järjekorras", + "no_downloads_title": "Nii tühi", + "no_downloads_description": "Sa pole veel Hydraga midagi alla laadinud, aga pole kunagi hilja alustada.", + "checking_files": "Failide kontrollimine…" + }, + "settings": { + "downloads_path": "Allalaadimiste tee", + "change": "Uuenda", + "notifications": "Teavitused", + "enable_download_notifications": "Kui allalaadimine on lõpetatud", + "enable_repack_list_notifications": "Kui uus repack on lisatud", + "real_debrid_api_token_label": "Real-Debrid API võti", + "quit_app_instead_hiding": "Ära peida Hydrat sulgemisel", + "launch_with_system": "Käivita Hydra süsteemi käivitamisel", + "general": "Üldine", + "behavior": "Käitumine", + "download_sources": "Allalaadimise allikad", + "language": "Keel", + "real_debrid_api_token": "API Võti", + "enable_real_debrid": "Luba Real-Debrid", + "real_debrid_description": "Real-Debrid on piiranguteta allalaadija, mis võimaldab sul faile alla laadida koheselt ja sinu internetiühenduse parima kiirusega.", + "real_debrid_invalid_token": "Vigane API võti", + "real_debrid_api_token_hint": "Sa saad oma API võtme <0>siit", + "real_debrid_free_account_error": "Konto \"{{username}}\" on tasuta konto. Palun telli Real-Debrid", + "real_debrid_linked_message": "Konto \"{{username}}\" ühendatud", + "save_changes": "Salvesta muudatused", + "changes_saved": "Muudatused edukalt salvestatud", + "download_sources_description": "Hydra laeb allalaadimise lingid nendest allikatest. Allika URL peab olema otsene link .json failile, mis sisaldab allalaadimise linke.", + "validate_download_source": "Valideeri", + "remove_download_source": "Eemalda", + "add_download_source": "Lisa allikas", + "download_count_zero": "Allalaadimise valikuid pole", + "download_count_one": "{{countFormatted}} allalaadimise valik", + "download_count_other": "{{countFormatted}} allalaadimise valikut", + "download_source_url": "Allalaadimise allika URL", + "add_download_source_description": "Sisesta URL, mis sisaldab .json faili", + "download_source_up_to_date": "Ajakohane", + "download_source_errored": "Vigane", + "sync_download_sources": "Sünkroniseeri allikad", + "removed_download_source": "Allalaadimise allikas eemaldatud", + "added_download_source": "Allalaadimise allikas lisatud", + "download_sources_synced": "Kõik allalaadimise allikad on sünkroniseeritud", + "insert_valid_json_url": "Sisesta kehtiv JSON url", + "found_download_option_zero": "Allalaadimise valikuid ei leitud", + "found_download_option_one": "Leitud {{countFormatted}} allalaadimise valik", + "found_download_option_other": "Leitud {{countFormatted}} allalaadimise valikut", + "import": "Impordi", + "public": "Avalik", + "private": "Privaatne", + "friends_only": "Ainult sõpradele", + "privacy": "Privaatsus", + "profile_visibility": "Profiili nähtavus", + "profile_visibility_description": "Vali, kes saavad näha sinu profiili ja kogu", + "required_field": "See väli on kohustuslik", + "source_already_exists": "See allikas on juba lisatud", + "must_be_valid_url": "Allikas peab olema kehtiv URL", + "blocked_users": "Blokeeritud kasutajad", + "user_unblocked": "Kasutaja blokeering on eemaldatud", + "enable_achievement_notifications": "Kui saavutus avatakse" + }, + "notifications": { + "download_complete": "Allalaadimine lõpetatud", + "game_ready_to_install": "{{title}} on valmis installimiseks", + "repack_list_updated": "Repackide nimekiri uuendatud", + "repack_count_one": "{{count}} repack lisatud", + "repack_count_other": "{{count}} repacki lisatud", + "new_update_available": "Versioon {{version}} saadaval", + "restart_to_install_update": "Taaskäivita Hydra uuenduse installimiseks", + "notification_achievement_unlocked_title": "Saavutus avatud mängus {{game}}", + "notification_achievement_unlocked_body": "{{achievement}} ja veel {{count}} avati" + }, + "system_tray": { + "open": "Ava Hydra", + "quit": "Välju" + }, + "game_card": { + "no_downloads": "Allalaadimisi pole saadaval" + }, + "binary_not_found_modal": { + "title": "Programmid pole installitud", + "description": "Wine või Lutrise käivitusfaile ei leitud sinu süsteemist", + "instructions": "Kontrolli õiget viisi nende installimiseks oma Linuxi distrol, et mäng saaks normaalselt töötada" + }, + "modal": { + "close": "Sulgemise nupp" + }, + "forms": { + "toggle_password_visibility": "Lülita parooli nähtavust" + }, + "user_profile": { + "amount_hours": "{{amount}} tundi", + "amount_minutes": "{{amount}} minutit", + "last_time_played": "Viimati mängitud {{period}}", + "activity": "Hiljutine aktiivsus", + "library": "Kogu", + "total_play_time": "Kogu mängitud aeg: {{amount}}", + "no_recent_activity_title": "Hmmm… siin pole midagi", + "no_recent_activity_description": "Sa pole hiljuti ühtegi mängu mänginud. On aeg seda muuta!", + "display_name": "Kuvatav nimi", + "saving": "Salvestamine", + "save": "Salvesta", + "edit_profile": "Muuda profiili", + "saved_successfully": "Edukalt salvestatud", + "try_again": "Palun proovi uuesti", + "sign_out_modal_title": "Oled sa kindel?", + "cancel": "Tühista", + "successfully_signed_out": "Edukalt välja logitud", + "sign_out": "Logi välja", + "playing_for": "Mängib {{amount}}", + "sign_out_modal_text": "Sinu kogu on seotud sinu praeguse kontoga. Välja logides pole sinu kogu enam nähtav ja edasist progressi ei salvestata. Jätkata väljalogimisega?", + "add_friends": "Lisa sõpru", + "add": "Lisa", + "friend_code": "Sõbrakood", + "see_profile": "Vaata profiili", + "sending": "Saatmine", + "friend_request_sent": "Sõbrakutse saadetud", + "friends": "Sõbrad", + "friends_list": "Sõbrade nimekiri", + "user_not_found": "Kasutajat ei leitud", + "block_user": "Blokeeri kasutaja", + "add_friend": "Lisa sõbraks", + "request_sent": "Kutse saadetud", + "request_received": "Kutse saadud", + "accept_request": "Võta kutse vastu", + "ignore_request": "Ignoreeri kutset", + "cancel_request": "Tühista kutse", + "undo_friendship": "Tühista sõprus", + "request_accepted": "Kutse vastu võetud", + "user_blocked_successfully": "Kasutaja edukalt blokeeritud", + "user_block_modal_text": "See blokeerib kasutaja {{displayName}}", + "blocked_users": "Blokeeritud kasutajad", + "unblock": "Eemalda blokeering", + "no_friends_added": "Sul pole veel lisatud sõpru", + "pending": "Ootel", + "no_pending_invites": "Sul pole ootel kutseid", + "no_blocked_users": "Sul pole blokeeritud kasutajaid", + "friend_code_copied": "Sõbrakood kopeeritud", + "undo_friendship_modal_text": "See tühistab sinu sõpruse kasutajaga {{displayName}}", + "privacy_hint": "Et muuta, kes seda näevad, mine <0>Seadetesse", + "locked_profile": "See profiil on privaatne", + "image_process_failure": "Viga pildi töötlemisel", + "required_field": "See väli on kohustuslik", + "displayname_min_length": "Kuvatav nimi peab olema vähemalt 3 tähemärki pikk", + "displayname_max_length": "Kuvatav nimi võib olla maksimaalselt 50 tähemärki pikk", + "report_profile": "Teata sellest profiilist", + "report_reason": "Miks sa sellest profiilist teatad?", + "report_description": "Lisainfo", + "report_description_placeholder": "Lisainfo", + "report": "Teata", + "report_reason_hate": "Vaenukõne", + "report_reason_sexual_content": "Seksuaalne sisu", + "report_reason_violence": "Vägivald", + "report_reason_spam": "Rämpspost", + "report_reason_other": "Muu", + "profile_reported": "Profiilist teatatud", + "your_friend_code": "Sinu sõbrakood:", + "upload_banner": "Lae üles bänner", + "uploading_banner": "Bänneri üleslaadimine…" + }, + "achievement": { + "achievement_unlocked": "Saavutus avatud", + "user_achievements": "{{displayName}} saavutused", + "your_achievements": "Sinu saavutused", + "unlocked_at": "Avatud:", + "subscription_needed": "Selle sisu nägemiseks on vaja Hydra Cloud tellimust", + "new_achievements_unlocked": "Avatud {{achievementCount}} uut saavutust {{gameCount}} mängust" + }, + "tour": { + "subscription_tour_title": "Hydra Cloud Tellimus", + "subscribe_now": "Telli kohe", + "cloud_saving": "Pilvesalvestus (kuni {{gameCount}} mängu)", + "cloud_achievements": "Salvesta oma saavutused pilve", + "animated_profile_picture": "Animeeritud profiilipildid", + "premium_support": "Premium tugi", + "show_and_compare_achievements": "Näita ja võrdle oma saavutusi teiste kasutajatega", + "animated_profile_banner": "Animeeritud profiilibänner" + } +} diff --git a/src/locales/index.ts b/src/locales/index.ts index 8b5f9d9a..26d15b61 100644 --- a/src/locales/index.ts +++ b/src/locales/index.ts @@ -23,6 +23,7 @@ import ca from "./ca/translation.json"; import kk from "./kk/translation.json"; import cs from "./cs/translation.json"; import nb from "./nb/translation.json"; +import et from "./et/translation.json"; export default { "pt-BR": ptBR, @@ -50,4 +51,5 @@ export default { kk, cs, nb, + et, }; diff --git a/src/locales/pt-BR/translation.json b/src/locales/pt-BR/translation.json index c79c0847..e71668e8 100644 --- a/src/locales/pt-BR/translation.json +++ b/src/locales/pt-BR/translation.json @@ -367,6 +367,7 @@ "animated_profile_picture": "Fotos de perfil animadas", "premium_support": "Suporte Premium", "show_and_compare_achievements": "Exiba e compare suas conquistas com outros usuários", - "animated_profile_banner": "Banner animado no perfil" + "animated_profile_banner": "Banner animado no perfil", + "cloud_saving": "Saves na Cloud (até {{gameCount}} jogos)" } } diff --git a/src/main/events/auth/sign-out.ts b/src/main/events/auth/sign-out.ts index 724626b7..ed399f6d 100644 --- a/src/main/events/auth/sign-out.ts +++ b/src/main/events/auth/sign-out.ts @@ -7,7 +7,7 @@ import { gamesPlaytime, } from "@main/services"; import { dataSource } from "@main/data-source"; -import { DownloadQueue, Game, UserAuth } from "@main/entity"; +import { DownloadQueue, Game, UserAuth, UserSubscription } from "@main/entity"; const signOut = async (_event: Electron.IpcMainInvokeEvent) => { const databaseOperations = dataSource @@ -19,6 +19,10 @@ const signOut = async (_event: Electron.IpcMainInvokeEvent) => { await transactionalEntityManager .getRepository(UserAuth) .delete({ id: 1 }); + + await transactionalEntityManager + .getRepository(UserSubscription) + .delete({ id: 1 }); }) .then(() => { /* Removes all games being played */ diff --git a/src/main/events/profile/get-me.ts b/src/main/events/profile/get-me.ts index 8ab78bf9..4f34ca32 100644 --- a/src/main/events/profile/get-me.ts +++ b/src/main/events/profile/get-me.ts @@ -1,43 +1,11 @@ import { registerEvent } from "../register-event"; -import { logger } from "@main/services"; -import type { ProfileVisibility, UserDetails } from "@types"; -import { userAuthRepository } from "@main/repository"; -import { UserNotLoggedInError } from "@shared"; +import type { UserDetails } from "@types"; import { getUserData } from "@main/services/user/get-user-data"; const getMe = async ( _event: Electron.IpcMainInvokeEvent ): Promise => { - return getUserData().catch(async (err) => { - if (err instanceof UserNotLoggedInError) { - return null; - } - logger.error("Failed to get logged user", err); - const loggedUser = await userAuthRepository.findOne({ where: { id: 1 } }); - - if (loggedUser) { - return { - ...loggedUser, - id: loggedUser.userId, - username: "", - bio: "", - profileVisibility: "PUBLIC" as ProfileVisibility, - subscription: loggedUser.subscription - ? { - id: loggedUser.subscription.subscriptionId, - status: loggedUser.subscription.status, - plan: { - id: loggedUser.subscription.planId, - name: loggedUser.subscription.planName, - }, - expiresAt: loggedUser.subscription.expiresAt, - } - : null, - }; - } - - return null; - }); + return getUserData(); }; registerEvent("getMe", getMe); diff --git a/src/main/main.ts b/src/main/main.ts index a680c824..69bc62e0 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -12,7 +12,6 @@ import { UserPreferences } from "./entity"; import { RealDebridClient } from "./services/real-debrid"; import { HydraApi } from "./services/hydra-api"; import { uploadGamesBatch } from "./services/library-sync"; -import { getUserData } from "./services/user/get-user-data"; const loadState = async (userPreferences: UserPreferences | null) => { import("./events"); @@ -23,8 +22,7 @@ const loadState = async (userPreferences: UserPreferences | null) => { Ludusavi.addManifestToLudusaviConfig(); - await HydraApi.setupApi().then(async () => { - await getUserData().catch(() => {}); + HydraApi.setupApi().then(() => { uploadGamesBatch(); }); diff --git a/src/main/services/achievements/find-achivement-files.ts b/src/main/services/achievements/find-achivement-files.ts index 9195c13a..85c5b767 100644 --- a/src/main/services/achievements/find-achivement-files.ts +++ b/src/main/services/achievements/find-achivement-files.ts @@ -71,6 +71,7 @@ const crackers = [ Cracker.smartSteamEmu, Cracker.empress, Cracker.flt, + Cracker.razor1911, ]; const getPathFromCracker = (cracker: Cracker) => { @@ -221,6 +222,15 @@ const getPathFromCracker = (cracker: Cracker) => { ]; } + if (cracker == Cracker.razor1911) { + return [ + { + folderPath: path.join(appData, ".1911"), + fileLocation: ["achievement"], + }, + ]; + } + achievementsLogger.error(`Cracker ${cracker} not implemented`); throw new Error(`Cracker ${cracker} not implemented`); }; diff --git a/src/main/services/achievements/merge-achievements.ts b/src/main/services/achievements/merge-achievements.ts index b1ae0273..41bf575a 100644 --- a/src/main/services/achievements/merge-achievements.ts +++ b/src/main/services/achievements/merge-achievements.ts @@ -125,7 +125,7 @@ export const mergeAchievements = async ( id: game.remoteId, achievements: mergedLocalAchievements, }, - { needsCloud: true } + { needsSubscription: true } ) .then((response) => { return saveAchievementsOnLocal( diff --git a/src/main/services/achievements/parse-achievement-file.ts b/src/main/services/achievements/parse-achievement-file.ts index 07854935..38b388ca 100644 --- a/src/main/services/achievements/parse-achievement-file.ts +++ b/src/main/services/achievements/parse-achievement-file.ts @@ -65,6 +65,10 @@ export const parseAchievementFile = ( return processCreamAPI(parsed); } + if (type === Cracker.razor1911) { + return processRazor1911(filePath); + } + achievementsLogger.log( `Unprocessed ${type} achievements found on ${filePath}` ); @@ -111,6 +115,35 @@ const jsonParse = (filePath: string) => { } }; +const processRazor1911 = (filePath: string): UnlockedAchievement[] => { + try { + const fileContent = readFileSync(filePath, "utf-8"); + achievementsLogger.log("processing file", filePath, fileContent); + const lines = + fileContent.charCodeAt(0) === 0xfeff + ? fileContent.slice(1).split(/[\r\n]+/) + : fileContent.split(/[\r\n]+/); + + const achievements: UnlockedAchievement[] = []; + for (const line of lines) { + if (!line.length) continue; + + const [name, unlocked, unlockTime] = line.split(" "); + if (unlocked === "1") { + achievements.push({ + name, + unlockTime: Number(unlockTime) * 1000, + }); + } + } + achievementsLogger.log("processing file", achievements); + return achievements; + } catch (err) { + achievementsLogger.error(`Error processing ${filePath}`, err); + return []; + } +}; + const processOnlineFix = (unlockedAchievements: any): UnlockedAchievement[] => { const parsedUnlockedAchievements: UnlockedAchievement[] = []; diff --git a/src/main/services/hydra-api.ts b/src/main/services/hydra-api.ts index ffe2fcb7..41d76408 100644 --- a/src/main/services/hydra-api.ts +++ b/src/main/services/hydra-api.ts @@ -11,10 +11,18 @@ import { logger } from "./logger"; import { UserNotLoggedInError, SubscriptionRequiredError } from "@shared"; import { omit } from "lodash-es"; import { appVersion } from "@main/constants"; +import { getUserData } from "./user/get-user-data"; interface HydraApiOptions { needsAuth?: boolean; - needsCloud?: boolean; + needsSubscription?: boolean; +} + +interface HydraApiUserAuth { + authToken: string; + refreshToken: string; + expirationTimestamp: number; + subscription: { expiresAt: Date | null } | null; } export class HydraApi { @@ -25,27 +33,22 @@ export class HydraApi { private static secondsToMilliseconds = (seconds: number) => seconds * 1000; - private static userAuth = { + private static userAuth: HydraApiUserAuth = { authToken: "", refreshToken: "", expirationTimestamp: 0, + subscription: null, }; private static isLoggedIn() { return this.userAuth.authToken !== ""; } - private static async hasCloudSubscription() { - return userSubscriptionRepository - .findOne({ where: { id: 1 } }) - .then((userSubscription) => { - if (!userSubscription) return false; - - return ( - !userSubscription.expiresAt || - userSubscription!.expiresAt > new Date() - ); - }); + private static hasCloudSubscription() { + return ( + this.userAuth.subscription?.expiresAt && + this.userAuth.subscription.expiresAt > new Date() + ); } static async handleExternalAuth(uri: string) { @@ -67,6 +70,7 @@ export class HydraApi { authToken: accessToken, refreshToken: refreshToken, expirationTimestamp: tokenExpirationTimestamp, + subscription: null, }; logger.log( @@ -84,6 +88,16 @@ export class HydraApi { ["id"] ); + await getUserData().then((userDetails) => { + if (userDetails?.subscription) { + this.userAuth.subscription = { + expiresAt: userDetails.subscription.expiresAt + ? new Date(userDetails.subscription.expiresAt) + : null, + }; + } + }); + if (WindowManager.mainWindow) { WindowManager.mainWindow.webContents.send("on-signin"); await clearGamesRemoteIds(); @@ -96,6 +110,7 @@ export class HydraApi { authToken: "", refreshToken: "", expirationTimestamp: 0, + subscription: null, }; } @@ -161,14 +176,20 @@ export class HydraApi { ); } + await getUserData(); + const userAuth = await userAuthRepository.findOne({ where: { id: 1 }, + relations: { subscription: true }, }); this.userAuth = { authToken: userAuth?.accessToken ?? "", refreshToken: userAuth?.refreshToken ?? "", expirationTimestamp: userAuth?.tokenExpirationTimestamp ?? 0, + subscription: userAuth?.subscription + ? { expiresAt: userAuth.subscription?.expiresAt } + : null, }; } @@ -236,9 +257,11 @@ export class HydraApi { authToken: "", expirationTimestamp: 0, refreshToken: "", + subscription: null, }; userAuthRepository.delete({ id: 1 }); + userSubscriptionRepository.delete({ id: 1 }); this.sendSignOutEvent(); } @@ -248,14 +271,14 @@ export class HydraApi { private static async validateOptions(options?: HydraApiOptions) { const needsAuth = options?.needsAuth == undefined || options.needsAuth; - const needsCloud = options?.needsCloud === true; + const needsSubscription = options?.needsSubscription === true; if (needsAuth) { if (!this.isLoggedIn()) throw new UserNotLoggedInError(); await this.revalidateAccessTokenIfExpired(); } - if (needsCloud) { + if (needsSubscription) { if (!(await this.hasCloudSubscription())) { throw new SubscriptionRequiredError(); } diff --git a/src/main/services/user/get-user-data.ts b/src/main/services/user/get-user-data.ts index 5035b296..c3ca6eb8 100644 --- a/src/main/services/user/get-user-data.ts +++ b/src/main/services/user/get-user-data.ts @@ -1,43 +1,79 @@ -import type { UserDetails } from "@types"; +import type { ProfileVisibility, UserDetails } from "@types"; import { HydraApi } from "../hydra-api"; import { userAuthRepository, userSubscriptionRepository, } from "@main/repository"; import * as Sentry from "@sentry/electron/main"; +import { UserNotLoggedInError } from "@shared"; +import { logger } from "../logger"; export const getUserData = () => { - return HydraApi.get(`/profile/me`).then(async (me) => { - userAuthRepository.upsert( - { - id: 1, - displayName: me.displayName, - profileImageUrl: me.profileImageUrl, - backgroundImageUrl: me.backgroundImageUrl, - userId: me.id, - }, - ["id"] - ); - - if (me.subscription) { - await userSubscriptionRepository.upsert( + return HydraApi.get(`/profile/me`) + .then(async (me) => { + userAuthRepository.upsert( { id: 1, - subscriptionId: me.subscription?.id || "", - status: me.subscription?.status || "", - planId: me.subscription?.plan.id || "", - planName: me.subscription?.plan.name || "", - expiresAt: me.subscription?.expiresAt || null, - user: { id: 1 }, + displayName: me.displayName, + profileImageUrl: me.profileImageUrl, + backgroundImageUrl: me.backgroundImageUrl, + userId: me.id, }, ["id"] ); - } else { - await userSubscriptionRepository.delete({ id: 1 }); - } - Sentry.setUser({ id: me.id, username: me.username }); + if (me.subscription) { + await userSubscriptionRepository.upsert( + { + id: 1, + subscriptionId: me.subscription?.id || "", + status: me.subscription?.status || "", + planId: me.subscription?.plan.id || "", + planName: me.subscription?.plan.name || "", + expiresAt: me.subscription?.expiresAt || null, + user: { id: 1 }, + }, + ["id"] + ); + } else { + await userSubscriptionRepository.delete({ id: 1 }); + } - return me; - }); + Sentry.setUser({ id: me.id, username: me.username }); + + return me; + }) + .catch(async (err) => { + if (err instanceof UserNotLoggedInError) { + return null; + } + logger.error("Failed to get logged user", err); + const loggedUser = await userAuthRepository.findOne({ + where: { id: 1 }, + relations: { subscription: true }, + }); + + if (loggedUser) { + return { + ...loggedUser, + id: loggedUser.userId, + username: "", + bio: "", + profileVisibility: "PUBLIC" as ProfileVisibility, + subscription: loggedUser.subscription + ? { + id: loggedUser.subscription.subscriptionId, + status: loggedUser.subscription.status, + plan: { + id: loggedUser.subscription.planId, + name: loggedUser.subscription.planName, + }, + expiresAt: loggedUser.subscription.expiresAt, + } + : null, + } as UserDetails; + } + + return null; + }); }; diff --git a/src/renderer/src/pages/achievements/achievements-content.tsx b/src/renderer/src/pages/achievements/achievements-content.tsx index aa93bc30..72dfe83f 100644 --- a/src/renderer/src/pages/achievements/achievements-content.tsx +++ b/src/renderer/src/pages/achievements/achievements-content.tsx @@ -42,6 +42,7 @@ interface AchievementSummaryProps { function AchievementSummary({ user, isComparison }: AchievementSummaryProps) { const { t } = useTranslation("achievement"); const { userDetails, hasActiveSubscription } = useUserDetails(); + const { handleClickOpenCheckout } = useContext(gameDetailsContext); const getProfileImage = ( user: Pick @@ -90,7 +91,12 @@ function AchievementSummary({ user, isComparison }: AchievementSummaryProps) { >

- {t("subscription_needed")} +

{ + const playAudio = useCallback(() => { const audio = new Audio(achievementSound); audio.volume = 0.2; - audio.preload = "auto"; - return audio; + audio.play(); }, []); useEffect(() => { @@ -47,14 +46,14 @@ export function AchievementNotification() { }, ]); - audio.play(); + playAudio(); } ); return () => { unsubscribe(); }; - }, [audio]); + }, [playAudio]); useEffect(() => { const unsubscribe = window.electron.onAchievementUnlocked( @@ -63,14 +62,14 @@ export function AchievementNotification() { setAchievements((ach) => ach.concat(achievements)); - audio.play(); + playAudio(); } ); return () => { unsubscribe(); }; - }, [audio]); + }, [playAudio]); const hasAchievementsPending = achievements.length > 0; diff --git a/src/shared/constants.ts b/src/shared/constants.ts index f0f6d2f0..2d313abb 100644 --- a/src/shared/constants.ts +++ b/src/shared/constants.ts @@ -39,4 +39,5 @@ export enum Cracker { _3dm = "3dm", flt = "FLT", rle = "RLE", + razor1911 = "RAZOR1911", } diff --git a/src/types/index.ts b/src/types/index.ts index 41a51e40..7f970d63 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -238,7 +238,7 @@ export interface Subscription { id: string; status: SubscriptionStatus; plan: { id: string; name: string }; - expiresAt: Date | null; + expiresAt: string | null; } export interface UserDetails {