抽出素材上传生命周期模型

扩展 ImageCanvasUploadModel 承载素材上传占位、进度、失败和持久化回写状态迁移

精简 useImageCanvasUploadWorkflow 中的资产与图层状态补丁逻辑

补充上传模型单测覆盖生命周期状态和图层绑定

更新 TRACKING.md 记录第四十六执行批次与验证结果
This commit is contained in:
2026-06-17 20:36:11 +08:00
parent 6afc1cf920
commit d8bd371c69
4 changed files with 409 additions and 86 deletions

View File

@@ -171,3 +171,5 @@
- 2026-06-17 前端拆分第四十四执行批次验证补充:统一编辑器回归命令 `npm run test -- src/components/image-editor/ImageCanvasStageInteractionModel.test.ts src/components/image-editor/useImageCanvasGenerationSubmissionWorkflow.test.tsx src/components/image-editor/ImageCanvasGenerationDialogModel.test.ts src/components/image-editor/ImageCanvasAssetLibraryModel.test.ts src/components/image-editor/ImageCanvasUploadModel.test.ts src/components/image-editor/ImageCanvasGenerationSubmissionModel.test.ts src/components/image-editor/ImageCanvasGenerationLayerModel.test.ts src/components/image-editor/ImageCanvasAssetRowView.test.tsx src/components/image-editor/ImageCanvasSidebarView.test.tsx src/components/image-editor/ImageCanvasBasicGenerationComposerView.test.tsx src/components/image-editor/ImageCanvasCharacterGenerationComposerView.test.tsx src/components/image-editor/ImageCanvasEditGenerationModalView.test.tsx src/components/image-editor/ImageCanvasEditorShellView.test.tsx src/components/image-editor/ImageCanvasBottomToolbarView.test.tsx src/components/image-editor/ImageCanvasPanelDockView.test.tsx src/components/image-editor/ImageCanvasContextMenusView.test.tsx src/components/image-editor/ImageCanvasSelectedLayerToolbarView.test.tsx src/components/image-editor/ImageCanvasIconSpritesheetComposerView.test.tsx src/components/image-editor/ImageCanvasSpecGenerationPanelView.test.tsx src/components/image-editor/ImageCanvasGenerationImageOptionsView.test.tsx src/components/image-editor/ImageCanvasQuickEditPanelView.test.tsx src/components/image-editor/ImageCanvasCharacterAnimationPanelView.test.tsx src/components/image-editor/ImageCanvasWorldView.test.tsx src/components/image-editor/useImageCanvasAssetLibrary.test.tsx src/components/image-editor/useImageCanvasGenerationSurface.test.tsx src/components/image-editor/useImageCanvasGenerationWorkflow.test.tsx src/components/image-editor/useImageCanvasUploadWorkflow.test.tsx src/components/image-editor/useImageCanvasStageInteractions.test.tsx src/components/image-editor/useImageCanvasAssetPointerDragBridge.test.tsx src/components/image-editor/useImageCanvasAssetCanvasBridge.test.tsx src/components/image-editor/ImageCanvasEditorAssetsIntegration.test.tsx src/components/image-editor/ImageCanvasEditorGenerationIntegration.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx` 通过 33 个文件 / 219 个测试;`npm run typecheck``npm run check:encoding``git diff --check` 均通过。浏览器回归:`http://127.0.0.1:10007/editor/canvas` 使用 Playwright CLI headless 打开成功,未登录显示 `账号入口`;关闭登录后 `画布背景设置` 可打开,点击 `暖灰` 后 viewport 背景为 `rgb(243, 240, 234)``background-image: none`;默认素材侧栏显示 `素材` / `项目素材` / `上传到项目素材`,切换 `打开图层` 后侧栏显示 `图层`,点击 `生成工具``Image Generator` 占位、`生成图片` 对话框和 `AI画布工具栏` 均可见;网络请求仅有预期未登录 `/api/auth/refresh` 401其余 editor smoke 相关请求正常。
- 2026-06-17 前端拆分第四十五执行批次:继续收口 `useImageCanvasUploadWorkflow`,扩展 `ImageCanvasUploadModel`,把生成参考图上传后的 dialog 状态转换从 hook 中抽成纯模型:统一创建上传参考图对象、将 failed 生成面板恢复为 idle、按 `spec-reference` / `character-spec` / `character-reference` / `icon-spec` 写入对应引用字段,并保持不匹配 dialog 不变upload workflow hook 继续保留文件筛选、Data URL 读取、文件 input、未登录素材上传续传、真实素材创建 API、上传进度和画布落图副作用。新增模型单测覆盖参考图 fallback label、failed 状态清理、规范 / 角色 / 图标参考图写入和角色参考图追加;局部验证命令:`npm run test -- src/components/image-editor/ImageCanvasUploadModel.test.ts src/components/image-editor/useImageCanvasUploadWorkflow.test.tsx`
- 2026-06-17 前端拆分第四十五执行批次验证补充:统一编辑器回归命令 `npm run test -- src/components/image-editor/ImageCanvasStageInteractionModel.test.ts src/components/image-editor/useImageCanvasGenerationSubmissionWorkflow.test.tsx src/components/image-editor/ImageCanvasGenerationDialogModel.test.ts src/components/image-editor/ImageCanvasAssetLibraryModel.test.ts src/components/image-editor/ImageCanvasUploadModel.test.ts src/components/image-editor/ImageCanvasGenerationSubmissionModel.test.ts src/components/image-editor/ImageCanvasGenerationLayerModel.test.ts src/components/image-editor/ImageCanvasAssetRowView.test.tsx src/components/image-editor/ImageCanvasSidebarView.test.tsx src/components/image-editor/ImageCanvasBasicGenerationComposerView.test.tsx src/components/image-editor/ImageCanvasCharacterGenerationComposerView.test.tsx src/components/image-editor/ImageCanvasEditGenerationModalView.test.tsx src/components/image-editor/ImageCanvasEditorShellView.test.tsx src/components/image-editor/ImageCanvasBottomToolbarView.test.tsx src/components/image-editor/ImageCanvasPanelDockView.test.tsx src/components/image-editor/ImageCanvasContextMenusView.test.tsx src/components/image-editor/ImageCanvasSelectedLayerToolbarView.test.tsx src/components/image-editor/ImageCanvasIconSpritesheetComposerView.test.tsx src/components/image-editor/ImageCanvasSpecGenerationPanelView.test.tsx src/components/image-editor/ImageCanvasGenerationImageOptionsView.test.tsx src/components/image-editor/ImageCanvasQuickEditPanelView.test.tsx src/components/image-editor/ImageCanvasCharacterAnimationPanelView.test.tsx src/components/image-editor/ImageCanvasWorldView.test.tsx src/components/image-editor/useImageCanvasAssetLibrary.test.tsx src/components/image-editor/useImageCanvasGenerationSurface.test.tsx src/components/image-editor/useImageCanvasGenerationWorkflow.test.tsx src/components/image-editor/useImageCanvasUploadWorkflow.test.tsx src/components/image-editor/useImageCanvasStageInteractions.test.tsx src/components/image-editor/useImageCanvasAssetPointerDragBridge.test.tsx src/components/image-editor/useImageCanvasAssetCanvasBridge.test.tsx src/components/image-editor/ImageCanvasEditorAssetsIntegration.test.tsx src/components/image-editor/ImageCanvasEditorGenerationIntegration.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx` 通过 33 个文件 / 223 个测试;`npm run typecheck``npm run check:encoding``git diff --check` 均通过。浏览器回归:`http://127.0.0.1:10007/editor/canvas` 使用 Playwright CLI headless 打开成功,未登录显示 `账号入口`;关闭登录后 `画布背景设置` 可打开,点击 `暖灰` 后 viewport 背景为 `rgb(243, 240, 234)``background-image: none`;默认素材侧栏显示 `素材` / `项目素材` / `上传到项目素材`,切换 `打开图层` 后侧栏显示 `图层`,点击 `生成工具``Image Generator` 占位、`生成图片` 对话框和 `AI画布工具栏` 均可见;网络请求仅有预期未登录 `/api/auth/refresh` 401其余 editor smoke 相关请求正常。只读子代理复核生成提交链路后建议暂停继续硬拆,除非后续新增生成模式再考虑按“生成成功后的落图提交事务”抽内部 hook。
- 2026-06-17 前端拆分第四十六执行批次:继续收口 `useImageCanvasUploadWorkflow`,扩展 `ImageCanvasUploadModel`,把素材上传生命周期中的文件夹展开、读取成功 / 失败、上传中、持久化资产替换、上传失败、图片尺寸回写和画布图层绑定持久化素材抽成纯模型upload workflow hook 继续保留文件筛选、Data URL 读取、登录弹窗、真实素材创建 API、Image 尺寸读取、画布落图和 React setter 编排。新增模型单测覆盖上传占位卡各阶段状态、持久化后清理上传态、尺寸回写和图层绑定;局部验证命令:`npm run test -- src/components/image-editor/ImageCanvasUploadModel.test.ts src/components/image-editor/useImageCanvasUploadWorkflow.test.tsx`
- 2026-06-17 前端拆分第四十六执行批次验证补充:统一编辑器回归命令 `npm run test -- src/components/image-editor/ImageCanvasStageInteractionModel.test.ts src/components/image-editor/useImageCanvasGenerationSubmissionWorkflow.test.tsx src/components/image-editor/ImageCanvasGenerationDialogModel.test.ts src/components/image-editor/ImageCanvasAssetLibraryModel.test.ts src/components/image-editor/ImageCanvasUploadModel.test.ts src/components/image-editor/ImageCanvasGenerationSubmissionModel.test.ts src/components/image-editor/ImageCanvasGenerationLayerModel.test.ts src/components/image-editor/ImageCanvasAssetRowView.test.tsx src/components/image-editor/ImageCanvasSidebarView.test.tsx src/components/image-editor/ImageCanvasBasicGenerationComposerView.test.tsx src/components/image-editor/ImageCanvasCharacterGenerationComposerView.test.tsx src/components/image-editor/ImageCanvasEditGenerationModalView.test.tsx src/components/image-editor/ImageCanvasEditorShellView.test.tsx src/components/image-editor/ImageCanvasBottomToolbarView.test.tsx src/components/image-editor/ImageCanvasPanelDockView.test.tsx src/components/image-editor/ImageCanvasContextMenusView.test.tsx src/components/image-editor/ImageCanvasSelectedLayerToolbarView.test.tsx src/components/image-editor/ImageCanvasIconSpritesheetComposerView.test.tsx src/components/image-editor/ImageCanvasSpecGenerationPanelView.test.tsx src/components/image-editor/ImageCanvasGenerationImageOptionsView.test.tsx src/components/image-editor/ImageCanvasQuickEditPanelView.test.tsx src/components/image-editor/ImageCanvasCharacterAnimationPanelView.test.tsx src/components/image-editor/ImageCanvasWorldView.test.tsx src/components/image-editor/useImageCanvasAssetLibrary.test.tsx src/components/image-editor/useImageCanvasGenerationSurface.test.tsx src/components/image-editor/useImageCanvasGenerationWorkflow.test.tsx src/components/image-editor/useImageCanvasUploadWorkflow.test.tsx src/components/image-editor/useImageCanvasStageInteractions.test.tsx src/components/image-editor/useImageCanvasAssetPointerDragBridge.test.tsx src/components/image-editor/useImageCanvasAssetCanvasBridge.test.tsx src/components/image-editor/ImageCanvasEditorAssetsIntegration.test.tsx src/components/image-editor/ImageCanvasEditorGenerationIntegration.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx` 通过 33 个文件 / 228 个测试;`npm run typecheck``npm run check:encoding``git diff --check` 均通过。浏览器回归:`http://127.0.0.1:10007/editor/canvas` 使用系统 Chrome headless 打开成功,未登录显示 `账号入口`;默认素材侧栏显示 `素材` / `项目素材`;关闭登录后 `画布背景设置` 可打开,点击 `暖灰` 后 viewport 背景为 `rgb(243, 240, 234)``background-image: none`;切换 `打开图层` 后侧栏显示 `图层`;点击 `生成工具``Image Generator` 占位、生成表单控件和 `AI画布工具栏` 均可见;除预期未登录 `/api/auth/refresh` 401 外无额外 API 失败或控制台错误。

