mirror of
https://github.com/hydralauncher/hydra.git
synced 2026-01-11 13:56:16 +00:00
feat: adding api call for decky plugin
This commit is contained in:
@@ -78,6 +78,7 @@
|
||||
"edit_game_modal_drop_to_replace_logo": "Drop to replace logo",
|
||||
"edit_game_modal_drop_to_replace_hero": "Drop to replace hero",
|
||||
"install_decky_plugin": "Install Decky Plugin",
|
||||
"update_decky_plugin": "Update Decky Plugin",
|
||||
"decky_plugin_installed_version": "Decky Plugin (v{{version}})",
|
||||
"install_decky_plugin_title": "Install Hydra Decky Plugin",
|
||||
"install_decky_plugin_message": "This will download and install the Hydra plugin for Decky Loader. This may require elevated permissions. Continue?",
|
||||
|
||||
@@ -78,6 +78,7 @@
|
||||
"edit_game_modal_drop_to_replace_logo": "Solte para substituir o logo",
|
||||
"edit_game_modal_drop_to_replace_hero": "Solte para substituir o hero",
|
||||
"install_decky_plugin": "Instalar Plugin Decky",
|
||||
"update_decky_plugin": "Atualizar Plugin Decky",
|
||||
"decky_plugin_installed_version": "Plugin Decky (v{{version}})",
|
||||
"install_decky_plugin_title": "Instalar Plugin Hydra Decky",
|
||||
"install_decky_plugin_message": "Isso irá baixar e instalar o plugin Hydra para Decky Loader. Pode ser necessário permissões elevadas. Continuar?",
|
||||
|
||||
@@ -1,17 +1,37 @@
|
||||
import { registerEvent } from "../register-event";
|
||||
import { logger } from "@main/services";
|
||||
import { logger, HydraApi } from "@main/services";
|
||||
import { HYDRA_DECKY_PLUGIN_LOCATION } from "@main/constants";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
interface DeckyReleaseInfo {
|
||||
version: string;
|
||||
downloadUrl: string;
|
||||
}
|
||||
|
||||
const getHydraDeckyPluginInfo = async (
|
||||
_event: Electron.IpcMainInvokeEvent
|
||||
): Promise<{
|
||||
installed: boolean;
|
||||
version: string | null;
|
||||
path: string;
|
||||
outdated: boolean;
|
||||
expectedVersion: string | null;
|
||||
}> => {
|
||||
try {
|
||||
// Fetch the expected version from API
|
||||
let expectedVersion: string | null = null;
|
||||
try {
|
||||
const releaseInfo = await HydraApi.get<DeckyReleaseInfo>(
|
||||
"/decky/release",
|
||||
{},
|
||||
{ needsAuth: false }
|
||||
);
|
||||
expectedVersion = releaseInfo.version;
|
||||
} catch (error) {
|
||||
logger.error("Failed to fetch Decky release info:", error);
|
||||
}
|
||||
|
||||
// Check if plugin folder exists
|
||||
if (!fs.existsSync(HYDRA_DECKY_PLUGIN_LOCATION)) {
|
||||
logger.log("Hydra Decky plugin not installed");
|
||||
@@ -19,6 +39,8 @@ const getHydraDeckyPluginInfo = async (
|
||||
installed: false,
|
||||
version: null,
|
||||
path: HYDRA_DECKY_PLUGIN_LOCATION,
|
||||
outdated: true,
|
||||
expectedVersion,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -34,6 +56,8 @@ const getHydraDeckyPluginInfo = async (
|
||||
installed: false,
|
||||
version: null,
|
||||
path: HYDRA_DECKY_PLUGIN_LOCATION,
|
||||
outdated: true,
|
||||
expectedVersion,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -42,12 +66,18 @@ const getHydraDeckyPluginInfo = async (
|
||||
const packageJson = JSON.parse(packageJsonContent);
|
||||
const version = packageJson.version;
|
||||
|
||||
logger.log(`Hydra Decky plugin installed, version: ${version}`);
|
||||
const outdated = expectedVersion ? version !== expectedVersion : false;
|
||||
|
||||
logger.log(
|
||||
`Hydra Decky plugin installed, version: ${version}, expected: ${expectedVersion}, outdated: ${outdated}`
|
||||
);
|
||||
|
||||
return {
|
||||
installed: true,
|
||||
version,
|
||||
path: HYDRA_DECKY_PLUGIN_LOCATION,
|
||||
outdated,
|
||||
expectedVersion,
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error("Failed to get plugin info:", error);
|
||||
@@ -55,6 +85,8 @@ const getHydraDeckyPluginInfo = async (
|
||||
installed: false,
|
||||
version: null,
|
||||
path: HYDRA_DECKY_PLUGIN_LOCATION,
|
||||
outdated: true,
|
||||
expectedVersion: null,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -41,7 +41,7 @@ const installHydraDeckyPlugin = async (
|
||||
success: false,
|
||||
path: HYDRA_DECKY_PLUGIN_LOCATION,
|
||||
currentVersion: null,
|
||||
expectedVersion: "0.0.3",
|
||||
expectedVersion: "unknown",
|
||||
error: errorMessage,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -11,11 +11,35 @@ import {
|
||||
import { logger } from "./logger";
|
||||
import { SevenZip } from "./7zip";
|
||||
import { SystemPath } from "./system-path";
|
||||
import { HydraApi } from "./hydra-api";
|
||||
|
||||
interface DeckyReleaseInfo {
|
||||
version: string;
|
||||
downloadUrl: string;
|
||||
}
|
||||
|
||||
export class DeckyPlugin {
|
||||
private static readonly EXPECTED_VERSION = "0.0.3";
|
||||
private static readonly DOWNLOAD_URL =
|
||||
"https://github.com/hydralauncher/decky-hydra-launcher/releases/download/0.0.3/Hydra.zip";
|
||||
private static releaseInfo: DeckyReleaseInfo | null = null;
|
||||
|
||||
private static async getDeckyReleaseInfo(): Promise<DeckyReleaseInfo> {
|
||||
if (this.releaseInfo) {
|
||||
return this.releaseInfo;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await HydraApi.get<DeckyReleaseInfo>(
|
||||
"/decky/release",
|
||||
{},
|
||||
{ needsAuth: false }
|
||||
);
|
||||
|
||||
this.releaseInfo = response;
|
||||
return response;
|
||||
} catch (error) {
|
||||
logger.error("Failed to fetch Decky release info:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
private static getPackageJsonPath(): string {
|
||||
return path.join(HYDRA_DECKY_PLUGIN_LOCATION, "package.json");
|
||||
@@ -24,10 +48,11 @@ export class DeckyPlugin {
|
||||
private static async downloadPlugin(): Promise<string> {
|
||||
logger.log("Downloading Hydra Decky plugin...");
|
||||
|
||||
const releaseInfo = await this.getDeckyReleaseInfo();
|
||||
const tempDir = SystemPath.getPath("temp");
|
||||
const zipPath = path.join(tempDir, "Hydra.zip");
|
||||
|
||||
const response = await axios.get(this.DOWNLOAD_URL, {
|
||||
const response = await axios.get(releaseInfo.downloadUrl, {
|
||||
responseType: "arraybuffer",
|
||||
});
|
||||
|
||||
@@ -209,14 +234,15 @@ export class DeckyPlugin {
|
||||
return;
|
||||
}
|
||||
|
||||
const releaseInfo = await this.getDeckyReleaseInfo();
|
||||
const packageJsonContent = fs.readFileSync(packageJsonPath, "utf-8");
|
||||
const packageJson = JSON.parse(packageJsonContent);
|
||||
const currentVersion = packageJson.version;
|
||||
const isOutdated = currentVersion !== this.EXPECTED_VERSION;
|
||||
const isOutdated = currentVersion !== releaseInfo.version;
|
||||
|
||||
if (isOutdated) {
|
||||
logger.log(
|
||||
`Hydra Decky plugin is outdated. Current: ${currentVersion}, Expected: ${this.EXPECTED_VERSION}. Updating...`
|
||||
`Hydra Decky plugin is outdated. Current: ${currentVersion}, Expected: ${releaseInfo.version}. Updating...`
|
||||
);
|
||||
|
||||
await this.updatePlugin();
|
||||
@@ -235,78 +261,139 @@ export class DeckyPlugin {
|
||||
currentVersion: string | null;
|
||||
expectedVersion: string;
|
||||
}> {
|
||||
if (!fs.existsSync(HYDRA_DECKY_PLUGIN_LOCATION)) {
|
||||
logger.log("Hydra Decky plugin folder not found, installing...");
|
||||
try {
|
||||
const releaseInfo = await this.getDeckyReleaseInfo();
|
||||
|
||||
if (!fs.existsSync(HYDRA_DECKY_PLUGIN_LOCATION)) {
|
||||
logger.log("Hydra Decky plugin folder not found, installing...");
|
||||
|
||||
try {
|
||||
await this.updatePlugin();
|
||||
|
||||
// Read the actual installed version from package.json
|
||||
const packageJsonPath = this.getPackageJsonPath();
|
||||
if (fs.existsSync(packageJsonPath)) {
|
||||
const packageJsonContent = fs.readFileSync(
|
||||
packageJsonPath,
|
||||
"utf-8"
|
||||
);
|
||||
const packageJson = JSON.parse(packageJsonContent);
|
||||
return {
|
||||
exists: true,
|
||||
outdated: false,
|
||||
currentVersion: packageJson.version,
|
||||
expectedVersion: releaseInfo.version,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
exists: true,
|
||||
outdated: false,
|
||||
currentVersion: releaseInfo.version,
|
||||
expectedVersion: releaseInfo.version,
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error("Failed to install plugin:", error);
|
||||
return {
|
||||
exists: false,
|
||||
outdated: true,
|
||||
currentVersion: null,
|
||||
expectedVersion: releaseInfo.version,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const packageJsonPath = this.getPackageJsonPath();
|
||||
|
||||
try {
|
||||
await this.updatePlugin();
|
||||
if (!fs.existsSync(packageJsonPath)) {
|
||||
logger.log(
|
||||
"Hydra Decky plugin package.json not found, installing..."
|
||||
);
|
||||
|
||||
await this.updatePlugin();
|
||||
|
||||
// Read the actual installed version from package.json
|
||||
if (fs.existsSync(packageJsonPath)) {
|
||||
const packageJsonContent = fs.readFileSync(
|
||||
packageJsonPath,
|
||||
"utf-8"
|
||||
);
|
||||
const packageJson = JSON.parse(packageJsonContent);
|
||||
return {
|
||||
exists: true,
|
||||
outdated: false,
|
||||
currentVersion: packageJson.version,
|
||||
expectedVersion: releaseInfo.version,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
exists: true,
|
||||
outdated: false,
|
||||
currentVersion: releaseInfo.version,
|
||||
expectedVersion: releaseInfo.version,
|
||||
};
|
||||
}
|
||||
|
||||
const packageJsonContent = fs.readFileSync(packageJsonPath, "utf-8");
|
||||
const packageJson = JSON.parse(packageJsonContent);
|
||||
const currentVersion = packageJson.version;
|
||||
const isOutdated = currentVersion !== releaseInfo.version;
|
||||
|
||||
if (isOutdated) {
|
||||
logger.log(
|
||||
`Hydra Decky plugin is outdated. Current: ${currentVersion}, Expected: ${releaseInfo.version}`
|
||||
);
|
||||
|
||||
await this.updatePlugin();
|
||||
|
||||
if (fs.existsSync(packageJsonPath)) {
|
||||
const updatedPackageJsonContent = fs.readFileSync(
|
||||
packageJsonPath,
|
||||
"utf-8"
|
||||
);
|
||||
const updatedPackageJson = JSON.parse(updatedPackageJsonContent);
|
||||
return {
|
||||
exists: true,
|
||||
outdated: false,
|
||||
currentVersion: updatedPackageJson.version,
|
||||
expectedVersion: releaseInfo.version,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
exists: true,
|
||||
outdated: false,
|
||||
currentVersion: releaseInfo.version,
|
||||
expectedVersion: releaseInfo.version,
|
||||
};
|
||||
} else {
|
||||
logger.log(`Hydra Decky plugin is up to date (${currentVersion})`);
|
||||
}
|
||||
|
||||
return {
|
||||
exists: true,
|
||||
outdated: false,
|
||||
currentVersion: this.EXPECTED_VERSION,
|
||||
expectedVersion: this.EXPECTED_VERSION,
|
||||
outdated: isOutdated,
|
||||
currentVersion,
|
||||
expectedVersion: releaseInfo.version,
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error("Failed to install plugin:", error);
|
||||
logger.error(`Error checking Hydra Decky plugin version: ${error}`);
|
||||
return {
|
||||
exists: false,
|
||||
outdated: true,
|
||||
currentVersion: null,
|
||||
expectedVersion: this.EXPECTED_VERSION,
|
||||
expectedVersion: releaseInfo.version,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const packageJsonPath = this.getPackageJsonPath();
|
||||
|
||||
try {
|
||||
if (!fs.existsSync(packageJsonPath)) {
|
||||
logger.log("Hydra Decky plugin package.json not found, installing...");
|
||||
|
||||
await this.updatePlugin();
|
||||
return {
|
||||
exists: true,
|
||||
outdated: false,
|
||||
currentVersion: this.EXPECTED_VERSION,
|
||||
expectedVersion: this.EXPECTED_VERSION,
|
||||
};
|
||||
}
|
||||
|
||||
const packageJsonContent = fs.readFileSync(packageJsonPath, "utf-8");
|
||||
const packageJson = JSON.parse(packageJsonContent);
|
||||
const currentVersion = packageJson.version;
|
||||
const isOutdated = currentVersion !== this.EXPECTED_VERSION;
|
||||
|
||||
if (isOutdated) {
|
||||
logger.log(
|
||||
`Hydra Decky plugin is outdated. Current: ${currentVersion}, Expected: ${this.EXPECTED_VERSION}`
|
||||
);
|
||||
|
||||
await this.updatePlugin();
|
||||
|
||||
return {
|
||||
exists: true,
|
||||
outdated: false,
|
||||
currentVersion: this.EXPECTED_VERSION,
|
||||
expectedVersion: this.EXPECTED_VERSION,
|
||||
};
|
||||
} else {
|
||||
logger.log(`Hydra Decky plugin is up to date (${currentVersion})`);
|
||||
}
|
||||
|
||||
return {
|
||||
exists: true,
|
||||
outdated: isOutdated,
|
||||
currentVersion,
|
||||
expectedVersion: this.EXPECTED_VERSION,
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error(`Error checking Hydra Decky plugin version: ${error}`);
|
||||
logger.error(`Error fetching release info: ${error}`);
|
||||
return {
|
||||
exists: false,
|
||||
outdated: true,
|
||||
currentVersion: null,
|
||||
expectedVersion: this.EXPECTED_VERSION,
|
||||
expectedVersion: "unknown",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,8 @@ export function Sidebar() {
|
||||
const [deckyPluginInfo, setDeckyPluginInfo] = useState<{
|
||||
installed: boolean;
|
||||
version: string | null;
|
||||
}>({ installed: false, version: null });
|
||||
outdated: boolean;
|
||||
}>({ installed: false, version: null, outdated: false });
|
||||
const [homebrewFolderExists, setHomebrewFolderExists] = useState(false);
|
||||
const [showDeckyConfirmModal, setShowDeckyConfirmModal] = useState(false);
|
||||
const navigate = useNavigate();
|
||||
@@ -102,6 +103,7 @@ export function Sidebar() {
|
||||
setDeckyPluginInfo({
|
||||
installed: info.installed,
|
||||
version: info.version,
|
||||
outdated: info.outdated,
|
||||
});
|
||||
setHomebrewFolderExists(folderExists);
|
||||
} catch (error) {
|
||||
@@ -110,6 +112,9 @@ export function Sidebar() {
|
||||
};
|
||||
|
||||
const handleInstallHydraDeckyPlugin = () => {
|
||||
if (deckyPluginInfo.installed && !deckyPluginInfo.outdated) {
|
||||
return;
|
||||
}
|
||||
setShowDeckyConfirmModal(true);
|
||||
};
|
||||
|
||||
@@ -318,11 +323,13 @@ export function Sidebar() {
|
||||
style={{ width: 16, height: 16 }}
|
||||
/>
|
||||
<span>
|
||||
{deckyPluginInfo.installed
|
||||
{deckyPluginInfo.installed && !deckyPluginInfo.outdated
|
||||
? t("decky_plugin_installed_version", {
|
||||
version: deckyPluginInfo.version,
|
||||
})
|
||||
: t("install_decky_plugin")}
|
||||
: deckyPluginInfo.installed && deckyPluginInfo.outdated
|
||||
? t("update_decky_plugin")
|
||||
: t("install_decky_plugin")}
|
||||
</span>
|
||||
</button>
|
||||
</li>
|
||||
@@ -433,12 +440,12 @@ export function Sidebar() {
|
||||
<ConfirmationModal
|
||||
visible={showDeckyConfirmModal}
|
||||
title={
|
||||
deckyPluginInfo.installed
|
||||
deckyPluginInfo.installed && deckyPluginInfo.outdated
|
||||
? t("update_decky_plugin_title")
|
||||
: t("install_decky_plugin_title")
|
||||
}
|
||||
descriptionText={
|
||||
deckyPluginInfo.installed
|
||||
deckyPluginInfo.installed && deckyPluginInfo.outdated
|
||||
? t("update_decky_plugin_message")
|
||||
: t("install_decky_plugin_message")
|
||||
}
|
||||
|
||||
2
src/renderer/src/declaration.d.ts
vendored
2
src/renderer/src/declaration.d.ts
vendored
@@ -350,6 +350,8 @@ declare global {
|
||||
installed: boolean;
|
||||
version: string | null;
|
||||
path: string;
|
||||
outdated: boolean;
|
||||
expectedVersion: string | null;
|
||||
}>;
|
||||
checkHomebrewFolderExists: () => Promise<boolean>;
|
||||
onCommonRedistProgress: (
|
||||
|
||||
@@ -6,8 +6,6 @@ function removeZalgoText(text: string): string {
|
||||
return text.replaceAll(zalgoRegex, "");
|
||||
}
|
||||
|
||||
|
||||
|
||||
export function sanitizeHtml(html: string): string {
|
||||
if (!html || typeof html !== "string") {
|
||||
return "";
|
||||
|
||||
Reference in New Issue
Block a user