From 47a5f4d32762f2f43ca0ebfd6251862e62d4f3a8 Mon Sep 17 00:00:00 2001 From: Hachi-R Date: Tue, 17 Dec 2024 11:10:25 -0300 Subject: [PATCH 01/41] feat: add reset achievements modal --- src/locales/en/translation.json | 5 +- src/locales/pt-BR/translation.json | 5 +- .../modals/game-options-modal.tsx | 19 ++++++++ .../modals/reset-achievements-modal.tsx | 46 +++++++++++++++++++ 4 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 src/renderer/src/pages/game-details/modals/reset-achievements-modal.tsx diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 940e3185..f2adae8b 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -168,7 +168,10 @@ "select_folder": "Select folder", "backup_from": "Backup from {{date}}", "custom_backup_location_set": "Custom backup location set", - "no_directory_selected": "No directory selected" + "no_directory_selected": "No directory selected", + "reset_achievements": "Reset achievements", + "reset_achievements_description": "This will reset all achievements for {{game}}", + "reset_achievements_title": "Are you sure?" }, "activation": { "title": "Activate Hydra", diff --git a/src/locales/pt-BR/translation.json b/src/locales/pt-BR/translation.json index e724cdc3..30d8f322 100644 --- a/src/locales/pt-BR/translation.json +++ b/src/locales/pt-BR/translation.json @@ -164,7 +164,10 @@ "select_folder": "Selecione a pasta", "manage_files_description": "Gerencie quais arquivos serão feitos backup", "clear": "Limpar", - "no_directory_selected": "Nenhum diretório selecionado" + "no_directory_selected": "Nenhum diretório selecionado", + "reset_achievements": "Resetar conquistas", + "reset_achievements_description": "Isso irá resetar todas as conquistas de {{game}}", + "reset_achievements_title": "Tem certeza?" }, "activation": { "title": "Ativação", diff --git a/src/renderer/src/pages/game-details/modals/game-options-modal.tsx b/src/renderer/src/pages/game-details/modals/game-options-modal.tsx index e5c83ec4..0d1fdc2c 100644 --- a/src/renderer/src/pages/game-details/modals/game-options-modal.tsx +++ b/src/renderer/src/pages/game-details/modals/game-options-modal.tsx @@ -7,6 +7,7 @@ import { gameDetailsContext } from "@renderer/context"; import { DeleteGameModal } from "@renderer/pages/downloads/delete-game-modal"; import { useDownload, useToast } from "@renderer/hooks"; import { RemoveGameFromLibraryModal } from "./remove-from-library-modal"; +import { ResetAchievementsModal } from "./reset-achievements-modal"; import { FileDirectoryIcon, FileIcon } from "@primer/octicons-react"; export interface GameOptionsModalProps { @@ -29,6 +30,8 @@ export function GameOptionsModal({ const [showDeleteModal, setShowDeleteModal] = useState(false); const [showRemoveGameModal, setShowRemoveGameModal] = useState(false); + const [showResetAchievementsModal, setShowResetAchievementsModal] = + useState(false); const { removeGameInstaller, @@ -134,6 +137,13 @@ export function GameOptionsModal({ game={game} /> + setShowResetAchievementsModal(false)} + // resetAchievements={handleResetAchievements} + game={game} + /> + {t("remove_from_library")} + + + + + + + + ); +} From ac6eb247df4cfe5d57172bc10fbda0ccefbc31b1 Mon Sep 17 00:00:00 2001 From: Hachi-R Date: Tue, 17 Dec 2024 13:15:55 -0300 Subject: [PATCH 02/41] feat: implement reset game achievements functionality --- src/main/events/index.ts | 1 + .../events/library/reset-game-achievements.ts | 52 +++++++++++++++++++ src/preload/index.ts | 2 + src/renderer/src/declaration.d.ts | 2 +- .../modals/game-options-modal.tsx | 7 ++- .../modals/reset-achievements-modal.tsx | 6 +-- 6 files changed, 65 insertions(+), 5 deletions(-) create mode 100644 src/main/events/library/reset-game-achievements.ts diff --git a/src/main/events/index.ts b/src/main/events/index.ts index eff62531..e26ed91c 100644 --- a/src/main/events/index.ts +++ b/src/main/events/index.ts @@ -25,6 +25,7 @@ import "./library/verify-executable-path"; import "./library/remove-game"; import "./library/remove-game-from-library"; import "./library/select-game-wine-prefix"; +import "./library/reset-game-achievements"; import "./misc/open-checkout"; import "./misc/open-external"; import "./misc/show-open-dialog"; diff --git a/src/main/events/library/reset-game-achievements.ts b/src/main/events/library/reset-game-achievements.ts new file mode 100644 index 00000000..7780c3ed --- /dev/null +++ b/src/main/events/library/reset-game-achievements.ts @@ -0,0 +1,52 @@ +import { gameAchievementRepository, gameRepository } from "@main/repository"; +import { registerEvent } from "../register-event"; +import { findAchievementFiles } from "@main/services/achievements/find-achivement-files"; +import fs from "fs"; +import { WindowManager } from "@main/services"; +import { getUnlockedAchievements } from "../user/get-unlocked-achievements"; + +const resetGameAchievements = async ( + _event: Electron.IpcMainInvokeEvent, + gameId: number +) => { + const game = await gameRepository.findOne({ where: { id: gameId } }); + + if (!game) return; + + const achievementFiles = findAchievementFiles(game); + + if (achievementFiles.length) { + try { + await Promise.all( + achievementFiles.map(async (achievementFile) => { + await fs.promises.rm(achievementFile.filePath, { recursive: true }); + }) + ); + } catch (error) { + console.error(error); + } + } + + await gameAchievementRepository.update( + { objectId: game.objectID }, + { + unlockedAchievements: null, + achievements: null, + } + ); + + // TODO: remove from db + + const gameAchievements = await getUnlockedAchievements( + game.objectID, + game.shop, + false + ); + + WindowManager.mainWindow?.webContents.send( + `on-update-achievements-${game.objectID}-${game.shop}`, + gameAchievements + ); +}; + +registerEvent("resetGameAchievements", resetGameAchievements); diff --git a/src/preload/index.ts b/src/preload/index.ts index f9d19644..d100228f 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -110,6 +110,8 @@ contextBridge.exposeInMainWorld("electron", { ipcRenderer.invoke("deleteGameFolder", gameId), getGameByObjectId: (objectId: string) => ipcRenderer.invoke("getGameByObjectId", objectId), + resetGameAchievements: (gameId: number) => + ipcRenderer.invoke("resetGameAchievements", gameId), onGamesRunning: ( cb: ( gamesRunning: Pick[] diff --git a/src/renderer/src/declaration.d.ts b/src/renderer/src/declaration.d.ts index 93c423e0..343c3ffe 100644 --- a/src/renderer/src/declaration.d.ts +++ b/src/renderer/src/declaration.d.ts @@ -105,7 +105,7 @@ declare global { ) => void ) => () => Electron.IpcRenderer; onLibraryBatchComplete: (cb: () => void) => () => Electron.IpcRenderer; - + resetGameAchievements: (gameId: number) => Promise; /* User preferences */ getUserPreferences: () => Promise; updateUserPreferences: ( diff --git a/src/renderer/src/pages/game-details/modals/game-options-modal.tsx b/src/renderer/src/pages/game-details/modals/game-options-modal.tsx index 0d1fdc2c..c4592e13 100644 --- a/src/renderer/src/pages/game-details/modals/game-options-modal.tsx +++ b/src/renderer/src/pages/game-details/modals/game-options-modal.tsx @@ -122,6 +122,11 @@ export function GameOptionsModal({ const shouldShowWinePrefixConfiguration = window.electron.platform === "linux"; + const handleResetAchievements = async () => { + await window.electron.resetGameAchievements(game.id); + updateGame(); + }; + return ( <> setShowResetAchievementsModal(false)} - // resetAchievements={handleResetAchievements} + resetAchievements={handleResetAchievements} game={game} /> diff --git a/src/renderer/src/pages/game-details/modals/reset-achievements-modal.tsx b/src/renderer/src/pages/game-details/modals/reset-achievements-modal.tsx index 409fedbe..d8861076 100644 --- a/src/renderer/src/pages/game-details/modals/reset-achievements-modal.tsx +++ b/src/renderer/src/pages/game-details/modals/reset-achievements-modal.tsx @@ -7,19 +7,19 @@ interface ResetAchievementsModalProps { visible: boolean; game: Game; onClose: () => void; -// resetAchievements: () => Promise; + resetAchievements: () => Promise; } export function ResetAchievementsModal({ onClose, game, visible, -// resetAchievements, + resetAchievements, }: ResetAchievementsModalProps) { const { t } = useTranslation("game_details"); const handleResetAchievements = async () => { - // await resetAchievements(); + await resetAchievements(); onClose(); }; From afcfcbf4828314fd09ec886e37881c8d4e8d8ed8 Mon Sep 17 00:00:00 2001 From: Hachi-R Date: Tue, 17 Dec 2024 13:55:45 -0300 Subject: [PATCH 03/41] refactor: clean up reset game achievements logic --- src/main/events/library/reset-game-achievements.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/events/library/reset-game-achievements.ts b/src/main/events/library/reset-game-achievements.ts index 7780c3ed..25344076 100644 --- a/src/main/events/library/reset-game-achievements.ts +++ b/src/main/events/library/reset-game-achievements.ts @@ -31,7 +31,6 @@ const resetGameAchievements = async ( { objectId: game.objectID }, { unlockedAchievements: null, - achievements: null, } ); @@ -40,7 +39,7 @@ const resetGameAchievements = async ( const gameAchievements = await getUnlockedAchievements( game.objectID, game.shop, - false + true ); WindowManager.mainWindow?.webContents.send( From 9f5d8caddaa8da12d11944c41f621e81290e996c Mon Sep 17 00:00:00 2001 From: bankov4eto <90499490+bankov4eto@users.noreply.github.com> Date: Sun, 29 Dec 2024 12:42:27 +0200 Subject: [PATCH 04/41] Update translation.json MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added missing translation for the new strings { "catalogue": { "search": "Filter…", "developers": "Developers", "genres": "Genres", "tags": "Tags", "publishers": "Publishers", "download_sources": "Download sources", "result_count": "{{resultCount}} results", "filter_count": "{{filterCount}} available", "clear_filters": "Clear {{filterCount}} selected" }, "game_details": { "launch_options": "Launch Options", "launch_options_description": "Advanced users may choose to enter modifications to their launch options", "launch_options_placeholder": "No parameter specified" }, "downloads": { "seeding": "Seeding", "stop_seeding": "Stop seeding", "resume_seeding": "Resume seeding", "options": "Manage" }, "settings": { "seed_after_download_complete": "Seed after download complete", "show_hidden_achievement_description": "Show hidden achievements description before unlocking them" }, "user_profile": { "stats": "Stats", "achievements": "achievements", "games": "Games", "top_percentile": "Top {{percentile}}%", "ranking_updated_weekly": "Ranking is updated weekly", "playing": "Playing {{game}}", "achievements_unlocked": "Achievements Unlocked", "earned_points": "Earned points", "show_achievements_on_profile": "Show your achievements on your profile", "show_points_on_profile": "Show your earned points on your profile" }, "achievement": { "hidden_achievement_tooltip": "This is a hidden achievement", "achievement_earn_points": "Earn {{points}} points with this achievement", "earned_points": "Earned points:", "available_points": "Available points:", "how_to_earn_achievements_points": "How to earn achievements points?" }, "hydra_cloud": { "hydra_cloud": "Hydra Cloud", "hydra_cloud_feature_found": "You've just discovered a Hydra Cloud feature!", "learn_more": "Learn More" } } --- src/locales/bg/translation.json | 38 +++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/src/locales/bg/translation.json b/src/locales/bg/translation.json index 3112bb08..537e4469 100644 --- a/src/locales/bg/translation.json +++ b/src/locales/bg/translation.json @@ -46,10 +46,20 @@ "checking_files": "Проверка на {{title}} файловете… ({{percentage}} готово)" }, "catalogue": { - "next_page": "Следваща страница", - "previous_page": "Предишна страница" + "search": "Филтър…", + "developers": "Разработчици", + "genres": "Жанрове", + "tags": "Тагове", + "publishers": "Издатели", + "download_sources": "Източници за изтегляне", + "result_count": "{{resultCount}} резултати", + "filter_count": "{{filterCount}} налични", + "clear_filters": "Изчисти {{filterCount}} избрани" }, "game_details": { + "launch_options": "Опции за стартиране", + "launch_options_description": "Напредналите потребители могат да въведат модификации на своите опции за стартиране", + "launch_options_placeholder": "Няма зададен параметър" "open_download_options": "Варианти за изтегляне", "download_options_zero": "Няма варианти за изтегляне", "download_options_one": "{{count}} варианти за изтегляне", @@ -177,6 +187,10 @@ "loading": "Зареждане…" }, "downloads": { + "seeding": "Сийдване", + "stop_seeding": "Спри сийдването", + "resume_seeding": "Продължи сийдването", + "options": "Управление" "resume": "Продължи", "pause": "Пауза", "eta": "Conclusion {{eta}}", @@ -202,6 +216,8 @@ "checking_files": "Проверка на файлове…" }, "settings": { + "seed_after_download_complete": "Сийд след завършване на изтеглянето", + "show_hidden_achievement_description": "Показвай описанието на скритите постижения преди отключването им" "downloads_path": "Инсталационен път", "change": "Актуализиране", "notifications": "Известия", @@ -288,6 +304,16 @@ "toggle_password_visibility": "Превключване на видимостта на паролата" }, "user_profile": { + "stats": "Статистики", + "achievements": "Постижения", + "games": "Игри", + "top_percentile": "Топ {{percentile}}%", + "ranking_updated_weekly": "Класацията се актуализира седмично", + "playing": "Играйки {{game}}", + "achievements_unlocked": "Отключени постижения", + "earned_points": "Спечелени точки", + "show_achievements_on_profile": "Показвай своите постижения в профила", + "show_points_on_profile": "Показвай спечелените точки в профила" "amount_hours": "{{amount}} часове", "amount_minutes": "{{amount}} минути", "last_time_played": "Последно играно {{period}}", @@ -359,6 +385,11 @@ "background_image_updated": "Обновено фоново изображение" }, "achievement": { + "hidden_achievement_tooltip": "Това е скрито постижение", + "achievement_earn_points": "Спечели {{points}} точки с това постижение", + "earned_points": "Спечелени точки:", + "available_points": "Налични точки:", + "how_to_earn_achievements_points": "Как да спечелиш точки за постижения?" "achievement_unlocked": "Постижението е отключено", "user_achievements": "Постиженията на {{displayName}} ", "your_achievements": "Вашите Постижения", @@ -369,6 +400,9 @@ "achievements_unlocked_for_game": "Отключени {{achievementCount}} нови постижения за {{gameTitle}}" }, "hydra_cloud": { + "hydra_cloud": "Hydra Cloud", + "hydra_cloud_feature_found": "Открихте функция на Hydra Cloud!", + "learn_more": "Научете повече "subscription_tour_title": "Hydra Cloud Абонамент", "subscribe_now": "Абонирай се сега", "cloud_saving": "Запазване в облака", From 6e00fb8e13275b1e627f2988c718a871c85548a3 Mon Sep 17 00:00:00 2001 From: bankov4eto <90499490+bankov4eto@users.noreply.github.com> Date: Sun, 29 Dec 2024 12:47:01 +0200 Subject: [PATCH 05/41] Update translation.json --- src/locales/bg/translation.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/locales/bg/translation.json b/src/locales/bg/translation.json index 537e4469..e7f7539b 100644 --- a/src/locales/bg/translation.json +++ b/src/locales/bg/translation.json @@ -226,7 +226,7 @@ "real_debrid_api_token_label": "Real-Debrid API токен", "quit_app_instead_hiding": "Не скривайте Hydra при затваряне", "launch_with_system": "Стартиране на Hydra при стартиране на системата", - "general": "Общ", + "general": "Общи", "behavior": "Поведение", "download_sources": "Източници за изтегляне", "language": "Език", @@ -309,7 +309,7 @@ "games": "Игри", "top_percentile": "Топ {{percentile}}%", "ranking_updated_weekly": "Класацията се актуализира седмично", - "playing": "Играйки {{game}}", + "playing": "Играе {{game}}", "achievements_unlocked": "Отключени постижения", "earned_points": "Спечелени точки", "show_achievements_on_profile": "Показвай своите постижения в профила", @@ -402,7 +402,7 @@ "hydra_cloud": { "hydra_cloud": "Hydra Cloud", "hydra_cloud_feature_found": "Открихте функция на Hydra Cloud!", - "learn_more": "Научете повече + "learn_more": "Научете повече" "subscription_tour_title": "Hydra Cloud Абонамент", "subscribe_now": "Абонирай се сега", "cloud_saving": "Запазване в облака", From 8286390d9fb0eea32303f14c8d999a898bfee033 Mon Sep 17 00:00:00 2001 From: bankov4eto <90499490+bankov4eto@users.noreply.github.com> Date: Sun, 29 Dec 2024 13:30:07 +0200 Subject: [PATCH 06/41] Update translation.json MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added missing translation for the new strings { "catalogue": { "search": "Filter…", "developers": "Developers", "genres": "Genres", "tags": "Tags", "publishers": "Publishers", "download_sources": "Download sources", "result_count": "{{resultCount}} results", "filter_count": "{{filterCount}} available", "clear_filters": "Clear {{filterCount}} selected" }, "game_details": { "launch_options": "Launch Options", "launch_options_description": "Advanced users may choose to enter modifications to their launch options", "launch_options_placeholder": "No parameter specified" }, "downloads": { "seeding": "Seeding", "stop_seeding": "Stop seeding", "resume_seeding": "Resume seeding", "options": "Manage" }, "settings": { "seed_after_download_complete": "Seed after download complete", "show_hidden_achievement_description": "Show hidden achievements description before unlocking them" }, "user_profile": { "stats": "Stats", "achievements": "achievements", "games": "Games", "top_percentile": "Top {{percentile}}%", "ranking_updated_weekly": "Ranking is updated weekly", "playing": "Playing {{game}}", "achievements_unlocked": "Achievements Unlocked", "earned_points": "Earned points", "show_achievements_on_profile": "Show your achievements on your profile", "show_points_on_profile": "Show your earned points on your profile" }, "achievement": { "hidden_achievement_tooltip": "This is a hidden achievement", "achievement_earn_points": "Earn {{points}} points with this achievement", "earned_points": "Earned points:", "available_points": "Available points:", "how_to_earn_achievements_points": "How to earn achievements points?" }, "hydra_cloud": { "hydra_cloud": "Hydra Cloud", "hydra_cloud_feature_found": "You've just discovered a Hydra Cloud feature!", "learn_more": "Learn More" } } --- src/locales/bg/translation.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/locales/bg/translation.json b/src/locales/bg/translation.json index e7f7539b..b46e3fc7 100644 --- a/src/locales/bg/translation.json +++ b/src/locales/bg/translation.json @@ -59,7 +59,7 @@ "game_details": { "launch_options": "Опции за стартиране", "launch_options_description": "Напредналите потребители могат да въведат модификации на своите опции за стартиране", - "launch_options_placeholder": "Няма зададен параметър" + "launch_options_placeholder": "Няма зададен параметър", "open_download_options": "Варианти за изтегляне", "download_options_zero": "Няма варианти за изтегляне", "download_options_one": "{{count}} варианти за изтегляне", @@ -190,7 +190,7 @@ "seeding": "Сийдване", "stop_seeding": "Спри сийдването", "resume_seeding": "Продължи сийдването", - "options": "Управление" + "options": "Управление", "resume": "Продължи", "pause": "Пауза", "eta": "Conclusion {{eta}}", @@ -217,7 +217,7 @@ }, "settings": { "seed_after_download_complete": "Сийд след завършване на изтеглянето", - "show_hidden_achievement_description": "Показвай описанието на скритите постижения преди отключването им" + "show_hidden_achievement_description": "Показвай описанието на скритите постижения преди отключването им", "downloads_path": "Инсталационен път", "change": "Актуализиране", "notifications": "Известия", @@ -313,7 +313,7 @@ "achievements_unlocked": "Отключени постижения", "earned_points": "Спечелени точки", "show_achievements_on_profile": "Показвай своите постижения в профила", - "show_points_on_profile": "Показвай спечелените точки в профила" + "show_points_on_profile": "Показвай спечелените точки в профила", "amount_hours": "{{amount}} часове", "amount_minutes": "{{amount}} минути", "last_time_played": "Последно играно {{period}}", @@ -389,7 +389,7 @@ "achievement_earn_points": "Спечели {{points}} точки с това постижение", "earned_points": "Спечелени точки:", "available_points": "Налични точки:", - "how_to_earn_achievements_points": "Как да спечелиш точки за постижения?" + "how_to_earn_achievements_points": "Как да спечелиш точки за постижения?", "achievement_unlocked": "Постижението е отключено", "user_achievements": "Постиженията на {{displayName}} ", "your_achievements": "Вашите Постижения", @@ -402,7 +402,7 @@ "hydra_cloud": { "hydra_cloud": "Hydra Cloud", "hydra_cloud_feature_found": "Открихте функция на Hydra Cloud!", - "learn_more": "Научете повече" + "learn_more": "Научете повече", "subscription_tour_title": "Hydra Cloud Абонамент", "subscribe_now": "Абонирай се сега", "cloud_saving": "Запазване в облака", From 402e5df9acb7c688c42a3913f5d40a9ac90ac8a9 Mon Sep 17 00:00:00 2001 From: Zamitto <167933696+zamitto@users.noreply.github.com> Date: Mon, 30 Dec 2024 22:38:16 -0300 Subject: [PATCH 07/41] feat: double click shows windows --- src/main/services/window-manager.ts | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/main/services/window-manager.ts b/src/main/services/window-manager.ts index 426d7afe..adc2f301 100644 --- a/src/main/services/window-manager.ts +++ b/src/main/services/window-manager.ts @@ -277,14 +277,9 @@ export class WindowManager { if (process.platform !== "darwin") { await updateSystemTray(); - tray.addListener("click", () => { + tray.addListener("double-click", () => { if (this.mainWindow) { - if ( - WindowManager.mainWindow?.isMinimized() || - !WindowManager.mainWindow?.isVisible() - ) { - WindowManager.mainWindow?.show(); - } + this.mainWindow.show(); } else { this.createMainWindow(); } From 726d99a5c7ed075d89215b883cdf708fa8fecf3e Mon Sep 17 00:00:00 2001 From: Zamitto <167933696+zamitto@users.noreply.github.com> Date: Mon, 30 Dec 2024 23:06:23 -0300 Subject: [PATCH 08/41] chore: bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index dc11fde4..625b1c9c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hydralauncher", - "version": "3.1.2", + "version": "3.1.3", "description": "Hydra", "main": "./out/main/index.js", "author": "Los Broxas", From 726c75356812c819730ce2c352e5038659c1a4ea Mon Sep 17 00:00:00 2001 From: Chubby Granny Chaser Date: Tue, 31 Dec 2024 04:44:05 +0000 Subject: [PATCH 09/41] feat: adding sentry to renderer --- .github/workflows/build.yml | 15 +- .github/workflows/release.yml | 14 +- .gitignore | 3 + electron.vite.config.ts | 12 +- package.json | 2 + scripts/postinstall.cjs | 22 +- src/renderer/src/main.tsx | 13 + src/renderer/src/vite-env.d.ts | 1 + yarn.lock | 464 ++++++++++++++++++++++++++++++++- 9 files changed, 512 insertions(+), 34 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1c79222c..161708bb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -43,11 +43,12 @@ jobs: MAIN_VITE_API_URL: ${{ vars.MAIN_VITE_STAGING_API_URL }} MAIN_VITE_AUTH_URL: ${{ vars.MAIN_VITE_STAGING_AUTH_URL }} MAIN_VITE_CHECKOUT_URL: ${{ vars.MAIN_VITE_STAGING_CHECKOUT_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_EXTERNAL_RESOURCES_URL: ${{ vars.RENDERER_VITE_EXTERNAL_RESOURCES_URL }} + RENDERER_VITE_EXTERNAL_RESOURCES_URL: ${{ vars.EXTERNAL_RESOURCES_URL }} + MAIN_VITE_EXTERNAL_RESOURCES_URL: ${{ vars.EXTERNAL_RESOURCES_URL }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - MAIN_VITE_EXTERNAL_RESOURCES_URL: ${{ vars.MAIN_VITE_EXTERNAL_RESOURCES_URL }} + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + RENDERER_VITE_SENTRY_DSN: ${{ vars.SENTRY_DSN }} - name: Build Windows if: matrix.os == 'windows-latest' @@ -56,11 +57,12 @@ jobs: MAIN_VITE_API_URL: ${{ vars.MAIN_VITE_STAGING_API_URL }} MAIN_VITE_AUTH_URL: ${{ vars.MAIN_VITE_STAGING_AUTH_URL }} MAIN_VITE_CHECKOUT_URL: ${{ vars.MAIN_VITE_STAGING_CHECKOUT_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_EXTERNAL_RESOURCES_URL: ${{ vars.RENDERER_VITE_EXTERNAL_RESOURCES_URL }} + RENDERER_VITE_EXTERNAL_RESOURCES_URL: ${{ vars.EXTERNAL_RESOURCES_URL }} + MAIN_VITE_EXTERNAL_RESOURCES_URL: ${{ vars.EXTERNAL_RESOURCES_URL }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - MAIN_VITE_EXTERNAL_RESOURCES_URL: ${{ vars.MAIN_VITE_EXTERNAL_RESOURCES_URL }} + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + RENDERER_VITE_SENTRY_DSN: ${{ vars.SENTRY_DSN }} - name: Test Upload build env: @@ -72,6 +74,7 @@ jobs: BUILDS_URL: ${{ secrets.BUILDS_URL }} BUILD_WEBHOOK_URL: ${{ secrets.BUILD_WEBHOOK_URL }} GITHUB_ACTOR: ${{ github.actor }} + run: node scripts/upload-build.cjs - name: Create artifact diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 101221d1..afa5502c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -47,9 +47,12 @@ jobs: MAIN_VITE_CHECKOUT_URL: ${{ vars.MAIN_VITE_CHECKOUT_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_EXTERNAL_RESOURCES_URL: ${{ vars.RENDERER_VITE_EXTERNAL_RESOURCES_URL }} + RENDERER_VITE_EXTERNAL_RESOURCES_URL: ${{ vars.EXTERNAL_RESOURCES_URL }} + MAIN_VITE_EXTERNAL_RESOURCES_URL: ${{ vars.EXTERNAL_RESOURCES_URL }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - MAIN_VITE_EXTERNAL_RESOURCES_URL: ${{ vars.MAIN_VITE_EXTERNAL_RESOURCES_URL }} + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + RENDERER_VITE_SENTRY_DSN: ${{ vars.SENTRY_DSN }} + - name: Build Windows if: matrix.os == 'windows-latest' run: yarn build:win @@ -59,9 +62,12 @@ jobs: MAIN_VITE_CHECKOUT_URL: ${{ vars.MAIN_VITE_CHECKOUT_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_EXTERNAL_RESOURCES_URL: ${{ vars.RENDERER_VITE_EXTERNAL_RESOURCES_URL }} + RENDERER_VITE_EXTERNAL_RESOURCES_URL: ${{ vars.EXTERNAL_RESOURCES_URL }} + MAIN_VITE_EXTERNAL_RESOURCES_URL: ${{ vars.EXTERNAL_RESOURCES_URL }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - MAIN_VITE_EXTERNAL_RESOURCES_URL: ${{ vars.MAIN_VITE_EXTERNAL_RESOURCES_URL }} + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + RENDERER_VITE_SENTRY_DSN: ${{ vars.SENTRY_DSN }} + - name: Create artifact uses: actions/upload-artifact@v4 with: diff --git a/.gitignore b/.gitignore index 68b8342c..36e620fc 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,6 @@ ludusavi/ hydra-python-rpc/ aria2/ .python-version + +# Sentry Config File +.env.sentry-build-plugin diff --git a/electron.vite.config.ts b/electron.vite.config.ts index be37cc40..cd08b6d4 100644 --- a/electron.vite.config.ts +++ b/electron.vite.config.ts @@ -8,6 +8,7 @@ import { import react from "@vitejs/plugin-react"; import { vanillaExtractPlugin } from "@vanilla-extract/vite-plugin"; import svgr from "vite-plugin-svgr"; +import { sentryVitePlugin } from "@sentry/vite-plugin"; export default defineConfig(({ mode }) => { loadEnv(mode); @@ -44,7 +45,16 @@ export default defineConfig(({ mode }) => { "@shared": resolve("src/shared"), }, }, - plugins: [svgr(), react(), vanillaExtractPlugin()], + plugins: [ + svgr(), + react(), + vanillaExtractPlugin(), + sentryVitePlugin({ + authToken: process.env.SENTRY_AUTH_TOKEN, + org: "hydra-launcher", + project: "hydra-renderer", + }), + ], }, }; }); diff --git a/package.json b/package.json index 625b1c9c..f8ff14dd 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,8 @@ "@primer/octicons-react": "^19.9.0", "@radix-ui/react-dropdown-menu": "^2.1.2", "@reduxjs/toolkit": "^2.2.3", + "@sentry/react": "^8.47.0", + "@sentry/vite-plugin": "^2.22.7", "@vanilla-extract/css": "^1.14.2", "@vanilla-extract/dynamic": "^2.1.2", "@vanilla-extract/recipes": "^0.5.2", diff --git a/scripts/postinstall.cjs b/scripts/postinstall.cjs index 17edb025..70768a7d 100644 --- a/scripts/postinstall.cjs +++ b/scripts/postinstall.cjs @@ -48,11 +48,6 @@ const downloadLudusavi = async () => { }; const downloadAria2WindowsAndLinux = async () => { - if (fs.existsSync("aria2")) { - console.log("Aria2 already exists, skipping download..."); - return; - } - const file = process.platform === "win32" ? "aria2-1.37.0-win-64bit-build1.zip" @@ -111,10 +106,17 @@ const copyAria2Macos = async () => { await exec(`cp $(which aria2c) aria2/aria2c`); }; -if (process.platform == "darwin") { - copyAria2Macos(); -} else { - downloadAria2WindowsAndLinux(); -} +const copyAria2 = () => { + if (fs.existsSync("aria2")) { + console.log("Aria2 already exists, skipping download..."); + return; + } + if (process.platform == "darwin") { + copyAria2Macos(); + } else { + downloadAria2WindowsAndLinux(); + } +}; +copyAria2(); downloadLudusavi(); diff --git a/src/renderer/src/main.tsx b/src/renderer/src/main.tsx index 221c2726..61c561f1 100644 --- a/src/renderer/src/main.tsx +++ b/src/renderer/src/main.tsx @@ -34,6 +34,19 @@ const Achievements = React.lazy( () => import("./pages/achievements/achievements") ); +import * as Sentry from "@sentry/react"; + +Sentry.init({ + dsn: import.meta.env.RENDERER_VITE_SENTRY_DSN, + integrations: [ + Sentry.browserTracingIntegration(), + Sentry.replayIntegration(), + ], + tracesSampleRate: 1.0, + replaysSessionSampleRate: 0.1, + replaysOnErrorSampleRate: 1.0, +}); + console.log = logger.log; const isStaging = await window.electron.isStaging(); diff --git a/src/renderer/src/vite-env.d.ts b/src/renderer/src/vite-env.d.ts index 41b3f064..8972c89a 100644 --- a/src/renderer/src/vite-env.d.ts +++ b/src/renderer/src/vite-env.d.ts @@ -3,6 +3,7 @@ interface ImportMetaEnv { readonly RENDERER_VITE_EXTERNAL_RESOURCES_URL: string; + readonly RENDERER_VITE_SENTRY_DSN: string; } interface ImportMeta { diff --git a/yarn.lock b/yarn.lock index c28ea384..1f7c7e2e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -633,6 +633,15 @@ "@babel/highlight" "^7.24.7" picocolors "^1.0.0" +"@babel/code-frame@^7.25.9", "@babel/code-frame@^7.26.0", "@babel/code-frame@^7.26.2": + version "7.26.2" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.26.2.tgz#4b5fab97d33338eff916235055f0ebc21e573a85" + integrity sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ== + dependencies: + "@babel/helper-validator-identifier" "^7.25.9" + js-tokens "^4.0.0" + picocolors "^1.0.0" + "@babel/compat-data@^7.23.5": version "7.24.4" resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.4.tgz" @@ -643,6 +652,32 @@ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.25.4.tgz#7d2a80ce229890edcf4cc259d4d696cb4dae2fcb" integrity sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ== +"@babel/compat-data@^7.25.9": + version "7.26.3" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.26.3.tgz#99488264a56b2aded63983abd6a417f03b92ed02" + integrity sha512-nHIxvKPniQXpmQLb0vhY3VaFb3S0YrTAwpOWJZh1wn3oJPjJk9Asva204PsBdmAE8vpzfHudT8DB0scYvy9q0g== + +"@babel/core@^7.18.5": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.26.0.tgz#d78b6023cc8f3114ccf049eb219613f74a747b40" + integrity sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.26.0" + "@babel/generator" "^7.26.0" + "@babel/helper-compilation-targets" "^7.25.9" + "@babel/helper-module-transforms" "^7.26.0" + "@babel/helpers" "^7.26.0" + "@babel/parser" "^7.26.0" + "@babel/template" "^7.25.9" + "@babel/traverse" "^7.25.9" + "@babel/types" "^7.26.0" + convert-source-map "^2.0.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" + "@babel/core@^7.21.3", "@babel/core@^7.23.5", "@babel/core@^7.23.9": version "7.24.5" resolved "https://registry.npmjs.org/@babel/core/-/core-7.24.5.tgz" @@ -715,6 +750,17 @@ "@jridgewell/trace-mapping" "^0.3.25" jsesc "^2.5.1" +"@babel/generator@^7.26.0", "@babel/generator@^7.26.3": + version "7.26.3" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.26.3.tgz#ab8d4360544a425c90c248df7059881f4b2ce019" + integrity sha512-6FF/urZvD0sTeO7k6/B15pMLC4CHUv1426lzr3N01aHJTl046uCAh9LXW/fzeXXjPNCJ6iABW5XaWOsIZB93aQ== + dependencies: + "@babel/parser" "^7.26.3" + "@babel/types" "^7.26.3" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" + jsesc "^3.0.2" + "@babel/helper-compilation-targets@^7.23.6": version "7.23.6" resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz" @@ -737,6 +783,17 @@ lru-cache "^5.1.1" semver "^6.3.1" +"@babel/helper-compilation-targets@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz#55af025ce365be3cdc0c1c1e56c6af617ce88875" + integrity sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ== + dependencies: + "@babel/compat-data" "^7.25.9" + "@babel/helper-validator-option" "^7.25.9" + browserslist "^4.24.0" + lru-cache "^5.1.1" + semver "^6.3.1" + "@babel/helper-environment-visitor@^7.22.20": version "7.22.20" resolved "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz" @@ -794,6 +851,14 @@ "@babel/traverse" "^7.24.7" "@babel/types" "^7.24.7" +"@babel/helper-module-imports@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz#e7f8d20602ebdbf9ebbea0a0751fb0f2a4141715" + integrity sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw== + dependencies: + "@babel/traverse" "^7.25.9" + "@babel/types" "^7.25.9" + "@babel/helper-module-transforms@^7.24.5": version "7.24.5" resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.5.tgz" @@ -815,6 +880,15 @@ "@babel/helper-validator-identifier" "^7.24.7" "@babel/traverse" "^7.25.2" +"@babel/helper-module-transforms@^7.26.0": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz#8ce54ec9d592695e58d84cd884b7b5c6a2fdeeae" + integrity sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw== + dependencies: + "@babel/helper-module-imports" "^7.25.9" + "@babel/helper-validator-identifier" "^7.25.9" + "@babel/traverse" "^7.25.9" + "@babel/helper-plugin-utils@^7.24.0", "@babel/helper-plugin-utils@^7.24.5": version "7.24.5" resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.5.tgz" @@ -869,6 +943,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz#5b3329c9a58803d5df425e5785865881a81ca48d" integrity sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ== +"@babel/helper-string-parser@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz#1aabb72ee72ed35789b4bbcad3ca2862ce614e8c" + integrity sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA== + "@babel/helper-validator-identifier@^7.24.5": version "7.24.5" resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.5.tgz" @@ -879,6 +958,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz#75b889cfaf9e35c2aaf42cf0d72c8e91719251db" integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w== +"@babel/helper-validator-identifier@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz#24b64e2c3ec7cd3b3c547729b8d16871f22cbdc7" + integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ== + "@babel/helper-validator-option@^7.23.5": version "7.23.5" resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz" @@ -889,6 +973,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz#3725cdeea8b480e86d34df15304806a06975e33d" integrity sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q== +"@babel/helper-validator-option@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz#86e45bd8a49ab7e03f276577f96179653d41da72" + integrity sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw== + "@babel/helpers@^7.24.5": version "7.24.5" resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.5.tgz" @@ -906,6 +995,14 @@ "@babel/template" "^7.25.0" "@babel/types" "^7.25.6" +"@babel/helpers@^7.26.0": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.26.0.tgz#30e621f1eba5aa45fe6f4868d2e9154d884119a4" + integrity sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw== + dependencies: + "@babel/template" "^7.25.9" + "@babel/types" "^7.26.0" + "@babel/highlight@^7.24.2": version "7.24.5" resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.5.tgz" @@ -943,6 +1040,13 @@ dependencies: "@babel/types" "^7.25.6" +"@babel/parser@^7.25.9", "@babel/parser@^7.26.0", "@babel/parser@^7.26.3": + version "7.26.3" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.3.tgz#8c51c5db6ddf08134af1ddbacf16aaab48bac234" + integrity sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA== + dependencies: + "@babel/types" "^7.26.3" + "@babel/plugin-syntax-typescript@^7.23.3": version "7.24.1" resolved "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.1.tgz" @@ -1012,6 +1116,15 @@ "@babel/parser" "^7.25.0" "@babel/types" "^7.25.0" +"@babel/template@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.25.9.tgz#ecb62d81a8a6f5dc5fe8abfc3901fc52ddf15016" + integrity sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg== + dependencies: + "@babel/code-frame" "^7.25.9" + "@babel/parser" "^7.25.9" + "@babel/types" "^7.25.9" + "@babel/traverse@^7.24.5": version "7.24.5" resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.5.tgz" @@ -1057,6 +1170,19 @@ debug "^4.3.1" globals "^11.1.0" +"@babel/traverse@^7.25.9": + version "7.26.4" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.26.4.tgz#ac3a2a84b908dde6d463c3bfa2c5fdc1653574bd" + integrity sha512-fH+b7Y4p3yqvApJALCPJcwb0/XaOSgtK4pzV6WVjPR5GLFQBRI7pfoX2V2iM48NXvX07NUxxm1Vw98YjqTcU5w== + dependencies: + "@babel/code-frame" "^7.26.2" + "@babel/generator" "^7.26.3" + "@babel/parser" "^7.26.3" + "@babel/template" "^7.25.9" + "@babel/types" "^7.26.3" + debug "^4.3.1" + globals "^11.1.0" + "@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.21.3", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.24.0", "@babel/types@^7.24.5": version "7.24.5" resolved "https://registry.npmjs.org/@babel/types/-/types-7.24.5.tgz" @@ -1084,6 +1210,14 @@ "@babel/helper-validator-identifier" "^7.24.7" to-fast-properties "^2.0.0" +"@babel/types@^7.25.9", "@babel/types@^7.26.0", "@babel/types@^7.26.3": + version "7.26.3" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.26.3.tgz#37e79830f04c2b5687acc77db97fbc75fb81f3c0" + integrity sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA== + dependencies: + "@babel/helper-string-parser" "^7.25.9" + "@babel/helper-validator-identifier" "^7.25.9" + "@bufbuild/protobuf@^2.0.0": version "2.2.2" resolved "https://registry.yarnpkg.com/@bufbuild/protobuf/-/protobuf-2.2.2.tgz#1a6d89603fb215dc4d4178052d05b30b83c75402" @@ -1745,7 +1879,7 @@ resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz" integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== -"@jridgewell/sourcemap-codec@^1.5.0": +"@jridgewell/sourcemap-codec@^1.4.15", "@jridgewell/sourcemap-codec@^1.5.0": version "1.5.0" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== @@ -2261,6 +2395,142 @@ resolved "https://registry.yarnpkg.com/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz#60de891bb126abfdc5410fdc6166aca065f10a0c" integrity sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg== +"@sentry-internal/browser-utils@8.47.0": + version "8.47.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/browser-utils/-/browser-utils-8.47.0.tgz#39f2766a1bbdffc2d211e2f61f8ed8c258245b3d" + integrity sha512-vOXzYzHTKkahTLDzWWIA4EiVCQ+Gk+7xGWUlNcR2ZiEPBqYZVb5MjsUozAcc7syrSUy6WicyFjcomZ3rlCVQhg== + dependencies: + "@sentry/core" "8.47.0" + +"@sentry-internal/feedback@8.47.0": + version "8.47.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-8.47.0.tgz#22bceac03b61ab8509e79c0875fb140f214b7c4f" + integrity sha512-IAiIemTQIalxAOYhUENs9bZ8pMNgJnX3uQSuY7v0gknEqClOGpGkG04X/cxCmtJUj1acZ9ShTGDxoh55a+ggAQ== + dependencies: + "@sentry/core" "8.47.0" + +"@sentry-internal/replay-canvas@8.47.0": + version "8.47.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/replay-canvas/-/replay-canvas-8.47.0.tgz#5bbd04c81235b2bf627aa216185ae1993d2102c4" + integrity sha512-M4W9UGouEeELbGbP3QsXLDVtGiQSZoWJlKwqMWyqdQgZuLoKw0S33+60t6teLVMhuQZR0UI9VJTF5coiXysnnA== + dependencies: + "@sentry-internal/replay" "8.47.0" + "@sentry/core" "8.47.0" + +"@sentry-internal/replay@8.47.0": + version "8.47.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/replay/-/replay-8.47.0.tgz#4f7bd359df2de25d919a378295cab67dfa05a406" + integrity sha512-G/S40ZBORj0HSMLw/uVC6YDEPN/dqVk901vf4VYfml686DEhJrZesfAfp5SydJumQ0NKZQrdtvny+BWnlI5H1w== + dependencies: + "@sentry-internal/browser-utils" "8.47.0" + "@sentry/core" "8.47.0" + +"@sentry/babel-plugin-component-annotate@2.22.7": + version "2.22.7" + resolved "https://registry.yarnpkg.com/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-2.22.7.tgz#604c7e33d48528a13477e7af597c4d5fca51b8bd" + integrity sha512-aa7XKgZMVl6l04NY+3X7BP7yvQ/s8scn8KzQfTLrGRarziTlMGrsCOBQtCNWXOPEbtxAIHpZ9dsrAn5EJSivOQ== + +"@sentry/browser@8.47.0": + version "8.47.0" + resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-8.47.0.tgz#fe0b6b65c0394f54438d6704039adeaec214ce18" + integrity sha512-K6BzHisykmbFy/wORtGyfsAlw7ShevLALzu3ReZZZ18dVubO1bjSNjkZQU9MJD5Jcb9oLwkq89n3N9XIBfvdRA== + dependencies: + "@sentry-internal/browser-utils" "8.47.0" + "@sentry-internal/feedback" "8.47.0" + "@sentry-internal/replay" "8.47.0" + "@sentry-internal/replay-canvas" "8.47.0" + "@sentry/core" "8.47.0" + +"@sentry/bundler-plugin-core@2.22.7": + version "2.22.7" + resolved "https://registry.yarnpkg.com/@sentry/bundler-plugin-core/-/bundler-plugin-core-2.22.7.tgz#28204a224cd1fef58d157e5beeb2493947a9bc35" + integrity sha512-ouQh5sqcB8vsJ8yTTe0rf+iaUkwmeUlGNFi35IkCFUQlWJ22qS6OfvNjOqFI19e6eGUXks0c/2ieFC4+9wJ+1g== + dependencies: + "@babel/core" "^7.18.5" + "@sentry/babel-plugin-component-annotate" "2.22.7" + "@sentry/cli" "2.39.1" + dotenv "^16.3.1" + find-up "^5.0.0" + glob "^9.3.2" + magic-string "0.30.8" + unplugin "1.0.1" + +"@sentry/cli-darwin@2.39.1": + version "2.39.1" + resolved "https://registry.yarnpkg.com/@sentry/cli-darwin/-/cli-darwin-2.39.1.tgz#75c338a53834b4cf72f57599f4c72ffb36cf0781" + integrity sha512-kiNGNSAkg46LNGatfNH5tfsmI/kCAaPA62KQuFZloZiemTNzhy9/6NJP8HZ/GxGs8GDMxic6wNrV9CkVEgFLJQ== + +"@sentry/cli-linux-arm64@2.39.1": + version "2.39.1" + resolved "https://registry.yarnpkg.com/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.39.1.tgz#27db44700c33fcb1e8966257020b43f8494373e6" + integrity sha512-5VbVJDatolDrWOgaffsEM7znjs0cR8bHt9Bq0mStM3tBolgAeSDHE89NgHggfZR+DJ2VWOy4vgCwkObrUD6NQw== + +"@sentry/cli-linux-arm@2.39.1": + version "2.39.1" + resolved "https://registry.yarnpkg.com/@sentry/cli-linux-arm/-/cli-linux-arm-2.39.1.tgz#451683fa9a5a60b1359d104ec71334ed16f4b63c" + integrity sha512-DkENbxyRxUrfLnJLXTA4s5UL/GoctU5Cm4ER1eB7XN7p9WsamFJd/yf2KpltkjEyiTuplv0yAbdjl1KX3vKmEQ== + +"@sentry/cli-linux-i686@2.39.1": + version "2.39.1" + resolved "https://registry.yarnpkg.com/@sentry/cli-linux-i686/-/cli-linux-i686-2.39.1.tgz#9965a81f97a94e8b6d1d15589e43fee158e35201" + integrity sha512-pXWVoKXCRrY7N8vc9H7mETiV9ZCz+zSnX65JQCzZxgYrayQPJTc+NPRnZTdYdk5RlAupXaFicBI2GwOCRqVRkg== + +"@sentry/cli-linux-x64@2.39.1": + version "2.39.1" + resolved "https://registry.yarnpkg.com/@sentry/cli-linux-x64/-/cli-linux-x64-2.39.1.tgz#31fe008b02f92769543dc9919e2a5cbc4cda7889" + integrity sha512-IwayNZy+it7FWG4M9LayyUmG1a/8kT9+/IEm67sT5+7dkMIMcpmHDqL8rWcPojOXuTKaOBBjkVdNMBTXy0mXlA== + +"@sentry/cli-win32-i686@2.39.1": + version "2.39.1" + resolved "https://registry.yarnpkg.com/@sentry/cli-win32-i686/-/cli-win32-i686-2.39.1.tgz#609e8790c49414011445e397130560c777850b35" + integrity sha512-NglnNoqHSmE+Dz/wHeIVRnV2bLMx7tIn3IQ8vXGO5HWA2f8zYJGktbkLq1Lg23PaQmeZLPGlja3gBQfZYSG10Q== + +"@sentry/cli-win32-x64@2.39.1": + version "2.39.1" + resolved "https://registry.yarnpkg.com/@sentry/cli-win32-x64/-/cli-win32-x64-2.39.1.tgz#1a874a5570c6d162b35d9d001c96e5389d07d2cb" + integrity sha512-xv0R2CMf/X1Fte3cMWie1NXuHmUyQPDBfCyIt6k6RPFPxAYUgcqgMPznYwVMwWEA1W43PaOkSn3d8ZylsDaETw== + +"@sentry/cli@2.39.1": + version "2.39.1" + resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-2.39.1.tgz#916bb5b7567ccf7fdf94ef6cf8a2b9ab78370d29" + integrity sha512-JIb3e9vh0+OmQ0KxmexMXg9oZsR/G7HMwxt5BUIKAXZ9m17Xll4ETXTRnRUBT3sf7EpNGAmlQk1xEmVN9pYZYQ== + dependencies: + https-proxy-agent "^5.0.0" + node-fetch "^2.6.7" + progress "^2.0.3" + proxy-from-env "^1.1.0" + which "^2.0.2" + optionalDependencies: + "@sentry/cli-darwin" "2.39.1" + "@sentry/cli-linux-arm" "2.39.1" + "@sentry/cli-linux-arm64" "2.39.1" + "@sentry/cli-linux-i686" "2.39.1" + "@sentry/cli-linux-x64" "2.39.1" + "@sentry/cli-win32-i686" "2.39.1" + "@sentry/cli-win32-x64" "2.39.1" + +"@sentry/core@8.47.0": + version "8.47.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-8.47.0.tgz#e811444552f7a91b5de573875a318a6cd4e802f8" + integrity sha512-iSEJZMe3DOcqBFZQAqgA3NB2lCWBc4Gv5x/SCri/TVg96wAlss4VrUunSI2Mp0J4jJ5nJcJ2ChqHSBAU48k3FA== + +"@sentry/react@^8.47.0": + version "8.47.0" + resolved "https://registry.yarnpkg.com/@sentry/react/-/react-8.47.0.tgz#0d9c120b0d4a2efd6d8e8fb9acff332c63afd50d" + integrity sha512-SRk2Up+qBTow4rQGiRXViC2i4M5w/tae5w8I/rmX+IxFoPyh8wXERcLAj/8xbbRm8aR+A4i5gNgfFtrYsyFJFA== + dependencies: + "@sentry/browser" "8.47.0" + "@sentry/core" "8.47.0" + hoist-non-react-statics "^3.3.2" + +"@sentry/vite-plugin@^2.22.7": + version "2.22.7" + resolved "https://registry.yarnpkg.com/@sentry/vite-plugin/-/vite-plugin-2.22.7.tgz#9b63452d1d8cd02e6ba6234395a611ae7656c67a" + integrity sha512-sYRNiNm4toQGq2BfZSJPdw36em3eQaLu+3NTFpA7Hl4g3Sp2Rt3CYObnW5bxlFEruRhxzvdyB383N9OefVZ6KA== + dependencies: + "@sentry/bundler-plugin-core" "2.22.7" + unplugin "1.0.1" + "@sindresorhus/is@^4.0.0": version "4.6.0" resolved "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz" @@ -3451,6 +3721,11 @@ acorn@^8.11.3, acorn@^8.9.0: resolved "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz" integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== +acorn@^8.8.1: + version "8.14.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" + integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== + agent-base@6, agent-base@^6.0.2: version "6.0.2" resolved "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz" @@ -3539,6 +3814,14 @@ any-promise@^1.0.0: resolved "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz" integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A== +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + app-builder-bin@5.0.0-alpha.10: version "5.0.0-alpha.10" resolved "https://registry.yarnpkg.com/app-builder-bin/-/app-builder-bin-5.0.0-alpha.10.tgz#cf12e593b6b847fb9d04027fa755c6c6610d778b" @@ -3821,6 +4104,11 @@ better-sqlite3@^11.7.0: bindings "^1.5.0" prebuild-install "^7.1.1" +binary-extensions@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" + integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== + bindings@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" @@ -3874,7 +4162,7 @@ brace-expansion@^2.0.1: dependencies: balanced-match "^1.0.0" -braces@^3.0.3: +braces@^3.0.3, braces@~3.0.2: version "3.0.3" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== @@ -3891,6 +4179,16 @@ browserslist@^4.22.2, browserslist@^4.23.1: node-releases "^2.0.18" update-browserslist-db "^1.1.0" +browserslist@^4.24.0: + version "4.24.3" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.3.tgz#5fc2725ca8fb3c1432e13dac278c7cc103e026d2" + integrity sha512-1CPmv8iobE2fyRMV97dAcMVegvvWKxmq94hkLiAkUGwKVTyDLw33K+ZxiFrREKmmps4rIw6grcCFCnTMSZ/YiA== + dependencies: + caniuse-lite "^1.0.30001688" + electron-to-chromium "^1.5.73" + node-releases "^2.0.19" + update-browserslist-db "^1.1.1" + buffer-builder@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/buffer-builder/-/buffer-builder-0.2.0.tgz#3322cd307d8296dab1f604618593b261a3fade8f" @@ -4056,6 +4354,11 @@ caniuse-lite@^1.0.30001663: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001664.tgz#d588d75c9682d3301956b05a3749652a80677df4" integrity sha512-AmE7k4dXiNKQipgn7a2xg558IRqPN3jMQY/rOsbxDhrd0tyChwbITBfiwtnqz8bi2M5mIWbxAYBvk7W7QBUS2g== +caniuse-lite@^1.0.30001688: + version "1.0.30001690" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001690.tgz#f2d15e3aaf8e18f76b2b8c1481abde063b8104c8" + integrity sha512-5ExiE3qQN6oF8Clf8ifIDcMRCRE/dMGcETG/XGMD8/XiXm6HXQgQTh1yZYLXXpSOsEUlJm1Xr7kGULZTuGtP/w== + chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" @@ -4083,6 +4386,21 @@ check-disk-space@^3.4.0: resolved "https://registry.yarnpkg.com/check-disk-space/-/check-disk-space-3.4.0.tgz#eb8e69eee7a378fd12e35281b8123a8b4c4a8ff7" integrity sha512-drVkSqfwA+TvuEhFipiR1OC9boEGZL5RrWvVsOthdcvQNXyCCuKkEiTOTXZ7qxSf/GLwq4GvzfrQD/Wz325hgw== +chokidar@^3.5.3: + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + chownr@^1.1.1: version "1.1.4" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" @@ -4672,6 +4990,11 @@ dotenv@^16.0.3, dotenv@^16.4.4, dotenv@^16.4.5: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f" integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg== +dotenv@^16.3.1: + version "16.4.7" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.7.tgz#0e20c5b82950140aa99be360a8a5f52335f53c26" + integrity sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ== + dunder-proto@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.0.tgz#c2fce098b3c8f8899554905f4377b6d85dabaa80" @@ -4739,6 +5062,11 @@ electron-to-chromium@^1.5.28: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.30.tgz#5b264b489cfe0c3dd71097c164d795444834e7c7" integrity sha512-sXI35EBN4lYxzc/pIGorlymYNzDBOqkSlVRe6MkgBsW/hW1tpC/HDJ2fjG7XnjakzfLEuvdmux0Mjs6jHq4UOA== +electron-to-chromium@^1.5.73: + version "1.5.76" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.76.tgz#db20295c5061b68f07c8ea4dfcbd701485d94a3d" + integrity sha512-CjVQyG7n7Sr+eBXE86HIulnL5N8xZY1sgmOPGuq/F0Rr0FJq63lg0kEtOIDfZBk44FnDLf6FUJ+dsJcuiUDdDQ== + electron-updater@^6.3.9: version "6.3.9" resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-6.3.9.tgz#e1e7f155624c58e6f3760f376c3a584028165ec4" @@ -5551,11 +5879,6 @@ get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.3, get-intrinsic@ has-symbols "^1.0.3" hasown "^2.0.0" -get-nonce@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/get-nonce/-/get-nonce-1.0.1.tgz#fdf3f0278073820d2ce9426c18f07481b1e0cdf3" - integrity sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q== - get-intrinsic@^1.2.5, get-intrinsic@^1.2.6: version "1.2.6" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.6.tgz#43dd3dd0e7b49b82b2dfcad10dc824bf7fc265d5" @@ -5572,6 +5895,11 @@ get-intrinsic@^1.2.5, get-intrinsic@^1.2.6: hasown "^2.0.2" math-intrinsics "^1.0.0" +get-nonce@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-nonce/-/get-nonce-1.0.1.tgz#fdf3f0278073820d2ce9426c18f07481b1e0cdf3" + integrity sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q== + get-package-type@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" @@ -5625,7 +5953,7 @@ github-from-package@0.0.0: resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" integrity sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw== -glob-parent@^5.1.2: +glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== @@ -5685,6 +6013,16 @@ glob@^8.0.1: minimatch "^5.0.1" once "^1.3.0" +glob@^9.3.2: + version "9.3.5" + resolved "https://registry.yarnpkg.com/glob/-/glob-9.3.5.tgz#ca2ed8ca452781a3009685607fdf025a899dfe21" + integrity sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q== + dependencies: + fs.realpath "^1.0.0" + minimatch "^8.0.2" + minipass "^4.2.4" + path-scurry "^1.6.1" + global-agent@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/global-agent/-/global-agent-3.0.0.tgz#ae7cd31bd3583b93c5a16437a1afe27cc33a1ab6" @@ -5836,6 +6174,13 @@ highlight.js@^10.7.1: resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.7.3.tgz#697272e3991356e40c3cac566a74eef681756531" integrity sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A== +hoist-non-react-statics@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" + integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== + dependencies: + react-is "^16.7.0" + hosted-git-info@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-4.1.0.tgz#827b82867e9ff1c8d0c4d9d53880397d2c86d224" @@ -6083,6 +6428,13 @@ is-bigint@^1.1.0: dependencies: has-bigints "^1.0.2" +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + is-boolean-object@^1.1.0: version "1.1.2" resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" @@ -6164,7 +6516,7 @@ is-generator-function@^1.0.10: dependencies: has-tostringtag "^1.0.0" -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== @@ -6450,6 +6802,11 @@ jsesc@^2.5.1: resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== +jsesc@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d" + integrity sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA== + json-buffer@3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" @@ -6771,6 +7128,13 @@ lru-cache@^7.7.1: resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.18.3.tgz#f793896e0fd0e954a59dfdd82f0773808df6aa89" integrity sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA== +magic-string@0.30.8: + version "0.30.8" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.8.tgz#14e8624246d2bedba70d5462aa99ac9681844613" + integrity sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ== + dependencies: + "@jridgewell/sourcemap-codec" "^1.4.15" + magic-string@^0.30.10: version "0.30.11" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.11.tgz#301a6f93b3e8c2cb13ac1a7a673492c0dfd12954" @@ -6904,6 +7268,13 @@ minimatch@^5.0.1: dependencies: brace-expansion "^2.0.1" +minimatch@^8.0.2: + version "8.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-8.0.4.tgz#847c1b25c014d4e9a7f68aaf63dedd668a626229" + integrity sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA== + dependencies: + brace-expansion "^2.0.1" + minimatch@^9.0.1, minimatch@^9.0.3, minimatch@^9.0.4: version "9.0.5" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" @@ -6962,6 +7333,11 @@ minipass@^3.0.0, minipass@^3.1.1, minipass@^3.1.6: dependencies: yallist "^4.0.0" +minipass@^4.2.4: + version "4.2.8" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-4.2.8.tgz#f0010f64393ecfc1d1ccb5f582bcaf45f48e1a3a" + integrity sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ== + minipass@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d" @@ -7101,6 +7477,13 @@ node-domexception@^1.0.0: resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== +node-fetch@^2.6.7: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + node-fetch@^3.3.0: version "3.3.2" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.3.2.tgz#d1e889bacdf733b4ff3b2b243eb7a12866a0b78b" @@ -7132,6 +7515,11 @@ node-releases@^2.0.18: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.18.tgz#f010e8d35e2fe8d6b2944f03f70213ecedc4ca3f" integrity sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g== +node-releases@^2.0.19: + version "2.0.19" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.19.tgz#9e445a52950951ec4d177d843af370b411caf314" + integrity sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw== + nopt@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/nopt/-/nopt-6.0.0.tgz#245801d8ebf409c6df22ab9d95b65e1309cdb16d" @@ -7139,6 +7527,11 @@ nopt@^6.0.0: dependencies: abbrev "^1.0.0" +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + normalize-url@^6.0.1: version "6.1.0" resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" @@ -7381,7 +7774,7 @@ path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== -path-scurry@^1.11.0, path-scurry@^1.11.1: +path-scurry@^1.11.0, path-scurry@^1.11.1, path-scurry@^1.6.1: version "1.11.1" resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== @@ -7424,7 +7817,7 @@ picocolors@^1.0.0, picocolors@^1.0.1, picocolors@^1.1.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.0.tgz#5358b76a78cde483ba5cef6a9dc9671440b27d59" integrity sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw== -picomatch@^2.3.1: +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== @@ -7632,7 +8025,7 @@ react-i18next@^14.1.0: "@babel/runtime" "^7.23.9" html-parse-stringify "^3.0.1" -react-is@^16.13.1: +react-is@^16.13.1, react-is@^16.7.0: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== @@ -7726,6 +8119,13 @@ readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + rechoir@^0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.8.0.tgz#49f866e0d32146142da3ad8f0eff352b3215ff22" @@ -8714,6 +9114,11 @@ tr46@^5.0.0: dependencies: punycode "^2.3.1" +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + truncate-utf8-bytes@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz#405923909592d56f78a5818434b0b78489ca5f2b" @@ -8920,12 +9325,22 @@ universalify@^2.0.0: resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== +unplugin@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/unplugin/-/unplugin-1.0.1.tgz#83b528b981cdcea1cad422a12cd02e695195ef3f" + integrity sha512-aqrHaVBWW1JVKBHmGo33T5TxeL0qWzfvjWokObHA9bYmN7eNDkwOxmLjhioHl9878qDFMAaT51XNroRyuz7WxA== + dependencies: + acorn "^8.8.1" + chokidar "^3.5.3" + webpack-sources "^3.2.3" + webpack-virtual-modules "^0.5.0" + untildify@^3.0.2: version "3.0.3" resolved "https://registry.yarnpkg.com/untildify/-/untildify-3.0.3.tgz#1e7b42b140bcfd922b22e70ca1265bfe3634c7c9" integrity sha512-iSk/J8efr8uPT/Z4eSUywnqyrQU7DSdMfdqK4iWEaUVVmcP5JcnpRqmVMwcwcnmI1ATFNgC5V90u09tBynNFKA== -update-browserslist-db@^1.1.0: +update-browserslist-db@^1.1.0, update-browserslist-db@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz#80846fba1d79e82547fb661f8d141e0945755fe5" integrity sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A== @@ -9064,11 +9479,26 @@ web-streams-polyfill@^3.0.3: resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz#2073b91a2fdb1fbfbd401e7de0ac9f8214cecb4b" integrity sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw== +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + webidl-conversions@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a" integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== +webpack-sources@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" + integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== + +webpack-virtual-modules@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/webpack-virtual-modules/-/webpack-virtual-modules-0.5.0.tgz#362f14738a56dae107937ab98ea7062e8bdd3b6c" + integrity sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw== + whatwg-encoding@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz#d0f4ef769905d426e1688f3e34381a99b60b76e5" @@ -9089,6 +9519,14 @@ whatwg-url@^14.0.0: tr46 "^5.0.0" webidl-conversions "^7.0.0" +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + which-boxed-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" From 16259b539965531626bb06ac8776aae704c9da92 Mon Sep 17 00:00:00 2001 From: Chubby Granny Chaser Date: Tue, 31 Dec 2024 05:10:03 +0000 Subject: [PATCH 10/41] fix: fixing backups per game limit as conditional --- .../game-details/cloud-sync-modal/cloud-sync-modal.tsx | 9 +++++---- src/types/index.ts | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/renderer/src/pages/game-details/cloud-sync-modal/cloud-sync-modal.tsx b/src/renderer/src/pages/game-details/cloud-sync-modal/cloud-sync-modal.tsx index b4665f15..3e8cc7f1 100644 --- a/src/renderer/src/pages/game-details/cloud-sync-modal/cloud-sync-modal.tsx +++ b/src/renderer/src/pages/game-details/cloud-sync-modal/cloud-sync-modal.tsx @@ -88,6 +88,9 @@ export function CloudSyncModal({ visible, onClose }: CloudSyncModalProps) { } }, [getGameBackupPreview, visible]); + const userDetails = useAppSelector((state) => state.userDetails.userDetails); + const backupsPerGameLimit = userDetails?.quirks?.backupsPerGameLimit ?? 0; + const backupStateLabel = useMemo(() => { if (uploadingBackup) { return ( @@ -120,7 +123,7 @@ export function CloudSyncModal({ visible, onClose }: CloudSyncModalProps) { ); } - if (artifacts.length >= 2) { + if (artifacts.length >= backupsPerGameLimit) { return t("max_number_of_artifacts_reached"); } @@ -140,14 +143,12 @@ export function CloudSyncModal({ visible, onClose }: CloudSyncModalProps) { restoringBackup, loadingPreview, artifacts, + backupsPerGameLimit, t, ]); const disableActions = uploadingBackup || restoringBackup || deletingArtifact; - const userDetails = useAppSelector((state) => state.userDetails.userDetails); - const backupsPerGameLimit = userDetails?.quirks.backupsPerGameLimit ?? 0; - return ( Date: Tue, 31 Dec 2024 02:31:59 -0300 Subject: [PATCH 11/41] chore: bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f8ff14dd..897ba00c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hydralauncher", - "version": "3.1.3", + "version": "3.1.4", "description": "Hydra", "main": "./out/main/index.js", "author": "Los Broxas", From ad204e38793b4b38e0b3cde3a65d3fd5e32b4272 Mon Sep 17 00:00:00 2001 From: Zamitto <167933696+zamitto@users.noreply.github.com> Date: Tue, 31 Dec 2024 14:06:27 -0300 Subject: [PATCH 12/41] fix: issues --- src/main/events/auth/get-session-hash.ts | 2 ++ src/main/events/cloud-save/get-game-artifacts.ts | 6 +++++- src/main/events/misc/open-checkout.ts | 11 ++--------- .../src/context/game-details/game-details.context.tsx | 10 +++------- 4 files changed, 12 insertions(+), 17 deletions(-) diff --git a/src/main/events/auth/get-session-hash.ts b/src/main/events/auth/get-session-hash.ts index 2a17bcf1..c9dd39cc 100644 --- a/src/main/events/auth/get-session-hash.ts +++ b/src/main/events/auth/get-session-hash.ts @@ -9,6 +9,8 @@ const getSessionHash = async (_event: Electron.IpcMainInvokeEvent) => { if (!auth) return null; const payload = jwt.decode(auth.accessToken) as jwt.JwtPayload; + if (!payload) return null; + return payload.sessionId; }; diff --git a/src/main/events/cloud-save/get-game-artifacts.ts b/src/main/events/cloud-save/get-game-artifacts.ts index dbdcb853..3fa8552c 100644 --- a/src/main/events/cloud-save/get-game-artifacts.ts +++ b/src/main/events/cloud-save/get-game-artifacts.ts @@ -1,7 +1,7 @@ import { HydraApi } from "@main/services"; import { registerEvent } from "../register-event"; import type { GameArtifact, GameShop } from "@types"; -import { SubscriptionRequiredError } from "@shared"; +import { SubscriptionRequiredError, UserNotLoggedInError } from "@shared"; const getGameArtifacts = async ( _event: Electron.IpcMainInvokeEvent, @@ -22,6 +22,10 @@ const getGameArtifacts = async ( return []; } + if (err instanceof UserNotLoggedInError) { + return []; + } + throw err; }); }; diff --git a/src/main/events/misc/open-checkout.ts b/src/main/events/misc/open-checkout.ts index 5d087be0..ba48f03b 100644 --- a/src/main/events/misc/open-checkout.ts +++ b/src/main/events/misc/open-checkout.ts @@ -1,16 +1,10 @@ import { shell } from "electron"; import { registerEvent } from "../register-event"; -import { - userAuthRepository, - userPreferencesRepository, -} from "@main/repository"; +import { userAuthRepository } from "@main/repository"; import { HydraApi } from "@main/services"; const openCheckout = async (_event: Electron.IpcMainInvokeEvent) => { - const [userAuth, userPreferences] = await Promise.all([ - userAuthRepository.findOne({ where: { id: 1 } }), - userPreferencesRepository.findOne({ where: { id: 1 } }), - ]); + const userAuth = await userAuthRepository.findOne({ where: { id: 1 } }); if (!userAuth) { return; @@ -22,7 +16,6 @@ const openCheckout = async (_event: Electron.IpcMainInvokeEvent) => { const params = new URLSearchParams({ token: paymentToken, - lng: userPreferences?.language || "en", }); shell.openExternal( diff --git a/src/renderer/src/context/game-details/game-details.context.tsx b/src/renderer/src/context/game-details/game-details.context.tsx index 09ac7257..9242d9a6 100644 --- a/src/renderer/src/context/game-details/game-details.context.tsx +++ b/src/renderer/src/context/game-details/game-details.context.tsx @@ -117,11 +117,7 @@ export function GameDetailsContextProvider({ abortControllerRef.current = abortController; window.electron - .getGameShopDetails( - objectId!, - shop as GameShop, - getSteamLanguage(i18n.language) - ) + .getGameShopDetails(objectId, shop, getSteamLanguage(i18n.language)) .then((result) => { if (abortController.signal.aborted) return; @@ -140,14 +136,14 @@ export function GameDetailsContextProvider({ setIsLoading(false); }); - window.electron.getGameStats(objectId, shop as GameShop).then((result) => { + window.electron.getGameStats(objectId, shop).then((result) => { if (abortController.signal.aborted) return; setStats(result); }); if (userDetails) { window.electron - .getUnlockedAchievements(objectId, shop as GameShop) + .getUnlockedAchievements(objectId, shop) .then((achievements) => { if (abortController.signal.aborted) return; setAchievements(achievements); From 0661cbd6618f460bfa059443d3a5217d1878904b Mon Sep 17 00:00:00 2001 From: Zamitto <167933696+zamitto@users.noreply.github.com> Date: Tue, 31 Dec 2024 19:32:41 -0300 Subject: [PATCH 13/41] fix: steamGenres --- src/renderer/src/pages/catalogue/game-item.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/renderer/src/pages/catalogue/game-item.tsx b/src/renderer/src/pages/catalogue/game-item.tsx index 8fb4c1b6..18454870 100644 --- a/src/renderer/src/pages/catalogue/game-item.tsx +++ b/src/renderer/src/pages/catalogue/game-item.tsx @@ -31,11 +31,11 @@ export function GameItem({ game }: GameItemProps) { const genres = useMemo(() => { return game.genres?.map((genre) => { - const index = steamGenres["en"].findIndex( + const index = steamGenres["en"]?.findIndex( (steamGenre) => steamGenre === genre ); - if (steamGenres[language] && steamGenres[language][index]) { + if (index && steamGenres[language] && steamGenres[language][index]) { return steamGenres[language][index]; } From 1226483debfde99a0a052bfe0f7477c91c4991cb Mon Sep 17 00:00:00 2001 From: Zamitto <167933696+zamitto@users.noreply.github.com> Date: Tue, 31 Dec 2024 19:38:17 -0300 Subject: [PATCH 14/41] fix: open game with parameters --- src/locales/bg/translation.json | 2 +- src/locales/en/translation.json | 2 +- src/locales/pt-BR/translation.json | 2 +- src/main/events/library/open-game.ts | 11 +++++++---- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/locales/bg/translation.json b/src/locales/bg/translation.json index b46e3fc7..b68e60da 100644 --- a/src/locales/bg/translation.json +++ b/src/locales/bg/translation.json @@ -58,7 +58,7 @@ }, "game_details": { "launch_options": "Опции за стартиране", - "launch_options_description": "Напредналите потребители могат да въведат модификации на своите опции за стартиране", + "launch_options_description": "Напредналите потребители могат да въведат модификации на своите опции за стартиране (экспериментальный)", "launch_options_placeholder": "Няма зададен параметър", "open_download_options": "Варианти за изтегляне", "download_options_zero": "Няма варианти за изтегляне", diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index c93cad1a..5724dac7 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -168,7 +168,7 @@ "wine_prefix": "Wine Prefix", "wine_prefix_description": "The Wine prefix used to run this game", "launch_options": "Launch Options", - "launch_options_description": "Advanced users may choose to enter modifications to their launch options", + "launch_options_description": "Advanced users may choose to enter modifications to their launch options (experimental feature)", "launch_options_placeholder": "No parameter specified", "no_download_option_info": "No information available", "backup_deletion_failed": "Failed to delete backup", diff --git a/src/locales/pt-BR/translation.json b/src/locales/pt-BR/translation.json index 1c880176..c94c826f 100644 --- a/src/locales/pt-BR/translation.json +++ b/src/locales/pt-BR/translation.json @@ -156,7 +156,7 @@ "wine_prefix": "Prefixo Wine", "wine_prefix_description": "O prefixo Wine que foi utilizado para instalar o jogo", "launch_options": "Opções de Inicialização", - "launch_options_description": "Usuários avançados podem adicionar opções de inicialização no jogo", + "launch_options_description": "Usuários avançados podem adicionar opções de inicialização no jogo (experimental)", "launch_options_placeholder": "Nenhum parâmetro informado", "no_download_option_info": "Sem informações disponíveis", "backup_deletion_failed": "Falha ao apagar backup", diff --git a/src/main/events/library/open-game.ts b/src/main/events/library/open-game.ts index f43dd1a9..c2980f36 100644 --- a/src/main/events/library/open-game.ts +++ b/src/main/events/library/open-game.ts @@ -20,13 +20,16 @@ const openGame = async ( { executablePath: parsedPath, launchOptions } ); - if (process.platform === "linux" || process.platform === "darwin") { + if ( + process.platform === "linux" || + process.platform === "darwin" || + parsedParams.length === 0 + ) { shell.openPath(parsedPath); + return; } - if (process.platform === "win32") { - spawn(parsedPath, parsedParams, { shell: false, detached: true }); - } + spawn(parsedPath, parsedParams, { shell: false, detached: true }); }; registerEvent("openGame", openGame); From 6278600b9839c2f24f3eac619202a76c873a3b19 Mon Sep 17 00:00:00 2001 From: 7ROBE <75377870+7ROBE@users.noreply.github.com> Date: Wed, 1 Jan 2025 11:11:41 +0300 Subject: [PATCH 15/41] Update translation.json --- src/locales/ar/translation.json | 735 ++++++++++++++++---------------- 1 file changed, 375 insertions(+), 360 deletions(-) diff --git a/src/locales/ar/translation.json b/src/locales/ar/translation.json index a4724b21..35a64d2d 100644 --- a/src/locales/ar/translation.json +++ b/src/locales/ar/translation.json @@ -4,399 +4,414 @@ "successfully_signed_in": "تم تسجيل الدخول بنجاح" }, "home": { - "featured": "مميّز", - "surprise_me": "فاجئني", - "no_results": "لم يتم العثور على نتائج", - "start_typing": "بدء الكتابة للبحث...", - "hot": "الأكثر رواجا الآن", - "weekly": "📅 أفضل ألعاب الأسبوع", - "achievements": "🏆 ألعاب للتغلب عليها" + "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": "بحاجة الى مساعدة؟" + "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}} متاح. " + "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}} مكتمل)" + "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": "الصفحة السابقة" + "search": "تَصْفِيَةٌ...", + "developers": "الْمُطَوِّرُونَ", + "genres": "الْأَنْوَاعُ", + "tags": "الْعَلَامَاتُ", + "publishers": "النَّاشِرُونَ", + "download_sources": "مَصَادِرُ التَّنْزِيلِ", + "result_count": "{{resultCount}} نَتائِجُ", + "filter_count": "{{filterCount}} مَتَوَفِّرٌ", + "clear_filters": "مَسْحُ {{filterCount}} الْمُخْتَارَةِ" }, "game_details": { - "open_download_options": "افتح خيارات التنزيل", - "download_options_zero": "{{count}} خيارات التنزيل", - "updated_at": "تم التحديث {{updated_at}}", - "install": "ثَبَّتَ", - "resume": "استئناف", - "pause": "إيقاف", - "cancel": "إلغاء", - "remove": "إزالة", - "space_left_on_disk": "{{space}} متبقية على القرص", - "eta": "الوقت المتبقي {{eta}}", - "calculating_eta": "جارٍ حساب الوقت المتبقي…", - "downloading_metadata": "جارٍ تنزيل البيانات الوصفية…", - "filter": "إعادة حزم التصفية", - "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": "اختر الحزمة التي تريد تنزيلها", - "select_folder_hint": "لتغيير المجلد الافتراضي، انتقل إلى <0>إعدادات", - "download_now": "قم بالتنزيل الآن", - "no_shop_details": "لا يمكن استرداد تفاصيل المتجر.", - "download_options": "خيارات التنزيل", - "download_path": "مسار التحميل", - "previous_screenshot": "لقطة الشاشة السابقة", - "next_screenshot": "لقطة الشاشة التالية", - "screenshot": "لقطة الشاشة {{number}}", - "open_screenshot": "فتح لقطة الشاشة {{number}}", - "download_settings": "تحميل الإعدادات", - "downloader": "أداة التنزيل", - "select_executable": "يختار", - "no_executable_selected": "لم يتم تحديد أي ملف قابل للتنفيذ", - "open_folder": "افتح المجلد", - "open_download_location": "انظر الملفات التي تم تنزيلها", - "create_shortcut": "إنشاء اختصار سطح المكتب", - "clear": "واضح", - "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 مفتوحًا حتى اكتماله. ", - "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_prefix_description": "بادئة Wine المستخدمة لتشغيل هذه اللعبة", - "no_download_option_info": "لا توجد معلومات متاحة", - "backup_deletion_failed": "فشل في حذف النسخة الاحتياطية", - "max_number_of_artifacts_reached": "تم الوصول إلى الحد الأقصى لعدد النسخ الاحتياطية لهذه اللعبة", - "achievements_not_sync": "لا تتم مزامنة إنجازاتك", - "manage_files_description": "إدارة الملفات التي سيتم نسخها احتياطيًا واستعادتها", - "select_folder": "حدد المجلد", - "backup_from": "نسخة احتياطية من {{date}}", - "custom_backup_location_set": "تعيين موقع النسخ الاحتياطي المخصص", - "no_directory_selected": "لم يتم تحديد أي دليل", - "download_options_one": "{{count}} خيار التنزيل", - "download_options_two": "{{count}} خيارات التنزيل", - "download_options_few": "{{count}} خيارات التنزيل", - "download_options_many": "{{count}} خيارات التنزيل", - "download_options_other": "{{count}} خيارات التنزيل" + "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": "تَصْفِيَةُ الْإِصْدَارَاتِ الْمُعَادِ تَغْلِيفُهَا", + "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": "اخْتَرِ الْإِصْدَارَ الْمُعَادَ تَغْلِيفُهُ الَّذِي تُرِيدُ تَنْزِيلَهُ", + "select_folder_hint": "لِتَغْيِيرِ الْمَجَلَّدِ الافْتِرَاضِيِّ، اذْهَبْ إِلَى <0>الإعْدَادَاتِ", + "download_now": "تَنْزِيلٌ الْآن", + "no_shop_details": "لَمْ يَتَمَكَّنْ مِنْ اسْتِرْدَادِ تَفَاصِيلِ الْمَتْجَرِ.", + "download_options": "خِيَارَاتُ التَّنْزِيلِ", + "download_path": "مَسَارُ التَّنْزِيلِ", + "previous_screenshot": "لَقْطَةُ الشَّاشَةِ السَّابِقَةُ", + "next_screenshot": "لَقْطَةُ الشَّاشَةِ التَّالِيَةُ", + "screenshot": "لَقْطَةُ الشَّاشَةِ {{number}}", + "open_screenshot": "فَتْحُ لَقْطَةِ الشَّاشَةِ {{number}}", + "download_settings": "إعْدَادَاتُ التَّنْزِيلِ", + "downloader": "الْمُنَزِّلُ", + "select_executable": "تَحْدِيدٌ", + "no_executable_selected": "لَمْ يُحَدَّدْ مِلَفٌّ تَنْفِيذِيٌّ", + "open_folder": "فَتْحُ الْمَجَلَّدِ", + "open_download_location": "مُشَاهَدَةُ الْمَلَفَّاتِ الْمُنَزَّلَةِ", + "create_shortcut": "إِنْشَاءُ طَرِيقٍ مُخْتَصَرٍ عَلَى سَطْحِ الْمَكْتَبِ", + "clear": "مَسْحٌ", + "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 الْمُسْتَخْدَمَةُ لِتَشْغِيلِ هَذِهِ اللُّعْبَةِ", + "launch_options": "خِيَارَاتُ الْإِطْلَاقِ", + "launch_options_description": "يُمْكِنُ لِلْمُسْتَخْدِمِينَ الْمُتَقَدِّمِينَ إِدْخَالُ تَعْدِيلَاتٍ عَلَى خِيَارَاتِ الْإِطْلَاقِ", + "launch_options_placeholder": "لَمْ يُحَدَّدْ أَيُّ مُعَامِلٍ", + "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": "تَمَّ تَحْدِيدُ مَوْقِعِ النُّسْخَةِ الِاحْتِيَاطِيَّةِ الْمُخَصَّصِ", + "no_directory_selected": "لَمْ يُحَدَّدْ أَيُّ دَلِيلٍ" }, "activation": { - "title": "تفعيل Hydra", - "installation_id": "معرف التثبيت:", - "enter_activation_code": "أدخل رمز التفعيل الخاص بك", - "message": "إذا كنت لا تعرف أين تطلب هذا، فلا ينبغي أن يكون لديك هذا.", - "activate": "فعل", - "loading": "تحميل…" + "title": "تَفْعِيلُ Hydra", + "installation_id": "مُعَرِّفُ التَّثْبِيتِ:", + "enter_activation_code": "أَدْخِلْ رَمْزَ التَّفْعِيلِ", + "message": "إِذَا كُنْتَ لَا تَعْرِفُ أَيْنَ تَطْلُبُ هَذَا، فَلا يَجِبُ أَنْ تَكُونَ لَدَيْكَ.", + "activate": "تَفْعِيلٌ", + "loading": "جَارٍ التَّحْمِيلُ..." }, "downloads": { - "resume": "استئناف", - "pause": "إيقاف مؤقت", - "eta": "الوقت المتبقي {{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": "جارٍ فحص الملفات…" + "resume": "اسْتِئْنَافٌ", + "pause": "إِيقَافٌ", + "eta": "الِاكْتِمَالُ {{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": "جَارٍ التَّحَقُّقُ مِنَ الْمَلَفَّاتِ...", + "seeding": "الْبَذْرُ", + "stop_seeding": "إِيقَافُ الْبَذْرِ", + "resume_seeding": "اسْتِئْنَافُ الْبَذْرِ", + "options": "إِدَارَةٌ" }, "settings": { - "downloads_path": "مسار التنزيلات", - "change": "تحديث", - "notifications": "إشعارات", - "enable_download_notifications": "عند اكتمال التنزيل", - "enable_repack_list_notifications": "عند إضافة حزمة جديدة", - "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_description": "Real-Debrid هو برنامج تنزيل غير مقيد يسمح لك بتنزيل الملفات بسرعة، ولا يقتصر ذلك إلا على سرعة الإنترنت لديك.", - "real_debrid_invalid_token": "رمز API غير صالح", - "real_debrid_api_token_hint": "يمكنك الحصول على رمز API الخاص بك <0>هنا", - "real_debrid_free_account_error": "الحساب \"{{username}}\" هو حساب مجاني. يرجى الاشتراك في Real-Debrid", - "real_debrid_linked_message": "حساب \"{{username}}\"مرتبط", - "save_changes": "حفظ التغييرات", - "changes_saved": "تم حفظ التغييرات بنجاح", - "download_sources_description": "ستقوم Hydra بجلب روابط التنزيل من هذه المصادر. ", - "validate_download_source": "التحقق من صحة", - "remove_download_source": "إزالة", - "add_download_source": "أضف المصدر", - "download_count_zero": "{{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": "أدخل عنوان URL صالحًا لـ JSON", - "found_download_option_zero": "وجد {{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", - "show_hidden_achievement_description": "إظهار وصف الإنجازات المخفية قبل فتحها", - "download_count_one": "{{countFormatted}} خيار التنزيل", - "download_count_two": "{{countFormatted}} خيارات التنزيل", - "download_count_few": "{{countFormatted}} خيارات التنزيل", - "download_count_many": "{{countFormatted}} خيارات التنزيل", - "download_count_other": "{{countFormatted}} خيارات التنزيل", - "found_download_option_one": "وجد {{countFormatted}} خيار التنزيل", - "found_download_option_two": "وجد {{countFormatted}} خيارات التنزيل", - "found_download_option_few": "وجد {{countFormatted}} خيارات التنزيل", - "found_download_option_many": "وجد {{countFormatted}} خيارات التنزيل", - "found_download_option_other": "وجد {{countFormatted}} خيارات التنزيل" + "downloads_path": "مَسَارُ التَّنْزِيلَاتِ", + "change": "تَحْدِيثٌ", + "notifications": "الإِشْعَارَاتُ", + "enable_download_notifications": "عِنْدَ اكْتِمَالِ التَّنْزِيلِ", + "enable_repack_list_notifications": "عِنْدَ إِضَافَةِ إِصْدَارٍ مُعَادٍ تَغْلِيفِهِ جَدِيدٍ", + "real_debrid_api_token_label": "رَمْزُ واجهة برمجة التطبيقات Real-Debrid", + "quit_app_instead_hiding": "لا تُخْفِ Hydra عِنْدَ الإِغْلَاقِ", + "launch_with_system": "تَشْغِيلُ Hydra عِنْدَ بَدْءِ النِّظَامِ", + "general": "عَامٌ", + "behavior": "سُلُوكٌ", + "download_sources": "مَصَادِرُ التَّنْزِيلِ", + "language": "اللُّغَةُ", + "real_debrid_api_token": "رَمْزُ واجهة برمجة التطبيقات", + "enable_real_debrid": "تَمْكِينُ Real-Debrid", + "real_debrid_description": "Real-Debrid هُوَ مُنَزِّلٌ غَيْرُ مَقْيُودٍ يَتِيحُ لَكَ تَنْزِيلَ الْمَلَفَّاتِ بِسُرْعَةٍ، مَحْدُودٌ فَقَطْ بِسُرْعَةِ الْإِنْتَرْنِتِ لَدَيْكَ.", + "real_debrid_invalid_token": "رَمْزُ واجهة برمجة التطبيقات غَيْرُ صَالِحٍ", + "real_debrid_api_token_hint": "يُمْكِنُكَ الْحُصُولُ عَلَى رَمْزِ واجهة برمجة التطبيقات <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": "عُنْوَانُ مَصْدَرِ التَّنْزِيلِ", + "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": "تَعْطِيلُ تَنْبِيهِ الْمُحْتَوَى غَيْرِ اللَّائِقِ", + "seed_after_download_complete": "الْبَذْرُ بَعْدَ اكْتِمَالِ التَّنْزِيلِ", + "show_hidden_achievement_description": "إِظْهَارُ وَصْفِ الإِنْجَازَاتِ الْمَخْفِيَّةِ قَبْلَ فَتْحِهَا" }, "notifications": { - "download_complete": "اكتمل التنزيل", - "game_ready_to_install": "{{title}} جاهز للتثبيت", - "repack_list_updated": "تم تحديث قائمة إعادة التعبئة", - "new_update_available": "إصدار {{version}} متاح", - "restart_to_install_update": "أعد تشغيل Hydra لتثبيت التحديث", - "notification_achievement_unlocked_title": "تم فتح الإنجاز لـ {{game}}", - "notification_achievement_unlocked_body": "{{achievement}} وغيرها {{count}} تم فتحها", - "repack_count_zero": "{{count}} تمت إضافة العبوات", - "repack_count_one": "{{count}} تمت إضافة أعد حزم", - "repack_count_two": "{{count}} تمت إضافة العبوات", - "repack_count_few": "{{count}} تمت إضافة العبوات", - "repack_count_many": "{{count}} تمت إضافة العبوات", - "repack_count_other": "{{count}} تمت إضافة العبوات" + "download_complete": "اكْتِمَالُ التَّنْزِيلِ", + "game_ready_to_install": "{{title}} جَاهِزٌ لِلتَّثْبِيتِ", + "repack_list_updated": "تَمَّ تَحْدِيثُ قَائِمَةِ الإِصْدَارَاتِ الْمُعَادَةِ تَغْلِيفُهَا", + "repack_count_one": "{{count}} إِصْدَارٌ مُعَادٌ تَغْلِيفُهُ أُضِيفَ", + "repack_count_other": "{{count}} إِصْدَارَاتٌ مُعَادَةٌ تَغْلِيفُهَا أُضِيفَتْ", + "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": "خروج" + "open": "فَتْحُ Hydra", + "quit": "الْخُرُوجُ" }, "game_card": { - "no_downloads": "لا توجد تنزيلات متاحة" + "no_downloads": "لَا تَوْجَدُ تَنْزِيلَاتٌ مَتَوَفِّرَةٌ" }, "binary_not_found_modal": { - "title": "البرامج غير مثبتة", - "description": "لم يتم العثور على الملفات التنفيذية الخاصة بـ Wine أو Lutris على نظامك", - "instructions": "تحقق من الطريقة الصحيحة لتثبيت أي منها على توزيعة Linux لديك حتى تعمل اللعبة بشكل طبيعي" + "title": "الْبَرَامِجُ غَيْرُ مُثَبَّتَةٍ", + "description": "لَمْ يُعْثَرْ عَلَى مَلَفَّاتٍ تَنْفِيذِيَّةٍ لِـ Wine أَوْ Lutris عَلَى نِظَامِكَ", + "instructions": "تَحَقَّقْ مِنَ الطَّرِيقَةِ الصَّحِيحَةِ لِتَثْبِيتِ أَيٍّ مِنْهُمَا عَلَى تَوْزِيعَةِ Linux لَدَيْكَ لِتَعْمَلَ اللُّعْبَةُ بِشَكْلٍ طَبِيعِيٍّ" }, "modal": { - "close": "زر الإغلاق" + "close": "زِرُّ الإِغْلَاقِ" }, "forms": { - "toggle_password_visibility": "تبديل رؤية كلمة المرور" + "toggle_password_visibility": "تَبْدِيلُ رُؤْيَةِ كَلِمَةِ الْمَرُورِ" }, "user_profile": { - "amount_hours": "{{amount}} ساعات", - "amount_minutes": "{{amount}} دقائق", - "last_time_played": "لعبت آخر مرة {{period}}", - "activity": "النشاط الأخير", - "library": "مكتبة", - "total_play_time": "إجمالي وقت اللعب", - "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>إعدادات", - "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": "رسائل إلكترونية مزعجة", - "profile_reported": "تم الإبلاغ عن الملف الشخصي", - "your_friend_code": "رمز صديقك:", - "upload_banner": "تحميل لافتة", - "uploading_banner": "جارٍ تحميل البانر…", - "background_image_updated": "تم تحديث صورة الخلفية", - "report_reason_zero": "آخر", - "report_reason_one": "لماذا تقوم بالإبلاغ عن هذا الملف الشخصي؟", - "report_reason_two": "آخر", - "report_reason_few": "آخر", - "report_reason_many": "آخر", - "report_reason_other": "آخر" + "amount_hours": "{{amount}} سَاعَاتٌ", + "amount_minutes": "{{amount}} دَقَائِقُ", + "last_time_played": "آخِرُ مَرَّةٍ لُعِبَتْ {{period}}", + "activity": "النَّشَاطُ الْأَخِيرُ", + "library": "الْمَكْتَبَةُ", + "total_play_time": "إِجْمَالِيُّ وَقْتِ اللَّعِبِ", + "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>الإعْدَادَاتِ", + "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": "تَمَّ تَحْدِيثُ صُورَةِ الْخَلْفِيَّةِ", + "stats": "الإحْصَائِيَّاتُ", + "achievements": "الإِنْجَازَاتُ", + "games": "الْأَلْعَابُ", + "top_percentile": "الْأَفْضَلُ {{percentile}}%", + "ranking_updated_weekly": "التَّرْتِيبُ يُحَدَّثُ أُسْبُوعِيًّا", + "playing": "جَارِي اللَّعِبُ {{game}}", + "achievements_unlocked": "الإِنْجَازَاتُ الْمَفْتُوحَةُ", + "earned_points": "النَّقَاطُ الْمَكْسُوبَةُ", + "show_achievements_on_profile": "عَرْضُ إِنْجَازَاتِكَ عَلَى مَلَفِّكَ الشَّخْصِيِّ", + "show_points_on_profile": "عَرْضُ النَّقَاطِ الْمَكْسُوبَةِ عَلَى مَلَفِّكَ الشَّخْصِيِّ" }, "achievement": { - "achievement_unlocked": "تم فتح الإنجاز", - "user_achievements": "{{displayName}}إنجازات", - "your_achievements": "إنجازاتك", - "unlocked_at": "مقفلة في: {{date}}", - "subscription_needed": "مطلوب اشتراك Hydra Cloud لرؤية هذا المحتوى", - "new_achievements_unlocked": "مفتوح {{achievementCount}} انجازات جديدة من {{gameCount}} ألعاب", - "achievement_progress": "{{unlockedCount}}/{{totalCount}} الإنجازات", - "achievements_unlocked_for_game": "مفتوح {{achievementCount}} انجازات جديدة ل {{gameTitle}}" + "achievement_unlocked": "إِنْجَازٌ مَفْتُوحٌ", + "user_achievements": "إِنْجَازَاتُ {{displayName}}", + "your_achievements": "إِنْجَازَاتُكَ", + "unlocked_at": "تَمَّ الْفَتْحُ فِي: {{date}}", + "subscription_needed": "يَحْتَاجُ اشْتِرَاكُ Hydra Cloud لِرُؤْيَةِ هَذَا الْمُحْتَوَى", + "new_achievements_unlocked": "تَمَّ فَتْحُ {{achievementCount}} إِنْجَازَاتٍ جَدِيدَةٍ مِنْ {{gameCount}} أَلْعَابٍ", + "achievement_progress": "{{unlockedCount}}/{{totalCount}} إِنْجَازَاتٍ", + "achievements_unlocked_for_game": "تَمَّ فَتْحُ {{achievementCount}} إِنْجَازَاتٍ جَدِيدَةٍ لِـ {{gameTitle}}", + "hidden_achievement_tooltip": "هَذَا إِنْجَازٌ مَخْفِيٌّ", + "achievement_earn_points": "اكْسِبْ {{points}} نَقَاطًا بِهَذَا الإِنْجَازِ", + "earned_points": "النَّقَاطُ الْمَكْسُوبَةُ:", + "available_points": "النَّقَاطُ الْمُتَوَفِّرَةُ:", + "how_to_earn_achievements_points": "كَيْفَ تَكْسِبُ نَقَاطَ الإِنْجَازَاتِ؟" }, "hydra_cloud": { - "subscription_tour_title": "اشتراك Hydra كلاود", - "subscribe_now": "اشترك الآن", - "cloud_saving": "الحفظ السحابي", - "cloud_achievements": "احفظ إنجازاتك على السحابة", - "animated_profile_picture": "صور شخصية متحركة", - "premium_support": "دعم متميز", - "show_and_compare_achievements": "عرض ومقارنة إنجازاتك مع المستخدمين الآخرين", - "animated_profile_banner": "لافتة الملف الشخصي المتحركة" + "subscription_tour_title": "اشْتِرَاكُ Hydra Cloud", + "subscribe_now": "اشْتَرِكِ الْآنَ", + "cloud_saving": "حِفْظٌ سَحَابِيٌّ", + "cloud_achievements": "حِفْظُ إِنْجَازَاتِكَ فِي السَّحَابَةِ", + "animated_profile_picture": "صُورُ الْمَلَفِّ الشَّخْصِيِّ الْمُتَحَرِّكَةِ", + "premium_support": "الدَّعْمُ الْمُتَقَدِّمُ", + "show_and_compare_achievements": "عَرْضٌ وَمُقَارَنَةُ إِنْجَازَاتِكَ مَعَ مُسْتَخْدِمِينَ آخَرِينَ", + "animated_profile_banner": "لَافِتَةُ الْمَلَفِّ الشَّخْصِيِّ الْمُتَحَرِّكَةِ", + "hydra_cloud": "Hydra Cloud", + "hydra_cloud_feature_found": "لَقَدْ اكْتَشَفْتَ مِيزَةً مِنْ Hydra Cloud!", + "learn_more": "تَعَلَّمْ أَكْثَرَ" } } From a121ef77c0bdcbb7bdd07e7f471e87ca4a044575 Mon Sep 17 00:00:00 2001 From: Chubby Granny Chaser Date: Wed, 1 Jan 2025 21:32:22 +0000 Subject: [PATCH 16/41] feat: adding translation for button --- package.json | 2 +- src/locales/en/translation.json | 3 +- src/locales/pt-BR/translation.json | 3 +- .../hardware/check-folder-write-permission.ts | 15 ++++ .../events/hardware/get-disk-free-space.ts | 4 +- src/main/events/index.ts | 4 +- src/main/events/misc/get-features.ts | 8 ++ src/main/services/window-manager.ts | 19 ++-- src/preload/index.ts | 3 + src/renderer/src/components/modal/modal.tsx | 6 ++ .../src/components/text-field/text-field.tsx | 8 +- src/renderer/src/declaration.d.ts | 6 +- src/renderer/src/hooks/index.ts | 1 + src/renderer/src/hooks/use-feature.ts | 23 +++++ src/renderer/src/hooks/use-user-details.ts | 7 ++ .../modals/download-settings-modal.css.ts | 7 ++ .../modals/download-settings-modal.tsx | 90 ++++++++++++------- .../edit-profile-modal/edit-profile-modal.tsx | 2 +- .../profile/report-profile/report-profile.tsx | 2 +- .../settings/add-download-source-modal.tsx | 2 +- yarn.lock | 23 +++-- 21 files changed, 176 insertions(+), 62 deletions(-) create mode 100644 src/main/events/hardware/check-folder-write-permission.ts create mode 100644 src/main/events/misc/get-features.ts create mode 100644 src/renderer/src/hooks/use-feature.ts diff --git a/package.json b/package.json index 897ba00c..7e838c4a 100644 --- a/package.json +++ b/package.json @@ -47,13 +47,13 @@ "auto-launch": "^5.0.6", "axios": "^1.7.9", "better-sqlite3": "^11.7.0", - "check-disk-space": "^3.4.0", "classnames": "^2.5.1", "color": "^4.2.3", "color.js": "^1.2.0", "create-desktop-shortcuts": "^1.11.0", "date-fns": "^3.6.0", "dexie": "^4.0.10", + "diskusage": "^1.2.0", "electron-log": "^5.2.4", "electron-updater": "^6.3.9", "file-type": "^19.6.0", diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index c93cad1a..a164308c 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -178,7 +178,8 @@ "select_folder": "Select folder", "backup_from": "Backup from {{date}}", "custom_backup_location_set": "Custom backup location set", - "no_directory_selected": "No directory selected" + "no_directory_selected": "No directory selected", + "no_write_permission": "Cannot download into this directory. Click here to learn more." }, "activation": { "title": "Activate Hydra", diff --git a/src/locales/pt-BR/translation.json b/src/locales/pt-BR/translation.json index 1c880176..203eef81 100644 --- a/src/locales/pt-BR/translation.json +++ b/src/locales/pt-BR/translation.json @@ -167,7 +167,8 @@ "select_folder": "Selecione a pasta", "manage_files_description": "Gerencie quais arquivos serão feitos backup", "clear": "Limpar", - "no_directory_selected": "Nenhum diretório selecionado" + "no_directory_selected": "Nenhum diretório selecionado", + "no_write_permission": "Его нельзя загрузить из этого каталога. Нажмите здесь, чтобы узнать больше." }, "activation": { "title": "Ativação", diff --git a/src/main/events/hardware/check-folder-write-permission.ts b/src/main/events/hardware/check-folder-write-permission.ts new file mode 100644 index 00000000..c74f01e7 --- /dev/null +++ b/src/main/events/hardware/check-folder-write-permission.ts @@ -0,0 +1,15 @@ +import fs from "node:fs"; + +import { registerEvent } from "../register-event"; + +const checkFolderWritePermission = async ( + _event: Electron.IpcMainInvokeEvent, + path: string +) => + new Promise((resolve) => { + fs.access(path, fs.constants.W_OK, (err) => { + resolve(!err); + }); + }); + +registerEvent("checkFolderWritePermission", checkFolderWritePermission); diff --git a/src/main/events/hardware/get-disk-free-space.ts b/src/main/events/hardware/get-disk-free-space.ts index ca591865..b5ac86e3 100644 --- a/src/main/events/hardware/get-disk-free-space.ts +++ b/src/main/events/hardware/get-disk-free-space.ts @@ -1,10 +1,10 @@ -import checkDiskSpace from "check-disk-space"; +import disk from "diskusage"; import { registerEvent } from "../register-event"; const getDiskFreeSpace = async ( _event: Electron.IpcMainInvokeEvent, path: string -) => checkDiskSpace(path); +) => disk.check(path); registerEvent("getDiskFreeSpace", getDiskFreeSpace); diff --git a/src/main/events/index.ts b/src/main/events/index.ts index d4053974..68944060 100644 --- a/src/main/events/index.ts +++ b/src/main/events/index.ts @@ -11,6 +11,7 @@ import "./catalogue/get-trending-games"; import "./catalogue/get-publishers"; import "./catalogue/get-developers"; import "./hardware/get-disk-free-space"; +import "./hardware/check-folder-write-permission"; import "./library/add-game-to-library"; import "./library/create-game-shortcut"; import "./library/close-game"; @@ -30,6 +31,8 @@ import "./library/select-game-wine-prefix"; import "./misc/open-checkout"; import "./misc/open-external"; import "./misc/show-open-dialog"; +import "./misc/get-features"; +import "./misc/show-item-in-folder"; import "./torrenting/cancel-game-download"; import "./torrenting/pause-game-download"; import "./torrenting/resume-game-download"; @@ -71,7 +74,6 @@ import "./cloud-save/delete-game-artifact"; import "./cloud-save/select-game-backup-path"; import "./notifications/publish-new-repacks-notification"; import { isPortableVersion } from "@main/helpers"; -import "./misc/show-item-in-folder"; ipcMain.handle("ping", () => "pong"); ipcMain.handle("getVersion", () => appVersion); diff --git a/src/main/events/misc/get-features.ts b/src/main/events/misc/get-features.ts new file mode 100644 index 00000000..766c84aa --- /dev/null +++ b/src/main/events/misc/get-features.ts @@ -0,0 +1,8 @@ +import { registerEvent } from "../register-event"; +import { HydraApi } from "@main/services"; + +const getFeatures = async (_event: Electron.IpcMainInvokeEvent) => { + return HydraApi.get("/features", null, { needsAuth: false }); +}; + +registerEvent("getFeatures", getFeatures); diff --git a/src/main/services/window-manager.ts b/src/main/services/window-manager.ts index adc2f301..a7cfcee2 100644 --- a/src/main/services/window-manager.ts +++ b/src/main/services/window-manager.ts @@ -64,7 +64,10 @@ export class WindowManager { this.mainWindow.webContents.session.webRequest.onBeforeSendHeaders( (details, callback) => { - if (details.webContentsId !== this.mainWindow?.webContents.id) { + if ( + details.webContentsId !== this.mainWindow?.webContents.id || + details.url.includes("chatwoot") + ) { return callback(details); } @@ -81,15 +84,11 @@ export class WindowManager { this.mainWindow.webContents.session.webRequest.onHeadersReceived( (details, callback) => { - if (details.webContentsId !== this.mainWindow?.webContents.id) { - return callback(details); - } - - if (details.url.includes("featurebase")) { - return callback(details); - } - - if (details.url.includes("chatwoot")) { + if ( + details.webContentsId !== this.mainWindow?.webContents.id || + details.url.includes("featurebase") || + details.url.includes("chatwoot") + ) { return callback(details); } diff --git a/src/preload/index.ts b/src/preload/index.ts index 2a8ed69e..7b555000 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -150,6 +150,8 @@ contextBridge.exposeInMainWorld("electron", { /* Hardware */ getDiskFreeSpace: (path: string) => ipcRenderer.invoke("getDiskFreeSpace", path), + checkFolderWritePermission: (path: string) => + ipcRenderer.invoke("checkFolderWritePermission", path), /* Cloud save */ uploadSaveGame: ( @@ -226,6 +228,7 @@ contextBridge.exposeInMainWorld("electron", { ipcRenderer.invoke("showOpenDialog", options), showItemInFolder: (path: string) => ipcRenderer.invoke("showItemInFolder", path), + getFeatures: () => ipcRenderer.invoke("getFeatures"), platform: process.platform, /* Auto update */ diff --git a/src/renderer/src/components/modal/modal.tsx b/src/renderer/src/components/modal/modal.tsx index af15feb5..d8d0554d 100644 --- a/src/renderer/src/components/modal/modal.tsx +++ b/src/renderer/src/components/modal/modal.tsx @@ -46,6 +46,12 @@ export function Modal({ }, [onClose]); const isTopMostModal = () => { + if ( + document.querySelector( + ".featurebase-widget-overlay.featurebase-display-block" + ) + ) + return false; const openModals = document.querySelectorAll("[role=dialog]"); return ( diff --git a/src/renderer/src/components/text-field/text-field.tsx b/src/renderer/src/components/text-field/text-field.tsx index d4dfa007..32664e03 100644 --- a/src/renderer/src/components/text-field/text-field.tsx +++ b/src/renderer/src/components/text-field/text-field.tsx @@ -1,6 +1,5 @@ import React, { useId, useMemo, useState } from "react"; import type { RecipeVariants } from "@vanilla-extract/recipes"; -import type { FieldError, FieldErrorsImpl, Merge } from "react-hook-form"; import { EyeClosedIcon, EyeIcon } from "@primer/octicons-react"; import { useTranslation } from "react-i18next"; @@ -23,7 +22,7 @@ export interface TextFieldProps HTMLDivElement >; rightContent?: React.ReactNode | null; - error?: FieldError | Merge> | undefined; + error?: string | React.ReactNode; } export const TextField = React.forwardRef( @@ -55,10 +54,7 @@ export const TextField = React.forwardRef( }, [props.type, isPasswordVisible]); const hintContent = useMemo(() => { - if (error && error.message) - return ( - {error.message as string} - ); + if (error) return {error}; if (hint) return {hint}; return null; diff --git a/src/renderer/src/declaration.d.ts b/src/renderer/src/declaration.d.ts index feec8284..88a16665 100644 --- a/src/renderer/src/declaration.d.ts +++ b/src/renderer/src/declaration.d.ts @@ -31,7 +31,7 @@ import type { CatalogueSearchPayload, } from "@types"; import type { AxiosProgressEvent } from "axios"; -import type { DiskSpace } from "check-disk-space"; +import type disk from "diskusage"; declare global { declare module "*.svg" { @@ -140,7 +140,8 @@ declare global { ) => Promise<{ fingerprint: string }>; /* Hardware */ - getDiskFreeSpace: (path: string) => Promise; + getDiskFreeSpace: (path: string) => Promise; + checkFolderWritePermission: (path: string) => Promise; /* Cloud save */ uploadSaveGame: ( @@ -195,6 +196,7 @@ declare global { options: Electron.OpenDialogOptions ) => Promise; showItemInFolder: (path: string) => Promise; + getFeatures: () => Promise; platform: NodeJS.Platform; /* Auto update */ diff --git a/src/renderer/src/hooks/index.ts b/src/renderer/src/hooks/index.ts index 97f519ef..8140e0cd 100644 --- a/src/renderer/src/hooks/index.ts +++ b/src/renderer/src/hooks/index.ts @@ -6,3 +6,4 @@ export * from "./redux"; export * from "./use-user-details"; export * from "./use-format"; export * from "./use-repacks"; +export * from "./use-feature"; diff --git a/src/renderer/src/hooks/use-feature.ts b/src/renderer/src/hooks/use-feature.ts new file mode 100644 index 00000000..ea682ce4 --- /dev/null +++ b/src/renderer/src/hooks/use-feature.ts @@ -0,0 +1,23 @@ +import { useEffect } from "react"; + +enum Feature { + CheckDownloadWritePermission = "CHECK_DOWNLOAD_WRITE_PERMISSION", +} + +export function useFeature() { + useEffect(() => { + window.electron.getFeatures().then((features) => { + localStorage.setItem("features", JSON.stringify(features || [])); + }); + }, []); + + const isFeatureEnabled = (feature: Feature) => { + const features = JSON.parse(localStorage.getItem("features") || "[]"); + return features.includes(feature); + }; + + return { + isFeatureEnabled, + Feature, + }; +} diff --git a/src/renderer/src/hooks/use-user-details.ts b/src/renderer/src/hooks/use-user-details.ts index 3328c517..43636ecd 100644 --- a/src/renderer/src/hooks/use-user-details.ts +++ b/src/renderer/src/hooks/use-user-details.ts @@ -13,6 +13,7 @@ import type { UpdateProfileRequest, UserDetails, } from "@types"; +import * as Sentry from "@sentry/react"; import { UserFriendModalTab } from "@renderer/pages/shared-modals/user-friend-modal"; import { isFuture, isToday } from "date-fns"; @@ -44,6 +45,12 @@ export function useUserDetails() { const updateUserDetails = useCallback( async (userDetails: UserDetails) => { + Sentry.setUser({ + id: userDetails.id, + username: userDetails.username, + email: userDetails.email ?? undefined, + }); + dispatch(setUserDetails(userDetails)); window.localStorage.setItem("userDetails", JSON.stringify(userDetails)); }, diff --git a/src/renderer/src/pages/game-details/modals/download-settings-modal.css.ts b/src/renderer/src/pages/game-details/modals/download-settings-modal.css.ts index 5450378c..3a776736 100644 --- a/src/renderer/src/pages/game-details/modals/download-settings-modal.css.ts +++ b/src/renderer/src/pages/game-details/modals/download-settings-modal.css.ts @@ -36,3 +36,10 @@ export const downloaderIcon = style({ position: "absolute", left: `${SPACING_UNIT * 2}px`, }); + +export const pathError = style({ + cursor: "pointer", + ":hover": { + textDecoration: "underline", + }, +}); diff --git a/src/renderer/src/pages/game-details/modals/download-settings-modal.tsx b/src/renderer/src/pages/game-details/modals/download-settings-modal.tsx index 191d9ac1..541bd01c 100644 --- a/src/renderer/src/pages/game-details/modals/download-settings-modal.tsx +++ b/src/renderer/src/pages/game-details/modals/download-settings-modal.tsx @@ -1,7 +1,6 @@ -import { useEffect, useMemo, useState } from "react"; +import { useCallback, useEffect, useMemo, useState } from "react"; import { Trans, useTranslation } from "react-i18next"; -import { DiskSpace } from "check-disk-space"; import * as styles from "./download-settings-modal.css"; import { Button, Link, Modal, TextField } from "@renderer/components"; import { CheckCircleFillIcon, DownloadIcon } from "@primer/octicons-react"; @@ -10,7 +9,7 @@ import { Downloader, formatBytes, getDownloadersForUris } from "@shared"; import type { GameRepack } from "@types"; import { SPACING_UNIT } from "@renderer/theme.css"; import { DOWNLOADER_NAME } from "@renderer/constants"; -import { useAppSelector, useToast } from "@renderer/hooks"; +import { useAppSelector, useFeature, useToast } from "@renderer/hooks"; export interface DownloadSettingsModalProps { visible: boolean; @@ -33,21 +32,45 @@ export function DownloadSettingsModal({ const { showErrorToast } = useToast(); - const [diskFreeSpace, setDiskFreeSpace] = useState(null); + const [diskFreeSpace, setDiskFreeSpace] = useState(null); const [selectedPath, setSelectedPath] = useState(""); const [downloadStarting, setDownloadStarting] = useState(false); const [selectedDownloader, setSelectedDownloader] = useState(null); + const [hasWritePermission, setHasWritePermission] = useState( + null + ); + + const { isFeatureEnabled, Feature } = useFeature(); const userPreferences = useAppSelector( (state) => state.userPreferences.value ); + const getDiskFreeSpace = (path: string) => { + window.electron.getDiskFreeSpace(path).then((result) => { + setDiskFreeSpace(result.free); + }); + }; + + const checkFolderWritePermission = useCallback( + async (path: string) => { + if (isFeatureEnabled(Feature.CheckDownloadWritePermission)) { + const result = await window.electron.checkFolderWritePermission(path); + setHasWritePermission(result); + } else { + setHasWritePermission(true); + } + }, + [Feature, isFeatureEnabled] + ); + useEffect(() => { if (visible) { getDiskFreeSpace(selectedPath); + checkFolderWritePermission(selectedPath); } - }, [visible, selectedPath]); + }, [visible, checkFolderWritePermission, selectedPath]); const downloaders = useMemo(() => { return getDownloadersForUris(repack?.uris ?? []); @@ -84,12 +107,6 @@ export function DownloadSettingsModal({ userPreferences?.realDebridApiToken, ]); - const getDiskFreeSpace = (path: string) => { - window.electron.getDiskFreeSpace(path).then((result) => { - setDiskFreeSpace(result); - }); - }; - const handleChooseDownloadsPath = async () => { const { filePaths } = await window.electron.showOpenDialog({ defaultPath: selectedPath, @@ -124,7 +141,7 @@ export function DownloadSettingsModal({ visible={visible} title={t("download_settings")} description={t("space_left_on_disk", { - space: formatBytes(diskFreeSpace?.free ?? 0), + space: formatBytes(diskFreeSpace ?? 0), })} onClose={onClose} > @@ -168,23 +185,32 @@ export function DownloadSettingsModal({ gap: `${SPACING_UNIT}px`, }} > -
- - - -
+ + {t("no_write_permission")} + + ) : undefined + } + rightContent={ + + } + />

@@ -195,7 +221,11 @@ export function DownloadSettingsModal({ diff --git a/src/renderer/src/pages/game-details/modals/reset-achievements-modal.tsx b/src/renderer/src/pages/game-details/modals/reset-achievements-modal.tsx index b053060f..642d32ba 100644 --- a/src/renderer/src/pages/game-details/modals/reset-achievements-modal.tsx +++ b/src/renderer/src/pages/game-details/modals/reset-achievements-modal.tsx @@ -2,7 +2,6 @@ import { useTranslation } from "react-i18next"; import { Button, Modal } from "@renderer/components"; import * as styles from "./remove-from-library-modal.css"; import type { Game } from "@types"; - type ResetAchievementsModalProps = Readonly<{ visible: boolean; game: Game; @@ -19,18 +18,21 @@ export function ResetAchievementsModal({ const { t } = useTranslation("game_details"); const handleResetAchievements = async () => { - await resetAchievements(); - onClose(); + try { + await resetAchievements(); + } finally { + onClose(); + } }; return (

From b68fe300ba8325d2c711983f61c5cc052dbdd08f Mon Sep 17 00:00:00 2001 From: Hachi-R Date: Fri, 3 Jan 2025 17:24:37 -0300 Subject: [PATCH 33/41] refactor: rename state variable for clarity --- .../src/pages/game-details/modals/game-options-modal.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/renderer/src/pages/game-details/modals/game-options-modal.tsx b/src/renderer/src/pages/game-details/modals/game-options-modal.tsx index b2d47dcb..e751a67b 100644 --- a/src/renderer/src/pages/game-details/modals/game-options-modal.tsx +++ b/src/renderer/src/pages/game-details/modals/game-options-modal.tsx @@ -34,7 +34,7 @@ export function GameOptionsModal({ const [launchOptions, setLaunchOptions] = useState(game.launchOptions ?? ""); const [showResetAchievementsModal, setShowResetAchievementsModal] = useState(false); - const [isDeleting, setIsDeleting] = useState(false); + const [isDeletingAchievements, setIsDeletingAchievements] = useState(false); const { removeGameInstaller, @@ -146,12 +146,12 @@ export function GameOptionsModal({ window.electron.platform === "linux"; const handleResetAchievements = async () => { - setIsDeleting(true); + setIsDeletingAchievements(true); try { await window.electron.resetGameAchievements(game.id); } finally { await updateGame(); - setIsDeleting(false); + setIsDeletingAchievements(false); } }; @@ -338,7 +338,7 @@ export function GameOptionsModal({ From ef3bf9890353996baabdf75a99263b3bd829b599 Mon Sep 17 00:00:00 2001 From: Hachi-R Date: Fri, 3 Jan 2025 17:36:55 -0300 Subject: [PATCH 34/41] feat: add success and error toast --- src/locales/en/translation.json | 4 +++- src/locales/pt-BR/translation.json | 4 +++- src/main/events/library/reset-game-achievements.ts | 3 ++- .../src/pages/game-details/modals/game-options-modal.tsx | 5 ++++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 3aea8fac..4e3dcb37 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -182,7 +182,9 @@ "no_write_permission": "Cannot download into this directory. Click here to learn more.", "reset_achievements": "Reset achievements", "reset_achievements_description": "This will reset all achievements for {{game}}", - "reset_achievements_title": "Are you sure?" + "reset_achievements_title": "Are you sure?", + "reset_achievements_success": "Achievements successfully reset", + "reset_achievements_error": "Failed to reset achievements" }, "activation": { "title": "Activate Hydra", diff --git a/src/locales/pt-BR/translation.json b/src/locales/pt-BR/translation.json index b6f2360b..2a80084f 100644 --- a/src/locales/pt-BR/translation.json +++ b/src/locales/pt-BR/translation.json @@ -170,7 +170,9 @@ "no_directory_selected": "Nenhum diretório selecionado", "reset_achievements": "Resetar conquistas", "reset_achievements_description": "Isso irá resetar todas as conquistas de {{game}}", - "reset_achievements_title": "Tem certeza?" + "reset_achievements_title": "Tem certeza?", + "reset_achievements_success": "Conquistas resetadas com sucesso", + "reset_achievements_error": "Falha ao resetar conquistas" }, "activation": { "title": "Ativação", diff --git a/src/main/events/library/reset-game-achievements.ts b/src/main/events/library/reset-game-achievements.ts index cfd0dc8a..eb55a412 100644 --- a/src/main/events/library/reset-game-achievements.ts +++ b/src/main/events/library/reset-game-achievements.ts @@ -30,7 +30,7 @@ const resetGameAchievements = async ( } ); - await HydraApi.delete(`/profile/games/${game.remoteId}/achievements`) + await HydraApi.delete(`/profile/games/achievements/${game.remoteId}`) .catch((err) => achievementsLogger.error(err)) .then((res) => achievementsLogger.log(res)); @@ -46,6 +46,7 @@ const resetGameAchievements = async ( ); } catch (error) { achievementsLogger.error(error); + throw error; } }; diff --git a/src/renderer/src/pages/game-details/modals/game-options-modal.tsx b/src/renderer/src/pages/game-details/modals/game-options-modal.tsx index e751a67b..fad02a96 100644 --- a/src/renderer/src/pages/game-details/modals/game-options-modal.tsx +++ b/src/renderer/src/pages/game-details/modals/game-options-modal.tsx @@ -149,8 +149,11 @@ export function GameOptionsModal({ setIsDeletingAchievements(true); try { await window.electron.resetGameAchievements(game.id); - } finally { await updateGame(); + showSuccessToast(t("reset_achievements_success")); + } catch (error) { + showErrorToast(t("reset_achievements_error")); + } finally { setIsDeletingAchievements(false); } }; From 2ddda4e4d225860a5d5b77850db3c096cc61217d Mon Sep 17 00:00:00 2001 From: Hachi-R Date: Fri, 3 Jan 2025 17:56:13 -0300 Subject: [PATCH 35/41] refactor: remove error logging --- src/main/events/library/reset-game-achievements.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/events/library/reset-game-achievements.ts b/src/main/events/library/reset-game-achievements.ts index eb55a412..17e00d5d 100644 --- a/src/main/events/library/reset-game-achievements.ts +++ b/src/main/events/library/reset-game-achievements.ts @@ -31,7 +31,6 @@ const resetGameAchievements = async ( ); await HydraApi.delete(`/profile/games/achievements/${game.remoteId}`) - .catch((err) => achievementsLogger.error(err)) .then((res) => achievementsLogger.log(res)); const gameAchievements = await getUnlockedAchievements( From e6d76a5dbeaaa56c21a196cb50b31d12e16e4045 Mon Sep 17 00:00:00 2001 From: Hachi-R Date: Fri, 3 Jan 2025 17:56:39 -0300 Subject: [PATCH 36/41] lint --- src/main/events/library/reset-game-achievements.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/events/library/reset-game-achievements.ts b/src/main/events/library/reset-game-achievements.ts index 17e00d5d..4d591a5d 100644 --- a/src/main/events/library/reset-game-achievements.ts +++ b/src/main/events/library/reset-game-achievements.ts @@ -30,8 +30,9 @@ const resetGameAchievements = async ( } ); - await HydraApi.delete(`/profile/games/achievements/${game.remoteId}`) - .then((res) => achievementsLogger.log(res)); + await HydraApi.delete(`/profile/games/achievements/${game.remoteId}`).then( + (res) => achievementsLogger.log(res) + ); const gameAchievements = await getUnlockedAchievements( game.objectID, From 190ddeb46ea30087f78d2c76dc1b24e727054ab5 Mon Sep 17 00:00:00 2001 From: Hachi-R Date: Fri, 3 Jan 2025 18:22:13 -0300 Subject: [PATCH 37/41] refactor: improve logging for deleted game achievements --- src/main/events/library/reset-game-achievements.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/events/library/reset-game-achievements.ts b/src/main/events/library/reset-game-achievements.ts index 4d591a5d..25b9e6d7 100644 --- a/src/main/events/library/reset-game-achievements.ts +++ b/src/main/events/library/reset-game-achievements.ts @@ -31,7 +31,7 @@ const resetGameAchievements = async ( ); await HydraApi.delete(`/profile/games/achievements/${game.remoteId}`).then( - (res) => achievementsLogger.log(res) + () => achievementsLogger.log(`Deleted achievements from ${game.remoteId} - ${game.objectID} - ${game.title}`) ); const gameAchievements = await getUnlockedAchievements( From 50616955003f6b75dd6780fa0303ac9960d33b19 Mon Sep 17 00:00:00 2001 From: Hachi-R Date: Fri, 3 Jan 2025 18:22:25 -0300 Subject: [PATCH 38/41] lint --- src/main/events/library/reset-game-achievements.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/events/library/reset-game-achievements.ts b/src/main/events/library/reset-game-achievements.ts index 25b9e6d7..8d52a3a6 100644 --- a/src/main/events/library/reset-game-achievements.ts +++ b/src/main/events/library/reset-game-achievements.ts @@ -31,7 +31,10 @@ const resetGameAchievements = async ( ); await HydraApi.delete(`/profile/games/achievements/${game.remoteId}`).then( - () => achievementsLogger.log(`Deleted achievements from ${game.remoteId} - ${game.objectID} - ${game.title}`) + () => + achievementsLogger.log( + `Deleted achievements from ${game.remoteId} - ${game.objectID} - ${game.title}` + ) ); const gameAchievements = await getUnlockedAchievements( From 2df57b071dab55d85bb6623c5cd740b5ac17fc20 Mon Sep 17 00:00:00 2001 From: Hachi-R Date: Fri, 3 Jan 2025 18:50:02 -0300 Subject: [PATCH 39/41] feat: disable reset achievement button if has no achievements --- .../src/pages/game-details/modals/game-options-modal.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/renderer/src/pages/game-details/modals/game-options-modal.tsx b/src/renderer/src/pages/game-details/modals/game-options-modal.tsx index fad02a96..3afc3870 100644 --- a/src/renderer/src/pages/game-details/modals/game-options-modal.tsx +++ b/src/renderer/src/pages/game-details/modals/game-options-modal.tsx @@ -26,7 +26,7 @@ export function GameOptionsModal({ const { showSuccessToast, showErrorToast } = useToast(); - const { updateGame, setShowRepacksModal, repacks, selectGameExecutable } = + const { updateGame, setShowRepacksModal, repacks, selectGameExecutable, achievements } = useContext(gameDetailsContext); const [showDeleteModal, setShowDeleteModal] = useState(false); @@ -43,6 +43,10 @@ export function GameOptionsModal({ cancelDownload, } = useDownload(); + const hasAchievements = + (achievements?.filter((achievement) => achievement.unlocked).length ?? 0) > + 0; + const deleting = isGameDeleting(game.id); const { lastPacket } = useDownload(); @@ -341,7 +345,7 @@ export function GameOptionsModal({ From 3efb1425b9835f191f8221e5902c6fc7cb522b2f Mon Sep 17 00:00:00 2001 From: Hachi-R Date: Fri, 3 Jan 2025 18:50:13 -0300 Subject: [PATCH 40/41] lint --- .../src/pages/game-details/modals/game-options-modal.tsx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/renderer/src/pages/game-details/modals/game-options-modal.tsx b/src/renderer/src/pages/game-details/modals/game-options-modal.tsx index 3afc3870..a677e4b9 100644 --- a/src/renderer/src/pages/game-details/modals/game-options-modal.tsx +++ b/src/renderer/src/pages/game-details/modals/game-options-modal.tsx @@ -26,8 +26,13 @@ export function GameOptionsModal({ const { showSuccessToast, showErrorToast } = useToast(); - const { updateGame, setShowRepacksModal, repacks, selectGameExecutable, achievements } = - useContext(gameDetailsContext); + const { + updateGame, + setShowRepacksModal, + repacks, + selectGameExecutable, + achievements, + } = useContext(gameDetailsContext); const [showDeleteModal, setShowDeleteModal] = useState(false); const [showRemoveGameModal, setShowRemoveGameModal] = useState(false); From cade56bb128c8da09301d2d2ddd1996624c96de0 Mon Sep 17 00:00:00 2001 From: Hachi-R Date: Fri, 3 Jan 2025 19:15:31 -0300 Subject: [PATCH 41/41] feat: disable reset achievements button if user is not logged in --- .../pages/game-details/modals/game-options-modal.tsx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/renderer/src/pages/game-details/modals/game-options-modal.tsx b/src/renderer/src/pages/game-details/modals/game-options-modal.tsx index a677e4b9..b06de28a 100644 --- a/src/renderer/src/pages/game-details/modals/game-options-modal.tsx +++ b/src/renderer/src/pages/game-details/modals/game-options-modal.tsx @@ -5,7 +5,7 @@ import type { Game } from "@types"; import * as styles from "./game-options-modal.css"; import { gameDetailsContext } from "@renderer/context"; import { DeleteGameModal } from "@renderer/pages/downloads/delete-game-modal"; -import { useDownload, useToast } from "@renderer/hooks"; +import { useDownload, useToast, useUserDetails } from "@renderer/hooks"; import { RemoveGameFromLibraryModal } from "./remove-from-library-modal"; import { ResetAchievementsModal } from "./reset-achievements-modal"; import { FileDirectoryIcon, FileIcon } from "@primer/octicons-react"; @@ -48,6 +48,8 @@ export function GameOptionsModal({ cancelDownload, } = useDownload(); + const { userDetails } = useUserDetails(); + const hasAchievements = (achievements?.filter((achievement) => achievement.unlocked).length ?? 0) > 0; @@ -350,7 +352,12 @@ export function GameOptionsModal({