diff --git a/.cursorrules b/.cursorrules
index 0b0c009c..5015ab7e 100644
--- a/.cursorrules
+++ b/.cursorrules
@@ -27,3 +27,11 @@
- Follow TypeScript strict mode conventions
- Use async/await instead of promises when possible
- Prefer named exports over default exports for utilities and services
+
+## Comments
+
+- Keep comments concise and purposeful; avoid verbose explanations.
+- Focus on the "why" or non-obvious context, not restating the code.
+- Prefer self-explanatory naming and structure over excessive comments.
+- Do not comment every line or obvious behavior; remove stale comments.
+- Use docblocks only where they add value (public APIs, complex logic).
diff --git a/.env.example b/.env.example
index 3f914eb3..051d8aa3 100644
--- a/.env.example
+++ b/.env.example
@@ -3,3 +3,4 @@ MAIN_VITE_AUTH_URL=
MAIN_VITE_WS_URL=
RENDERER_VITE_REAL_DEBRID_REFERRAL_ID=
RENDERER_VITE_TORBOX_REFERRAL_CODE=
+MAIN_VITE_LAUNCHER_SUBDOMAIN=
diff --git a/.github/workflows/build-renderer.yml b/.github/workflows/build-renderer.yml
index f7361883..34f7d303 100644
--- a/.github/workflows/build-renderer.yml
+++ b/.github/workflows/build-renderer.yml
@@ -6,23 +6,37 @@ concurrency:
on:
push:
- branches: [main]
+ branches:
+ - release/**
jobs:
build:
runs-on: ubuntu-latest
+ permissions:
+ contents: read
+
+ env:
+ NODE_OPTIONS: --max-old-space-size=4096
+ BRANCH_NAME: ${{ github.ref_name }}
+
steps:
- name: Check out Git repository
uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
- - name: Install Node.js
+ - name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 22.21.0
+ cache: "yarn"
+
+ - name: Enable Corepack (Yarn)
+ run: corepack enable
- name: Install dependencies
- run: yarn --frozen-lockfile --ignore-scripts
+ run: yarn install --frozen-lockfile --ignore-scripts
- name: Build Renderer
run: yarn build
@@ -36,5 +50,5 @@ jobs:
run: |
npx --yes wrangler@3 pages deploy out/renderer \
--project-name="hydra" \
- --commit-dirty=true \
- --branch="main"
+ --branch "$BRANCH_NAME" \
+ --commit-dirty
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 75ff209a..df01b358 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -6,7 +6,8 @@ concurrency:
on:
push:
- branches: [main]
+ branches:
+ - release/**
jobs:
build:
@@ -61,7 +62,7 @@ jobs:
RENDERER_VITE_SENTRY_DSN: ${{ vars.SENTRY_DSN }}
RENDERER_VITE_REAL_DEBRID_REFERRAL_ID: ${{ vars.RENDERER_VITE_REAL_DEBRID_REFERRAL_ID }}
RENDERER_VITE_TORBOX_REFERRAL_CODE: ${{ vars.RENDERER_VITE_TORBOX_REFERRAL_CODE }}
- MAIN_VITE_RENDERER_URL: ${{ vars.MAIN_VITE_RENDERER_URL }}
+ MAIN_VITE_LAUNCHER_SUBDOMAIN: ${{ vars.MAIN_VITE_LAUNCHER_SUBDOMAIN }}
- name: Build Windows
if: matrix.os == 'windows-2022'
@@ -78,7 +79,7 @@ jobs:
RENDERER_VITE_SENTRY_DSN: ${{ vars.SENTRY_DSN }}
RENDERER_VITE_REAL_DEBRID_REFERRAL_ID: ${{ vars.RENDERER_VITE_REAL_DEBRID_REFERRAL_ID }}
RENDERER_VITE_TORBOX_REFERRAL_CODE: ${{ vars.RENDERER_VITE_TORBOX_REFERRAL_CODE }}
- MAIN_VITE_RENDERER_URL: ${{ vars.MAIN_VITE_RENDERER_URL }}
+ MAIN_VITE_LAUNCHER_SUBDOMAIN: ${{ vars.MAIN_VITE_LAUNCHER_SUBDOMAIN }}
- name: Create artifact
uses: actions/upload-artifact@v4
diff --git a/.github/workflows/update-aur.yml b/.github/workflows/update-aur.yml
index 2a3583bc..52fe907e 100644
--- a/.github/workflows/update-aur.yml
+++ b/.github/workflows/update-aur.yml
@@ -98,6 +98,7 @@ jobs:
# Update pkgver in PKGBUILD
cd hydra-launcher-bin
NEW_VERSION="${{ steps.get-version.outputs.version }}"
+ NEW_VERSION="${NEW_VERSION#v}"
echo "Updating PKGBUILD pkgver to $NEW_VERSION"
@@ -137,6 +138,9 @@ jobs:
COMMIT_MSG="v${{ steps.get-version.outputs.version }}"
git commit -m "$COMMIT_MSG"
+
+ export GIT_SSH_COMMAND="ssh -i ~/.ssh/id_rsa -F ~/.ssh/config -o UserKnownHostsFile=$SSH_PATH/known_hosts"
+
git push origin master
echo "Successfully updated AUR package to version ${{ steps.get-version.outputs.version }}"
fi
diff --git a/package.json b/package.json
index 9ed25fa9..5d84e763 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "hydralauncher",
- "version": "3.7.1",
+ "version": "3.7.2",
"description": "Hydra",
"main": "./out/main/index.js",
"author": "Los Broxas",
diff --git a/src/locales/es/translation.json b/src/locales/es/translation.json
index dfa7f7a1..863b8332 100644
--- a/src/locales/es/translation.json
+++ b/src/locales/es/translation.json
@@ -541,7 +541,9 @@
"notification_preview": "Probar notificación de logro",
"debrid": "Debrid",
"debrid_description": "Los servicios Debrid son descargadores premium sin restricciones que te dejan descargar más rápido archivos alojados en servicios de alojamiento siendo que la única limitación es tu velocidad de internet.",
- "enable_friend_start_game_notifications": "Cuando un amigo está jugando un juego"
+ "enable_friend_start_game_notifications": "Cuando un amigo está jugando un juego",
+ "autoplay_trailers_on_game_page": "Reproducir trailers automáticamente en la página del juego",
+ "hide_to_tray_on_game_start": "Ocultar Hydra en la bandeja al iniciar un juego"
},
"notifications": {
"download_complete": "Descarga completada",
diff --git a/src/locales/hu/translation.json b/src/locales/hu/translation.json
index 7d868aee..8aea356b 100644
--- a/src/locales/hu/translation.json
+++ b/src/locales/hu/translation.json
@@ -8,7 +8,7 @@
"no_results": "Nincs találat",
"start_typing": "Kereséshez gépelj...",
"hot": "Most felkapott",
- "weekly": "📅 A hét felkapott játékai",
+ "weekly": "📅 A hét felkapottjai",
"achievements": "🏆 Achievement támogatott"
},
"sidebar": {
@@ -26,7 +26,7 @@
"sign_in": "Bejelentkezés",
"friends": "Barátok",
"need_help": "Elakadtál?",
- "favorites": "Kedvenc játékok",
+ "favorites": "Kedvenc Játékaim",
"playable_button_title": "Csak az azonnal játszható játékokat mutasd",
"add_custom_game_tooltip": "Saját játék hozzáadása",
"show_playable_only_tooltip": "Csak játszható játék mutatása",
@@ -224,7 +224,7 @@
"show_less": "Mutass kevesebbet",
"reviews": "Vélemények",
"leave_a_review": "Hagyd itt a véleményed",
- "write_review_placeholder": "Oszd meg a gondolataid a játékról...",
+ "write_review_placeholder": "Oszd meg gondolatod a játékról...",
"sort_newest": "Legújabb",
"no_reviews_yet": "Még nem lett vélemény megosztva",
"be_first_to_review": "Légy az első, aki megossza a véleményét a játékról!",
@@ -252,7 +252,7 @@
"you_seemed_to_enjoy_this_game": "Úgy látszik élvezted ezt a játékot",
"would_you_recommend_this_game": "Szeretnél véleményt írni erről a játékról?",
"yes": "Igen",
- "maybe_later": "Talán Később",
+ "maybe_later": "Talán később",
"cloud_save": "Mentés felhőben",
"cloud_save_description": "Mentsd el az előrehaladásod a felhőben, majd folytasd egy másik eszközön",
"backups": "Biztonsági másolatok",
@@ -356,13 +356,18 @@
"delete_review_modal_title": "Biztos vagy abban hogy törölni szeretnéd a véleményed?",
"delete_review_modal_description": "Ez a lépés nem vonható vissza.",
"delete_review_modal_delete_button": "Törlés",
- "delete_review_modal_cancel_button": "Mégse"
+ "delete_review_modal_cancel_button": "Mégse",
+ "vote_failed": "A szavazatod nem regisztrálódott. Kérlek próbáld újra.",
+ "show_original": "Eredeti megjelenítése",
+ "show_translation": "Fordítás megjelenítése",
+ "show_original_translated_from": "Eredeti megjelenítése (fordítva: {{language}})",
+ "hide_original": "Eredeti elrejtése"
},
"activation": {
"title": "Hydra Aktiválása",
"installation_id": "Telepítési Azonosító:",
"enter_activation_code": "Írd be az aktiválási kódod",
- "message": "Ha nem tudod hol kérdezz efelől, akkor nem kéne ilyened legyen.",
+ "message": "Ha nem tudod merre kérdezz efelől, akkor nem kéne ilyened legyen.",
"activate": "Aktiválás",
"loading": "Töltés…"
},
@@ -386,7 +391,7 @@
"download_in_progress": "Folyamatban lévő",
"queued_downloads": "Várakozósoron lévő letöltések",
"downloads_completed": "Befejezett",
- "queued": "Várakozási sorban",
+ "queued": "Várakozásban",
"no_downloads_title": "Oly üres..",
"no_downloads_description": "Még nem töltöttél le semmit a Hydra segítségével, de soha nem késő elkezdeni.",
"checking_files": "Fájlok ellenőrzése…",
@@ -419,20 +424,30 @@
"debrid_linked_message": "Fiók összekapcsolva: \"{{username}}\" ",
"save_changes": "Változtatások mentése",
"changes_saved": "Változtatások sikeresen mentve",
- "download_sources_description": "A Hydra lefogja tölteni a letöltési linkeket a forrásokból. Az URL forrásnak közvetlen linknek kell lennie egy .json fájlhoz, ami tartalmazza a linkeket.",
+ "download_sources_description": "A Hydra lefogja tölteni a letöltési linkeket a forrásokból. Az URL Forrásnak közvetlen linknek kell lennie egy .json fájlhoz, ami tartalmazza a linkeket.",
"validate_download_source": "Érvényesítés",
"remove_download_source": "Eltávolítás",
"add_download_source": "Forrás hozáadása",
+ "adding": "Hozzáadás…",
+ "failed_add_download_source": "Letöltési forrás hozzáadása sikertelen. Kérlek próbáld újra.",
+ "download_source_already_exists": "Ez a letöltési forrás URL már létezik.",
"download_count_zero": "Nincs letöltési opció",
"download_count_one": "{{countFormatted}} letöltési opció",
"download_count_other": "{{countFormatted}} letöltési opció",
- "download_source_url": "URL forrás:",
+ "download_source_url": "URL Forrás:",
"add_download_source_description": "Helyezd be a .json fájl URL-jét",
"download_source_up_to_date": "Naprakész",
"download_source_errored": "Hiba történt",
+ "download_source_pending_matching": "Frissítés hamarosan",
+ "download_source_matched": "Naprakész",
+ "download_source_matching": "Frissítés..",
+ "download_source_failed": "Hiba",
+ "download_source_no_information": "Nincs elérhető információ",
"sync_download_sources": "Források szinkronizálása",
"removed_download_source": "Letöltési forrás eltávolítva",
"removed_download_sources": "Letöltési források eltávolítva",
+ "removed_all_download_sources": "Összes letöltési forrás eltávolítva",
+ "download_sources_synced_successfully": "Az összes letöltési forrás szinkronizálva",
"cancel_button_confirmation_delete_all_sources": "Nem",
"confirm_button_confirmation_delete_all_sources": "Igen, törölj mindent",
"title_confirmation_delete_all_sources": "Az összes letöltési forrás törlése",
@@ -445,6 +460,7 @@
"found_download_option_one": "{{countFormatted}} Letöltési opció találva",
"found_download_option_other": "{{countFormatted}} Letöltési opciók találva",
"import": "Importálás",
+ "importing": "Importálás...",
"public": "Publikus",
"private": "Privát",
"friends_only": "Csak barátok",
@@ -462,6 +478,7 @@
"seed_after_download_complete": "Letöltés utáni seedelés",
"show_hidden_achievement_description": "Rejtett achievementek leírásának megjelenítése feloldás előtt",
"account": "Fiók",
+ "hydra_cloud": "Hydra Cloud",
"no_users_blocked": "Nincsenek letiltott felhasználóid",
"subscription_active_until": "Hydra Cloud előfizetésed aktív, eddig: {{date}}",
"manage_subscription": "Előfizetés kezelése",
@@ -498,14 +515,14 @@
"cancel": "Mégsem",
"appearance": "Megjelenés",
"debrid": "Debrid",
- "debrid_description": "A Debrid szolgáltatások prémium szolgáltatások amelyek lehetővé teszik, hogy gyorsan letölts különböző fájltároló szolgáltatásokon tárolt fájlokat, csak az internet sebességed szab határt.",
+ "debrid_description": "A Debrid szolgáltatások prémium szolgáltatások amelyek lehetővé teszik, hogy gyorsan letölts különböző fájltároló szolgáltatásokon tárolt fájlokat, és csak az internet sebességed szab határt.",
"enable_torbox": "TorBox bekapcsolása",
"torbox_description": "A TorBox egy olyan premium seedbox szolgáltatás, amely még a piacon elérhető legjobb szerverekkel is felveszi a versenyt.",
"torbox_account_linked": "TorBox fiók összekapcsolva",
"create_real_debrid_account": "Kattints ide ha még nincs Real-Debrid fiókod",
"create_torbox_account": "Kattints ide ha még nincs TorBox fiókod",
"real_debrid_account_linked": "Real-Debrid fiók összekapcsolva",
- "name_min_length": "A téma neve legalább 3 karakter hosszú legyen",
+ "name_min_length": "A téma neve legalább 3 karakter hosszú kell legyen",
"import_theme": "Téma importálása",
"import_theme_description": "Ezt a témát fogod importálni a Témaáruház-ból: {{theme}}",
"error_importing_theme": "Hiba lépett fel a téma importálása közben",
@@ -535,7 +552,9 @@
"hidden": "Rejtett",
"test_notification": "Értesítés tesztelése",
"notification_preview": "Achievement Értesítés Előnézete",
- "enable_friend_start_game_notifications": "Amikor egy barátod elkezd játszani egy játékot"
+ "enable_friend_start_game_notifications": "Amikor egy barátod elkezd játszani egy játékot",
+ "autoplay_trailers_on_game_page": "Játékelőzetes automatikus lejátszása a játék oldalán",
+ "hide_to_tray_on_game_start": "Hydra elrejtése játék elindításakor a tálcára"
},
"notifications": {
"download_complete": "Letöltés befejezve",
@@ -563,10 +582,10 @@
"available_one": "Elérhető",
"available_other": "Elérhető",
"no_downloads": "Nincs elérhető letöltés",
- "calculating": "Feldolgozás"
+ "calculating": "Számítás alatt.."
},
"binary_not_found_modal": {
- "title": "A programok nincsenek telepítve",
+ "title": "Hiányzó programok",
"description": "Wine vagy Lutris futtatható fájlok nem találhatók a rendszereden",
"instructions": "Ellenőrízd hogy melyiket kell helyesen telepíteni a Linux disztribúciódra, hogy a játék megfelelően fusson"
},
@@ -585,6 +604,7 @@
"activity": "Legutóbbi tevékenység",
"library": "Könyvtár",
"pinned": "Kitűzve",
+ "sort_by": "Rendezés:",
"achievements_earned": "Elért achievementek",
"played_recently": "Nemrég játszva",
"playtime": "Játszottidő",
@@ -654,7 +674,7 @@
"uploading_banner": "Borítókép feltöltése…",
"background_image_updated": "Borítókép frissítve",
"stats": "Statisztikák",
- "achievements": "achievementek",
+ "achievements": "achievement",
"games": "Játékok",
"top_percentile": "Top {{percentile}}%",
"ranking_updated_weekly": "A rangsor hetente frissül.",
@@ -669,7 +689,7 @@
"game_added_to_pinned": "Játék hozzáadva a kitűzöttekhez",
"karma": "Karma",
"karma_count": "karma",
- "karma_description": "Pozitív értékelésekre kapott pontok alapján"
+ "karma_description": "Pozitív értékelésekkel szerzett pontok"
},
"achievement": {
"achievement_unlocked": "Achievement feloldva",
@@ -678,7 +698,7 @@
"unlocked_at": "Feloldva: {{date}}",
"subscription_needed": "A tartalom megtekintéséhez Hydra Cloud előfizetés szükséges",
"new_achievements_unlocked": "{{achievementCount}} új achievement feloldva {{gameCount}} játékban",
- "achievement_progress": "{{unlockedCount}}/{{totalCount}} achievementek",
+ "achievement_progress": "{{unlockedCount}}/{{totalCount}} achievement",
"achievements_unlocked_for_game": "{{achievementCount}} új achievement feloldva itt: {{gameTitle}}",
"hidden_achievement_tooltip": "Ez egy rejtett achievement",
"achievement_earn_points": "Szerezz be {{points}} pontot ezzel az achievement-el",
diff --git a/src/locales/pt-BR/translation.json b/src/locales/pt-BR/translation.json
index c9e908ac..5bfc2af3 100755
--- a/src/locales/pt-BR/translation.json
+++ b/src/locales/pt-BR/translation.json
@@ -538,7 +538,9 @@
"hidden": "Oculta",
"test_notification": "Testar notificação",
"notification_preview": "Prévia da Notificação de Conquistas",
- "enable_friend_start_game_notifications": "Quando um amigo iniciar um jogo"
+ "enable_friend_start_game_notifications": "Quando um amigo iniciar um jogo",
+ "autoplay_trailers_on_game_page": "Reproduzir trailers automaticamente na página do jogo",
+ "hide_to_tray_on_game_start": "Ocultar o Hydra na bandeja ao iniciar um jogo"
},
"notifications": {
"download_complete": "Download concluído",
diff --git a/src/locales/ru/translation.json b/src/locales/ru/translation.json
index 886c7d07..15a9c9cb 100644
--- a/src/locales/ru/translation.json
+++ b/src/locales/ru/translation.json
@@ -212,6 +212,7 @@
"stats": "Статистика",
"download_count": "Загрузки",
"player_count": "Активные игроки",
+ "rating_count": "Оценка",
"download_error": "Этот вариант загрузки недоступен",
"download": "Скачать",
"executable_path_in_use": "Исполняемый файл уже используется \"{{game}}\"",
@@ -252,17 +253,6 @@
"would_you_recommend_this_game": "Хотите оставить отзыв об этой игре?",
"yes": "Да",
"maybe_later": "Возможно позже",
- "rating_count": "Оценка",
- "delete_review": "Удалить отзыв",
- "remove_review": "Удалить отзыв",
- "delete_review_modal_title": "Вы уверены, что хотите удалить свой отзыв?",
- "delete_review_modal_description": "Это действие нельзя отменить.",
- "delete_review_modal_delete_button": "Удалить",
- "delete_review_modal_cancel_button": "Отмена",
- "show_original": "Показать оригинал",
- "show_translation": "Показать перевод",
- "show_original_translated_from": "Показать оригинал (переведено с {{language}})",
- "hide_original": "Скрыть оригинал",
"cloud_save": "Облачное сохранение",
"cloud_save_description": "Сохраняйте ваш прогресс в облаке и продолжайте играть на любом устройстве",
"backups": "Резервные копии",
@@ -360,7 +350,18 @@
"caption": "Субтитры",
"audio": "Аудио",
"filter_by_source": "Фильтр по источнику",
- "no_repacks_found": "Источники для этой игры не найдены"
+ "no_repacks_found": "Источники для этой игры не найдены",
+ "delete_review": "Удалить отзыв",
+ "remove_review": "Удалить отзыв",
+ "delete_review_modal_title": "Вы уверены, что хотите удалить свой отзыв?",
+ "delete_review_modal_description": "Это действие нельзя отменить.",
+ "delete_review_modal_delete_button": "Удалить",
+ "delete_review_modal_cancel_button": "Отмена",
+ "vote_failed": "Не удалось зарегистрировать ваш голос. Пожалуйста, попробуйте снова.",
+ "show_original": "Показать оригинал",
+ "show_translation": "Показать перевод",
+ "show_original_translated_from": "Показать оригинал (переведено с {{language}})",
+ "hide_original": "Скрыть оригинал"
},
"activation": {
"title": "Активировать Hydra",
@@ -427,6 +428,9 @@
"validate_download_source": "Проверить",
"remove_download_source": "Удалить",
"add_download_source": "Добавить источник",
+ "adding": "Добавление…",
+ "failed_add_download_source": "Не удалось добавить источник. Пожалуйста, попробуйте снова.",
+ "download_source_already_exists": "Этот URL источника уже существует.",
"download_count_zero": "В списке нет загрузок",
"download_count_one": "{{countFormatted}} загрузка в списке",
"download_count_other": "{{countFormatted}} загрузок в списке",
@@ -434,9 +438,16 @@
"add_download_source_description": "Вставьте ссылку на .json-файл",
"download_source_up_to_date": "Обновлён",
"download_source_errored": "Ошибка",
+ "download_source_pending_matching": "Скоро обновится",
+ "download_source_matched": "Обновлен",
+ "download_source_matching": "Обновление",
+ "download_source_failed": "Ошибка",
+ "download_source_no_information": "Информация отсутствует",
"sync_download_sources": "Обновить источники",
"removed_download_source": "Источник удален",
"removed_download_sources": "Источники удалены",
+ "removed_all_download_sources": "Все источники удалены",
+ "download_sources_synced_successfully": "Все источники синхронизированы",
"cancel_button_confirmation_delete_all_sources": "Нет",
"confirm_button_confirmation_delete_all_sources": "Да, удалить все",
"title_confirmation_delete_all_sources": "Удалить все источники",
@@ -467,6 +478,7 @@
"seed_after_download_complete": "Раздавать после завершения загрузки",
"show_hidden_achievement_description": "Показывать описание скрытых достижений перед их получением",
"account": "Аккаунт",
+ "hydra_cloud": "Hydra Cloud",
"no_users_blocked": "У вас нет заблокированных пользователей",
"subscription_active_until": "Ваша подписка на Hydra Cloud активна до {{date}}",
"manage_subscription": "Управлять подпиской",
@@ -540,7 +552,9 @@
"hidden": "Скрытый",
"test_notification": "Тестовое уведомление",
"notification_preview": "Предварительный просмотр уведомления о достижении",
- "enable_friend_start_game_notifications": "Когда друг начинает играть в игру"
+ "enable_friend_start_game_notifications": "Когда друг начинает играть в игру",
+ "autoplay_trailers_on_game_page": "Автоматически начинать воспроизведение трейлеров на странице игры",
+ "hide_to_tray_on_game_start": "Скрывать Hydra в трей при запуске игры"
},
"notifications": {
"download_complete": "Загрузка завершена",
@@ -590,6 +604,7 @@
"activity": "Недавняя активность",
"library": "Библиотека",
"pinned": "Закрепленные",
+ "sort_by": "Сортировать по:",
"achievements_earned": "Заработанные достижения",
"played_recently": "Недавно сыгранные",
"playtime": "Время игры",
diff --git a/src/main/services/window-manager.ts b/src/main/services/window-manager.ts
index 118ff98b..673bf1a0 100644
--- a/src/main/services/window-manager.ts
+++ b/src/main/services/window-manager.ts
@@ -25,6 +25,7 @@ import type {
} from "@types";
import { AuthPage, generateAchievementCustomNotificationTest } from "@shared";
import { isStaging } from "@main/constants";
+import { logger } from "./logger";
export class WindowManager {
public static mainWindow: Electron.BrowserWindow | null = null;
@@ -54,21 +55,25 @@ export class WindowManager {
show: false,
};
+ private static formatVersionNumber(version: string) {
+ return version.replaceAll(".", "-");
+ }
+
private static async loadWindowURL(window: BrowserWindow, hash: string = "") {
// HMR for renderer base on electron-vite cli.
// Load the remote URL for development or the local html file for production.
if (is.dev && process.env["ELECTRON_RENDERER_URL"]) {
window.loadURL(`${process.env["ELECTRON_RENDERER_URL"]}#/${hash}`);
- } else if (import.meta.env.MAIN_VITE_RENDERER_URL) {
+ } else if (import.meta.env.MAIN_VITE_LAUNCHER_SUBDOMAIN) {
// Try to load from remote URL in production
try {
await window.loadURL(
- `${import.meta.env.MAIN_VITE_RENDERER_URL}#/${hash}`
+ `https://release-v${this.formatVersionNumber(app.getVersion())}.${import.meta.env.MAIN_VITE_LAUNCHER_SUBDOMAIN}#/${hash}`
);
} catch (error) {
// Fall back to local file if remote URL fails
- console.error(
- "Failed to load from MAIN_VITE_RENDERER_URL, falling back to local file:",
+ logger.error(
+ "Failed to load from MAIN_VITE_LAUNCHER_SUBDOMAIN, falling back to local file:",
error
);
window.loadFile(path.join(__dirname, "../renderer/index.html"), {
diff --git a/src/main/vite-env.d.ts b/src/main/vite-env.d.ts
index c9b006d5..7b0ed536 100644
--- a/src/main/vite-env.d.ts
+++ b/src/main/vite-env.d.ts
@@ -7,7 +7,7 @@ interface ImportMetaEnv {
readonly MAIN_VITE_CHECKOUT_URL: string;
readonly MAIN_VITE_EXTERNAL_RESOURCES_URL: string;
readonly MAIN_VITE_WS_URL: string;
- readonly MAIN_VITE_RENDERER_URL: string;
+ readonly MAIN_VITE_LAUNCHER_SUBDOMAIN: string;
readonly ELECTRON_RENDERER_URL: string;
}
diff --git a/src/renderer/src/pages/catalogue/pagination.tsx b/src/renderer/src/pages/catalogue/pagination.tsx
index 9febc8f8..ecc2afe3 100644
--- a/src/renderer/src/pages/catalogue/pagination.tsx
+++ b/src/renderer/src/pages/catalogue/pagination.tsx
@@ -29,9 +29,11 @@ function JumpControl({
return isOpen ? (
) {
const { formatNumber } = useFormat();
const [isJumpOpen, setIsJumpOpen] = useState(false);
@@ -87,13 +89,15 @@ export function Pagination({
}
const onJumpChange = (e: ChangeEvent) => {
- const val = e.target.value;
- if (val === "") {
+ const raw = e.target.value;
+ const digitsOnly = raw.replaceAll(/\D+/g, "");
+ if (digitsOnly === "") {
setJumpValue("");
return;
}
- const num = Number(val);
+ const num = Number.parseInt(digitsOnly, 10);
if (Number.isNaN(num)) {
+ setJumpValue("");
return;
}
if (num < 1) {
@@ -104,19 +108,36 @@ export function Pagination({
setJumpValue(String(totalPages));
return;
}
- setJumpValue(val);
+ setJumpValue(String(num));
};
const onJumpKeyDown = (e: KeyboardEvent) => {
+ const controlKeys = [
+ "Backspace",
+ "Delete",
+ "Tab",
+ "ArrowLeft",
+ "ArrowRight",
+ "Home",
+ "End",
+ ];
+
+ if (controlKeys.includes(e.key) || e.ctrlKey || e.metaKey) {
+ return;
+ }
+
if (e.key === "Enter") {
- if (jumpValue.trim() === "") return;
- const parsed = Number(jumpValue);
+ const sanitized = jumpValue.replaceAll(/\D+/g, "");
+ if (sanitized.trim() === "") return;
+ const parsed = Number.parseInt(sanitized, 10);
if (Number.isNaN(parsed)) return;
const target = Math.max(1, Math.min(totalPages, parsed));
onPageChange(target);
setIsJumpOpen(false);
} else if (e.key === "Escape") {
setIsJumpOpen(false);
+ } else if (!/^\d$/.test(e.key)) {
+ e.preventDefault();
}
};