mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-10-28 06:05:24 +00:00
fix(file-manager): render transfer toasts without plugin hooks (#1546)
This commit is contained in:
1 parent
4785bf5dfa
commit
2c4de5f705
9 files changed
+82
-12
No files matched your search
@@ -1416,10 +1416,13 @@ function FileManagerContent({
|
|||||||
const { downloadSSHFileStream } =
|
const { downloadSSHFileStream } =
|
||||||
await import("./api/ssh-file-operations-api");
|
await import("./api/ssh-file-operations-api");
|
||||||
|
|
||||||
toast.loading(<DownloadProgressToast fileName={file.name} loaded={0} />, {
|
toast.loading(
|
||||||
id: toastId,
|
<DownloadProgressToast t={t} fileName={file.name} loaded={0} />,
|
||||||
duration: Infinity,
|
{
|
||||||
});
|
id: toastId,
|
||||||
|
duration: Infinity,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
await downloadSSHFileStream(
|
await downloadSSHFileStream(
|
||||||
sshSessionId,
|
sshSessionId,
|
||||||
@@ -1438,6 +1441,7 @@ function FileManagerContent({
|
|||||||
|
|
||||||
toast.loading(
|
toast.loading(
|
||||||
<DownloadProgressToast
|
<DownloadProgressToast
|
||||||
|
t={t}
|
||||||
fileName={file.name}
|
fileName={file.name}
|
||||||
loaded={loaded}
|
loaded={loaded}
|
||||||
total={total}
|
total={total}
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ export function DiffViewer({
|
|||||||
|
|
||||||
const handleDownloadFile = async (file: FileItem) => {
|
const handleDownloadFile = async (file: FileItem) => {
|
||||||
const toastId = toast.loading(
|
const toastId = toast.loading(
|
||||||
<DownloadProgressToast fileName={file.name} loaded={0} />,
|
<DownloadProgressToast t={t} fileName={file.name} loaded={0} />,
|
||||||
{ duration: Infinity },
|
{ duration: Infinity },
|
||||||
);
|
);
|
||||||
try {
|
try {
|
||||||
@@ -145,6 +145,7 @@ export function DiffViewer({
|
|||||||
({ loaded, total }) => {
|
({ loaded, total }) => {
|
||||||
toast.loading(
|
toast.loading(
|
||||||
<DownloadProgressToast
|
<DownloadProgressToast
|
||||||
|
t={t}
|
||||||
fileName={file.name}
|
fileName={file.name}
|
||||||
loaded={loaded}
|
loaded={loaded}
|
||||||
total={total}
|
total={total}
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import { formatTransferMbPerSec } from "../api/transfer-api";
|
import { formatTransferMbPerSec } from "../api/transfer-api";
|
||||||
import { useTranslation } from "@termix/plugin-sdk/frontend";
|
import type { TranslateFn } from "@termix/plugin-sdk/frontend";
|
||||||
import { ArrowDownToLine } from "lucide-react";
|
import { ArrowDownToLine } from "lucide-react";
|
||||||
import { TransferProgressBar } from "./TransferProgressBar";
|
import { TransferProgressBar } from "./TransferProgressBar";
|
||||||
|
|
||||||
interface DownloadProgressToastProps {
|
interface DownloadProgressToastProps {
|
||||||
|
t: TranslateFn;
|
||||||
fileName: string;
|
fileName: string;
|
||||||
loaded: number;
|
loaded: number;
|
||||||
total?: number;
|
total?: number;
|
||||||
@@ -25,12 +26,12 @@ function formatBytes(bytes: number): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function DownloadProgressToast({
|
export function DownloadProgressToast({
|
||||||
|
t,
|
||||||
fileName,
|
fileName,
|
||||||
loaded,
|
loaded,
|
||||||
total,
|
total,
|
||||||
mbPerSec,
|
mbPerSec,
|
||||||
}: DownloadProgressToastProps) {
|
}: DownloadProgressToastProps) {
|
||||||
const { t } = useTranslation();
|
|
||||||
const percent =
|
const percent =
|
||||||
total !== undefined && total > 0
|
total !== undefined && total > 0
|
||||||
? Math.min(100, Math.round((loaded / total) * 100))
|
? Math.min(100, Math.round((loaded / total) * 100))
|
||||||
|
|||||||
@@ -483,7 +483,7 @@ export function FileWindow({
|
|||||||
|
|
||||||
const handleDownload = async () => {
|
const handleDownload = async () => {
|
||||||
const toastId = toast.loading(
|
const toastId = toast.loading(
|
||||||
<DownloadProgressToast fileName={file.name} loaded={0} />,
|
<DownloadProgressToast t={t} fileName={file.name} loaded={0} />,
|
||||||
{ duration: Infinity },
|
{ duration: Infinity },
|
||||||
);
|
);
|
||||||
try {
|
try {
|
||||||
@@ -495,6 +495,7 @@ export function FileWindow({
|
|||||||
({ loaded, total }) => {
|
({ loaded, total }) => {
|
||||||
toast.loading(
|
toast.loading(
|
||||||
<DownloadProgressToast
|
<DownloadProgressToast
|
||||||
|
t={t}
|
||||||
fileName={file.name}
|
fileName={file.name}
|
||||||
loaded={loaded}
|
loaded={loaded}
|
||||||
total={total}
|
total={total}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Button } from "@termix/plugin-sdk/ui";
|
import { Button } from "@termix/plugin-sdk/ui";
|
||||||
import { useTranslation } from "@termix/plugin-sdk/frontend";
|
import type { TranslateFn } from "@termix/plugin-sdk/frontend";
|
||||||
import { formatFileSize } from "../file-manager-utils.ts";
|
import { formatFileSize } from "../file-manager-utils.ts";
|
||||||
|
|
||||||
export interface LocalTransferBatchStatus {
|
export interface LocalTransferBatchStatus {
|
||||||
@@ -16,15 +16,16 @@ export interface LocalTransferBatchStatus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface LocalTransferProgressToastProps {
|
interface LocalTransferProgressToastProps {
|
||||||
|
t: TranslateFn;
|
||||||
status: LocalTransferBatchStatus;
|
status: LocalTransferBatchStatus;
|
||||||
onCancel?: () => void;
|
onCancel?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function LocalTransferProgressToast({
|
export function LocalTransferProgressToast({
|
||||||
|
t,
|
||||||
status,
|
status,
|
||||||
onCancel,
|
onCancel,
|
||||||
}: LocalTransferProgressToastProps) {
|
}: LocalTransferProgressToastProps) {
|
||||||
const { t } = useTranslation();
|
|
||||||
const percent =
|
const percent =
|
||||||
status.totalBytes > 0
|
status.totalBytes > 0
|
||||||
? Math.min(100, Math.round((status.bytesDone / status.totalBytes) * 100))
|
? Math.min(100, Math.round((status.bytesDone / status.totalBytes) * 100))
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import {
|
|||||||
getTransferProgressPercent,
|
getTransferProgressPercent,
|
||||||
type TransferProgressResponse,
|
type TransferProgressResponse,
|
||||||
} from "../api/transfer-api";
|
} from "../api/transfer-api";
|
||||||
import { useTranslation } from "@termix/plugin-sdk/frontend";
|
import type { TranslateFn } from "@termix/plugin-sdk/frontend";
|
||||||
import {
|
import {
|
||||||
Archive,
|
Archive,
|
||||||
ArchiveRestore,
|
ArchiveRestore,
|
||||||
@@ -16,6 +16,7 @@ import {
|
|||||||
import { TransferProgressBar } from "./TransferProgressBar";
|
import { TransferProgressBar } from "./TransferProgressBar";
|
||||||
|
|
||||||
interface TransferProgressToastProps {
|
interface TransferProgressToastProps {
|
||||||
|
t: TranslateFn;
|
||||||
status: TransferProgressResponse;
|
status: TransferProgressResponse;
|
||||||
liveMbPerSec?: number;
|
liveMbPerSec?: number;
|
||||||
stalled?: boolean;
|
stalled?: boolean;
|
||||||
@@ -25,6 +26,7 @@ interface TransferProgressToastProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function TransferProgressToast({
|
export function TransferProgressToast({
|
||||||
|
t,
|
||||||
status,
|
status,
|
||||||
liveMbPerSec,
|
liveMbPerSec,
|
||||||
stalled = false,
|
stalled = false,
|
||||||
@@ -32,7 +34,6 @@ export function TransferProgressToast({
|
|||||||
onCancel,
|
onCancel,
|
||||||
cancelling = false,
|
cancelling = false,
|
||||||
}: TransferProgressToastProps) {
|
}: TransferProgressToastProps) {
|
||||||
const { t } = useTranslation();
|
|
||||||
const percent = getTransferProgressPercent(status);
|
const percent = getTransferProgressPercent(status);
|
||||||
|
|
||||||
let title = t("transfer.progressTransferring");
|
let title = t("transfer.progressTransferring");
|
||||||
|
|||||||
@@ -193,6 +193,7 @@ export function useLocalTransfers({
|
|||||||
const render = () => {
|
const render = () => {
|
||||||
toast.loading(
|
toast.loading(
|
||||||
createElement(LocalTransferProgressToast, {
|
createElement(LocalTransferProgressToast, {
|
||||||
|
t,
|
||||||
status: { ...status, cancelling },
|
status: { ...status, cancelling },
|
||||||
onCancel: () => {
|
onCancel: () => {
|
||||||
cancelled = true;
|
cancelled = true;
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ function formatFileSize(bytes?: number): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function renderTransferProgressToast(
|
function renderTransferProgressToast(
|
||||||
|
t: TFunction,
|
||||||
toastId: string | number,
|
toastId: string | number,
|
||||||
status: TransferProgressResponse,
|
status: TransferProgressResponse,
|
||||||
liveMbPerSec?: number,
|
liveMbPerSec?: number,
|
||||||
@@ -47,6 +48,7 @@ function renderTransferProgressToast(
|
|||||||
): void {
|
): void {
|
||||||
toast.loading(
|
toast.loading(
|
||||||
<TransferProgressToast
|
<TransferProgressToast
|
||||||
|
t={t}
|
||||||
status={status}
|
status={status}
|
||||||
liveMbPerSec={liveMbPerSec}
|
liveMbPerSec={liveMbPerSec}
|
||||||
stalled={stalled}
|
stalled={stalled}
|
||||||
@@ -265,6 +267,7 @@ export function beginTransferProgressMonitoring(
|
|||||||
|
|
||||||
const progressToast = toast.loading(
|
const progressToast = toast.loading(
|
||||||
<TransferProgressToast
|
<TransferProgressToast
|
||||||
|
t={t}
|
||||||
status={initialStatus}
|
status={initialStatus}
|
||||||
formatSize={formatFileSize}
|
formatSize={formatFileSize}
|
||||||
/>,
|
/>,
|
||||||
@@ -279,6 +282,7 @@ export function beginTransferProgressMonitoring(
|
|||||||
if (cancelling) return;
|
if (cancelling) return;
|
||||||
cancelling = true;
|
cancelling = true;
|
||||||
renderTransferProgressToast(
|
renderTransferProgressToast(
|
||||||
|
t,
|
||||||
progressToast,
|
progressToast,
|
||||||
{ ...initialStatus, transferId },
|
{ ...initialStatus, transferId },
|
||||||
undefined,
|
undefined,
|
||||||
@@ -294,6 +298,7 @@ export function beginTransferProgressMonitoring(
|
|||||||
options.onProgress?.(status);
|
options.onProgress?.(status);
|
||||||
const { rate, stalled } = progressTracker.update(status);
|
const { rate, stalled } = progressTracker.update(status);
|
||||||
renderTransferProgressToast(
|
renderTransferProgressToast(
|
||||||
|
t,
|
||||||
progressToast,
|
progressToast,
|
||||||
status,
|
status,
|
||||||
rate,
|
rate,
|
||||||
@@ -333,6 +338,7 @@ export function beginTransferProgressMonitoring(
|
|||||||
});
|
});
|
||||||
|
|
||||||
renderTransferProgressToast(
|
renderTransferProgressToast(
|
||||||
|
t,
|
||||||
progressToast,
|
progressToast,
|
||||||
initialStatus,
|
initialStatus,
|
||||||
undefined,
|
undefined,
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
import { cleanup, fireEvent, render, screen } from "@testing-library/react";
|
||||||
|
import { afterEach, expect, it, vi } from "vitest";
|
||||||
|
vi.mock("@termix/plugin-sdk/frontend", () => ({
|
||||||
|
useTranslation: () => {
|
||||||
|
throw Error("No plugin scope in the global toaster");
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
import { DownloadProgressToast } from "../../src/frontend/components/DownloadProgressToast";
|
||||||
|
import { TransferProgressToast } from "../../src/frontend/components/TransferProgressToast";
|
||||||
|
import { LocalTransferProgressToast } from "../../src/frontend/components/LocalTransferProgressToast";
|
||||||
|
afterEach(cleanup);
|
||||||
|
const t = (key: string) => key;
|
||||||
|
it("renders download progress outside plugin scope", () => {
|
||||||
|
render(
|
||||||
|
<DownloadProgressToast t={t} fileName="test.txt" loaded={50} total={100} />,
|
||||||
|
);
|
||||||
|
expect(screen.getByRole("progressbar").getAttribute("aria-valuenow")).toBe(
|
||||||
|
"50",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it("renders host transfer progress outside plugin scope", () => {
|
||||||
|
render(
|
||||||
|
<TransferProgressToast
|
||||||
|
t={t}
|
||||||
|
status={{
|
||||||
|
transferId: "test",
|
||||||
|
status: "running",
|
||||||
|
phase: "transferring",
|
||||||
|
bytesTransferred: 50,
|
||||||
|
totalBytes: 100,
|
||||||
|
}}
|
||||||
|
formatSize={String}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
expect(screen.getByRole("progressbar")).toBeTruthy();
|
||||||
|
});
|
||||||
|
it("preserves cancellation on local transfers outside plugin scope", () => {
|
||||||
|
const cancel = vi.fn();
|
||||||
|
render(
|
||||||
|
<LocalTransferProgressToast
|
||||||
|
t={t}
|
||||||
|
status={{
|
||||||
|
direction: "upload",
|
||||||
|
totalFiles: 2,
|
||||||
|
completedFiles: 1,
|
||||||
|
bytesDone: 50,
|
||||||
|
totalBytes: 100,
|
||||||
|
}}
|
||||||
|
onCancel={cancel}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
fireEvent.click(screen.getByRole("button"));
|
||||||
|
expect(cancel).toHaveBeenCalledOnce();
|
||||||
|
});
|
||||||
Reference in new issue
Block a user