mirror of
https://github.com/hydralauncher/hydra.git
synced 2026-06-02 06:14:48 +02:00
Feat/lbx 650 (#2117)
* feat: Add new user preference for deleting archive files after extraction * feat: Implement user preference for automatic archive deletion after extraction * feat: Add checkbox for user preference to delete archive files after extraction * feat: Add delete archive files after extraction preference to settings * i18n: Add translations for "delete archive files after extraction" in English, Portuguese, and Russian * fix: Change default setting for extracting files after download to false * refactor: Rename user preference for deleting archive files after extraction to clarify default behavior * feat: Add automaticallyDeleteArchiveFiles property to download and game download payload types * refactor: Enhance archive deletion logic based on user preferences in GameFilesManager * refactor: Update addGameToQueue and startGameDownload to include automaticallyDeleteArchiveFiles parameter * refactor: Integrate automaticallyDeleteArchiveFiles parameter into DownloadSettingsModal and RepacksModal, and update related user preferences in SettingsContextDownloads * refactor: Include automaticallyDeleteArchiveFiles parameter in GameDetails component for enhanced download handling * refactor: streamline archive deletion prompt handling in App component * fix: enable extractFilesByDefault in SettingsContextDownloads for improved user experience * refactor: remove automatic extraction setting from DownloadSettingsModal * refactor: update download flow to ensure download starts before saving to sublevel * refactor: update GameFilesManager to send delete notifications instead of unlinking files directly * refactor: separate deleteArchive logic into a dedicated function and update GameFilesManager to use it --------- Co-authored-by: Chubby Granny Chaser <weak.fern2638@heliokroger.com> Co-authored-by: Helio Kroger <me@heliokroger.com>
This commit is contained in:
@@ -486,6 +486,7 @@
|
||||
"game_removed_from_pinned": "Game removed from pinned",
|
||||
"game_added_to_pinned": "Game added to pinned",
|
||||
"automatically_extract_downloaded_files": "Automatically extract downloaded files",
|
||||
"delete_archive_files_after_extraction": "Always delete archive files after extraction",
|
||||
"create_start_menu_shortcut": "Create Start Menu shortcut",
|
||||
"invalid_wine_prefix_path": "Invalid Wine prefix path",
|
||||
"invalid_wine_prefix_path_description": "The path to the Wine prefix is invalid. Please check the path and try again.",
|
||||
@@ -803,6 +804,7 @@
|
||||
"max_download_speed_unit_megabits": "Mbps",
|
||||
"max_download_speed_unlimited": "Unlimited",
|
||||
"extract_files_by_default": "Extract files by default after download",
|
||||
"delete_archive_files_after_extraction": "Always delete archive files after extraction",
|
||||
"enable_steam_achievements": "Enable search for Steam achievements",
|
||||
"enable_new_download_options_badges": "Show new download options badges",
|
||||
"achievement_custom_notification_position": "Achievement custom notification position",
|
||||
|
||||
@@ -349,6 +349,7 @@
|
||||
"files_removed_success": "Arquivos removidos com sucesso",
|
||||
"failed_remove_files": "Falha ao remover arquivos",
|
||||
"automatically_extract_downloaded_files": "Extrair automaticamente os arquivos baixados",
|
||||
"delete_archive_files_after_extraction": "Sempre deletar arquivos de arquivo após a extração",
|
||||
"create_start_menu_shortcut": "Criar atalho no Menu Iniciar",
|
||||
"invalid_wine_prefix_path": "Caminho do prefixo Wine inválido",
|
||||
"invalid_wine_prefix_path_description": "O caminho para o prefixo Wine é inválido. Por favor, verifique o caminho e tente novamente.",
|
||||
@@ -754,6 +755,7 @@
|
||||
"max_download_speed_unit_megabits": "Mbps",
|
||||
"max_download_speed_unlimited": "Ilimitada",
|
||||
"extract_files_by_default": "Extrair arquivos automaticamente após o download",
|
||||
"delete_archive_files_after_extraction": "Sempre deletar arquivos de arquivo após a extração",
|
||||
"enable_steam_achievements": "Habilitar busca por conquistas da Steam",
|
||||
"enable_new_download_options_badges": "Mostrar badges de novas opções de download",
|
||||
"enable_achievement_custom_notifications": "Habilitar notificações customizadas de conquistas",
|
||||
|
||||
@@ -486,6 +486,7 @@
|
||||
"game_removed_from_pinned": "Игра удалена из закрепленных",
|
||||
"game_added_to_pinned": "Игра добавлена в закрепленные",
|
||||
"automatically_extract_downloaded_files": "Автоматическая распаковка загруженных файлов",
|
||||
"delete_archive_files_after_extraction": "Всегда удалять архивные файлы после извлечения",
|
||||
"create_start_menu_shortcut": "Создать ярлык в меню «Пуск»",
|
||||
"invalid_wine_prefix_path": "Недопустимый путь префикса Wine",
|
||||
"invalid_wine_prefix_path_description": "Путь к префиксу Wine недействителен. Пожалуйста, проверьте путь и попробуйте снова.",
|
||||
@@ -798,6 +799,7 @@
|
||||
"max_download_speed_unit_megabits": "Mbps",
|
||||
"max_download_speed_unlimited": "Без ограничений",
|
||||
"extract_files_by_default": "Извлекать файлы по умолчанию после загрузки",
|
||||
"delete_archive_files_after_extraction": "Всегда удалять архивные файлы после извлечения",
|
||||
"enable_steam_achievements": "Включить поиск достижений Steam",
|
||||
"enable_new_download_options_badges": "Показывать значки новых вариантов загрузки",
|
||||
"achievement_custom_notification_position": "Позиция уведомлений достижений",
|
||||
|
||||
@@ -2,13 +2,10 @@ import path from "node:path";
|
||||
import fs from "node:fs";
|
||||
|
||||
import { registerEvent } from "../register-event";
|
||||
import { logger } from "@main/services";
|
||||
import { logger } from "@main/services/logger";
|
||||
import { downloadsSublevel, gamesSublevel, levelKeys } from "@main/level";
|
||||
|
||||
const deleteArchive = async (
|
||||
_event: Electron.IpcMainInvokeEvent,
|
||||
filePath: string
|
||||
) => {
|
||||
export const deleteArchiveFile = async (filePath: string) => {
|
||||
try {
|
||||
if (fs.existsSync(filePath)) {
|
||||
await fs.promises.unlink(filePath);
|
||||
@@ -47,4 +44,9 @@ const deleteArchive = async (
|
||||
}
|
||||
};
|
||||
|
||||
const deleteArchive = async (
|
||||
_event: Electron.IpcMainInvokeEvent,
|
||||
filePath: string
|
||||
) => deleteArchiveFile(filePath);
|
||||
|
||||
registerEvent("deleteArchive", deleteArchive);
|
||||
|
||||
@@ -22,6 +22,7 @@ const addGameToQueue = async (
|
||||
downloader,
|
||||
uri,
|
||||
automaticallyExtract,
|
||||
automaticallyDeleteArchiveFiles,
|
||||
fileSize,
|
||||
fileIndices,
|
||||
selectedFilesSize,
|
||||
@@ -47,6 +48,7 @@ const addGameToQueue = async (
|
||||
queued: true,
|
||||
extracting: false,
|
||||
automaticallyExtract,
|
||||
automaticallyDeleteArchiveFiles,
|
||||
extractionProgress: 0,
|
||||
fileIndices,
|
||||
selectedFilesSize,
|
||||
|
||||
@@ -21,6 +21,7 @@ const startGameDownload = async (
|
||||
downloader,
|
||||
uri,
|
||||
automaticallyExtract,
|
||||
automaticallyDeleteArchiveFiles,
|
||||
fileIndices,
|
||||
selectedFilesSize,
|
||||
} = payload;
|
||||
@@ -61,6 +62,7 @@ const startGameDownload = async (
|
||||
queued: true,
|
||||
extracting: false,
|
||||
automaticallyExtract,
|
||||
automaticallyDeleteArchiveFiles,
|
||||
extractionProgress: 0,
|
||||
fileIndices,
|
||||
selectedFilesSize,
|
||||
|
||||
@@ -1,27 +1,28 @@
|
||||
import path from "node:path";
|
||||
import fs from "node:fs";
|
||||
import axios from "axios";
|
||||
import sharp from "sharp";
|
||||
import pngToIco from "png-to-ico";
|
||||
import type { GameShop, UserPreferences } from "@types";
|
||||
import { ASSETS_PATH } from "@main/constants";
|
||||
import { getGameAssets } from "@main/events/catalogue/get-game-assets";
|
||||
import { getDirectorySize } from "@main/events/helpers/get-directory-size";
|
||||
import { db, downloadsSublevel, gamesSublevel, levelKeys } from "@main/level";
|
||||
import {
|
||||
Downloader,
|
||||
FILE_EXTENSIONS_TO_EXTRACT,
|
||||
removeSymbolsFromName,
|
||||
} from "@shared";
|
||||
import { SevenZip, ExtractionProgress } from "./7zip";
|
||||
import { WindowManager } from "./window-manager";
|
||||
import { publishExtractionCompleteNotification } from "./notifications";
|
||||
import { logger } from "./logger";
|
||||
import { getDirectorySize } from "@main/events/helpers/get-directory-size";
|
||||
import { GameExecutables } from "./game-executables";
|
||||
import type { GameShop, UserPreferences } from "@types";
|
||||
import axios from "axios";
|
||||
import createDesktopShortcut from "create-desktop-shortcuts";
|
||||
import { app } from "electron";
|
||||
import { SystemPath } from "./system-path";
|
||||
import { ASSETS_PATH } from "@main/constants";
|
||||
import { getGameAssets } from "@main/events/catalogue/get-game-assets";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import pngToIco from "png-to-ico";
|
||||
import sharp from "sharp";
|
||||
import { ExtractionProgress, SevenZip } from "./7zip";
|
||||
import { getPathType } from "./extraction-path";
|
||||
import { GameExecutables } from "./game-executables";
|
||||
import { logger } from "./logger";
|
||||
import { deleteArchiveFile } from "@main/events/library/delete-archive";
|
||||
import { publishExtractionCompleteNotification } from "./notifications";
|
||||
import { SystemPath } from "./system-path";
|
||||
import { WindowManager } from "./window-manager";
|
||||
|
||||
const PROGRESS_THROTTLE_MS = 1000;
|
||||
|
||||
@@ -186,10 +187,28 @@ export class GameFilesManager {
|
||||
.filter((archivePath) => fs.existsSync(archivePath));
|
||||
|
||||
if (archivePaths.length > 0) {
|
||||
WindowManager.mainWindow?.webContents.send(
|
||||
"on-archive-deletion-prompt",
|
||||
archivePaths
|
||||
);
|
||||
const [download, userPreferences] = await Promise.all([
|
||||
downloadsSublevel.get(this.gameKey),
|
||||
db.get<string, UserPreferences | null>(levelKeys.userPreferences, {
|
||||
valueEncoding: "json",
|
||||
}),
|
||||
]);
|
||||
|
||||
const shouldDelete =
|
||||
download?.automaticallyDeleteArchiveFiles ??
|
||||
userPreferences?.deleteArchiveFilesAfterExtractionByDefault ??
|
||||
false;
|
||||
|
||||
if (shouldDelete) {
|
||||
for (const archivePath of archivePaths) {
|
||||
await deleteArchiveFile(archivePath);
|
||||
}
|
||||
} else {
|
||||
WindowManager.mainWindow?.webContents.send(
|
||||
"on-archive-deletion-prompt",
|
||||
archivePaths
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -656,10 +675,24 @@ export class GameFilesManager {
|
||||
}
|
||||
|
||||
if (fs.existsSync(extractionPath) && fs.existsSync(filePath)) {
|
||||
WindowManager.mainWindow?.webContents.send(
|
||||
"on-archive-deletion-prompt",
|
||||
[filePath]
|
||||
const userPreferences = await db.get<string, UserPreferences | null>(
|
||||
levelKeys.userPreferences,
|
||||
{ valueEncoding: "json" }
|
||||
);
|
||||
|
||||
const shouldDelete =
|
||||
download.automaticallyDeleteArchiveFiles ??
|
||||
userPreferences?.deleteArchiveFilesAfterExtractionByDefault ??
|
||||
false;
|
||||
|
||||
if (shouldDelete) {
|
||||
await deleteArchiveFile(filePath);
|
||||
} else {
|
||||
WindowManager.mainWindow?.webContents.send(
|
||||
"on-archive-deletion-prompt",
|
||||
[filePath]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
await downloadsSublevel.put(this.gameKey, {
|
||||
|
||||
+18
-18
@@ -1,6 +1,4 @@
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { Sidebar, BottomPanel, Header, Toast } from "@renderer/components";
|
||||
import { WorkWonders } from "workwonders-sdk";
|
||||
import { BottomPanel, Header, Sidebar, Toast } from "@renderer/components";
|
||||
import {
|
||||
useAppDispatch,
|
||||
useAppSelector,
|
||||
@@ -10,32 +8,34 @@ import {
|
||||
useUserDetails,
|
||||
} from "@renderer/hooks";
|
||||
import { useDownloadOptionsListener } from "@renderer/hooks/use-download-options-listener";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { WorkWonders } from "workwonders-sdk";
|
||||
|
||||
import { Outlet, useLocation, useNavigate } from "react-router-dom";
|
||||
import {
|
||||
clearExtraction,
|
||||
closeToast,
|
||||
setExtractionProgress,
|
||||
setGameRunning,
|
||||
setProfileBackground,
|
||||
setUserDetails,
|
||||
setUserPreferences,
|
||||
toggleDraggingDisabled,
|
||||
closeToast,
|
||||
setUserDetails,
|
||||
setProfileBackground,
|
||||
setGameRunning,
|
||||
setExtractionProgress,
|
||||
clearExtraction,
|
||||
} from "@renderer/features";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Outlet, useLocation, useNavigate } from "react-router-dom";
|
||||
import { useSubscription } from "./hooks/use-subscription";
|
||||
import { HydraCloudModal } from "./pages/shared-modals/hydra-cloud/hydra-cloud-modal";
|
||||
import { ArchiveDeletionModal } from "./pages/downloads/archive-deletion-error-modal";
|
||||
import { HydraCloudModal } from "./pages/shared-modals/hydra-cloud/hydra-cloud-modal";
|
||||
|
||||
import {
|
||||
injectCustomCss,
|
||||
removeCustomCss,
|
||||
getAchievementSoundUrl,
|
||||
getAchievementSoundVolume,
|
||||
} from "./helpers";
|
||||
import { levelDBService } from "./services/leveldb.service";
|
||||
import type { UserPreferences } from "@types";
|
||||
import "./app.scss";
|
||||
import {
|
||||
getAchievementSoundUrl,
|
||||
getAchievementSoundVolume,
|
||||
injectCustomCss,
|
||||
removeCustomCss,
|
||||
} from "./helpers";
|
||||
import { levelDBService } from "./services/leveldb.service";
|
||||
|
||||
export interface AppProps {
|
||||
children: React.ReactNode;
|
||||
|
||||
@@ -105,6 +105,7 @@ export default function GameDetails() {
|
||||
addToQueueOnly = false,
|
||||
fileIndices?: number[],
|
||||
selectedFilesSize?: number | null,
|
||||
automaticallyDeleteArchiveFiles = false,
|
||||
signal?: AbortSignal
|
||||
) => {
|
||||
const response = addToQueueOnly
|
||||
@@ -116,7 +117,8 @@ export default function GameDetails() {
|
||||
shop,
|
||||
downloadPath,
|
||||
uri: selectRepackUri(repack, downloader),
|
||||
automaticallyExtract: automaticallyExtract,
|
||||
automaticallyExtract,
|
||||
automaticallyDeleteArchiveFiles,
|
||||
fileSize: repack.fileSize,
|
||||
fileIndices,
|
||||
selectedFilesSize,
|
||||
@@ -131,7 +133,8 @@ export default function GameDetails() {
|
||||
shop,
|
||||
downloadPath,
|
||||
uri: selectRepackUri(repack, downloader),
|
||||
automaticallyExtract: automaticallyExtract,
|
||||
automaticallyExtract,
|
||||
automaticallyDeleteArchiveFiles,
|
||||
fileSize: repack.fileSize,
|
||||
fileIndices,
|
||||
selectedFilesSize,
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import {
|
||||
type ReactNode,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from "react";
|
||||
import { Trans, useTranslation } from "react-i18next";
|
||||
CheckCircleFillIcon,
|
||||
CheckIcon,
|
||||
ChevronDownIcon,
|
||||
DownloadIcon,
|
||||
FileDirectoryIcon,
|
||||
FileIcon,
|
||||
PlusIcon,
|
||||
SyncIcon,
|
||||
} from "@primer/octicons-react";
|
||||
import {
|
||||
Badge,
|
||||
Button,
|
||||
@@ -16,23 +17,6 @@ import {
|
||||
SelectField,
|
||||
TextField,
|
||||
} from "@renderer/components";
|
||||
import {
|
||||
DownloadIcon,
|
||||
SyncIcon,
|
||||
CheckCircleFillIcon,
|
||||
CheckIcon,
|
||||
PlusIcon,
|
||||
ChevronDownIcon,
|
||||
FileDirectoryIcon,
|
||||
FileIcon,
|
||||
} from "@primer/octicons-react";
|
||||
import {
|
||||
DownloadError,
|
||||
Downloader,
|
||||
formatBytes,
|
||||
getDownloadersForUri,
|
||||
} from "@shared";
|
||||
import type { GameRepack, TorrentFile, TorrentFilesResponse } from "@types";
|
||||
import { DOWNLOADER_NAME } from "@renderer/constants";
|
||||
import {
|
||||
useAppSelector,
|
||||
@@ -40,10 +24,26 @@ import {
|
||||
useFeature,
|
||||
useToast,
|
||||
} from "@renderer/hooks";
|
||||
import {
|
||||
DownloadError,
|
||||
Downloader,
|
||||
formatBytes,
|
||||
getDownloadersForUri,
|
||||
} from "@shared";
|
||||
import type { GameRepack, TorrentFile, TorrentFilesResponse } from "@types";
|
||||
import { motion } from "framer-motion";
|
||||
import {
|
||||
type ReactNode,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from "react";
|
||||
import { Trans, useTranslation } from "react-i18next";
|
||||
import { Tooltip } from "react-tooltip";
|
||||
import { RealDebridInfoModal } from "./real-debrid-info-modal";
|
||||
import "./download-settings-modal.scss";
|
||||
import { RealDebridInfoModal } from "./real-debrid-info-modal";
|
||||
|
||||
export interface DownloadSettingsModalProps {
|
||||
visible: boolean;
|
||||
@@ -56,6 +56,7 @@ export interface DownloadSettingsModalProps {
|
||||
addToQueueOnly?: boolean,
|
||||
fileIndices?: number[],
|
||||
selectedFilesSize?: number | null,
|
||||
automaticallyDeleteArchiveFiles?: boolean,
|
||||
signal?: AbortSignal
|
||||
) => Promise<{ ok: boolean; error?: string }>;
|
||||
repack: GameRepack | null;
|
||||
@@ -251,6 +252,12 @@ export function DownloadSettingsModal({
|
||||
const [automaticExtractionEnabled, setAutomaticExtractionEnabled] = useState(
|
||||
userPreferences?.extractFilesByDefault ?? true
|
||||
);
|
||||
const [
|
||||
deleteArchiveFilesAfterExtraction,
|
||||
setDeleteArchiveFilesAfterExtraction,
|
||||
] = useState(
|
||||
userPreferences?.deleteArchiveFilesAfterExtractionByDefault ?? false
|
||||
);
|
||||
const [selectedDownloader, setSelectedDownloader] =
|
||||
useState<Downloader | null>(null);
|
||||
const [hasWritePermission, setHasWritePermission] = useState<boolean | null>(
|
||||
@@ -469,6 +476,18 @@ export function DownloadSettingsModal({
|
||||
setSelectedDownloader(getDefaultDownloader(availableDownloaders));
|
||||
}, [getDefaultDownloader, userPreferences?.downloadsPath, downloadOptions]);
|
||||
|
||||
useEffect(() => {
|
||||
if (visible) {
|
||||
setDeleteArchiveFilesAfterExtraction(
|
||||
userPreferences?.deleteArchiveFilesAfterExtractionByDefault ?? false
|
||||
);
|
||||
setAutomaticExtractionEnabled(
|
||||
userPreferences?.extractFilesByDefault ?? true
|
||||
);
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [visible]);
|
||||
|
||||
const torrentFilesByIndex = useMemo(() => {
|
||||
const fileMap = new Map<number, TorrentFile>();
|
||||
torrentFiles.forEach((file) => fileMap.set(file.index, file));
|
||||
@@ -931,6 +950,7 @@ export function DownloadSettingsModal({
|
||||
hasActiveDownload,
|
||||
selectedFileIndices,
|
||||
totalSelectedSize,
|
||||
deleteArchiveFilesAfterExtraction,
|
||||
abortController.signal
|
||||
);
|
||||
|
||||
@@ -1382,6 +1402,16 @@ export function DownloadSettingsModal({
|
||||
}
|
||||
/>
|
||||
|
||||
<CheckboxField
|
||||
label={t("delete_archive_files_after_extraction")}
|
||||
checked={deleteArchiveFilesAfterExtraction}
|
||||
onChange={() =>
|
||||
setDeleteArchiveFilesAfterExtraction(
|
||||
!deleteArchiveFilesAfterExtraction
|
||||
)
|
||||
}
|
||||
/>
|
||||
|
||||
<Button
|
||||
onClick={handlePrimaryButtonClick}
|
||||
disabled={
|
||||
|
||||
@@ -43,6 +43,7 @@ export interface RepacksModalProps {
|
||||
addToQueueOnly?: boolean,
|
||||
fileIndices?: number[],
|
||||
selectedFilesSize?: number | null,
|
||||
automaticallyDeleteArchiveFiles?: boolean,
|
||||
signal?: AbortSignal
|
||||
) => Promise<{ ok: boolean; error?: string }>;
|
||||
onClose: () => void;
|
||||
|
||||
@@ -49,6 +49,7 @@ export function SettingsContextDownloads() {
|
||||
extractFilesByDefault: true,
|
||||
createStartMenuShortcut: true,
|
||||
maxDownloadSpeedMegabytes: "",
|
||||
deleteArchiveFilesAfterExtractionByDefault: false,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
@@ -69,6 +70,8 @@ export function SettingsContextDownloads() {
|
||||
userPreferences.showDownloadSpeedInMegabytes ?? false
|
||||
)
|
||||
: "",
|
||||
deleteArchiveFilesAfterExtractionByDefault:
|
||||
userPreferences.deleteArchiveFilesAfterExtractionByDefault ?? false,
|
||||
});
|
||||
}, [userPreferences]);
|
||||
|
||||
@@ -182,6 +185,17 @@ export function SettingsContextDownloads() {
|
||||
onChange={handleSpeedUnitChange}
|
||||
/>
|
||||
|
||||
<CheckboxField
|
||||
label={t("delete_archive_files_after_extraction")}
|
||||
checked={form.deleteArchiveFilesAfterExtractionByDefault}
|
||||
onChange={() =>
|
||||
handleChange({
|
||||
deleteArchiveFilesAfterExtractionByDefault:
|
||||
!form.deleteArchiveFilesAfterExtractionByDefault,
|
||||
})
|
||||
}
|
||||
/>
|
||||
|
||||
{window.electron.platform === "win32" && (
|
||||
<CheckboxField
|
||||
label={t("create_shortcuts_on_download")}
|
||||
|
||||
@@ -138,6 +138,7 @@ export interface StartGameDownloadPayload {
|
||||
downloadPath: string;
|
||||
downloader: Downloader;
|
||||
automaticallyExtract: boolean;
|
||||
automaticallyDeleteArchiveFiles: boolean;
|
||||
fileSize?: string | null;
|
||||
fileIndices?: number[];
|
||||
selectedFilesSize?: number | null;
|
||||
|
||||
@@ -88,6 +88,7 @@ export interface Download {
|
||||
timestamp: number;
|
||||
extracting: boolean;
|
||||
automaticallyExtract: boolean;
|
||||
automaticallyDeleteArchiveFiles: boolean;
|
||||
extractionProgress: number;
|
||||
fileIndices?: number[];
|
||||
selectedFilesSize?: number | null;
|
||||
@@ -136,6 +137,7 @@ export interface UserPreferences {
|
||||
friendStartGameNotificationsEnabled?: boolean;
|
||||
showDownloadSpeedInMegabytes?: boolean;
|
||||
extractFilesByDefault?: boolean;
|
||||
deleteArchiveFilesAfterExtractionByDefault?: boolean;
|
||||
enableSteamAchievements?: boolean;
|
||||
autoplayGameTrailers?: boolean;
|
||||
hideToTrayOnGameStart?: boolean;
|
||||
|
||||
Reference in New Issue
Block a user