This commit is contained in:
2026-04-25 22:19:04 +08:00
parent 2ebfd1cf55
commit 8404081d7b
149 changed files with 10508 additions and 2732 deletions

View File

@@ -59,7 +59,7 @@ import {
getPuzzleAgentSession,
streamPuzzleAgentMessage,
} from '../../services/puzzle-agent';
import { getPuzzleGalleryDetail } from '../../services/puzzle-gallery';
import { getPuzzleGalleryDetail, listPuzzleGallery } from '../../services/puzzle-gallery';
import {
advanceLocalPuzzleLevel,
dragLocalPuzzlePiece,
@@ -82,6 +82,11 @@ import { useRpgCreationAgentOperationPolling } from '../rpg-entry/useRpgCreation
import { useRpgCreationEnterWorld } from '../rpg-entry/useRpgCreationEnterWorld';
import { useRpgCreationResultAutosave } from '../rpg-entry/useRpgCreationResultAutosave';
import { useRpgCreationSessionController } from '../rpg-entry/useRpgCreationSessionController';
import {
isPuzzleGalleryEntry,
mapPuzzleWorkToPlatformGalleryCard,
type PlatformPublicGalleryCard,
} from '../rpg-entry/rpgEntryWorldPresentation';
import { PlatformEntryCreationTypeModal } from './PlatformEntryCreationTypeModal';
import { PlatformEntryHomeView } from './PlatformEntryHomeView';
import {
@@ -93,6 +98,7 @@ import type { PlatformCreationTypeId } from './platformEntryCreationTypes';
import type { PlatformEntryFlowShellProps } from './platformEntryTypes';
import { PlatformEntryWorldDetailView } from './PlatformEntryWorldDetailView';
import { usePlatformEntryBootstrap } from './usePlatformEntryBootstrap';
import { usePlatformCreationAgentFlowController } from './usePlatformCreationAgentFlowController';
import { usePlatformEntryLibraryDetail } from './usePlatformEntryLibraryDetail';
import { usePlatformEntryNavigation } from './usePlatformEntryNavigation';
@@ -114,6 +120,33 @@ const AGENT_RESULT_STRUCTURAL_BLOCKER_CODES = new Set([
'publish_missing_first_act',
]);
function getPlatformPublicGalleryEntryTime(entry: PlatformPublicGalleryCard) {
const rawTime = entry.publishedAt ?? entry.updatedAt;
const timestamp = new Date(rawTime).getTime();
return Number.isNaN(timestamp) ? 0 : timestamp;
}
function getPlatformPublicGalleryEntryKey(entry: PlatformPublicGalleryCard) {
return `${isPuzzleGalleryEntry(entry) ? 'puzzle' : 'rpg'}:${entry.ownerUserId}:${entry.profileId}`;
}
function mergePlatformPublicGalleryEntries(
rpgEntries: CustomWorldGalleryCard[],
puzzleEntries: PlatformPublicGalleryCard[],
) {
const entryMap = new Map<string, PlatformPublicGalleryCard>();
[...rpgEntries, ...puzzleEntries].forEach((entry) => {
entryMap.set(getPlatformPublicGalleryEntryKey(entry), entry);
});
return Array.from(entryMap.values()).sort(
(left, right) =>
getPlatformPublicGalleryEntryTime(right) -
getPlatformPublicGalleryEntryTime(left),
);
}
function readProfileTextField(
profile: CustomWorldProfile | null,
paths: string[],
@@ -304,28 +337,20 @@ export function PlatformEntryFlowShellImpl({
const [showCreationTypeModal, setShowCreationTypeModal] = useState(false);
const [selectedDetailEntry, setSelectedDetailEntry] =
useState<CustomWorldLibraryEntry<CustomWorldProfile> | null>(null);
const [bigFishSession, setBigFishSession] =
useState<BigFishSessionSnapshotResponse | null>(null);
const [bigFishWorks, setBigFishWorks] = useState<BigFishWorkSummary[]>([]);
const [bigFishRun, setBigFishRun] =
useState<BigFishRuntimeSnapshotResponse | null>(null);
const [bigFishError, setBigFishError] = useState<string | null>(null);
const [isBigFishBusy, setIsBigFishBusy] = useState(false);
const [isBigFishLoadingLibrary, setIsBigFishLoadingLibrary] = useState(false);
const [streamingBigFishReplyText, setStreamingBigFishReplyText] =
useState('');
const [isStreamingBigFishReply, setIsStreamingBigFishReply] = useState(false);
const bigFishInputInFlightRef = useRef(false);
const [puzzleSession, setPuzzleSession] =
useState<PuzzleAgentSessionSnapshot | null>(null);
const [puzzleOperation, setPuzzleOperation] =
useState<PuzzleAgentOperationRecord | null>(null);
const [puzzleWorks, setPuzzleWorks] = useState<PuzzleWorkSummary[]>([]);
const [puzzleGalleryEntries, setPuzzleGalleryEntries] = useState<
PuzzleWorkSummary[]
>([]);
const [selectedPuzzleDetail, setSelectedPuzzleDetail] =
useState<PuzzleWorkSummary | null>(null);
const [puzzleRun, setPuzzleRun] = useState<PuzzleRunSnapshot | null>(null);
const [puzzleError, setPuzzleError] = useState<string | null>(null);
const [isPuzzleBusy, setIsPuzzleBusy] = useState(false);
const [isPuzzleLoadingLibrary, setIsPuzzleLoadingLibrary] = useState(false);
const [isSearchingPublicCode, setIsSearchingPublicCode] = useState(false);
const [publicSearchError, setPublicSearchError] = useState<string | null>(null);
@@ -334,8 +359,6 @@ export function PlatformEntryFlowShellImpl({
const [deletingCreationWorkId, setDeletingCreationWorkId] = useState<
string | null
>(null);
const [streamingPuzzleReplyText, setStreamingPuzzleReplyText] = useState('');
const [isStreamingPuzzleReply, setIsStreamingPuzzleReply] = useState(false);
const hasInitialAgentSession = Boolean(
readCustomWorldAgentUiState().activeSessionId,
);
@@ -359,6 +382,17 @@ export function PlatformEntryFlowShellImpl({
setPlatformTab('create');
}, [setPlatformTab]);
const resolveBigFishErrorMessage = useCallback(
(error: unknown, fallback: string) =>
resolveRpgCreationErrorMessage(error, fallback),
[],
);
const resolvePuzzleErrorMessage = useCallback(
(error: unknown, fallback: string) =>
resolveRpgCreationErrorMessage(error, fallback),
[],
);
const sessionController = useRpgCreationSessionController({
userId: authUi?.user?.id,
openLoginModal: authUi?.openLoginModal,
@@ -441,10 +475,18 @@ export function PlatformEntryFlowShellImpl({
agentSessionProfile: sessionController.agentDraftResultProfile,
agentSession: sessionController.agentSession,
handleCustomWorldSelect,
executePublishWorld: () =>
autosaveCoordinator.executeAgentActionAndWait({
executePublishWorld: async () => {
const latestSession = await autosaveCoordinator.executeAgentActionAndWait({
action: 'publish_world',
}),
});
// 发布动作会在后端同步 gallery 投影;前端发布完成后立即刷新首页/分类页共用的公开作品列表。
await Promise.allSettled([
platformBootstrap.refreshPublishedGallery(),
platformBootstrap.refreshCustomWorldWorks(),
refreshPuzzleGallery(),
]);
return latestSession;
},
setGeneratedCustomWorldProfile:
sessionController.setGeneratedCustomWorldProfile,
});
@@ -495,8 +537,24 @@ export function PlatformEntryFlowShellImpl({
}, [agentResultPreview]);
const featuredGalleryEntries = useMemo(
() => platformBootstrap.publishedGalleryEntries.slice(0, 6),
[platformBootstrap.publishedGalleryEntries],
() => {
const puzzlePublicEntries = puzzleGalleryEntries.map(
mapPuzzleWorkToPlatformGalleryCard,
);
return mergePlatformPublicGalleryEntries(
platformBootstrap.publishedGalleryEntries,
puzzlePublicEntries,
).slice(0, 6);
},
[platformBootstrap.publishedGalleryEntries, puzzleGalleryEntries],
);
const latestGalleryEntries = useMemo(
() =>
mergePlatformPublicGalleryEntries(
platformBootstrap.publishedGalleryEntries,
puzzleGalleryEntries.map(mapPuzzleWorkToPlatformGalleryCard),
),
[platformBootstrap.publishedGalleryEntries, puzzleGalleryEntries],
);
const creationHubItems =
@@ -523,17 +581,6 @@ export function PlatformEntryFlowShellImpl({
setSelectionStage,
]);
useEffect(() => {
if (selectionStage === 'big-fish-result' && !bigFishSession?.draft) {
setSelectionStage(
bigFishSession ? 'big-fish-agent-workspace' : 'platform',
);
}
if (selectionStage === 'big-fish-runtime' && !bigFishRun) {
setSelectionStage(bigFishSession?.draft ? 'big-fish-result' : 'platform');
}
}, [bigFishRun, bigFishSession, selectionStage, setSelectionStage]);
const runProtectedAction = useCallback(
(action: () => void) => {
if (!authUi?.requireAuth) {
@@ -647,17 +694,6 @@ export function PlatformEntryFlowShellImpl({
setShowCreationTypeModal(true);
}, [prepareCreationLaunch]);
const resolveBigFishErrorMessage = useCallback(
(error: unknown, fallback: string) =>
resolveRpgCreationErrorMessage(error, fallback),
[],
);
const resolvePuzzleErrorMessage = useCallback(
(error: unknown, fallback: string) =>
resolveRpgCreationErrorMessage(error, fallback),
[],
);
const refreshBigFishShelf = useCallback(async () => {
setIsBigFishLoadingLibrary(true);
@@ -690,64 +726,144 @@ export function PlatformEntryFlowShellImpl({
}
}, [resolvePuzzleErrorMessage]);
const openBigFishAgentWorkspace = useCallback(async () => {
if (isBigFishBusy) {
return;
}
setIsBigFishBusy(true);
setBigFishError(null);
setBigFishRun(null);
const refreshPuzzleGallery = useCallback(async () => {
try {
const { session } = await createBigFishCreationSession({});
setBigFishSession(session);
enterCreateTab();
setShowCreationTypeModal(false);
setSelectionStage('big-fish-agent-workspace');
const galleryResponse = await listPuzzleGallery();
setPuzzleGalleryEntries(galleryResponse.items);
return galleryResponse.items;
} catch (error) {
setBigFishError(
resolveBigFishErrorMessage(error, '开启大鱼吃小鱼共创工作台失败。'),
setPuzzleGalleryEntries([]);
setPuzzleError(
resolvePuzzleErrorMessage(error, '读取拼图广场失败。'),
);
} finally {
setIsBigFishBusy(false);
return [];
}
}, [
}, [resolvePuzzleErrorMessage]);
const bigFishFlow = usePlatformCreationAgentFlowController<
BigFishSessionSnapshotResponse,
Record<string, never>,
{ session: BigFishSessionSnapshotResponse },
SendBigFishMessageRequest,
ExecuteBigFishActionRequest,
{ session: BigFishSessionSnapshotResponse }
>({
client: {
createSession: createBigFishCreationSession,
getSession: getBigFishCreationSession,
streamMessage: streamBigFishCreationMessage,
executeAction: executeBigFishCreationAction,
selectSession: (response) => response.session,
},
createPayload: {},
workspaceStage: 'big-fish-agent-workspace',
resultStage: 'big-fish-result',
platformStage: 'platform',
isCompileAction: (payload) => payload.action === 'big_fish_compile_draft',
resolveErrorMessage: resolveBigFishErrorMessage,
errorMessages: {
open: '开启大鱼吃小鱼共创工作台失败。',
restoreMissingSession: '这份大鱼吃小鱼草稿缺少会话信息,请重新开始创作。',
restore: '读取大鱼吃小鱼创作草稿失败。',
submit: '发送大鱼吃小鱼共创消息失败。',
execute: '执行大鱼吃小鱼操作失败。',
},
enterCreateTab,
isBigFishBusy,
resolveBigFishErrorMessage,
setSelectionStage,
]);
onSessionOpened: () => {
setShowCreationTypeModal(false);
},
onActionComplete: ({ response, setSession }) => {
setSession(response.session);
},
});
const puzzleFlow = usePlatformCreationAgentFlowController<
PuzzleAgentSessionSnapshot,
Record<string, never>,
{ session: PuzzleAgentSessionSnapshot },
SendPuzzleAgentMessageRequest,
PuzzleAgentActionRequest,
{ operation: PuzzleAgentOperationRecord }
>({
client: {
createSession: createPuzzleAgentSession,
getSession: getPuzzleAgentSession,
streamMessage: streamPuzzleAgentMessage,
executeAction: executePuzzleAgentAction,
selectSession: (response) => response.session,
},
createPayload: {},
workspaceStage: 'puzzle-agent-workspace',
resultStage: 'puzzle-result',
platformStage: 'platform',
isCompileAction: (payload) => payload.action === 'compile_puzzle_draft',
resolveErrorMessage: resolvePuzzleErrorMessage,
errorMessages: {
open: '开启拼图共创工作台失败。',
restoreMissingSession: '这份拼图草稿缺少会话信息,请重新开始创作。',
restore: '读取拼图创作草稿失败。',
submit: '发送拼图共创消息失败。',
execute: '执行拼图操作失败。',
},
enterCreateTab,
setSelectionStage,
onSessionOpened: () => {
setShowCreationTypeModal(false);
},
onActionComplete: async ({ payload, response, session, setSession }) => {
setPuzzleOperation(response.operation);
if (payload.action === 'publish_puzzle_work') {
await Promise.allSettled([
refreshPuzzleShelf(),
refreshPuzzleGallery(),
]);
}
const latestResponse = await getPuzzleAgentSession(session.sessionId);
const latestSession = latestResponse.session;
setSession(latestSession);
if (
payload.action === 'publish_puzzle_work' &&
latestSession.publishedProfileId
) {
const galleryDetail = await getPuzzleGalleryDetail(
latestSession.publishedProfileId,
);
setSelectedPuzzleDetail(galleryDetail.item);
setSelectionStage('puzzle-gallery-detail');
}
},
});
const bigFishSession = bigFishFlow.session;
const bigFishError = bigFishFlow.error;
const setBigFishError = bigFishFlow.setError;
const isBigFishBusy = bigFishFlow.isBusy;
const setIsBigFishBusy = bigFishFlow.setIsBusy;
const streamingBigFishReplyText = bigFishFlow.streamingReplyText;
const isStreamingBigFishReply = bigFishFlow.isStreamingReply;
const puzzleSession = puzzleFlow.session;
const puzzleError = puzzleFlow.error;
const setPuzzleError = puzzleFlow.setError;
const isPuzzleBusy = puzzleFlow.isBusy;
const setIsPuzzleBusy = puzzleFlow.setIsBusy;
const streamingPuzzleReplyText = puzzleFlow.streamingReplyText;
const isStreamingPuzzleReply = puzzleFlow.isStreamingReply;
const openBigFishAgentWorkspace = useCallback(async () => {
setBigFishRun(null);
await bigFishFlow.openWorkspace();
}, [bigFishFlow]);
const openPuzzleAgentWorkspace = useCallback(async () => {
if (isPuzzleBusy) {
return;
}
setIsPuzzleBusy(true);
setPuzzleError(null);
setPuzzleRun(null);
setPuzzleOperation(null);
try {
const { session } = await createPuzzleAgentSession({});
setPuzzleSession(session);
enterCreateTab();
setShowCreationTypeModal(false);
setSelectionStage('puzzle-agent-workspace');
} catch (error) {
setPuzzleError(
resolvePuzzleErrorMessage(error, '开启拼图共创工作台失败。'),
);
} finally {
setIsPuzzleBusy(false);
}
}, [
enterCreateTab,
isPuzzleBusy,
resolvePuzzleErrorMessage,
setSelectionStage,
]);
await puzzleFlow.openWorkspace();
}, [puzzleFlow]);
const handleCreationHubCreateType = useCallback(
(type: PlatformCreationTypeId) => {
@@ -789,206 +905,34 @@ export function PlatformEntryFlowShellImpl({
);
const leaveBigFishFlow = useCallback(() => {
setBigFishError(null);
setBigFishRun(null);
setStreamingBigFishReplyText('');
setIsStreamingBigFishReply(false);
enterCreateTab();
setSelectionStage('platform');
}, [enterCreateTab, setSelectionStage]);
bigFishFlow.leaveFlow();
}, [bigFishFlow]);
const leavePuzzleFlow = useCallback(() => {
setPuzzleError(null);
setPuzzleOperation(null);
setPuzzleRun(null);
setStreamingPuzzleReplyText('');
setIsStreamingPuzzleReply(false);
enterCreateTab();
setSelectionStage('platform');
}, [enterCreateTab, setSelectionStage]);
puzzleFlow.leaveFlow();
}, [puzzleFlow]);
const submitBigFishMessage = useCallback(
async (payload: SendBigFishMessageRequest) => {
if (!bigFishSession || isStreamingBigFishReply) {
return;
}
const submitBigFishMessage = bigFishFlow.submitMessage;
const optimisticMessage = {
id: payload.clientMessageId,
role: 'user',
kind: 'chat',
text: payload.text.trim(),
createdAt: new Date().toISOString(),
};
const submitPuzzleMessage = puzzleFlow.submitMessage;
setBigFishError(null);
setStreamingBigFishReplyText('');
setIsStreamingBigFishReply(true);
setBigFishSession((current) =>
current
? {
...current,
messages: [...current.messages, optimisticMessage],
updatedAt: optimisticMessage.createdAt,
}
: current,
const executeBigFishAction = bigFishFlow.executeAction;
const executePuzzleAction = puzzleFlow.executeAction;
useEffect(() => {
if (selectionStage === 'big-fish-result' && !bigFishSession?.draft) {
setSelectionStage(
bigFishSession ? 'big-fish-agent-workspace' : 'platform',
);
try {
const nextSession = await streamBigFishCreationMessage(
bigFishSession.sessionId,
payload,
{
onUpdate: setStreamingBigFishReplyText,
},
);
setBigFishSession(nextSession);
setStreamingBigFishReplyText('');
} catch (error) {
setBigFishError(
resolveBigFishErrorMessage(error, '发送大鱼吃小鱼共创消息失败。'),
);
} finally {
setIsStreamingBigFishReply(false);
}
},
[bigFishSession, isStreamingBigFishReply, resolveBigFishErrorMessage],
);
const submitPuzzleMessage = useCallback(
async (payload: SendPuzzleAgentMessageRequest) => {
if (!puzzleSession || isStreamingPuzzleReply) {
return;
}
const optimisticMessage = {
id: payload.clientMessageId,
role: 'user',
kind: 'chat',
text: payload.text.trim(),
createdAt: new Date().toISOString(),
} satisfies PuzzleAgentSessionSnapshot['messages'][number];
setPuzzleError(null);
setStreamingPuzzleReplyText('');
setIsStreamingPuzzleReply(true);
setPuzzleSession((current) =>
current
? {
...current,
messages: [...current.messages, optimisticMessage],
updatedAt: optimisticMessage.createdAt,
}
: current,
);
try {
const nextSession = await streamPuzzleAgentMessage(
puzzleSession.sessionId,
payload,
{
onUpdate: setStreamingPuzzleReplyText,
},
);
setPuzzleSession(nextSession);
setStreamingPuzzleReplyText('');
} catch (error) {
setPuzzleError(
resolvePuzzleErrorMessage(error, '发送拼图共创消息失败。'),
);
} finally {
setIsStreamingPuzzleReply(false);
}
},
[isStreamingPuzzleReply, puzzleSession, resolvePuzzleErrorMessage],
);
const executeBigFishAction = useCallback(
async (payload: ExecuteBigFishActionRequest) => {
if (!bigFishSession || isBigFishBusy) {
return;
}
setIsBigFishBusy(true);
setBigFishError(null);
try {
const { session } = await executeBigFishCreationAction(
bigFishSession.sessionId,
payload,
);
setBigFishSession(session);
if (payload.action === 'big_fish_compile_draft') {
setSelectionStage('big-fish-result');
}
} catch (error) {
setBigFishError(
resolveBigFishErrorMessage(error, '执行大鱼吃小鱼操作失败。'),
);
} finally {
setIsBigFishBusy(false);
}
},
[
bigFishSession,
isBigFishBusy,
resolveBigFishErrorMessage,
setSelectionStage,
],
);
const executePuzzleAction = useCallback(
async (payload: PuzzleAgentActionRequest) => {
if (!puzzleSession || isPuzzleBusy) {
return;
}
setIsPuzzleBusy(true);
setPuzzleError(null);
try {
const { operation } = await executePuzzleAgentAction(
puzzleSession.sessionId,
payload,
);
setPuzzleOperation(operation);
if (payload.action === 'publish_puzzle_work') {
await refreshPuzzleShelf();
}
const { session } = await getPuzzleAgentSession(
puzzleSession.sessionId,
);
setPuzzleSession(session);
if (payload.action === 'compile_puzzle_draft') {
setSelectionStage('puzzle-result');
}
if (
payload.action === 'publish_puzzle_work' &&
session.publishedProfileId
) {
const galleryDetail = await getPuzzleGalleryDetail(
session.publishedProfileId,
);
setSelectedPuzzleDetail(galleryDetail.item);
setSelectionStage('puzzle-gallery-detail');
}
} catch (error) {
setPuzzleError(resolvePuzzleErrorMessage(error, '执行拼图操作失败。'));
} finally {
setIsPuzzleBusy(false);
}
},
[
isPuzzleBusy,
puzzleSession,
refreshPuzzleShelf,
resolvePuzzleErrorMessage,
setSelectionStage,
],
);
}
if (selectionStage === 'big-fish-runtime' && !bigFishRun) {
setSelectionStage(bigFishSession?.draft ? 'big-fish-result' : 'platform');
}
}, [bigFishRun, bigFishSession, selectionStage, setSelectionStage]);
const startBigFishRun = useCallback(async () => {
if (!bigFishSession || isBigFishBusy) {
@@ -1327,6 +1271,7 @@ export function PlatformEntryFlowShellImpl({
void deletePuzzleWork(work.profileId)
.then((response) => {
setPuzzleWorks(response.items);
void refreshPuzzleGallery();
})
.catch((error) => {
setPuzzleError(resolvePuzzleErrorMessage(error, '删除拼图作品失败。'));
@@ -1336,7 +1281,12 @@ export function PlatformEntryFlowShellImpl({
});
});
},
[deletingCreationWorkId, resolvePuzzleErrorMessage, runProtectedAction],
[
deletingCreationWorkId,
refreshPuzzleGallery,
resolvePuzzleErrorMessage,
runProtectedAction,
],
);
const openPuzzleDetail = useCallback(
@@ -1360,80 +1310,28 @@ export function PlatformEntryFlowShellImpl({
const openPuzzleDraft = useCallback(
async (item: PuzzleWorkSummary) => {
const sessionId = item.sourceSessionId?.trim();
if (!sessionId) {
setPuzzleError('这份拼图草稿缺少会话信息,请重新开始创作。');
return;
}
setIsPuzzleBusy(true);
setPuzzleError(null);
setPuzzleOperation(null);
setPuzzleRun(null);
setSelectedPuzzleDetail(null);
setStreamingPuzzleReplyText('');
setIsStreamingPuzzleReply(false);
try {
const { session } = await getPuzzleAgentSession(sessionId);
setPuzzleSession(session);
enterCreateTab();
setSelectionStage(session.draft ? 'puzzle-result' : 'puzzle-agent-workspace');
} catch (error) {
const restoredSession = await puzzleFlow.restoreDraft(item.sourceSessionId);
if (!restoredSession) {
await refreshPuzzleShelf().catch(() => undefined);
setPuzzleError(resolvePuzzleErrorMessage(error, '读取拼图创作草稿失败。'));
enterCreateTab();
setSelectionStage('platform');
} finally {
setIsPuzzleBusy(false);
}
},
[
enterCreateTab,
refreshPuzzleShelf,
resolvePuzzleErrorMessage,
setSelectionStage,
],
[puzzleFlow, refreshPuzzleShelf],
);
const openBigFishDraft = useCallback(
async (item: BigFishWorkSummary) => {
const sessionId = item.sourceSessionId?.trim();
if (!sessionId) {
setBigFishError('这份大鱼吃小鱼草稿缺少会话信息,请重新开始创作。');
return;
}
setIsBigFishBusy(true);
setBigFishError(null);
setBigFishRun(null);
setStreamingBigFishReplyText('');
setIsStreamingBigFishReply(false);
try {
const { session } = await getBigFishCreationSession(sessionId);
setBigFishSession(session);
enterCreateTab();
setSelectionStage(
session.draft ? 'big-fish-result' : 'big-fish-agent-workspace',
);
} catch (error) {
const restoredSession = await bigFishFlow.restoreDraft(
item.sourceSessionId,
);
if (!restoredSession) {
await refreshBigFishShelf().catch(() => undefined);
setBigFishError(
resolveBigFishErrorMessage(error, '读取大鱼吃小鱼创作草稿失败。'),
);
enterCreateTab();
setSelectionStage('platform');
} finally {
setIsBigFishBusy(false);
}
},
[
enterCreateTab,
refreshBigFishShelf,
resolveBigFishErrorMessage,
setSelectionStage,
],
[bigFishFlow, refreshBigFishShelf],
);
const startBigFishRunFromWork = useCallback(
@@ -1450,7 +1348,7 @@ export function PlatformEntryFlowShellImpl({
try {
const { session } = await getBigFishCreationSession(sessionId);
const { run } = await startBigFishRuntimeRun(sessionId);
setBigFishSession(session);
bigFishFlow.setSession(session);
setBigFishRun(run);
setSelectionStage('big-fish-runtime');
} catch (error) {
@@ -1461,9 +1359,15 @@ export function PlatformEntryFlowShellImpl({
setIsBigFishBusy(false);
}
},
[resolveBigFishErrorMessage, setSelectionStage],
[bigFishFlow, resolveBigFishErrorMessage, setSelectionStage],
);
useEffect(() => {
if (selectionStage === 'platform') {
void refreshPuzzleGallery();
}
}, [refreshPuzzleGallery, selectionStage]);
useEffect(() => {
if (
(platformBootstrap.platformTab === 'create' ||
@@ -1610,7 +1514,7 @@ export function PlatformEntryFlowShellImpl({
saveEntries={platformBootstrap.saveEntries}
saveError={platformBootstrap.saveError}
featuredEntries={featuredGalleryEntries}
latestEntries={platformBootstrap.publishedGalleryEntries}
latestEntries={latestGalleryEntries}
myEntries={platformBootstrap.savedCustomWorldEntries}
historyEntries={platformBootstrap.historyEntries}
profileDashboard={platformBootstrap.profileDashboard}
@@ -1636,6 +1540,11 @@ export function PlatformEntryFlowShellImpl({
onOpenCreateWorld={openCreationTypePicker}
onOpenCreateTypePicker={openCreationTypePicker}
onOpenGalleryDetail={(entry) => {
if (isPuzzleGalleryEntry(entry)) {
void openPuzzleDetail(entry.profileId);
return;
}
runProtectedAction(() => {
void detailNavigation.openGalleryDetail(entry);
});
@@ -1658,6 +1567,7 @@ export function PlatformEntryFlowShellImpl({
void platformBootstrap.refreshProfileDashboard();
}
}}
onRechargeSuccess={platformBootstrap.refreshProfileDashboard}
/>
</motion.div>
)}
@@ -1788,6 +1698,7 @@ export function PlatformEntryFlowShellImpl({
<BigFishAgentWorkspace
session={bigFishSession}
streamingReplyText={streamingBigFishReplyText}
isStreamingReply={isStreamingBigFishReply}
isBusy={isBigFishBusy || isStreamingBigFishReply}
error={bigFishError}
onBack={leaveBigFishFlow}
@@ -1871,6 +1782,7 @@ export function PlatformEntryFlowShellImpl({
session={puzzleSession}
activeOperation={puzzleOperation}
streamingReplyText={streamingPuzzleReplyText}
isStreamingReply={isStreamingPuzzleReply}
isBusy={isPuzzleBusy || isStreamingPuzzleReply}
error={puzzleError}
onBack={leavePuzzleFlow}
@@ -1985,7 +1897,7 @@ export function PlatformEntryFlowShellImpl({
onInterrupt={undefined}
backLabel="返回工作区"
settingActionLabel={null}
retryLabel="重新生成草稿"
retryLabel="继续生成草稿"
settingTitle="当前世界信息"
settingDescription={null}
progressTitle="世界草稿生成进度"
@@ -2024,26 +1936,7 @@ export function PlatformEntryFlowShellImpl({
onBack={
sessionController.isAgentDraftResultView
? () => {
void (async () => {
const currentProfile =
sessionController.generatedCustomWorldProfile;
if (!currentProfile) {
leaveAgentDraftResult();
return;
}
await autosaveCoordinator.syncAgentDraftResultProfile(
currentProfile,
);
leaveAgentDraftResult();
})().catch((error) => {
sessionController.setCustomWorldError(
resolveRpgCreationErrorMessage(
error,
'返回创作前同步草稿失败。',
),
);
});
leaveAgentDraftResult();
}
: leaveCustomWorldResult
}