删除 asset-canvas 前端精修草稿入口并重接资源派生

- 删除 apps/ai-game-creator-shell/src/features/asset-canvas 全部四个文件(AssetCanvasSurface.tsx、assetCanvasNaming.ts、assetCanvasSurface.css、tauriImageCanvasHostAdapter.ts)
- index.tsx 删除 assetCanvasRoute 状态与 ref、beginAssetCanvas/openAssetCanvas/normalizeRasterSourceAndOpen、cancelAssetCanvas/handleAssetCanvasSaveAttempt/handleAssetCommitted 与 game-creator-local-asset-committed 事件监听、中央主视窗渲染分支与 resources.asset-canvas 视图状态
- index.tsx 把 assetCanvasNotice 改名为通用 resourceWorkbenchNotice,保留非草稿流程文案与资源定位按钮
- resourceEditModel.ts 取消 image-canvas 路由,PNG/JPEG/WebP 统一走 derive + image-reference(复用 resource_editor.rs 的 /editor/images/edits)
- styles.css 删除 resources.asset-canvas 两条画布选择器,保留 resources.ui-editor 规则
- check-config.mjs 把 normalize_local_project_raster_resource 加入 native-only 白名单(临时项:C3 快速编辑重建后会重新获得前端调用方,届时删除该 allowlist 条目)
- index.tsx 移除 useMemo 依赖数组里模块级常量 visibleCategoryOrder(基线遗留的 react-hooks/exhaustive-deps warning,会阻断 pre-commit,属通过门禁所需的最小修正)
This commit is contained in:
2026-09-09 20:04:24 +08:00
parent 1abbbadb07
commit 9fd5b99972
8 changed files with 55 additions and 6979 deletions
@@ -111,6 +111,7 @@ const allowedUncalledTauriCommands = [
'chat_with_game_creator_agent',
'check_ui_editor_font_glyph_coverage',
'create_ui_design_resource',
'normalize_local_project_raster_resource',
'open_game_creator_launcher_window',
'open_game_creator_workspace_window',
'read_direct_project_conversation',
File diff suppressed because it is too large Load Diff
@@ -1,82 +0,0 @@
const COMMIT_ID_SUFFIX =
/--[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
const WINDOWS_RESERVED_NAMES = new Set([
'CON',
'PRN',
'AUX',
'NUL',
'COM1',
'COM2',
'COM3',
'COM4',
'COM5',
'COM6',
'COM7',
'COM8',
'COM9',
'LPT1',
'LPT2',
'LPT3',
'LPT4',
'LPT5',
'LPT6',
'LPT7',
'LPT8',
'LPT9',
]);
const FORBIDDEN_FILE_NAME_CHARACTERS = '/\\:*?"<>|';
function isForbiddenFileNameCharacter(value: string) {
const code = value.codePointAt(0) ?? 0;
return (
code <= 0x1f ||
code === 0x7f ||
FORBIDDEN_FILE_NAME_CHARACTERS.includes(value)
);
}
function sanitizeAssetBaseName(value: string, fallback: string) {
const normalized = value
.normalize('NFC')
.split('')
.filter((character) => !isForbiddenFileNameCharacter(character))
.join('');
const bounded = Array.from(normalized)
.slice(0, 80)
.join('')
.replace(/[. ]+$/u, '');
if (
bounded.length === 0 ||
WINDOWS_RESERVED_NAMES.has(bounded.split('.')[0]?.toUpperCase() ?? '')
) {
return fallback;
}
return bounded;
}
export function canonicalAssetBaseName(
localPath: string,
fallback = '画布素材',
) {
const fileName = localPath.split(/[\\/]/u).filter(Boolean).pop() ?? '';
let stem = fileName.replace(/\.[^.]+$/u, '');
let next = stem.replace(COMMIT_ID_SUFFIX, '');
while (next !== stem) {
stem = next;
next = stem.replace(COMMIT_ID_SUFFIX, '');
}
return sanitizeAssetBaseName(next, fallback);
}
export function isValidAssetCanvasName(name: string) {
if (
name.length === 0 ||
Array.from(name).length > 80 ||
Array.from(name).some(isForbiddenFileNameCharacter) ||
/[. ]$/u.test(name) ||
WINDOWS_RESERVED_NAMES.has(name.split('.')[0]?.toUpperCase() ?? '')
) {
return false;
}
return true;
}
File diff suppressed because it is too large Load Diff
@@ -5444,7 +5444,6 @@ iframe.preview-frame {
box-shadow: var(--platform-nav-active-shadow);
}
.game-workbench-stage[data-resource-view-state^='resources.asset-canvas'],
.game-workbench-stage[data-resource-view-state='resources.ui-editor'] {
grid-template-rows: auto minmax(0, 1fr);
}
@@ -5455,12 +5454,6 @@ iframe.preview-frame {
min-height: 0;
}
.game-workbench-stage[data-resource-view-state^='resources.asset-canvas']
> .asset-canvas-surface {
grid-row: 2;
min-height: 0;
}
.game-workbench-toolbar {
position: relative;
display: flex;
File diff suppressed because it is too large Load Diff
@@ -11,26 +11,13 @@ export type LocalProjectResourceEditKind =
| 'agent-result'
| 'version';
export type ProjectResourceEditCapability =
| {
route: 'image-canvas';
sourceAssetId: string;
normalizeSource: false;
mediaType: 'image/png' | 'image/jpeg' | 'image/webp';
}
| {
route: 'image-canvas';
sourceAssetId: null;
normalizeSource: true;
mediaType: 'image/png' | 'image/jpeg' | 'image/webp';
}
| {
route: 'derive';
editKind: LocalProjectResourceEditKind;
sourceMediaType: string;
semanticNotice: string | null;
generationMode?: 'create' | 'derive';
};
export type ProjectResourceEditCapability = {
route: 'derive';
editKind: LocalProjectResourceEditKind;
sourceMediaType: string;
semanticNotice: string | null;
generationMode?: 'create' | 'derive';
};
const extensionMediaTypes: Record<string, string> = {
png: 'image/png',
@@ -140,21 +127,6 @@ export function resolveProjectResourceEditCapability(
}
const mediaType = canonicalProjectedResourceMediaType(resource);
if (['image/png', 'image/jpeg', 'image/webp'].includes(mediaType)) {
return resource.manifestAssetId
? {
route: 'image-canvas',
sourceAssetId: resource.manifestAssetId,
normalizeSource: false,
mediaType: mediaType as 'image/png' | 'image/jpeg' | 'image/webp',
}
: {
route: 'image-canvas',
sourceAssetId: null,
normalizeSource: true,
mediaType: mediaType as 'image/png' | 'image/jpeg' | 'image/webp',
};
}
if (mediaType === 'image/svg+xml') {
return {
route: 'derive',