Compare commits

...

18 Commits

Author SHA1 Message Date
Chubby Granny Chaser
a21f2b9614 Merge pull request #1579 from hydralauncher/feat/ludusavi-upgrade
Feat/ludusavi upgrade
2025-04-18 23:12:48 +01:00
Chubby Granny Chaser
c16cbfe04e Merge branch 'main' into feat/ludusavi-upgrade 2025-04-18 23:09:33 +01:00
Chubby Granny Chaser
4ff41da05a Merge branch 'feat/ludusavi-upgrade' of github.com:hydralauncher/hydra into feat/ludusavi-upgrade 2025-04-18 22:59:56 +01:00
Chubby Granny Chaser
a12e5a15fa chore: bumping version 2025-04-18 22:57:28 +01:00
Zamitto
cc2311529b Merge pull request #1580 from caumeira/patch-1
chore: update create-desktop-shortcuts
2025-04-18 17:04:41 -03:00
Carlos Meira
18b63d735d Update yarn.lock 2025-04-18 16:47:49 -03:00
Zamitto
7379113dc8 chore: update issue template 2025-04-18 12:33:33 -03:00
Carlos Meira
ea85da259c chore: update create-desktop-shortcuts
Fix a issue with bugged icons
2025-04-18 11:27:07 -03:00
Zamitto
b8084d6f67 feat: add await to ensure HydraApi is setup before renderer opens window 2025-04-18 07:22:01 -03:00
Chubby Granny Chaser
97589e63fa Merge branch 'feat/ludusavi-upgrade' of github.com:hydralauncher/hydra into feat/ludusavi-upgrade 2025-04-18 00:07:43 +01:00
Chubby Granny Chaser
2539f67e13 Merge branch 'main' of github.com:hydralauncher/hydra into feat/ludusavi-upgrade 2025-04-18 00:07:36 +01:00
Chubby Granny Chaser
cc4aed2e17 fix: fixing date on backup upload 2025-04-18 00:06:30 +01:00
Chubby Granny Chaser
9ea68e629a Merge branch 'main' into feat/ludusavi-upgrade 2025-04-17 23:48:49 +01:00
Chubby Granny Chaser
8c66b9a499 fix: fixing date on backup upload 2025-04-17 23:44:25 +01:00
Chubby Granny Chaser
8fb183007a Merge pull request #1571 from Lianela/main
Update spanish translation.json
2025-04-17 23:29:23 +01:00
Chubby Granny Chaser
d0ac819da5 feat: upgrading ludusavi 2025-04-17 23:27:22 +01:00
Chubby Granny Chaser
f4e428a574 feat: upgrading ludusavi 2025-04-17 23:23:06 +01:00
Lianela
69879a0303 Update translation.json 2025-04-15 18:29:38 -06:00
13 changed files with 95 additions and 75 deletions

View File

@@ -33,9 +33,9 @@ body:
attributes:
label: Additional information and data
description: |
Add screenshots and upload your logs file here.
Logs location on Windows: "%appdata%/hydra"
Logs location on Linux: "~/.config/hydra/"
Add screenshots and upload your all logs file here.
Logs location on Windows: "%appdata%/hydralauncher/logs"
Logs location on Linux: "~/.config/hydralauncher/logs"
validations:
required: true
- type: input

View File

