feat: correcting date in process-watcher

This commit is contained in:
Chubby Granny Chaser 2024-05-29 17:20:47 +01:00
commit 85516c1744
No known key found for this signature in database
47 changed files with 334 additions and 489 deletions

1
.gitignore vendored
View File

@ -9,4 +9,3 @@ out
*.log*
.env
.vite

View File

@ -18,6 +18,7 @@
[![ru](https://img.shields.io/badge/lang-ru-yellow.svg)](README.ru.md)
[![uk-UA](https://img.shields.io/badge/lang-uk--UA-blue)](README.uk-UA.md)
[![be](https://img.shields.io/badge/lang-be-orange)](README.be.md)
[![es](https://img.shields.io/badge/lang-es-red)](README.es.md)
![Hydra Catalogue](./docs/screenshot.png)

View File

@ -18,7 +18,7 @@
[![pt-BR](https://img.shields.io/badge/lang-pt--BR-green.svg)](README.pt-BR.md)
[![ru](https://img.shields.io/badge/lang-ru-yellow.svg)](README.ru.md)
[![uk-UA](https://img.shields.io/badge/lang-uk--UA-blue)](README.uk-UA.md)
[![es](https://img.shields.io/badge/lang-es-red)](README.es.md)
[![en](https://img.shields.io/badge/lang-en-red.svg)](README.md)
![Hydra Catalogue](./docs/screenshot.png)

View File

@ -18,6 +18,7 @@
[![pt-BR](https://img.shields.io/badge/lang-pt--BR-green.svg)](README.pt-BR.md)
[![ru](https://img.shields.io/badge/lang-ru-yellow.svg)](README.ru.md)
[![uk-UA](https://img.shields.io/badge/lang-uk--UA-blue)](README.uk-UA.md)
[![es](https://img.shields.io/badge/lang-es-red)](README.es.md)
![Hydra Catalogue](./docs/screenshot.png)

View File

@ -18,6 +18,7 @@
[![pt-BR](https://img.shields.io/badge/lang-pt--BR-green.svg)](README.pt-BR.md)
[![ru](https://img.shields.io/badge/lang-ru-yellow.svg)](README.ru.md)
[![uk-UA](https://img.shields.io/badge/lang-uk--UA-blue)](README.uk-UA.md)
[![es](https://img.shields.io/badge/lang-es-red)](README.es.md)
![Hydra Catalogue](./docs/screenshot.png)

View File

@ -18,6 +18,8 @@
[![pl](https://img.shields.io/badge/lang-pl-white)](README.pl.md)
[![ru](https://img.shields.io/badge/lang-ru-yellow.svg)](README.ru.md)
[![uk-UA](https://img.shields.io/badge/lang-uk--UA-blue)](README.uk-UA.md)
[![es](https://img.shields.io/badge/lang-es-red)](README.es.md)
![Hydra Catalogue](./docs/screenshot.png)
</div>

View File

@ -18,6 +18,7 @@
[![pl](https://img.shields.io/badge/lang-pl-white)](README.pl.md)
[![pt-BR](https://img.shields.io/badge/lang-pt--BR-green.svg)](README.pt-BR.md)
[![uk-UA](https://img.shields.io/badge/lang-uk--UA-blue)](README.uk-UA.md)
[![es](https://img.shields.io/badge/lang-es-red)](README.es.md)
![Hydra Catalogue](./docs/screenshot.png)

View File

@ -18,6 +18,7 @@
[![pl](https://img.shields.io/badge/lang-pl-white)](README.pl.md)
[![pt-BR](https://img.shields.io/badge/lang-pt--BR-green.svg)](README.pt-BR.md)
[![ru](https://img.shields.io/badge/lang-ru-yellow.svg)](README.ru.md)
[![es](https://img.shields.io/badge/lang-es-red)](README.es.md)
![Hydra Catalogue](./docs/screenshot.png)

BIN
build/icons/512x512.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

View File

@ -40,8 +40,11 @@ linux:
- AppImage
- snap
- deb
- rpm
maintainer: electronjs.org
category: Utility
category: Game
mimeTypes:
- x-scheme-handler/hydralauncher
appImage:
artifactName: ${name}-${version}.${ext}
npmRebuild: false

BIN
hydra.db

Binary file not shown.

View File

@ -50,6 +50,7 @@
"color": "^4.2.3",
"color.js": "^1.2.0",
"date-fns": "^3.6.0",
"electron-log": "^5.1.4",
"electron-updater": "^6.1.8",
"fetch-cookie": "^3.0.1",
"flexsearch": "^0.7.43",
@ -66,7 +67,6 @@
"react-router-dom": "^6.22.3",
"typeorm": "^0.3.20",
"user-agents": "^1.1.193",
"winston": "^3.13.0",
"yaml": "^2.4.1"
},
"devDependencies": {

View File

@ -29,7 +29,8 @@
"catalogue": "Catalogue",
"downloads": "Downloads",
"search_results": "Search results",
"settings": "Settings"
"settings": "Settings",
"version_available": "Version {{version}} available. Click here to restart and install."
},
"bottom_panel": {
"no_downloads_in_progress": "No downloads in progress",
@ -153,6 +154,7 @@
"real_debrid": "Real-Debrid",
"real_debrid_description": "Real-Debrid is an unrestricted downloader that allows you to download files instantly and at the best of your Internet speed.",
"real_debrid_api_token_hint": "You can get your API token <0>here</0>.",
"real_debrid_free_account": "The account \"{{username}}\" is a free account. Please subscribe to Real-Debrid.",
"save_changes": "Save changes"
},
"notifications": {
@ -176,11 +178,5 @@
},
"modal": {
"close": "Close button"
},
"splash": {
"downloading_version": "Downloading version {{version}}",
"searching_updates": "Searching for updates",
"update_found": "Update {{version}} found",
"restarting_and_applying": "Restarting and applying update"
}
}

View File

@ -29,7 +29,8 @@
"catalogue": "Catálogo",
"downloads": "Descargas",
"search_results": "Resultados de búsqueda",
"settings": "Ajustes"
"settings": "Ajustes",
"version_available": "Version {{version}} disponible. Haga clic aquí para reiniciar e instalar."
},
"bottom_panel": {
"no_downloads_in_progress": "Sin descargas en progreso",
@ -54,7 +55,7 @@
"remove": "Eliminar",
"remove_from_list": "Quitar",
"space_left_on_disk": "{{space}} restantes en el disco",
"eta": "Finalizando en {{eta}}",
"eta": "Tiempo restante: {{eta}}",
"downloading_metadata": "Descargando metadatos…",
"checking_files": "Analizando archivos…",
"filter": "Buscar repacks",
@ -176,11 +177,5 @@
},
"modal": {
"close": "Botón de cierre"
},
"splash": {
"downloading_version": "Descargando versión {{version}}",
"searching_updates": "Buscando actualizaciones",
"update_found": "Actualización {{version}} encontrada",
"restarting_and_applying": "Reiniciando y aplicando actualización"
}
}

View File

@ -72,7 +72,7 @@
"minutes": "minuti",
"amount_hours": "{{amount}} ore",
"amount_minutes": "{{amount}} minuti",
"accuracy": "{{accuratezza}}% di accuratezza",
"accuracy": "{{accuracy}}% di accuratezza",
"add_to_library": "Aggiungi alla libreria",
"remove_from_library": "Rimuovi dalla libreria",
"no_downloads": "Nessun download disponibile",
@ -86,7 +86,6 @@
"playing_now": "Stai giocando adesso",
"change": "Aggiorna",
"repacks_modal_description": "Scegli il repack che vuoi scaricare",
"downloads_path": "Percorso dei download",
"select_folder_hint": "Per cambiare la cartella predefinita, accedi alle",
"download_now": "Scarica ora",
"installation_instructions": "Istruzioni di installazione",
@ -96,7 +95,14 @@
"dont_show_it_again": "Non mostrarlo più",
"copy_to_clipboard": "Copia",
"copied_to_clipboard": "Copiato",
"got_it": "Capito"
"got_it": "Capito",
"no_shop_details": "Impossibile recuperare i dettagli del negozio.",
"download_options": "Opzioni di download",
"download_path": "Percorso di download",
"previous_screenshot": "Screenshot precedente",
"next_screenshot": "Screenshot successivo",
"screenshot": "Screenshot {{number}}",
"open_screenshot": "Apri screenshot {{number}}"
},
"activation": {
"title": "Attiva Hydra",
@ -127,7 +133,9 @@
"remove_from_list": "Rimuovi",
"delete_modal_title": "Sei sicuro?",
"delete_modal_description": "Questo rimuoverà tutti i file di installazione dal tuo computer",
"install": "Installa"
"install": "Installa",
"real_debrid": "Real Debrid",
"torrent": "Torrent"
},
"settings": {
"downloads_path": "Percorso dei download",
@ -136,7 +144,16 @@
"enable_download_notifications": "Quando un download è completo",
"enable_repack_list_notifications": "Quando viene aggiunto un nuovo repack",
"telemetry": "Telemetria",
"telemetry_description": "Abilita statistiche di utilizzo anonime"
"telemetry_description": "Abilita statistiche di utilizzo anonime",
"real_debrid_api_token_label": "Token API Real Debrid",
"quit_app_instead_hiding": "Esci da Hydra invece di nascondere nell'area di notifica",
"launch_with_system": "Apri Hydra all'avvio",
"general": "Generale",
"behavior": "Comportamento",
"enable_real_debrid": "Abilita Real Debrid",
"real_debrid": "Real Debrid",
"real_debrid_api_token_hint": "Puoi trovare la tua chiave API <0>here</0>.",
"save_changes": "Salva modifiche"
},
"notifications": {
"download_complete": "Download completato",

View File

@ -29,7 +29,8 @@
"downloads": "Downloads",
"search_results": "Resultados da busca",
"settings": "Configurações",
"home": "Início"
"home": "Início",
"version_available": "Versão {{version}} disponível. Clique aqui para reiniciar e instalar."
},
"bottom_panel": {
"no_downloads_in_progress": "Sem downloads em andamento",

View File

@ -26,6 +26,8 @@ export const databasePath = path.join(
"hydra.db"
);
export const logsPath = path.join(app.getPath("appData"), "hydra", "logs");
export const seedsPath = app.isPackaged
? path.join(process.resourcesPath, "seeds")
: path.join(__dirname, "..", "..", "seeds");

View File

@ -57,7 +57,7 @@ export class Game {
@Column("int", { default: 0 })
bytesDownloaded: number;
@Column("text", { nullable: true })
@Column("datetime", { nullable: true })
lastTimePlayed: Date | null;
@Column("float", { default: 0 })

View File

@ -1,41 +1,27 @@
import { AppUpdaterEvents } from "@types";
import { registerEvent } from "../register-event";
import updater, { ProgressInfo, UpdateInfo } from "electron-updater";
import updater, { UpdateInfo } from "electron-updater";
import { WindowManager } from "@main/services";
import { app } from "electron";
const { autoUpdater } = updater;
const sendEvent = (event: AppUpdaterEvents) => {
WindowManager.splashWindow?.webContents.send("autoUpdaterEvent", event);
WindowManager.mainWindow?.webContents.send("autoUpdaterEvent", event);
};
const mockValuesForDebug = async () => {
sendEvent({ type: "update-downloaded" });
sendEvent({ type: "update-available", info: { version: "1.3.0" } });
// sendEvent({ type: "update-downloaded" });
};
const checkForUpdates = async (_event: Electron.IpcMainInvokeEvent) => {
autoUpdater
.addListener("error", () => {
sendEvent({ type: "error" });
})
.addListener("checking-for-update", () => {
sendEvent({ type: "checking-for-updates" });
})
.addListener("update-not-available", () => {
sendEvent({ type: "update-not-available" });
})
.addListener("update-available", (info: UpdateInfo) => {
sendEvent({ type: "update-available", info });
})
.addListener("update-downloaded", () => {
sendEvent({ type: "update-downloaded" });
})
.addListener("download-progress", (info: ProgressInfo) => {
sendEvent({ type: "download-progress", info });
})
.addListener("update-cancelled", () => {
sendEvent({ type: "update-cancelled" });
});
if (app.isPackaged) {

View File

@ -1,12 +0,0 @@
import { WindowManager } from "@main/services";
import { registerEvent } from "../register-event";
import updater from "electron-updater";
const { autoUpdater } = updater;
const continueToMainWindow = async (_event: Electron.IpcMainInvokeEvent) => {
autoUpdater.removeAllListeners();
WindowManager.prepareMainWindowAndCloseSplash();
};
registerEvent("continueToMainWindow", continueToMainWindow);

View File

@ -1,16 +1,13 @@
import { app } from "electron";
import { registerEvent } from "../register-event";
import updater from "electron-updater";
import { WindowManager } from "@main/services";
const { autoUpdater } = updater;
const restartAndInstallUpdate = async (_event: Electron.IpcMainInvokeEvent) => {
autoUpdater.removeAllListeners();
if (app.isPackaged) {
autoUpdater.quitAndInstall(true, true);
} else {
autoUpdater.removeAllListeners();
WindowManager.prepareMainWindowAndCloseSplash();
}
};

View File

@ -29,7 +29,6 @@ import "./user-preferences/update-user-preferences";
import "./user-preferences/auto-launch";
import "./autoupdater/check-for-updates";
import "./autoupdater/restart-and-install-update";
import "./autoupdater/continue-to-main-window";
import "./user-preferences/authenticate-real-debrid";
ipcMain.handle("ping", () => "pong");

View File

@ -50,8 +50,6 @@ const startGameDownload = async (
isDeleted: false,
}
);
return DownloadManager.startDownload(game);
} else {
const steamGame = stateManager
.getValue("steamGames")
@ -81,16 +79,16 @@ const startGameDownload = async (
return result;
});
const createdGame = await gameRepository.findOne({
where: {
objectID,
},
relations: { repack: true },
});
return DownloadManager.startDownload(createdGame!);
}
const updatedGame = await gameRepository.findOne({
where: {
objectID,
},
relations: { repack: true },
});
await DownloadManager.startDownload(updatedGame!);
};
registerEvent("startGameDownload", startGameDownload);

View File

@ -64,7 +64,7 @@ app.whenReady().then(() => {
where: { id: 1 },
});
WindowManager.createSplashScreen();
WindowManager.createMainWindow();
WindowManager.createSystemTray(userPreferences?.language || "en");
});
});

View File

@ -0,0 +1,49 @@
import { Game } from "@main/entity";
import { MigrationInterface, QueryRunner } from "typeorm";
export class AlterLastTimePlayedToDatime1716776027208
implements MigrationInterface
{
public async up(queryRunner: QueryRunner): Promise<void> {
// 2024-05-27 02:08:17
// Mon, 27 May 2024 02:08:17 GMT
const updateLastTimePlayedValues = `
UPDATE game SET lastTimePlayed = (SELECT
SUBSTR(lastTimePlayed, 13, 4) || '-' || -- Year
CASE SUBSTR(lastTimePlayed, 9, 3)
WHEN 'Jan' THEN '01'
WHEN 'Feb' THEN '02'
WHEN 'Mar' THEN '03'
WHEN 'Apr' THEN '04'
WHEN 'May' THEN '05'
WHEN 'Jun' THEN '06'
WHEN 'Jul' THEN '07'
WHEN 'Aug' THEN '08'
WHEN 'Sep' THEN '09'
WHEN 'Oct' THEN '10'
WHEN 'Nov' THEN '11'
WHEN 'Dec' THEN '12'
END || '-' || -- Month
SUBSTR(lastTimePlayed, 6, 2) || ' ' || -- Day
SUBSTR(lastTimePlayed, 18, 8) -- hh:mm:ss;
FROM game)
WHERE lastTimePlayed IS NOT NULL;
`;
await queryRunner.query(updateLastTimePlayedValues);
}
public async down(queryRunner: QueryRunner): Promise<void> {
const queryBuilder = queryRunner.manager.createQueryBuilder(Game, "game");
const result = await queryBuilder.getMany();
for (const game of result) {
if (!game.lastTimePlayed) continue;
await queryRunner.query(
`UPDATE game set lastTimePlayed = ? WHERE id = ?;`,
[game.lastTimePlayed.toUTCString(), game.id]
);
}
}
}

View File

@ -1,3 +1,7 @@
import { FixRepackUploadDate1715900413313 } from "./1715900413313-fix_repack_uploadDate";
import { AlterLastTimePlayedToDatime1716776027208 } from "./1716776027208-alter_lastTimePlayed_to_datime";
export default [FixRepackUploadDate1715900413313];
export default [
FixRepackUploadDate1715900413313,
AlterLastTimePlayedToDatime1716776027208,
];

View File

@ -186,7 +186,8 @@ export class DownloadManager {
}
if (WindowManager.mainWindow && game) {
WindowManager.mainWindow.setProgressBar(progress === 1 ? -1 : progress);
if (!isNaN(progress))
WindowManager.mainWindow.setProgressBar(progress === 1 ? -1 : progress);
const payload = {
numPeers: Number(status.connections),
@ -237,11 +238,12 @@ export class DownloadManager {
if (this.gid) {
await this.aria2.call("forcePause", this.gid);
this.gid = null;
this.game = null;
this.realDebridTorrentId = null;
WindowManager.mainWindow?.setProgressBar(-1);
}
this.game = null;
this.realDebridTorrentId = null;
WindowManager.mainWindow?.setProgressBar(-1);
}
static async resumeDownload(game: Game) {
@ -251,6 +253,7 @@ export class DownloadManager {
this.gid = gid;
this.game = game;
this.realDebridTorrentId = null;
} else {
return this.startDownload(game);
}
@ -269,7 +272,6 @@ export class DownloadManager {
);
} else {
this.gid = await this.aria2.call("addUri", [game.repack.magnet], options);
this.downloads.set(game.id, this.gid);
}

View File

@ -1,11 +1,26 @@
import winston from "winston";
import { logsPath } from "@main/constants";
import log from "electron-log";
import path from "path";
export const logger = winston.createLogger({
level: "info",
format: winston.format.json(),
transports: [
new winston.transports.File({ filename: "error.log", level: "error" }),
new winston.transports.File({ filename: "info.log", level: "info" }),
new winston.transports.File({ filename: "combined.log" }),
],
log.transports.file.resolvePathFn = (
_: log.PathVariables,
message?: log.LogMessage | undefined
) => {
if (message?.level === "error") {
return path.join(logsPath, "error.txt");
}
if (message?.level === "info") {
return path.join(logsPath, "info.txt");
}
return path.join(logsPath, "logs.txt");
};
log.errorHandler.startCatching({
showDialog: false,
});
log.initialize();
export const logger = log.scope("main");

View File

@ -46,7 +46,7 @@ export const watchProcesses = async () => {
await gameRepository.update(game.id, {
playTimeInMilliseconds: game.playTimeInMilliseconds + delta,
lastTimePlayed: new Date().toUTCString(),
lastTimePlayed: new Date(),
});
}

View File

@ -17,8 +17,6 @@ import { IsNull, Not } from "typeorm";
export class WindowManager {
public static mainWindow: Electron.BrowserWindow | null = null;
public static splashWindow: Electron.BrowserWindow | null = null;
public static isReadyToShowMainWindow = false;
private static loadURL(hash = "") {
// HMR for renderer base on electron-vite cli.
@ -37,44 +35,8 @@ export class WindowManager {
}
}
private static loadSplashURL() {
// HMR for renderer base on electron-vite cli.
// Load the remote URL for development or the local html file for production.
if (is.dev && process.env["ELECTRON_RENDERER_URL"]) {
this.splashWindow?.loadURL(
`${process.env["ELECTRON_RENDERER_URL"]}#/splash`
);
} else {
this.splashWindow?.loadFile(
path.join(__dirname, "../renderer/index.html"),
{
hash: "splash",
}
);
}
}
public static createSplashScreen() {
if (this.splashWindow) return;
this.splashWindow = new BrowserWindow({
width: 380,
height: 380,
frame: false,
resizable: false,
backgroundColor: "#1c1c1c",
webPreferences: {
preload: path.join(__dirname, "../preload/index.mjs"),
sandbox: false,
},
});
this.loadSplashURL();
this.splashWindow.removeMenu();
}
public static createMainWindow() {
if (this.mainWindow || !this.isReadyToShowMainWindow) return;
if (this.mainWindow) return;
this.mainWindow = new BrowserWindow({
width: 1200,
@ -94,6 +56,7 @@ export class WindowManager {
preload: path.join(__dirname, "../preload/index.mjs"),
sandbox: false,
},
show: false,
});
this.loadURL();
@ -101,6 +64,7 @@ export class WindowManager {
this.mainWindow.on("ready-to-show", () => {
if (!app.isPackaged) WindowManager.mainWindow?.webContents.openDevTools();
WindowManager.mainWindow?.show();
});
this.mainWindow.on("close", async () => {
@ -115,12 +79,6 @@ export class WindowManager {
});
}
public static prepareMainWindowAndCloseSplash() {
this.isReadyToShowMainWindow = true;
this.splashWindow?.close();
this.createMainWindow();
}
public static redirect(hash: string) {
if (!this.mainWindow) this.createMainWindow();
this.loadURL(hash);

View File

@ -104,7 +104,7 @@ contextBridge.exposeInMainWorld("electron", {
ipcRenderer.invoke("showOpenDialog", options),
platform: process.platform,
/* Splash */
/* Auto update */
onAutoUpdaterEvent: (cb: (value: AppUpdaterEvent) => void) => {
const listener = (
_event: Electron.IpcRendererEvent,
@ -119,5 +119,4 @@ contextBridge.exposeInMainWorld("electron", {
},
checkForUpdates: () => ipcRenderer.invoke("checkForUpdates"),
restartAndInstallUpdate: () => ipcRenderer.invoke("restartAndInstallUpdate"),
continueToMainWindow: () => ipcRenderer.invoke("continueToMainWindow"),
});

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

View File

@ -145,3 +145,21 @@ export const title = recipe({
},
},
});
export const subheader = style({
borderBottom: `solid 1px ${vars.color.border}`,
padding: `${SPACING_UNIT / 2}px ${SPACING_UNIT * 3}px`,
});
export const newVersionButton = style({
display: "flex",
alignItems: "center",
justifyContent: "center",
gap: `${SPACING_UNIT}px`,
color: vars.color.bodyText,
borderBottom: "1px solid transparent",
":hover": {
borderBottom: `1px solid ${vars.color.bodyText}`,
cursor: "pointer",
},
});

View File

@ -1,12 +1,18 @@
import { useTranslation } from "react-i18next";
import { useEffect, useMemo, useRef, useState } from "react";
import { useLocation, useNavigate } from "react-router-dom";
import { ArrowLeftIcon, SearchIcon, XIcon } from "@primer/octicons-react";
import {
ArrowLeftIcon,
SearchIcon,
SyncIcon,
XIcon,
} from "@primer/octicons-react";
import { useAppDispatch, useAppSelector } from "@renderer/hooks";
import * as styles from "./header.css";
import { clearSearch } from "@renderer/features";
import { AppUpdaterEvents } from "@types";
export interface HeaderProps {
onSearch: (query: string) => void;
@ -34,6 +40,9 @@ export function Header({ onSearch, onClear, search }: HeaderProps) {
const [isFocused, setIsFocused] = useState(false);
const [showUpdateSubheader, setShowUpdateSubheader] = useState(false);
const [newVersion, setNewVersion] = useState("");
const { t } = useTranslation("header");
const title = useMemo(() => {
@ -49,6 +58,30 @@ export function Header({ onSearch, onClear, search }: HeaderProps) {
}
}, [location.pathname, search, dispatch]);
const handleClickRestartAndUpdate = () => {
window.electron.restartAndInstallUpdate();
};
useEffect(() => {
const unsubscribe = window.electron.onAutoUpdaterEvent(
(event: AppUpdaterEvents) => {
if (event.type == "update-available") {
setNewVersion(event.info.version || "");
}
if (event.type == "update-downloaded") {
setShowUpdateSubheader(true);
}
}
);
window.electron.checkForUpdates();
return () => {
unsubscribe();
};
});
const focusInput = () => {
setIsFocused(true);
inputRef.current?.focus();
@ -63,64 +96,80 @@ export function Header({ onSearch, onClear, search }: HeaderProps) {
};
return (
<header
className={styles.header({
draggingDisabled,
isWindows: window.electron.platform === "win32",
})}
>
<div className={styles.section}>
<button
type="button"
className={styles.backButton({ enabled: location.key !== "default" })}
onClick={handleBackButtonClick}
disabled={location.key === "default"}
>
<ArrowLeftIcon />
</button>
<h3
className={styles.title({
hasBackButton: location.key !== "default",
})}
>
{title}
</h3>
</div>
<section className={styles.section}>
<div className={styles.search({ focused: isFocused })}>
<>
<header
className={styles.header({
draggingDisabled,
isWindows: window.electron.platform === "win32",
})}
>
<div className={styles.section}>
<button
type="button"
className={styles.actionButton}
onClick={focusInput}
className={styles.backButton({
enabled: location.key !== "default",
})}
onClick={handleBackButtonClick}
disabled={location.key === "default"}
>
<SearchIcon />
<ArrowLeftIcon />
</button>
<input
ref={inputRef}
type="text"
name="search"
placeholder={t("search")}
value={search}
className={styles.searchInput}
onChange={(event) => onSearch(event.target.value)}
onFocus={() => setIsFocused(true)}
onBlur={handleBlur}
/>
<h3
className={styles.title({
hasBackButton: location.key !== "default",
})}
>
{title}
</h3>
</div>
{search && (
<section className={styles.section}>
<div className={styles.search({ focused: isFocused })}>
<button
type="button"
onClick={onClear}
className={styles.actionButton}
onClick={focusInput}
>
<XIcon />
<SearchIcon />
</button>
)}
</div>
</section>
</header>
<input
ref={inputRef}
type="text"
name="search"
placeholder={t("search")}
value={search}
className={styles.searchInput}
onChange={(event) => onSearch(event.target.value)}
onFocus={() => setIsFocused(true)}
onBlur={handleBlur}
/>
{search && (
<button
type="button"
onClick={onClear}
className={styles.actionButton}
>
<XIcon />
</button>
)}
</div>
</section>
</header>
{showUpdateSubheader && (
<header className={styles.subheader}>
<button
type="button"
className={styles.newVersionButton}
onClick={handleClickRestartAndUpdate}
>
<SyncIcon size={12} />
<small>{t("version_available", { version: newVersion })}</small>
</button>
</header>
)}
</>
);
}

View File

@ -3,7 +3,7 @@ import { keyframes, style } from "@vanilla-extract/css";
import { SPACING_UNIT, vars } from "../../theme.css";
import { recipe } from "@vanilla-extract/recipes";
const TOAST_HEIGHT = 55;
const TOAST_HEIGHT = 80;
export const slideIn = keyframes({
"0%": { transform: `translateY(${TOAST_HEIGHT + SPACING_UNIT * 2}px)` },
@ -19,12 +19,12 @@ export const toast = recipe({
base: {
animationDuration: "0.2s",
animationTimingFunction: "ease-in-out",
height: TOAST_HEIGHT,
maxHeight: TOAST_HEIGHT,
position: "fixed",
backgroundColor: vars.color.background,
borderRadius: "4px",
border: `solid 1px ${vars.color.border}`,
left: "50%",
right: `${SPACING_UNIT * 2}px`,
/* Bottom panel height + 16px */
bottom: `${26 + SPACING_UNIT * 2}px`,
overflow: "hidden",
@ -32,6 +32,7 @@ export const toast = recipe({
flexDirection: "column",
justifyContent: "space-between",
zIndex: "0",
maxWidth: "500px",
},
variants: {
closing: {

View File

@ -82,6 +82,7 @@ export function Toast({ visible, message, type, onClose }: ToastProps) {
{type === "success" && (
<CheckCircleFillIcon className={styles.successIcon} />
)}
{type === "error" && <XCircleFillIcon className={styles.errorIcon} />}
<span style={{ fontWeight: "bold" }}>{message}</span>
</div>

View File

@ -11,6 +11,7 @@ import type {
DownloadProgress,
UserPreferences,
StartGameDownloadPayload,
RealDebridUser,
} from "@types";
import type { DiskSpace } from "check-disk-space";
@ -88,13 +89,12 @@ declare global {
) => Promise<Electron.OpenDialogReturnValue>;
platform: NodeJS.Platform;
/* Splash */
/* Auto update */
onAutoUpdaterEvent: (
cb: (event: AppUpdaterEvents) => void
) => () => Electron.IpcRenderer;
checkForUpdates: () => Promise<void>;
restartAndInstallUpdate: () => Promise<void>;
continueToMainWindow: () => Promise<void>;
}
interface Window {

View File

@ -20,6 +20,7 @@ export const toastSlice = createSlice({
reducers: {
showToast: (state, action: PayloadAction<Omit<ToastState, "visible">>) => {
state.message = action.payload.message;
state.type = action.payload.type;
state.visible = true;
},
closeToast: (state) => {

View File

@ -0,0 +1,3 @@
import log from "electron-log/renderer";
export const logger = log.scope("renderer");

View File

@ -27,7 +27,6 @@ import {
import { store } from "./store";
import * as resources from "@locales";
import Splash from "./pages/splash/splash";
i18n
.use(LanguageDetector)
@ -48,7 +47,6 @@ ReactDOM.createRoot(document.getElementById("root")!).render(
<Provider store={store}>
<HashRouter>
<Routes>
<Route path="/splash" Component={Splash} />
<Route element={<App />}>
<Route path="/" Component={Home} />
<Route path="/catalogue" Component={Catalogue} />

View File

@ -8,6 +8,7 @@ import { CheckCircleFillIcon, DownloadIcon } from "@primer/octicons-react";
import { Downloader, formatBytes } from "@shared";
import type { GameRepack, UserPreferences } from "@types";
import { SPACING_UNIT } from "@renderer/theme.css";
export interface SelectFolderModalProps {
visible: boolean;
@ -95,7 +96,14 @@ export function SelectFolderModal({
>
<div className={styles.container}>
<div>
<label style={{ marginBottom: 0, padding: 0 }}>Method</label>
<span
style={{
marginBottom: `${SPACING_UNIT}px`,
display: "block",
}}
>
Method
</span>
<div className={styles.downloaders}>
<Button
@ -130,25 +138,27 @@ export function SelectFolderModal({
</div>
</div>
<div className={styles.downloadsPathField}>
<TextField value={selectedPath} readOnly disabled label="Path" />
<div>
<div className={styles.downloadsPathField}>
<TextField value={selectedPath} readOnly disabled label="Path" />
<Button
style={{ alignSelf: "flex-end" }}
theme="outline"
onClick={handleChooseDownloadsPath}
disabled={downloadStarting}
>
{t("change")}
</Button>
<Button
style={{ alignSelf: "flex-end" }}
theme="outline"
onClick={handleChooseDownloadsPath}
disabled={downloadStarting}
>
{t("change")}
</Button>
</div>
<p className={styles.hintText}>
<Trans i18nKey="select_folder_hint" ns="game_details">
<Link to="/settings" />
</Trans>
</p>
</div>
<p className={styles.hintText}>
<Trans i18nKey="select_folder_hint" ns="game_details">
<Link to="/settings" />
</Trans>
</p>
<Button onClick={handleStartClick} disabled={downloadStarting}>
<DownloadIcon />
{t("download_now")}

View File

@ -10,5 +10,5 @@ export const form = style({
export const description = style({
fontFamily: "'Fira Sans', sans-serif",
marginBottom: `${SPACING_UNIT}px`,
marginBottom: `${SPACING_UNIT * 2}px`,
});

View File

@ -41,12 +41,7 @@ export function SettingsRealDebrid({
event
) => {
event.preventDefault();
dispatch(
showToast({
message: t("real_debrid_authenticated"),
type: "success",
})
);
if (form.useRealDebrid) {
const user = await window.electron.authenticateRealDebrid(
form.realDebridApiToken!
@ -55,18 +50,25 @@ export function SettingsRealDebrid({
if (user.type === "premium") {
dispatch(
showToast({
message: t("real_debrid_authenticated"),
type: "success",
message: t("real_debrid_free_account", { username: user.username }),
type: "error",
})
);
updateUserPreferences({
realDebridApiToken: form.useRealDebrid
? form.realDebridApiToken
: null,
});
return;
}
}
// dispatch(
// showToast({
// message: t("real_debrid_free_account", { username: "doctorp" }),
// type: "error",
// })
// );
updateUserPreferences({
realDebridApiToken: form.useRealDebrid ? form.realDebridApiToken : null,
});
};
const isButtonDisabled = form.useRealDebrid && !form.realDebridApiToken;
@ -106,7 +108,7 @@ export function SettingsRealDebrid({
<Button
type="submit"
style={{ alignSelf: "flex-end" }}
style={{ alignSelf: "flex-end", marginTop: `${SPACING_UNIT * 2}px` }}
disabled={isButtonDisabled}
>
{t("save_changes")}

View File

@ -1,49 +0,0 @@
import { style } from "@vanilla-extract/css";
import { SPACING_UNIT, vars } from "../../theme.css";
export const main = style({
width: "100%",
height: "100%",
display: "flex",
flexDirection: "column",
padding: `${SPACING_UNIT * 3}px`,
flex: "1",
overflowY: "auto",
alignItems: "center",
});
export const splashIcon = style({
width: "75%",
});
export const updateInfoSection = style({
width: "100%",
display: "flex",
flexDirection: "column",
gap: `${SPACING_UNIT * 2}px`,
flex: "1",
overflowY: "auto",
alignItems: "center",
justifyContent: "center",
});
export const progressBar = style({
WebkitAppearance: "none",
appearance: "none",
borderRadius: "4px",
width: "100%",
border: `solid 1px ${vars.color.border}`,
overflow: "hidden",
height: "18px",
"::-webkit-progress-value": {
backgroundColor: vars.color.muted,
transition: "width 0.2s",
},
"::-webkit-progress-bar": {
backgroundColor: vars.color.darkBackground,
},
});
export const progressBarText = style({
zIndex: 2,
});

View File

@ -1,82 +0,0 @@
import icon from "@renderer/assets/icon.png";
import * as styles from "./splash.css";
import { themeClass } from "../../theme.css";
import "../../app.css";
import { useEffect, useState } from "react";
import { AppUpdaterEvents } from "@types";
import { useTranslation } from "react-i18next";
document.body.classList.add(themeClass);
export default function Splash() {
const [status, setStatus] = useState<AppUpdaterEvents | null>(null);
const [newVersion, setNewVersion] = useState("");
const { t } = useTranslation("splash");
useEffect(() => {
const unsubscribe = window.electron.onAutoUpdaterEvent(
(event: AppUpdaterEvents) => {
setStatus(event);
switch (event.type) {
case "error":
window.electron.continueToMainWindow();
break;
case "update-available":
setNewVersion(event.info.version);
break;
case "update-cancelled":
window.electron.continueToMainWindow();
break;
case "update-downloaded":
window.electron.restartAndInstallUpdate();
break;
case "update-not-available":
window.electron.continueToMainWindow();
break;
}
}
);
window.electron.checkForUpdates();
return () => {
unsubscribe();
};
}, []);
const renderUpdateInfo = () => {
switch (status?.type) {
case "download-progress":
return (
<>
<p>{t("downloading_version", { version: newVersion })}</p>
<progress
className={styles.progressBar}
max="100"
value={status.info.percent}
/>
</>
);
case "checking-for-updates":
return <p>{t("searching_updates")}</p>;
case "update-available":
return <p>{t("update_found", { version: newVersion })}</p>;
case "update-downloaded":
return <p>{t("restarting_and_applying")}</p>;
default:
return <></>;
}
};
return (
<main className={styles.main}>
<img src={icon} className={styles.splashIcon} alt="Hydra Launcher Logo" />
<section className={styles.updateInfoSection}>
{renderUpdateInfo()}
</section>
</main>
);
}

View File

@ -230,3 +230,6 @@ export interface RealDebridUser {
premium: number;
expiration: string;
}
export type AppUpdaterEvents =
| { type: "update-available"; info: Partial<UpdateInfo> }
| { type: "update-downloaded" };

141
yarn.lock
View File

@ -235,11 +235,6 @@
"@babel/helper-validator-identifier" "^7.24.5"
to-fast-properties "^2.0.0"
"@colors/colors@1.6.0", "@colors/colors@^1.6.0":
version "1.6.0"
resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.6.0.tgz#ec6cd237440700bc23ca23087f513c75508958b0"
integrity sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==
"@commitlint/cli@^19.3.0":
version "19.3.0"
resolved "https://registry.yarnpkg.com/@commitlint/cli/-/cli-19.3.0.tgz#44e6da9823a01f0cdcc43054bbefdd2c6c5ddf39"
@ -396,15 +391,6 @@
"@types/conventional-commits-parser" "^5.0.0"
chalk "^5.3.0"
"@dabh/diagnostics@^2.0.2":
version "2.0.3"
resolved "https://registry.yarnpkg.com/@dabh/diagnostics/-/diagnostics-2.0.3.tgz#7f7e97ee9a725dffc7808d93668cc984e1dc477a"
integrity sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==
dependencies:
colorspace "1.1.x"
enabled "2.0.x"
kuler "^2.0.0"
"@develar/schema-utils@~2.6.5":
version "2.6.5"
resolved "https://registry.yarnpkg.com/@develar/schema-utils/-/schema-utils-2.6.5.tgz#3ece22c5838402419a6e0425f85742b961d9b6c6"
@ -1391,11 +1377,6 @@
resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.5.tgz#cb6e2a691b70cb177c6e3ae9c1d2e8b2ea8cd304"
integrity sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==
"@types/triple-beam@^1.3.2":
version "1.3.5"
resolved "https://registry.yarnpkg.com/@types/triple-beam/-/triple-beam-1.3.5.tgz#74fef9ffbaa198eb8b588be029f38b00299caa2c"
integrity sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==
"@types/use-sync-external-store@^0.0.3":
version "0.0.3"
resolved "https://registry.yarnpkg.com/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz#b6725d5f4af24ace33b36fafd295136e75509f43"
@ -2231,7 +2212,7 @@ clone-response@^1.0.2:
dependencies:
mimic-response "^1.0.0"
color-convert@^1.9.0, color-convert@^1.9.3:
color-convert@^1.9.0:
version "1.9.3"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
@ -2255,7 +2236,7 @@ color-name@^1.0.0, color-name@~1.1.4:
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
color-string@^1.6.0, color-string@^1.9.0:
color-string@^1.9.0:
version "1.9.1"
resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.1.tgz#4467f9146f036f855b764dfb5bf8582bf342c7a4"
integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==
@ -2268,14 +2249,6 @@ color.js@^1.2.0:
resolved "https://registry.yarnpkg.com/color.js/-/color.js-1.2.0.tgz#18d9f55545111730d25ccf18ea8b6933c71440d7"
integrity sha512-0ajlNgWWOR7EK9N6l2h0YKsZPzMCLQG5bheCoTGpGfhkR8tB5eQNItdua1oFHDTeq9JKgSzQJqo+Gp3V/xW+Lw==
color@^3.1.3:
version "3.2.1"
resolved "https://registry.yarnpkg.com/color/-/color-3.2.1.tgz#3544dc198caf4490c3ecc9a790b54fe9ff45e164"
integrity sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==
dependencies:
color-convert "^1.9.3"
color-string "^1.6.0"
color@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/color/-/color-4.2.3.tgz#d781ecb5e57224ee43ea9627560107c0e0c6463a"
@ -2284,14 +2257,6 @@ color@^4.2.3:
color-convert "^2.0.1"
color-string "^1.9.0"
colorspace@1.1.x:
version "1.1.4"
resolved "https://registry.yarnpkg.com/colorspace/-/colorspace-1.1.4.tgz#8d442d1186152f60453bf8070cd66eb364e59243"
integrity sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==
dependencies:
color "^3.1.3"
text-hex "1.0.x"
combined-stream@^1.0.8:
version "1.0.8"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
@ -2705,6 +2670,11 @@ electron-builder@^24.9.1:
simple-update-notifier "2.0.0"
yargs "^17.6.2"
electron-log@^5.1.4:
version "5.1.4"
resolved "https://registry.yarnpkg.com/electron-log/-/electron-log-5.1.4.tgz#9b7ea4ae1167475f3c9babc5c3d94d54f46dd35a"
integrity sha512-P0RSXnwT3z+e89Z5uAcZDeN85/QjIgv764a93kqCi+wh2Jm22CCbc3AGDt4S8rsxAHWHB4Q0PGsQl3fw1AN0kQ==
electron-publish@24.13.1:
version "24.13.1"
resolved "https://registry.yarnpkg.com/electron-publish/-/electron-publish-24.13.1.tgz#57289b2f7af18737dc2ad134668cdd4a1b574a0c"
@ -2768,11 +2738,6 @@ emoji-regex@^9.2.2:
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72"
integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==
enabled@2.0.x:
version "2.0.0"
resolved "https://registry.yarnpkg.com/enabled/-/enabled-2.0.0.tgz#f9dd92ec2d6f4bbc0d5d1e64e21d61cd4665e7c2"
integrity sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==
end-of-stream@^1.1.0, end-of-stream@^1.4.1:
version "1.4.4"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
@ -3249,11 +3214,6 @@ fd-slicer@~1.1.0:
dependencies:
pend "~1.2.0"
fecha@^4.2.0:
version "4.2.3"
resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.3.tgz#4d9ccdbc61e8629b259fdca67e65891448d569fd"
integrity sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==
fetch-blob@^3.1.2, fetch-blob@^3.1.4:
version "3.2.0"
resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.2.0.tgz#f09b8d4bbd45adc6f0c20b7e787e793e309dcce9"
@ -3332,11 +3292,6 @@ flexsearch@^0.7.43:
resolved "https://registry.yarnpkg.com/flexsearch/-/flexsearch-0.7.43.tgz#34f89b36278a466ce379c5bf6fb341965ed3f16c"
integrity sha512-c5o/+Um8aqCSOXGcZoqZOm+NqtVwNsvVpWv6lfmSclU954O3wvQKxxK8zj74fPaSJbXpSLTs4PRhh+wnoCXnKg==
fn.name@1.x.x:
version "1.1.0"
resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc"
integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==
follow-redirects@^1.15.6:
version "1.15.6"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b"
@ -4009,11 +3964,6 @@ is-shared-array-buffer@^1.0.2, is-shared-array-buffer@^1.0.3:
dependencies:
call-bind "^1.0.7"
is-stream@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077"
integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==
is-stream@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac"
@ -4244,11 +4194,6 @@ keyv@^4.0.0, keyv@^4.5.3:
dependencies:
json-buffer "3.0.1"
kuler@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/kuler/-/kuler-2.0.0.tgz#e2c570a3800388fb44407e851531c1d670b061b3"
integrity sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==
language-subtag-registry@^0.3.20:
version "0.3.22"
resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz#2e1500861b2e457eba7e7ae86877cbd08fa1fd1d"
@ -4363,18 +4308,6 @@ lodash@^4.17.15:
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
logform@^2.3.2, logform@^2.4.0:
version "2.6.0"
resolved "https://registry.yarnpkg.com/logform/-/logform-2.6.0.tgz#8c82a983f05d6eaeb2d75e3decae7a768b2bf9b5"
integrity sha512-1ulHeNPp6k/LD8H91o7VYFBng5i1BDE7HoKxVbZiGFidS1Rj65qcywLxX+pVfAPoQJEjRdvKcusKwOupHCVOVQ==
dependencies:
"@colors/colors" "1.6.0"
"@types/triple-beam" "^1.3.2"
fecha "^4.2.0"
ms "^2.1.1"
safe-stable-stringify "^2.3.1"
triple-beam "^1.3.0"
loose-envify@^1.1.0, loose-envify@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
@ -4610,11 +4543,6 @@ ms@2.1.2:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
ms@^2.1.1:
version "2.1.3"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
mz@^2.4.0:
version "2.7.0"
resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32"
@ -4771,13 +4699,6 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0:
dependencies:
wrappy "1"
one-time@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/one-time/-/one-time-1.0.0.tgz#e06bc174aed214ed58edede573b433bbf827cb45"
integrity sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==
dependencies:
fn.name "1.x.x"
onetime@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/onetime/-/onetime-6.0.0.tgz#7c24c18ed1fd2e9bca4bd26806a33613c77d34b4"
@ -5161,7 +5082,7 @@ read-config-file@6.3.2:
json5 "^2.2.0"
lazy-val "^1.0.4"
readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0:
readable-stream@^3.1.1, readable-stream@^3.4.0:
version "3.6.2"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967"
integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==
@ -5359,11 +5280,6 @@ safe-regex-test@^1.0.3:
es-errors "^1.3.0"
is-regex "^1.1.4"
safe-stable-stringify@^2.3.1:
version "2.4.3"
resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz#138c84b6f6edb3db5f8ef3ef7115b8f55ccbf886"
integrity sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==
"safer-buffer@>= 2.1.2 < 3.0.0":
version "2.1.2"
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
@ -5562,11 +5478,6 @@ sprintf-js@^1.1.2:
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.3.tgz#4914b903a2f8b685d17fdf78a70e917e872e444a"
integrity sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==
stack-trace@0.0.x:
version "0.0.10"
resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0"
integrity sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==
stat-mode@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/stat-mode/-/stat-mode-1.0.0.tgz#68b55cb61ea639ff57136f36b216a291800d1465"
@ -5778,11 +5689,6 @@ text-extensions@^2.0.0:
resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-2.4.0.tgz#a1cfcc50cf34da41bfd047cc744f804d1680ea34"
integrity sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==
text-hex@1.0.x:
version "1.0.0"
resolved "https://registry.yarnpkg.com/text-hex/-/text-hex-1.0.0.tgz#69dc9c1b17446ee79a92bf5b884bb4b9127506f5"
integrity sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==
text-table@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
@ -5858,11 +5764,6 @@ tr46@~0.0.3:
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==
triple-beam@^1.3.0:
version "1.4.1"
resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.4.1.tgz#6fde70271dc6e5d73ca0c3b24e2d92afb7441984"
integrity sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==
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"
@ -6233,32 +6134,6 @@ winreg@1.2.4:
resolved "https://registry.yarnpkg.com/winreg/-/winreg-1.2.4.tgz#ba065629b7a925130e15779108cf540990e98d1b"
integrity sha512-IHpzORub7kYlb8A43Iig3reOvlcBJGX9gZ0WycHhghHtA65X0LYnMRuJs+aH1abVnMJztQkvQNlltnbPi5aGIA==
winston-transport@^4.7.0:
version "4.7.0"
resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.7.0.tgz#e302e6889e6ccb7f383b926df6936a5b781bd1f0"
integrity sha512-ajBj65K5I7denzer2IYW6+2bNIVqLGDHqDw3Ow8Ohh+vdW+rv4MZ6eiDvHoKhfJFZ2auyN8byXieDDJ96ViONg==
dependencies:
logform "^2.3.2"
readable-stream "^3.6.0"
triple-beam "^1.3.0"
winston@^3.13.0:
version "3.13.0"
resolved "https://registry.yarnpkg.com/winston/-/winston-3.13.0.tgz#e76c0d722f78e04838158c61adc1287201de7ce3"
integrity sha512-rwidmA1w3SE4j0E5MuIufFhyJPBDG7Nu71RkZor1p2+qHvJSZ9GYDA81AyleQcZbh/+V6HjeBdfnTZJm9rSeQQ==
dependencies:
"@colors/colors" "^1.6.0"
"@dabh/diagnostics" "^2.0.2"
async "^3.2.3"
is-stream "^2.0.0"
logform "^2.4.0"
one-time "^1.0.0"
readable-stream "^3.4.0"
safe-stable-stringify "^2.3.1"
stack-trace "0.0.x"
triple-beam "^1.3.0"
winston-transport "^4.7.0"
word-wrap@^1.2.5:
version "1.2.5"
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34"