View File

@@ -7,9 +7,17 @@ import type {
} from './ImageCanvasEditorTypes';
import {
applyGenerationReferenceUpload,
applyMeasuredUploadAssetSize,
applyPersistedUploadAsset,
applyUploadAssetCreateFailure,
applyUploadAssetCreatePending,
applyUploadAssetReadFailure,
applyUploadAssetReadSuccess,
bindUploadLayerToPersistedAsset,
createUploadCanvasLayer,
createUploadedGenerationReference,
createUploadingAssetPlaceholder,
expandUploadFolder,
resizeUploadCanvasLayerToImage,
resolveUploadFolderId,
setFailedGenerationIdle,
@@ -47,6 +55,19 @@ function createLayer(overrides: Partial<CanvasLayer> = {}): CanvasLayer {
};
}
function createUploadingAsset(
overrides: Partial<ReturnType<typeof createUploadingAssetPlaceholder>> = {},
) {
return {
...createUploadingAssetPlaceholder({
uploadIndex: 1,
fileName: '上传图片.png',
folderId: 'project',
}),
...overrides,
};
}
function createDialog(
overrides: Partial<GenerateDialogState> = {},
): GenerateDialogState {
@@ -109,6 +130,167 @@ describe('ImageCanvasUploadModel', () => {
});
});
it('opens the target upload folder without changing other folders', () => {
expect(
expandUploadFolder({
folders: [
createFolder({ id: 'project', collapsed: true }),
createFolder({ id: 'characters', label: '角色素材', collapsed: true }),
],
folderId: 'characters',
}),
).toEqual([
createFolder({ id: 'project', collapsed: true }),
createFolder({ id: 'characters', label: '角色素材', collapsed: false }),
]);
});
it('applies upload asset lifecycle patches', () => {
const asset = createUploadingAsset();
const otherAsset = createUploadingAsset({
id: 'upload-other',
label: '其他图片.png',
});
expect(
applyUploadAssetReadSuccess({
assets: [asset, otherAsset],
uploadAssetId: asset.id,
imageSrc: 'data:image/png;base64,read',
}),
).toMatchObject([
{
id: 'upload-1',
src: 'data:image/png;base64,read',
uploadProgress: 42,
uploadMessage: '读取图片',
},
{ id: 'upload-other', label: '其他图片.png' },
]);
expect(
applyUploadAssetCreatePending({
assets: [asset],
uploadAssetId: asset.id,
}),
).toMatchObject([
{
id: 'upload-1',
uploadStatus: 'uploading',
uploadProgress: 68,
uploadMessage: '上传中',
},
]);
expect(
applyUploadAssetReadFailure({
assets: [asset],
uploadAssetId: asset.id,
}),
).toMatchObject([
{
id: 'upload-1',
uploadStatus: 'failed',
uploadProgress: 100,
uploadMessage: '读取失败',
},
]);
expect(
applyUploadAssetCreateFailure({
assets: [asset],
uploadAssetId: asset.id,
message: '请先登录',
}),
).toMatchObject([
{
id: 'upload-1',
uploadStatus: 'failed',
uploadProgress: 100,
uploadMessage: '请先登录',
},
]);
});
it('replaces upload placeholders with persisted assets and clears upload state', () => {
expect(
applyPersistedUploadAsset({
assets: [createUploadingAsset()],
uploadAssetId: 'upload-1',
persistedAsset: {
assetId: 'asset-1',
folderId: 'characters',
label: '角色.png',
imageSrc: 'data:image/png;base64,persisted',
width: 1024,
height: 768,
objectKey: 'object-key',
assetObjectId: 'asset-object',
},
}),
).toEqual([
{
id: 'asset-1',
label: '角色.png',
src: 'data:image/png;base64,persisted',
width: 1024,
height: 768,
folderId: 'characters',
sourceKind: 'uploaded',
sourceType: 'uploaded',
persisted: true,
objectKey: 'object-key',
assetObjectId: 'asset-object',
uploadStatus: undefined,
uploadProgress: undefined,
uploadMessage: undefined,
},
]);
});
it('updates measured asset size after the browser loads the uploaded image', () => {
expect(
applyMeasuredUploadAssetSize({
assets: [createUploadingAsset()],
uploadAssetId: 'upload-1',
originalWidth: 1600,
originalHeight: 900,
}),
).toMatchObject([
{
id: 'upload-1',
width: 1600,
height: 900,
},
]);
});
it('binds uploaded canvas layers to persisted asset metadata', () => {
expect(
bindUploadLayerToPersistedAsset({
layers: [createLayer({ objectKey: 'local-object' })],
layerId: 'layer-upload-1',
persistedAsset: {
assetId: 'asset-1',
folderId: 'project',
label: '上传图片.png',
imageSrc: 'data:image/png;base64,persisted',
width: 420,
height: 315,
objectKey: 'object-key',
assetObjectId: 'asset-object',
},
}),
).toMatchObject([
{
id: 'layer-upload-1',
sourceAssetId: 'asset-1',
objectKey: 'object-key',
assetObjectId: 'asset-object',
},
]);
});
it('creates uploaded generation references with fallback labels', () => {
vi.useFakeTimers();
vi.setSystemTime(new Date('2026-06-17T12:00:00.000Z'));

View File

@@ -10,6 +10,16 @@ import type {
type CanvasSize = { width: number; height: number };
type CanvasPoint = { x: number; y: number };
type PersistedUploadAsset = {
assetId: string;
folderId: string;
label: string;
imageSrc: string;
width: number;
height: number;
objectKey?: string | null;
assetObjectId?: string | null;
};
type GenerationReferenceUploadTarget =
| 'character-reference'
| 'character-spec'
@@ -140,6 +150,175 @@ export function createUploadingAssetPlaceholder({
};
}
export function expandUploadFolder({
folders,
folderId,
}: {
folders: EditorAssetFolder[];
folderId: string;
}) {
return folders.map((folder) =>
folder.id === folderId
? {
...folder,
collapsed: false,
}
: folder,
);
}
export function applyUploadAssetReadSuccess({
assets,
uploadAssetId,
imageSrc,
}: {
assets: EditorAsset[];
uploadAssetId: string;
imageSrc: string;
}) {
return assets.map((asset) =>
asset.id === uploadAssetId
? {
...asset,
src: imageSrc,
uploadProgress: 42,
uploadMessage: '读取图片',
}
: asset,
);
}
export function applyUploadAssetReadFailure({
assets,
uploadAssetId,
}: {
assets: EditorAsset[];
uploadAssetId: string;
}) {
return assets.map((asset) =>
asset.id === uploadAssetId
? {
...asset,
uploadStatus: 'failed' as const,
uploadProgress: 100,
uploadMessage: '读取失败',
}
: asset,
);
}
export function applyUploadAssetCreatePending({
assets,
uploadAssetId,
}: {
assets: EditorAsset[];
uploadAssetId: string;
}) {
return assets.map((asset) =>
asset.id === uploadAssetId
? {
...asset,
uploadProgress: 68,
uploadMessage: '上传中',
}
: asset,
);
}
export function applyPersistedUploadAsset({
assets,
uploadAssetId,
persistedAsset,
}: {
assets: EditorAsset[];
uploadAssetId: string;
persistedAsset: PersistedUploadAsset;
}) {
return assets.map((asset) =>
asset.id === uploadAssetId
? {
...asset,
id: persistedAsset.assetId,
folderId: persistedAsset.folderId,
label: persistedAsset.label,
src: persistedAsset.imageSrc,
width: persistedAsset.width,
height: persistedAsset.height,
objectKey: persistedAsset.objectKey ?? undefined,
assetObjectId: persistedAsset.assetObjectId ?? undefined,
persisted: true,
uploadStatus: undefined,
uploadProgress: undefined,
uploadMessage: undefined,
}
: asset,
);
}
export function applyUploadAssetCreateFailure({
assets,
uploadAssetId,
message,
}: {
assets: EditorAsset[];
uploadAssetId: string;
message: string;
}) {
return assets.map((asset) =>
asset.id === uploadAssetId
? {
...asset,
uploadStatus: 'failed' as const,
uploadProgress: 100,
uploadMessage: message,
}
: asset,
);
}
export function applyMeasuredUploadAssetSize({
assets,
uploadAssetId,
originalWidth,
originalHeight,
}: {
assets: EditorAsset[];
uploadAssetId: string;
originalWidth: number;
originalHeight: number;
}) {
return assets.map((asset) =>
asset.id === uploadAssetId
? {
...asset,
width: originalWidth,
height: originalHeight,
}
: asset,
);
}
export function bindUploadLayerToPersistedAsset({
layers,
layerId,
persistedAsset,
}: {
layers: CanvasLayer[];
layerId: string;
persistedAsset: PersistedUploadAsset;
}) {
return layers.map((layer) =>
layer.id === layerId
? {
...layer,
sourceAssetId: persistedAsset.assetId,
objectKey: persistedAsset.objectKey ?? layer.objectKey,
assetObjectId: persistedAsset.assetObjectId ?? layer.assetObjectId,
}
: layer,
);
}
export function normalizeUploadScreenPoint({
canvasPoint,
canvasSize,

View File

@@ -21,9 +21,17 @@ import type {
import { isImageFile, readImageFileAsDataUrl } from './ImageCanvasFileModel';
import {
applyGenerationReferenceUpload,
applyMeasuredUploadAssetSize,
applyPersistedUploadAsset,
applyUploadAssetCreateFailure,
applyUploadAssetCreatePending,
applyUploadAssetReadFailure,
applyUploadAssetReadSuccess,
bindUploadLayerToPersistedAsset,
createUploadCanvasLayer,
createUploadedGenerationReference,
createUploadingAssetPlaceholder,
expandUploadFolder,
resizeUploadCanvasLayerToImage,
resolveUploadFolderId,
} from './ImageCanvasUploadModel';
@@ -232,43 +240,28 @@ export function useImageCanvasUploadWorkflow({
});
setAssets((currentAssets) => [...currentAssets, uploadedAsset]);
setAssetFolders((currentFolders) =>
currentFolders.map((folder) =>
folder.id === uploadFolderId
? {
...folder,
collapsed: false,
}
: folder,
),
expandUploadFolder({
folders: currentFolders,
folderId: uploadFolderId,
}),
);
let imageSrc = '';
try {
imageSrc = await readImageFileAsDataUrl(file);
setAssets((currentAssets) =>
currentAssets.map((asset) =>
asset.id === uploadedAsset.id
? {
...asset,
src: imageSrc,
uploadProgress: 42,
uploadMessage: '读取图片',
}
: asset,
),
applyUploadAssetReadSuccess({
assets: currentAssets,
uploadAssetId: uploadedAsset.id,
imageSrc,
}),
);
} catch {
setAssets((currentAssets) =>
currentAssets.map((asset) =>
asset.id === uploadedAsset.id
? {
...asset,
uploadStatus: 'failed',
uploadProgress: 100,
uploadMessage: '读取失败',
}
: asset,
),
applyUploadAssetReadFailure({
assets: currentAssets,
uploadAssetId: uploadedAsset.id,
}),
);
return;
}
@@ -288,15 +281,10 @@ export function useImageCanvasUploadWorkflow({
}
setAssets((currentAssets) =>
currentAssets.map((asset) =>
asset.id === uploadedAsset.id
? {
...asset,
uploadProgress: 68,
uploadMessage: '上传中',
}
: asset,
),
applyUploadAssetCreatePending({
assets: currentAssets,
uploadAssetId: uploadedAsset.id,
}),
);
createEditorAsset({
folderId: uploadFolderId,
@@ -308,39 +296,19 @@ export function useImageCanvasUploadWorkflow({
})
.then((asset) => {
setAssets((currentAssets) =>
currentAssets.map((currentAsset) =>
currentAsset.id === uploadedAsset.id
? {
...currentAsset,
id: asset.assetId,
folderId: asset.folderId,
label: asset.label,
src: asset.imageSrc,
width: asset.width,
height: asset.height,
objectKey: asset.objectKey ?? undefined,
assetObjectId: asset.assetObjectId ?? undefined,
persisted: true,
uploadStatus: undefined,
uploadProgress: undefined,
uploadMessage: undefined,
}
: currentAsset,
),
applyPersistedUploadAsset({
assets: currentAssets,
uploadAssetId: uploadedAsset.id,
persistedAsset: asset,
}),
);
if (options.addToCanvas) {
setLayers((currentLayers) =>
currentLayers.map((currentLayer) =>
currentLayer.id === nextLayer.id
? {
...currentLayer,
sourceAssetId: asset.assetId,
objectKey: asset.objectKey ?? currentLayer.objectKey,
assetObjectId:
asset.assetObjectId ?? currentLayer.assetObjectId,
}
: currentLayer,
),
bindUploadLayerToPersistedAsset({
layers: currentLayers,
layerId: nextLayer.id,
persistedAsset: asset,
}),
);
}
})
@@ -350,16 +318,11 @@ export function useImageCanvasUploadWorkflow({
openEditorLoginModal();
}
setAssets((currentAssets) =>
currentAssets.map((asset) =>
asset.id === uploadedAsset.id
? {
...asset,
uploadStatus: 'failed',
uploadProgress: 100,
uploadMessage: isAuthError ? '请先登录' : '上传失败',
}
: asset,
),
applyUploadAssetCreateFailure({
assets: currentAssets,
uploadAssetId: uploadedAsset.id,
message: isAuthError ? '请先登录' : '上传失败',
}),
);
});
@@ -387,15 +350,12 @@ export function useImageCanvasUploadWorkflow({
);
}
setAssets((currentAssets) =>
currentAssets.map((asset) =>
asset.id === uploadedAsset.id
? {
...asset,
width: originalWidth,
height: originalHeight,
}
: asset,
),
applyMeasuredUploadAssetSize({
assets: currentAssets,
uploadAssetId: uploadedAsset.id,
originalWidth,
originalHeight,
}),
);
};
uploadedImage.src = imageSrc;