mirror of
https://github.com/hydralauncher/hydra.git
synced 2026-01-10 21:36:17 +00:00
feat: adding motion
This commit is contained in:
@@ -57,6 +57,7 @@
|
||||
"electron-log": "^5.2.4",
|
||||
"electron-updater": "^6.6.2",
|
||||
"file-type": "^20.5.0",
|
||||
"framer-motion": "^12.15.0",
|
||||
"i18next": "^23.11.2",
|
||||
"i18next-browser-languagedetector": "^7.2.1",
|
||||
"jsdom": "^24.0.0",
|
||||
|
||||
@@ -217,7 +217,9 @@
|
||||
"freeze_backup": "Pin it so it's not overwritten by automatic backups",
|
||||
"unfreeze_backup": "Unpin it",
|
||||
"backup_frozen": "Backup pinned",
|
||||
"backup_unfrozen": "Backup unpinned"
|
||||
"backup_unfrozen": "Backup unpinned",
|
||||
"backup_freeze_failed": "Failed to freeze backup",
|
||||
"backup_freeze_failed_description": "You must leave at least one free slot for automatic backups"
|
||||
},
|
||||
"activation": {
|
||||
"title": "Activate Hydra",
|
||||
|
||||
@@ -204,7 +204,9 @@
|
||||
"freeze_backup": "Fixar para não ser apagado por backups automáticos",
|
||||
"unfreeze_backup": "Remover dos fixados",
|
||||
"backup_frozen": "Backup fixado",
|
||||
"backup_unfrozen": "Backup removido dos fixados"
|
||||
"backup_unfrozen": "Backup removido dos fixados",
|
||||
"backup_freeze_failed": "Falha ao fixar backup",
|
||||
"backup_freeze_failed_description": "Você deve deixar pelo menos um espaço livre para backups automáticos"
|
||||
},
|
||||
"activation": {
|
||||
"title": "Ativação",
|
||||
|
||||
@@ -135,6 +135,7 @@ export function CloudSyncContextProvider({
|
||||
getGameArtifacts();
|
||||
} catch (err) {
|
||||
logger.error("Failed to toggle artifact freeze", objectId, shop, err);
|
||||
throw err;
|
||||
} finally {
|
||||
setFreezingArtifact(false);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Button, Modal, ModalProps } from "@renderer/components";
|
||||
import { useContext, useEffect, useMemo, useState } from "react";
|
||||
import { cloudSyncContext, gameDetailsContext } from "@renderer/context";
|
||||
|
||||
import "./cloud-sync-modal.scss";
|
||||
import { formatBytes } from "@shared";
|
||||
import {
|
||||
@@ -22,6 +21,8 @@ import { AxiosProgressEvent } from "axios";
|
||||
import { formatDownloadProgress } from "@renderer/helpers";
|
||||
import { CloudSyncRenameArtifactModal } from "../cloud-sync-rename-artifact-modal/cloud-sync-rename-artifact-modal";
|
||||
import { GameArtifact } from "@types";
|
||||
import { motion, AnimatePresence } from "framer-motion";
|
||||
import { orderBy } from "lodash-es";
|
||||
|
||||
export interface CloudSyncModalProps
|
||||
extends Omit<ModalProps, "children" | "title"> {}
|
||||
@@ -35,7 +36,6 @@ export function CloudSyncModal({ visible, onClose }: CloudSyncModalProps) {
|
||||
);
|
||||
|
||||
const { t } = useTranslation("game_details");
|
||||
|
||||
const { formatDate, formatDateTime } = useDate();
|
||||
|
||||
const {
|
||||
@@ -60,10 +60,8 @@ export function CloudSyncModal({ visible, onClose }: CloudSyncModalProps) {
|
||||
|
||||
const handleDeleteArtifactClick = async (gameArtifactId: string) => {
|
||||
setDeletingArtifact(true);
|
||||
|
||||
try {
|
||||
await deleteGameArtifact(gameArtifactId);
|
||||
|
||||
showSuccessToast(t("backup_deleted"));
|
||||
} catch (err) {
|
||||
showErrorToast("backup_deletion_failed");
|
||||
@@ -81,7 +79,6 @@ export function CloudSyncModal({ visible, onClose }: CloudSyncModalProps) {
|
||||
setBackupDownloadProgress(progressEvent);
|
||||
}
|
||||
);
|
||||
|
||||
return () => {
|
||||
removeBackupDownloadProgressListener();
|
||||
};
|
||||
@@ -96,12 +93,14 @@ export function CloudSyncModal({ visible, onClose }: CloudSyncModalProps) {
|
||||
artifactId: string,
|
||||
isFrozen: boolean
|
||||
) => {
|
||||
await toggleArtifactFreeze(artifactId, isFrozen);
|
||||
|
||||
if (isFrozen) {
|
||||
showSuccessToast(t("backup_frozen"));
|
||||
} else {
|
||||
showSuccessToast(t("backup_unfrozen"));
|
||||
try {
|
||||
await toggleArtifactFreeze(artifactId, isFrozen);
|
||||
showSuccessToast(isFrozen ? t("backup_frozen") : t("backup_unfrozen"));
|
||||
} catch (err) {
|
||||
showErrorToast(
|
||||
t("backup_freeze_failed"),
|
||||
t("backup_freeze_failed_description")
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -123,7 +122,6 @@ export function CloudSyncModal({ visible, onClose }: CloudSyncModalProps) {
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
if (restoringBackup) {
|
||||
return (
|
||||
<span className="cloud-sync-modal__backup-state-label">
|
||||
@@ -136,7 +134,6 @@ export function CloudSyncModal({ visible, onClose }: CloudSyncModalProps) {
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
if (loadingPreview) {
|
||||
return (
|
||||
<span className="cloud-sync-modal__backup-state-label">
|
||||
@@ -145,19 +142,15 @@ export function CloudSyncModal({ visible, onClose }: CloudSyncModalProps) {
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
if (artifacts.length >= backupsPerGameLimit) {
|
||||
return t("max_number_of_artifacts_reached");
|
||||
}
|
||||
|
||||
if (!backupPreview) {
|
||||
return t("no_backup_preview");
|
||||
}
|
||||
|
||||
if (artifacts.length === 0) {
|
||||
return t("no_backups");
|
||||
}
|
||||
|
||||
return "";
|
||||
}, [
|
||||
uploadingBackup,
|
||||
@@ -194,7 +187,6 @@ export function CloudSyncModal({ visible, onClose }: CloudSyncModalProps) {
|
||||
<div className="cloud-sync-modal__title-container">
|
||||
<h2>{gameTitle}</h2>
|
||||
<p>{backupStateLabel}</p>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className="cloud-sync-modal__manage-files-button"
|
||||
@@ -235,83 +227,99 @@ export function CloudSyncModal({ visible, onClose }: CloudSyncModalProps) {
|
||||
|
||||
{artifacts.length > 0 ? (
|
||||
<ul className="cloud-sync-modal__artifacts">
|
||||
{artifacts.map((artifact) => (
|
||||
<li key={artifact.id} className="cloud-sync-modal__artifact">
|
||||
<div className="cloud-sync-modal__artifact-info">
|
||||
<div className="cloud-sync-modal__artifact-header">
|
||||
<button
|
||||
type="button"
|
||||
className="cloud-sync-modal__artifact-label"
|
||||
onClick={() => setArtifactToRename(artifact)}
|
||||
>
|
||||
{artifact.label ??
|
||||
t("backup_from", {
|
||||
date: formatDate(artifact.createdAt),
|
||||
})}
|
||||
|
||||
<PencilIcon />
|
||||
</button>
|
||||
<small>{formatBytes(artifact.artifactLengthInBytes)}</small>
|
||||
</div>
|
||||
|
||||
<span className="cloud-sync-modal__artifact-meta">
|
||||
<DeviceDesktopIcon size={14} />
|
||||
{artifact.hostname}
|
||||
</span>
|
||||
|
||||
<span className="cloud-sync-modal__artifact-meta">
|
||||
<InfoIcon size={14} />
|
||||
{artifact.downloadOptionTitle ??
|
||||
t("no_download_option_info")}
|
||||
</span>
|
||||
|
||||
<span className="cloud-sync-modal__artifact-meta">
|
||||
<ClockIcon size={14} />
|
||||
{formatDateTime(artifact.createdAt)}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="cloud-sync-modal__artifact-actions">
|
||||
<Button
|
||||
type="button"
|
||||
tooltip={
|
||||
artifact.isFrozen
|
||||
? t("unfreeze_backup")
|
||||
: t("freeze_backup")
|
||||
}
|
||||
theme={artifact.isFrozen ? "primary" : "outline"}
|
||||
onClick={() =>
|
||||
handleFreezeArtifactClick(artifact.id, !artifact.isFrozen)
|
||||
}
|
||||
disabled={disableActions}
|
||||
<AnimatePresence>
|
||||
{orderBy(artifacts, [(a) => !a.isFrozen], ["asc"]).map(
|
||||
(artifact) => (
|
||||
<motion.li
|
||||
key={artifact.id}
|
||||
className="cloud-sync-modal__artifact"
|
||||
layout
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, y: -10 }}
|
||||
transition={{ duration: 0.2 }}
|
||||
>
|
||||
{artifact.isFrozen ? <PinSlashIcon /> : <PinIcon />}
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
onClick={() => handleBackupInstallClick(artifact.id)}
|
||||
disabled={disableActions}
|
||||
theme="outline"
|
||||
>
|
||||
{restoringBackup ? (
|
||||
<SyncIcon className="cloud-sync-modal__sync-icon" />
|
||||
) : (
|
||||
<HistoryIcon />
|
||||
)}
|
||||
{t("install_backup")}
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
onClick={() => handleDeleteArtifactClick(artifact.id)}
|
||||
disabled={disableActions || artifact.isFrozen}
|
||||
theme="outline"
|
||||
tooltip={t("delete_backup")}
|
||||
>
|
||||
<TrashIcon />
|
||||
</Button>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
<div className="cloud-sync-modal__artifact-info">
|
||||
<div className="cloud-sync-modal__artifact-header">
|
||||
<button
|
||||
type="button"
|
||||
className="cloud-sync-modal__artifact-label"
|
||||
onClick={() => setArtifactToRename(artifact)}
|
||||
>
|
||||
{artifact.label ??
|
||||
t("backup_from", {
|
||||
date: formatDate(artifact.createdAt),
|
||||
})}
|
||||
<PencilIcon />
|
||||
</button>
|
||||
<small>
|
||||
{formatBytes(artifact.artifactLengthInBytes)}
|
||||
</small>
|
||||
</div>
|
||||
|
||||
<span className="cloud-sync-modal__artifact-meta">
|
||||
<DeviceDesktopIcon size={14} />
|
||||
{artifact.hostname}
|
||||
</span>
|
||||
|
||||
<span className="cloud-sync-modal__artifact-meta">
|
||||
<InfoIcon size={14} />
|
||||
{artifact.downloadOptionTitle ??
|
||||
t("no_download_option_info")}
|
||||
</span>
|
||||
|
||||
<span className="cloud-sync-modal__artifact-meta">
|
||||
<ClockIcon size={14} />
|
||||
{formatDateTime(artifact.createdAt)}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="cloud-sync-modal__artifact-actions">
|
||||
<Button
|
||||
type="button"
|
||||
tooltip={
|
||||
artifact.isFrozen
|
||||
? t("unfreeze_backup")
|
||||
: t("freeze_backup")
|
||||
}
|
||||
theme={artifact.isFrozen ? "primary" : "outline"}
|
||||
onClick={() =>
|
||||
handleFreezeArtifactClick(
|
||||
artifact.id,
|
||||
!artifact.isFrozen
|
||||
)
|
||||
}
|
||||
disabled={disableActions}
|
||||
>
|
||||
{artifact.isFrozen ? <PinSlashIcon /> : <PinIcon />}
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
onClick={() => handleBackupInstallClick(artifact.id)}
|
||||
disabled={disableActions}
|
||||
theme="outline"
|
||||
>
|
||||
{restoringBackup ? (
|
||||
<SyncIcon className="cloud-sync-modal__sync-icon" />
|
||||
) : (
|
||||
<HistoryIcon />
|
||||
)}
|
||||
{t("install_backup")}
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
onClick={() => handleDeleteArtifactClick(artifact.id)}
|
||||
disabled={disableActions || artifact.isFrozen}
|
||||
theme="outline"
|
||||
tooltip={t("delete_backup")}
|
||||
>
|
||||
<TrashIcon />
|
||||
</Button>
|
||||
</div>
|
||||
</motion.li>
|
||||
)
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</ul>
|
||||
) : (
|
||||
<p>{t("no_backups_created")}</p>
|
||||
|
||||
23
yarn.lock
23
yarn.lock
@@ -5646,6 +5646,15 @@ formdata-polyfill@^4.0.10:
|
||||
dependencies:
|
||||
fetch-blob "^3.1.2"
|
||||
|
||||
framer-motion@^12.15.0:
|
||||
version "12.15.0"
|
||||
resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-12.15.0.tgz#6892283fc7967b071f537d6d160ab49e3d5e73ae"
|
||||
integrity sha512-XKg/LnKExdLGugZrDILV7jZjI599785lDIJZLxMiiIFidCsy0a4R2ZEf+Izm67zyOuJgQYTHOmodi7igQsw3vg==
|
||||
dependencies:
|
||||
motion-dom "^12.15.0"
|
||||
motion-utils "^12.12.1"
|
||||
tslib "^2.4.0"
|
||||
|
||||
fs-extra@^10.0.0, fs-extra@^10.1.0:
|
||||
version "10.1.0"
|
||||
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf"
|
||||
@@ -7304,6 +7313,18 @@ module-error@^1.0.1:
|
||||
resolved "https://registry.yarnpkg.com/module-error/-/module-error-1.0.2.tgz#8d1a48897ca883f47a45816d4fb3e3c6ba404d86"
|
||||
integrity sha512-0yuvsqSCv8LbaOKhnsQ/T5JhyFlCYLPXK3U2sgV10zoKQwzs/MyfuQUOZQ1V/6OCOJsK/TRgNVrPuPDqtdMFtA==
|
||||
|
||||
motion-dom@^12.15.0:
|
||||
version "12.15.0"
|
||||
resolved "https://registry.yarnpkg.com/motion-dom/-/motion-dom-12.15.0.tgz#eca7c9d8c28976b8c920f175f92d5288f5a17785"
|
||||
integrity sha512-D2ldJgor+2vdcrDtKJw48k3OddXiZN1dDLLWrS8kiHzQdYVruh0IoTwbJBslrnTXIPgFED7PBN2Zbwl7rNqnhA==
|
||||
dependencies:
|
||||
motion-utils "^12.12.1"
|
||||
|
||||
motion-utils@^12.12.1:
|
||||
version "12.12.1"
|
||||
resolved "https://registry.yarnpkg.com/motion-utils/-/motion-utils-12.12.1.tgz#63e28751325cb9d1cd684f3c273a570022b0010e"
|
||||
integrity sha512-f9qiqUHm7hWSLlNW8gS9pisnsN7CRFRD58vNjptKdsqFLpkVnX00TNeD6Q0d27V9KzT7ySFyK1TZ/DShfVOv6w==
|
||||
|
||||
ms@^2.0.0, ms@^2.1.1, ms@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
|
||||
@@ -9041,7 +9062,7 @@ ts-node@^10.9.2:
|
||||
v8-compile-cache-lib "^3.0.1"
|
||||
yn "3.1.1"
|
||||
|
||||
tslib@^2.0.0, tslib@^2.1.0:
|
||||
tslib@^2.0.0, tslib@^2.1.0, tslib@^2.4.0:
|
||||
version "2.8.1"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f"
|
||||
integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==
|
||||
|
||||
Reference in New Issue
Block a user