mirror of
https://github.com/hydralauncher/hydra.git
synced 2026-01-20 01:33:56 +00:00
Compare commits
19 Commits
feat/impro
...
v3.7.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2fb44a6c0e | ||
|
|
49c2bc34d1 | ||
|
|
49df40650c | ||
|
|
499a830e3e | ||
|
|
437b0a3b19 | ||
|
|
d59ff5c484 | ||
|
|
dcf13a5920 | ||
|
|
51861752a1 | ||
|
|
e143fadf38 | ||
|
|
f99f8d9554 | ||
|
|
274080069f | ||
|
|
b1069426e4 | ||
|
|
dc6d578462 | ||
|
|
8a12c6e088 | ||
|
|
b795cea599 | ||
|
|
dc8a19e845 | ||
|
|
ce0619bbe3 | ||
|
|
73e378e26a | ||
|
|
3dc71a8d1f |
@@ -3,3 +3,4 @@ MAIN_VITE_AUTH_URL=
|
|||||||
MAIN_VITE_WS_URL=
|
MAIN_VITE_WS_URL=
|
||||||
RENDERER_VITE_REAL_DEBRID_REFERRAL_ID=
|
RENDERER_VITE_REAL_DEBRID_REFERRAL_ID=
|
||||||
RENDERER_VITE_TORBOX_REFERRAL_CODE=
|
RENDERER_VITE_TORBOX_REFERRAL_CODE=
|
||||||
|
MAIN_VITE_LAUNCHER_SUBDOMAIN=
|
||||||
|
|||||||
24
.github/workflows/build-renderer.yml
vendored
24
.github/workflows/build-renderer.yml
vendored
@@ -6,23 +6,37 @@ concurrency:
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [main]
|
branches:
|
||||||
|
- release/**
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
env:
|
||||||
|
NODE_OPTIONS: --max-old-space-size=4096
|
||||||
|
BRANCH_NAME: ${{ github.ref_name }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out Git repository
|
- name: Check out Git repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Install Node.js
|
- name: Set up Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 22.21.0
|
node-version: 22.21.0
|
||||||
|
cache: "yarn"
|
||||||
|
|
||||||
|
- name: Enable Corepack (Yarn)
|
||||||
|
run: corepack enable
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: yarn --frozen-lockfile --ignore-scripts
|
run: yarn install --frozen-lockfile --ignore-scripts
|
||||||
|
|
||||||
- name: Build Renderer
|
- name: Build Renderer
|
||||||
run: yarn build
|
run: yarn build
|
||||||
@@ -36,5 +50,5 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
npx --yes wrangler@3 pages deploy out/renderer \
|
npx --yes wrangler@3 pages deploy out/renderer \
|
||||||
--project-name="hydra" \
|
--project-name="hydra" \
|
||||||
--commit-dirty=true \
|
--branch "$BRANCH_NAME" \
|
||||||
--branch="main"
|
--commit-dirty
|
||||||
|
|||||||
7
.github/workflows/release.yml
vendored
7
.github/workflows/release.yml
vendored
@@ -6,7 +6,8 @@ concurrency:
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [main]
|
branches:
|
||||||
|
- release/**
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
@@ -61,7 +62,7 @@ jobs:
|
|||||||
RENDERER_VITE_SENTRY_DSN: ${{ vars.SENTRY_DSN }}
|
RENDERER_VITE_SENTRY_DSN: ${{ vars.SENTRY_DSN }}
|
||||||
RENDERER_VITE_REAL_DEBRID_REFERRAL_ID: ${{ vars.RENDERER_VITE_REAL_DEBRID_REFERRAL_ID }}
|
RENDERER_VITE_REAL_DEBRID_REFERRAL_ID: ${{ vars.RENDERER_VITE_REAL_DEBRID_REFERRAL_ID }}
|
||||||
RENDERER_VITE_TORBOX_REFERRAL_CODE: ${{ vars.RENDERER_VITE_TORBOX_REFERRAL_CODE }}
|
RENDERER_VITE_TORBOX_REFERRAL_CODE: ${{ vars.RENDERER_VITE_TORBOX_REFERRAL_CODE }}
|
||||||
MAIN_VITE_RENDERER_URL: ${{ vars.MAIN_VITE_RENDERER_URL }}
|
MAIN_VITE_LAUNCHER_SUBDOMAIN: ${{ vars.MAIN_VITE_LAUNCHER_SUBDOMAIN }}
|
||||||
|
|
||||||
- name: Build Windows
|
- name: Build Windows
|
||||||
if: matrix.os == 'windows-2022'
|
if: matrix.os == 'windows-2022'
|
||||||
@@ -78,7 +79,7 @@ jobs:
|
|||||||
RENDERER_VITE_SENTRY_DSN: ${{ vars.SENTRY_DSN }}
|
RENDERER_VITE_SENTRY_DSN: ${{ vars.SENTRY_DSN }}
|
||||||
RENDERER_VITE_REAL_DEBRID_REFERRAL_ID: ${{ vars.RENDERER_VITE_REAL_DEBRID_REFERRAL_ID }}
|
RENDERER_VITE_REAL_DEBRID_REFERRAL_ID: ${{ vars.RENDERER_VITE_REAL_DEBRID_REFERRAL_ID }}
|
||||||
RENDERER_VITE_TORBOX_REFERRAL_CODE: ${{ vars.RENDERER_VITE_TORBOX_REFERRAL_CODE }}
|
RENDERER_VITE_TORBOX_REFERRAL_CODE: ${{ vars.RENDERER_VITE_TORBOX_REFERRAL_CODE }}
|
||||||
MAIN_VITE_RENDERER_URL: ${{ vars.MAIN_VITE_RENDERER_URL }}
|
MAIN_VITE_LAUNCHER_SUBDOMAIN: ${{ vars.MAIN_VITE_LAUNCHER_SUBDOMAIN }}
|
||||||
|
|
||||||
- name: Create artifact
|
- name: Create artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "hydralauncher",
|
"name": "hydralauncher",
|
||||||
"version": "3.7.1",
|
"version": "3.7.2",
|
||||||
"description": "Hydra",
|
"description": "Hydra",
|
||||||
"main": "./out/main/index.js",
|
"main": "./out/main/index.js",
|
||||||
"author": "Los Broxas",
|
"author": "Los Broxas",
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import type {
|
|||||||
} from "@types";
|
} from "@types";
|
||||||
import { AuthPage, generateAchievementCustomNotificationTest } from "@shared";
|
import { AuthPage, generateAchievementCustomNotificationTest } from "@shared";
|
||||||
import { isStaging } from "@main/constants";
|
import { isStaging } from "@main/constants";
|
||||||
|
import { logger } from "./logger";
|
||||||
|
|
||||||
export class WindowManager {
|
export class WindowManager {
|
||||||
public static mainWindow: Electron.BrowserWindow | null = null;
|
public static mainWindow: Electron.BrowserWindow | null = null;
|
||||||
@@ -54,21 +55,25 @@ export class WindowManager {
|
|||||||
show: false,
|
show: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private static formatVersionNumber(version: string) {
|
||||||
|
return version.replaceAll(".", "-");
|
||||||
|
}
|
||||||
|
|
||||||
private static async loadWindowURL(window: BrowserWindow, hash: string = "") {
|
private static async loadWindowURL(window: BrowserWindow, hash: string = "") {
|
||||||
// HMR for renderer base on electron-vite cli.
|
// HMR for renderer base on electron-vite cli.
|
||||||
// Load the remote URL for development or the local html file for production.
|
// Load the remote URL for development or the local html file for production.
|
||||||
if (is.dev && process.env["ELECTRON_RENDERER_URL"]) {
|
if (is.dev && process.env["ELECTRON_RENDERER_URL"]) {
|
||||||
window.loadURL(`${process.env["ELECTRON_RENDERER_URL"]}#/${hash}`);
|
window.loadURL(`${process.env["ELECTRON_RENDERER_URL"]}#/${hash}`);
|
||||||
} else if (import.meta.env.MAIN_VITE_RENDERER_URL) {
|
} else if (import.meta.env.MAIN_VITE_LAUNCHER_SUBDOMAIN) {
|
||||||
// Try to load from remote URL in production
|
// Try to load from remote URL in production
|
||||||
try {
|
try {
|
||||||
await window.loadURL(
|
await window.loadURL(
|
||||||
`${import.meta.env.MAIN_VITE_RENDERER_URL}#/${hash}`
|
`https://release-v${this.formatVersionNumber(app.getVersion())}.${import.meta.env.MAIN_VITE_LAUNCHER_SUBDOMAIN}#/${hash}`
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Fall back to local file if remote URL fails
|
// Fall back to local file if remote URL fails
|
||||||
console.error(
|
logger.error(
|
||||||
"Failed to load from MAIN_VITE_RENDERER_URL, falling back to local file:",
|
"Failed to load from MAIN_VITE_LAUNCHER_SUBDOMAIN, falling back to local file:",
|
||||||
error
|
error
|
||||||
);
|
);
|
||||||
window.loadFile(path.join(__dirname, "../renderer/index.html"), {
|
window.loadFile(path.join(__dirname, "../renderer/index.html"), {
|
||||||
|
|||||||
2
src/main/vite-env.d.ts
vendored
2
src/main/vite-env.d.ts
vendored
@@ -7,7 +7,7 @@ interface ImportMetaEnv {
|
|||||||
readonly MAIN_VITE_CHECKOUT_URL: string;
|
readonly MAIN_VITE_CHECKOUT_URL: string;
|
||||||
readonly MAIN_VITE_EXTERNAL_RESOURCES_URL: string;
|
readonly MAIN_VITE_EXTERNAL_RESOURCES_URL: string;
|
||||||
readonly MAIN_VITE_WS_URL: string;
|
readonly MAIN_VITE_WS_URL: string;
|
||||||
readonly MAIN_VITE_RENDERER_URL: string;
|
readonly MAIN_VITE_LAUNCHER_SUBDOMAIN: string;
|
||||||
readonly ELECTRON_RENDERER_URL: string;
|
readonly ELECTRON_RENDERER_URL: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
import React, { useId, useMemo, useState } from "react";
|
import React, { useId, useState } from "react";
|
||||||
import { EyeClosedIcon, EyeIcon } from "@primer/octicons-react";
|
import { EyeClosedIcon, EyeIcon } from "@primer/octicons-react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
import cn from "classnames";
|
import cn from "classnames";
|
||||||
|
|
||||||
import "./text-field.scss";
|
import "./text-field.scss";
|
||||||
|
|
||||||
export interface TextFieldProps
|
export interface TextFieldProps
|
||||||
@@ -42,44 +40,30 @@ export const TextField = React.forwardRef<HTMLInputElement, TextFieldProps>(
|
|||||||
) => {
|
) => {
|
||||||
const id = useId();
|
const id = useId();
|
||||||
const [isFocused, setIsFocused] = useState(false);
|
const [isFocused, setIsFocused] = useState(false);
|
||||||
|
|
||||||
const [isPasswordVisible, setIsPasswordVisible] = useState(false);
|
const [isPasswordVisible, setIsPasswordVisible] = useState(false);
|
||||||
|
|
||||||
const { t } = useTranslation("forms");
|
const { t } = useTranslation("forms");
|
||||||
|
|
||||||
const showPasswordToggleButton = props.type === "password";
|
const showPasswordToggleButton = props.type === "password";
|
||||||
|
const inputType =
|
||||||
const inputType = useMemo(() => {
|
props.type === "password" && isPasswordVisible
|
||||||
if (props.type === "password" && isPasswordVisible) return "text";
|
? "text"
|
||||||
return props.type ?? "text";
|
: (props.type ?? "text");
|
||||||
}, [props.type, isPasswordVisible]);
|
const hintContent = error ? (
|
||||||
|
<small className="text-field-container__error-label">{error}</small>
|
||||||
const hintContent = useMemo(() => {
|
) : hint ? (
|
||||||
if (error)
|
<small>{hint}</small>
|
||||||
return (
|
) : null;
|
||||||
<small className="text-field-container__error-label">{error}</small>
|
|
||||||
);
|
|
||||||
|
|
||||||
if (hint) return <small>{hint}</small>;
|
|
||||||
return null;
|
|
||||||
}, [hint, error]);
|
|
||||||
|
|
||||||
const handleFocus: React.FocusEventHandler<HTMLInputElement> = (event) => {
|
const handleFocus: React.FocusEventHandler<HTMLInputElement> = (event) => {
|
||||||
setIsFocused(true);
|
setIsFocused(true);
|
||||||
if (props.onFocus) props.onFocus(event);
|
props.onFocus?.(event);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleBlur: React.FocusEventHandler<HTMLInputElement> = (event) => {
|
const handleBlur: React.FocusEventHandler<HTMLInputElement> = (event) => {
|
||||||
setIsFocused(false);
|
setIsFocused(false);
|
||||||
if (props.onBlur) props.onBlur(event);
|
props.onBlur?.(event);
|
||||||
};
|
};
|
||||||
|
|
||||||
const hasError = !!error;
|
const hasError = !!error;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="text-field-container" {...containerProps}>
|
<div className="text-field-container" {...containerProps}>
|
||||||
{label && <label htmlFor={id}>{label}</label>}
|
{label && <label htmlFor={id}>{label}</label>}
|
||||||
|
|
||||||
<div className="text-field-container__text-field-wrapper">
|
<div className="text-field-container__text-field-wrapper">
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
@@ -104,7 +88,6 @@ export const TextField = React.forwardRef<HTMLInputElement, TextFieldProps>(
|
|||||||
onBlur={handleBlur}
|
onBlur={handleBlur}
|
||||||
type={inputType}
|
type={inputType}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{showPasswordToggleButton && (
|
{showPasswordToggleButton && (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@@ -120,14 +103,11 @@ export const TextField = React.forwardRef<HTMLInputElement, TextFieldProps>(
|
|||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{rightContent}
|
{rightContent}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{hintContent}
|
{hintContent}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
TextField.displayName = "TextField";
|
TextField.displayName = "TextField";
|
||||||
|
|||||||
Reference in New Issue
Block a user