修复画布图层保存体积过大
画布布局不再写入图片base64正文 加载画布时从项目资源补回图层图片地址 补充大图素材保存布局回归测试
This commit is contained in:
@@ -1623,6 +1623,49 @@ describe('ImageCanvasEditorView', () => {
|
|||||||
expect(createEditorAssetMock).not.toHaveBeenCalled();
|
expect(createEditorAssetMock).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('saves canvas layout without embedding image payloads in layer snapshots', async () => {
|
||||||
|
loadEditorAssetLibraryMock.mockResolvedValueOnce({
|
||||||
|
folders: [
|
||||||
|
{
|
||||||
|
folderId: 'project',
|
||||||
|
label: '项目素材',
|
||||||
|
sortOrder: 0,
|
||||||
|
collapsed: false,
|
||||||
|
systemDefault: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
assets: [
|
||||||
|
{
|
||||||
|
assetId: 'asset-data-heavy',
|
||||||
|
folderId: 'project',
|
||||||
|
label: '大图素材',
|
||||||
|
imageSrc: 'data:image/png;base64,'.concat('a'.repeat(4000)),
|
||||||
|
width: 1024,
|
||||||
|
height: 768,
|
||||||
|
sourceType: 'uploaded',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
render(<ImageCanvasEditorView />);
|
||||||
|
|
||||||
|
await screen.findByRole('button', { name: '添加大图素材' });
|
||||||
|
fireEvent.click(screen.getByRole('button', { name: '添加大图素材' }));
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(saveEditorProjectLayoutMock).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
const layoutCalls = saveEditorProjectLayoutMock.mock.calls;
|
||||||
|
const lastLayout = layoutCalls.at(-1)?.[1];
|
||||||
|
|
||||||
|
expect(lastLayout.layers).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
expect.not.objectContaining({
|
||||||
|
src: expect.stringMatching(/^data:image/u),
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('adds an asset library image to the canvas with pointer dragging', async () => {
|
it('adds an asset library image to the canvas with pointer dragging', async () => {
|
||||||
await renderLoadedEditor();
|
await renderLoadedEditor();
|
||||||
|
|
||||||
|
|||||||
@@ -539,7 +539,6 @@ function serializeLayer(layer: CanvasLayer): EditorProjectLayerSnapshot {
|
|||||||
layerId: layer.id,
|
layerId: layer.id,
|
||||||
resourceId: layer.resourceId,
|
resourceId: layer.resourceId,
|
||||||
title: layer.title,
|
title: layer.title,
|
||||||
src: layer.src,
|
|
||||||
x: layer.x,
|
x: layer.x,
|
||||||
y: layer.y,
|
y: layer.y,
|
||||||
width: layer.width,
|
width: layer.width,
|
||||||
@@ -565,10 +564,14 @@ function serializeLayer(layer: CanvasLayer): EditorProjectLayerSnapshot {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function hydrateLayer(snapshot: EditorProjectLayerSnapshot): CanvasLayer | null {
|
function hydrateLayer(
|
||||||
|
snapshot: EditorProjectLayerSnapshot,
|
||||||
|
resourcesById: Map<string, { imageSrc: string }>,
|
||||||
|
): CanvasLayer | null {
|
||||||
const resourceId = typeof snapshot.resourceId === 'string' ? snapshot.resourceId : '';
|
const resourceId = typeof snapshot.resourceId === 'string' ? snapshot.resourceId : '';
|
||||||
const layerId = typeof snapshot.layerId === 'string' ? snapshot.layerId : '';
|
const layerId = typeof snapshot.layerId === 'string' ? snapshot.layerId : '';
|
||||||
const src = typeof snapshot.src === 'string' ? snapshot.src : '';
|
const snapshotSrc = typeof snapshot.src === 'string' ? snapshot.src : '';
|
||||||
|
const src = snapshotSrc || resourcesById.get(resourceId)?.imageSrc || '';
|
||||||
const title = typeof snapshot.title === 'string' ? snapshot.title : '画布图片';
|
const title = typeof snapshot.title === 'string' ? snapshot.title : '画布图片';
|
||||||
if (!resourceId || !layerId || !src) {
|
if (!resourceId || !layerId || !src) {
|
||||||
return null;
|
return null;
|
||||||
@@ -1221,8 +1224,14 @@ export function ImageCanvasEditorView() {
|
|||||||
setProjectTitle(nextProjectTitle);
|
setProjectTitle(nextProjectTitle);
|
||||||
setProjectRenameValue(nextProjectTitle);
|
setProjectRenameValue(nextProjectTitle);
|
||||||
setViewport(project.viewport);
|
setViewport(project.viewport);
|
||||||
|
const resourcesById = new Map(
|
||||||
|
project.resources.map((resource) => [
|
||||||
|
resource.resourceId,
|
||||||
|
{ imageSrc: resource.imageSrc },
|
||||||
|
]),
|
||||||
|
);
|
||||||
const hydratedLayers = project.layers
|
const hydratedLayers = project.layers
|
||||||
.map(hydrateLayer)
|
.map((layer) => hydrateLayer(layer, resourcesById))
|
||||||
.filter((layer): layer is CanvasLayer => Boolean(layer));
|
.filter((layer): layer is CanvasLayer => Boolean(layer));
|
||||||
layerCounterRef.current = hydratedLayers.length;
|
layerCounterRef.current = hydratedLayers.length;
|
||||||
setLayers(hydratedLayers);
|
setLayers(hydratedLayers);
|
||||||
@@ -2099,11 +2108,19 @@ export function ImageCanvasEditorView() {
|
|||||||
}
|
}
|
||||||
: currentLayer,
|
: currentLayer,
|
||||||
);
|
);
|
||||||
if (options.saveLayout) {
|
|
||||||
void saveProjectLayoutNow(nextLayers).catch(() => {});
|
|
||||||
}
|
|
||||||
return nextLayers;
|
return nextLayers;
|
||||||
});
|
});
|
||||||
|
if (options.saveLayout) {
|
||||||
|
const latestLayers = layersRef.current.map((currentLayer) =>
|
||||||
|
currentLayer.id === layer.id
|
||||||
|
? {
|
||||||
|
...currentLayer,
|
||||||
|
resourceId: resource.resourceId,
|
||||||
|
}
|
||||||
|
: currentLayer,
|
||||||
|
);
|
||||||
|
void saveProjectLayoutNow(latestLayers).catch(() => {});
|
||||||
|
}
|
||||||
return resource;
|
return resource;
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
@@ -2228,9 +2245,7 @@ export function ImageCanvasEditorView() {
|
|||||||
);
|
);
|
||||||
captureCanvasHistory();
|
captureCanvasHistory();
|
||||||
setLayers((currentLayers) => {
|
setLayers((currentLayers) => {
|
||||||
const nextLayers = [...currentLayers, nextLayer];
|
return [...currentLayers, nextLayer];
|
||||||
void saveProjectLayoutNow(nextLayers).catch(() => {});
|
|
||||||
return nextLayers;
|
|
||||||
});
|
});
|
||||||
selectSingleLayer(nextLayer.id);
|
selectSingleLayer(nextLayer.id);
|
||||||
setHoveredLayerId(null);
|
setHoveredLayerId(null);
|
||||||
@@ -2853,7 +2868,6 @@ export function ImageCanvasEditorView() {
|
|||||||
}
|
}
|
||||||
: currentLayer,
|
: currentLayer,
|
||||||
);
|
);
|
||||||
void saveProjectLayoutNow(nextLayers).catch(() => {});
|
|
||||||
return nextLayers;
|
return nextLayers;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user