1
This commit is contained in:
@@ -79,6 +79,12 @@ export function PlatformEntryCreationTypeModal({
|
||||
return null;
|
||||
}
|
||||
|
||||
// 平台入口只渲染当前允许展示的创作类型;
|
||||
// 被隐藏的玩法仍保留既有实现与路由,不在这里删除能力本体。
|
||||
const visibleCreationTypes = PLATFORM_CREATION_TYPES.filter(
|
||||
(item) => !item.hidden,
|
||||
);
|
||||
|
||||
return (
|
||||
<UnifiedModal
|
||||
open={isOpen}
|
||||
@@ -89,7 +95,7 @@ export function PlatformEntryCreationTypeModal({
|
||||
size="lg"
|
||||
>
|
||||
<div className="grid gap-3 sm:grid-cols-5">
|
||||
{PLATFORM_CREATION_TYPES.map((item) => (
|
||||
{visibleCreationTypes.map((item) => (
|
||||
<CreationTypeCard
|
||||
key={item.id}
|
||||
item={item}
|
||||
|
||||
@@ -95,7 +95,9 @@ import {
|
||||
} from '../../services/puzzle-runtime';
|
||||
import {
|
||||
dragLocalPuzzlePiece,
|
||||
isLocalPuzzleRun,
|
||||
startLocalPuzzleRun,
|
||||
submitLocalPuzzleLeaderboard,
|
||||
swapLocalPuzzlePieces,
|
||||
} from '../../services/puzzle-runtime/puzzleLocalRuntime';
|
||||
import { deletePuzzleWork, listPuzzleWorks } from '../../services/puzzle-works';
|
||||
@@ -126,7 +128,6 @@ import {
|
||||
} from './PlatformEntryHomeView';
|
||||
import {
|
||||
buildCreationHubFallbackItems,
|
||||
normalizeAgentBackedProfile,
|
||||
resolveRpgCreationErrorMessage,
|
||||
} from './platformEntryShared';
|
||||
import type { PlatformEntryFlowShellProps } from './platformEntryTypes';
|
||||
@@ -590,7 +591,6 @@ export function PlatformEntryFlowShellImpl({
|
||||
const autosaveCoordinator = useRpgCreationResultAutosave({
|
||||
selectionStage,
|
||||
activeAgentSessionId: sessionController.activeAgentSessionId,
|
||||
agentSession: sessionController.agentSession,
|
||||
generatedCustomWorldProfile: sessionController.generatedCustomWorldProfile,
|
||||
isAgentDraftResultView: sessionController.isAgentDraftResultView,
|
||||
userId: authUi?.user?.id,
|
||||
@@ -602,8 +602,9 @@ export function PlatformEntryFlowShellImpl({
|
||||
refreshCustomWorldWorks: platformBootstrap.refreshCustomWorldWorks,
|
||||
persistAgentUiState: sessionController.persistAgentUiState,
|
||||
syncAgentSessionSnapshot: sessionController.syncAgentSessionSnapshot,
|
||||
buildDraftResultProfile: (session) =>
|
||||
rpgCreationPreviewAdapter.buildPreviewFromSession(session),
|
||||
syncAgentCreationResultView: sessionController.syncAgentCreationResultView,
|
||||
buildDraftResultProfile: (view) =>
|
||||
rpgCreationPreviewAdapter.buildPreviewFromResultView(view),
|
||||
});
|
||||
|
||||
const detailNavigation = usePlatformEntryLibraryDetail({
|
||||
@@ -630,9 +631,9 @@ export function PlatformEntryFlowShellImpl({
|
||||
refreshCustomWorldWorks: platformBootstrap.refreshCustomWorldWorks,
|
||||
refreshPublishedGallery: platformBootstrap.refreshPublishedGallery,
|
||||
persistAgentUiState: sessionController.persistAgentUiState,
|
||||
syncAgentSessionSnapshot: sessionController.syncAgentSessionSnapshot,
|
||||
buildDraftResultProfile: (session) =>
|
||||
rpgCreationPreviewAdapter.buildPreviewFromSession(session),
|
||||
syncAgentCreationResultView: sessionController.syncAgentCreationResultView,
|
||||
buildDraftResultProfile: (view) =>
|
||||
rpgCreationPreviewAdapter.buildPreviewFromResultView(view),
|
||||
suppressAgentDraftResultAutoOpen:
|
||||
sessionController.suppressAgentDraftResultAutoOpen,
|
||||
releaseAgentDraftResultAutoOpenSuppression:
|
||||
@@ -646,9 +647,9 @@ export function PlatformEntryFlowShellImpl({
|
||||
isAgentDraftResultView: sessionController.isAgentDraftResultView,
|
||||
activeAgentSessionId: sessionController.activeAgentSessionId,
|
||||
generatedCustomWorldProfile: sessionController.generatedCustomWorldProfile,
|
||||
agentSessionProfile: sessionController.agentDraftResultProfile,
|
||||
agentSession: sessionController.agentSession,
|
||||
handleCustomWorldSelect,
|
||||
syncAgentDraftResultProfile:
|
||||
autosaveCoordinator.syncAgentDraftResultProfile,
|
||||
executePublishWorld: async () => {
|
||||
const latestSession = await autosaveCoordinator.executeAgentActionAndWait(
|
||||
{
|
||||
@@ -664,6 +665,7 @@ export function PlatformEntryFlowShellImpl({
|
||||
]);
|
||||
return latestSession;
|
||||
},
|
||||
syncAgentCreationResultView: sessionController.syncAgentCreationResultView,
|
||||
setGeneratedCustomWorldProfile:
|
||||
sessionController.setGeneratedCustomWorldProfile,
|
||||
});
|
||||
@@ -1252,7 +1254,9 @@ export function PlatformEntryFlowShellImpl({
|
||||
}
|
||||
|
||||
setBigFishRun((currentRun) =>
|
||||
currentRun ? advanceLocalBigFishRuntimeRun(currentRun, payload) : currentRun,
|
||||
currentRun
|
||||
? advanceLocalBigFishRuntimeRun(currentRun, payload)
|
||||
: currentRun,
|
||||
);
|
||||
},
|
||||
[bigFishRun],
|
||||
@@ -1308,13 +1312,21 @@ export function PlatformEntryFlowShellImpl({
|
||||
nickname: authUi?.user?.displayName?.trim() || '玩家',
|
||||
};
|
||||
|
||||
if (isLocalPuzzleRun(puzzleRun)) {
|
||||
setPuzzleRun(submitLocalPuzzleLeaderboard(puzzleRun, payload.nickname));
|
||||
setIsPuzzleLeaderboardBusy(false);
|
||||
return;
|
||||
}
|
||||
|
||||
void submitPuzzleLeaderboard(puzzleRun.runId, payload)
|
||||
.then(({ run }) => {
|
||||
setPuzzleRun(run);
|
||||
})
|
||||
.catch((error) => {
|
||||
submittedPuzzleLeaderboardKeysRef.current.delete(submitKey);
|
||||
setPuzzleError(resolvePuzzleErrorMessage(error, '提交拼图排行榜失败。'));
|
||||
setPuzzleError(
|
||||
resolvePuzzleErrorMessage(error, '提交拼图排行榜失败。'),
|
||||
);
|
||||
})
|
||||
.finally(() => {
|
||||
setIsPuzzleLeaderboardBusy(false);
|
||||
@@ -1684,25 +1696,25 @@ export function PlatformEntryFlowShellImpl({
|
||||
|
||||
const startBigFishRunFromWork = useCallback(
|
||||
(item: BigFishWorkSummary) => {
|
||||
const sessionId = item.sourceSessionId?.trim();
|
||||
if (!sessionId) {
|
||||
setBigFishError('当前作品缺少会话信息,暂时无法进入玩法。');
|
||||
return;
|
||||
}
|
||||
const sessionId = item.sourceSessionId?.trim();
|
||||
if (!sessionId) {
|
||||
setBigFishError('当前作品缺少会话信息,暂时无法进入玩法。');
|
||||
return;
|
||||
}
|
||||
|
||||
const publicWorkCode = buildBigFishPublicWorkCode(item.sourceSessionId);
|
||||
setBigFishError(null);
|
||||
bigFishFlow.setSession(null);
|
||||
setBigFishRuntimeShare({
|
||||
title: item.title,
|
||||
publicWorkCode,
|
||||
});
|
||||
setBigFishRun(startLocalBigFishRuntimeRun({ work: item }));
|
||||
setSelectionStage('big-fish-runtime');
|
||||
pushAppHistoryPath(
|
||||
buildPublicWorkStagePath('big-fish-runtime', publicWorkCode),
|
||||
);
|
||||
},
|
||||
const publicWorkCode = buildBigFishPublicWorkCode(item.sourceSessionId);
|
||||
setBigFishError(null);
|
||||
bigFishFlow.setSession(null);
|
||||
setBigFishRuntimeShare({
|
||||
title: item.title,
|
||||
publicWorkCode,
|
||||
});
|
||||
setBigFishRun(startLocalBigFishRuntimeRun({ work: item }));
|
||||
setSelectionStage('big-fish-runtime');
|
||||
pushAppHistoryPath(
|
||||
buildPublicWorkStagePath('big-fish-runtime', publicWorkCode),
|
||||
);
|
||||
},
|
||||
[bigFishFlow, setSelectionStage],
|
||||
);
|
||||
|
||||
@@ -2532,17 +2544,17 @@ export function PlatformEntryFlowShellImpl({
|
||||
<Suspense
|
||||
fallback={<LazyPanelFallback label="正在加载拼图玩法..." />}
|
||||
>
|
||||
<PuzzleRuntimeShell
|
||||
run={puzzleRun}
|
||||
isBusy={
|
||||
isPuzzleBusy ||
|
||||
isPuzzleNextLevelGenerating ||
|
||||
isPuzzleLeaderboardBusy
|
||||
}
|
||||
error={puzzleError}
|
||||
onBack={() => {
|
||||
setSelectionStage(puzzleRuntimeReturnStage);
|
||||
}}
|
||||
<PuzzleRuntimeShell
|
||||
run={puzzleRun}
|
||||
isBusy={
|
||||
isPuzzleBusy ||
|
||||
isPuzzleNextLevelGenerating ||
|
||||
isPuzzleLeaderboardBusy
|
||||
}
|
||||
error={puzzleError}
|
||||
onBack={() => {
|
||||
setSelectionStage(puzzleRuntimeReturnStage);
|
||||
}}
|
||||
onSwapPieces={(payload) => {
|
||||
void swapPuzzlePiecesInRun(payload);
|
||||
}}
|
||||
@@ -2627,9 +2639,7 @@ export function PlatformEntryFlowShellImpl({
|
||||
progressLabel=""
|
||||
error={resultViewError}
|
||||
onProfileChange={(profile) => {
|
||||
sessionController.setGeneratedCustomWorldProfile(
|
||||
normalizeAgentBackedProfile(profile),
|
||||
);
|
||||
sessionController.setGeneratedCustomWorldProfile(profile);
|
||||
}}
|
||||
onBack={
|
||||
sessionController.isAgentDraftResultView
|
||||
@@ -2699,23 +2709,25 @@ export function PlatformEntryFlowShellImpl({
|
||||
kind === 'landmark'
|
||||
? 'generate_landmarks'
|
||||
: 'generate_characters';
|
||||
const latestSession =
|
||||
await autosaveCoordinator.executeAgentActionAndWait(
|
||||
{
|
||||
action,
|
||||
count: 1,
|
||||
...(kind === 'playable'
|
||||
? { roleType: 'playable' as const }
|
||||
: kind === 'story'
|
||||
? { roleType: 'story' as const }
|
||||
: {}),
|
||||
},
|
||||
await autosaveCoordinator.executeAgentActionAndWait({
|
||||
action,
|
||||
count: 1,
|
||||
...(kind === 'playable'
|
||||
? { roleType: 'playable' as const }
|
||||
: kind === 'story'
|
||||
? { roleType: 'story' as const }
|
||||
: {}),
|
||||
});
|
||||
const latestView =
|
||||
sessionController.activeAgentSessionId
|
||||
? await sessionController.syncAgentCreationResultView(
|
||||
sessionController.activeAgentSessionId,
|
||||
)
|
||||
: null;
|
||||
const latestProfile =
|
||||
rpgCreationPreviewAdapter.buildPreviewFromResultView(
|
||||
latestView,
|
||||
);
|
||||
const latestProfile = latestSession
|
||||
? rpgCreationPreviewAdapter.buildPreviewFromSession(
|
||||
latestSession,
|
||||
)
|
||||
: null;
|
||||
if (latestProfile) {
|
||||
sessionController.setGeneratedCustomWorldProfile(
|
||||
latestProfile,
|
||||
@@ -2729,17 +2741,21 @@ export function PlatformEntryFlowShellImpl({
|
||||
sessionController.isAgentDraftResultView
|
||||
? async (kind, ids) => {
|
||||
if (ids.length === 0) return;
|
||||
const latestSession =
|
||||
await autosaveCoordinator.executeAgentActionAndWait(
|
||||
kind === 'story'
|
||||
? { action: 'delete_characters', roleIds: ids }
|
||||
: { action: 'delete_landmarks', sceneIds: ids },
|
||||
await autosaveCoordinator.executeAgentActionAndWait(
|
||||
kind === 'story'
|
||||
? { action: 'delete_characters', roleIds: ids }
|
||||
: { action: 'delete_landmarks', sceneIds: ids },
|
||||
);
|
||||
const latestView =
|
||||
sessionController.activeAgentSessionId
|
||||
? await sessionController.syncAgentCreationResultView(
|
||||
sessionController.activeAgentSessionId,
|
||||
)
|
||||
: null;
|
||||
const latestProfile =
|
||||
rpgCreationPreviewAdapter.buildPreviewFromResultView(
|
||||
latestView,
|
||||
);
|
||||
const latestProfile = latestSession
|
||||
? rpgCreationPreviewAdapter.buildPreviewFromSession(
|
||||
latestSession,
|
||||
)
|
||||
: null;
|
||||
if (latestProfile) {
|
||||
sessionController.setGeneratedCustomWorldProfile(
|
||||
latestProfile,
|
||||
|
||||
@@ -11,10 +11,12 @@ export type PlatformCreationTypeCard = {
|
||||
subtitle: string;
|
||||
badge: string;
|
||||
locked: boolean;
|
||||
hidden?: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* 创作页与类型弹层共用同一份模板元数据,避免多入口文案和可用状态漂移。
|
||||
* `hidden` 只控制平台入口是否展示,不影响既有玩法链路和路由能力。
|
||||
*/
|
||||
export const PLATFORM_CREATION_TYPES: PlatformCreationTypeCard[] = [
|
||||
{
|
||||
@@ -30,6 +32,7 @@ export const PLATFORM_CREATION_TYPES: PlatformCreationTypeCard[] = [
|
||||
subtitle: '实时成长玩法',
|
||||
badge: '可创建',
|
||||
locked: false,
|
||||
hidden: true,
|
||||
},
|
||||
{
|
||||
id: 'puzzle',
|
||||
|
||||
@@ -4,6 +4,5 @@
|
||||
*/
|
||||
export {
|
||||
buildCreationHubFallbackItems,
|
||||
normalizeAgentBackedProfile,
|
||||
resolveRpgCreationErrorMessage,
|
||||
} from '../rpg-entry/rpgEntryShared';
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type {
|
||||
CustomWorldAgentSessionSnapshot,
|
||||
} from '../../../packages/shared/src/contracts/customWorldAgent';
|
||||
import type { RpgCreationResultView } from '../../../packages/shared/src/contracts/rpgCreationResultView';
|
||||
import type { HydratedSavedGameSnapshot } from '../../persistence/runtimeSnapshotTypes';
|
||||
import type { CustomWorldProfile } from '../../types';
|
||||
|
||||
@@ -37,6 +38,7 @@ export type CustomWorldAutoSaveState = 'idle' | 'saving' | 'saved' | 'error';
|
||||
export type SyncedAgentDraftResult = {
|
||||
session: CustomWorldAgentSessionSnapshot | null;
|
||||
profile: CustomWorldProfile | null;
|
||||
view?: RpgCreationResultView | null;
|
||||
};
|
||||
|
||||
export type PlatformEntryFlowShellProps = {
|
||||
|
||||
Reference in New Issue
Block a user