mirror of
https://github.com/hydralauncher/hydra.git
synced 2026-01-19 09:13:57 +00:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c4698d951b | ||
|
|
3fe61ef36b | ||
|
|
9d601fa1c8 | ||
|
|
8cf4656d6d | ||
|
|
a922d9a166 |
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "hydralauncher",
|
"name": "hydralauncher",
|
||||||
"version": "3.4.6",
|
"version": "3.4.7",
|
||||||
"description": "Hydra",
|
"description": "Hydra",
|
||||||
"main": "./out/main/index.js",
|
"main": "./out/main/index.js",
|
||||||
"author": "Los Broxas",
|
"author": "Los Broxas",
|
||||||
|
|||||||
@@ -198,7 +198,8 @@
|
|||||||
"download_error_not_cached_on_hydra": "This download is not available on Nimbus.",
|
"download_error_not_cached_on_hydra": "This download is not available on Nimbus.",
|
||||||
"game_removed_from_favorites": "Game removed from favorites",
|
"game_removed_from_favorites": "Game removed from favorites",
|
||||||
"game_added_to_favorites": "Game added to favorites",
|
"game_added_to_favorites": "Game added to favorites",
|
||||||
"automatically_extract_downloaded_files": "Automatically extract downloaded files"
|
"automatically_extract_downloaded_files": "Automatically extract downloaded files",
|
||||||
|
"create_start_menu_shortcut": "Create Start Menu shortcut"
|
||||||
},
|
},
|
||||||
"activation": {
|
"activation": {
|
||||||
"title": "Activate Hydra",
|
"title": "Activate Hydra",
|
||||||
|
|||||||
@@ -187,7 +187,8 @@
|
|||||||
"download_error_not_cached_on_hydra": "Este download não está disponível no Nimbus.",
|
"download_error_not_cached_on_hydra": "Este download não está disponível no Nimbus.",
|
||||||
"game_removed_from_favorites": "Jogo removido dos favoritos",
|
"game_removed_from_favorites": "Jogo removido dos favoritos",
|
||||||
"game_added_to_favorites": "Jogo adicionado aos favoritos",
|
"game_added_to_favorites": "Jogo adicionado aos favoritos",
|
||||||
"automatically_extract_downloaded_files": "Extrair automaticamente os arquivos baixados"
|
"automatically_extract_downloaded_files": "Extrair automaticamente os arquivos baixados",
|
||||||
|
"create_start_menu_shortcut": "Criar atalho no Menu Iniciar"
|
||||||
},
|
},
|
||||||
"activation": {
|
"activation": {
|
||||||
"title": "Ativação",
|
"title": "Ativação",
|
||||||
|
|||||||
@@ -178,7 +178,8 @@
|
|||||||
"download_error_not_cached_on_real_debrid": "Este download não está disponível no Real-Debrid e a verificação do status do download não está disponível.",
|
"download_error_not_cached_on_real_debrid": "Este download não está disponível no Real-Debrid e a verificação do status do download não está disponível.",
|
||||||
"download_error_not_cached_on_torbox": "Este download não está disponível no TorBox e a verificação do status do download não está disponível.",
|
"download_error_not_cached_on_torbox": "Este download não está disponível no TorBox e a verificação do status do download não está disponível.",
|
||||||
"game_removed_from_favorites": "Jogo removido dos favoritos",
|
"game_removed_from_favorites": "Jogo removido dos favoritos",
|
||||||
"game_added_to_favorites": "Jogo adicionado aos favoritos"
|
"game_added_to_favorites": "Jogo adicionado aos favoritos",
|
||||||
|
"create_start_menu_shortcut": "Criar atalho no Menu Iniciar"
|
||||||
},
|
},
|
||||||
"activation": {
|
"activation": {
|
||||||
"title": "Ativação",
|
"title": "Ativação",
|
||||||
|
|||||||
@@ -8,6 +8,14 @@ export const defaultDownloadsPath = SystemPath.getPath("downloads");
|
|||||||
|
|
||||||
export const isStaging = import.meta.env.MAIN_VITE_API_URL.includes("staging");
|
export const isStaging = import.meta.env.MAIN_VITE_API_URL.includes("staging");
|
||||||
|
|
||||||
|
export const windowsStartMenuPath = path.join(
|
||||||
|
SystemPath.getPath("appData"),
|
||||||
|
"Microsoft",
|
||||||
|
"Windows",
|
||||||
|
"Start Menu",
|
||||||
|
"Programs"
|
||||||
|
);
|
||||||
|
|
||||||
export const levelDatabasePath = path.join(
|
export const levelDatabasePath = path.join(
|
||||||
SystemPath.getPath("userData"),
|
SystemPath.getPath("userData"),
|
||||||
`hydra-db${isStaging ? "-staging" : ""}`
|
`hydra-db${isStaging ? "-staging" : ""}`
|
||||||
|
|||||||
@@ -3,14 +3,16 @@ import createDesktopShortcut from "create-desktop-shortcuts";
|
|||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import { app } from "electron";
|
import { app } from "electron";
|
||||||
import { removeSymbolsFromName } from "@shared";
|
import { removeSymbolsFromName } from "@shared";
|
||||||
import { GameShop } from "@types";
|
import { GameShop, ShortcutLocation } from "@types";
|
||||||
import { gamesSublevel, levelKeys } from "@main/level";
|
import { gamesSublevel, levelKeys } from "@main/level";
|
||||||
import { SystemPath } from "@main/services/system-path";
|
import { SystemPath } from "@main/services/system-path";
|
||||||
|
import { windowsStartMenuPath } from "@main/constants";
|
||||||
|
|
||||||
const createGameShortcut = async (
|
const createGameShortcut = async (
|
||||||
_event: Electron.IpcMainInvokeEvent,
|
_event: Electron.IpcMainInvokeEvent,
|
||||||
shop: GameShop,
|
shop: GameShop,
|
||||||
objectId: string
|
objectId: string,
|
||||||
|
location: ShortcutLocation
|
||||||
): Promise<boolean> => {
|
): Promise<boolean> => {
|
||||||
const gameKey = levelKeys.game(shop, objectId);
|
const gameKey = levelKeys.game(shop, objectId);
|
||||||
const game = await gamesSublevel.get(gameKey);
|
const game = await gamesSublevel.get(gameKey);
|
||||||
@@ -25,7 +27,10 @@ const createGameShortcut = async (
|
|||||||
const options = {
|
const options = {
|
||||||
filePath,
|
filePath,
|
||||||
name: removeSymbolsFromName(game.title),
|
name: removeSymbolsFromName(game.title),
|
||||||
outputPath: SystemPath.getPath("desktop"),
|
outputPath:
|
||||||
|
location === "desktop"
|
||||||
|
? SystemPath.getPath("desktop")
|
||||||
|
: windowsStartMenuPath,
|
||||||
};
|
};
|
||||||
|
|
||||||
return createDesktopShortcut({
|
return createDesktopShortcut({
|
||||||
|
|||||||
@@ -1,19 +1,7 @@
|
|||||||
import { registerEvent } from "../register-event";
|
import { registerEvent } from "../register-event";
|
||||||
import AutoLaunch from "auto-launch";
|
import AutoLaunch from "auto-launch";
|
||||||
import { app } from "electron";
|
import { app } from "electron";
|
||||||
import path from "path";
|
|
||||||
import fs from "node:fs";
|
|
||||||
import { logger } from "@main/services";
|
import { logger } from "@main/services";
|
||||||
import { SystemPath } from "@main/services/system-path";
|
|
||||||
|
|
||||||
const windowsStartupPath = path.join(
|
|
||||||
SystemPath.getPath("appData"),
|
|
||||||
"Microsoft",
|
|
||||||
"Windows",
|
|
||||||
"Start Menu",
|
|
||||||
"Programs",
|
|
||||||
"Startup"
|
|
||||||
);
|
|
||||||
|
|
||||||
const autoLaunch = async (
|
const autoLaunch = async (
|
||||||
_event: Electron.IpcMainInvokeEvent,
|
_event: Electron.IpcMainInvokeEvent,
|
||||||
@@ -31,10 +19,6 @@ const autoLaunch = async (
|
|||||||
logger.error(err);
|
logger.error(err);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if (process.platform == "win32") {
|
|
||||||
fs.rm(path.join(windowsStartupPath, "Hydra.vbs"), () => {});
|
|
||||||
}
|
|
||||||
|
|
||||||
appLauncher.disable().catch((err) => {
|
appLauncher.disable().catch((err) => {
|
||||||
logger.error(err);
|
logger.error(err);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ export class CommonRedistManager {
|
|||||||
for (const redist of this.redistributables) {
|
for (const redist of this.redistributables) {
|
||||||
const filePath = path.join(commonRedistPath, redist);
|
const filePath = path.join(commonRedistPath, redist);
|
||||||
|
|
||||||
if (fs.existsSync(filePath)) {
|
if (fs.existsSync(filePath) && redist !== "install.bat") {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import type {
|
|||||||
GameAchievement,
|
GameAchievement,
|
||||||
Theme,
|
Theme,
|
||||||
FriendRequestSync,
|
FriendRequestSync,
|
||||||
|
ShortcutLocation,
|
||||||
} from "@types";
|
} from "@types";
|
||||||
import type { AuthPage, CatalogueCategory } from "@shared";
|
import type { AuthPage, CatalogueCategory } from "@shared";
|
||||||
import type { AxiosProgressEvent } from "axios";
|
import type { AxiosProgressEvent } from "axios";
|
||||||
@@ -122,8 +123,11 @@ contextBridge.exposeInMainWorld("electron", {
|
|||||||
),
|
),
|
||||||
addGameToLibrary: (shop: GameShop, objectId: string, title: string) =>
|
addGameToLibrary: (shop: GameShop, objectId: string, title: string) =>
|
||||||
ipcRenderer.invoke("addGameToLibrary", shop, objectId, title),
|
ipcRenderer.invoke("addGameToLibrary", shop, objectId, title),
|
||||||
createGameShortcut: (shop: GameShop, objectId: string) =>
|
createGameShortcut: (
|
||||||
ipcRenderer.invoke("createGameShortcut", shop, objectId),
|
shop: GameShop,
|
||||||
|
objectId: string,
|
||||||
|
location: ShortcutLocation
|
||||||
|
) => ipcRenderer.invoke("createGameShortcut", shop, objectId, location),
|
||||||
updateExecutablePath: (
|
updateExecutablePath: (
|
||||||
shop: GameShop,
|
shop: GameShop,
|
||||||
objectId: string,
|
objectId: string,
|
||||||
|
|||||||
7
src/renderer/src/declaration.d.ts
vendored
7
src/renderer/src/declaration.d.ts
vendored
@@ -32,6 +32,7 @@ import type {
|
|||||||
Theme,
|
Theme,
|
||||||
Badge,
|
Badge,
|
||||||
Auth,
|
Auth,
|
||||||
|
ShortcutLocation,
|
||||||
} from "@types";
|
} from "@types";
|
||||||
import type { AxiosProgressEvent } from "axios";
|
import type { AxiosProgressEvent } from "axios";
|
||||||
import type disk from "diskusage";
|
import type disk from "diskusage";
|
||||||
@@ -101,7 +102,11 @@ declare global {
|
|||||||
objectId: string,
|
objectId: string,
|
||||||
title: string
|
title: string
|
||||||
) => Promise<void>;
|
) => Promise<void>;
|
||||||
createGameShortcut: (shop: GameShop, objectId: string) => Promise<boolean>;
|
createGameShortcut: (
|
||||||
|
shop: GameShop,
|
||||||
|
objectId: string,
|
||||||
|
location: ShortcutLocation
|
||||||
|
) => Promise<boolean>;
|
||||||
updateExecutablePath: (
|
updateExecutablePath: (
|
||||||
shop: GameShop,
|
shop: GameShop,
|
||||||
objectId: string,
|
objectId: string,
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export const toastSlice = createSlice({
|
|||||||
state.title = action.payload.title;
|
state.title = action.payload.title;
|
||||||
state.message = action.payload.message;
|
state.message = action.payload.message;
|
||||||
state.type = action.payload.type;
|
state.type = action.payload.type;
|
||||||
state.duration = action.payload.duration ?? 2000;
|
state.duration = action.payload.duration ?? 3000;
|
||||||
state.visible = true;
|
state.visible = true;
|
||||||
},
|
},
|
||||||
closeToast: (state) => {
|
closeToast: (state) => {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useContext, useRef, useState } from "react";
|
import { useContext, useRef, useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Button, CheckboxField, Modal, TextField } from "@renderer/components";
|
import { Button, CheckboxField, Modal, TextField } from "@renderer/components";
|
||||||
import type { LibraryGame } from "@types";
|
import type { LibraryGame, ShortcutLocation } from "@types";
|
||||||
import { gameDetailsContext } from "@renderer/context";
|
import { gameDetailsContext } from "@renderer/context";
|
||||||
import { DeleteGameModal } from "@renderer/pages/downloads/delete-game-modal";
|
import { DeleteGameModal } from "@renderer/pages/downloads/delete-game-modal";
|
||||||
import { useDownload, useToast, useUserDetails } from "@renderer/hooks";
|
import { useDownload, useToast, useUserDetails } from "@renderer/hooks";
|
||||||
@@ -107,15 +107,18 @@ export function GameOptionsModal({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCreateShortcut = async () => {
|
const handleCreateShortcut = async (location: ShortcutLocation) => {
|
||||||
window.electron
|
window.electron
|
||||||
.createGameShortcut(game.shop, game.objectId)
|
.createGameShortcut(game.shop, game.objectId, location)
|
||||||
.then((success) => {
|
.then((success) => {
|
||||||
if (success) {
|
if (success) {
|
||||||
showSuccessToast(t("create_shortcut_success"));
|
showSuccessToast(t("create_shortcut_success"));
|
||||||
} else {
|
} else {
|
||||||
showErrorToast(t("create_shortcut_error"));
|
showErrorToast(t("create_shortcut_error"));
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
showErrorToast(t("create_shortcut_error"));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -176,6 +179,9 @@ export function GameOptionsModal({
|
|||||||
const shouldShowWinePrefixConfiguration =
|
const shouldShowWinePrefixConfiguration =
|
||||||
window.electron.platform === "linux";
|
window.electron.platform === "linux";
|
||||||
|
|
||||||
|
const shouldShowCreateStartMenuShortcut =
|
||||||
|
window.electron.platform === "win32";
|
||||||
|
|
||||||
const handleResetAchievements = async () => {
|
const handleResetAchievements = async () => {
|
||||||
setIsDeletingAchievements(true);
|
setIsDeletingAchievements(true);
|
||||||
try {
|
try {
|
||||||
@@ -278,9 +284,20 @@ export function GameOptionsModal({
|
|||||||
>
|
>
|
||||||
{t("open_folder")}
|
{t("open_folder")}
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={handleCreateShortcut} theme="outline">
|
<Button
|
||||||
|
onClick={() => handleCreateShortcut("desktop")}
|
||||||
|
theme="outline"
|
||||||
|
>
|
||||||
{t("create_shortcut")}
|
{t("create_shortcut")}
|
||||||
</Button>
|
</Button>
|
||||||
|
{shouldShowCreateStartMenuShortcut && (
|
||||||
|
<Button
|
||||||
|
onClick={() => handleCreateShortcut("start_menu")}
|
||||||
|
theme="outline"
|
||||||
|
>
|
||||||
|
{t("create_start_menu_shortcut")}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
export type GameShop = "steam" | "epic";
|
export type GameShop = "steam" | "epic";
|
||||||
|
|
||||||
|
export type ShortcutLocation = "desktop" | "start_menu";
|
||||||
|
|
||||||
export interface UnlockedAchievement {
|
export interface UnlockedAchievement {
|
||||||
name: string;
|
name: string;
|
||||||
unlockTime: number;
|
unlockTime: number;
|
||||||
|
|||||||
Reference in New Issue
Block a user