feat: updating settings general

This commit is contained in:
Chubby Granny Chaser 2024-06-03 02:17:58 +01:00
commit 28de50b244
No known key found for this signature in database
13 changed files with 280 additions and 92 deletions

View file

@ -135,7 +135,7 @@ pip install -r requirements.txt
You'll need an SteamGridDB API Key in order to fetch the game icons on installation. You'll need an SteamGridDB API Key in order to fetch the game icons on installation.
If you want to have onlinefix as a repacker you'll need to add your credentials to the .env If you want to have onlinefix as a repacker you'll need to add your credentials to the .env
Once you have it, you can copy or rename the `.env.example` file to `.env`and put it on`STEAMGRIDDB_API_KEY`, `ONLINEFIX_USERNAME`, `ONLINEFIX_PASSWORD`. Once you have it, you can copy or rename the `.env.example` file to `.env` and put it on`STEAMGRIDDB_API_KEY`, `ONLINEFIX_USERNAME`, `ONLINEFIX_PASSWORD`.
## Running ## Running

View file

@ -40,6 +40,7 @@
"@reduxjs/toolkit": "^2.2.3", "@reduxjs/toolkit": "^2.2.3",
"@vanilla-extract/css": "^1.14.2", "@vanilla-extract/css": "^1.14.2",
"@vanilla-extract/recipes": "^0.5.2", "@vanilla-extract/recipes": "^0.5.2",
"iso-639-1": "3.1.2",
"aria2": "^4.1.2", "aria2": "^4.1.2",
"auto-launch": "^5.0.6", "auto-launch": "^5.0.6",
"axios": "^1.6.8", "axios": "^1.6.8",

View file

@ -149,6 +149,7 @@
"general": "General", "general": "General",
"behavior": "Behavior", "behavior": "Behavior",
"download_sources": "Download sources", "download_sources": "Download sources",
"language": "Language",
"real_debrid_api_token": "API Token", "real_debrid_api_token": "API Token",
"enable_real_debrid": "Enable Real-Debrid", "enable_real_debrid": "Enable 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_description": "Real-Debrid is an unrestricted downloader that allows you to download files instantly and at the best of your Internet speed.",

View file

