1
This commit is contained in:
@@ -162,7 +162,10 @@ import {
|
||||
listMatch3DGallery,
|
||||
listMatch3DWorks,
|
||||
} from '../../services/match3d-works';
|
||||
import { preloadMatch3DGeneratedModelAssets } from '../../services/match3dGeneratedModelCache';
|
||||
import {
|
||||
hasMatch3DGeneratedImageAsset,
|
||||
preloadMatch3DGeneratedRuntimeAssets,
|
||||
} from '../../services/match3dGeneratedModelCache';
|
||||
import {
|
||||
buildBabyObjectMatchGenerationAnchorEntries,
|
||||
buildBigFishGenerationAnchorEntries,
|
||||
@@ -359,6 +362,18 @@ type PendingDraftShelfMap = Partial<
|
||||
Record<string, PendingDraftShelfState>
|
||||
>
|
||||
>;
|
||||
type Match3DBackgroundCompileTask = {
|
||||
session: Match3DAgentSessionSnapshot;
|
||||
payload: CreateMatch3DSessionRequest;
|
||||
generationState: MiniGameDraftGenerationState;
|
||||
error: string | null;
|
||||
};
|
||||
type PuzzleBackgroundCompileTask = {
|
||||
session: PuzzleAgentSessionSnapshot;
|
||||
payload: CreatePuzzleAgentSessionRequest;
|
||||
generationState: MiniGameDraftGenerationState;
|
||||
error: string | null;
|
||||
};
|
||||
|
||||
type PuzzleDetailReturnTarget = {
|
||||
tab: PlatformHomeTab;
|
||||
@@ -667,14 +682,10 @@ function buildMatch3DProfileFromSession(
|
||||
};
|
||||
}
|
||||
|
||||
function hasMatch3DGeneratedModelAsset(
|
||||
function hasMatch3DRuntimeAsset(
|
||||
assets: readonly Match3DGeneratedItemAsset[] | null | undefined,
|
||||
) {
|
||||
return Boolean(
|
||||
assets?.some(
|
||||
(asset) => asset.modelSrc?.trim() || asset.modelObjectKey?.trim(),
|
||||
),
|
||||
);
|
||||
return hasMatch3DGeneratedImageAsset(assets);
|
||||
}
|
||||
|
||||
function resolveMatch3DRuntimeGeneratedItemAssets(
|
||||
@@ -690,7 +701,7 @@ function resolveMatch3DRuntimeGeneratedItemAssets(
|
||||
: [];
|
||||
|
||||
if (runProfileId && profile?.profileId === runProfileId) {
|
||||
if (hasMatch3DGeneratedModelAsset(profileAssets)) {
|
||||
if (hasMatch3DRuntimeAsset(profileAssets)) {
|
||||
return profileAssets;
|
||||
}
|
||||
|
||||
@@ -699,10 +710,12 @@ function resolveMatch3DRuntimeGeneratedItemAssets(
|
||||
isMatch3DGalleryEntry(publicWorkDetail) &&
|
||||
publicWorkDetail.profileId === runProfileId
|
||||
) {
|
||||
return hasMatch3DGeneratedModelAsset(publicDetailAssets)
|
||||
return hasMatch3DRuntimeAsset(publicDetailAssets)
|
||||
? publicDetailAssets
|
||||
: profileAssets;
|
||||
}
|
||||
|
||||
return profileAssets;
|
||||
}
|
||||
|
||||
if (
|
||||
@@ -714,9 +727,10 @@ function resolveMatch3DRuntimeGeneratedItemAssets(
|
||||
return publicDetailAssets;
|
||||
}
|
||||
|
||||
return hasMatch3DGeneratedModelAsset(profileAssets)
|
||||
? profileAssets
|
||||
: publicDetailAssets;
|
||||
if (hasMatch3DRuntimeAsset(profileAssets)) {
|
||||
return profileAssets;
|
||||
}
|
||||
return publicDetailAssets.length > 0 ? publicDetailAssets : profileAssets;
|
||||
}
|
||||
|
||||
function resolveActiveMatch3DRuntimeProfile(
|
||||
@@ -777,23 +791,23 @@ function resolveMatch3DGenerationStateFromAssets(
|
||||
|
||||
const assetList = assets ?? [];
|
||||
const imageReadyCount = assetList.filter(
|
||||
(asset) => asset.imageObjectKey?.trim() || asset.imageSrc?.trim(),
|
||||
).length;
|
||||
const modelReadyCount = assetList.filter(
|
||||
(asset) =>
|
||||
asset.status === 'model_ready' &&
|
||||
(asset.modelObjectKey?.trim() || asset.modelSrc?.trim()),
|
||||
asset.imageViews?.some(
|
||||
(view) => view.imageObjectKey?.trim() || view.imageSrc?.trim(),
|
||||
) ||
|
||||
asset.imageObjectKey?.trim() ||
|
||||
asset.imageSrc?.trim(),
|
||||
).length;
|
||||
const totalAssetCount = Math.max(3, assetList.length);
|
||||
const totalAssetCount = Math.max(5, assetList.length);
|
||||
const failedAsset = assetList.find((asset) => asset.error?.trim());
|
||||
|
||||
return {
|
||||
...current,
|
||||
phase:
|
||||
imageReadyCount > 0 || modelReadyCount > 0
|
||||
imageReadyCount > 0
|
||||
? 'match3d-generate-views'
|
||||
: current.phase,
|
||||
completedAssetCount: modelReadyCount,
|
||||
completedAssetCount: imageReadyCount,
|
||||
totalAssetCount,
|
||||
error: failedAsset?.error?.trim() || current.error,
|
||||
};
|
||||
@@ -2071,6 +2085,8 @@ export function PlatformEntryFlowShellImpl({
|
||||
useState<CreateMatch3DSessionRequest | null>(null);
|
||||
const [match3dGenerationState, setMatch3DGenerationState] =
|
||||
useState<MiniGameDraftGenerationState | null>(null);
|
||||
const [match3dBackgroundCompileTasks, setMatch3DBackgroundCompileTasks] =
|
||||
useState<Record<string, Match3DBackgroundCompileTask>>({});
|
||||
const [isMatch3DLoadingLibrary, setIsMatch3DLoadingLibrary] = useState(false);
|
||||
const [squareHoleWorks, setSquareHoleWorks] = useState<
|
||||
SquareHoleWorkSummary[]
|
||||
@@ -2155,6 +2171,8 @@ export function PlatformEntryFlowShellImpl({
|
||||
);
|
||||
const [puzzleGenerationState, setPuzzleGenerationState] =
|
||||
useState<MiniGameDraftGenerationState | null>(null);
|
||||
const [puzzleBackgroundCompileTasks, setPuzzleBackgroundCompileTasks] =
|
||||
useState<Record<string, PuzzleBackgroundCompileTask>>({});
|
||||
const [miniGameGenerationProgressNowMs, setMiniGameGenerationProgressNowMs] =
|
||||
useState(() => Date.now());
|
||||
const [puzzleFormDraftPayload, setPuzzleFormDraftPayload] =
|
||||
@@ -2287,6 +2305,8 @@ export function PlatformEntryFlowShellImpl({
|
||||
);
|
||||
const handledInitialPublicWorkCodeRef = useRef<string | null>(null);
|
||||
const selectionStageRef = useRef(selectionStage);
|
||||
const activeMatch3DGenerationSessionIdRef = useRef<string | null>(null);
|
||||
const activePuzzleGenerationSessionIdRef = useRef<string | null>(null);
|
||||
const [draftGenerationNotices, setDraftGenerationNotices] =
|
||||
useState<DraftGenerationNoticeMap>({});
|
||||
const [pendingDraftShelfItems, setPendingDraftShelfItems] =
|
||||
@@ -2437,6 +2457,24 @@ export function PlatformEntryFlowShellImpl({
|
||||
},
|
||||
[updatePendingDraftShelfItem],
|
||||
);
|
||||
const getMatch3DBackgroundCompileTask = useCallback(
|
||||
(sessionId: string | null | undefined) => {
|
||||
const normalizedSessionId = normalizeDraftNoticeId(sessionId);
|
||||
return normalizedSessionId
|
||||
? (match3dBackgroundCompileTasks[normalizedSessionId] ?? null)
|
||||
: null;
|
||||
},
|
||||
[match3dBackgroundCompileTasks],
|
||||
);
|
||||
const getPuzzleBackgroundCompileTask = useCallback(
|
||||
(sessionId: string | null | undefined) => {
|
||||
const normalizedSessionId = normalizeDraftNoticeId(sessionId);
|
||||
return normalizedSessionId
|
||||
? (puzzleBackgroundCompileTasks[normalizedSessionId] ?? null)
|
||||
: null;
|
||||
},
|
||||
[puzzleBackgroundCompileTasks],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
@@ -2501,6 +2539,18 @@ export function PlatformEntryFlowShellImpl({
|
||||
selectionStageRef.current = 'platform';
|
||||
setSelectionStage('platform');
|
||||
}, [enterCreateTab, setSelectionStage]);
|
||||
const isViewingMatch3DGeneration = useCallback((sessionId: string) => {
|
||||
return (
|
||||
selectionStageRef.current === 'match3d-generating' &&
|
||||
activeMatch3DGenerationSessionIdRef.current === sessionId
|
||||
);
|
||||
}, []);
|
||||
const isViewingPuzzleGeneration = useCallback((sessionId: string) => {
|
||||
return (
|
||||
selectionStageRef.current === 'puzzle-generating' &&
|
||||
activePuzzleGenerationSessionIdRef.current === sessionId
|
||||
);
|
||||
}, []);
|
||||
|
||||
const resolveBigFishErrorMessage = useCallback(
|
||||
(error: unknown, fallback: string) =>
|
||||
@@ -3515,9 +3565,9 @@ export function PlatformEntryFlowShellImpl({
|
||||
...current,
|
||||
phase: 'ready',
|
||||
completedAssetCount:
|
||||
response.session.draft?.generatedItemAssets?.length ?? 3,
|
||||
response.session.draft?.generatedItemAssets?.length ?? 5,
|
||||
totalAssetCount:
|
||||
response.session.draft?.generatedItemAssets?.length ?? 3,
|
||||
response.session.draft?.generatedItemAssets?.length ?? 5,
|
||||
}
|
||||
: current,
|
||||
);
|
||||
@@ -3552,7 +3602,7 @@ export function PlatformEntryFlowShellImpl({
|
||||
);
|
||||
if (openResult && runtimeProfile) {
|
||||
try {
|
||||
await preloadMatch3DGeneratedModelAssets(
|
||||
await preloadMatch3DGeneratedRuntimeAssets(
|
||||
runtimeProfile.generatedItemAssets,
|
||||
{ expireSeconds: 300 },
|
||||
);
|
||||
@@ -4151,6 +4201,39 @@ export function PlatformEntryFlowShellImpl({
|
||||
const resetAutoSaveTrackingToIdle =
|
||||
autosaveCoordinator.resetAutoSaveTrackingToIdle;
|
||||
|
||||
const activeMatch3DBackgroundCompileTask =
|
||||
getMatch3DBackgroundCompileTask(match3dSession?.sessionId);
|
||||
const match3dGenerationViewState =
|
||||
activeMatch3DBackgroundCompileTask?.generationState ??
|
||||
match3dGenerationState;
|
||||
const match3dGenerationViewSession =
|
||||
activeMatch3DBackgroundCompileTask?.session ?? match3dSession;
|
||||
const match3dGenerationViewPayload =
|
||||
activeMatch3DBackgroundCompileTask?.payload ?? match3dFormDraftPayload;
|
||||
const match3dGenerationViewError =
|
||||
activeMatch3DBackgroundCompileTask?.error ?? match3dError;
|
||||
const isMatch3DGenerationViewBusy =
|
||||
isMatch3DBusy ||
|
||||
isMiniGameDraftGenerating(
|
||||
activeMatch3DBackgroundCompileTask?.generationState ?? null,
|
||||
);
|
||||
const activePuzzleBackgroundCompileTask = getPuzzleBackgroundCompileTask(
|
||||
puzzleSession?.sessionId,
|
||||
);
|
||||
const puzzleGenerationViewState =
|
||||
activePuzzleBackgroundCompileTask?.generationState ?? puzzleGenerationState;
|
||||
const puzzleGenerationViewSession =
|
||||
activePuzzleBackgroundCompileTask?.session ?? puzzleSession;
|
||||
const puzzleGenerationViewPayload =
|
||||
activePuzzleBackgroundCompileTask?.payload ?? puzzleFormDraftPayload;
|
||||
const puzzleGenerationViewError =
|
||||
activePuzzleBackgroundCompileTask?.error ?? puzzleError;
|
||||
const isPuzzleGenerationViewBusy =
|
||||
isPuzzleBusy ||
|
||||
isMiniGameDraftGenerating(
|
||||
activePuzzleBackgroundCompileTask?.generationState ?? null,
|
||||
);
|
||||
|
||||
const match3DGeneratingSessionId =
|
||||
selectionStage === 'match3d-generating' ? match3dSession?.sessionId : null;
|
||||
|
||||
@@ -4302,60 +4385,366 @@ export function PlatformEntryFlowShellImpl({
|
||||
const createPuzzleDraftFromForm = useCallback(
|
||||
async (payload: CreatePuzzleAgentSessionRequest) => {
|
||||
setPuzzleFormDraftPayload(payload);
|
||||
setPuzzleGenerationState(null);
|
||||
const nextSession =
|
||||
puzzleFlow.session && !isEmptyPuzzleFormOnlyDraft(puzzleFlow.session)
|
||||
? puzzleFlow.session
|
||||
: await puzzleFlow.openWorkspace(payload);
|
||||
if (!nextSession) {
|
||||
setPuzzleCreationError(null);
|
||||
setPuzzleError(null);
|
||||
|
||||
let nextSession: PuzzleAgentSessionSnapshot;
|
||||
try {
|
||||
const response = await createPuzzleAgentSession(payload);
|
||||
nextSession = response.session;
|
||||
} catch (error) {
|
||||
const errorMessage = resolvePuzzleErrorMessage(
|
||||
error,
|
||||
'开启拼图创作工作台失败。',
|
||||
);
|
||||
setPuzzleCreationError(errorMessage);
|
||||
setPuzzleError(errorMessage);
|
||||
return;
|
||||
}
|
||||
markPendingDraftGenerating('puzzle', nextSession.sessionId);
|
||||
|
||||
await puzzleFlow.executeAction(
|
||||
buildPuzzleCompileActionFromFormPayload(payload),
|
||||
nextSession,
|
||||
);
|
||||
const generationState = createMiniGameDraftGenerationState('puzzle');
|
||||
setPuzzleBackgroundCompileTasks((current) => ({
|
||||
...current,
|
||||
[nextSession.sessionId]: {
|
||||
session: nextSession,
|
||||
payload,
|
||||
generationState,
|
||||
error: null,
|
||||
},
|
||||
}));
|
||||
puzzleFlow.setSession(nextSession);
|
||||
setPuzzleGenerationState(generationState);
|
||||
markDraftGenerating('puzzle', [
|
||||
nextSession.sessionId,
|
||||
buildPuzzleResultWorkId(nextSession.sessionId),
|
||||
nextSession.publishedProfileId,
|
||||
buildPuzzleResultProfileId(nextSession.sessionId),
|
||||
]);
|
||||
markPendingDraftGenerating('puzzle', nextSession.sessionId);
|
||||
selectionStageRef.current = 'puzzle-generating';
|
||||
activePuzzleGenerationSessionIdRef.current = nextSession.sessionId;
|
||||
setSelectionStage('puzzle-generating');
|
||||
|
||||
try {
|
||||
const actionPayload = buildPuzzleCompileActionFromFormPayload(payload);
|
||||
const response = await executePuzzleAgentAction(
|
||||
nextSession.sessionId,
|
||||
actionPayload,
|
||||
);
|
||||
setPuzzleOperation(response.operation);
|
||||
const openResult = isViewingPuzzleGeneration(nextSession.sessionId);
|
||||
const readyGenerationState = {
|
||||
...generationState,
|
||||
phase: 'ready' as const,
|
||||
completedAssetCount: 1,
|
||||
totalAssetCount: 1,
|
||||
};
|
||||
setPuzzleBackgroundCompileTasks((current) => ({
|
||||
...current,
|
||||
[nextSession.sessionId]: {
|
||||
session: response.session,
|
||||
payload,
|
||||
generationState: readyGenerationState,
|
||||
error: null,
|
||||
},
|
||||
}));
|
||||
if (isViewingPuzzleGeneration(nextSession.sessionId)) {
|
||||
puzzleFlow.setSession(response.session);
|
||||
setPuzzleGenerationState(readyGenerationState);
|
||||
}
|
||||
|
||||
const profileId =
|
||||
response.session.publishedProfileId ??
|
||||
buildPuzzleResultProfileId(response.session.sessionId);
|
||||
markPendingDraftReady('puzzle', response.session.sessionId, openResult);
|
||||
markDraftReady(
|
||||
'puzzle',
|
||||
[
|
||||
response.session.sessionId,
|
||||
buildPuzzleResultWorkId(response.session.sessionId),
|
||||
profileId,
|
||||
],
|
||||
openResult,
|
||||
);
|
||||
void refreshPuzzleShelf();
|
||||
|
||||
if (openResult && response.session.draft) {
|
||||
const draft = response.session.draft;
|
||||
const draftProfileId =
|
||||
response.session.publishedProfileId ??
|
||||
buildPuzzleResultProfileId(response.session.sessionId);
|
||||
if (!draft.coverImageSrc || !draftProfileId) {
|
||||
setPuzzleError(
|
||||
!draft.coverImageSrc
|
||||
? '请先选择一张正式拼图图片。'
|
||||
: '这份拼图草稿缺少会话信息,请重新开始创作。',
|
||||
);
|
||||
setSelectionStage('puzzle-result');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const { item } = await updatePuzzleWork(draftProfileId, {
|
||||
workTitle: draft.workTitle,
|
||||
workDescription: draft.workDescription,
|
||||
levelName: draft.levelName,
|
||||
summary: draft.summary,
|
||||
themeTags: draft.themeTags,
|
||||
coverImageSrc: draft.coverImageSrc,
|
||||
coverAssetId: draft.coverAssetId,
|
||||
levels: draft.levels ?? [],
|
||||
});
|
||||
const run = startLocalPuzzleRun(item);
|
||||
setSelectedPuzzleDetail(item);
|
||||
setPuzzleRun(run);
|
||||
setPuzzleRuntimeAuthMode('default');
|
||||
setPuzzleRuntimeReturnStage('puzzle-result');
|
||||
setSelectionStage('puzzle-runtime');
|
||||
} catch (error) {
|
||||
setPuzzleError(
|
||||
resolvePuzzleErrorMessage(error, '启动拼图试玩失败。'),
|
||||
);
|
||||
setSelectionStage('puzzle-result');
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
const errorMessage = resolvePuzzleErrorMessage(
|
||||
error,
|
||||
'执行拼图操作失败。',
|
||||
);
|
||||
const failedGenerationState = {
|
||||
...generationState,
|
||||
phase: 'failed' as const,
|
||||
error: errorMessage,
|
||||
};
|
||||
setPuzzleBackgroundCompileTasks((current) => ({
|
||||
...current,
|
||||
[nextSession.sessionId]: {
|
||||
session: nextSession,
|
||||
payload,
|
||||
generationState: failedGenerationState,
|
||||
error: errorMessage,
|
||||
},
|
||||
}));
|
||||
if (isViewingPuzzleGeneration(nextSession.sessionId)) {
|
||||
setPuzzleError(errorMessage);
|
||||
setPuzzleGenerationState(failedGenerationState);
|
||||
}
|
||||
}
|
||||
},
|
||||
[markPendingDraftGenerating, puzzleFlow],
|
||||
[
|
||||
markDraftGenerating,
|
||||
markDraftReady,
|
||||
markPendingDraftGenerating,
|
||||
markPendingDraftReady,
|
||||
isViewingPuzzleGeneration,
|
||||
puzzleFlow,
|
||||
refreshPuzzleShelf,
|
||||
resolvePuzzleErrorMessage,
|
||||
setPuzzleError,
|
||||
setSelectionStage,
|
||||
],
|
||||
);
|
||||
|
||||
const createMatch3DDraftFromForm = useCallback(
|
||||
async (payload: CreateMatch3DSessionRequest) => {
|
||||
setMatch3DFormDraftPayload(payload);
|
||||
setMatch3DGenerationState(null);
|
||||
setMatch3DSession(null);
|
||||
setMatch3DProfile(null);
|
||||
setMatch3DRuntimeProfile(null);
|
||||
setMatch3DRun(null);
|
||||
setMatch3DError(null);
|
||||
setStreamingMatch3DReplyText('');
|
||||
setIsStreamingMatch3DReply(false);
|
||||
|
||||
const nextSession = await match3dFlow.openWorkspace(payload);
|
||||
if (!nextSession) {
|
||||
let nextSession: Match3DAgentSessionSnapshot;
|
||||
try {
|
||||
const response = await match3dCreationClient.createSession(payload);
|
||||
nextSession = response.session;
|
||||
} catch (error) {
|
||||
setMatch3DError(
|
||||
resolveMatch3DErrorMessage(error, '开启抓大鹅共创工作台失败。'),
|
||||
);
|
||||
return;
|
||||
}
|
||||
markDraftGenerating('match3d', [nextSession.sessionId]);
|
||||
markPendingDraftGenerating('match3d', nextSession.sessionId);
|
||||
|
||||
await match3dFlow.executeAction(
|
||||
{
|
||||
action: 'match3d_compile_draft',
|
||||
generateClickSound: payload.generateClickSound,
|
||||
const generationState = createMiniGameDraftGenerationState('match3d');
|
||||
setMatch3DBackgroundCompileTasks((current) => ({
|
||||
...current,
|
||||
[nextSession.sessionId]: {
|
||||
session: nextSession,
|
||||
payload,
|
||||
generationState,
|
||||
error: null,
|
||||
},
|
||||
nextSession,
|
||||
);
|
||||
}));
|
||||
setMatch3DSession(nextSession);
|
||||
setMatch3DProfile(null);
|
||||
setMatch3DRuntimeProfile(null);
|
||||
setMatch3DRun(null);
|
||||
setMatch3DGenerationState(generationState);
|
||||
markDraftGenerating('match3d', [
|
||||
nextSession.draft?.profileId,
|
||||
nextSession.publishedProfileId,
|
||||
nextSession.sessionId,
|
||||
]);
|
||||
markPendingDraftGenerating('match3d', nextSession.sessionId);
|
||||
selectionStageRef.current = 'match3d-generating';
|
||||
activeMatch3DGenerationSessionIdRef.current = nextSession.sessionId;
|
||||
setSelectionStage('match3d-generating');
|
||||
|
||||
try {
|
||||
const response = await match3dCreationClient.executeAction(
|
||||
nextSession.sessionId,
|
||||
{
|
||||
action: 'match3d_compile_draft',
|
||||
generateClickSound: payload.generateClickSound,
|
||||
},
|
||||
);
|
||||
const openResult = isViewingMatch3DGeneration(nextSession.sessionId);
|
||||
const readyGenerationState = {
|
||||
...generationState,
|
||||
phase: 'ready' as const,
|
||||
completedAssetCount:
|
||||
response.session.draft?.generatedItemAssets?.length ?? 5,
|
||||
totalAssetCount:
|
||||
response.session.draft?.generatedItemAssets?.length ?? 5,
|
||||
};
|
||||
setMatch3DBackgroundCompileTasks((current) => ({
|
||||
...current,
|
||||
[nextSession.sessionId]: {
|
||||
session: response.session,
|
||||
payload,
|
||||
generationState: readyGenerationState,
|
||||
error: null,
|
||||
},
|
||||
}));
|
||||
if (isViewingMatch3DGeneration(nextSession.sessionId)) {
|
||||
setMatch3DSession(response.session);
|
||||
setMatch3DGenerationState(readyGenerationState);
|
||||
}
|
||||
|
||||
const profileId = response.session.draft?.profileId;
|
||||
if (!profileId) {
|
||||
if (isViewingMatch3DGeneration(nextSession.sessionId)) {
|
||||
setMatch3DProfile(null);
|
||||
setMatch3DRuntimeProfile(null);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
let runtimeProfile: Match3DWorkProfile | null = null;
|
||||
try {
|
||||
const { item } = await getMatch3DWorkDetail(profileId);
|
||||
runtimeProfile = {
|
||||
...item,
|
||||
generatedItemAssets:
|
||||
response.session.draft?.generatedItemAssets ??
|
||||
item.generatedItemAssets,
|
||||
};
|
||||
if (isViewingMatch3DGeneration(nextSession.sessionId)) {
|
||||
setMatch3DProfile(runtimeProfile);
|
||||
}
|
||||
await refreshMatch3DShelf().catch(() => undefined);
|
||||
} catch {
|
||||
runtimeProfile = buildMatch3DProfileFromSession(response.session);
|
||||
if (isViewingMatch3DGeneration(nextSession.sessionId)) {
|
||||
setMatch3DProfile(runtimeProfile);
|
||||
}
|
||||
}
|
||||
|
||||
markPendingDraftReady(
|
||||
'match3d',
|
||||
response.session.sessionId,
|
||||
openResult,
|
||||
);
|
||||
markDraftReady(
|
||||
'match3d',
|
||||
[profileId, response.session.sessionId],
|
||||
openResult,
|
||||
);
|
||||
if (openResult && runtimeProfile) {
|
||||
try {
|
||||
await preloadMatch3DGeneratedRuntimeAssets(
|
||||
runtimeProfile.generatedItemAssets,
|
||||
{ expireSeconds: 300 },
|
||||
);
|
||||
const { run } = await match3dRuntimeAdapter.startRun(
|
||||
runtimeProfile.profileId,
|
||||
);
|
||||
setMatch3DRuntimeProfile(runtimeProfile);
|
||||
setMatch3DRun(run);
|
||||
setMatch3DProfile(runtimeProfile);
|
||||
setMatch3DRuntimeReturnStage('match3d-result');
|
||||
setSelectionStage('match3d-runtime');
|
||||
} catch (error) {
|
||||
setMatch3DError(
|
||||
resolveMatch3DErrorMessage(error, '启动抓大鹅玩法失败。'),
|
||||
);
|
||||
setSelectionStage('match3d-result');
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
const errorMessage = resolveMatch3DErrorMessage(
|
||||
error,
|
||||
'执行抓大鹅操作失败。',
|
||||
);
|
||||
const failedGenerationState = {
|
||||
...generationState,
|
||||
phase: 'failed' as const,
|
||||
error: errorMessage,
|
||||
};
|
||||
setMatch3DBackgroundCompileTasks((current) => ({
|
||||
...current,
|
||||
[nextSession.sessionId]: {
|
||||
session: nextSession,
|
||||
payload,
|
||||
generationState: failedGenerationState,
|
||||
error: errorMessage,
|
||||
},
|
||||
}));
|
||||
if (isViewingMatch3DGeneration(nextSession.sessionId)) {
|
||||
setMatch3DError(errorMessage);
|
||||
setMatch3DGenerationState(failedGenerationState);
|
||||
}
|
||||
try {
|
||||
const { session: latestSession } =
|
||||
await match3dCreationClient.getSession(nextSession.sessionId);
|
||||
setMatch3DBackgroundCompileTasks((current) => ({
|
||||
...current,
|
||||
[nextSession.sessionId]: {
|
||||
session: latestSession,
|
||||
payload,
|
||||
generationState: failedGenerationState,
|
||||
error: errorMessage,
|
||||
},
|
||||
}));
|
||||
if (isViewingMatch3DGeneration(nextSession.sessionId)) {
|
||||
setMatch3DSession(latestSession);
|
||||
const profileId =
|
||||
latestSession.draft?.profileId ?? latestSession.publishedProfileId;
|
||||
if (profileId) {
|
||||
const { item } = await getMatch3DWorkDetail(profileId);
|
||||
setMatch3DProfile(item);
|
||||
}
|
||||
}
|
||||
await refreshMatch3DShelf().catch(() => undefined);
|
||||
} catch {
|
||||
await refreshMatch3DShelf().catch(() => undefined);
|
||||
}
|
||||
}
|
||||
},
|
||||
[
|
||||
match3dFlow,
|
||||
match3dRuntimeAdapter,
|
||||
isViewingMatch3DGeneration,
|
||||
markDraftGenerating,
|
||||
markDraftReady,
|
||||
markPendingDraftGenerating,
|
||||
markPendingDraftReady,
|
||||
refreshMatch3DShelf,
|
||||
resolveMatch3DErrorMessage,
|
||||
setIsStreamingMatch3DReply,
|
||||
setMatch3DError,
|
||||
setMatch3DProfile,
|
||||
setMatch3DRun,
|
||||
setMatch3DSession,
|
||||
setSelectionStage,
|
||||
setStreamingMatch3DReplyText,
|
||||
],
|
||||
);
|
||||
@@ -4552,6 +4941,8 @@ export function PlatformEntryFlowShellImpl({
|
||||
setMatch3DProfile(null);
|
||||
setMatch3DRuntimeProfile(null);
|
||||
setMatch3DFormDraftPayload(null);
|
||||
setMatch3DBackgroundCompileTasks({});
|
||||
activeMatch3DGenerationSessionIdRef.current = null;
|
||||
setActiveCreationFormType('puzzle');
|
||||
setMatch3DWorks([]);
|
||||
setMatch3DGalleryEntries([]);
|
||||
@@ -4585,6 +4976,8 @@ export function PlatformEntryFlowShellImpl({
|
||||
setPuzzleRun(null);
|
||||
setPuzzleRuntimeAuthMode('default');
|
||||
setPuzzleGenerationState(null);
|
||||
setPuzzleBackgroundCompileTasks({});
|
||||
activePuzzleGenerationSessionIdRef.current = null;
|
||||
setIsPuzzleNextLevelGenerating(false);
|
||||
setPuzzleShelfError(null);
|
||||
setPuzzleCreationError(null);
|
||||
@@ -5361,7 +5754,7 @@ export function PlatformEntryFlowShellImpl({
|
||||
|
||||
const executePuzzleBackgroundAction = useCallback(
|
||||
async (payload: PuzzleAgentActionRequest) => {
|
||||
const targetSession = puzzleFlow.session;
|
||||
const targetSession = puzzleSession;
|
||||
if (!targetSession) {
|
||||
return;
|
||||
}
|
||||
@@ -5383,7 +5776,7 @@ export function PlatformEntryFlowShellImpl({
|
||||
setPuzzleError(resolvePuzzleErrorMessage(error, '执行拼图操作失败。'));
|
||||
}
|
||||
},
|
||||
[puzzleFlow, resolvePuzzleErrorMessage, setPuzzleError],
|
||||
[puzzleFlow, puzzleSession, resolvePuzzleErrorMessage, setPuzzleError],
|
||||
);
|
||||
|
||||
const retryPuzzleDraftGeneration = useCallback(() => {
|
||||
@@ -5427,7 +5820,7 @@ export function PlatformEntryFlowShellImpl({
|
||||
(payload: PuzzleAgentActionRequest) => {
|
||||
if (
|
||||
payload.action === 'compile_puzzle_draft' &&
|
||||
isEmptyPuzzleFormOnlyDraft(puzzleFlow.session)
|
||||
isEmptyPuzzleFormOnlyDraft(puzzleSession)
|
||||
) {
|
||||
const formPayload = buildPuzzleFormPayloadFromAction(payload);
|
||||
if (formPayload) {
|
||||
@@ -5447,7 +5840,7 @@ export function PlatformEntryFlowShellImpl({
|
||||
createPuzzleDraftFromForm,
|
||||
executePuzzleAction,
|
||||
executePuzzleBackgroundAction,
|
||||
puzzleFlow.session,
|
||||
puzzleSession,
|
||||
],
|
||||
);
|
||||
|
||||
@@ -5815,7 +6208,7 @@ export function PlatformEntryFlowShellImpl({
|
||||
|
||||
try {
|
||||
let runtimeProfile = profile;
|
||||
if (!hasMatch3DGeneratedModelAsset(profile.generatedItemAssets)) {
|
||||
if (!hasMatch3DRuntimeAsset(profile.generatedItemAssets)) {
|
||||
try {
|
||||
const { item } = await getMatch3DWorkDetail(profile.profileId);
|
||||
runtimeProfile = item;
|
||||
@@ -5823,7 +6216,7 @@ export function PlatformEntryFlowShellImpl({
|
||||
// 中文注释:详情补读只为拿完整生成素材;失败时继续按摘要开局,避免推荐流卡死。
|
||||
}
|
||||
}
|
||||
await preloadMatch3DGeneratedModelAssets(
|
||||
await preloadMatch3DGeneratedRuntimeAssets(
|
||||
runtimeProfile.generatedItemAssets,
|
||||
{ expireSeconds: 300 },
|
||||
);
|
||||
@@ -7628,10 +8021,31 @@ export function PlatformEntryFlowShellImpl({
|
||||
|
||||
if (
|
||||
item.sourceSessionId === puzzleSession?.sessionId &&
|
||||
isMiniGameDraftGenerating(puzzleGenerationState)
|
||||
isMiniGameDraftGenerating(puzzleGenerationViewState)
|
||||
) {
|
||||
enterCreateTab();
|
||||
selectionStageRef.current = 'puzzle-generating';
|
||||
activePuzzleGenerationSessionIdRef.current = item.sourceSessionId;
|
||||
setSelectionStage('puzzle-generating');
|
||||
return;
|
||||
}
|
||||
|
||||
const backgroundTask = getPuzzleBackgroundCompileTask(
|
||||
item.sourceSessionId,
|
||||
);
|
||||
if (
|
||||
backgroundTask &&
|
||||
isMiniGameDraftGenerating(backgroundTask.generationState)
|
||||
) {
|
||||
puzzleFlow.setSession(backgroundTask.session);
|
||||
setPuzzleFormDraftPayload(backgroundTask.payload);
|
||||
setPuzzleGenerationState(backgroundTask.generationState);
|
||||
if (backgroundTask.error) {
|
||||
setPuzzleError(backgroundTask.error);
|
||||
}
|
||||
enterCreateTab();
|
||||
selectionStageRef.current = 'puzzle-generating';
|
||||
activePuzzleGenerationSessionIdRef.current = item.sourceSessionId;
|
||||
setSelectionStage('puzzle-generating');
|
||||
return;
|
||||
}
|
||||
@@ -7655,10 +8069,11 @@ export function PlatformEntryFlowShellImpl({
|
||||
},
|
||||
[
|
||||
enterCreateTab,
|
||||
getPuzzleBackgroundCompileTask,
|
||||
markDraftNoticeSeen,
|
||||
openPuzzleDetail,
|
||||
puzzleFlow,
|
||||
puzzleGenerationState,
|
||||
puzzleGenerationViewState,
|
||||
puzzleSession?.sessionId,
|
||||
refreshPuzzleShelf,
|
||||
setPuzzleError,
|
||||
@@ -7695,10 +8110,31 @@ export function PlatformEntryFlowShellImpl({
|
||||
|
||||
if (
|
||||
item.sourceSessionId === match3dSession?.sessionId &&
|
||||
isMiniGameDraftGenerating(match3dGenerationState)
|
||||
isMiniGameDraftGenerating(match3dGenerationViewState)
|
||||
) {
|
||||
enterCreateTab();
|
||||
selectionStageRef.current = 'match3d-generating';
|
||||
activeMatch3DGenerationSessionIdRef.current = item.sourceSessionId;
|
||||
setSelectionStage('match3d-generating');
|
||||
return;
|
||||
}
|
||||
|
||||
const backgroundTask = getMatch3DBackgroundCompileTask(
|
||||
item.sourceSessionId,
|
||||
);
|
||||
if (
|
||||
backgroundTask &&
|
||||
isMiniGameDraftGenerating(backgroundTask.generationState)
|
||||
) {
|
||||
setMatch3DSession(backgroundTask.session);
|
||||
setMatch3DFormDraftPayload(backgroundTask.payload);
|
||||
setMatch3DGenerationState(backgroundTask.generationState);
|
||||
if (backgroundTask.error) {
|
||||
setMatch3DError(backgroundTask.error);
|
||||
}
|
||||
enterCreateTab();
|
||||
selectionStageRef.current = 'match3d-generating';
|
||||
activeMatch3DGenerationSessionIdRef.current = item.sourceSessionId;
|
||||
setSelectionStage('match3d-generating');
|
||||
return;
|
||||
}
|
||||
@@ -7726,9 +8162,10 @@ export function PlatformEntryFlowShellImpl({
|
||||
},
|
||||
[
|
||||
enterCreateTab,
|
||||
getMatch3DBackgroundCompileTask,
|
||||
markDraftNoticeSeen,
|
||||
match3dFlow,
|
||||
match3dGenerationState,
|
||||
match3dGenerationViewState,
|
||||
match3dSession?.sessionId,
|
||||
openPublicWorkDetail,
|
||||
refreshMatch3DShelf,
|
||||
@@ -9630,18 +10067,7 @@ export function PlatformEntryFlowShellImpl({
|
||||
>
|
||||
{getVisiblePlatformCreationTypes(creationEntryTypes).map((item) => {
|
||||
const selected = item.id === activeCreationFormType;
|
||||
const disabled =
|
||||
item.locked ||
|
||||
sessionController.isCreatingAgentSession ||
|
||||
isCreativeAgentBusy ||
|
||||
isCreativeAgentStreaming ||
|
||||
isBigFishBusy ||
|
||||
isMatch3DBusy ||
|
||||
isSquareHoleBusy ||
|
||||
isPuzzleBusy ||
|
||||
isVisualNovelBusy ||
|
||||
isVisualNovelStreamingReply ||
|
||||
isBabyObjectMatchBusy;
|
||||
const disabled = item.locked;
|
||||
|
||||
return (
|
||||
<button
|
||||
@@ -9708,7 +10134,7 @@ export function PlatformEntryFlowShellImpl({
|
||||
>
|
||||
<Match3DAgentWorkspace
|
||||
session={match3dSession}
|
||||
isBusy={isMatch3DBusy || isStreamingMatch3DReply}
|
||||
isBusy={isStreamingMatch3DReply}
|
||||
error={match3dError}
|
||||
onBack={leaveMatch3DFlow}
|
||||
onExecuteAction={(payload) => {
|
||||
@@ -9765,7 +10191,7 @@ export function PlatformEntryFlowShellImpl({
|
||||
>
|
||||
<PuzzleAgentWorkspace
|
||||
session={puzzleSession}
|
||||
isBusy={isPuzzleBusy || isStreamingPuzzleReply}
|
||||
isBusy={isStreamingPuzzleReply}
|
||||
error={puzzleError}
|
||||
onBack={leavePuzzleFlow}
|
||||
onSubmitMessage={(payload) => {
|
||||
@@ -10287,7 +10713,7 @@ export function PlatformEntryFlowShellImpl({
|
||||
>
|
||||
<Match3DAgentWorkspace
|
||||
session={match3dSession}
|
||||
isBusy={isMatch3DBusy || isStreamingMatch3DReply}
|
||||
isBusy={isStreamingMatch3DReply}
|
||||
error={match3dError}
|
||||
onBack={leaveMatch3DFlow}
|
||||
onExecuteAction={(payload) => {
|
||||
@@ -10311,19 +10737,19 @@ export function PlatformEntryFlowShellImpl({
|
||||
>
|
||||
<CustomWorldGenerationView
|
||||
settingText={
|
||||
match3dSession?.lastAssistantReply ??
|
||||
match3dGenerationViewSession?.lastAssistantReply ??
|
||||
'正在生成本局抓大鹅物品素材。'
|
||||
}
|
||||
anchorEntries={buildMatch3DGenerationAnchorEntries(
|
||||
match3dSession,
|
||||
match3dFormDraftPayload,
|
||||
match3dGenerationViewSession,
|
||||
match3dGenerationViewPayload,
|
||||
)}
|
||||
progress={buildMiniGameDraftGenerationProgress(
|
||||
match3dGenerationState,
|
||||
match3dGenerationViewState,
|
||||
miniGameGenerationProgressNowMs,
|
||||
)}
|
||||
isGenerating={isMatch3DBusy}
|
||||
error={match3dError}
|
||||
isGenerating={isMatch3DGenerationViewBusy}
|
||||
error={match3dGenerationViewError}
|
||||
onBack={returnToCreationCenterFromGeneration}
|
||||
onEditSetting={() => {
|
||||
setSelectionStage('match3d-agent-workspace');
|
||||
@@ -10364,7 +10790,7 @@ export function PlatformEntryFlowShellImpl({
|
||||
isBusy={isMatch3DBusy}
|
||||
error={match3dError}
|
||||
onBack={() => {
|
||||
setSelectionStage('match3d-agent-workspace');
|
||||
returnToCreationCenterFromGeneration();
|
||||
}}
|
||||
onSaved={(profile) => {
|
||||
setMatch3DProfile(profile);
|
||||
@@ -10388,7 +10814,6 @@ export function PlatformEntryFlowShellImpl({
|
||||
}}
|
||||
onStartTestRun={(profile, options) => {
|
||||
setMatch3DProfile(profile);
|
||||
setMatch3DRuntimeProfile(profile);
|
||||
void startMatch3DRunFromProfile(
|
||||
profile,
|
||||
'match3d-result',
|
||||
@@ -10895,7 +11320,7 @@ export function PlatformEntryFlowShellImpl({
|
||||
>
|
||||
<PuzzleAgentWorkspace
|
||||
session={puzzleSession}
|
||||
isBusy={isPuzzleBusy || isStreamingPuzzleReply}
|
||||
isBusy={isStreamingPuzzleReply}
|
||||
error={puzzleError}
|
||||
onBack={leavePuzzleFlow}
|
||||
onSubmitMessage={(payload) => {
|
||||
@@ -10950,18 +11375,19 @@ export function PlatformEntryFlowShellImpl({
|
||||
>
|
||||
<CustomWorldGenerationView
|
||||
settingText={
|
||||
puzzleSession?.lastAssistantReply ?? '正在整理当前拼图草稿。'
|
||||
puzzleGenerationViewSession?.lastAssistantReply ??
|
||||
'正在整理当前拼图草稿。'
|
||||
}
|
||||
anchorEntries={buildPuzzleGenerationAnchorEntries(
|
||||
puzzleSession,
|
||||
puzzleFormDraftPayload,
|
||||
puzzleGenerationViewSession,
|
||||
puzzleGenerationViewPayload,
|
||||
)}
|
||||
progress={buildMiniGameDraftGenerationProgress(
|
||||
puzzleGenerationState,
|
||||
puzzleGenerationViewState,
|
||||
miniGameGenerationProgressNowMs,
|
||||
)}
|
||||
isGenerating={isPuzzleBusy}
|
||||
error={puzzleError}
|
||||
isGenerating={isPuzzleGenerationViewBusy}
|
||||
error={puzzleGenerationViewError}
|
||||
onBack={returnToCreationCenterFromGeneration}
|
||||
onEditSetting={() => {
|
||||
setSelectionStage('puzzle-agent-workspace');
|
||||
@@ -11537,18 +11963,7 @@ export function PlatformEntryFlowShellImpl({
|
||||
{creationEntryConfig ? (
|
||||
<PlatformEntryCreationTypeModal
|
||||
isOpen={showCreationTypeModal}
|
||||
isBusy={
|
||||
sessionController.isCreatingAgentSession ||
|
||||
isCreativeAgentBusy ||
|
||||
isCreativeAgentStreaming ||
|
||||
isBigFishBusy ||
|
||||
isMatch3DBusy ||
|
||||
isSquareHoleBusy ||
|
||||
isPuzzleBusy ||
|
||||
isVisualNovelBusy ||
|
||||
isVisualNovelStreamingReply ||
|
||||
isBabyObjectMatchBusy
|
||||
}
|
||||
isBusy={sessionController.isCreatingAgentSession}
|
||||
error={
|
||||
creationEntryConfigError ??
|
||||
bigFishError ??
|
||||
@@ -11564,18 +11979,7 @@ export function PlatformEntryFlowShellImpl({
|
||||
entryConfig={creationEntryConfig}
|
||||
creationTypes={creationEntryTypes}
|
||||
onClose={() => {
|
||||
if (
|
||||
sessionController.isCreatingAgentSession ||
|
||||
isCreativeAgentBusy ||
|
||||
isCreativeAgentStreaming ||
|
||||
isBigFishBusy ||
|
||||
isMatch3DBusy ||
|
||||
isSquareHoleBusy ||
|
||||
isPuzzleBusy ||
|
||||
isVisualNovelBusy ||
|
||||
isVisualNovelStreamingReply ||
|
||||
isBabyObjectMatchBusy
|
||||
) {
|
||||
if (sessionController.isCreatingAgentSession) {
|
||||
return;
|
||||
}
|
||||
setShowCreationTypeModal(false);
|
||||
|
||||
Reference in New Issue
Block a user