refactor: 收口推荐运行态启动意图
This commit is contained in:
@@ -361,15 +361,7 @@ import {
|
||||
selectAdjacentPlatformRecommendEntry,
|
||||
} from '../rpg-entry/rpgEntryPublicGalleryViewModel';
|
||||
import {
|
||||
isBarkBattleGalleryEntry,
|
||||
isBigFishGalleryEntry,
|
||||
isEdutainmentGalleryEntry,
|
||||
isJumpHopGalleryEntry,
|
||||
isMatch3DGalleryEntry,
|
||||
isPuzzleGalleryEntry,
|
||||
isSquareHoleGalleryEntry,
|
||||
isVisualNovelGalleryEntry,
|
||||
isWoodenFishGalleryEntry,
|
||||
mapBabyObjectMatchDraftToPlatformGalleryCard,
|
||||
mapBarkBattleWorkToPlatformGalleryCard,
|
||||
mapBigFishWorkToPlatformGalleryCard,
|
||||
@@ -514,15 +506,12 @@ import {
|
||||
isSamePlatformPublicGalleryEntry,
|
||||
mergePlatformPublicGalleryEntries,
|
||||
type RecommendRuntimeKind,
|
||||
resolvePlatformRecommendRuntimeStartIntent,
|
||||
} from './platformPublicGalleryFlow';
|
||||
import {
|
||||
mapBarkBattlePublicDetailToWorkSummary,
|
||||
mapBarkBattleWorkToPublicWorkDetail,
|
||||
mapBigFishWorkToPublicWorkDetail,
|
||||
mapJumpHopWorkToPublicWorkDetail,
|
||||
mapPublicWorkDetailToBigFishWork,
|
||||
mapPublicWorkDetailToPuzzleWork,
|
||||
mapPublicWorkDetailToSquareHoleWork,
|
||||
mapPuzzleWorkToPublicWorkDetail,
|
||||
mapRpgGalleryCardToPublicWorkDetail,
|
||||
mapSquareHoleWorkToPublicWorkDetail,
|
||||
@@ -12762,98 +12751,99 @@ export function PlatformEntryFlowShellImpl({
|
||||
|
||||
try {
|
||||
let started = false;
|
||||
if (isBigFishGalleryEntry(entry)) {
|
||||
const work = mapPublicWorkDetailToBigFishWork(entry);
|
||||
if (!work) {
|
||||
setBigFishError('当前作品缺少会话信息,暂时无法进入玩法。');
|
||||
} else {
|
||||
started = await startBigFishRunFromWork(work, 'platform', {
|
||||
embedded: true,
|
||||
const intent = resolvePlatformRecommendRuntimeStartIntent(entry, {
|
||||
selectedPuzzleDetail,
|
||||
barkBattleGalleryEntries,
|
||||
mapMatch3DWork: mapPublicWorkDetailToMatch3DWork,
|
||||
});
|
||||
|
||||
switch (intent.type) {
|
||||
case 'blocked':
|
||||
if (intent.errorTarget === 'big-fish') {
|
||||
setBigFishError(intent.errorMessage);
|
||||
} else if (intent.errorTarget === 'puzzle') {
|
||||
setPuzzleError(intent.errorMessage);
|
||||
} else if (intent.errorTarget === 'match3d') {
|
||||
setMatch3DError(intent.errorMessage);
|
||||
} else if (intent.errorTarget === 'square-hole') {
|
||||
setSquareHoleError(intent.errorMessage);
|
||||
} else {
|
||||
setBarkBattleError(intent.errorMessage);
|
||||
}
|
||||
break;
|
||||
case 'start-big-fish':
|
||||
started = await startBigFishRunFromWork(intent.work, 'platform', {
|
||||
embedded: intent.embedded,
|
||||
});
|
||||
}
|
||||
} else if (isPuzzleGalleryEntry(entry)) {
|
||||
const work =
|
||||
selectedPuzzleDetail?.profileId === entry.profileId
|
||||
? selectedPuzzleDetail
|
||||
: mapPublicWorkDetailToPuzzleWork(entry);
|
||||
if (!work) {
|
||||
setPuzzleError('当前拼图作品信息不完整,暂时无法进入玩法。');
|
||||
} else {
|
||||
break;
|
||||
case 'start-puzzle':
|
||||
started = await startPuzzleRunFromProfile(
|
||||
work.profileId,
|
||||
'platform',
|
||||
work,
|
||||
intent.work.profileId,
|
||||
intent.returnStage,
|
||||
intent.work,
|
||||
false,
|
||||
null,
|
||||
{ embedded: true },
|
||||
{ embedded: intent.embedded },
|
||||
);
|
||||
}
|
||||
} else if (isJumpHopGalleryEntry(entry)) {
|
||||
started = await startJumpHopRunFromProfile(entry.profileId, {
|
||||
embedded: true,
|
||||
returnStage: 'platform',
|
||||
});
|
||||
} else if (isWoodenFishGalleryEntry(entry)) {
|
||||
started = await startWoodenFishRunFromProfile(entry.profileId, {
|
||||
embedded: true,
|
||||
returnStage: 'platform',
|
||||
});
|
||||
} else if (isMatch3DGalleryEntry(entry)) {
|
||||
const work = mapPublicWorkDetailToMatch3DWork(entry);
|
||||
if (!work) {
|
||||
setMatch3DError('当前抓大鹅作品信息不完整,暂时无法进入玩法。');
|
||||
} else {
|
||||
started = await startMatch3DRunFromProfile(
|
||||
work,
|
||||
'work-detail',
|
||||
false,
|
||||
{ embedded: true },
|
||||
);
|
||||
}
|
||||
} else if (isSquareHoleGalleryEntry(entry)) {
|
||||
const work = mapPublicWorkDetailToSquareHoleWork(entry);
|
||||
if (!work) {
|
||||
setSquareHoleError(
|
||||
'当前方洞挑战作品信息不完整,暂时无法进入玩法。',
|
||||
);
|
||||
} else {
|
||||
started = await startSquareHoleRunFromProfile(
|
||||
work,
|
||||
'platform',
|
||||
false,
|
||||
{ embedded: true },
|
||||
);
|
||||
}
|
||||
} else if (isVisualNovelGalleryEntry(entry)) {
|
||||
started = await startVisualNovelRunFromProfile(
|
||||
entry.profileId,
|
||||
'platform',
|
||||
{ embedded: true },
|
||||
);
|
||||
} else if (isBarkBattleGalleryEntry(entry)) {
|
||||
const work =
|
||||
barkBattleGalleryEntries.find(
|
||||
(item) => item.workId === entry.workId,
|
||||
) ?? mapBarkBattlePublicDetailToWorkSummary(entry);
|
||||
if (!work) {
|
||||
setBarkBattleError(
|
||||
'当前汪汪声浪作品信息不完整,暂时无法进入玩法。',
|
||||
);
|
||||
} else {
|
||||
started = await startBarkBattleRunFromWork(work, 'platform', {
|
||||
embedded: true,
|
||||
break;
|
||||
case 'start-jump-hop':
|
||||
started = await startJumpHopRunFromProfile(intent.profileId, {
|
||||
embedded: intent.embedded,
|
||||
returnStage: intent.returnStage,
|
||||
});
|
||||
break;
|
||||
case 'start-wooden-fish':
|
||||
started = await startWoodenFishRunFromProfile(intent.profileId, {
|
||||
embedded: intent.embedded,
|
||||
returnStage: intent.returnStage,
|
||||
});
|
||||
break;
|
||||
case 'start-match3d':
|
||||
started = await startMatch3DRunFromProfile(
|
||||
intent.work,
|
||||
intent.returnStage,
|
||||
false,
|
||||
{ embedded: intent.embedded },
|
||||
);
|
||||
break;
|
||||
case 'start-square-hole':
|
||||
started = await startSquareHoleRunFromProfile(
|
||||
intent.work,
|
||||
intent.returnStage,
|
||||
false,
|
||||
{ embedded: intent.embedded },
|
||||
);
|
||||
break;
|
||||
case 'start-visual-novel':
|
||||
started = await startVisualNovelRunFromProfile(
|
||||
intent.profileId,
|
||||
intent.returnStage,
|
||||
{ embedded: intent.embedded },
|
||||
);
|
||||
break;
|
||||
case 'start-bark-battle':
|
||||
started = await startBarkBattleRunFromWork(
|
||||
intent.work,
|
||||
intent.returnStage,
|
||||
{ embedded: intent.embedded },
|
||||
);
|
||||
break;
|
||||
case 'start-edutainment':
|
||||
started = await startBabyObjectMatchRuntimeFromEntry(
|
||||
intent.entry,
|
||||
intent.returnStage,
|
||||
{
|
||||
embedded: intent.embedded,
|
||||
},
|
||||
);
|
||||
break;
|
||||
case 'mark-ready':
|
||||
started = true;
|
||||
break;
|
||||
default: {
|
||||
const exhaustive: never = intent;
|
||||
return exhaustive;
|
||||
}
|
||||
} else if (isEdutainmentGalleryEntry(entry)) {
|
||||
started = await startBabyObjectMatchRuntimeFromEntry(
|
||||
entry,
|
||||
'platform',
|
||||
{
|
||||
embedded: true,
|
||||
},
|
||||
);
|
||||
} else {
|
||||
started = true;
|
||||
}
|
||||
|
||||
if (!isCurrentStartRequest()) {
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { expect, test } from 'vitest';
|
||||
|
||||
import type { BarkBattleWorkSummary } from '../../../packages/shared/src/contracts/barkBattle';
|
||||
import type { Match3DWorkSummary } from '../../../packages/shared/src/contracts/match3dWorks';
|
||||
import type { PuzzleWorkSummary } from '../../../packages/shared/src/contracts/puzzleWorkSummary';
|
||||
import type { CustomWorldGalleryCard } from '../../../packages/shared/src/contracts/runtime';
|
||||
import {
|
||||
EDUTAINMENT_BABY_OBJECT_MATCH_TEMPLATE_ID,
|
||||
@@ -12,8 +15,16 @@ import {
|
||||
getPlatformRecommendRuntimeKind,
|
||||
isSamePlatformPublicGalleryEntry,
|
||||
mergePlatformPublicGalleryEntries,
|
||||
type PlatformRecommendRuntimeStartIntentDeps,
|
||||
type RecommendRuntimeKind,
|
||||
resolvePlatformRecommendRuntimeStartIntent,
|
||||
} from './platformPublicGalleryFlow';
|
||||
import {
|
||||
mapBarkBattlePublicDetailToWorkSummary,
|
||||
mapPublicWorkDetailToBigFishWork,
|
||||
mapPublicWorkDetailToPuzzleWork,
|
||||
mapPublicWorkDetailToSquareHoleWork,
|
||||
} from './platformPublicWorkDetailFlow';
|
||||
|
||||
type TypedPlatformPublicGalleryCard = Extract<
|
||||
PlatformPublicGalleryCard,
|
||||
@@ -109,6 +120,99 @@ function buildTypedEntry(
|
||||
}
|
||||
}
|
||||
|
||||
function buildPuzzleWork(
|
||||
overrides: Partial<PuzzleWorkSummary> = {},
|
||||
): PuzzleWorkSummary {
|
||||
return {
|
||||
workId: 'puzzle-work',
|
||||
profileId: 'puzzle-profile',
|
||||
ownerUserId: 'user-1',
|
||||
sourceSessionId: 'puzzle-session',
|
||||
authorDisplayName: '玩家',
|
||||
levelName: '拼图作品',
|
||||
summary: '拼图摘要',
|
||||
themeTags: ['拼图'],
|
||||
coverImageSrc: '/puzzle-cover.png',
|
||||
publicationStatus: 'published',
|
||||
updatedAt: '2026-06-01T01:00:00.000Z',
|
||||
publishedAt: '2026-06-01T00:00:00.000Z',
|
||||
playCount: 3,
|
||||
remixCount: 2,
|
||||
likeCount: 1,
|
||||
pointIncentiveTotalHalfPoints: 0,
|
||||
pointIncentiveClaimedPoints: 0,
|
||||
pointIncentiveTotalPoints: 0,
|
||||
pointIncentiveClaimablePoints: 0,
|
||||
publishReady: true,
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
function buildMatch3DWork(
|
||||
overrides: Partial<Match3DWorkSummary> = {},
|
||||
): Match3DWorkSummary {
|
||||
return {
|
||||
workId: 'match3d-work',
|
||||
profileId: 'match3d-profile',
|
||||
ownerUserId: 'user-1',
|
||||
sourceSessionId: 'match3d-session',
|
||||
gameName: '抓大鹅作品',
|
||||
themeText: '经典消除',
|
||||
summary: '抓大鹅摘要',
|
||||
tags: ['抓大鹅'],
|
||||
coverImageSrc: '/match3d-cover.png',
|
||||
referenceImageSrc: null,
|
||||
clearCount: 12,
|
||||
difficulty: 4,
|
||||
publicationStatus: 'published',
|
||||
playCount: 10,
|
||||
updatedAt: '2026-06-01T01:00:00.000Z',
|
||||
publishedAt: '2026-06-01T00:00:00.000Z',
|
||||
publishReady: true,
|
||||
generatedItemAssets: [],
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
function buildBarkBattleWork(
|
||||
overrides: Partial<BarkBattleWorkSummary> = {},
|
||||
): BarkBattleWorkSummary {
|
||||
return {
|
||||
workId: 'bark-battle-work',
|
||||
draftId: 'bark-battle-draft',
|
||||
ownerUserId: 'user-1',
|
||||
authorDisplayName: '玩家',
|
||||
title: '汪汪声浪作品',
|
||||
summary: '汪汪摘要',
|
||||
themeDescription: '森林擂台',
|
||||
playerImageDescription: '小狗',
|
||||
opponentImageDescription: '对手',
|
||||
playerCharacterImageSrc: '/player.png',
|
||||
opponentCharacterImageSrc: '/opponent.png',
|
||||
uiBackgroundImageSrc: '/bark-bg.png',
|
||||
difficultyPreset: 'normal',
|
||||
status: 'published',
|
||||
generationStatus: 'ready',
|
||||
publishReady: true,
|
||||
playCount: 9,
|
||||
recentPlayCount7d: 2,
|
||||
updatedAt: '2026-06-01T01:00:00.000Z',
|
||||
publishedAt: '2026-06-01T00:00:00.000Z',
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
function buildRecommendRuntimeStartDeps(
|
||||
overrides: Partial<PlatformRecommendRuntimeStartIntentDeps> = {},
|
||||
): PlatformRecommendRuntimeStartIntentDeps {
|
||||
return {
|
||||
selectedPuzzleDetail: null,
|
||||
barkBattleGalleryEntries: [],
|
||||
mapMatch3DWork: () => buildMatch3DWork(),
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
test('platform public gallery flow resolves stable key and runtime kind for every play kind', () => {
|
||||
const cases: Array<
|
||||
[sourceType: PlatformGallerySourceType, keyKind: string, kind: RecommendRuntimeKind]
|
||||
@@ -160,6 +264,181 @@ test('platform public gallery flow compares entries by resolved identity', () =>
|
||||
expect(isSamePlatformPublicGalleryEntry(left, otherKind)).toBe(false);
|
||||
});
|
||||
|
||||
test('platform public gallery flow resolves recommend runtime start intent', () => {
|
||||
const bigFishEntry = buildTypedEntry('big-fish');
|
||||
expect(
|
||||
resolvePlatformRecommendRuntimeStartIntent(
|
||||
bigFishEntry,
|
||||
buildRecommendRuntimeStartDeps(),
|
||||
),
|
||||
).toEqual({
|
||||
type: 'start-big-fish',
|
||||
work: mapPublicWorkDetailToBigFishWork(bigFishEntry),
|
||||
returnStage: 'platform',
|
||||
embedded: true,
|
||||
});
|
||||
|
||||
const selectedPuzzleDetail = buildPuzzleWork({
|
||||
profileId: 'puzzle-profile',
|
||||
});
|
||||
expect(
|
||||
resolvePlatformRecommendRuntimeStartIntent(
|
||||
buildTypedEntry('puzzle'),
|
||||
buildRecommendRuntimeStartDeps({ selectedPuzzleDetail }),
|
||||
),
|
||||
).toEqual({
|
||||
type: 'start-puzzle',
|
||||
work: selectedPuzzleDetail,
|
||||
returnStage: 'platform',
|
||||
embedded: true,
|
||||
});
|
||||
|
||||
const puzzleEntry = buildTypedEntry('puzzle', {
|
||||
profileId: 'fallback-puzzle-profile',
|
||||
});
|
||||
expect(
|
||||
resolvePlatformRecommendRuntimeStartIntent(
|
||||
puzzleEntry,
|
||||
buildRecommendRuntimeStartDeps({
|
||||
selectedPuzzleDetail: buildPuzzleWork({ profileId: 'stale-profile' }),
|
||||
}),
|
||||
),
|
||||
).toEqual({
|
||||
type: 'start-puzzle',
|
||||
work: mapPublicWorkDetailToPuzzleWork(puzzleEntry),
|
||||
returnStage: 'platform',
|
||||
embedded: true,
|
||||
});
|
||||
|
||||
expect(
|
||||
resolvePlatformRecommendRuntimeStartIntent(
|
||||
buildTypedEntry('jump-hop'),
|
||||
buildRecommendRuntimeStartDeps(),
|
||||
),
|
||||
).toEqual({
|
||||
type: 'start-jump-hop',
|
||||
profileId: 'jump-hop-profile',
|
||||
returnStage: 'platform',
|
||||
embedded: true,
|
||||
});
|
||||
expect(
|
||||
resolvePlatformRecommendRuntimeStartIntent(
|
||||
buildTypedEntry('wooden-fish'),
|
||||
buildRecommendRuntimeStartDeps(),
|
||||
),
|
||||
).toEqual({
|
||||
type: 'start-wooden-fish',
|
||||
profileId: 'wooden-fish-profile',
|
||||
returnStage: 'platform',
|
||||
embedded: true,
|
||||
});
|
||||
expect(
|
||||
resolvePlatformRecommendRuntimeStartIntent(
|
||||
buildTypedEntry('visual-novel'),
|
||||
buildRecommendRuntimeStartDeps(),
|
||||
),
|
||||
).toEqual({
|
||||
type: 'start-visual-novel',
|
||||
profileId: 'visual-novel-profile',
|
||||
returnStage: 'platform',
|
||||
embedded: true,
|
||||
});
|
||||
expect(
|
||||
resolvePlatformRecommendRuntimeStartIntent(
|
||||
buildTypedEntry('edutainment'),
|
||||
buildRecommendRuntimeStartDeps(),
|
||||
),
|
||||
).toEqual({
|
||||
type: 'start-edutainment',
|
||||
entry: buildTypedEntry('edutainment'),
|
||||
returnStage: 'platform',
|
||||
embedded: true,
|
||||
});
|
||||
expect(
|
||||
resolvePlatformRecommendRuntimeStartIntent(
|
||||
buildRpgEntry(),
|
||||
buildRecommendRuntimeStartDeps(),
|
||||
),
|
||||
).toEqual({
|
||||
type: 'mark-ready',
|
||||
});
|
||||
});
|
||||
|
||||
test('platform public gallery flow resolves recommend runtime mapper-backed start intent', () => {
|
||||
const match3DEntry = buildTypedEntry('match3d');
|
||||
const match3DWork = buildMatch3DWork({ workId: 'mapped-match3d-work' });
|
||||
expect(
|
||||
resolvePlatformRecommendRuntimeStartIntent(
|
||||
match3DEntry,
|
||||
buildRecommendRuntimeStartDeps({
|
||||
mapMatch3DWork: (entry) =>
|
||||
entry === match3DEntry ? match3DWork : null,
|
||||
}),
|
||||
),
|
||||
).toEqual({
|
||||
type: 'start-match3d',
|
||||
work: match3DWork,
|
||||
returnStage: 'work-detail',
|
||||
embedded: true,
|
||||
});
|
||||
expect(
|
||||
resolvePlatformRecommendRuntimeStartIntent(
|
||||
match3DEntry,
|
||||
buildRecommendRuntimeStartDeps({ mapMatch3DWork: () => null }),
|
||||
),
|
||||
).toEqual({
|
||||
type: 'blocked',
|
||||
errorTarget: 'match3d',
|
||||
errorMessage: '当前抓大鹅作品信息不完整,暂时无法进入玩法。',
|
||||
});
|
||||
|
||||
const squareHoleEntry = buildTypedEntry('square-hole');
|
||||
expect(
|
||||
resolvePlatformRecommendRuntimeStartIntent(
|
||||
squareHoleEntry,
|
||||
buildRecommendRuntimeStartDeps(),
|
||||
),
|
||||
).toEqual({
|
||||
type: 'start-square-hole',
|
||||
work: mapPublicWorkDetailToSquareHoleWork(squareHoleEntry),
|
||||
returnStage: 'platform',
|
||||
embedded: true,
|
||||
});
|
||||
});
|
||||
|
||||
test('platform public gallery flow resolves recommend runtime bark battle priority', () => {
|
||||
const entry = buildTypedEntry('bark-battle');
|
||||
const galleryWork = buildBarkBattleWork({
|
||||
workId: 'bark-battle-work',
|
||||
title: '推荐缓存',
|
||||
});
|
||||
|
||||
expect(
|
||||
resolvePlatformRecommendRuntimeStartIntent(
|
||||
entry,
|
||||
buildRecommendRuntimeStartDeps({
|
||||
barkBattleGalleryEntries: [galleryWork],
|
||||
}),
|
||||
),
|
||||
).toEqual({
|
||||
type: 'start-bark-battle',
|
||||
work: galleryWork,
|
||||
returnStage: 'platform',
|
||||
embedded: true,
|
||||
});
|
||||
expect(
|
||||
resolvePlatformRecommendRuntimeStartIntent(
|
||||
entry,
|
||||
buildRecommendRuntimeStartDeps(),
|
||||
),
|
||||
).toEqual({
|
||||
type: 'start-bark-battle',
|
||||
work: mapBarkBattlePublicDetailToWorkSummary(entry),
|
||||
returnStage: 'platform',
|
||||
embedded: true,
|
||||
});
|
||||
});
|
||||
|
||||
test('platform public gallery flow merges duplicate identities and sorts newest first', () => {
|
||||
const staleRpgEntry = buildRpgEntry({
|
||||
profileId: 'shared-rpg',
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import type { BarkBattleWorkSummary } from '../../../packages/shared/src/contracts/barkBattle';
|
||||
import type { BigFishWorkSummary } from '../../../packages/shared/src/contracts/bigFishWorkSummary';
|
||||
import type { Match3DWorkSummary } from '../../../packages/shared/src/contracts/match3dWorks';
|
||||
import type { PuzzleWorkSummary } from '../../../packages/shared/src/contracts/puzzleWorkSummary';
|
||||
import type { CustomWorldGalleryCard } from '../../../packages/shared/src/contracts/runtime';
|
||||
import type { SquareHoleWorkSummary } from '../../../packages/shared/src/contracts/squareHoleWorks';
|
||||
import {
|
||||
isBarkBattleGalleryEntry,
|
||||
isBigFishGalleryEntry,
|
||||
@@ -11,6 +16,12 @@ import {
|
||||
isWoodenFishGalleryEntry,
|
||||
type PlatformPublicGalleryCard,
|
||||
} from '../rpg-entry/rpgEntryWorldPresentation';
|
||||
import {
|
||||
mapBarkBattlePublicDetailToWorkSummary,
|
||||
mapPublicWorkDetailToBigFishWork,
|
||||
mapPublicWorkDetailToPuzzleWork,
|
||||
mapPublicWorkDetailToSquareHoleWork,
|
||||
} from './platformPublicWorkDetailFlow';
|
||||
|
||||
export type RecommendRuntimeKind =
|
||||
| 'bark-battle'
|
||||
@@ -24,6 +35,85 @@ export type RecommendRuntimeKind =
|
||||
| 'visual-novel'
|
||||
| 'rpg';
|
||||
|
||||
export type PlatformRecommendRuntimeStartErrorTarget =
|
||||
| 'bark-battle'
|
||||
| 'big-fish'
|
||||
| 'match3d'
|
||||
| 'puzzle'
|
||||
| 'square-hole';
|
||||
|
||||
export type PlatformRecommendRuntimeStartIntent =
|
||||
| {
|
||||
type: 'blocked';
|
||||
errorTarget: PlatformRecommendRuntimeStartErrorTarget;
|
||||
errorMessage: string;
|
||||
}
|
||||
| {
|
||||
type: 'start-big-fish';
|
||||
work: BigFishWorkSummary;
|
||||
returnStage: 'platform';
|
||||
embedded: true;
|
||||
}
|
||||
| {
|
||||
type: 'start-puzzle';
|
||||
work: PuzzleWorkSummary;
|
||||
returnStage: 'platform';
|
||||
embedded: true;
|
||||
}
|
||||
| {
|
||||
type: 'start-jump-hop';
|
||||
profileId: string;
|
||||
returnStage: 'platform';
|
||||
embedded: true;
|
||||
}
|
||||
| {
|
||||
type: 'start-wooden-fish';
|
||||
profileId: string;
|
||||
returnStage: 'platform';
|
||||
embedded: true;
|
||||
}
|
||||
| {
|
||||
type: 'start-match3d';
|
||||
work: Match3DWorkSummary;
|
||||
returnStage: 'work-detail';
|
||||
embedded: true;
|
||||
}
|
||||
| {
|
||||
type: 'start-square-hole';
|
||||
work: SquareHoleWorkSummary;
|
||||
returnStage: 'platform';
|
||||
embedded: true;
|
||||
}
|
||||
| {
|
||||
type: 'start-visual-novel';
|
||||
profileId: string;
|
||||
returnStage: 'platform';
|
||||
embedded: true;
|
||||
}
|
||||
| {
|
||||
type: 'start-bark-battle';
|
||||
work: BarkBattleWorkSummary;
|
||||
returnStage: 'platform';
|
||||
embedded: true;
|
||||
}
|
||||
| {
|
||||
type: 'start-edutainment';
|
||||
entry: PlatformPublicGalleryCard;
|
||||
returnStage: 'platform';
|
||||
embedded: true;
|
||||
}
|
||||
| {
|
||||
type: 'mark-ready';
|
||||
};
|
||||
|
||||
export type PlatformRecommendRuntimeStartIntentDeps = {
|
||||
selectedPuzzleDetail?: PuzzleWorkSummary | null;
|
||||
barkBattleGalleryEntries?: readonly BarkBattleWorkSummary[];
|
||||
mapMatch3DWork: (
|
||||
entry: PlatformPublicGalleryCard,
|
||||
) => Match3DWorkSummary | null;
|
||||
};
|
||||
|
||||
export function getPlatformPublicGalleryEntryTime(
|
||||
entry: PlatformPublicGalleryCard,
|
||||
) {
|
||||
@@ -100,6 +190,148 @@ export function getPlatformRecommendRuntimeKind(
|
||||
return 'rpg';
|
||||
}
|
||||
|
||||
export function resolvePlatformRecommendRuntimeStartIntent(
|
||||
entry: PlatformPublicGalleryCard,
|
||||
deps: PlatformRecommendRuntimeStartIntentDeps,
|
||||
): PlatformRecommendRuntimeStartIntent {
|
||||
if (isBigFishGalleryEntry(entry)) {
|
||||
const work = mapPublicWorkDetailToBigFishWork(entry);
|
||||
if (!work) {
|
||||
return {
|
||||
type: 'blocked',
|
||||
errorTarget: 'big-fish',
|
||||
errorMessage: '当前作品缺少会话信息,暂时无法进入玩法。',
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'start-big-fish',
|
||||
work,
|
||||
returnStage: 'platform',
|
||||
embedded: true,
|
||||
};
|
||||
}
|
||||
|
||||
if (isPuzzleGalleryEntry(entry)) {
|
||||
const work =
|
||||
deps.selectedPuzzleDetail?.profileId === entry.profileId
|
||||
? deps.selectedPuzzleDetail
|
||||
: mapPublicWorkDetailToPuzzleWork(entry);
|
||||
if (!work) {
|
||||
return {
|
||||
type: 'blocked',
|
||||
errorTarget: 'puzzle',
|
||||
errorMessage: '当前拼图作品信息不完整,暂时无法进入玩法。',
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'start-puzzle',
|
||||
work,
|
||||
returnStage: 'platform',
|
||||
embedded: true,
|
||||
};
|
||||
}
|
||||
|
||||
if (isJumpHopGalleryEntry(entry)) {
|
||||
return {
|
||||
type: 'start-jump-hop',
|
||||
profileId: entry.profileId,
|
||||
returnStage: 'platform',
|
||||
embedded: true,
|
||||
};
|
||||
}
|
||||
|
||||
if (isWoodenFishGalleryEntry(entry)) {
|
||||
return {
|
||||
type: 'start-wooden-fish',
|
||||
profileId: entry.profileId,
|
||||
returnStage: 'platform',
|
||||
embedded: true,
|
||||
};
|
||||
}
|
||||
|
||||
if (isMatch3DGalleryEntry(entry)) {
|
||||
// 中文注释:抓大鹅推荐 runtime 仍接 Match3D Module 的 Adapter,避免复制素材归一规则。
|
||||
const work = deps.mapMatch3DWork(entry);
|
||||
if (!work) {
|
||||
return {
|
||||
type: 'blocked',
|
||||
errorTarget: 'match3d',
|
||||
errorMessage: '当前抓大鹅作品信息不完整,暂时无法进入玩法。',
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'start-match3d',
|
||||
work,
|
||||
returnStage: 'work-detail',
|
||||
embedded: true,
|
||||
};
|
||||
}
|
||||
|
||||
if (isSquareHoleGalleryEntry(entry)) {
|
||||
const work = mapPublicWorkDetailToSquareHoleWork(entry);
|
||||
if (!work) {
|
||||
return {
|
||||
type: 'blocked',
|
||||
errorTarget: 'square-hole',
|
||||
errorMessage: '当前方洞挑战作品信息不完整,暂时无法进入玩法。',
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'start-square-hole',
|
||||
work,
|
||||
returnStage: 'platform',
|
||||
embedded: true,
|
||||
};
|
||||
}
|
||||
|
||||
if (isVisualNovelGalleryEntry(entry)) {
|
||||
return {
|
||||
type: 'start-visual-novel',
|
||||
profileId: entry.profileId,
|
||||
returnStage: 'platform',
|
||||
embedded: true,
|
||||
};
|
||||
}
|
||||
|
||||
if (isBarkBattleGalleryEntry(entry)) {
|
||||
const work =
|
||||
deps.barkBattleGalleryEntries?.find(
|
||||
(item) => item.workId === entry.workId,
|
||||
) ?? mapBarkBattlePublicDetailToWorkSummary(entry);
|
||||
if (!work) {
|
||||
return {
|
||||
type: 'blocked',
|
||||
errorTarget: 'bark-battle',
|
||||
errorMessage: '当前汪汪声浪作品信息不完整,暂时无法进入玩法。',
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'start-bark-battle',
|
||||
work,
|
||||
returnStage: 'platform',
|
||||
embedded: true,
|
||||
};
|
||||
}
|
||||
|
||||
if (isEdutainmentGalleryEntry(entry)) {
|
||||
return {
|
||||
type: 'start-edutainment',
|
||||
entry,
|
||||
returnStage: 'platform',
|
||||
embedded: true,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'mark-ready',
|
||||
};
|
||||
}
|
||||
|
||||
export function isSamePlatformPublicGalleryEntry(
|
||||
left: PlatformPublicGalleryCard,
|
||||
right: PlatformPublicGalleryCard,
|
||||
|
||||
Reference in New Issue
Block a user