@@ -88,6 +88,18 @@ jobs:
dist/*.blockmap
dist/*.pacman
- name: Upload build
env:
BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
S3_ENDPOINT: ${{ secrets.S3_ENDPOINT }}
S3_ACCESS_KEY_ID: ${{ secrets.S3_ACCESS_KEY_ID }}
S3_SECRET_ACCESS_KEY: ${{ secrets.S3_SECRET_ACCESS_KEY }}
S3_BUILDS_BUCKET_NAME: ${{ secrets.S3_BUILDS_BUCKET_NAME }}
BUILDS_URL: ${{ secrets.BUILDS_URL }}
BUILD_WEBHOOK_URL: ${{ secrets.BUILD_WEBHOOK_URL }}
GITHUB_ACTOR: ${{ github.actor }}
run: node scripts/upload-build.cjs
- name: Release
uses: softprops/action-gh-release@v2
with:

View File

@@ -1,6 +1,6 @@
{
"name": "hydralauncher",
"version": "3.4.3",
"version": "3.4.4",
"description": "Hydra",
"main": "./out/main/index.js",
"author": "Los Broxas",
@@ -48,7 +48,7 @@
"classnames": "^2.5.1",
"color": "^4.2.3",
"color.js": "^1.2.0",
"create-desktop-shortcuts": "^1.11.0",
"create-desktop-shortcuts": "^1.11.1",
"date-fns": "^3.6.0",
"dexie": "^4.0.10",
"diskusage": "^1.2.0",
@@ -59,7 +59,6 @@
"i18next-browser-languagedetector": "^7.2.1",
"jsdom": "^24.0.0",
"jsonwebtoken": "^9.0.2",
"kill-port": "^2.0.1",
"lodash-es": "^4.17.21",
"parse-torrent": "^11.0.17",
"piscina": "^4.7.0",

View File

@@ -1,4 +1,5 @@
const { default: axios } = require("axios");
const tar = require("tar");
const util = require("node:util");
const fs = require("node:fs");
const path = require("node:path");
@@ -6,10 +7,12 @@ const { spawnSync } = require("node:child_process");
const exec = util.promisify(require("node:child_process").exec);
const ludusaviVersion = "0.29.0";
const fileName = {
win32: "ludusavi-v0.25.0-win64.zip",
linux: "ludusavi-v0.25.0-linux.zip",
darwin: "ludusavi-v0.25.0-mac.zip",
win32: `ludusavi-v${ludusaviVersion}-win64.zip`,
linux: `ludusavi-v${ludusaviVersion}-linux.tar.gz`,
darwin: `ludusavi-v${ludusaviVersion}-mac.tar.gz`,
};
const downloadLudusavi = async () => {
@@ -19,7 +22,7 @@ const downloadLudusavi = async () => {
}
const file = fileName[process.platform];
const downloadUrl = `https://github.com/mtkennerly/ludusavi/releases/download/v0.25.0/${file}`;
const downloadUrl = `https://github.com/mtkennerly/ludusavi/releases/download/v${ludusaviVersion}/${file}`;
console.log(`Downloading ${file}...`);
@@ -31,10 +34,18 @@ const downloadLudusavi = async () => {
console.log(`Downloaded ${file}, extracting...`);
const pwd = process.cwd();
const targetPath = path.join(pwd, "ludusavi");
await exec(`npx extract-zip ${file} ${targetPath}`);
await fs.promises.mkdir(targetPath, { recursive: true });
if (process.platform === "win32") {
await exec(`npx extract-zip ${file} ${targetPath}`);
} else {
await tar.x({
file: file,
cwd: targetPath,
});
}
if (process.platform !== "win32") {
fs.chmodSync(path.join(targetPath, "ludusavi"), 0o755);

View File

@@ -44,6 +44,9 @@
"downloading_metadata": "Descargando metadatos de {{title}}…",
"downloading": "Descargando {{title}}… ({{percentage}} completado) - Finalizando {{eta}} - {{speed}}",
"calculating_eta": "Descargando {{title}}… ({{percentage}} completado) - Calculando tiempo restante…",
"installation_complete": "Instalación completada",
"installation_complete_message": "Common redistributables instalados exitosamente",
"installing_common_redist": "{{log}}…",
"checking_files": "Verificando archivos de {{title}}… ({{percentage}} completado)"
},
"catalogue": {
@@ -59,6 +62,8 @@
},
"game_details": {
"open_download_options": "Ver opciones de descargas",
"automatically_extract_downloaded_files": "Extraer automáticamente archivos descargados",
"download_error_not_cached_on_hydra": "Esta descarga no está disponible en Nimbus.",
"download_options_zero": "No hay opciones de descargas disponibles",
"download_options_one": "{{count}} opción de descarga",
"download_options_other": "{{count}} opciones de descargas",
@@ -230,10 +235,19 @@
"seeding": "Seeding",
"stop_seeding": "Detener seeding",
"resume_seeding": "Continuar seeding",
"extract": "Extraer archivos",
"extracting": "Extrayendo archivos…",
"options": "Gestionar"
},
"settings": {
"downloads_path": "Ruta de descarga",
"common_redist": "Common redistributables",
"common_redist_description": "Las Common redistributables son requeridos para ejecutar algunos juegos. Es recomendado instalarlos para evitar problemas.",
"create_real_debrid_account": "Presiona acá si no tienes una cuenta de Real-Debrid aún",
"create_torbox_account": "Presiona acá si no tienes una cuenta de TorBox aún",
"install_common_redist": "Instalar",
"installing_common_redist": "Instalando…",
"show_download_speed_in_megabytes": "Mostrar velocidad de descargar en megabytes por segundo",
"change": "Cambiar",
"notifications": "Notificaciones",
"enable_download_notifications": "Cuando se completa una descarga",
@@ -346,6 +360,8 @@
},
"notifications": {
"download_complete": "Descarga completada",
"extraction_complete": "Extracción completada",
"game_extracted": "{{title}} extraído exitosamente",
"game_ready_to_install": "{{title}} está listo para instalarse",
"repack_list_updated": "Lista de repacks actualizadas",
"repack_count_one": "{{count}} repack ha sido añadido",
@@ -475,6 +491,7 @@
},
"hydra_cloud": {
"subscription_tour_title": "Suscripción Hydra Cloud",
"debrid_description": "Descargas hasta x4 más rápidas con Nimbus",
"subscribe_now": "Suscribirse ahora",
"cloud_saving": "Guardado en la nube",
"cloud_achievements": "Guarda tus logros en la nube",

View File

@@ -1,8 +1,6 @@
import { CloudSync } from "@main/services";
import { registerEvent } from "../register-event";
import type { GameShop } from "@types";
import i18next, { t } from "i18next";
import { formatDate } from "date-fns";
const uploadSaveGame = async (
_event: Electron.IpcMainInvokeEvent,
@@ -10,16 +8,11 @@ const uploadSaveGame = async (
shop: GameShop,
downloadOptionTitle: string | null
) => {
const { language } = i18next;
return CloudSync.uploadSaveGame(
objectId,
shop,
downloadOptionTitle,
t("backup_from", {
ns: "game_details",
date: formatDate(new Date(), language),
})
CloudSync.getBackupLabel(false)
);
};

View File

@@ -3,7 +3,6 @@ import updater from "electron-updater";
import i18n from "i18next";
import path from "node:path";
import url from "node:url";
import kill from "kill-port";
import { electronApp, optimizer } from "@electron-toolkit/utils";
import { logger, WindowManager } from "@main/services";
import resources from "@locales";
@@ -58,7 +57,7 @@ app.whenReady().then(async () => {
return net.fetch(url.pathToFileURL(decodeURI(filePath)).toString());
});
await kill(PythonRPC.RPC_PORT).finally(() => loadState());
await loadState();
const language = await db.get<string, string>(levelKeys.language, {
valueEncoding: "utf-8",

View File

@@ -32,7 +32,7 @@ export const loadState = async () => {
Ludusavi.addManifestToLudusaviConfig();
HydraApi.setupApi().then(() => {
await HydraApi.setupApi().then(() => {
uploadGamesBatch();
});

View File

@@ -13,9 +13,28 @@ import { logger } from "./logger";
import { WindowManager } from "./window-manager";
import axios from "axios";
import { Ludusavi } from "./ludusavi";
import { SubscriptionRequiredError } from "@shared";
import { formatDate, SubscriptionRequiredError } from "@shared";
import i18next, { t } from "i18next";
export class CloudSync {
public static getBackupLabel(automatic: boolean) {
const language = i18next.language;
const date = formatDate(new Date(), language);
if (automatic) {
return t("automatic_backup_from", {
ns: "game_details",
date,
});
}
return t("backup_from", {
ns: "game_details",
date,
});
}
private static async bundleBackup(
shop: GameShop,
objectId: string,
@@ -25,7 +44,11 @@ export class CloudSync {
// Remove existing backup
if (fs.existsSync(backupPath)) {
fs.rmSync(backupPath, { recursive: true });
try {
await fs.promises.rm(backupPath, { recursive: true });
} catch (error) {
logger.error("Failed to remove backup path", error);
}
}
await Ludusavi.backupGame(shop, objectId, backupPath, winePrefix);
@@ -101,11 +124,10 @@ export class CloudSync {
true
);
fs.rm(bundleLocation, (err) => {
if (err) {
logger.error("Failed to remove tar file", err);
throw err;
}
});
try {
await fs.promises.unlink(bundleLocation);
} catch (error) {
logger.error("Failed to remove tar file", error);
}
}
}

View File

@@ -6,9 +6,7 @@ import axios from "axios";
import { exec } from "child_process";
import { ProcessPayload } from "./download/types";
import { gamesSublevel, levelKeys } from "@main/level";
import i18next, { t } from "i18next";
import { CloudSync } from "./cloud-sync";
import { formatDate } from "date-fns";
const commands = {
findWineDir: `lsof -c wine 2>/dev/null | grep '/drive_c/windows$' | head -n 1 | awk '{for(i=9;i<=NF;i++) printf "%s ", $i; print ""}'`,
@@ -229,17 +227,12 @@ function onOpenGame(game: Game) {
if (game.remoteId) {
updateGamePlaytime(game, 0, new Date()).catch(() => {});
const { language } = i18next;
if (game.automaticCloudSync) {
CloudSync.uploadSaveGame(
game.objectId,
game.shop,
null,
t("automatic_backup_from", {
ns: "game_details",
date: formatDate(new Date(), language),
})
CloudSync.getBackupLabel(true)
);
}
} else {
@@ -298,8 +291,6 @@ const onCloseGame = (game: Game) => {
)!;
gamesPlaytime.delete(levelKeys.game(game.shop, game.objectId));
const { language } = i18next;
if (game.remoteId) {
updateGamePlaytime(
game,
@@ -312,10 +303,7 @@ const onCloseGame = (game: Game) => {
game.objectId,
game.shop,
null,
t("automatic_backup_from", {
ns: "game_details",
date: formatDate(new Date(), language),
})
CloudSync.getBackupLabel(true)
);
}
} else {

View File

@@ -1,7 +1,6 @@
import { formatDate, getDateLocale } from "@shared";
import { format, formatDistance, subMilliseconds } from "date-fns";
import type { FormatDistanceOptions } from "date-fns";
import { enUS } from "date-fns/locale";
import { useTranslation } from "react-i18next";
export function useDate() {
@@ -41,10 +40,10 @@ export function useDate() {
},
formatDateTime: (date: number | Date | string): string => {
const locale = getDateLocale(language);
return format(
date,
locale == enUS ? "MM/dd/yyyy - HH:mm" : "dd/MM/yyyy HH:mm"
language == "en" ? "MM-dd-yyyy - hh:mm a" : "dd/MM/yyyy HH:mm",
{ locale: getDateLocale(language) }
);
},

View File

@@ -173,7 +173,5 @@ export const formatDate = (
language: string
): string => {
if (isNaN(new Date(date).getDate())) return "N/A";
const locale = getDateLocale(language);
return format(date, locale == enUS ? "MM/dd/yyyy" : "dd/MM/yyyy");
return format(date, language == "en" ? "MM-dd-yyyy" : "dd/MM/yyyy");
};

View File

@@ -1460,9 +1460,9 @@
optionalDependencies:
global-agent "^3.0.0"
"@electron/node-gyp@git+https://github.com/electron/node-gyp.git#06b29aafb7708acef8b3669835c8a7857ebc92d2":
"@electron/node-gyp@https://github.com/electron/node-gyp#06b29aafb7708acef8b3669835c8a7857ebc92d2":
version "10.2.0-electron.1"
resolved "git+https://github.com/electron/node-gyp.git#06b29aafb7708acef8b3669835c8a7857ebc92d2"
resolved "https://github.com/electron/node-gyp#06b29aafb7708acef8b3669835c8a7857ebc92d2"
dependencies:
env-paths "^2.2.0"
exponential-backoff "^3.1.1"
@@ -4501,10 +4501,10 @@ crc@^3.8.0:
dependencies:
buffer "^5.1.0"
create-desktop-shortcuts@^1.11.0:
version "1.11.0"
resolved "https://registry.yarnpkg.com/create-desktop-shortcuts/-/create-desktop-shortcuts-1.11.0.tgz#8eed89329e9bce70dece46d02a80573fe1f2536d"
integrity sha512-nmVtPVqNyMuAyMpDnd7l++hb2laqCWZXnHQaFhqGT1YEi2Ve3unu6QyuyIpGxAwIscNHcG1Ehnl+lFw6ygB2nQ==
create-desktop-shortcuts@^1.11.1:
version "1.11.1"
resolved "https://registry.yarnpkg.com/create-desktop-shortcuts/-/create-desktop-shortcuts-1.11.1.tgz#59f9dced7931bda551c0717791a909419472c809"
integrity sha512-EiHvxrMXXEp4xDD3Nvu1FKLueL9+aBWFYtuTlstYZLIg9H45SoYciizteNB+hvQAls3cRSpoXCM7c4q+lcJpyw==
dependencies:
which "2.0.2"
@@ -5814,11 +5814,6 @@ get-symbol-description@^1.1.0:
es-errors "^1.3.0"
get-intrinsic "^1.2.6"
get-them-args@1.3.2:
version "1.3.2"
resolved "https://registry.yarnpkg.com/get-them-args/-/get-them-args-1.3.2.tgz#74a20ba8a4abece5ae199ad03f2bcc68fdfc9ba5"
integrity sha512-LRn8Jlk+DwZE4GTlDbT3Hikd1wSHgLMme/+7ddlqKd7ldwR6LjJgTVWzBnR01wnYGe4KgrXjg287RaI22UHmAw==
git-raw-commits@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/git-raw-commits/-/git-raw-commits-4.0.0.tgz#b212fd2bff9726d27c1283a1157e829490593285"
@@ -6826,14 +6821,6 @@ keyv@^4.0.0, keyv@^4.5.3:
dependencies:
json-buffer "3.0.1"
kill-port@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/kill-port/-/kill-port-2.0.1.tgz#e5e18e2706b13d54320938be42cb7d40609b15cf"
integrity sha512-e0SVOV5jFo0mx8r7bS29maVWp17qGqLBZ5ricNSajON6//kmb7qqqNnml4twNE8Dtj97UQD+gNFOaipS/q1zzQ==
dependencies:
get-them-args "1.3.2"
shell-exec "1.0.2"
language-subtag-registry@^0.3.20:
version "0.3.23"
resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz#23529e04d9e3b74679d70142df3fd2eb6ec572e7"
@@ -8459,11 +8446,6 @@ shebang-regex@^3.0.0:
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
shell-exec@1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/shell-exec/-/shell-exec-1.0.2.tgz#2e9361b0fde1d73f476c4b6671fa17785f696756"
integrity sha512-jyVd+kU2X+mWKMmGhx4fpWbPsjvD53k9ivqetutVW/BQ+WIZoDoP4d8vUMGezV6saZsiNoW2f9GIhg9Dondohg==
side-channel-list@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/side-channel-list/-/side-channel-list-1.0.0.tgz#10cb5984263115d3b7a0e336591e290a830af8ad"