Increase VectorEngine timeouts and add image UI
Add VectorEngine image generation config and raise request timeouts (env + scripts) from 180000 to 1000000ms. Introduce a reusable CreativeImageInputPanel component with tests and wire up mobile keyboard-focus helpers; update generation views and related tests (CustomWorldGenerationView, BarkBattle editor, Match3D, Puzzle flows). Improve API error handling / VectorEngine request guidance (packages/shared http.ts and docs), and apply multiple backend/frontend fixes for puzzle/match3d/prompt handling. Also include extensive docs and decision-log updates describing UI/UX decisions and verification steps.
This commit is contained in:
@@ -483,7 +483,30 @@ test('运行态会换签并渲染抓大鹅中心容器 UI 图', async () => {
|
||||
);
|
||||
});
|
||||
|
||||
test('容器图换签失败时保留默认圆形容器兜底', async () => {
|
||||
test('运行态没有生成容器时使用透明参考容器兜底', async () => {
|
||||
const run = startLocalMatch3DRun(3);
|
||||
|
||||
renderRuntime(run, []);
|
||||
|
||||
let containerImage!: HTMLImageElement;
|
||||
await waitFor(() => {
|
||||
containerImage = screen.getByTestId(
|
||||
'match3d-container-image',
|
||||
) as HTMLImageElement;
|
||||
expect(containerImage.getAttribute('src')).toBe(
|
||||
'/match3d-background-references/pot-fused-reference.png',
|
||||
);
|
||||
});
|
||||
fireEvent.load(containerImage);
|
||||
expect(screen.getByTestId('match3d-board').className).toContain(
|
||||
'bg-transparent',
|
||||
);
|
||||
expect(screen.getByTestId('match3d-board').className).not.toContain(
|
||||
'rounded-full',
|
||||
);
|
||||
});
|
||||
|
||||
test('容器图换签失败时使用透明参考容器兜底', async () => {
|
||||
const run = startLocalMatch3DRun(3);
|
||||
const generatedItemAssets: Match3DGeneratedItemAsset[] = [
|
||||
{
|
||||
@@ -515,12 +538,17 @@ test('容器图换签失败时保留默认圆形容器兜底', async () => {
|
||||
await waitFor(() => {
|
||||
expect(globalThis.fetch).toHaveBeenCalled();
|
||||
});
|
||||
expect(screen.queryByTestId('match3d-container-image')).toBeNull();
|
||||
await waitFor(() => {
|
||||
expect(
|
||||
screen.getByTestId('match3d-container-image').getAttribute('src'),
|
||||
).toBe('/match3d-background-references/pot-fused-reference.png');
|
||||
});
|
||||
fireEvent.load(screen.getByTestId('match3d-container-image'));
|
||||
expect(screen.getByTestId('match3d-board').className).toContain(
|
||||
'rounded-full',
|
||||
'bg-transparent',
|
||||
);
|
||||
expect(screen.getByTestId('match3d-board').className).not.toContain(
|
||||
'bg-transparent',
|
||||
'rounded-full',
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -108,6 +108,8 @@ function resolveTrayPreviewItem(
|
||||
}
|
||||
|
||||
const DEFAULT_MATCH3D_MUSIC_VOLUME = 0.42;
|
||||
const MATCH3D_CONTAINER_REFERENCE_SRC =
|
||||
'/match3d-background-references/pot-fused-reference.png';
|
||||
|
||||
function formatTimer(value: number) {
|
||||
const totalSeconds = Math.max(0, Math.ceil(value / 1000));
|
||||
@@ -580,7 +582,7 @@ export function Match3DRuntimeShell({
|
||||
)
|
||||
.find(Boolean) ||
|
||||
'';
|
||||
const containerAssetSrc =
|
||||
const generatedContainerAssetSrc =
|
||||
generatedBackgroundAsset?.containerImageSrc?.trim() ||
|
||||
generatedBackgroundAsset?.containerImageObjectKey?.trim() ||
|
||||
runtimeGeneratedItemAssets
|
||||
@@ -591,6 +593,8 @@ export function Match3DRuntimeShell({
|
||||
'',
|
||||
)
|
||||
.find(Boolean) || '';
|
||||
const containerAssetSrc =
|
||||
generatedContainerAssetSrc || MATCH3D_CONTAINER_REFERENCE_SRC;
|
||||
const imageSourcesByType = useMemo(
|
||||
() => buildMatch3DImageSourcesByType(run, runtimeGeneratedItemAssets),
|
||||
[runtimeGeneratedItemAssets, run],
|
||||
@@ -726,12 +730,6 @@ export function Match3DRuntimeShell({
|
||||
}, [backgroundAssetSrc]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!containerAssetSrc) {
|
||||
setResolvedContainerImageSrc('');
|
||||
setIsContainerImageLoaded(false);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let cancelled = false;
|
||||
const controller = new AbortController();
|
||||
setResolvedContainerImageSrc('');
|
||||
@@ -748,7 +746,11 @@ export function Match3DRuntimeShell({
|
||||
})
|
||||
.catch(() => {
|
||||
if (!cancelled) {
|
||||
setResolvedContainerImageSrc('');
|
||||
setResolvedContainerImageSrc(
|
||||
containerAssetSrc === MATCH3D_CONTAINER_REFERENCE_SRC
|
||||
? ''
|
||||
: MATCH3D_CONTAINER_REFERENCE_SRC,
|
||||
);
|
||||
setIsContainerImageLoaded(false);
|
||||
}
|
||||
});
|
||||
@@ -911,7 +913,7 @@ export function Match3DRuntimeShell({
|
||||
style={{
|
||||
boxSizing: 'border-box',
|
||||
maxWidth: '100vw',
|
||||
width: 'min(100vw, 23.5rem)',
|
||||
width: 'min(100vw, 28rem)',
|
||||
}}
|
||||
>
|
||||
<header className="flex items-center justify-between gap-2">
|
||||
@@ -946,7 +948,7 @@ export function Match3DRuntimeShell({
|
||||
: 'overflow-hidden rounded-full border-[10px] border-[#e6d19b] bg-[radial-gradient(circle_at_50%_42%,#f2d993_0%,#c88f43_56%,#835223_100%)] shadow-[inset_0_8px_34px_rgba(72,41,16,0.34),0_22px_42px_rgba(15,23,42,0.28)]'
|
||||
}`}
|
||||
style={{
|
||||
width: 'min(92vw, 58dvh, 100%)',
|
||||
width: 'min(96vw, 60dvh, 100%)',
|
||||
}}
|
||||
onPointerDown={handleBoardPointerDown}
|
||||
data-testid="match3d-board"
|
||||
@@ -956,14 +958,18 @@ export function Match3DRuntimeShell({
|
||||
src={resolvedContainerImageSrc}
|
||||
alt=""
|
||||
aria-hidden="true"
|
||||
className={`pointer-events-none absolute inset-[-8%] z-0 h-[116%] w-[116%] object-contain drop-shadow-[0_22px_42px_rgba(15,23,42,0.28)] ${
|
||||
className={`pointer-events-none absolute inset-[-10%] z-0 h-[120%] w-[120%] object-contain drop-shadow-[0_22px_42px_rgba(15,23,42,0.28)] ${
|
||||
isContainerImageLoaded ? 'opacity-100' : 'opacity-0'
|
||||
}`}
|
||||
data-testid="match3d-container-image"
|
||||
onLoad={() => setIsContainerImageLoaded(true)}
|
||||
onError={() => {
|
||||
setIsContainerImageLoaded(false);
|
||||
setResolvedContainerImageSrc('');
|
||||
setResolvedContainerImageSrc((currentSrc) =>
|
||||
currentSrc && currentSrc !== MATCH3D_CONTAINER_REFERENCE_SRC
|
||||
? MATCH3D_CONTAINER_REFERENCE_SRC
|
||||
: '',
|
||||
);
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
|
||||
Reference in New Issue
Block a user