refactor: consolidate thumbnail rendering onto UIRedesignStaging base

Apply useFileThumbnail + DocumentThumbnail to FileEditorThumbnail, rebased
onto UIRedesignStaging. Also carry forward the FileEditorFileName truncation
fix from main (#6310).
This commit is contained in:
EthanHealy01
2026-05-05 17:31:04 +01:00
parent 18fd86f5bf
commit 2c7efe1e83
5 changed files with 148 additions and 10 deletions
@@ -0,0 +1,53 @@
import React from "react";
import { describe, expect, test } from "vitest";
import { render, screen } from "@testing-library/react";
import { MantineProvider } from "@mantine/core";
import FileEditorFileName from "@app/components/fileEditor/FileEditorFileName";
import type { StirlingFileStub } from "@app/types/fileContext";
import type { FileId } from "@app/types/file";
const buildFileStub = (
overrides: Partial<StirlingFileStub> = {},
): StirlingFileStub => ({
id: "file-1" as FileId,
name: "report.pdf",
type: "application/pdf",
size: 1024,
lastModified: 0,
isLeaf: true,
originalFileId: "file-1",
versionNumber: 1,
...overrides,
});
const renderName = (file: StirlingFileStub) =>
render(
<MantineProvider>
<FileEditorFileName file={file} />
</MantineProvider>,
);
describe("FileEditorFileName (core / web)", () => {
test.each([
{ name: "not-saved", file: buildFileStub() },
{
name: "dirty",
file: buildFileStub({ localFilePath: "/tmp/report.pdf", isDirty: true }),
},
{
name: "saved",
file: buildFileStub({ localFilePath: "/tmp/report.pdf", isDirty: false }),
},
])("does not render a save indicator ($name)", ({ file }) => {
renderName(file);
expect(screen.queryByLabelText("fileNotSavedToDisk")).toBeNull();
expect(screen.queryByLabelText("unsavedChanges")).toBeNull();
expect(screen.queryByLabelText("fileSavedToDisk")).toBeNull();
});
test("renders the filename", () => {
renderName(buildFileStub({ name: "invoice.pdf" }));
expect(screen.getByText("invoice.pdf")).toBeInTheDocument();
});
});
@@ -1,13 +1,18 @@
import React from "react";
import { StirlingFileStub } from "@app/types/fileContext";
import { PrivateContent } from "@app/components/shared/PrivateContent";
import { truncateCenter } from "@app/utils/textUtils";
interface FileEditorFileNameProps {
file: StirlingFileStub;
maxLength?: number;
}
const FileEditorFileName = ({ file }: FileEditorFileNameProps) => (
<PrivateContent>{file.name}</PrivateContent>
const FileEditorFileName = ({
file,
maxLength = 40,
}: FileEditorFileNameProps) => (
<PrivateContent>{truncateCenter(file.name, maxLength)}</PrivateContent>
);
export default FileEditorFileName;
@@ -27,7 +27,6 @@ import {
} from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
import { StirlingFileStub } from "@app/types/fileContext";
import { zipFileService } from "@app/services/zipFileService";
import { useFileThumbnail } from "@app/hooks/useFileThumbnail";
import styles from "@app/components/fileEditor/FileEditorThumbnail.module.css";
import { useFileContext } from "@app/contexts/FileContext";
@@ -43,6 +42,7 @@ import UploadToServerModal from "@app/components/shared/UploadToServerModal";
import ShareFileModal from "@app/components/shared/ShareFileModal";
import { useAppConfig } from "@app/contexts/AppConfigContext";
import { truncateCenter } from "@app/utils/textUtils";
import { useFileThumbnail } from "@app/hooks/useFileThumbnail";
import DocumentThumbnail from "@app/components/shared/filePreview/DocumentThumbnail";
interface FileEditorThumbnailProps {
@@ -86,11 +86,6 @@ const FileEditorThumbnail = ({
} = useFileContext();
const { state, selectors } = useFileState();
const isMobile = useIsMobile();
const {
isEncrypted,
thumbnail: displayThumbnail,
isGenerating: isThumbGenerating,
} = useFileThumbnail(file);
const actualFile = useMemo(
() => activeFiles.find((f) => f.fileId === file.id),
@@ -102,6 +97,11 @@ const FileEditorThumbnail = ({
const hasError = state.ui.errorFileIds.includes(file.id);
const pageCount = file.processedFile?.totalPages || 0;
const {
isEncrypted,
thumbnail: displayThumbnail,
isGenerating: isThumbGenerating,
} = useFileThumbnail(file);
// Aspect ratio from page dimensions, falling back to letter size
const firstPage = file.processedFile?.pages?.[0];
@@ -0,0 +1,75 @@
import React from "react";
import { describe, expect, test } from "vitest";
import { render, screen } from "@testing-library/react";
import { MantineProvider } from "@mantine/core";
import FileEditorFileName from "@app/components/fileEditor/FileEditorFileName";
import type { StirlingFileStub } from "@app/types/fileContext";
import type { FileId } from "@app/types/file";
const buildFileStub = (
overrides: Partial<StirlingFileStub> = {},
): StirlingFileStub => ({
id: "file-1" as FileId,
name: "report.pdf",
type: "application/pdf",
size: 1024,
lastModified: 0,
isLeaf: true,
originalFileId: "file-1",
versionNumber: 1,
...overrides,
});
const renderName = (file: StirlingFileStub) =>
render(
<MantineProvider>
<FileEditorFileName file={file} />
</MantineProvider>,
);
describe("FileEditorFileName (desktop)", () => {
test("renders red 'not saved' indicator when file has no local path", () => {
renderName(buildFileStub());
const indicator = screen.getByLabelText("fileNotSavedToDisk");
expect(indicator).toBeInTheDocument();
expect(indicator).toHaveStyle({
backgroundColor: "var(--mantine-color-red-6)",
});
expect(screen.queryByLabelText("unsavedChanges")).toBeNull();
expect(screen.queryByLabelText("fileSavedToDisk")).toBeNull();
});
test("renders yellow 'unsaved changes' indicator when file is dirty", () => {
renderName(
buildFileStub({ localFilePath: "/tmp/report.pdf", isDirty: true }),
);
const indicator = screen.getByLabelText("unsavedChanges");
expect(indicator).toBeInTheDocument();
expect(indicator).toHaveStyle({
backgroundColor: "var(--mantine-color-yellow-6)",
});
expect(screen.queryByLabelText("fileNotSavedToDisk")).toBeNull();
expect(screen.queryByLabelText("fileSavedToDisk")).toBeNull();
});
test("renders green 'saved' indicator when file is persisted and clean", () => {
renderName(
buildFileStub({ localFilePath: "/tmp/report.pdf", isDirty: false }),
);
const indicator = screen.getByLabelText("fileSavedToDisk");
expect(indicator).toBeInTheDocument();
expect(indicator).toHaveStyle({
backgroundColor: "var(--mantine-color-green-6)",
});
expect(screen.queryByLabelText("fileNotSavedToDisk")).toBeNull();
expect(screen.queryByLabelText("unsavedChanges")).toBeNull();
});
test("renders the filename alongside the indicator", () => {
renderName(buildFileStub({ name: "invoice.pdf" }));
expect(screen.getByText("invoice.pdf")).toBeInTheDocument();
});
});
@@ -3,17 +3,22 @@ import { Tooltip } from "@mantine/core";
import { useTranslation } from "react-i18next";
import { StirlingFileStub } from "@app/types/fileContext";
import { PrivateContent } from "@app/components/shared/PrivateContent";
import { truncateCenter } from "@app/utils/textUtils";
interface FileEditorFileNameProps {
file: StirlingFileStub;
maxLength?: number;
}
const FileEditorFileName = ({ file }: FileEditorFileNameProps) => {
const FileEditorFileName = ({
file,
maxLength = 40,
}: FileEditorFileNameProps) => {
const { t } = useTranslation();
return (
<>
<PrivateContent>{file.name}</PrivateContent>
<PrivateContent>{truncateCenter(file.name, maxLength)}</PrivateContent>
{!file.localFilePath && (
<Tooltip label={t("fileNotSavedToDisk", "Not saved to disk")}>
<span