1
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { AnimatePresence, motion } from 'motion/react';
|
||||
import { Loader2 } from 'lucide-react';
|
||||
import { AnimatePresence, motion } from 'motion/react';
|
||||
import {
|
||||
lazy,
|
||||
Suspense,
|
||||
@@ -9,6 +10,7 @@ import {
|
||||
useState,
|
||||
} from 'react';
|
||||
|
||||
import type { PublicUserSummary } from '../../../packages/shared/src/contracts/auth';
|
||||
import type {
|
||||
BigFishRuntimeSnapshotResponse,
|
||||
BigFishSessionSnapshotResponse,
|
||||
@@ -31,7 +33,6 @@ import type {
|
||||
CustomWorldGalleryCard,
|
||||
CustomWorldLibraryEntry,
|
||||
} from '../../../packages/shared/src/contracts/runtime';
|
||||
import type { PublicUserSummary } from '../../../packages/shared/src/contracts/auth';
|
||||
import { buildCustomWorldPlayableCharacters } from '../../data/characterPresets';
|
||||
import {
|
||||
getPublicAuthUserByCode,
|
||||
@@ -43,15 +44,22 @@ import {
|
||||
getBigFishCreationSession,
|
||||
streamBigFishCreationMessage,
|
||||
} from '../../services/big-fish-creation';
|
||||
import {
|
||||
deleteBigFishWork,
|
||||
listBigFishWorks,
|
||||
} from '../../services/big-fish-works';
|
||||
import {
|
||||
startBigFishRuntimeRun,
|
||||
submitBigFishRuntimeInput,
|
||||
} from '../../services/big-fish-runtime';
|
||||
import {
|
||||
deleteBigFishWork,
|
||||
listBigFishWorks,
|
||||
} from '../../services/big-fish-works';
|
||||
import { readCustomWorldAgentUiState } from '../../services/customWorldAgentUiState';
|
||||
import {
|
||||
buildBigFishGenerationAnchorEntries,
|
||||
buildMiniGameDraftGenerationProgress,
|
||||
buildPuzzleGenerationAnchorEntries,
|
||||
createMiniGameDraftGenerationState,
|
||||
type MiniGameDraftGenerationState,
|
||||
} from '../../services/miniGameDraftGenerationProgress';
|
||||
import { getPlatformProfileDashboard } from '../../services/platform-entry';
|
||||
import {
|
||||
createPuzzleAgentSession,
|
||||
@@ -60,17 +68,17 @@ import {
|
||||
streamPuzzleAgentMessage,
|
||||
} from '../../services/puzzle-agent';
|
||||
import { getPuzzleGalleryDetail, listPuzzleGallery } from '../../services/puzzle-gallery';
|
||||
import { advanceLocalPuzzleNextLevel } from '../../services/puzzle-runtime';
|
||||
import {
|
||||
advanceLocalPuzzleLevel,
|
||||
dragLocalPuzzlePiece,
|
||||
startLocalPuzzleRun,
|
||||
swapLocalPuzzlePieces,
|
||||
} from '../../services/puzzle-runtime/puzzleLocalRuntime';
|
||||
import { deletePuzzleWork, listPuzzleWorks } from '../../services/puzzle-works';
|
||||
import { deleteRpgEntryWorldProfile } from '../../services/rpg-entry';
|
||||
import { getRpgEntryWorldGalleryDetailByCode } from '../../services/rpg-entry/rpgEntryLibraryClient';
|
||||
import { deleteRpgCreationAgentSession } from '../../services/rpg-creation';
|
||||
import { rpgCreationPreviewAdapter } from '../../services/rpg-creation/rpgCreationPreviewAdapter';
|
||||
import { deleteRpgEntryWorldProfile } from '../../services/rpg-entry';
|
||||
import { getRpgEntryWorldGalleryDetailByCode } from '../../services/rpg-entry/rpgEntryLibraryClient';
|
||||
import type { CustomWorldProfile } from '../../types';
|
||||
import { useAuthUi } from '../auth/AuthUiContext';
|
||||
import { CustomWorldCreationHub } from '../custom-world-home/CustomWorldCreationHub';
|
||||
@@ -88,13 +96,13 @@ import {
|
||||
type PlatformPublicGalleryCard,
|
||||
} from '../rpg-entry/rpgEntryWorldPresentation';
|
||||
import { PlatformEntryCreationTypeModal } from './PlatformEntryCreationTypeModal';
|
||||
import type { PlatformCreationTypeId } from './platformEntryCreationTypes';
|
||||
import { PlatformEntryHomeView } from './PlatformEntryHomeView';
|
||||
import {
|
||||
buildCreationHubFallbackItems,
|
||||
normalizeAgentBackedProfile,
|
||||
resolveRpgCreationErrorMessage,
|
||||
} from './platformEntryShared';
|
||||
import type { PlatformCreationTypeId } from './platformEntryCreationTypes';
|
||||
import type { PlatformEntryFlowShellProps } from './platformEntryTypes';
|
||||
import { PlatformEntryWorldDetailView } from './PlatformEntryWorldDetailView';
|
||||
import { usePlatformEntryBootstrap } from './usePlatformEntryBootstrap';
|
||||
@@ -341,6 +349,8 @@ export function PlatformEntryFlowShellImpl({
|
||||
const [bigFishRun, setBigFishRun] =
|
||||
useState<BigFishRuntimeSnapshotResponse | null>(null);
|
||||
const [isBigFishLoadingLibrary, setIsBigFishLoadingLibrary] = useState(false);
|
||||
const [bigFishGenerationState, setBigFishGenerationState] =
|
||||
useState<MiniGameDraftGenerationState | null>(null);
|
||||
const bigFishInputInFlightRef = useRef(false);
|
||||
const [puzzleOperation, setPuzzleOperation] =
|
||||
useState<PuzzleAgentOperationRecord | null>(null);
|
||||
@@ -352,6 +362,10 @@ export function PlatformEntryFlowShellImpl({
|
||||
useState<PuzzleWorkSummary | null>(null);
|
||||
const [puzzleRun, setPuzzleRun] = useState<PuzzleRunSnapshot | null>(null);
|
||||
const [isPuzzleLoadingLibrary, setIsPuzzleLoadingLibrary] = useState(false);
|
||||
const [puzzleGenerationState, setPuzzleGenerationState] =
|
||||
useState<MiniGameDraftGenerationState | null>(null);
|
||||
const [isPuzzleNextLevelGenerating, setIsPuzzleNextLevelGenerating] =
|
||||
useState(false);
|
||||
const [isSearchingPublicCode, setIsSearchingPublicCode] = useState(false);
|
||||
const [publicSearchError, setPublicSearchError] = useState<string | null>(null);
|
||||
const [searchedPublicUser, setSearchedPublicUser] =
|
||||
@@ -773,8 +787,44 @@ export function PlatformEntryFlowShellImpl({
|
||||
onSessionOpened: () => {
|
||||
setShowCreationTypeModal(false);
|
||||
},
|
||||
onActionComplete: ({ response, setSession }) => {
|
||||
onActionComplete: ({ payload, response, setSession }) => {
|
||||
setSession(response.session);
|
||||
if (payload.action !== 'big_fish_compile_draft') {
|
||||
return;
|
||||
}
|
||||
setBigFishGenerationState((current) =>
|
||||
current
|
||||
? {
|
||||
...current,
|
||||
phase: 'ready',
|
||||
completedAssetCount: response.session.assetSlots.filter(
|
||||
(slot) => slot.status === 'ready',
|
||||
).length,
|
||||
totalAssetCount: response.session.assetSlots.length,
|
||||
}
|
||||
: current,
|
||||
);
|
||||
},
|
||||
beforeExecuteAction: ({ payload }) => {
|
||||
if (payload.action !== 'big_fish_compile_draft') {
|
||||
return;
|
||||
}
|
||||
setSelectionStage('big-fish-generating');
|
||||
setBigFishGenerationState(createMiniGameDraftGenerationState('big-fish'));
|
||||
},
|
||||
onActionError: ({ payload, errorMessage }) => {
|
||||
if (payload.action !== 'big_fish_compile_draft') {
|
||||
return;
|
||||
}
|
||||
setBigFishGenerationState((current) =>
|
||||
current
|
||||
? {
|
||||
...current,
|
||||
phase: 'failed',
|
||||
error: errorMessage,
|
||||
}
|
||||
: current,
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -784,7 +834,7 @@ export function PlatformEntryFlowShellImpl({
|
||||
{ session: PuzzleAgentSessionSnapshot },
|
||||
SendPuzzleAgentMessageRequest,
|
||||
PuzzleAgentActionRequest,
|
||||
{ operation: PuzzleAgentOperationRecord }
|
||||
{ operation: PuzzleAgentOperationRecord; session: PuzzleAgentSessionSnapshot }
|
||||
>({
|
||||
client: {
|
||||
createSession: createPuzzleAgentSession,
|
||||
@@ -811,8 +861,9 @@ export function PlatformEntryFlowShellImpl({
|
||||
onSessionOpened: () => {
|
||||
setShowCreationTypeModal(false);
|
||||
},
|
||||
onActionComplete: async ({ payload, response, session, setSession }) => {
|
||||
onActionComplete: async ({ payload, response, setSession }) => {
|
||||
setPuzzleOperation(response.operation);
|
||||
setSession(response.session);
|
||||
|
||||
if (payload.action === 'publish_puzzle_work') {
|
||||
await Promise.allSettled([
|
||||
@@ -821,21 +872,51 @@ export function PlatformEntryFlowShellImpl({
|
||||
]);
|
||||
}
|
||||
|
||||
const latestResponse = await getPuzzleAgentSession(session.sessionId);
|
||||
const latestSession = latestResponse.session;
|
||||
setSession(latestSession);
|
||||
if (payload.action === 'compile_puzzle_draft') {
|
||||
setPuzzleGenerationState((current) =>
|
||||
current
|
||||
? {
|
||||
...current,
|
||||
phase: 'ready',
|
||||
completedAssetCount: 1,
|
||||
totalAssetCount: 1,
|
||||
}
|
||||
: current,
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
payload.action === 'publish_puzzle_work' &&
|
||||
latestSession.publishedProfileId
|
||||
response.session.publishedProfileId
|
||||
) {
|
||||
const galleryDetail = await getPuzzleGalleryDetail(
|
||||
latestSession.publishedProfileId,
|
||||
response.session.publishedProfileId,
|
||||
);
|
||||
setSelectedPuzzleDetail(galleryDetail.item);
|
||||
setSelectionStage('puzzle-gallery-detail');
|
||||
}
|
||||
},
|
||||
beforeExecuteAction: ({ payload }) => {
|
||||
if (payload.action !== 'compile_puzzle_draft') {
|
||||
return;
|
||||
}
|
||||
setSelectionStage('puzzle-generating');
|
||||
setPuzzleGenerationState(createMiniGameDraftGenerationState('puzzle'));
|
||||
},
|
||||
onActionError: ({ payload, errorMessage }) => {
|
||||
if (payload.action !== 'compile_puzzle_draft') {
|
||||
return;
|
||||
}
|
||||
setPuzzleGenerationState((current) =>
|
||||
current
|
||||
? {
|
||||
...current,
|
||||
phase: 'failed',
|
||||
error: errorMessage,
|
||||
}
|
||||
: current,
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
const bigFishSession = bigFishFlow.session;
|
||||
@@ -906,12 +987,15 @@ export function PlatformEntryFlowShellImpl({
|
||||
|
||||
const leaveBigFishFlow = useCallback(() => {
|
||||
setBigFishRun(null);
|
||||
setBigFishGenerationState(null);
|
||||
bigFishFlow.leaveFlow();
|
||||
}, [bigFishFlow]);
|
||||
|
||||
const leavePuzzleFlow = useCallback(() => {
|
||||
setPuzzleOperation(null);
|
||||
setPuzzleRun(null);
|
||||
setPuzzleGenerationState(null);
|
||||
setIsPuzzleNextLevelGenerating(false);
|
||||
puzzleFlow.leaveFlow();
|
||||
}, [puzzleFlow]);
|
||||
|
||||
@@ -1039,9 +1123,35 @@ export function PlatformEntryFlowShellImpl({
|
||||
return;
|
||||
}
|
||||
|
||||
const currentLevel = puzzleRun.currentLevel;
|
||||
if (!currentLevel || currentLevel.status !== 'cleared') {
|
||||
return;
|
||||
}
|
||||
|
||||
setIsPuzzleBusy(true);
|
||||
setIsPuzzleNextLevelGenerating(true);
|
||||
setPuzzleError(null);
|
||||
setPuzzleRun(advanceLocalPuzzleLevel(puzzleRun));
|
||||
}, [isPuzzleBusy, puzzleRun]);
|
||||
|
||||
try {
|
||||
const { run } = await advanceLocalPuzzleNextLevel({
|
||||
run: puzzleRun,
|
||||
sourceSessionId:
|
||||
selectedPuzzleDetail?.sourceSessionId ?? puzzleSession?.sessionId ?? null,
|
||||
});
|
||||
setPuzzleRun(run);
|
||||
} catch (error) {
|
||||
setPuzzleError(resolvePuzzleErrorMessage(error, '准备下一关失败。'));
|
||||
} finally {
|
||||
setIsPuzzleNextLevelGenerating(false);
|
||||
setIsPuzzleBusy(false);
|
||||
}
|
||||
}, [
|
||||
isPuzzleBusy,
|
||||
puzzleRun,
|
||||
puzzleSession,
|
||||
resolvePuzzleErrorMessage,
|
||||
selectedPuzzleDetail,
|
||||
]);
|
||||
|
||||
const leaveAgentWorkspace = useCallback(() => {
|
||||
enterCreateTab();
|
||||
@@ -1713,6 +1823,49 @@ export function PlatformEntryFlowShellImpl({
|
||||
</motion.div>
|
||||
)}
|
||||
|
||||
{selectionStage === 'big-fish-generating' && (
|
||||
<motion.div
|
||||
key="big-fish-generating"
|
||||
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="正在加载大鱼吃小鱼生成面板..." />}
|
||||
>
|
||||
<CustomWorldGenerationView
|
||||
settingText={
|
||||
bigFishSession?.lastAssistantReply ?? '正在整理当前玩法草稿。'
|
||||
}
|
||||
anchorEntries={buildBigFishGenerationAnchorEntries(bigFishSession)}
|
||||
progress={buildMiniGameDraftGenerationProgress(
|
||||
bigFishGenerationState,
|
||||
)}
|
||||
isGenerating={isBigFishBusy}
|
||||
error={bigFishError}
|
||||
onBack={leaveBigFishFlow}
|
||||
onEditSetting={() => {
|
||||
setSelectionStage('big-fish-agent-workspace');
|
||||
}}
|
||||
onRetry={() => {
|
||||
void executeBigFishAction({ action: 'big_fish_compile_draft' });
|
||||
}}
|
||||
onInterrupt={undefined}
|
||||
backLabel="返回创作中心"
|
||||
settingActionLabel={null}
|
||||
retryLabel="重新生成草稿"
|
||||
settingTitle="当前玩法信息"
|
||||
settingDescription={null}
|
||||
progressTitle="大鱼吃小鱼草稿生成进度"
|
||||
activeBadgeLabel="草稿生成中"
|
||||
pausedBadgeLabel="草稿生成已暂停"
|
||||
idleBadgeLabel="等待返回工作区"
|
||||
/>
|
||||
</Suspense>
|
||||
</motion.div>
|
||||
)}
|
||||
|
||||
{selectionStage === 'big-fish-result' && bigFishSession?.draft && (
|
||||
<motion.div
|
||||
key="big-fish-result"
|
||||
@@ -1796,6 +1949,49 @@ export function PlatformEntryFlowShellImpl({
|
||||
</motion.div>
|
||||
)}
|
||||
|
||||
{selectionStage === 'puzzle-generating' && (
|
||||
<motion.div
|
||||
key="puzzle-generating"
|
||||
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="正在加载拼图生成面板..." />}
|
||||
>
|
||||
<CustomWorldGenerationView
|
||||
settingText={
|
||||
puzzleSession?.lastAssistantReply ?? '正在整理当前拼图草稿。'
|
||||
}
|
||||
anchorEntries={buildPuzzleGenerationAnchorEntries(puzzleSession)}
|
||||
progress={buildMiniGameDraftGenerationProgress(
|
||||
puzzleGenerationState,
|
||||
)}
|
||||
isGenerating={isPuzzleBusy}
|
||||
error={puzzleError}
|
||||
onBack={leavePuzzleFlow}
|
||||
onEditSetting={() => {
|
||||
setSelectionStage('puzzle-agent-workspace');
|
||||
}}
|
||||
onRetry={() => {
|
||||
void executePuzzleAction({ action: 'compile_puzzle_draft' });
|
||||
}}
|
||||
onInterrupt={undefined}
|
||||
backLabel="返回创作中心"
|
||||
settingActionLabel={null}
|
||||
retryLabel="重新生成草稿"
|
||||
settingTitle="当前拼图信息"
|
||||
settingDescription={null}
|
||||
progressTitle="拼图草稿生成进度"
|
||||
activeBadgeLabel="草稿生成中"
|
||||
pausedBadgeLabel="草稿生成已暂停"
|
||||
idleBadgeLabel="等待返回工作区"
|
||||
/>
|
||||
</Suspense>
|
||||
</motion.div>
|
||||
)}
|
||||
|
||||
{selectionStage === 'puzzle-result' && puzzleSession?.draft && (
|
||||
<motion.div
|
||||
key="puzzle-result"
|
||||
@@ -1852,7 +2048,7 @@ export function PlatformEntryFlowShellImpl({
|
||||
>
|
||||
<PuzzleRuntimeShell
|
||||
run={puzzleRun}
|
||||
isBusy={isPuzzleBusy}
|
||||
isBusy={isPuzzleBusy || isPuzzleNextLevelGenerating}
|
||||
error={puzzleError}
|
||||
onBack={() => {
|
||||
setSelectionStage('puzzle-gallery-detail');
|
||||
@@ -1867,6 +2063,17 @@ export function PlatformEntryFlowShellImpl({
|
||||
void advancePuzzleLevel();
|
||||
}}
|
||||
/>
|
||||
{isPuzzleNextLevelGenerating ? (
|
||||
<div className="fixed inset-0 z-[120] flex items-center justify-center bg-slate-950/62 px-5 backdrop-blur-sm">
|
||||
<div className="flex max-w-[18rem] flex-col items-center gap-3 rounded-[1.5rem] border border-white/12 bg-slate-950/92 px-6 py-5 text-center text-white shadow-[0_28px_80px_rgba(0,0,0,0.35)]">
|
||||
<Loader2 className="h-6 w-6 animate-spin text-amber-200" />
|
||||
<div className="text-sm font-bold">正在准备下一关</div>
|
||||
<div className="text-xs leading-5 text-white/68">
|
||||
广场暂无可接续作品,正在生成新的候选图。
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
</motion.div>
|
||||
)}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user