Files
Genarrative/src/components/image-editor/ImageCanvasAssetLibraryModel.ts
kdletters 6e8089c297 拆分编辑器素材库模型
抽出素材库分组和本地状态变更规则

补充素材库模型单测

更新 TRACKING.md 记录第三十七阶段验证
2026-06-17 18:15:34 +08:00

217 lines
4.5 KiB
TypeScript

import type {
EditorAsset,
EditorAssetFolder,
} from './ImageCanvasEditorTypes';
export type GroupedAssetFolder = EditorAssetFolder & {
assets: EditorAsset[];
};
export function groupAssetsByFolder(
assetFolders: EditorAssetFolder[],
assets: EditorAsset[],
): GroupedAssetFolder[] {
return assetFolders.map((folder) => ({
...folder,
assets: assets.filter((asset) => asset.folderId === folder.id),
}));
}
export function getSelectableAssets(assets: EditorAsset[]) {
return assets.filter((asset) => asset.sourceKind === 'uploaded');
}
export function areAllSelectableAssetsSelected(
selectableAssets: EditorAsset[],
selectedAssetIds: Set<string>,
) {
return (
selectableAssets.length > 0 &&
selectableAssets.every((asset) => selectedAssetIds.has(asset.id))
);
}
export function renameAssetById(
assets: EditorAsset[],
assetId: string,
label: string,
) {
return assets.map((asset) =>
asset.id === assetId
? {
...asset,
label,
}
: asset,
);
}
export function toggleAssetFolderCollapsed(
assetFolders: EditorAssetFolder[],
folderId: string,
) {
return assetFolders.map((folder) =>
folder.id === folderId
? {
...folder,
collapsed: !folder.collapsed,
}
: folder,
);
}
export function createLocalAssetFolder({
folderId,
label,
}: {
folderId: string;
label: string;
}): EditorAssetFolder {
return {
id: folderId,
label,
collapsed: false,
systemDefault: false,
persisted: false,
};
}
export function replaceLocalAssetFolder({
folders,
assets,
localFolderId,
persistedFolder,
}: {
folders: EditorAssetFolder[];
assets: EditorAsset[];
localFolderId: string;
persistedFolder: {
folderId: string;
label: string;
collapsed: boolean;
systemDefault: boolean;
};
}) {
return {
folders: folders.map((folder) =>
folder.id === localFolderId
? {
id: persistedFolder.folderId,
label: persistedFolder.label,
collapsed: persistedFolder.collapsed,
systemDefault: persistedFolder.systemDefault,
persisted: true,
}
: folder,
),
assets: assets.map((asset) =>
asset.folderId === localFolderId
? {
...asset,
folderId: persistedFolder.folderId,
}
: asset,
),
};
}
export function removeAssetById(assets: EditorAsset[], assetId: string) {
return assets.filter((asset) => asset.id !== assetId);
}
export function renameAssetFolderById(
assetFolders: EditorAssetFolder[],
folderId: string,
label: string,
) {
return assetFolders.map((folder) =>
folder.id === folderId
? {
...folder,
label,
}
: folder,
);
}
export function resolveDefaultAssetFolder(assetFolders: EditorAssetFolder[]) {
return (
assetFolders.find((folder) => folder.systemDefault) ?? assetFolders[0] ?? null
);
}
export function deleteAssetFolderLocally({
folders,
assets,
folderId,
defaultFolderId,
}: {
folders: EditorAssetFolder[];
assets: EditorAsset[];
folderId: string;
defaultFolderId: string;
}) {
return {
folders: folders.filter((folder) => folder.id !== folderId),
assets: assets.map((asset) =>
asset.folderId === folderId
? {
...asset,
folderId: defaultFolderId,
}
: asset,
),
};
}
export function toggleAssetSelection(
selectedAssetIds: Set<string>,
assetId: string,
) {
const nextIds = new Set(selectedAssetIds);
if (nextIds.has(assetId)) {
nextIds.delete(assetId);
} else {
nextIds.add(assetId);
}
return nextIds;
}
export function resolveAllAssetSelection({
allSelectableAssetsSelected,
selectableAssets,
}: {
allSelectableAssetsSelected: boolean;
selectableAssets: EditorAsset[];
}) {
return allSelectableAssetsSelected
? new Set<string>()
: new Set(selectableAssets.map((asset) => asset.id));
}
export function removeSelectedAssets(
assets: EditorAsset[],
selectedAssetIds: Set<string>,
) {
const deletedAssets = assets.filter((asset) => selectedAssetIds.has(asset.id));
return {
assets: assets.filter((asset) => !selectedAssetIds.has(asset.id)),
deletedAssets,
};
}
export function moveAssetToFolderLocally(
assets: EditorAsset[],
assetId: string,
folderId: string,
) {
return assets.map((asset) =>
asset.id === assetId
? {
...asset,
folderId,
}
: asset,
);
}