feat: integrate jump-hop shelf and asset flow
This commit is contained in:
@@ -177,9 +177,10 @@ import {
|
||||
type JumpHopRunResponse,
|
||||
type JumpHopSessionResponse,
|
||||
type JumpHopSessionSnapshotResponse,
|
||||
type JumpHopWorkProfileResponse,
|
||||
type JumpHopWorkspaceCreateRequest,
|
||||
JumpHopWorkProfileResponse,
|
||||
JumpHopWorkspaceCreateRequest,
|
||||
} from '../../services/jump-hop/jumpHopClient';
|
||||
import type { JumpHopWorkSummaryResponse } from '../../../packages/shared/src/contracts/jumpHop';
|
||||
import { match3dCreationClient } from '../../services/match3d-creation';
|
||||
import { createServerMatch3DRuntimeAdapter } from '../../services/match3d-runtime';
|
||||
import {
|
||||
@@ -1853,7 +1854,7 @@ function hasRecoverableGeneratedPuzzleDraft(
|
||||
);
|
||||
}
|
||||
|
||||
function getGenerationNoticeShelfKeys(item: CreationWorkShelfItem) {
|
||||
function getGenerationNoticeShelfKeys(item: CreationWorkShelfItem): string[] {
|
||||
switch (item.source.kind) {
|
||||
case 'rpg':
|
||||
return collectDraftNoticeKeys('rpg', [
|
||||
@@ -1882,6 +1883,13 @@ function getGenerationNoticeShelfKeys(item: CreationWorkShelfItem) {
|
||||
item.source.item.profileId,
|
||||
item.source.item.sourceSessionId,
|
||||
]);
|
||||
case 'jump-hop':
|
||||
return collectDraftNoticeKeys('jump-hop', [
|
||||
item.id,
|
||||
item.source.item.workId,
|
||||
item.source.item.profileId,
|
||||
item.source.item.sourceSessionId,
|
||||
]);
|
||||
case 'puzzle':
|
||||
return collectDraftNoticeKeys('puzzle', [
|
||||
item.id,
|
||||
@@ -1967,6 +1975,39 @@ function buildPendingBigFishWorks(
|
||||
}));
|
||||
}
|
||||
|
||||
function buildPendingJumpHopWorks(
|
||||
pending: Record<string, PendingDraftShelfState> | undefined,
|
||||
existingItems: readonly JumpHopWorkSummaryResponse[],
|
||||
): JumpHopWorkSummaryResponse[] {
|
||||
if (!pending) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return Object.entries(pending)
|
||||
.filter(([sessionId]) =>
|
||||
existingItems.every((item) => item.sourceSessionId !== sessionId),
|
||||
)
|
||||
.map(([sessionId, state]) => ({
|
||||
runtimeKind: 'jump-hop',
|
||||
workId: `jump-hop-work-${sessionId}`,
|
||||
profileId: `jump-hop-profile-${sessionId}`,
|
||||
ownerUserId: '',
|
||||
sourceSessionId: sessionId,
|
||||
workTitle: '跳一跳草稿',
|
||||
workDescription: '正在生成跳一跳玩法草稿。',
|
||||
themeTags: [],
|
||||
difficulty: 'standard',
|
||||
stylePreset: 'minimal-blocks',
|
||||
coverImageSrc: null,
|
||||
publicationStatus: 'draft',
|
||||
playCount: 0,
|
||||
updatedAt: state.updatedAt,
|
||||
publishedAt: null,
|
||||
publishReady: false,
|
||||
generationStatus: state.status === 'generating' ? 'generating' : 'ready',
|
||||
}));
|
||||
}
|
||||
|
||||
function buildPendingMatch3DWorks(
|
||||
pending: Record<string, PendingDraftShelfState> | undefined,
|
||||
existingItems: readonly Match3DWorkSummary[],
|
||||
@@ -2637,6 +2678,9 @@ export function PlatformEntryFlowShellImpl({
|
||||
const [jumpHopGalleryEntries, setJumpHopGalleryEntries] = useState<
|
||||
JumpHopGalleryCardResponse[]
|
||||
>([]);
|
||||
const [jumpHopWorks, setJumpHopWorks] = useState<
|
||||
JumpHopWorkSummaryResponse[]
|
||||
>([]);
|
||||
const [jumpHopRuntimeReturnStage, setJumpHopRuntimeReturnStage] =
|
||||
useState<JumpHopRuntimeReturnStage>('jump-hop-result');
|
||||
const [jumpHopGenerationState, setJumpHopGenerationState] =
|
||||
@@ -2855,6 +2899,10 @@ export function PlatformEntryFlowShellImpl({
|
||||
creationEntryTypes,
|
||||
'big-fish',
|
||||
);
|
||||
const isJumpHopCreationVisible = isPlatformCreationTypeVisible(
|
||||
creationEntryTypes,
|
||||
'jump-hop',
|
||||
);
|
||||
const isSquareHoleCreationVisible = isPlatformCreationTypeVisible(
|
||||
creationEntryTypes,
|
||||
'square-hole',
|
||||
@@ -3304,6 +3352,22 @@ export function PlatformEntryFlowShellImpl({
|
||||
}
|
||||
}, []);
|
||||
|
||||
const refreshJumpHopShelf = useCallback(async () => {
|
||||
if (!isJumpHopCreationVisible) {
|
||||
setJumpHopWorks([]);
|
||||
return [];
|
||||
}
|
||||
|
||||
try {
|
||||
const worksResponse = await jumpHopClient.listWorks();
|
||||
setJumpHopWorks(worksResponse.items);
|
||||
return worksResponse.items;
|
||||
} catch {
|
||||
setJumpHopWorks([]);
|
||||
return [];
|
||||
}
|
||||
}, [isJumpHopCreationVisible]);
|
||||
|
||||
const refreshWoodenFishGallery = useCallback(async () => {
|
||||
try {
|
||||
const galleryResponse = await woodenFishClient.listGallery();
|
||||
@@ -3513,6 +3577,22 @@ export function PlatformEntryFlowShellImpl({
|
||||
selectionStage,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!platformBootstrap.canReadProtectedData) {
|
||||
setJumpHopWorks([]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (platformBootstrap.platformTab === 'create' || selectionStage === 'platform') {
|
||||
void refreshJumpHopShelf();
|
||||
}
|
||||
}, [
|
||||
platformBootstrap.canReadProtectedData,
|
||||
platformBootstrap.platformTab,
|
||||
refreshJumpHopShelf,
|
||||
selectionStage,
|
||||
]);
|
||||
|
||||
const sessionController = useRpgCreationSessionController({
|
||||
userId: authUi?.user?.id,
|
||||
openLoginModal: authUi?.openLoginModal,
|
||||
@@ -3860,6 +3940,16 @@ export function PlatformEntryFlowShellImpl({
|
||||
],
|
||||
[bigFishWorks, pendingDraftShelfItems],
|
||||
);
|
||||
const jumpHopShelfItems = useMemo(
|
||||
() => [
|
||||
...buildPendingJumpHopWorks(
|
||||
pendingDraftShelfItems['jump-hop'],
|
||||
jumpHopWorks,
|
||||
),
|
||||
...jumpHopWorks,
|
||||
],
|
||||
[jumpHopWorks, pendingDraftShelfItems],
|
||||
);
|
||||
const match3dShelfItems = useMemo(
|
||||
() => [
|
||||
...buildPendingMatch3DWorks(pendingDraftShelfItems.match3d, match3dWorks),
|
||||
@@ -3935,6 +4025,13 @@ export function PlatformEntryFlowShellImpl({
|
||||
...bigFishShelfItems.flatMap((item) =>
|
||||
collectDraftNoticeKeys('big-fish', [item.workId, item.sourceSessionId]),
|
||||
),
|
||||
...jumpHopShelfItems.flatMap((item) =>
|
||||
collectDraftNoticeKeys('jump-hop', [
|
||||
item.workId,
|
||||
item.profileId,
|
||||
item.sourceSessionId,
|
||||
]),
|
||||
),
|
||||
...match3dShelfItems.flatMap((item) =>
|
||||
collectDraftNoticeKeys('match3d', [
|
||||
item.workId,
|
||||
@@ -3977,6 +4074,7 @@ export function PlatformEntryFlowShellImpl({
|
||||
babyObjectMatchDrafts,
|
||||
barkBattleShelfItems,
|
||||
bigFishShelfItems,
|
||||
jumpHopShelfItems,
|
||||
creationHubItems,
|
||||
isSquareHoleCreationVisible,
|
||||
match3dShelfItems,
|
||||
@@ -7312,6 +7410,22 @@ export function PlatformEntryFlowShellImpl({
|
||||
setJumpHopSession(response.session);
|
||||
setJumpHopWork(response.work ?? null);
|
||||
setJumpHopGenerationState(readyState);
|
||||
if (response.work) {
|
||||
setJumpHopWorks((current) =>
|
||||
[response.work!.summary, ...current.filter((item) => item.workId !== response.work!.summary.workId)],
|
||||
);
|
||||
markPendingDraftReady('jump-hop', created.session.sessionId, false);
|
||||
markDraftReady(
|
||||
'jump-hop',
|
||||
[
|
||||
created.session.sessionId,
|
||||
response.work.summary.workId,
|
||||
response.work.summary.profileId,
|
||||
],
|
||||
false,
|
||||
);
|
||||
void refreshJumpHopShelf().catch(() => undefined);
|
||||
}
|
||||
setSelectionStage('jump-hop-result');
|
||||
} catch (error) {
|
||||
const errorMessage = resolveRpgCreationErrorMessage(
|
||||
@@ -7426,6 +7540,10 @@ export function PlatformEntryFlowShellImpl({
|
||||
try {
|
||||
const response = await jumpHopClient.publishWork(profileId);
|
||||
setJumpHopWork(response.item);
|
||||
setJumpHopWorks((current) =>
|
||||
[response.item.summary, ...current.filter((item) => item.workId !== response.item.summary.workId)],
|
||||
);
|
||||
void refreshJumpHopShelf().catch(() => undefined);
|
||||
openPublishShareModal({
|
||||
title: response.item.summary.workTitle || '跳一跳',
|
||||
publicWorkCode: buildJumpHopPublicWorkCode(
|
||||
@@ -10121,6 +10239,43 @@ export function PlatformEntryFlowShellImpl({
|
||||
[openPublicWorkDetail, setJumpHopError, setSelectionStage],
|
||||
);
|
||||
|
||||
const openJumpHopDraft = useCallback(
|
||||
async (item: JumpHopWorkSummaryResponse) => {
|
||||
markDraftNoticeSeen(
|
||||
collectDraftNoticeKeys('jump-hop', [
|
||||
item.workId,
|
||||
item.profileId,
|
||||
item.sourceSessionId,
|
||||
]),
|
||||
);
|
||||
|
||||
if (item.publicationStatus === 'published') {
|
||||
void openJumpHopPublicWorkDetail(item.profileId);
|
||||
return;
|
||||
}
|
||||
|
||||
setJumpHopError(null);
|
||||
setPublicWorkDetailError(null);
|
||||
setIsJumpHopBusy(true);
|
||||
try {
|
||||
const detail = await jumpHopClient.getWorkDetail(item.profileId);
|
||||
setJumpHopSession(null);
|
||||
setJumpHopRun(null);
|
||||
setJumpHopWork(detail.item);
|
||||
setJumpHopRuntimeReturnStage('jump-hop-result');
|
||||
enterCreateTab();
|
||||
setSelectionStage('jump-hop-result');
|
||||
} catch (error) {
|
||||
setJumpHopError(
|
||||
resolveRpgCreationErrorMessage(error, '读取跳一跳草稿失败。'),
|
||||
);
|
||||
} finally {
|
||||
setIsJumpHopBusy(false);
|
||||
}
|
||||
},
|
||||
[enterCreateTab, markDraftNoticeSeen, openPublicWorkDetail, setSelectionStage],
|
||||
);
|
||||
|
||||
const openWoodenFishPublicWorkDetail = useCallback(
|
||||
async (profileId: string) => {
|
||||
setIsPublicWorkDetailBusy(true);
|
||||
@@ -12842,6 +12997,7 @@ export function PlatformEntryFlowShellImpl({
|
||||
deletingWorkId={deletingCreationWorkId}
|
||||
rpgLibraryEntries={platformBootstrap.savedCustomWorldEntries}
|
||||
bigFishItems={isBigFishCreationVisible ? bigFishShelfItems : []}
|
||||
jumpHopItems={isJumpHopCreationVisible ? jumpHopShelfItems : []}
|
||||
onOpenBigFishDetail={
|
||||
isBigFishCreationVisible
|
||||
? (item) => {
|
||||
@@ -12851,6 +13007,15 @@ export function PlatformEntryFlowShellImpl({
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
onOpenJumpHopDetail={
|
||||
isJumpHopCreationVisible
|
||||
? (item) => {
|
||||
runProtectedAction(() => {
|
||||
void openJumpHopDraft(item);
|
||||
});
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
onDeleteBigFish={
|
||||
isBigFishCreationVisible
|
||||
? (item) => {
|
||||
@@ -12858,6 +13023,7 @@ export function PlatformEntryFlowShellImpl({
|
||||
}
|
||||
: null
|
||||
}
|
||||
onDeleteJumpHop={null}
|
||||
match3dItems={match3dShelfItems}
|
||||
onOpenMatch3DDetail={(item) => {
|
||||
runProtectedAction(() => {
|
||||
|
||||
Reference in New Issue
Block a user