diff --git a/apps/ai-game-creator-shell/src/components/AssetImporter/ImageImporterPreview.tsx b/apps/ai-game-creator-shell/src/components/AssetImporter/ImageImporterPreview.tsx index ad2b2620f..7378df15f 100644 --- a/apps/ai-game-creator-shell/src/components/AssetImporter/ImageImporterPreview.tsx +++ b/apps/ai-game-creator-shell/src/components/AssetImporter/ImageImporterPreview.tsx @@ -3,6 +3,7 @@ import { useEffect, useRef, useState } from 'react'; import { SpriteImagePreview } from '../../features/ui-editor/components/SpriteImagePreview'; import { readEditorAssetPreview } from '../../services/editorAssetHost'; +import { visibleClientErrorMessage } from '../../services/errorReporting'; import { cancelLocalProjectResourcePreviewScope, createProjectResourcePreviewRequestId, @@ -17,6 +18,7 @@ export function ImageImporterPreview({ selected, }: AssetImporterPreviewProps) { const [previewUrl, setPreviewUrl] = useState(null); + const [previewError, setPreviewError] = useState(''); const scopeIdRef = useRef(createProjectResourcePreviewScopeId()); useEffect(() => { @@ -29,6 +31,7 @@ export function ImageImporterPreview({ useEffect(() => { if (!selected || selected.isDirectory) { setPreviewUrl(null); + setPreviewError(''); return; } // A disk-only candidate deliberately has no formal asset identity. Keep @@ -36,16 +39,24 @@ export function ImageImporterPreview({ // first when the user confirms the import. if (selected.source === 'local' && !selected.asset) { setPreviewUrl(null); + setPreviewError(''); return; } if (selected.previewUrl) { setPreviewUrl(selected.previewUrl); + setPreviewError(''); return; } if (selected.source === 'remote' && selected.remoteAssetId) { void readEditorAssetPreview(selected.remoteAssetId) - .then((preview) => setPreviewUrl(preview.previewUrl)) - .catch(() => setPreviewUrl(null)); + .then((preview) => { + setPreviewUrl(preview.previewUrl); + setPreviewError(''); + }) + .catch((error) => { + setPreviewUrl(null); + setPreviewError(visibleClientErrorMessage(error)); + }); return; } if ( @@ -53,6 +64,7 @@ export function ImageImporterPreview({ /^https?:\/\//iu.test(selected.asset?.localPath ?? '') ) { setPreviewUrl(selected.asset?.localPath ?? null); + setPreviewError(''); return; } void invoke('read_local_project_image_preview', { @@ -62,7 +74,10 @@ export function ImageImporterPreview({ requestId: createProjectResourcePreviewRequestId(), }) .then((value) => setPreviewUrl(value.dataUrl)) - .catch(() => setPreviewUrl(null)); + .catch((error) => { + setPreviewUrl(null); + setPreviewError(visibleClientErrorMessage(error)); + }); }, [projectPath, selected]); return previewUrl ? ( @@ -72,10 +87,14 @@ export function ImageImporterPreview({ className="max-h-72 max-w-full object-contain" /> ) : ( - + {selected?.source === 'local' && !selected.asset ? '待导入,导入后可预览' - : (selected?.name ?? '选择一个文件')} + : previewError || selected?.name || '选择一个文件'} ); } diff --git a/apps/ai-game-creator-shell/src/features/project-workspace/ResourceReferencePicker.tsx b/apps/ai-game-creator-shell/src/features/project-workspace/ResourceReferencePicker.tsx index 733c04736..7c2f98736 100644 --- a/apps/ai-game-creator-shell/src/features/project-workspace/ResourceReferencePicker.tsx +++ b/apps/ai-game-creator-shell/src/features/project-workspace/ResourceReferencePicker.tsx @@ -27,6 +27,7 @@ import { isGameCreationAppUiDesignDocAsset, } from '../../../../../packages/shared/src/contracts/gameCreationApp'; import { resolveTauriInvoke } from '../../app/tauri'; +import { visibleClientErrorMessage } from '../../services/errorReporting'; import { cancelLocalProjectResourcePreviewScope, createProjectResourcePreviewRequestId, @@ -519,11 +520,13 @@ function ResourcePickerThumbnail({ const previewScopeIdRef = useRef(createProjectResourcePreviewScopeId()); const [previewUrl, setPreviewUrl] = useState(null); const [failed, setFailed] = useState(false); + const [previewError, setPreviewError] = useState(''); const mediaType = asset?.mediaType.toLowerCase() ?? ''; useEffect(() => { setPreviewUrl(null); setFailed(false); + setPreviewError(''); if (!asset || !projectPath || !mediaType.startsWith('image/')) { return; } @@ -539,8 +542,11 @@ function ResourcePickerThumbnail({ .then((result) => { if (!cancelled) setPreviewUrl(result.dataUrl); }) - .catch(() => { - if (!cancelled) setFailed(true); + .catch((error) => { + if (!cancelled) { + setFailed(true); + setPreviewError(visibleClientErrorMessage(error)); + } }); return () => { cancelled = true; @@ -555,7 +561,14 @@ function ResourcePickerThumbnail({ return ; } if (failed) { - return