@ -29,12 +29,13 @@
"downloads": "Descargas", "downloads": "Descargas",
"search_results": "Resultados de búsqueda", "search_results": "Resultados de búsqueda",
"settings": "Ajustes", "settings": "Ajustes",
"version_available": "Version {{version}} disponible. Haga clic aquí para reiniciar e instalar." "version_available": "Version {{version}} disponible. Haz clic aquí para reiniciar e instalar."
}, },
"bottom_panel": { "bottom_panel": {
"no_downloads_in_progress": "Sin descargas en progreso", "no_downloads_in_progress": "Sin descargas en progreso",
"downloading_metadata": "Descargando metadatos de {{title}}…", "downloading_metadata": "Descargando metadatos de {{title}}…",
"downloading": "Descargando {{title}}… ({{percentage}} completado) - Finalizando {{eta}} - {{speed}}" "downloading": "Descargando {{title}}… ({{percentage}} completado) - Finalizando {{eta}} - {{speed}}",
"calculating_eta": "Descargando {{title}}… ({{percentage}} completado) - Calculando tiempo restante…"
}, },
"catalogue": { "catalogue": {
"next_page": "Siguiente página", "next_page": "Siguiente página",
@ -54,6 +55,7 @@
"remove_from_list": "Quitar", "remove_from_list": "Quitar",
"space_left_on_disk": "{{space}} restantes en el disco", "space_left_on_disk": "{{space}} restantes en el disco",
"eta": "Tiempo restante: {{eta}}", "eta": "Tiempo restante: {{eta}}",
"calculating_eta": "Calculando tiempo restante…",
"downloading_metadata": "Descargando metadatos…", "downloading_metadata": "Descargando metadatos…",
"filter": "Buscar repacks", "filter": "Buscar repacks",
"requirements": "Requisitos del Sistema", "requirements": "Requisitos del Sistema",
@ -61,6 +63,7 @@
"recommended": "Recomendados", "recommended": "Recomendados",
"no_minimum_requirements": "Sin requisitos mínimos para {{title}}", "no_minimum_requirements": "Sin requisitos mínimos para {{title}}",
"no_recommended_requirements": "{{title}} no tiene requisitos recomendados", "no_recommended_requirements": "{{title}} no tiene requisitos recomendados",
"paused": "Pausado",
"release_date": "Fecha de lanzamiento: {{date}}", "release_date": "Fecha de lanzamiento: {{date}}",
"publisher": "Publicado por: {{publisher}}", "publisher": "Publicado por: {{publisher}}",
"copy_link_to_clipboard": "Copiar enlace", "copy_link_to_clipboard": "Copiar enlace",
@ -99,7 +102,9 @@
"previous_screenshot": "Anterior captura", "previous_screenshot": "Anterior captura",
"next_screenshot": "Siguiente captura", "next_screenshot": "Siguiente captura",
"screenshot": "Captura {{number}}", "screenshot": "Captura {{number}}",
"open_screenshot": "Abrir captura {{number}}" "open_screenshot": "Abrir captura {{number}}",
"download_settings": "Ajustes de descarga",
"downloader": "Descargador"
}, },
"activation": { "activation": {
"title": "Activar Hydra", "title": "Activar Hydra",
@ -117,6 +122,7 @@
"verifying": "Verificando…", "verifying": "Verificando…",
"completed_at": "Completado el {{date}}", "completed_at": "Completado el {{date}}",
"completed": "Completado", "completed": "Completado",
"removed": "No descargado",
"download_again": "Descargar de nuevo", "download_again": "Descargar de nuevo",
"cancel": "Cancelar", "cancel": "Cancelar",
"filter": "Buscar juegos descargados", "filter": "Buscar juegos descargados",
@ -143,9 +149,16 @@
"launch_with_system": "Iniciar Hydra al inicio del sistema", "launch_with_system": "Iniciar Hydra al inicio del sistema",
"general": "General", "general": "General",
"behavior": "Otros", "behavior": "Otros",
"language": "Idioma",
"real_debrid_api_token": "Token API",
"enable_real_debrid": "Activar Real-Debrid", "enable_real_debrid": "Activar Real-Debrid",
"real_debrid_description": "Real-Debrid es un descargador sin restricciones que te permite descargar archivos instantáneamente con la máxima velocidad de tu internet.",
"real_debrid_invalid_token": "Token de API inválido",
"real_debrid_api_token_hint": "Puedes obtener tu clave de API <0>aquí</0>", "real_debrid_api_token_hint": "Puedes obtener tu clave de API <0>aquí</0>",
"save_changes": "Guardar cambios" "real_debrid_free_account_error": "La cuenta \"{{username}}\" es una cuenta gratuita. Por favor, suscríbete a Real-Debrid",
"real_debrid_linked_message": "Cuenta \"{{username}}\" vinculada",
"save_changes": "Guardar cambios",
"changes_saved": "Ajustes guardados exitosamente"
}, },
"notifications": { "notifications": {
"download_complete": "Descarga completada", "download_complete": "Descarga completada",

View file

@ -109,7 +109,8 @@
"enable_download_notifications": "Quand un téléchargement est terminé", "enable_download_notifications": "Quand un téléchargement est terminé",
"enable_repack_list_notifications": "Quand un nouveau repack est ajouté", "enable_repack_list_notifications": "Quand un nouveau repack est ajouté",
"telemetry": "Télémétrie", "telemetry": "Télémétrie",
"telemetry_description": "Activer les statistiques d'utilisation anonymes" "telemetry_description": "Activer les statistiques d'utilisation anonymes",
"language": "Langue"
}, },
"notifications": { "notifications": {
"download_complete": "Téléchargement terminé", "download_complete": "Téléchargement terminé",

View file

@ -142,6 +142,7 @@
"launch_with_system": "Uruchom Hydra przy starcie systemu", "launch_with_system": "Uruchom Hydra przy starcie systemu",
"general": "Ogólne", "general": "Ogólne",
"behavior": "Zachowania", "behavior": "Zachowania",
"language": "Język",
"enable_real_debrid": "Włącz Real-Debrid", "enable_real_debrid": "Włącz Real-Debrid",
"real_debrid_api_token_hint": "Możesz uzyskać swój klucz API <0>tutaj</0>", "real_debrid_api_token_hint": "Możesz uzyskać swój klucz API <0>tutaj</0>",
"save_changes": "Zapisz zmiany" "save_changes": "Zapisz zmiany"

View file

@ -146,6 +146,7 @@
"general": "Geral", "general": "Geral",
"behavior": "Comportamento", "behavior": "Comportamento",
"download_sources": "Bibliotecas de download", "download_sources": "Bibliotecas de download",
"language": "Idioma",
"real_debrid_api_token": "Token de API", "real_debrid_api_token": "Token de API",
"enable_real_debrid": "Habilitar Real-Debrid", "enable_real_debrid": "Habilitar Real-Debrid",
"real_debrid_api_token_hint": "Você pode obter seu token de API <0>aqui</0>", "real_debrid_api_token_hint": "Você pode obter seu token de API <0>aqui</0>",

View file

@ -1,13 +1,28 @@
import { gameRepository } from "@main/repository"; import { shell } from "electron";
import { generateYML } from "../helpers/generate-lutris-yaml";
import path from "node:path"; import path from "node:path";
import fs from "node:fs"; import fs from "node:fs";
import { writeFile } from "node:fs/promises"; import { writeFile } from "node:fs/promises";
import { spawnSync, exec } from "node:child_process"; import { spawnSync, exec } from "node:child_process";
import { registerEvent } from "../register-event"; import { gameRepository } from "@main/repository";
import { shell } from "electron";
import { generateYML } from "../helpers/generate-lutris-yaml";
import { getDownloadsPath } from "../helpers/get-downloads-path"; import { getDownloadsPath } from "../helpers/get-downloads-path";
import { registerEvent } from "../register-event";
const executeGameInstaller = (filePath: string) => {
if (process.platform === "win32") {
shell.openPath(filePath);
return true;
}
if (spawnSync("which", ["wine"]).status === 0) {
exec(`wine "${filePath}"`);
return true;
}
return false;
};
const openGameInstaller = async ( const openGameInstaller = async (
_event: Electron.IpcMainInvokeEvent, _event: Electron.IpcMainInvokeEvent,
@ -17,7 +32,7 @@ const openGameInstaller = async (
where: { id: gameId, isDeleted: false }, where: { id: gameId, isDeleted: false },
}); });
if (!game) return true; if (!game || !game.folderName) return true;
const gamePath = path.join( const gamePath = path.join(
game.downloadPath ?? (await getDownloadsPath()), game.downloadPath ?? (await getDownloadsPath()),
@ -29,15 +44,24 @@ const openGameInstaller = async (
return true; return true;
} }
const setupPath = path.join(gamePath, "setup.exe"); if (fs.lstatSync(gamePath).isFile()) {
if (!fs.existsSync(setupPath)) { return executeGameInstaller(gamePath);
shell.openPath(gamePath);
return true;
} }
if (process.platform === "win32") { const setupPath = path.join(gamePath, "setup.exe");
shell.openPath(setupPath); if (fs.existsSync(setupPath)) {
return true; return executeGameInstaller(setupPath);
}
const gamePathFileNames = fs.readdirSync(gamePath);
const gamePathExecutableFiles = gamePathFileNames.filter(
(fileName: string) => path.extname(fileName).toLowerCase() === ".exe"
);
if (gamePathExecutableFiles.length === 1) {
return executeGameInstaller(
path.join(gamePath, gamePathExecutableFiles[0])
);
} }
if (spawnSync("which", ["lutris"]).status === 0) { if (spawnSync("which", ["lutris"]).status === 0) {
@ -47,12 +71,8 @@ const openGameInstaller = async (
return true; return true;
} }
if (spawnSync("which", ["wine"]).status === 0) { shell.openPath(gamePath);
exec(`wine "${setupPath}"`); return true;
return true;
}
return false;
}; };
registerEvent("openGameInstaller", openGameInstaller); registerEvent("openGameInstaller", openGameInstaller);

View file

@ -8,4 +8,5 @@ export * from "./sidebar/sidebar";
export * from "./text-field/text-field"; export * from "./text-field/text-field";
export * from "./checkbox-field/checkbox-field"; export * from "./checkbox-field/checkbox-field";
export * from "./link/link"; export * from "./link/link";
export * from "./select-field/select-field";
export * from "./toast/toast"; export * from "./toast/toast";

View file

@ -0,0 +1,58 @@
import { SPACING_UNIT, vars } from "../../theme.css";
import { style } from "@vanilla-extract/css";
import { recipe } from "@vanilla-extract/recipes";
export const select = recipe({
base: {
display: "inline-flex",
transition: "all ease 0.2s",
width: "fit-content",
alignItems: "center",
borderRadius: "8px",
border: `1px solid ${vars.color.border}`,
height: "40px",
minHeight: "40px",
},
variants: {
focused: {
true: {
borderColor: "#DADBE1",
},
false: {
":hover": {
borderColor: "rgba(255, 255, 255, 0.5)",
},
},
},
theme: {
primary: {
backgroundColor: vars.color.darkBackground,
},
dark: {
backgroundColor: vars.color.background,
},
},
},
});
export const option = style({
backgroundColor: vars.color.darkBackground,
borderRight: "4px solid",
borderColor: "transparent",
borderRadius: "8px",
width: "fit-content",
height: "100%",
outline: "none",
color: "#DADBE1",
cursor: "default",
fontFamily: "inherit",
fontSize: vars.size.body,
textOverflow: "ellipsis",
padding: `${SPACING_UNIT}px`,
});
export const label = style({
marginBottom: `${SPACING_UNIT}px`,
display: "block",
color: vars.color.body,
});

View file

@ -0,0 +1,51 @@
import { useId, useState } from "react";
import type { RecipeVariants } from "@vanilla-extract/recipes";
import * as styles from "./select-field.css";
export interface SelectProps
extends React.DetailedHTMLProps<
React.SelectHTMLAttributes<HTMLSelectElement>,
HTMLSelectElement
> {
theme?: NonNullable<RecipeVariants<typeof styles.select>>["theme"];
label?: string;
options?: { key: string; value: string; label: string }[];
}
export function SelectField({
value,
label,
options = [{ key: "-", value: value?.toString() || "-", label: "-" }],
theme = "primary",
onChange,
}: SelectProps) {
const [isFocused, setIsFocused] = useState(false);
const id = useId();
return (
<div style={{ flex: 1 }}>
{label && (
<label htmlFor={id} className={styles.label}>
{label}
</label>
)}
<div className={styles.select({ focused: isFocused, theme })}>
<select
id={id}
value={value}
className={styles.option}
onFocus={() => setIsFocused(true)}
onBlur={() => setIsFocused(false)}
onChange={onChange}
>
{options.map((option) => (
<option key={option.key} value={option.value}>
{option.label}
</option>
))}
</select>
</div>
</div>
);
}

View file

@ -1,12 +1,26 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import ISO6391 from "iso-639-1";
import { TextField, Button, CheckboxField } from "@renderer/components"; import {
TextField,
Button,
CheckboxField,
SelectField,
} from "@renderer/components";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import * as styles from "./settings-general.css"; import * as styles from "./settings-general.css";
import type { UserPreferences } from "@types"; import type { UserPreferences } from "@types";
import { useAppSelector } from "@renderer/hooks"; import { useAppSelector } from "@renderer/hooks";
import { changeLanguage } from "i18next";
import * as languageResources from "@locales";
import { orderBy } from "lodash-es";
interface LanguageOption {
option: string;
nativeName: string;
}
export interface SettingsGeneralProps { export interface SettingsGeneralProps {
updateUserPreferences: (values: Partial<UserPreferences>) => void; updateUserPreferences: (values: Partial<UserPreferences>) => void;
} }
@ -14,6 +28,8 @@ export interface SettingsGeneralProps {
export function SettingsGeneral({ export function SettingsGeneral({
updateUserPreferences, updateUserPreferences,
}: SettingsGeneralProps) { }: SettingsGeneralProps) {
const { t } = useTranslation("settings");
const userPreferences = useAppSelector( const userPreferences = useAppSelector(
(state) => state.userPreferences.value (state) => state.userPreferences.value
); );
@ -22,28 +38,45 @@ export function SettingsGeneral({
downloadsPath: "", downloadsPath: "",
downloadNotificationsEnabled: false, downloadNotificationsEnabled: false,
repackUpdatesNotificationsEnabled: false, repackUpdatesNotificationsEnabled: false,
language: "",
}); });
const [languageOptions, setLanguageOptions] = useState<LanguageOption[]>([]);
const [defaultDownloadsPath, setDefaultDownloadsPath] = useState("");
useEffect(() => { useEffect(() => {
if (userPreferences) { async function fetchdefaultDownloadsPath() {
const { setDefaultDownloadsPath(await window.electron.getDefaultDownloadsPath());
downloadsPath,
downloadNotificationsEnabled,
repackUpdatesNotificationsEnabled,
} = userPreferences;
window.electron.getDefaultDownloadsPath().then((defaultDownloadsPath) => {
setForm((prev) => ({
...prev,
downloadsPath: downloadsPath ?? defaultDownloadsPath,
downloadNotificationsEnabled,
repackUpdatesNotificationsEnabled,
}));
});
} }
}, [userPreferences]);
const { t } = useTranslation("settings"); fetchdefaultDownloadsPath();
setLanguageOptions(
orderBy(
Object.keys(languageResources).map((language) => {
return {
nativeName: ISO6391.getNativeName(language),
option: language,
};
}),
["nativeName"],
"asc"
)
);
}, []);
useEffect(updateFormWithUserPreferences, [
userPreferences,
defaultDownloadsPath,
]);
const handleLanguageChange = (event) => {
const value = event.target.value;
handleChange({ language: value });
changeLanguage(value);
};
const handleChange = (values: Partial<typeof form>) => { const handleChange = (values: Partial<typeof form>) => {
setForm((prev) => ({ ...prev, ...values })); setForm((prev) => ({ ...prev, ...values }));
@ -59,10 +92,25 @@ export function SettingsGeneral({
if (filePaths && filePaths.length > 0) { if (filePaths && filePaths.length > 0) {
const path = filePaths[0]; const path = filePaths[0];
handleChange({ downloadsPath: path }); handleChange({ downloadsPath: path });
updateUserPreferences({ downloadsPath: path });
} }
}; };
function updateFormWithUserPreferences() {
if (userPreferences) {
const parsedLanguage = userPreferences.language.split("-")[0];
setForm((prev) => ({
...prev,
downloadsPath: userPreferences.downloadsPath ?? defaultDownloadsPath,
downloadNotificationsEnabled:
userPreferences.downloadNotificationsEnabled,
repackUpdatesNotificationsEnabled:
userPreferences.repackUpdatesNotificationsEnabled,
language: parsedLanguage,
}));
}
}
return ( return (
<> <>
<div className={styles.downloadsPathField}> <div className={styles.downloadsPathField}>
@ -82,28 +130,40 @@ export function SettingsGeneral({
</Button> </Button>
</div> </div>
<SelectField
label={t("language")}
value={form.language}
onChange={handleLanguageChange}
options={languageOptions.map((language) => ({
key: language.option,
value: language.option,
label: language.nativeName,
}))}
/>
<h3>{t("notifications")}</h3> <h3>{t("notifications")}</h3>
<>
<CheckboxField
label={t("enable_download_notifications")}
checked={form.downloadNotificationsEnabled}
onChange={() =>
handleChange({
downloadNotificationsEnabled: !form.downloadNotificationsEnabled,
})
}
/>
<CheckboxField <CheckboxField
label={t("enable_download_notifications")} label={t("enable_repack_list_notifications")}
checked={form.downloadNotificationsEnabled} checked={form.repackUpdatesNotificationsEnabled}
onChange={() => onChange={() =>
handleChange({ handleChange({
downloadNotificationsEnabled: !form.downloadNotificationsEnabled, repackUpdatesNotificationsEnabled:
}) !form.repackUpdatesNotificationsEnabled,
} })
/> }
/>
<CheckboxField </>
label={t("enable_repack_list_notifications")}
checked={form.repackUpdatesNotificationsEnabled}
onChange={() =>
handleChange({
repackUpdatesNotificationsEnabled:
!form.repackUpdatesNotificationsEnabled,
})
}
/>
</> </>
); );
} }

View file

@ -4042,6 +4042,11 @@ isexe@^2.0.0:
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
iso-639-1@3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/iso-639-1/-/iso-639-1-3.1.2.tgz#86a53dcce056e0d856b17c022eb059eb16a35426"
integrity sha512-Le7BRl3Jt9URvaiEHJCDEdvPZCfhiQoXnFgLAWNRhzFMwRFdWO7/5tLRQbiPzE394I9xd7KdRCM7S6qdOhwG5A==
iterator.prototype@^1.1.2: iterator.prototype@^1.1.2:
version "1.1.2" version "1.1.2"
resolved "https://registry.yarnpkg.com/iterator.prototype/-/iterator.prototype-1.1.2.tgz#5e29c8924f01916cb9335f1ff80619dcff22b0c0" resolved "https://registry.yarnpkg.com/iterator.prototype/-/iterator.prototype-1.1.2.tgz#5e29c8924f01916cb9335f1ff80619dcff22b0c0"
@ -5513,16 +5518,7 @@ stat-mode@^1.0.0:
resolved "https://registry.yarnpkg.com/stat-mode/-/stat-mode-1.0.0.tgz#68b55cb61ea639ff57136f36b216a291800d1465" resolved "https://registry.yarnpkg.com/stat-mode/-/stat-mode-1.0.0.tgz#68b55cb61ea639ff57136f36b216a291800d1465"
integrity sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg== integrity sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==
"string-width-cjs@npm:string-width@^4.2.0": "string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
dependencies:
emoji-regex "^8.0.0"
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"
string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3" version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@ -5593,14 +5589,7 @@ string_decoder@^1.1.1:
dependencies: dependencies:
safe-buffer "~5.2.0" safe-buffer "~5.2.0"
"strip-ansi-cjs@npm:strip-ansi@^6.0.1": "strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies:
ansi-regex "^5.0.1"
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1" version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@ -6169,16 +6158,7 @@ word-wrap@^1.2.5:
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34"
integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
dependencies:
ansi-styles "^4.0.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"
wrap-ansi@^7.0.0:
version "7.0.0" version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==