fix: reconcile architecture adjustment merge
This commit is contained in:
@@ -219,6 +219,7 @@ import {
|
||||
buildSquareHoleGenerationAnchorEntries,
|
||||
buildWoodenFishGenerationAnchorEntries,
|
||||
createMiniGameDraftGenerationState,
|
||||
type MiniGameDraftGenerationKind,
|
||||
type MiniGameDraftGenerationState,
|
||||
resolveMiniGameDraftGenerationStartedAtMs,
|
||||
} from '../../services/miniGameDraftGenerationProgress';
|
||||
@@ -234,6 +235,7 @@ import {
|
||||
buildSquareHolePublicWorkCode,
|
||||
buildVisualNovelPublicWorkCode,
|
||||
buildWoodenFishPublicWorkCode,
|
||||
isSamePuzzleClearPublicWorkCode,
|
||||
isSamePuzzlePublicWorkCode,
|
||||
} from '../../services/publicWorkCode';
|
||||
import {
|
||||
@@ -373,7 +375,12 @@ import {
|
||||
selectAdjacentPlatformRecommendEntry,
|
||||
} from '../rpg-entry/rpgEntryPublicGalleryViewModel';
|
||||
import {
|
||||
isBigFishGalleryEntry,
|
||||
isEdutainmentGalleryEntry,
|
||||
isJumpHopGalleryEntry,
|
||||
isPuzzleGalleryEntry,
|
||||
isPuzzleClearGalleryEntry,
|
||||
mapPuzzleClearWorkToPlatformGalleryCard,
|
||||
mapPuzzleWorkToPlatformGalleryCard,
|
||||
type PlatformPublicGalleryCard,
|
||||
resolvePlatformPublicWorkCode,
|
||||
@@ -415,6 +422,7 @@ import {
|
||||
buildBigFishCreationUrlState,
|
||||
buildJumpHopCreationUrlState,
|
||||
buildMatch3DCreationUrlState,
|
||||
buildPuzzleClearCreationUrlState,
|
||||
buildPuzzleCreationUrlState,
|
||||
buildPuzzleDraftRuntimeUrlState,
|
||||
buildPuzzlePublishedRuntimeUrlState,
|
||||
@@ -456,6 +464,7 @@ import {
|
||||
buildPendingBigFishWorks,
|
||||
buildPendingJumpHopWorks,
|
||||
buildPendingMatch3DWorks,
|
||||
buildPendingPuzzleClearWorks,
|
||||
buildPendingPuzzleWorks,
|
||||
buildPendingSquareHoleWorks,
|
||||
buildPendingVisualNovelWorks,
|
||||
@@ -557,6 +566,8 @@ import {
|
||||
} from './platformMiniGameDraftPayloadModel';
|
||||
import {
|
||||
buildJumpHopPendingSession,
|
||||
buildPuzzleClearPendingSession,
|
||||
buildPuzzleClearSessionFromWorkDetail,
|
||||
buildPuzzleRuntimeWorkFromSession,
|
||||
buildSquareHoleProfileFromSession,
|
||||
buildVisualNovelSessionFromWorkDetail,
|
||||
@@ -752,7 +763,7 @@ async function resumePuzzleProfileSaveArchiveRaw(worldKey: string) {
|
||||
);
|
||||
}
|
||||
|
||||
const RECOMMEND_RUNTIME_BACKGROUND_AUTH_OPTIONS =
|
||||
const RECOMMEND_RUNTIME_BACKGROUND_AUTH_OPTIONS: JumpHopRuntimeRequestOptions =
|
||||
BACKGROUND_AUTH_REQUEST_OPTIONS;
|
||||
const RECOMMEND_PUZZLE_BACKGROUND_AUTH_OPTIONS: JumpHopRuntimeRequestOptions =
|
||||
RECOMMEND_RUNTIME_BACKGROUND_AUTH_OPTIONS;
|
||||
@@ -778,6 +789,16 @@ function resolveCurrentRecommendRuntimeAuthPlan(
|
||||
hasStoredAccessToken: Boolean(getStoredAccessToken()),
|
||||
});
|
||||
}
|
||||
|
||||
function shouldUseRecommendRuntimeGuestAuth(authUi: RecommendRuntimeAuthUi) {
|
||||
return (
|
||||
resolveCurrentRecommendRuntimeAuthPlan(authUi, {
|
||||
embedded: true,
|
||||
allowRuntimeGuestAuth: true,
|
||||
}).requestKind === 'runtime-guest'
|
||||
);
|
||||
}
|
||||
|
||||
async function buildRecommendRuntimeOptionsFromAuthPlan(
|
||||
plan: ReturnType<typeof resolvePlatformRecommendRuntimeAuthPlan>,
|
||||
) {
|
||||
@@ -797,6 +818,28 @@ async function buildRecommendRuntimeAuthOptions(
|
||||
resolveCurrentRecommendRuntimeAuthPlan(authUi, { embedded }),
|
||||
);
|
||||
}
|
||||
|
||||
function resolveRecommendEntryShareStage(
|
||||
entry: PlatformPublicGalleryCard,
|
||||
): PublishShareModalPayload['stage'] {
|
||||
if (isBigFishGalleryEntry(entry)) {
|
||||
return 'big-fish-runtime';
|
||||
}
|
||||
|
||||
if (isPuzzleGalleryEntry(entry)) {
|
||||
return 'puzzle-gallery-detail';
|
||||
}
|
||||
|
||||
return 'work-detail';
|
||||
}
|
||||
|
||||
function pushPuzzleResultHistoryEntry(
|
||||
session: PuzzleAgentSessionSnapshot | null,
|
||||
) {
|
||||
pushAppHistoryPath('/creation/puzzle/result');
|
||||
writeCreationUrlState(buildPuzzleCreationUrlState(session));
|
||||
}
|
||||
|
||||
const PUZZLE_DRAFT_GENERATION_POINT_COST = 2;
|
||||
const MATCH3D_DRAFT_GENERATION_POINT_COST = 10;
|
||||
const BARK_BATTLE_DRAFT_GENERATION_POINT_COST = 3;
|
||||
@@ -2795,6 +2838,7 @@ export function PlatformEntryFlowShellImpl({
|
||||
bigFishEntries: bigFishGalleryEntries,
|
||||
match3dEntries: match3dGalleryEntries,
|
||||
puzzleEntries: puzzleGalleryEntries,
|
||||
puzzleClearEntries: puzzleClearGalleryEntries,
|
||||
barkBattleGalleryEntries,
|
||||
barkBattleWorks,
|
||||
jumpHopEntries: jumpHopGalleryEntries,
|
||||
@@ -12358,6 +12402,12 @@ export function PlatformEntryFlowShellImpl({
|
||||
{ authMode: intent.authMode },
|
||||
);
|
||||
return;
|
||||
case 'start-puzzle-clear':
|
||||
setPublicWorkDetailError(null);
|
||||
void startPuzzleClearRunFromProfile(intent.profileId, {
|
||||
returnStage: intent.returnStage,
|
||||
});
|
||||
return;
|
||||
case 'start-jump-hop':
|
||||
setPublicWorkDetailError(null);
|
||||
void startJumpHopRunFromProfile(intent.profileId, {
|
||||
@@ -12491,6 +12541,8 @@ export function PlatformEntryFlowShellImpl({
|
||||
setBigFishError(intent.errorMessage);
|
||||
} else if (intent.errorTarget === 'puzzle') {
|
||||
setPuzzleError(intent.errorMessage);
|
||||
} else if (intent.errorTarget === 'puzzle-clear') {
|
||||
setPuzzleClearError(intent.errorMessage);
|
||||
} else if (intent.errorTarget === 'match3d') {
|
||||
setMatch3DError(intent.errorMessage);
|
||||
} else if (intent.errorTarget === 'square-hole') {
|
||||
@@ -12514,6 +12566,12 @@ export function PlatformEntryFlowShellImpl({
|
||||
{ embedded: intent.embedded },
|
||||
);
|
||||
break;
|
||||
case 'start-puzzle-clear':
|
||||
started = await startPuzzleClearRunFromProfile(intent.profileId, {
|
||||
embedded: intent.embedded,
|
||||
returnStage: intent.returnStage,
|
||||
});
|
||||
break;
|
||||
case 'start-jump-hop':
|
||||
started = await startJumpHopRunFromProfile(intent.profileId, {
|
||||
embedded: intent.embedded,
|
||||
@@ -13092,6 +13150,7 @@ export function PlatformEntryFlowShellImpl({
|
||||
hasBigFishRun: Boolean(bigFishRun),
|
||||
hasJumpHopRun: Boolean(jumpHopRun),
|
||||
hasMatch3DRun: Boolean(match3dRun),
|
||||
hasPuzzleClearRun: Boolean(puzzleClearRun),
|
||||
hasSquareHoleRun: Boolean(squareHoleRun),
|
||||
hasVisualNovelRun: Boolean(visualNovelRun),
|
||||
hasWoodenFishRun: Boolean(woodenFishRun),
|
||||
@@ -13114,6 +13173,7 @@ export function PlatformEntryFlowShellImpl({
|
||||
hasBigFishRun: Boolean(bigFishRun),
|
||||
hasJumpHopRun: Boolean(jumpHopRun),
|
||||
hasMatch3DRun: Boolean(match3dRun),
|
||||
hasPuzzleClearRun: Boolean(puzzleClearRun),
|
||||
hasSquareHoleRun: Boolean(squareHoleRun),
|
||||
hasVisualNovelRun: Boolean(visualNovelRun),
|
||||
hasWoodenFishRun: Boolean(woodenFishRun),
|
||||
|
||||
@@ -3,6 +3,10 @@ import type { BigFishSessionSnapshotResponse } from '../../../packages/shared/sr
|
||||
import type { BabyObjectMatchDraft } from '../../../packages/shared/src/contracts/edutainmentBabyObject';
|
||||
import type { Match3DAgentSessionSnapshot } from '../../../packages/shared/src/contracts/match3dAgent';
|
||||
import type { PuzzleAgentSessionSnapshot } from '../../../packages/shared/src/contracts/puzzleAgentSession';
|
||||
import type {
|
||||
PuzzleClearSessionSnapshotResponse,
|
||||
PuzzleClearWorkProfileResponse,
|
||||
} from '../../../packages/shared/src/contracts/puzzleClear';
|
||||
import type { PuzzleWorkSummary } from '../../../packages/shared/src/contracts/puzzleWorkSummary';
|
||||
import type { SquareHoleSessionSnapshot } from '../../../packages/shared/src/contracts/squareHoleAgent';
|
||||
import type { VisualNovelAgentSessionSnapshot } from '../../../packages/shared/src/contracts/visualNovel';
|
||||
@@ -393,6 +397,21 @@ export function buildJumpHopCreationUrlState(params: {
|
||||
};
|
||||
}
|
||||
|
||||
export function buildPuzzleClearCreationUrlState(params: {
|
||||
session?: PuzzleClearSessionSnapshotResponse | null;
|
||||
work?: PuzzleClearWorkProfileResponse | null;
|
||||
}): CreationUrlState {
|
||||
const sessionId = normalizeCreationUrlValue(params.session?.sessionId);
|
||||
const profileId = normalizeCreationUrlValue(
|
||||
params.work?.summary.profileId ?? params.session?.draft?.profileId,
|
||||
);
|
||||
return {
|
||||
sessionId,
|
||||
profileId,
|
||||
workId: normalizeCreationUrlValue(params.work?.summary.workId ?? profileId),
|
||||
};
|
||||
}
|
||||
|
||||
export function buildWoodenFishCreationUrlState(params: {
|
||||
session?: WoodenFishSessionSnapshotResponse | null;
|
||||
work?: WoodenFishWorkProfileResponse | null;
|
||||
|
||||
@@ -751,6 +751,7 @@ function buildJumpHopWork(
|
||||
profileId: 'jump-hop-profile-base',
|
||||
ownerUserId: 'user-1',
|
||||
sourceSessionId: 'jump-hop-session-base',
|
||||
themeText: '潮雾港口',
|
||||
workTitle: '潮雾跳一跳',
|
||||
workDescription: '潮雾港口跳一跳。',
|
||||
themeTags: [],
|
||||
|
||||
@@ -4,6 +4,7 @@ import type { CustomWorldWorkSummary } from '../../../packages/shared/src/contra
|
||||
import type { BabyObjectMatchDraft } from '../../../packages/shared/src/contracts/edutainmentBabyObject';
|
||||
import type { JumpHopWorkSummaryResponse } from '../../../packages/shared/src/contracts/jumpHop';
|
||||
import type { Match3DWorkSummary } from '../../../packages/shared/src/contracts/match3dWorks';
|
||||
import type { PuzzleClearWorkSummaryResponse } from '../../../packages/shared/src/contracts/puzzleClear';
|
||||
import type { PuzzleWorkSummary } from '../../../packages/shared/src/contracts/puzzleWorkSummary';
|
||||
import type { SquareHoleWorkSummary } from '../../../packages/shared/src/contracts/squareHoleWorks';
|
||||
import type { VisualNovelWorkSummary } from '../../../packages/shared/src/contracts/visualNovel';
|
||||
@@ -1191,6 +1192,7 @@ export function buildPendingJumpHopWorks(
|
||||
profileId: `jump-hop-profile-${sessionId}`,
|
||||
ownerUserId: '',
|
||||
sourceSessionId: sessionId,
|
||||
themeText: state.title ?? '跳一跳草稿',
|
||||
workTitle: '跳一跳草稿',
|
||||
workDescription:
|
||||
state.status === 'failed'
|
||||
@@ -1210,6 +1212,48 @@ export function buildPendingJumpHopWorks(
|
||||
});
|
||||
}
|
||||
|
||||
export function buildPendingPuzzleClearWorks(
|
||||
pending: Record<string, PendingDraftShelfState> | undefined,
|
||||
existingItems: readonly PuzzleClearWorkSummaryResponse[],
|
||||
): PuzzleClearWorkSummaryResponse[] {
|
||||
if (!pending) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return Object.entries(pending)
|
||||
.filter(([sessionId]) =>
|
||||
existingItems.every((item) => item.sourceSessionId !== sessionId),
|
||||
)
|
||||
.map(([sessionId, state]) => {
|
||||
const generationStatus =
|
||||
state.status === 'failed'
|
||||
? 'failed'
|
||||
: state.status === 'generating'
|
||||
? 'generating'
|
||||
: 'ready';
|
||||
return {
|
||||
runtimeKind: 'puzzle-clear',
|
||||
workId: `puzzle-clear-work-${sessionId}`,
|
||||
profileId: sessionId,
|
||||
ownerUserId: '',
|
||||
sourceSessionId: sessionId,
|
||||
workTitle: '拼消消草稿',
|
||||
workDescription:
|
||||
state.status === 'failed'
|
||||
? '拼消消草稿生成失败,可重新打开处理。'
|
||||
: '正在生成拼消消草稿。',
|
||||
themePrompt: '',
|
||||
coverImageSrc: null,
|
||||
publicationStatus: 'draft',
|
||||
playCount: 0,
|
||||
updatedAt: state.updatedAt,
|
||||
publishedAt: null,
|
||||
publishReady: false,
|
||||
generationStatus,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export function buildPendingWoodenFishWorks(
|
||||
pending: Record<string, PendingDraftShelfState> | undefined,
|
||||
existingItems: readonly WoodenFishWorkSummaryResponse[],
|
||||
|
||||
@@ -213,6 +213,7 @@ function buildJumpHopDraft(
|
||||
templateId: 'jump-hop',
|
||||
templateName: '跳一跳',
|
||||
profileId: 'jump-hop-profile-1',
|
||||
themeText: '草稿主题',
|
||||
workTitle: '草稿跳一跳',
|
||||
workDescription: '从草稿恢复。',
|
||||
themeTags: ['草稿'],
|
||||
@@ -236,6 +237,7 @@ function buildJumpHopPayload(
|
||||
): JumpHopWorkspaceCreateRequest {
|
||||
return {
|
||||
templateId: 'jump-hop',
|
||||
themeText: '表单主题',
|
||||
workTitle: '表单跳一跳',
|
||||
workDescription: '从表单提交。',
|
||||
themeTags: ['表单'],
|
||||
|
||||
@@ -76,7 +76,7 @@ export function buildPuzzleWorkUpdatePayloadFromDraft(
|
||||
}
|
||||
|
||||
export function buildJumpHopDraftActionPayload(
|
||||
actionType: 'compile-draft' | 'regenerate-character' | 'regenerate-tiles',
|
||||
actionType: 'compile-draft' | 'regenerate-tiles',
|
||||
input: {
|
||||
payload?: JumpHopWorkspaceCreateRequest | null;
|
||||
draft?: JumpHopSessionSnapshotResponse['draft'] | null;
|
||||
|
||||
@@ -120,6 +120,7 @@ function buildJumpHopSummary(
|
||||
profileId: 'jump-hop-profile-1',
|
||||
ownerUserId: 'user-1',
|
||||
sourceSessionId: ' jump-hop-session-1 ',
|
||||
themeText: '云阶机关',
|
||||
workTitle: '云阶跳跃',
|
||||
workDescription: '越过云阶。',
|
||||
themeTags: ['云阶'],
|
||||
@@ -522,6 +523,7 @@ describe('platformMiniGameSessionMappingModel', () => {
|
||||
templateId: 'jump-hop',
|
||||
templateName: '跳一跳',
|
||||
profileId: 'jump-hop-profile-1',
|
||||
themeText: '云阶机关',
|
||||
workTitle: '云阶跳跃',
|
||||
workDescription: '越过云阶。',
|
||||
themeTags: ['云阶'],
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
import type { JumpHopSessionSnapshotResponse, JumpHopWorkSummaryResponse } from '../../../packages/shared/src/contracts/jumpHop';
|
||||
import type {
|
||||
JumpHopSessionSnapshotResponse,
|
||||
JumpHopWorkSummaryResponse,
|
||||
} from '../../../packages/shared/src/contracts/jumpHop';
|
||||
import type {
|
||||
PuzzleClearSessionSnapshotResponse,
|
||||
PuzzleClearWorkProfileResponse,
|
||||
PuzzleClearWorkSummaryResponse,
|
||||
} from '../../../packages/shared/src/contracts/puzzleClear';
|
||||
import type { PuzzleAgentSessionSnapshot } from '../../../packages/shared/src/contracts/puzzleAgentSession';
|
||||
import type { PuzzleWorkSummary } from '../../../packages/shared/src/contracts/puzzleWorkSummary';
|
||||
import type { SquareHoleSessionSnapshot } from '../../../packages/shared/src/contracts/squareHoleAgent';
|
||||
@@ -59,6 +67,54 @@ export function buildPuzzleRuntimeWorkFromSession(
|
||||
};
|
||||
}
|
||||
|
||||
export function buildPuzzleClearSessionFromWorkDetail(
|
||||
work: PuzzleClearWorkProfileResponse,
|
||||
fallbackItem?: PuzzleClearWorkSummaryResponse | null,
|
||||
): PuzzleClearSessionSnapshotResponse {
|
||||
const sessionId =
|
||||
normalizeCreationUrlValue(work.summary.sourceSessionId) ??
|
||||
normalizeCreationUrlValue(fallbackItem?.sourceSessionId) ??
|
||||
work.summary.profileId;
|
||||
return {
|
||||
sessionId,
|
||||
ownerUserId: work.summary.ownerUserId,
|
||||
status: work.summary.generationStatus,
|
||||
draft: work.draft,
|
||||
createdAt: work.summary.updatedAt,
|
||||
updatedAt: work.summary.updatedAt,
|
||||
};
|
||||
}
|
||||
|
||||
export function buildPuzzleClearPendingSession(
|
||||
item: PuzzleClearWorkSummaryResponse,
|
||||
): PuzzleClearSessionSnapshotResponse {
|
||||
const sessionId =
|
||||
normalizeCreationUrlValue(item.sourceSessionId) ?? item.profileId;
|
||||
return {
|
||||
sessionId,
|
||||
ownerUserId: item.ownerUserId,
|
||||
status: item.generationStatus,
|
||||
draft: {
|
||||
templateId: 'puzzle-clear',
|
||||
templateName: '拼消消',
|
||||
profileId: item.profileId,
|
||||
workTitle: item.workTitle,
|
||||
workDescription: item.workDescription,
|
||||
themePrompt: item.themePrompt,
|
||||
boardBackgroundPrompt: item.themePrompt,
|
||||
generateBoardBackground: true,
|
||||
boardBackgroundAsset: null,
|
||||
cardBackImageSrc: null,
|
||||
atlasAsset: null,
|
||||
patternGroups: [],
|
||||
cardAssets: [],
|
||||
generationStatus: item.generationStatus,
|
||||
},
|
||||
createdAt: item.updatedAt,
|
||||
updatedAt: item.updatedAt,
|
||||
};
|
||||
}
|
||||
|
||||
export function buildSquareHoleProfileFromSession(
|
||||
session: SquareHoleSessionSnapshot | null,
|
||||
): SquareHoleWorkProfile | null {
|
||||
@@ -122,6 +178,7 @@ export function buildJumpHopPendingSession(
|
||||
templateId: 'jump-hop',
|
||||
templateName: '跳一跳',
|
||||
profileId: item.profileId,
|
||||
themeText: item.themeText,
|
||||
workTitle: item.workTitle,
|
||||
workDescription: item.workDescription,
|
||||
themeTags: item.themeTags,
|
||||
|
||||
@@ -303,6 +303,7 @@ function buildJumpHopCard(
|
||||
profileId,
|
||||
ownerUserId: 'user-1',
|
||||
authorDisplayName: '测试作者',
|
||||
themeText: '潮雾港',
|
||||
workTitle: '潮雾跳一跳',
|
||||
workDescription: '潮雾跳一跳说明。',
|
||||
coverImageSrc: null,
|
||||
|
||||
@@ -128,6 +128,7 @@ function buildJumpHopEntry(
|
||||
profileId: 'jump-hop-profile',
|
||||
ownerUserId: 'user-1',
|
||||
authorDisplayName: '玩家',
|
||||
themeText: '一路向前',
|
||||
workTitle: '跳一跳',
|
||||
workDescription: '一路向前。',
|
||||
coverImageSrc: '/jump-hop-cover.png',
|
||||
@@ -166,6 +167,13 @@ function buildTypedEntry(
|
||||
switch (sourceType) {
|
||||
case 'puzzle':
|
||||
return { ...common, ...overrides, sourceType };
|
||||
case 'puzzle-clear':
|
||||
return {
|
||||
...common,
|
||||
...overrides,
|
||||
sourceType,
|
||||
themePrompt: '拼消消主题',
|
||||
};
|
||||
case 'big-fish':
|
||||
return { ...common, ...overrides, sourceType };
|
||||
case 'match3d':
|
||||
@@ -769,6 +777,7 @@ test('platform public gallery flow builds feeds with visibility gates and bark b
|
||||
bigFishEntries: [hiddenBigFish],
|
||||
match3dEntries: [],
|
||||
puzzleEntries: [],
|
||||
puzzleClearEntries: [],
|
||||
barkBattleGalleryEntries: [],
|
||||
barkBattleWorks: [draftBarkFallback, publishedBarkFallback],
|
||||
jumpHopEntries: [],
|
||||
@@ -793,6 +802,7 @@ test('platform public gallery flow builds feeds with visibility gates and bark b
|
||||
bigFishEntries: [hiddenBigFish],
|
||||
match3dEntries: [],
|
||||
puzzleEntries: [],
|
||||
puzzleClearEntries: [],
|
||||
barkBattleGalleryEntries: [
|
||||
buildBarkBattleWork({
|
||||
workId: 'gallery-bark',
|
||||
@@ -828,6 +838,7 @@ test('platform public gallery flow preserves feed tie order and featured slice',
|
||||
bigFishEntries: [],
|
||||
match3dEntries: [],
|
||||
puzzleEntries: [],
|
||||
puzzleClearEntries: [],
|
||||
barkBattleGalleryEntries: [],
|
||||
barkBattleWorks: [
|
||||
buildBarkBattleWork({
|
||||
@@ -868,6 +879,7 @@ test('platform public gallery flow preserves feed tie order and featured slice',
|
||||
bigFishEntries: [],
|
||||
match3dEntries: [],
|
||||
puzzleEntries: [],
|
||||
puzzleClearEntries: [],
|
||||
barkBattleGalleryEntries: [],
|
||||
barkBattleWorks: [],
|
||||
jumpHopEntries: [],
|
||||
|
||||
@@ -8,12 +8,14 @@ import type { CustomWorldGalleryCard } from '../../../packages/shared/src/contra
|
||||
import type { SquareHoleWorkSummary } from '../../../packages/shared/src/contracts/squareHoleWorks';
|
||||
import type { VisualNovelWorkSummary } from '../../../packages/shared/src/contracts/visualNovel';
|
||||
import type { WoodenFishGalleryCardResponse } from '../../../packages/shared/src/contracts/woodenFish';
|
||||
import type { PuzzleClearGalleryCardResponse } from '../../services/puzzle-clear/puzzleClearClient';
|
||||
import {
|
||||
isBarkBattleGalleryEntry,
|
||||
isBigFishGalleryEntry,
|
||||
isEdutainmentGalleryEntry,
|
||||
isJumpHopGalleryEntry,
|
||||
isMatch3DGalleryEntry,
|
||||
isPuzzleClearGalleryEntry,
|
||||
isPuzzleGalleryEntry,
|
||||
isSquareHoleGalleryEntry,
|
||||
isVisualNovelGalleryEntry,
|
||||
@@ -22,6 +24,7 @@ import {
|
||||
mapBarkBattleWorkToPlatformGalleryCard,
|
||||
mapBigFishWorkToPlatformGalleryCard,
|
||||
mapJumpHopWorkToPlatformGalleryCard,
|
||||
mapPuzzleClearWorkToPlatformGalleryCard,
|
||||
mapPuzzleWorkToPlatformGalleryCard,
|
||||
mapSquareHoleWorkToPlatformGalleryCard,
|
||||
mapVisualNovelWorkToPlatformGalleryCard,
|
||||
@@ -43,6 +46,7 @@ export type RecommendRuntimeKind =
|
||||
| 'jump-hop'
|
||||
| 'match3d'
|
||||
| 'puzzle'
|
||||
| 'puzzle-clear'
|
||||
| 'square-hole'
|
||||
| 'wooden-fish'
|
||||
| 'visual-novel'
|
||||
@@ -53,6 +57,7 @@ export type PlatformRecommendRuntimeStartErrorTarget =
|
||||
| 'big-fish'
|
||||
| 'match3d'
|
||||
| 'puzzle'
|
||||
| 'puzzle-clear'
|
||||
| 'square-hole';
|
||||
|
||||
export type PlatformRecommendRuntimeStartIntent =
|
||||
@@ -73,6 +78,12 @@ export type PlatformRecommendRuntimeStartIntent =
|
||||
returnStage: 'platform';
|
||||
embedded: true;
|
||||
}
|
||||
| {
|
||||
type: 'start-puzzle-clear';
|
||||
profileId: string;
|
||||
returnStage: 'platform';
|
||||
embedded: true;
|
||||
}
|
||||
| {
|
||||
type: 'start-jump-hop';
|
||||
profileId: string;
|
||||
@@ -133,6 +144,7 @@ export type PlatformRecommendRuntimeReadyState = {
|
||||
hasBigFishRun?: boolean;
|
||||
hasJumpHopRun?: boolean;
|
||||
hasMatch3DRun?: boolean;
|
||||
hasPuzzleClearRun?: boolean;
|
||||
hasSquareHoleRun?: boolean;
|
||||
hasVisualNovelRun?: boolean;
|
||||
hasWoodenFishRun?: boolean;
|
||||
@@ -161,6 +173,7 @@ export type PlatformPublicGalleryFeedsInput = {
|
||||
bigFishEntries: readonly BigFishWorkSummary[];
|
||||
match3dEntries: readonly Match3DWorkSummary[];
|
||||
puzzleEntries: readonly PuzzleWorkSummary[];
|
||||
puzzleClearEntries: readonly PuzzleClearGalleryCardResponse[];
|
||||
barkBattleGalleryEntries: readonly BarkBattleWorkSummary[];
|
||||
barkBattleWorks: readonly BarkBattleWorkSummary[];
|
||||
jumpHopEntries: readonly JumpHopGalleryCardResponse[];
|
||||
@@ -194,21 +207,23 @@ export function getPlatformPublicGalleryEntryKey(
|
||||
? 'big-fish'
|
||||
: isPuzzleGalleryEntry(entry)
|
||||
? 'puzzle'
|
||||
: isJumpHopGalleryEntry(entry)
|
||||
? 'jump-hop'
|
||||
: isWoodenFishGalleryEntry(entry)
|
||||
? 'wooden-fish'
|
||||
: isMatch3DGalleryEntry(entry)
|
||||
? 'match3d'
|
||||
: isSquareHoleGalleryEntry(entry)
|
||||
? 'square-hole'
|
||||
: isVisualNovelGalleryEntry(entry)
|
||||
? 'visual-novel'
|
||||
: isBarkBattleGalleryEntry(entry)
|
||||
? 'bark-battle'
|
||||
: isEdutainmentGalleryEntry(entry)
|
||||
? `edutainment:${entry.templateId}`
|
||||
: 'rpg';
|
||||
: isPuzzleClearGalleryEntry(entry)
|
||||
? 'puzzle-clear'
|
||||
: isJumpHopGalleryEntry(entry)
|
||||
? 'jump-hop'
|
||||
: isWoodenFishGalleryEntry(entry)
|
||||
? 'wooden-fish'
|
||||
: isMatch3DGalleryEntry(entry)
|
||||
? 'match3d'
|
||||
: isSquareHoleGalleryEntry(entry)
|
||||
? 'square-hole'
|
||||
: isVisualNovelGalleryEntry(entry)
|
||||
? 'visual-novel'
|
||||
: isBarkBattleGalleryEntry(entry)
|
||||
? 'bark-battle'
|
||||
: isEdutainmentGalleryEntry(entry)
|
||||
? `edutainment:${entry.templateId}`
|
||||
: 'rpg';
|
||||
return `${kind}:${entry.ownerUserId}:${entry.profileId}`;
|
||||
}
|
||||
|
||||
@@ -223,6 +238,10 @@ export function getPlatformRecommendRuntimeKind(
|
||||
return 'puzzle';
|
||||
}
|
||||
|
||||
if (isPuzzleClearGalleryEntry(entry)) {
|
||||
return 'puzzle-clear';
|
||||
}
|
||||
|
||||
if (isJumpHopGalleryEntry(entry)) {
|
||||
return 'jump-hop';
|
||||
}
|
||||
@@ -297,6 +316,15 @@ export function resolvePlatformRecommendRuntimeStartIntent(
|
||||
};
|
||||
}
|
||||
|
||||
if (isPuzzleClearGalleryEntry(entry)) {
|
||||
return {
|
||||
type: 'start-puzzle-clear',
|
||||
profileId: entry.profileId,
|
||||
returnStage: 'platform',
|
||||
embedded: true,
|
||||
};
|
||||
}
|
||||
|
||||
if (isJumpHopGalleryEntry(entry)) {
|
||||
return {
|
||||
type: 'start-jump-hop',
|
||||
@@ -423,6 +451,9 @@ export function isPlatformRecommendRuntimeReadyForEntry(
|
||||
state.puzzleRunCurrentLevelProfileId === entry.profileId
|
||||
);
|
||||
}
|
||||
if (expectedKind === 'puzzle-clear') {
|
||||
return Boolean(state.hasPuzzleClearRun);
|
||||
}
|
||||
if (expectedKind === 'square-hole') {
|
||||
return Boolean(state.hasSquareHoleRun);
|
||||
}
|
||||
@@ -527,6 +558,7 @@ export function buildPlatformPublicGalleryFeeds(
|
||||
...bigFishEntries,
|
||||
...input.match3dEntries.map(mapMatch3DWorkToPublicWorkDetail),
|
||||
...input.puzzleEntries.map(mapPuzzleWorkToPlatformGalleryCard),
|
||||
...input.puzzleClearEntries.map(mapPuzzleClearWorkToPlatformGalleryCard),
|
||||
...barkBattleGalleryEntries,
|
||||
...input.jumpHopEntries.map(mapJumpHopWorkToPlatformGalleryCard),
|
||||
...barkBattleFallbackEntries,
|
||||
@@ -539,6 +571,7 @@ export function buildPlatformPublicGalleryFeeds(
|
||||
...bigFishEntries,
|
||||
...input.match3dEntries.map(mapMatch3DWorkToPublicWorkDetail),
|
||||
...input.puzzleEntries.map(mapPuzzleWorkToPlatformGalleryCard),
|
||||
...input.puzzleClearEntries.map(mapPuzzleClearWorkToPlatformGalleryCard),
|
||||
...(barkBattleGalleryEntries.length > 0
|
||||
? barkBattleGalleryEntries
|
||||
: barkBattleFallbackEntries),
|
||||
|
||||
@@ -6,6 +6,7 @@ import type { JumpHopGalleryCardResponse } from '../../../packages/shared/src/co
|
||||
import type { Match3DWorkSummary } from '../../../packages/shared/src/contracts/match3dWorks';
|
||||
import type { PuzzleRunSnapshot } from '../../../packages/shared/src/contracts/puzzleRuntimeSession';
|
||||
import type { PuzzleWorkSummary } from '../../../packages/shared/src/contracts/puzzleWorkSummary';
|
||||
import type { PuzzleClearGalleryCardResponse } from '../../../packages/shared/src/contracts/puzzleClear';
|
||||
import type {
|
||||
CustomWorldGalleryCard,
|
||||
CustomWorldLibraryEntry,
|
||||
@@ -25,6 +26,7 @@ import {
|
||||
mapBarkBattleWorkToPublicWorkDetail,
|
||||
mapBigFishWorkToPublicWorkDetail,
|
||||
mapJumpHopWorkToPublicWorkDetail,
|
||||
mapPuzzleClearWorkToPublicWorkDetail,
|
||||
mapPublicWorkDetailToBigFishWork,
|
||||
mapPublicWorkDetailToPuzzleWork,
|
||||
mapPublicWorkDetailToSquareHoleWork,
|
||||
@@ -133,6 +135,13 @@ function buildTypedEntry<TSourceType extends PlatformGallerySourceType>(
|
||||
...overrides,
|
||||
sourceType,
|
||||
});
|
||||
case 'puzzle-clear':
|
||||
return narrowTypedEntry<TSourceType>({
|
||||
...common,
|
||||
...overrides,
|
||||
sourceType,
|
||||
themePrompt: '拼消消主题',
|
||||
});
|
||||
case 'big-fish':
|
||||
return narrowTypedEntry<TSourceType>({
|
||||
...common,
|
||||
@@ -324,6 +333,7 @@ function buildJumpHopGalleryCard(
|
||||
profileId: 'jump-hop-profile',
|
||||
ownerUserId: 'user-1',
|
||||
authorDisplayName: '玩家',
|
||||
themeText: '跳一跳',
|
||||
workTitle: '跳一跳作品',
|
||||
workDescription: '跳一跳摘要',
|
||||
coverImageSrc: '/jump-hop-cover.png',
|
||||
@@ -339,6 +349,31 @@ function buildJumpHopGalleryCard(
|
||||
};
|
||||
}
|
||||
|
||||
function buildPuzzleClearGalleryCard(
|
||||
overrides: Partial<PuzzleClearGalleryCardResponse> = {},
|
||||
): PuzzleClearGalleryCardResponse {
|
||||
return {
|
||||
runtimeKind: 'puzzle-clear',
|
||||
publicWorkCode: 'PCLR-0001',
|
||||
workId: 'puzzle-clear-work',
|
||||
profileId: 'puzzle-clear-profile',
|
||||
ownerUserId: 'user-1',
|
||||
sourceSessionId: 'puzzle-clear-session',
|
||||
authorDisplayName: '玩家',
|
||||
workTitle: '拼消消作品',
|
||||
workDescription: '拼消消摘要',
|
||||
themePrompt: '水果',
|
||||
coverImageSrc: '/puzzle-clear-cover.png',
|
||||
publicationStatus: 'published',
|
||||
playCount: 6,
|
||||
updatedAt: '2026-06-01T01:00:00.000Z',
|
||||
publishedAt: '2026-06-01T00:00:00.000Z',
|
||||
publishReady: true,
|
||||
generationStatus: 'ready',
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
function buildWoodenFishGalleryCard(
|
||||
overrides: Partial<WoodenFishGalleryCardResponse> = {},
|
||||
): WoodenFishGalleryCardResponse {
|
||||
@@ -448,6 +483,7 @@ test('platform public work detail flow resolves detail kind for every play kind'
|
||||
> = [
|
||||
['big-fish', 'big-fish'],
|
||||
['puzzle', 'puzzle'],
|
||||
['puzzle-clear', 'puzzle-clear'],
|
||||
['jump-hop', 'jump-hop'],
|
||||
['wooden-fish', 'wooden-fish'],
|
||||
['match3d', 'match3d'],
|
||||
@@ -509,6 +545,13 @@ test('platform public work detail flow resolves open strategy', () => {
|
||||
kind: 'edutainment',
|
||||
},
|
||||
],
|
||||
[
|
||||
buildTypedEntry('puzzle-clear'),
|
||||
{
|
||||
type: 'use-entry',
|
||||
kind: 'puzzle-clear',
|
||||
},
|
||||
],
|
||||
[
|
||||
buildTypedEntry('puzzle'),
|
||||
{
|
||||
@@ -595,6 +638,14 @@ test('platform public work detail flow maps work summaries to detail entries', (
|
||||
profileId: 'jump-hop-profile',
|
||||
publicWorkCode: 'JH-0001',
|
||||
});
|
||||
expect(
|
||||
mapPuzzleClearWorkToPublicWorkDetail(buildPuzzleClearGalleryCard()),
|
||||
).toMatchObject({
|
||||
sourceType: 'puzzle-clear',
|
||||
workId: 'puzzle-clear-work',
|
||||
profileId: 'puzzle-clear-profile',
|
||||
publicWorkCode: 'PCLR-0001',
|
||||
});
|
||||
expect(
|
||||
mapWoodenFishWorkToPublicWorkDetail(buildWoodenFishGalleryCard()),
|
||||
).toMatchObject({
|
||||
@@ -773,6 +824,12 @@ test('platform public work detail flow resolves like intent', () => {
|
||||
type: 'like-puzzle',
|
||||
profileId: 'puzzle-profile',
|
||||
});
|
||||
expect(
|
||||
resolvePlatformPublicWorkLikeIntent(buildTypedEntry('puzzle-clear')),
|
||||
).toEqual({
|
||||
type: 'unsupported',
|
||||
errorMessage: '拼消消点赞将在后续版本开放。',
|
||||
});
|
||||
expect(resolvePlatformPublicWorkLikeIntent(buildRpgEntry())).toEqual({
|
||||
type: 'like-rpg-gallery',
|
||||
ownerUserId: 'user-1',
|
||||
@@ -826,6 +883,12 @@ test('platform public work detail flow resolves remix intent', () => {
|
||||
profileId: 'puzzle-profile',
|
||||
selectionStage: 'puzzle-result',
|
||||
});
|
||||
expect(
|
||||
resolvePlatformPublicWorkRemixIntent(buildTypedEntry('puzzle-clear')),
|
||||
).toEqual({
|
||||
type: 'unsupported',
|
||||
errorMessage: '拼消消作品改造将在后续版本开放。',
|
||||
});
|
||||
expect(resolvePlatformPublicWorkRemixIntent(buildRpgEntry())).toEqual({
|
||||
type: 'remix-rpg-gallery',
|
||||
ownerUserId: 'user-1',
|
||||
@@ -1038,6 +1101,15 @@ test('platform public work detail flow resolves edit intent for unsupported and
|
||||
type: 'blocked',
|
||||
errorMessage: '这份跳一跳作品暂时请从作品架编辑。',
|
||||
});
|
||||
expect(
|
||||
resolvePlatformPublicWorkEditIntent(
|
||||
buildTypedEntry('puzzle-clear'),
|
||||
buildEditIntentDeps(),
|
||||
),
|
||||
).toEqual({
|
||||
type: 'blocked',
|
||||
errorMessage: '这份拼消消作品暂时请从作品架编辑。',
|
||||
});
|
||||
expect(
|
||||
resolvePlatformPublicWorkEditIntent(
|
||||
buildTypedEntry('wooden-fish'),
|
||||
@@ -1126,6 +1198,16 @@ test('platform public work detail flow resolves start intent for direct launches
|
||||
profileId: 'jump-hop-profile',
|
||||
returnStage: 'work-detail',
|
||||
});
|
||||
expect(
|
||||
resolvePlatformPublicWorkStartIntent(
|
||||
buildTypedEntry('puzzle-clear'),
|
||||
buildStartIntentDeps(),
|
||||
),
|
||||
).toEqual({
|
||||
type: 'start-puzzle-clear',
|
||||
profileId: 'puzzle-clear-profile',
|
||||
returnStage: 'work-detail',
|
||||
});
|
||||
expect(
|
||||
resolvePlatformPublicWorkStartIntent(
|
||||
buildTypedEntry('wooden-fish'),
|
||||
|
||||
@@ -7,6 +7,10 @@ import type {
|
||||
import type { Match3DWorkSummary } from '../../../packages/shared/src/contracts/match3dWorks';
|
||||
import type { PuzzleRunSnapshot } from '../../../packages/shared/src/contracts/puzzleRuntimeSession';
|
||||
import type { PuzzleWorkSummary } from '../../../packages/shared/src/contracts/puzzleWorkSummary';
|
||||
import type {
|
||||
PuzzleClearGalleryCardResponse,
|
||||
PuzzleClearWorkProfileResponse,
|
||||
} from '../../../packages/shared/src/contracts/puzzleClear';
|
||||
import type {
|
||||
CustomWorldGalleryCard,
|
||||
CustomWorldLibraryEntry,
|
||||
@@ -25,6 +29,7 @@ import {
|
||||
isEdutainmentGalleryEntry,
|
||||
isJumpHopGalleryEntry,
|
||||
isMatch3DGalleryEntry,
|
||||
isPuzzleClearGalleryEntry,
|
||||
isPuzzleGalleryEntry,
|
||||
isSquareHoleGalleryEntry,
|
||||
isVisualNovelGalleryEntry,
|
||||
@@ -32,6 +37,7 @@ import {
|
||||
mapBarkBattleWorkToPlatformGalleryCard,
|
||||
mapBigFishWorkToPlatformGalleryCard,
|
||||
mapJumpHopWorkToPlatformGalleryCard,
|
||||
mapPuzzleClearWorkToPlatformGalleryCard,
|
||||
mapPuzzleWorkToPlatformGalleryCard,
|
||||
mapSquareHoleWorkToPlatformGalleryCard,
|
||||
mapVisualNovelWorkToPlatformGalleryCard,
|
||||
@@ -50,6 +56,7 @@ export type PlatformPublicWorkDetailKind =
|
||||
| 'jump-hop'
|
||||
| 'match3d'
|
||||
| 'puzzle'
|
||||
| 'puzzle-clear'
|
||||
| 'rpg'
|
||||
| 'square-hole'
|
||||
| 'visual-novel'
|
||||
@@ -199,6 +206,11 @@ export type PlatformPublicWorkStartIntent =
|
||||
returnStage: 'work-detail';
|
||||
authMode: 'isolated';
|
||||
}
|
||||
| {
|
||||
type: 'start-puzzle-clear';
|
||||
profileId: string;
|
||||
returnStage: 'work-detail';
|
||||
}
|
||||
| {
|
||||
type: 'start-jump-hop';
|
||||
profileId: string;
|
||||
@@ -325,6 +337,12 @@ export function mapJumpHopWorkToPublicWorkDetail(
|
||||
return mapJumpHopWorkToPlatformGalleryCard(item);
|
||||
}
|
||||
|
||||
export function mapPuzzleClearWorkToPublicWorkDetail(
|
||||
item: PuzzleClearGalleryCardResponse | PuzzleClearWorkProfileResponse,
|
||||
): PlatformPublicGalleryCard {
|
||||
return mapPuzzleClearWorkToPlatformGalleryCard(item);
|
||||
}
|
||||
|
||||
export function mapBarkBattleWorkToPublicWorkDetail(
|
||||
item: BarkBattleWorkSummary,
|
||||
): PlatformPublicGalleryCard {
|
||||
@@ -512,6 +530,10 @@ export function getPlatformPublicWorkDetailKind(
|
||||
return 'puzzle';
|
||||
}
|
||||
|
||||
if (isPuzzleClearGalleryEntry(entry)) {
|
||||
return 'puzzle-clear';
|
||||
}
|
||||
|
||||
if (isJumpHopGalleryEntry(entry)) {
|
||||
return 'jump-hop';
|
||||
}
|
||||
@@ -560,6 +582,13 @@ export function resolvePlatformPublicWorkDetailOpenStrategy(
|
||||
};
|
||||
}
|
||||
|
||||
if (isPuzzleClearGalleryEntry(entry)) {
|
||||
return {
|
||||
type: 'use-entry',
|
||||
kind: 'puzzle-clear',
|
||||
};
|
||||
}
|
||||
|
||||
if (isJumpHopGalleryEntry(entry)) {
|
||||
return {
|
||||
type: 'load-jump-hop-detail',
|
||||
@@ -653,6 +682,13 @@ export function resolvePlatformPublicWorkLikeIntent(
|
||||
};
|
||||
}
|
||||
|
||||
if (isPuzzleClearGalleryEntry(entry)) {
|
||||
return {
|
||||
type: 'unsupported',
|
||||
errorMessage: '拼消消点赞将在后续版本开放。',
|
||||
};
|
||||
}
|
||||
|
||||
if (isBarkBattleGalleryEntry(entry)) {
|
||||
return {
|
||||
type: 'unsupported',
|
||||
@@ -700,6 +736,13 @@ export function resolvePlatformPublicWorkRemixIntent(
|
||||
};
|
||||
}
|
||||
|
||||
if (isPuzzleClearGalleryEntry(entry)) {
|
||||
return {
|
||||
type: 'unsupported',
|
||||
errorMessage: '拼消消作品改造将在后续版本开放。',
|
||||
};
|
||||
}
|
||||
|
||||
if (isMatch3DGalleryEntry(entry)) {
|
||||
return {
|
||||
type: 'unsupported',
|
||||
@@ -833,6 +876,13 @@ export function resolvePlatformPublicWorkEditIntent(
|
||||
};
|
||||
}
|
||||
|
||||
if (isPuzzleClearGalleryEntry(entry)) {
|
||||
return {
|
||||
type: 'blocked',
|
||||
errorMessage: '这份拼消消作品暂时请从作品架编辑。',
|
||||
};
|
||||
}
|
||||
|
||||
if (isWoodenFishGalleryEntry(entry)) {
|
||||
return {
|
||||
type: 'blocked',
|
||||
@@ -944,6 +994,14 @@ export function resolvePlatformPublicWorkStartIntent(
|
||||
};
|
||||
}
|
||||
|
||||
if (isPuzzleClearGalleryEntry(entry)) {
|
||||
return {
|
||||
type: 'start-puzzle-clear',
|
||||
profileId: entry.profileId,
|
||||
returnStage: 'work-detail',
|
||||
};
|
||||
}
|
||||
|
||||
if (isJumpHopGalleryEntry(entry)) {
|
||||
return {
|
||||
type: 'start-jump-hop',
|
||||
|
||||
@@ -48,6 +48,10 @@ const PROTECTED_DATA_LOSS_STABLE_STAGE_BY_STAGE = {
|
||||
'puzzle-result': false,
|
||||
'puzzle-gallery-detail': true,
|
||||
'puzzle-runtime': false,
|
||||
'puzzle-clear-workspace': true,
|
||||
'puzzle-clear-generating': false,
|
||||
'puzzle-clear-result': false,
|
||||
'puzzle-clear-runtime': false,
|
||||
'custom-world-generating': false,
|
||||
'custom-world-result': false,
|
||||
} as const satisfies Record<SelectionStage, boolean>;
|
||||
|
||||
@@ -358,6 +358,7 @@ const {
|
||||
}));
|
||||
|
||||
vi.mock('../../services/apiClient', () => ({
|
||||
BACKGROUND_AUTH_REQUEST_OPTIONS: {},
|
||||
refreshStoredAccessToken: mockRefreshStoredAccessToken,
|
||||
}));
|
||||
|
||||
@@ -2670,7 +2671,7 @@ test('profile total play time card always uses hours', async () => {
|
||||
});
|
||||
|
||||
const playTimeCard = screen.getByRole('button', {
|
||||
name: /累计游玩/u,
|
||||
name: /累计游戏时长/u,
|
||||
});
|
||||
|
||||
expect(within(playTimeCard).getByText('1.5小时')).toBeTruthy();
|
||||
@@ -2684,11 +2685,11 @@ test('profile played works card shows count unit', async () => {
|
||||
});
|
||||
|
||||
const playedCard = screen.getByRole('button', {
|
||||
name: /已玩游戏\s*1个/u,
|
||||
name: /已玩游戏数量\s*1个/u,
|
||||
});
|
||||
|
||||
expect(within(playedCard).getByText('1个')).toBeTruthy();
|
||||
expect(within(playedCard).queryByText('已玩游戏数量')).toBeNull();
|
||||
expect(within(playedCard).getByText('已玩游戏数量')).toBeTruthy();
|
||||
await screen.findByText('1 / 1');
|
||||
});
|
||||
|
||||
@@ -2700,8 +2701,12 @@ test('profile stats cards are centered without update timestamp', async () => {
|
||||
const walletCard = screen.getByRole('button', {
|
||||
name: /泥点余额\s*0/u,
|
||||
});
|
||||
const playTimeCard = screen.getByRole('button', { name: /累计游玩\s*0小时/u });
|
||||
const playedCard = screen.getByRole('button', { name: /已玩游戏\s*0个/u });
|
||||
const playTimeCard = screen.getByRole('button', {
|
||||
name: /累计游戏时长\s*0小时/u,
|
||||
});
|
||||
const playedCard = screen.getByRole('button', {
|
||||
name: /已玩游戏数量\s*0个/u,
|
||||
});
|
||||
|
||||
for (const card of [walletCard, playTimeCard, playedCard]) {
|
||||
expect(card.className).toContain('platform-profile-stat-card');
|
||||
@@ -2753,8 +2758,8 @@ test('mobile profile page matches the reference layout sections', async () => {
|
||||
expect(statPanel.className).toContain('platform-profile-stats-panel');
|
||||
expect(statPanel.querySelector('.platform-profile-stats-grid')).toBeTruthy();
|
||||
expect(within(statPanel).getByRole('button', { name: /泥点余额\s*70/u })).toBeTruthy();
|
||||
expect(within(statPanel).getByRole('button', { name: /累计游玩\s*0小时/u })).toBeTruthy();
|
||||
expect(within(statPanel).getByRole('button', { name: /已玩游戏\s*0个/u })).toBeTruthy();
|
||||
expect(within(statPanel).getByRole('button', { name: /累计游戏时长\s*0小时/u })).toBeTruthy();
|
||||
expect(within(statPanel).getByRole('button', { name: /已玩游戏数量\s*0个/u })).toBeTruthy();
|
||||
expect(
|
||||
within(statPanel).getByRole('button', { name: /泥点余额\s*70/u }).className,
|
||||
).toContain('platform-profile-stat-card');
|
||||
|
||||
@@ -326,6 +326,15 @@ const WECHAT_PAY_CONFIRM_RETRY_DELAYS_MS = [800, 1600, 3000] as const;
|
||||
const WECHAT_NATIVE_PAY_QR_IMAGE_SIZE = 180;
|
||||
const PROFILE_QR_SCAN_INTERVAL_MS = 360;
|
||||
|
||||
function getDelayUntilNextProfileTaskReset(nowMs = Date.now()) {
|
||||
const shiftedNow = nowMs + PROFILE_TASK_BEIJING_OFFSET_MS;
|
||||
const nextDayStart =
|
||||
Math.floor(shiftedNow / PROFILE_TASK_DAY_MS) * PROFILE_TASK_DAY_MS +
|
||||
PROFILE_TASK_DAY_MS;
|
||||
const nextResetAt = nextDayStart - PROFILE_TASK_BEIJING_OFFSET_MS;
|
||||
return Math.max(PROFILE_TASK_MIN_RESET_DELAY_MS, nextResetAt - nowMs);
|
||||
}
|
||||
|
||||
type ProfileReferralPanel = 'invite' | 'redeem' | 'community';
|
||||
type ProfilePopupPanel = ProfileReferralPanel | 'saveArchives';
|
||||
type BarcodeDetectorLike = {
|
||||
|
||||
@@ -1018,6 +1018,9 @@ export function describePlatformPublicWorkKind(
|
||||
if (isPuzzleGalleryEntry(entry)) {
|
||||
return formatPlatformWorkDisplayTag('拼图');
|
||||
}
|
||||
if (isPuzzleClearGalleryEntry(entry)) {
|
||||
return formatPlatformWorkDisplayTag('拼消消');
|
||||
}
|
||||
if (isMatch3DGalleryEntry(entry)) {
|
||||
return formatPlatformWorkDisplayTag('抓大鹅');
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ describe('jumpHopClient runtime requests', () => {
|
||||
it('submits jump input with a generated client event id', async () => {
|
||||
await submitJumpHopJump(
|
||||
'run/1',
|
||||
{ chargeMs: 320 },
|
||||
{ dragDistance: 320 },
|
||||
{ runtimeGuestToken: 'runtime-guest-token' },
|
||||
);
|
||||
|
||||
@@ -69,7 +69,7 @@ describe('jumpHopClient runtime requests', () => {
|
||||
Authorization: 'Bearer runtime-guest-token',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
chargeMs: 320,
|
||||
dragDistance: 320,
|
||||
clientEventId: 'jump-run/1-1780000000000',
|
||||
}),
|
||||
}),
|
||||
|
||||
@@ -5,6 +5,7 @@ import type {
|
||||
JumpHopGalleryCardResponse,
|
||||
JumpHopGalleryDetailResponse,
|
||||
JumpHopGalleryResponse,
|
||||
JumpHopJumpRequest,
|
||||
JumpHopLeaderboardResponse,
|
||||
JumpHopRunResponse,
|
||||
JumpHopRuntimeRunSnapshotResponse,
|
||||
@@ -22,7 +23,11 @@ import {
|
||||
requestJson,
|
||||
} from '../apiClient';
|
||||
import { createCreationAgentClient } from '../creation-agent';
|
||||
import { type RuntimeGuestRequestOptions } from '../runtimeGuestAuth';
|
||||
import {
|
||||
buildRuntimeGuestAuthOptions,
|
||||
buildRuntimeGuestHeaders,
|
||||
type RuntimeGuestRequestOptions,
|
||||
} from '../runtimeGuestAuth';
|
||||
import { buildRuntimeApiPath, requestRuntimeJson } from '../runtimeRequest';
|
||||
|
||||
const JUMP_HOP_API_BASE = '/api/creation/jump-hop/sessions';
|
||||
@@ -40,11 +45,10 @@ type JumpHopRuntimeMode = 'draft' | 'published';
|
||||
type JumpHopStartRunOptions = JumpHopRuntimeRequestOptions & {
|
||||
runtimeMode?: JumpHopRuntimeMode;
|
||||
};
|
||||
type JumpHopJumpPayload = {
|
||||
dragDistance: number;
|
||||
dragVectorX?: number;
|
||||
dragVectorY?: number;
|
||||
};
|
||||
type JumpHopJumpPayload = Pick<
|
||||
JumpHopJumpRequest,
|
||||
'dragDistance' | 'dragVectorX' | 'dragVectorY'
|
||||
>;
|
||||
|
||||
export type {
|
||||
JumpHopActionRequest,
|
||||
|
||||
@@ -4,10 +4,12 @@ import {
|
||||
buildCustomWorldPublicWorkCode,
|
||||
buildJumpHopPublicWorkCode,
|
||||
buildMatch3DPublicWorkCode,
|
||||
buildPuzzleClearPublicWorkCode,
|
||||
buildWoodenFishPublicWorkCode,
|
||||
isSameCustomWorldPublicWorkCode,
|
||||
isSameJumpHopPublicWorkCode,
|
||||
isSameMatch3DPublicWorkCode,
|
||||
isSamePuzzleClearPublicWorkCode,
|
||||
isSameWoodenFishPublicWorkCode,
|
||||
} from './publicWorkCode';
|
||||
|
||||
|
||||
Reference in New Issue
Block a user