1
This commit is contained in:
@@ -31,6 +31,7 @@ import type {
|
||||
} from '../../../packages/shared/src/contracts/puzzleAgentSession';
|
||||
import type {
|
||||
PuzzleRunSnapshot,
|
||||
PuzzleRuntimePropKind,
|
||||
SubmitPuzzleLeaderboardRequest,
|
||||
} from '../../../packages/shared/src/contracts/puzzleRuntimeSession';
|
||||
import type { PuzzleWorkSummary } from '../../../packages/shared/src/contracts/puzzleWorkSummary';
|
||||
@@ -39,6 +40,7 @@ import type {
|
||||
CustomWorldLibraryEntry,
|
||||
ProfilePlayedWorkSummary,
|
||||
ProfilePlayStatsResponse,
|
||||
ProfileSaveArchiveSummary,
|
||||
} from '../../../packages/shared/src/contracts/runtime';
|
||||
import { buildCustomWorldPlayableCharacters } from '../../data/characterPresets';
|
||||
import {
|
||||
@@ -111,8 +113,10 @@ import {
|
||||
import {
|
||||
applyLocalPuzzleFreezeTime,
|
||||
dragLocalPuzzlePiece,
|
||||
extendLocalPuzzleTime,
|
||||
isLocalPuzzleRun,
|
||||
refreshLocalPuzzleTimer,
|
||||
restartLocalPuzzleLevel,
|
||||
setLocalPuzzlePaused,
|
||||
startLocalPuzzleRun,
|
||||
submitLocalPuzzleLeaderboard,
|
||||
@@ -128,7 +132,10 @@ import {
|
||||
recordRpgEntryWorldGalleryPlay,
|
||||
remixRpgEntryWorldGallery,
|
||||
} from '../../services/rpg-entry/rpgEntryLibraryClient';
|
||||
import { getRpgProfilePlayStats } from '../../services/rpg-entry/rpgProfileClient';
|
||||
import {
|
||||
getRpgProfilePlayStats,
|
||||
resumeRpgProfileSaveArchive,
|
||||
} from '../../services/rpg-entry/rpgProfileClient';
|
||||
import type { CustomWorldProfile } from '../../types';
|
||||
import { useAuthUi } from '../auth/AuthUiContext';
|
||||
import {
|
||||
@@ -178,6 +185,13 @@ type PuzzleRuntimeReturnStage =
|
||||
|
||||
type BigFishRuntimeReturnStage = 'big-fish-result' | 'work-detail' | 'platform';
|
||||
|
||||
type PuzzleSaveArchiveState = {
|
||||
runtimeKind?: unknown;
|
||||
entryProfileId?: unknown;
|
||||
currentProfileId?: unknown;
|
||||
currentLevelId?: unknown;
|
||||
};
|
||||
|
||||
type AgentResultBlockerView = {
|
||||
code?: string;
|
||||
message: string;
|
||||
@@ -210,7 +224,10 @@ function isSamePlatformPublicGalleryEntry(
|
||||
left: PlatformPublicGalleryCard,
|
||||
right: PlatformPublicGalleryCard,
|
||||
) {
|
||||
return getPlatformPublicGalleryEntryKey(left) === getPlatformPublicGalleryEntryKey(right);
|
||||
return (
|
||||
getPlatformPublicGalleryEntryKey(left) ===
|
||||
getPlatformPublicGalleryEntryKey(right)
|
||||
);
|
||||
}
|
||||
|
||||
function mergePlatformPublicGalleryEntries(
|
||||
@@ -272,6 +289,17 @@ function mapPublicWorkDetailToPuzzleWork(
|
||||
remixCount: entry.remixCount ?? 0,
|
||||
likeCount: entry.likeCount ?? 0,
|
||||
publishReady: true,
|
||||
levels:
|
||||
entry.coverSlides?.map((slide, index) => ({
|
||||
levelId: slide.id || `puzzle-level-${index + 1}`,
|
||||
levelName: slide.label,
|
||||
pictureDescription: entry.summaryText,
|
||||
candidates: [],
|
||||
selectedCandidateId: null,
|
||||
coverImageSrc: slide.imageSrc,
|
||||
coverAssetId: null,
|
||||
generationStatus: 'ready' as const,
|
||||
})) ?? [],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -322,7 +350,9 @@ function mergeBigFishWorkSummary(
|
||||
current: BigFishWorkSummary,
|
||||
updated: BigFishWorkSummary,
|
||||
): BigFishWorkSummary {
|
||||
return current.sourceSessionId === updated.sourceSessionId ? updated : current;
|
||||
return current.sourceSessionId === updated.sourceSessionId
|
||||
? updated
|
||||
: current;
|
||||
}
|
||||
|
||||
async function resolvePublicWorkAuthorSummary(
|
||||
@@ -562,6 +592,22 @@ function isPuzzleFormOnlyDraft(session: PuzzleAgentSessionSnapshot | null) {
|
||||
);
|
||||
}
|
||||
|
||||
function isEmptyPuzzleFormOnlyDraft(
|
||||
session: PuzzleAgentSessionSnapshot | null,
|
||||
) {
|
||||
if (!isPuzzleFormOnlyDraft(session)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const formDraft = session?.draft?.formDraft;
|
||||
return !(
|
||||
session?.seedText?.trim() ||
|
||||
formDraft?.workTitle?.trim() ||
|
||||
formDraft?.workDescription?.trim() ||
|
||||
formDraft?.pictureDescription?.trim()
|
||||
);
|
||||
}
|
||||
|
||||
const CustomWorldGenerationView = lazy(async () => {
|
||||
const module = await import('../CustomWorldGenerationView');
|
||||
return {
|
||||
@@ -665,11 +711,20 @@ function mergePuzzleServiceRuntimeState(
|
||||
? serviceLevel.leaderboardEntries
|
||||
: serviceRun.leaderboardEntries;
|
||||
|
||||
return {
|
||||
...currentRun,
|
||||
leaderboardEntries,
|
||||
currentLevel: {
|
||||
return {
|
||||
...currentRun,
|
||||
recommendedNextProfileId: serviceRun.recommendedNextProfileId,
|
||||
nextLevelMode: serviceRun.nextLevelMode,
|
||||
nextLevelProfileId: serviceRun.nextLevelProfileId,
|
||||
nextLevelId: serviceRun.nextLevelId,
|
||||
recommendedNextWorks: serviceRun.recommendedNextWorks,
|
||||
leaderboardEntries,
|
||||
currentLevel: {
|
||||
...currentRun.currentLevel,
|
||||
status: serviceLevel.status,
|
||||
startedAtMs: serviceLevel.startedAtMs,
|
||||
clearedAtMs: serviceLevel.clearedAtMs,
|
||||
elapsedMs: serviceLevel.elapsedMs,
|
||||
timeLimitMs: serviceLevel.timeLimitMs,
|
||||
remainingMs: serviceLevel.remainingMs,
|
||||
pausedAccumulatedMs: serviceLevel.pausedAccumulatedMs,
|
||||
@@ -1338,7 +1393,10 @@ export function PlatformEntryFlowShellImpl({
|
||||
const createPuzzleDraftFromForm = useCallback(
|
||||
async (payload: CreatePuzzleAgentSessionRequest) => {
|
||||
setPuzzleFormDraftPayload(payload);
|
||||
const nextSession = puzzleFlow.session ?? (await puzzleFlow.openWorkspace(payload));
|
||||
const nextSession =
|
||||
puzzleFlow.session && !isEmptyPuzzleFormOnlyDraft(puzzleFlow.session)
|
||||
? puzzleFlow.session
|
||||
: await puzzleFlow.openWorkspace(payload);
|
||||
if (!nextSession) {
|
||||
return;
|
||||
}
|
||||
@@ -1504,6 +1562,35 @@ export function PlatformEntryFlowShellImpl({
|
||||
|
||||
const executePuzzleAction = puzzleFlow.executeAction;
|
||||
|
||||
const retryPuzzleDraftGeneration = useCallback(() => {
|
||||
if (puzzleFormDraftPayload) {
|
||||
void createPuzzleDraftFromForm(puzzleFormDraftPayload);
|
||||
return;
|
||||
}
|
||||
|
||||
void executePuzzleAction(
|
||||
buildPuzzleCompileActionFromFormPayload(puzzleFormDraftPayload),
|
||||
);
|
||||
}, [createPuzzleDraftFromForm, executePuzzleAction, puzzleFormDraftPayload]);
|
||||
|
||||
const executePuzzleWorkspaceAction = useCallback(
|
||||
(payload: PuzzleAgentActionRequest) => {
|
||||
if (
|
||||
payload.action === 'compile_puzzle_draft' &&
|
||||
isEmptyPuzzleFormOnlyDraft(puzzleFlow.session)
|
||||
) {
|
||||
const formPayload = buildPuzzleFormPayloadFromAction(payload);
|
||||
if (formPayload) {
|
||||
void createPuzzleDraftFromForm(formPayload);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void executePuzzleAction(payload);
|
||||
},
|
||||
[createPuzzleDraftFromForm, executePuzzleAction, puzzleFlow.session],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (selectionStage === 'big-fish-result' && !bigFishSession?.draft) {
|
||||
setSelectionStage(
|
||||
@@ -1655,6 +1742,7 @@ export function PlatformEntryFlowShellImpl({
|
||||
remixCount: 0,
|
||||
likeCount: 0,
|
||||
publishReady: Boolean(puzzleSession?.resultPreview?.publishReady),
|
||||
levels: draft.levels,
|
||||
} satisfies PuzzleWorkSummary;
|
||||
},
|
||||
[
|
||||
@@ -1782,7 +1870,9 @@ export function PlatformEntryFlowShellImpl({
|
||||
paused,
|
||||
});
|
||||
setPuzzleRun((currentRun) =>
|
||||
currentRun ? mergePuzzleServiceRuntimeState(currentRun, run) : currentRun,
|
||||
currentRun
|
||||
? mergePuzzleServiceRuntimeState(currentRun, run)
|
||||
: currentRun,
|
||||
);
|
||||
void platformBootstrap.refreshProfileDashboard();
|
||||
} catch (error) {
|
||||
@@ -1812,7 +1902,9 @@ export function PlatformEntryFlowShellImpl({
|
||||
try {
|
||||
const { run } = await getPuzzleRun(puzzleRun.runId);
|
||||
setPuzzleRun((currentRun) =>
|
||||
currentRun ? mergePuzzleServiceRuntimeState(currentRun, run) : currentRun,
|
||||
currentRun
|
||||
? mergePuzzleServiceRuntimeState(currentRun, run)
|
||||
: currentRun,
|
||||
);
|
||||
} catch (error) {
|
||||
setPuzzleError(
|
||||
@@ -1822,11 +1914,13 @@ export function PlatformEntryFlowShellImpl({
|
||||
}, [puzzleRun, resolvePuzzleErrorMessage, setPuzzleError]);
|
||||
|
||||
const usePuzzleProp = useCallback(
|
||||
async (propKind: 'hint' | 'reference' | 'freezeTime') => {
|
||||
if (
|
||||
!puzzleRun?.currentLevel ||
|
||||
puzzleRun.currentLevel.status !== 'playing'
|
||||
) {
|
||||
async (propKind: PuzzleRuntimePropKind) => {
|
||||
if (!puzzleRun?.currentLevel) {
|
||||
return null;
|
||||
}
|
||||
const expectedStatus =
|
||||
propKind === 'extendTime' ? 'failed' : 'playing';
|
||||
if (puzzleRun.currentLevel.status !== expectedStatus) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1836,7 +1930,9 @@ export function PlatformEntryFlowShellImpl({
|
||||
return null;
|
||||
}
|
||||
const nextRun =
|
||||
propKind === 'freezeTime'
|
||||
propKind === 'extendTime'
|
||||
? extendLocalPuzzleTime(currentRun)
|
||||
: propKind === 'freezeTime'
|
||||
? applyLocalPuzzleFreezeTime(currentRun)
|
||||
: setLocalPuzzlePaused(currentRun, propKind === 'reference');
|
||||
puzzleRunRef.current = nextRun;
|
||||
@@ -1859,6 +1955,92 @@ export function PlatformEntryFlowShellImpl({
|
||||
[platformBootstrap, puzzleRun],
|
||||
);
|
||||
|
||||
const restartPuzzleCurrentLevel = useCallback(async () => {
|
||||
const currentLevel = puzzleRun?.currentLevel ?? null;
|
||||
if (!puzzleRun || !currentLevel || isPuzzleBusy) {
|
||||
return;
|
||||
}
|
||||
|
||||
setPuzzleError(null);
|
||||
if (isLocalPuzzleRun(puzzleRun)) {
|
||||
const nextRun = restartLocalPuzzleLevel(puzzleRunRef.current ?? puzzleRun);
|
||||
puzzleRunRef.current = nextRun;
|
||||
setPuzzleRun(nextRun);
|
||||
return;
|
||||
}
|
||||
|
||||
await startPuzzleRunFromProfile(
|
||||
currentLevel.profileId,
|
||||
puzzleRuntimeReturnStage,
|
||||
selectedPuzzleDetail?.profileId === currentLevel.profileId
|
||||
? selectedPuzzleDetail
|
||||
: undefined,
|
||||
false,
|
||||
currentLevel.levelId ?? null,
|
||||
);
|
||||
}, [
|
||||
isPuzzleBusy,
|
||||
puzzleRun,
|
||||
puzzleRuntimeReturnStage,
|
||||
selectedPuzzleDetail,
|
||||
setPuzzleError,
|
||||
startPuzzleRunFromProfile,
|
||||
]);
|
||||
|
||||
const resumePuzzleSaveArchive = useCallback(
|
||||
async (entry: ProfileSaveArchiveSummary) => {
|
||||
if (isPuzzleBusy) {
|
||||
return;
|
||||
}
|
||||
|
||||
setIsPuzzleBusy(true);
|
||||
setPuzzleError(null);
|
||||
platformBootstrap.setSaveError(null);
|
||||
|
||||
try {
|
||||
const resumedArchive = await resumeRpgProfileSaveArchive(
|
||||
entry.worldKey,
|
||||
);
|
||||
platformBootstrap.setSaveEntries((currentEntries) =>
|
||||
currentEntries.map((currentEntry) =>
|
||||
currentEntry.worldKey === resumedArchive.entry.worldKey
|
||||
? resumedArchive.entry
|
||||
: currentEntry,
|
||||
),
|
||||
);
|
||||
const gameState = resumedArchive.snapshot
|
||||
.gameState as PuzzleSaveArchiveState;
|
||||
const profileId =
|
||||
typeof gameState.currentProfileId === 'string' &&
|
||||
gameState.currentProfileId.trim()
|
||||
? gameState.currentProfileId
|
||||
: typeof gameState.entryProfileId === 'string' &&
|
||||
gameState.entryProfileId.trim()
|
||||
? gameState.entryProfileId
|
||||
: (entry.profileId ?? entry.worldKey.replace(/^puzzle:/u, ''));
|
||||
const levelId =
|
||||
typeof gameState.currentLevelId === 'string' &&
|
||||
gameState.currentLevelId.trim()
|
||||
? gameState.currentLevelId
|
||||
: null;
|
||||
await startPuzzleRunFromProfile(profileId, 'platform', undefined, false, levelId);
|
||||
} catch (error) {
|
||||
platformBootstrap.setSaveError(
|
||||
resolvePuzzleErrorMessage(error, '恢复拼图存档失败。'),
|
||||
);
|
||||
} finally {
|
||||
setIsPuzzleBusy(false);
|
||||
}
|
||||
},
|
||||
[
|
||||
isPuzzleBusy,
|
||||
platformBootstrap,
|
||||
resolvePuzzleErrorMessage,
|
||||
setPuzzleError,
|
||||
startPuzzleRunFromProfile,
|
||||
],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const currentLevel = puzzleRun?.currentLevel ?? null;
|
||||
if (!puzzleRun || !currentLevel || currentLevel.status !== 'cleared') {
|
||||
@@ -1916,7 +2098,10 @@ export function PlatformEntryFlowShellImpl({
|
||||
setPuzzleError,
|
||||
]);
|
||||
|
||||
const advancePuzzleLevel = useCallback(async () => {
|
||||
const advancePuzzleLevel = useCallback(async (target?: {
|
||||
profileId?: string;
|
||||
levelId?: string | null;
|
||||
}) => {
|
||||
if (!puzzleRun || isPuzzleBusy || isPuzzleLeaderboardBusy) {
|
||||
return;
|
||||
}
|
||||
@@ -1931,6 +2116,21 @@ export function PlatformEntryFlowShellImpl({
|
||||
setPuzzleError(null);
|
||||
|
||||
try {
|
||||
const targetProfileId = target?.profileId?.trim();
|
||||
if (
|
||||
targetProfileId &&
|
||||
targetProfileId !== currentLevel.profileId &&
|
||||
puzzleRun.nextLevelMode === 'similarWorks'
|
||||
) {
|
||||
await startPuzzleRunFromProfile(
|
||||
targetProfileId,
|
||||
'puzzle-gallery-detail',
|
||||
undefined,
|
||||
false,
|
||||
null,
|
||||
);
|
||||
return;
|
||||
}
|
||||
const { run } = isLocalPuzzleRun(puzzleRun)
|
||||
? await advanceLocalPuzzleNextLevel({
|
||||
run: puzzleRun,
|
||||
@@ -1954,6 +2154,7 @@ export function PlatformEntryFlowShellImpl({
|
||||
puzzleSession,
|
||||
resolvePuzzleErrorMessage,
|
||||
selectedPuzzleDetail,
|
||||
startPuzzleRunFromProfile,
|
||||
]);
|
||||
|
||||
const leaveAgentWorkspace = useCallback(() => {
|
||||
@@ -2262,24 +2463,27 @@ export function PlatformEntryFlowShellImpl({
|
||||
return;
|
||||
}
|
||||
setBigFishGalleryEntries((current) =>
|
||||
current.map((item) => mergeBigFishWorkSummary(item, updatedWork)),
|
||||
current.map((item) =>
|
||||
mergeBigFishWorkSummary(item, updatedWork),
|
||||
),
|
||||
);
|
||||
setBigFishWorks((current) =>
|
||||
current.map((item) => mergeBigFishWorkSummary(item, updatedWork)),
|
||||
current.map((item) =>
|
||||
mergeBigFishWorkSummary(item, updatedWork),
|
||||
),
|
||||
);
|
||||
syncUpdatedPublicWorkDetail(
|
||||
mapBigFishWorkToPublicWorkDetail(updatedWork),
|
||||
);
|
||||
setBigFishRuntimeWork((current) =>
|
||||
current ? mergeBigFishWorkSummary(current, updatedWork) : current,
|
||||
current
|
||||
? mergeBigFishWorkSummary(current, updatedWork)
|
||||
: current,
|
||||
);
|
||||
})
|
||||
.catch((error) => {
|
||||
setPublicWorkDetailError(
|
||||
resolveBigFishErrorMessage(
|
||||
error,
|
||||
'点赞大鱼吃小鱼作品失败。',
|
||||
),
|
||||
resolveBigFishErrorMessage(error, '点赞大鱼吃小鱼作品失败。'),
|
||||
);
|
||||
})
|
||||
.finally(() => {
|
||||
@@ -2293,13 +2497,19 @@ export function PlatformEntryFlowShellImpl({
|
||||
.then((response) => {
|
||||
const updatedWork = response.item;
|
||||
setPuzzleGalleryEntries((current) =>
|
||||
current.map((item) => mergePuzzleWorkSummary(item, updatedWork)),
|
||||
current.map((item) =>
|
||||
mergePuzzleWorkSummary(item, updatedWork),
|
||||
),
|
||||
);
|
||||
setPuzzleWorks((current) =>
|
||||
current.map((item) => mergePuzzleWorkSummary(item, updatedWork)),
|
||||
current.map((item) =>
|
||||
mergePuzzleWorkSummary(item, updatedWork),
|
||||
),
|
||||
);
|
||||
setSelectedPuzzleDetail((current) =>
|
||||
current ? mergePuzzleWorkSummary(current, updatedWork) : current,
|
||||
current
|
||||
? mergePuzzleWorkSummary(current, updatedWork)
|
||||
: current,
|
||||
);
|
||||
syncUpdatedPublicWorkDetail(
|
||||
mapPuzzleWorkToPublicWorkDetail(updatedWork),
|
||||
@@ -2319,13 +2529,13 @@ export function PlatformEntryFlowShellImpl({
|
||||
void likeRpgEntryWorldGallery(entry.ownerUserId, entry.profileId)
|
||||
.then((updatedEntry) => {
|
||||
setSelectedDetailEntry((current) =>
|
||||
current?.profileId === updatedEntry.profileId ? updatedEntry : current,
|
||||
current?.profileId === updatedEntry.profileId
|
||||
? updatedEntry
|
||||
: current,
|
||||
);
|
||||
platformBootstrap.setPublishedGalleryEntries((current) =>
|
||||
current.map((item) =>
|
||||
item.profileId === updatedEntry.profileId
|
||||
? mapRpgGalleryCardToPublicWorkDetail(updatedEntry)
|
||||
: item,
|
||||
item.profileId === updatedEntry.profileId ? updatedEntry : item,
|
||||
),
|
||||
);
|
||||
syncUpdatedPublicWorkDetail(
|
||||
@@ -3186,6 +3396,13 @@ export function PlatformEntryFlowShellImpl({
|
||||
createTabContent={creationHubContent}
|
||||
onContinueGame={handleContinueGame}
|
||||
onResumeSave={(entry) => {
|
||||
if (
|
||||
(entry.worldType ?? '').toLowerCase() === 'puzzle' ||
|
||||
entry.worldKey.startsWith('puzzle:')
|
||||
) {
|
||||
void resumePuzzleSaveArchive(entry);
|
||||
return;
|
||||
}
|
||||
void platformBootstrap.handleResumeSaveEntry(entry);
|
||||
}}
|
||||
onOpenCreateWorld={openCreationTypePicker}
|
||||
@@ -3286,7 +3503,9 @@ export function PlatformEntryFlowShellImpl({
|
||||
<PlatformWorkDetailView
|
||||
entry={mapRpgGalleryCardToPublicWorkDetail(selectedDetailEntry)}
|
||||
authorAvatarUrl={selectedPublicWorkAuthor?.avatarUrl ?? null}
|
||||
authorDisplayName={selectedPublicWorkAuthor?.displayName ?? null}
|
||||
authorDisplayName={
|
||||
selectedPublicWorkAuthor?.displayName ?? null
|
||||
}
|
||||
isBusy={detailNavigation.isMutatingDetail}
|
||||
error={detailNavigation.detailError}
|
||||
onBack={() => {
|
||||
@@ -3568,7 +3787,7 @@ export function PlatformEntryFlowShellImpl({
|
||||
void submitPuzzleMessage(payload);
|
||||
}}
|
||||
onExecuteAction={(payload) => {
|
||||
void executePuzzleAction(payload);
|
||||
executePuzzleWorkspaceAction(payload);
|
||||
}}
|
||||
initialFormPayload={puzzleFormDraftPayload}
|
||||
onCreateFromForm={(payload) => {
|
||||
@@ -3610,13 +3829,7 @@ export function PlatformEntryFlowShellImpl({
|
||||
onEditSetting={() => {
|
||||
setSelectionStage('puzzle-agent-workspace');
|
||||
}}
|
||||
onRetry={() => {
|
||||
void executePuzzleAction(
|
||||
buildPuzzleCompileActionFromFormPayload(
|
||||
puzzleFormDraftPayload,
|
||||
),
|
||||
);
|
||||
}}
|
||||
onRetry={retryPuzzleDraftGeneration}
|
||||
onInterrupt={undefined}
|
||||
backLabel="返回创作中心"
|
||||
settingActionLabel={null}
|
||||
@@ -3635,35 +3848,35 @@ export function PlatformEntryFlowShellImpl({
|
||||
{selectionStage === 'puzzle-result' &&
|
||||
puzzleSession?.draft &&
|
||||
!isPuzzleFormOnlyDraft(puzzleSession) && (
|
||||
<motion.div
|
||||
key="puzzle-result"
|
||||
initial={{ opacity: 0, y: 12 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, y: -12 }}
|
||||
className="flex h-full min-h-0 flex-col"
|
||||
>
|
||||
<Suspense
|
||||
fallback={<LazyPanelFallback label="正在加载拼图结果..." />}
|
||||
<motion.div
|
||||
key="puzzle-result"
|
||||
initial={{ opacity: 0, y: 12 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, y: -12 }}
|
||||
className="flex h-full min-h-0 flex-col"
|
||||
>
|
||||
<PuzzleResultView
|
||||
session={puzzleSession}
|
||||
profileId={
|
||||
puzzleSession.publishedProfileId ??
|
||||
buildPuzzleResultProfileId(puzzleSession.sessionId)
|
||||
}
|
||||
isBusy={isPuzzleBusy}
|
||||
error={puzzleError}
|
||||
onBack={() => {
|
||||
setSelectionStage('puzzle-agent-workspace');
|
||||
}}
|
||||
onExecuteAction={(payload) => {
|
||||
void executePuzzleAction(payload);
|
||||
}}
|
||||
onStartTestRun={startPuzzleTestRunFromDraft}
|
||||
/>
|
||||
</Suspense>
|
||||
</motion.div>
|
||||
)}
|
||||
<Suspense
|
||||
fallback={<LazyPanelFallback label="正在加载拼图结果..." />}
|
||||
>
|
||||
<PuzzleResultView
|
||||
session={puzzleSession}
|
||||
profileId={
|
||||
puzzleSession.publishedProfileId ??
|
||||
buildPuzzleResultProfileId(puzzleSession.sessionId)
|
||||
}
|
||||
isBusy={isPuzzleBusy}
|
||||
error={puzzleError}
|
||||
onBack={() => {
|
||||
setSelectionStage('puzzle-agent-workspace');
|
||||
}}
|
||||
onExecuteAction={(payload) => {
|
||||
void executePuzzleAction(payload);
|
||||
}}
|
||||
onStartTestRun={startPuzzleTestRunFromDraft}
|
||||
/>
|
||||
</Suspense>
|
||||
</motion.div>
|
||||
)}
|
||||
|
||||
{selectionStage === 'puzzle-gallery-detail' && selectedPuzzleDetail && (
|
||||
<motion.div
|
||||
@@ -3737,8 +3950,11 @@ export function PlatformEntryFlowShellImpl({
|
||||
onDragPiece={(payload) => {
|
||||
void dragPuzzlePiece(payload);
|
||||
}}
|
||||
onAdvanceNextLevel={() => {
|
||||
void advancePuzzleLevel();
|
||||
onAdvanceNextLevel={(target) => {
|
||||
void advancePuzzleLevel(target);
|
||||
}}
|
||||
onRestartLevel={() => {
|
||||
void restartPuzzleCurrentLevel();
|
||||
}}
|
||||
onPauseChange={setPuzzleRuntimePaused}
|
||||
onUseProp={usePuzzleProp}
|
||||
|
||||
Reference in New Issue
Block a user