Preserve partial creation replies on stream failure
Some checks failed
CI / verify (push) Has been cancelled
Some checks failed
CI / verify (push) Has been cancelled
This commit is contained in:
@@ -107,12 +107,17 @@ test('creation hub reflects updated draft title summary and counts after rerende
|
||||
const rpgButton = screen.getByRole('button', { name: /角色扮演/u });
|
||||
const puzzleButton = screen.getByRole('button', { name: /拼图.*创意礼物/u });
|
||||
const match3dButton = screen.getByRole('button', { name: /抓大鹅/u });
|
||||
const squareHoleButton = screen.getByRole('button', { name: /方洞挑战/u });
|
||||
expect(
|
||||
rpgButton.compareDocumentPosition(puzzleButton) &
|
||||
Node.DOCUMENT_POSITION_FOLLOWING,
|
||||
).toBeTruthy();
|
||||
expect((rpgButton as HTMLButtonElement).disabled).toBe(false);
|
||||
expect((match3dButton as HTMLButtonElement).disabled).toBe(false);
|
||||
expect((squareHoleButton as HTMLButtonElement).disabled).toBe(false);
|
||||
expect(
|
||||
within(squareHoleButton).getAllByText('反直觉形状分拣').length,
|
||||
).toBeGreaterThan(0);
|
||||
expect(
|
||||
within(match3dButton).getAllByText('经典消除玩法').length,
|
||||
).toBeGreaterThan(0);
|
||||
|
||||
@@ -4,6 +4,7 @@ import type { BigFishWorkSummary } from '../../../packages/shared/src/contracts/
|
||||
import type { CustomWorldWorkSummary } from '../../../packages/shared/src/contracts/customWorldAgent';
|
||||
import type { Match3DWorkSummary } from '../../../packages/shared/src/contracts/match3dWorks';
|
||||
import type { PuzzleWorkSummary } from '../../../packages/shared/src/contracts/puzzleWorkSummary';
|
||||
import type { SquareHoleWorkSummary } from '../../../packages/shared/src/contracts/squareHoleWorks';
|
||||
import type { CustomWorldLibraryEntry } from '../../../packages/shared/src/contracts/runtime';
|
||||
import type { CustomWorldProfile } from '../../types';
|
||||
import type { PlatformCreationTypeId } from '../platform-entry/platformEntryCreationTypes';
|
||||
@@ -48,6 +49,9 @@ type CustomWorldCreationHubProps = {
|
||||
match3dItems?: Match3DWorkSummary[];
|
||||
onOpenMatch3DDetail?: (item: Match3DWorkSummary) => void;
|
||||
onDeleteMatch3D?: ((item: Match3DWorkSummary) => void) | null;
|
||||
squareHoleItems?: SquareHoleWorkSummary[];
|
||||
onOpenSquareHoleDetail?: (item: SquareHoleWorkSummary) => void;
|
||||
onDeleteSquareHole?: ((item: SquareHoleWorkSummary) => void) | null;
|
||||
puzzleItems?: PuzzleWorkSummary[];
|
||||
onOpenPuzzleDetail?: (item: PuzzleWorkSummary) => void;
|
||||
onDeletePuzzle?: ((item: PuzzleWorkSummary) => void) | null;
|
||||
@@ -137,6 +141,9 @@ export function CustomWorldCreationHub({
|
||||
match3dItems = [],
|
||||
onOpenMatch3DDetail,
|
||||
onDeleteMatch3D = null,
|
||||
squareHoleItems = [],
|
||||
onOpenSquareHoleDetail,
|
||||
onDeleteSquareHole = null,
|
||||
puzzleItems = [],
|
||||
onOpenPuzzleDetail,
|
||||
onDeletePuzzle = null,
|
||||
@@ -152,10 +159,12 @@ export function CustomWorldCreationHub({
|
||||
rpgLibraryEntries,
|
||||
bigFishItems,
|
||||
match3dItems,
|
||||
squareHoleItems,
|
||||
puzzleItems,
|
||||
canDeleteRpg: Boolean(onDeletePublished),
|
||||
canDeleteBigFish: Boolean(onDeleteBigFish),
|
||||
canDeleteMatch3D: Boolean(onDeleteMatch3D),
|
||||
canDeleteSquareHole: Boolean(onDeleteSquareHole),
|
||||
canDeletePuzzle: Boolean(onDeletePuzzle),
|
||||
}),
|
||||
[
|
||||
@@ -164,10 +173,12 @@ export function CustomWorldCreationHub({
|
||||
match3dItems,
|
||||
onDeleteBigFish,
|
||||
onDeleteMatch3D,
|
||||
onDeleteSquareHole,
|
||||
onDeletePublished,
|
||||
onDeletePuzzle,
|
||||
puzzleItems,
|
||||
rpgLibraryEntries,
|
||||
squareHoleItems,
|
||||
],
|
||||
);
|
||||
const [metricSnapshot] = useState<WorkMetricSnapshot>(() =>
|
||||
@@ -201,6 +212,9 @@ export function CustomWorldCreationHub({
|
||||
case 'match3d':
|
||||
onOpenMatch3DDetail?.(item.source.item);
|
||||
return;
|
||||
case 'square-hole':
|
||||
onOpenSquareHoleDetail?.(item.source.item);
|
||||
return;
|
||||
case 'rpg':
|
||||
if (item.status === 'draft') {
|
||||
onOpenDraft(item.source.item);
|
||||
@@ -237,6 +251,12 @@ export function CustomWorldCreationHub({
|
||||
onDeleteMatch3D?.(sourceItem);
|
||||
};
|
||||
}
|
||||
case 'square-hole': {
|
||||
const sourceItem = item.source.item;
|
||||
return () => {
|
||||
onDeleteSquareHole?.(sourceItem);
|
||||
};
|
||||
}
|
||||
case 'rpg': {
|
||||
const sourceItem = item.source.item;
|
||||
return () => {
|
||||
|
||||
@@ -40,7 +40,7 @@ export function CustomWorldCreationStartCard({
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="-mx-1 flex snap-x gap-2 overflow-x-auto px-1 pb-1 scrollbar-hide sm:mx-0 sm:grid sm:gap-3 sm:overflow-visible sm:px-0 sm:pb-0 sm:grid-cols-2 xl:grid-cols-5 xl:gap-2.5">
|
||||
<div className="-mx-1 flex snap-x gap-2 overflow-x-auto px-1 pb-1 scrollbar-hide sm:mx-0 sm:grid sm:gap-3 sm:overflow-visible sm:px-0 sm:pb-0 sm:grid-cols-2 xl:grid-cols-6 xl:gap-2.5">
|
||||
{visibleCreationTypes.map((item) => {
|
||||
const disabled = item.locked || busy;
|
||||
|
||||
|
||||
@@ -2,16 +2,23 @@ import type { BigFishWorkSummary } from '../../../packages/shared/src/contracts/
|
||||
import type { CustomWorldWorkSummary } from '../../../packages/shared/src/contracts/customWorldAgent';
|
||||
import type { Match3DWorkSummary } from '../../../packages/shared/src/contracts/match3dWorks';
|
||||
import type { PuzzleWorkSummary } from '../../../packages/shared/src/contracts/puzzleWorkSummary';
|
||||
import type { SquareHoleWorkSummary } from '../../../packages/shared/src/contracts/squareHoleWorks';
|
||||
import type { CustomWorldLibraryEntry } from '../../../packages/shared/src/contracts/runtime';
|
||||
import { buildPublicWorkStagePath } from '../../routing/appPageRoutes';
|
||||
import {
|
||||
buildBigFishPublicWorkCode,
|
||||
buildMatch3DPublicWorkCode,
|
||||
buildPuzzlePublicWorkCode,
|
||||
buildSquareHolePublicWorkCode,
|
||||
} from '../../services/publicWorkCode';
|
||||
import type { CustomWorldProfile } from '../../types';
|
||||
|
||||
export type CreationWorkShelfKind = 'rpg' | 'big-fish' | 'match3d' | 'puzzle';
|
||||
export type CreationWorkShelfKind =
|
||||
| 'rpg'
|
||||
| 'big-fish'
|
||||
| 'match3d'
|
||||
| 'square-hole'
|
||||
| 'puzzle';
|
||||
export type CreationWorkShelfStatus = 'draft' | 'published';
|
||||
|
||||
export type CreationWorkShelfBadgeTone = 'warm' | 'success' | 'neutral';
|
||||
@@ -56,6 +63,10 @@ export type CreationWorkShelfSource =
|
||||
kind: 'match3d';
|
||||
item: Match3DWorkSummary;
|
||||
}
|
||||
| {
|
||||
kind: 'square-hole';
|
||||
item: SquareHoleWorkSummary;
|
||||
}
|
||||
| {
|
||||
kind: 'puzzle';
|
||||
item: PuzzleWorkSummary;
|
||||
@@ -87,10 +98,12 @@ export function buildCreationWorkShelfItems(params: {
|
||||
rpgLibraryEntries?: CustomWorldLibraryEntry<CustomWorldProfile>[];
|
||||
bigFishItems: BigFishWorkSummary[];
|
||||
match3dItems?: Match3DWorkSummary[];
|
||||
squareHoleItems?: SquareHoleWorkSummary[];
|
||||
puzzleItems: PuzzleWorkSummary[];
|
||||
canDeleteRpg?: boolean;
|
||||
canDeleteBigFish?: boolean;
|
||||
canDeleteMatch3D?: boolean;
|
||||
canDeleteSquareHole?: boolean;
|
||||
canDeletePuzzle?: boolean;
|
||||
}) {
|
||||
const {
|
||||
@@ -98,10 +111,12 @@ export function buildCreationWorkShelfItems(params: {
|
||||
rpgLibraryEntries = [],
|
||||
bigFishItems,
|
||||
match3dItems = [],
|
||||
squareHoleItems = [],
|
||||
puzzleItems,
|
||||
canDeleteRpg = false,
|
||||
canDeleteBigFish = false,
|
||||
canDeleteMatch3D = false,
|
||||
canDeleteSquareHole = false,
|
||||
canDeletePuzzle = false,
|
||||
} = params;
|
||||
|
||||
@@ -115,6 +130,9 @@ export function buildCreationWorkShelfItems(params: {
|
||||
...match3dItems.map((item) =>
|
||||
mapMatch3DWorkToShelfItem(item, canDeleteMatch3D),
|
||||
),
|
||||
...squareHoleItems.map((item) =>
|
||||
mapSquareHoleWorkToShelfItem(item, canDeleteSquareHole),
|
||||
),
|
||||
...puzzleItems.map((item) =>
|
||||
mapPuzzleWorkToShelfItem(item, canDeletePuzzle),
|
||||
),
|
||||
@@ -319,6 +337,50 @@ function mapPuzzleWorkToShelfItem(
|
||||
};
|
||||
}
|
||||
|
||||
function mapSquareHoleWorkToShelfItem(
|
||||
item: SquareHoleWorkSummary,
|
||||
canDelete: boolean,
|
||||
): CreationWorkShelfItem {
|
||||
const status = item.publicationStatus === 'published' ? 'published' : 'draft';
|
||||
const publicWorkCode =
|
||||
status === 'published'
|
||||
? buildSquareHolePublicWorkCode(item.profileId)
|
||||
: null;
|
||||
|
||||
return {
|
||||
id: item.workId,
|
||||
kind: 'square-hole',
|
||||
status,
|
||||
title: item.gameName,
|
||||
summary: item.summary,
|
||||
updatedAt: item.updatedAt,
|
||||
coverImageSrc: item.coverImageSrc ?? null,
|
||||
coverRenderMode: 'image',
|
||||
coverCharacterImageSrcs: [],
|
||||
publicWorkCode,
|
||||
sharePath:
|
||||
publicWorkCode && status === 'published'
|
||||
? buildPublicWorkStagePath('work-detail', publicWorkCode)
|
||||
: null,
|
||||
openActionLabel: status === 'published' ? '查看详情' : '继续创作',
|
||||
canDelete,
|
||||
canShare: status === 'published' && Boolean(publicWorkCode),
|
||||
badges: [
|
||||
buildStatusBadge(status),
|
||||
{ id: 'type', label: '方洞', tone: 'neutral' },
|
||||
],
|
||||
metrics:
|
||||
status === 'published'
|
||||
? buildPublishedMetrics({
|
||||
playCount: item.playCount,
|
||||
remixCount: 0,
|
||||
likeCount: 0,
|
||||
})
|
||||
: [],
|
||||
source: { kind: 'square-hole', item },
|
||||
};
|
||||
}
|
||||
|
||||
function buildPublishedMetrics(params: {
|
||||
playCount?: number | null;
|
||||
remixCount?: number | null;
|
||||
|
||||
Reference in New Issue
Block a user