import type { BarkBattleWorkSummary } from '../../../packages/shared/src/contracts/barkBattle'; import type { BigFishWorkSummary } from '../../../packages/shared/src/contracts/bigFishWorkSummary'; import type { JumpHopGalleryCardResponse, JumpHopWorkProfileResponse, } from '../../../packages/shared/src/contracts/jumpHop'; 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, } from '../../../packages/shared/src/contracts/runtime'; import type { SquareHoleWorkSummary } from '../../../packages/shared/src/contracts/squareHoleWorks'; import type { VisualNovelWorkSummary } from '../../../packages/shared/src/contracts/visualNovel'; import type { WoodenFishGalleryCardResponse, WoodenFishWorkProfileResponse, } from '../../../packages/shared/src/contracts/woodenFish'; import { buildPublicWorkStagePath } from '../../routing/appPageRoutes'; import type { CustomWorldProfile } from '../../types'; import { isBarkBattleGalleryEntry, isBigFishGalleryEntry, isEdutainmentGalleryEntry, isJumpHopGalleryEntry, isMatch3DGalleryEntry, isPuzzleClearGalleryEntry, isPuzzleGalleryEntry, isSquareHoleGalleryEntry, isVisualNovelGalleryEntry, isWoodenFishGalleryEntry, mapBarkBattleWorkToPlatformGalleryCard, mapBigFishWorkToPlatformGalleryCard, mapJumpHopWorkToPlatformGalleryCard, mapPuzzleClearWorkToPlatformGalleryCard, mapPuzzleWorkToPlatformGalleryCard, mapSquareHoleWorkToPlatformGalleryCard, mapVisualNovelWorkToPlatformGalleryCard, mapWoodenFishWorkToPlatformGalleryCard, type PlatformPublicGalleryCard, } from '../rpg-entry/rpgEntryWorldPresentation'; import { canExposePublicWork, EDUTAINMENT_HIDDEN_MESSAGE, } from './platformEdutainmentVisibility'; export type PlatformPublicWorkDetailKind = | 'bark-battle' | 'big-fish' | 'edutainment' | 'jump-hop' | 'match3d' | 'puzzle' | 'puzzle-clear' | 'rpg' | 'square-hole' | 'visual-novel' | 'wooden-fish'; export type PlatformRpgPublicWorkDetailEntry = | CustomWorldGalleryCard | CustomWorldLibraryEntry; export type PlatformPublicWorkDetailOpenStrategy = | { type: 'use-entry'; kind: Exclude< PlatformPublicWorkDetailKind, 'jump-hop' | 'puzzle' | 'rpg' | 'visual-novel' | 'wooden-fish' >; } | { type: 'load-puzzle-detail'; profileId: string; } | { type: 'load-jump-hop-detail'; profileId: string; } | { type: 'load-wooden-fish-detail'; profileId: string; } | { type: 'load-visual-novel-detail'; profileId: string; } | { type: 'load-rpg-detail'; entry: PlatformRpgPublicWorkDetailEntry; }; export type PlatformPublicWorkActionMode = 'edit' | 'remix'; export type PlatformPublicWorkLikeIntent = | { type: 'like-big-fish'; profileId: string; } | { type: 'like-puzzle'; profileId: string; } | { type: 'like-rpg-gallery'; ownerUserId: string; profileId: string; } | { type: 'unsupported'; errorMessage: string; }; export type PlatformPublicWorkRemixIntent = | { type: 'remix-big-fish'; profileId: string; selectionStage: 'big-fish-result'; } | { type: 'remix-puzzle'; profileId: string; selectionStage: 'puzzle-result'; } | { type: 'remix-rpg-gallery'; ownerUserId: string; profileId: string; } | { type: 'unsupported'; errorMessage: string; }; export type PlatformPublicWorkEditIntent = | { type: 'blocked'; errorMessage: string; } | { type: 'edit-big-fish'; work: BigFishWorkSummary; } | { type: 'edit-puzzle'; work: PuzzleWorkSummary; } | { type: 'edit-match3d'; work: Match3DWorkSummary; forceDraft: true; } | { type: 'edit-square-hole'; work: SquareHoleWorkSummary; forceDraft: true; } | { type: 'edit-visual-novel'; work: VisualNovelWorkSummary; forceDraft: true; } | { type: 'resolve-edutainment-draft'; entry: PlatformPublicGalleryCard; } | { type: 'edit-bark-battle'; work: BarkBattleWorkSummary; forceDraft: true; } | { type: 'edit-rpg-gallery'; entry: CustomWorldLibraryEntry; }; export type PlatformPublicWorkEditIntentDeps = { selectedPuzzleDetail?: PuzzleWorkSummary | null; selectedRpgDetailEntry?: PlatformRpgPublicWorkDetailEntry | null; visualNovelWorks?: readonly VisualNovelWorkSummary[]; barkBattleGalleryEntries?: readonly BarkBattleWorkSummary[]; barkBattleWorks?: readonly BarkBattleWorkSummary[]; mapMatch3DWork: ( entry: PlatformPublicGalleryCard, ) => Match3DWorkSummary | null; }; export type PlatformPublicWorkStartIntent = | { type: 'blocked'; errorMessage: string; } | { type: 'start-big-fish'; work: BigFishWorkSummary; returnStage: 'work-detail'; } | { type: 'start-puzzle'; work: PuzzleWorkSummary; returnStage: 'work-detail'; authMode: 'isolated'; } | { type: 'start-puzzle-clear'; profileId: string; returnStage: 'work-detail'; } | { type: 'start-jump-hop'; profileId: string; returnStage: 'work-detail'; } | { type: 'start-wooden-fish'; profileId: string; returnStage: 'work-detail'; } | { type: 'start-match3d'; work: Match3DWorkSummary; returnStage: 'work-detail'; } | { type: 'start-square-hole'; work: SquareHoleWorkSummary; returnStage: 'work-detail'; } | { type: 'start-visual-novel'; profileId: string; returnStage: 'work-detail'; } | { type: 'start-bark-battle'; work: BarkBattleWorkSummary; returnStage: 'work-detail'; } | { type: 'start-edutainment'; entry: PlatformPublicGalleryCard; returnStage: 'work-detail'; } | { type: 'record-rpg-gallery-play'; entry: PlatformRpgPublicWorkDetailEntry; }; export type PlatformPublicWorkStartIntentDeps = { selectedPuzzleDetail?: PuzzleWorkSummary | null; selectedRpgDetailEntry?: PlatformRpgPublicWorkDetailEntry | null; barkBattleGalleryEntries?: readonly BarkBattleWorkSummary[]; barkBattleWorks?: readonly BarkBattleWorkSummary[]; mapMatch3DWork: ( entry: PlatformPublicGalleryCard, ) => Match3DWorkSummary | null; }; export type PlatformPublicWorkDetailOpenDecision = | { type: 'blocked'; selectedDetail: null; errorMessage: string; selectionStage: 'platform'; historyPath: null; } | { type: 'open'; selectedDetail: PlatformPublicGalleryCard; errorMessage: null; selectionStage: 'work-detail'; historyPath: string | null; }; export type PlatformPublicWorkDetailOpenDecisionDeps = { canExposeEntry?: (entry: PlatformPublicGalleryCard) => boolean; hiddenMessage?: string; buildWorkDetailPath?: (publicWorkCode: string) => string; }; export type ActivePlatformPublicWorkAuthorEntryInput = { selectionStage: string; selectedPublicWorkDetail: PlatformPublicGalleryCard | null; selectedRpgDetailEntry: PlatformRpgPublicWorkDetailEntry | null; }; export function isRpgPublicWorkDetailEntry( entry: PlatformPublicGalleryCard, ): entry is PlatformRpgPublicWorkDetailEntry { return !('sourceType' in entry); } export function mapRpgGalleryCardToPublicWorkDetail( entry: PlatformRpgPublicWorkDetailEntry, ): CustomWorldGalleryCard { return { ownerUserId: entry.ownerUserId, profileId: entry.profileId, publicWorkCode: entry.publicWorkCode, authorPublicUserCode: entry.authorPublicUserCode, visibility: entry.visibility, publishedAt: entry.publishedAt, updatedAt: entry.updatedAt, authorDisplayName: entry.authorDisplayName, worldName: entry.worldName, subtitle: entry.subtitle, summaryText: entry.summaryText, coverImageSrc: entry.coverImageSrc, themeMode: entry.themeMode, playableNpcCount: entry.playableNpcCount, landmarkCount: entry.landmarkCount, playCount: entry.playCount ?? 0, remixCount: entry.remixCount ?? 0, likeCount: entry.likeCount ?? 0, recentPlayCount7d: entry.recentPlayCount7d ?? 0, }; } function isRpgPublicWorkLibraryEntry( entry: PlatformRpgPublicWorkDetailEntry | null | undefined, ): entry is CustomWorldLibraryEntry { return Boolean(entry && 'profile' in entry); } export function mapPuzzleWorkToPublicWorkDetail( item: PuzzleWorkSummary, ): PlatformPublicGalleryCard { return mapPuzzleWorkToPlatformGalleryCard(item); } export function mapSquareHoleWorkToPublicWorkDetail( item: SquareHoleWorkSummary, ): PlatformPublicGalleryCard { return mapSquareHoleWorkToPlatformGalleryCard(item); } export function mapBigFishWorkToPublicWorkDetail( item: BigFishWorkSummary, ): PlatformPublicGalleryCard { return mapBigFishWorkToPlatformGalleryCard(item); } export function mapVisualNovelWorkToPublicWorkDetail( item: VisualNovelWorkSummary, ): PlatformPublicGalleryCard { return mapVisualNovelWorkToPlatformGalleryCard(item); } export function mapJumpHopWorkToPublicWorkDetail( item: JumpHopGalleryCardResponse | JumpHopWorkProfileResponse, ): PlatformPublicGalleryCard { return mapJumpHopWorkToPlatformGalleryCard(item); } export function mapPuzzleClearWorkToPublicWorkDetail( item: PuzzleClearGalleryCardResponse | PuzzleClearWorkProfileResponse, ): PlatformPublicGalleryCard { return mapPuzzleClearWorkToPlatformGalleryCard(item); } export function mapBarkBattleWorkToPublicWorkDetail( item: BarkBattleWorkSummary, ): PlatformPublicGalleryCard { return mapBarkBattleWorkToPlatformGalleryCard(item); } export function mapWoodenFishWorkToPublicWorkDetail( item: WoodenFishGalleryCardResponse | WoodenFishWorkProfileResponse, ): PlatformPublicGalleryCard { return mapWoodenFishWorkToPlatformGalleryCard(item); } export function mapBarkBattlePublicDetailToWorkSummary( entry: PlatformPublicGalleryCard, ): BarkBattleWorkSummary | null { if (!isBarkBattleGalleryEntry(entry)) { return null; } return { workId: entry.workId, draftId: entry.sourceSessionId ?? null, ownerUserId: entry.ownerUserId, authorDisplayName: entry.authorDisplayName, title: entry.worldName, summary: entry.summaryText, themeDescription: entry.themeTags[0] ?? entry.summaryText, playerImageDescription: entry.themeTags[1] ?? entry.summaryText, opponentImageDescription: entry.themeTags[2] ?? entry.summaryText, onomatopoeia: undefined, playerCharacterImageSrc: entry.coverCharacterImageSrcs[0] ?? null, opponentCharacterImageSrc: entry.coverCharacterImageSrcs[1] ?? null, uiBackgroundImageSrc: entry.coverImageSrc, difficultyPreset: 'normal', status: 'published', generationStatus: 'ready', publishReady: true, playCount: entry.playCount ?? 0, recentPlayCount7d: entry.recentPlayCount7d ?? 0, updatedAt: entry.updatedAt, publishedAt: entry.publishedAt, }; } export function mapPublicWorkDetailToPuzzleWork( entry: PlatformPublicGalleryCard, ): PuzzleWorkSummary | null { if (!isPuzzleGalleryEntry(entry)) { return null; } return { workId: entry.workId, profileId: entry.profileId, ownerUserId: entry.ownerUserId, sourceSessionId: 'sourceSessionId' in entry && typeof entry.sourceSessionId === 'string' ? entry.sourceSessionId : null, authorDisplayName: entry.authorDisplayName, levelName: entry.worldName, summary: entry.summaryText, themeTags: entry.themeTags, coverImageSrc: entry.coverImageSrc, publicationStatus: 'published', updatedAt: entry.updatedAt, publishedAt: entry.publishedAt, playCount: entry.playCount ?? 0, remixCount: entry.remixCount ?? 0, likeCount: entry.likeCount ?? 0, pointIncentiveTotalHalfPoints: 0, pointIncentiveClaimedPoints: 0, pointIncentiveTotalPoints: 0, pointIncentiveClaimablePoints: 0, publishReady: true, levels: entry.coverSlides?.map((slide, index) => ({ levelId: slide.id || `puzzle-level-${index + 1}`, levelName: slide.label, pictureDescription: entry.summaryText, candidates: [], selectedCandidateId: null, coverImageSrc: slide.imageSrc, coverAssetId: null, generationStatus: 'ready' as const, })) ?? [], }; } export function resolveVisiblePuzzleDetailCoverCount( entry: PlatformPublicGalleryCard | null, run: PuzzleRunSnapshot | null, ) { if (!entry || !isPuzzleGalleryEntry(entry)) { return 1; } if (run?.entryProfileId !== entry.profileId) { return 1; } // 中文注释:封面首图永远公开,后续封面跟随当前玩家本次 run 的通关进度即时解锁。 return Math.max(1, run.clearedLevelCount + 1); } export function mapPublicWorkDetailToBigFishWork( entry: PlatformPublicGalleryCard, ): BigFishWorkSummary | null { if (!isBigFishGalleryEntry(entry)) { return null; } const levelCount = Number.parseInt( entry.themeTags.find((tag) => /^\d+级$/u.test(tag))?.replace('级', '') ?? '0', 10, ); return { workId: entry.workId, sourceSessionId: entry.profileId, ownerUserId: entry.ownerUserId, authorDisplayName: entry.authorDisplayName, title: entry.worldName, subtitle: entry.subtitle, summary: entry.summaryText, coverImageSrc: entry.coverImageSrc, status: 'published', updatedAt: entry.updatedAt, publishedAt: entry.publishedAt, publishReady: true, levelCount: Number.isNaN(levelCount) ? 0 : levelCount, levelMainImageReadyCount: 0, levelMotionReadyCount: 0, backgroundReady: Boolean(entry.coverImageSrc), playCount: entry.playCount ?? 0, remixCount: entry.remixCount ?? 0, likeCount: entry.likeCount ?? 0, }; } export function mapPublicWorkDetailToSquareHoleWork( entry: PlatformPublicGalleryCard, ): SquareHoleWorkSummary | null { if (!isSquareHoleGalleryEntry(entry)) { return null; } return { workId: entry.workId, profileId: entry.profileId, ownerUserId: entry.ownerUserId, sourceSessionId: 'sourceSessionId' in entry && typeof entry.sourceSessionId === 'string' ? entry.sourceSessionId : null, gameName: entry.worldName, themeText: entry.themeTags[0] ?? '方洞挑战', twistRule: entry.subtitle, summary: entry.summaryText, tags: entry.themeTags, coverImageSrc: entry.coverImageSrc, backgroundPrompt: entry.backgroundPrompt ?? '方洞挑战运行背景', backgroundImageSrc: entry.backgroundImageSrc ?? null, shapeOptions: entry.shapeOptions ?? [], holeOptions: entry.holeOptions ?? [], shapeCount: entry.shapeCount ?? 8, difficulty: entry.difficulty ?? 4, publicationStatus: 'published', playCount: entry.playCount ?? 0, updatedAt: entry.updatedAt, publishedAt: entry.publishedAt, publishReady: true, }; } export function getPlatformPublicWorkDetailKind( entry: PlatformPublicGalleryCard, ): PlatformPublicWorkDetailKind { if (isBigFishGalleryEntry(entry)) { return 'big-fish'; } if (isPuzzleGalleryEntry(entry)) { return 'puzzle'; } if (isPuzzleClearGalleryEntry(entry)) { return 'puzzle-clear'; } if (isJumpHopGalleryEntry(entry)) { return 'jump-hop'; } if (isWoodenFishGalleryEntry(entry)) { return 'wooden-fish'; } if (isMatch3DGalleryEntry(entry)) { return 'match3d'; } if (isSquareHoleGalleryEntry(entry)) { return 'square-hole'; } if (isVisualNovelGalleryEntry(entry)) { return 'visual-novel'; } if (isBarkBattleGalleryEntry(entry)) { return 'bark-battle'; } if (isEdutainmentGalleryEntry(entry)) { return 'edutainment'; } return 'rpg'; } export function resolvePlatformPublicWorkDetailOpenStrategy( entry: PlatformPublicGalleryCard, ): PlatformPublicWorkDetailOpenStrategy { if (isBigFishGalleryEntry(entry)) { return { type: 'use-entry', kind: 'big-fish', }; } if (isPuzzleGalleryEntry(entry)) { return { type: 'load-puzzle-detail', profileId: entry.profileId, }; } if (isPuzzleClearGalleryEntry(entry)) { return { type: 'use-entry', kind: 'puzzle-clear', }; } if (isJumpHopGalleryEntry(entry)) { return { type: 'load-jump-hop-detail', profileId: entry.profileId, }; } if (isWoodenFishGalleryEntry(entry)) { return { type: 'load-wooden-fish-detail', profileId: entry.profileId, }; } if (isMatch3DGalleryEntry(entry)) { return { type: 'use-entry', kind: 'match3d', }; } if (isSquareHoleGalleryEntry(entry)) { return { type: 'use-entry', kind: 'square-hole', }; } if (isVisualNovelGalleryEntry(entry)) { return { type: 'load-visual-novel-detail', profileId: entry.profileId, }; } if (isBarkBattleGalleryEntry(entry)) { return { type: 'use-entry', kind: 'bark-battle', }; } if (isEdutainmentGalleryEntry(entry)) { return { type: 'use-entry', kind: 'edutainment', }; } if (isRpgPublicWorkDetailEntry(entry)) { return { type: 'load-rpg-detail', entry, }; } const exhaustive: never = entry; return exhaustive; } export function resolvePlatformPublicWorkActionMode( entry: PlatformPublicGalleryCard, viewerUserId: string | null | undefined, ): PlatformPublicWorkActionMode { return viewerUserId?.trim() && entry.ownerUserId === viewerUserId.trim() ? 'edit' : 'remix'; } export function resolvePlatformPublicWorkLikeIntent( entry: PlatformPublicGalleryCard, ): PlatformPublicWorkLikeIntent { if (isBigFishGalleryEntry(entry)) { return { type: 'like-big-fish', profileId: entry.profileId, }; } if (isPuzzleGalleryEntry(entry)) { return { type: 'like-puzzle', profileId: entry.profileId, }; } if (isEdutainmentGalleryEntry(entry)) { return { type: 'unsupported', errorMessage: '宝贝识物点赞将在后续版本开放。', }; } if (isPuzzleClearGalleryEntry(entry)) { return { type: 'unsupported', errorMessage: '拼消消点赞将在后续版本开放。', }; } if (isWoodenFishGalleryEntry(entry)) { return { type: 'unsupported', errorMessage: '作品类型 wooden-fish 暂不支持点赞。', }; } if (isJumpHopGalleryEntry(entry)) { return { type: 'unsupported', errorMessage: '作品类型 jump-hop 暂不支持点赞。', }; } if (isMatch3DGalleryEntry(entry)) { return { type: 'unsupported', errorMessage: '作品类型 match3d 暂不支持点赞。', }; } if (isBarkBattleGalleryEntry(entry)) { return { type: 'unsupported', errorMessage: '汪汪声浪点赞将在后续版本开放。', }; } if (isSquareHoleGalleryEntry(entry)) { return { type: 'unsupported', errorMessage: '方洞挑战点赞将在后续版本开放。', }; } if (isVisualNovelGalleryEntry(entry)) { return { type: 'unsupported', errorMessage: '视觉小说点赞将在后续版本开放。', }; } return { type: 'like-rpg-gallery', ownerUserId: entry.ownerUserId, profileId: entry.profileId, }; } export function resolvePlatformPublicWorkRemixIntent( entry: PlatformPublicGalleryCard, ): PlatformPublicWorkRemixIntent { if (isBigFishGalleryEntry(entry)) { return { type: 'remix-big-fish', profileId: entry.profileId, selectionStage: 'big-fish-result', }; } if (isPuzzleGalleryEntry(entry)) { return { type: 'remix-puzzle', profileId: entry.profileId, selectionStage: 'puzzle-result', }; } if (isPuzzleClearGalleryEntry(entry)) { return { type: 'unsupported', errorMessage: '拼消消作品改造将在后续版本开放。', }; } if (isMatch3DGalleryEntry(entry)) { return { type: 'unsupported', errorMessage: '抓大鹅作品改造将在后续版本开放。', }; } if (isSquareHoleGalleryEntry(entry)) { return { type: 'unsupported', errorMessage: '方洞挑战作品改造将在后续版本开放。', }; } if (isJumpHopGalleryEntry(entry)) { return { type: 'unsupported', errorMessage: '跳一跳作品改造将在后续版本开放。', }; } if (isWoodenFishGalleryEntry(entry)) { return { type: 'unsupported', errorMessage: '敲木鱼作品改造将在后续版本开放。', }; } if (isVisualNovelGalleryEntry(entry)) { return { type: 'unsupported', errorMessage: '视觉小说作品改造将在后续版本开放。', }; } if (isEdutainmentGalleryEntry(entry)) { return { type: 'unsupported', errorMessage: '宝贝识物作品改造将在创作链路接入后开放。', }; } if (isBarkBattleGalleryEntry(entry)) { return { type: 'unsupported', errorMessage: '汪汪声浪作品改造将在后续版本开放。', }; } return { type: 'remix-rpg-gallery', ownerUserId: entry.ownerUserId, profileId: entry.profileId, }; } export function resolvePlatformPublicWorkEditIntent( entry: PlatformPublicGalleryCard, deps: PlatformPublicWorkEditIntentDeps, ): PlatformPublicWorkEditIntent { if (isBigFishGalleryEntry(entry)) { const work = mapPublicWorkDetailToBigFishWork(entry); if (!work?.sourceSessionId?.trim()) { return { type: 'blocked', errorMessage: '这份大鱼吃小鱼作品缺少原草稿会话,暂时无法编辑。', }; } return { type: 'edit-big-fish', work, }; } if (isPuzzleGalleryEntry(entry)) { const work = deps.selectedPuzzleDetail?.profileId === entry.profileId ? deps.selectedPuzzleDetail : mapPublicWorkDetailToPuzzleWork(entry); if (!work?.sourceSessionId?.trim()) { return { type: 'blocked', errorMessage: '这份拼图作品缺少原草稿会话,暂时无法编辑。', }; } return { type: 'edit-puzzle', work, }; } if (isMatch3DGalleryEntry(entry)) { // 中文注释:抓大鹅草稿恢复仍复用 Match3D Module 的 public detail -> work Adapter。 const work = deps.mapMatch3DWork(entry); if (!work?.sourceSessionId?.trim()) { return { type: 'blocked', errorMessage: '这份抓大鹅作品缺少原草稿会话,暂时无法编辑。', }; } return { type: 'edit-match3d', work, forceDraft: true, }; } if (isSquareHoleGalleryEntry(entry)) { const work = mapPublicWorkDetailToSquareHoleWork(entry); if (!work?.sourceSessionId?.trim()) { return { type: 'blocked', errorMessage: '这份方洞挑战作品缺少原草稿会话,暂时无法编辑。', }; } return { type: 'edit-square-hole', work, forceDraft: true, }; } if (isJumpHopGalleryEntry(entry)) { return { type: 'blocked', errorMessage: '这份跳一跳作品暂时请从作品架编辑。', }; } if (isPuzzleClearGalleryEntry(entry)) { return { type: 'blocked', errorMessage: '这份拼消消作品暂时请从作品架编辑。', }; } if (isWoodenFishGalleryEntry(entry)) { return { type: 'blocked', errorMessage: '这份敲木鱼作品暂时请从作品架编辑。', }; } if (isVisualNovelGalleryEntry(entry)) { const work = deps.visualNovelWorks?.find((item) => item.profileId === entry.profileId) ?? null; if (!work) { return { type: 'blocked', errorMessage: '这份视觉小说缺少可编辑草稿。', }; } return { type: 'edit-visual-novel', work, forceDraft: true, }; } if (isEdutainmentGalleryEntry(entry)) { return { type: 'resolve-edutainment-draft', entry, }; } if (isBarkBattleGalleryEntry(entry)) { const work = deps.barkBattleWorks?.find((item) => item.workId === entry.workId) ?? deps.barkBattleGalleryEntries?.find( (item) => item.workId === entry.workId, ) ?? mapBarkBattlePublicDetailToWorkSummary(entry); if (!work?.draftId?.trim()) { return { type: 'blocked', errorMessage: '这份汪汪声浪缺少可编辑草稿。', }; } return { type: 'edit-bark-battle', work, forceDraft: true, }; } const editEntry = deps.selectedRpgDetailEntry?.profileId === entry.profileId && isRpgPublicWorkLibraryEntry(deps.selectedRpgDetailEntry) ? deps.selectedRpgDetailEntry : null; if (!editEntry) { return { type: 'blocked', errorMessage: '作品详情尚未读取完成。', }; } return { type: 'edit-rpg-gallery', entry: editEntry, }; } export function resolvePlatformPublicWorkStartIntent( entry: PlatformPublicGalleryCard, deps: PlatformPublicWorkStartIntentDeps, ): PlatformPublicWorkStartIntent { if (isBigFishGalleryEntry(entry)) { const work = mapPublicWorkDetailToBigFishWork(entry); if (!work) { return { type: 'blocked', errorMessage: '当前作品缺少会话信息,暂时无法进入玩法。', }; } return { type: 'start-big-fish', work, returnStage: 'work-detail', }; } if (isPuzzleGalleryEntry(entry)) { const work = deps.selectedPuzzleDetail?.profileId === entry.profileId ? deps.selectedPuzzleDetail : mapPublicWorkDetailToPuzzleWork(entry); if (!work) { return { type: 'blocked', errorMessage: '当前拼图作品信息不完整,暂时无法进入玩法。', }; } return { type: 'start-puzzle', work, returnStage: 'work-detail', authMode: 'isolated', }; } if (isPuzzleClearGalleryEntry(entry)) { return { type: 'start-puzzle-clear', profileId: entry.profileId, returnStage: 'work-detail', }; } if (isJumpHopGalleryEntry(entry)) { return { type: 'start-jump-hop', profileId: entry.profileId, returnStage: 'work-detail', }; } if (isWoodenFishGalleryEntry(entry)) { return { type: 'start-wooden-fish', profileId: entry.profileId, returnStage: 'work-detail', }; } if (isMatch3DGalleryEntry(entry)) { // 中文注释:抓大鹅运行态素材归一仍归 Match3D Module,公开详情 Flow 只接其 Adapter。 const work = deps.mapMatch3DWork(entry); if (!work) { return { type: 'blocked', errorMessage: '当前抓大鹅作品信息不完整,暂时无法进入玩法。', }; } return { type: 'start-match3d', work, returnStage: 'work-detail', }; } if (isSquareHoleGalleryEntry(entry)) { const work = mapPublicWorkDetailToSquareHoleWork(entry); if (!work) { return { type: 'blocked', errorMessage: '当前方洞挑战作品信息不完整,暂时无法进入玩法。', }; } return { type: 'start-square-hole', work, returnStage: 'work-detail', }; } if (isVisualNovelGalleryEntry(entry)) { return { type: 'start-visual-novel', profileId: entry.profileId, returnStage: 'work-detail', }; } if (isBarkBattleGalleryEntry(entry)) { const work = deps.barkBattleGalleryEntries?.find( (item) => item.workId === entry.workId, ) ?? deps.barkBattleWorks?.find((item) => item.workId === entry.workId) ?? mapBarkBattlePublicDetailToWorkSummary(entry); if (!work) { return { type: 'blocked', errorMessage: '当前汪汪声浪作品信息不完整,暂时无法进入玩法。', }; } return { type: 'start-bark-battle', work, returnStage: 'work-detail', }; } if (isEdutainmentGalleryEntry(entry)) { return { type: 'start-edutainment', entry, returnStage: 'work-detail', }; } const launchEntry = deps.selectedRpgDetailEntry?.profileId === entry.profileId ? deps.selectedRpgDetailEntry : null; if (!launchEntry) { return { type: 'blocked', errorMessage: '作品详情尚未读取完成。', }; } return { type: 'record-rpg-gallery-play', entry: launchEntry, }; } export function resolvePlatformPublicWorkDetailOpenDecision( entry: PlatformPublicGalleryCard, deps: PlatformPublicWorkDetailOpenDecisionDeps = {}, ): PlatformPublicWorkDetailOpenDecision { const canExposeEntry = deps.canExposeEntry ?? canExposePublicWork; const hiddenMessage = deps.hiddenMessage ?? EDUTAINMENT_HIDDEN_MESSAGE; const buildWorkDetailPath = deps.buildWorkDetailPath ?? ((publicWorkCode: string) => buildPublicWorkStagePath('work-detail', publicWorkCode)); if (!canExposeEntry(entry)) { return { type: 'blocked', selectedDetail: null, errorMessage: hiddenMessage, selectionStage: 'platform', historyPath: null, }; } const publicWorkCode = entry.publicWorkCode?.trim() ? entry.publicWorkCode : null; return { type: 'open', selectedDetail: entry, errorMessage: null, selectionStage: 'work-detail', historyPath: publicWorkCode ? buildWorkDetailPath(publicWorkCode) : null, }; } export function resolveActivePlatformPublicWorkAuthorEntry({ selectionStage, selectedPublicWorkDetail, selectedRpgDetailEntry, }: ActivePlatformPublicWorkAuthorEntryInput): PlatformPublicGalleryCard | null { if (selectionStage === 'work-detail') { return selectedPublicWorkDetail; } if ( selectionStage === 'detail' && selectedRpgDetailEntry && selectedRpgDetailEntry.visibility !== 'draft' ) { return selectedRpgDetailEntry; } return null; }