修复画布图层保存体积过大
画布布局不再写入图片base64正文 加载画布时从项目资源补回图层图片地址 补充大图素材保存布局回归测试
This commit is contained in:
@@ -1623,6 +1623,49 @@ describe('ImageCanvasEditorView', () => {
|
||||
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 () => {
|
||||
await renderLoadedEditor();
|
||||
|
||||
|
||||
@@ -539,7 +539,6 @@ function serializeLayer(layer: CanvasLayer): EditorProjectLayerSnapshot {
|
||||
layerId: layer.id,
|
||||
resourceId: layer.resourceId,
|
||||
title: layer.title,
|
||||
src: layer.src,
|
||||
x: layer.x,
|
||||
y: layer.y,
|
||||
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 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 : '画布图片';
|
||||
if (!resourceId || !layerId || !src) {
|
||||
return null;
|
||||
@@ -1221,8 +1224,14 @@ export function ImageCanvasEditorView() {
|
||||
setProjectTitle(nextProjectTitle);
|
||||
setProjectRenameValue(nextProjectTitle);
|
||||
setViewport(project.viewport);
|
||||
const resourcesById = new Map(
|
||||
project.resources.map((resource) => [
|
||||
resource.resourceId,
|
||||
{ imageSrc: resource.imageSrc },
|
||||
]),
|
||||
);
|
||||
const hydratedLayers = project.layers
|
||||
.map(hydrateLayer)
|
||||
.map((layer) => hydrateLayer(layer, resourcesById))
|
||||
.filter((layer): layer is CanvasLayer => Boolean(layer));
|
||||
layerCounterRef.current = hydratedLayers.length;
|
||||
setLayers(hydratedLayers);
|
||||
@@ -2099,11 +2108,19 @@ export function ImageCanvasEditorView() {
|
||||
}
|
||||
: currentLayer,
|
||||
);
|
||||
if (options.saveLayout) {
|
||||
void saveProjectLayoutNow(nextLayers).catch(() => {});
|
||||
}
|
||||
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;
|
||||
})
|
||||
.catch(() => {
|
||||
@@ -2228,9 +2245,7 @@ export function ImageCanvasEditorView() {
|
||||
);
|
||||
captureCanvasHistory();
|
||||
setLayers((currentLayers) => {
|
||||
const nextLayers = [...currentLayers, nextLayer];
|
||||
void saveProjectLayoutNow(nextLayers).catch(() => {});
|
||||
return nextLayers;
|
||||
return [...currentLayers, nextLayer];
|
||||
});
|
||||
selectSingleLayer(nextLayer.id);
|
||||
setHoveredLayerId(null);
|
||||
@@ -2853,7 +2868,6 @@ export function ImageCanvasEditorView() {
|
||||
}
|
||||
: currentLayer,
|
||||
);
|
||||
void saveProjectLayoutNow(nextLayers).catch(() => {});
|
||||
return nextLayers;
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user