复用画布尺寸状态生成项目封面

由 ResizeObserver 维护的 canvasSize 传入项目持久化 hook
移除持久化层对 canvasViewportRef 和 clientWidth/clientHeight 的直接读取
更新持久化测试夹具并保持封面尺寸断言
This commit is contained in:
2026-07-24 16:08:49 +08:00
parent 23e2d099ff
commit 08cda72ea0
3 changed files with 9 additions and 23 deletions
@@ -1116,7 +1116,6 @@ export function ImageCanvasEditorView({
() => ({
layersRef,
viewportRef,
canvasViewportRef,
canvasGenerationDialogsRef,
canvasBackgroundColorRef,
}),
@@ -1156,6 +1155,7 @@ export function ImageCanvasEditorView({
layers,
canvasGenerationDialogs,
viewport,
canvasSize,
canvasBackgroundColor,
isViewportInteracting,
canAccessProtectedData: authUi ? authUi.canAccessProtectedData : true,
@@ -113,12 +113,12 @@ function ProjectPersistenceHarness({
y: 0,
scale: 1,
});
const canvasSize = { width: 900, height: 640 };
const [isViewportInteracting, setIsViewportInteracting] = useState(false);
const [projectTitle, setProjectTitle] = useState('');
const [projectRenameValue, setProjectRenameValue] = useState('');
const layersRef = useRef(layers);
const viewportRef = useRef(viewport);
const canvasViewportRef = useRef<HTMLDivElement | null>(null);
const canvasGenerationDialogsRef = useRef(generationDialogs);
const canvasBackgroundColorRef = useRef(canvasBackgroundColor);
const selectedLayerRef = useRef<string | null>(null);
@@ -147,7 +147,6 @@ function ProjectPersistenceHarness({
() => ({
layersRef,
viewportRef,
canvasViewportRef,
canvasGenerationDialogsRef,
canvasBackgroundColorRef,
}),
@@ -173,6 +172,7 @@ function ProjectPersistenceHarness({
layers,
canvasGenerationDialogs: generationDialogs,
viewport,
canvasSize,
canvasBackgroundColor,
isViewportInteracting,
canAccessProtectedData,
@@ -22,7 +22,6 @@ import {
canvasDisplayViewportToViewport,
type CanvasLayerResourceMetadata,
DEFAULT_CANVAS_BACKGROUND_COLOR,
DEFAULT_CANVAS_SIZE,
hydrateLayer,
isInlineEditorMediaSource,
serializeCanvasLayout,
@@ -40,6 +39,7 @@ import {
PROJECT_COVER_SNAPSHOT_ASSET_KIND,
PROJECT_COVER_SNAPSHOT_OBJECT_ASSET_KIND,
PROJECT_COVER_SNAPSHOT_SIZE,
type ProjectCoverSnapshotViewportSize,
} from './ImageCanvasProjectCoverSnapshotModel';
type ProjectResourceOptions = {
@@ -66,7 +66,6 @@ type CachedEditorProjectSnapshot = {
type ImageCanvasProjectPersistenceRefs = {
layersRef: RefObject<CanvasLayer[]>;
viewportRef: RefObject<CanvasViewport>;
canvasViewportRef: RefObject<HTMLDivElement | null>;
canvasGenerationDialogsRef: RefObject<CanvasGenerationDialogState[]>;
canvasBackgroundColorRef: RefObject<string>;
};
@@ -90,6 +89,7 @@ type ImageCanvasProjectPersistenceOptions = {
layers: CanvasLayer[];
canvasGenerationDialogs: CanvasGenerationDialogState[];
viewport: CanvasViewport;
canvasSize: ProjectCoverSnapshotViewportSize;
canvasBackgroundColor: string;
isViewportInteracting: boolean;
canAccessProtectedData: boolean;
@@ -116,21 +116,6 @@ function isEditorProjectRevisionConflict(error: unknown) {
return error instanceof ApiClientError && error.status === 409;
}
function resolveProjectCoverViewportSize(
viewportElement: HTMLDivElement | null,
) {
const width = viewportElement?.clientWidth ?? 0;
const height = viewportElement?.clientHeight ?? 0;
return {
width:
width > 0 && Number.isFinite(width) ? width : DEFAULT_CANVAS_SIZE.width,
height:
height > 0 && Number.isFinite(height)
? height
: DEFAULT_CANVAS_SIZE.height,
};
}
const EDITOR_PROJECT_LAYOUT_RETRYABLE_STATUS_CODES = new Set([
408, 425, 429, 502, 503, 504,
]);
@@ -330,6 +315,7 @@ export function useImageCanvasProjectPersistence({
layers,
canvasGenerationDialogs,
viewport,
canvasSize,
canvasBackgroundColor,
isViewportInteracting,
canAccessProtectedData,
@@ -354,6 +340,7 @@ export function useImageCanvasProjectPersistence({
const projectTitleRef = useRef('未命名画布');
const coverSnapshotSignatureRef = useRef<string | null>(null);
const coverSnapshotUploadRequestRef = useRef(0);
const coverSnapshotViewportSizeRef = useRef(canvasSize);
const [projectId, setProjectId] = useState<string | null>(null);
const [isProjectReady, setIsProjectReady] = useState(false);
const {
@@ -366,6 +353,7 @@ export function useImageCanvasProjectPersistence({
restoreCanvasGenerationDialogs,
applyCanvasBackgroundColor,
} = setters;
coverSnapshotViewportSizeRef.current = canvasSize;
const clearPendingProjectLayoutSave = useCallback(() => {
pendingProjectLayoutSaveRef.current = null;
@@ -478,9 +466,7 @@ export function useImageCanvasProjectPersistence({
}
const coverViewport =
canvasDisplayViewportToViewport(coverDisplayViewport);
const viewportSize = resolveProjectCoverViewportSize(
refs.canvasViewportRef.current,
);
const viewportSize = coverSnapshotViewportSizeRef.current;
const backgroundColor = refs.canvasBackgroundColorRef.current;
const signature = buildProjectCoverSnapshotSignature({
layers: coverLayers,