Files
Genarrative/src/components/platform-entry/platformPlayedWorkOpenModel.ts
T

213 lines
5.5 KiB
TypeScript

import type { BigFishWorkSummary } from '../../../packages/shared/src/contracts/bigFishWorkSummary';
import type {
CustomWorldGalleryCard,
ProfilePlayedWorkSummary,
} from '../../../packages/shared/src/contracts/runtime';
export type PlatformPlayedWorkOpenIntent =
| {
type: 'noop';
reason: 'missing-target';
}
| {
type: 'open-puzzle';
profileId: string;
tab: 'profile';
}
| {
type: 'open-match3d';
profileId: string;
}
| {
type: 'open-square-hole';
profileId: string;
}
| {
type: 'open-jump-hop';
profileId: string;
}
| {
type: 'open-wooden-fish';
profileId: string;
}
| {
type: 'open-big-fish';
sessionId: string;
fallbackWork: BigFishWorkSummary;
}
| {
type: 'open-rpg';
detail: CustomWorldGalleryCard;
};
function normalizePlayedWorkWorldType(worldType: string | null) {
return (worldType ?? '').toLowerCase();
}
function resolvePlayedWorkTargetId(
work: ProfilePlayedWorkSummary,
worldKeyPrefix: string,
) {
const prefixedWorldKey = `${worldKeyPrefix}:`;
return (
work.profileId ??
(work.worldKey.startsWith(prefixedWorldKey)
? work.worldKey.slice(prefixedWorldKey.length)
: work.worldKey)
);
}
function resolvePlayedWorkProfileIntent<TIntent extends PlatformPlayedWorkOpenIntent>(
profileId: string,
intent: (profileId: string) => TIntent,
) {
return profileId ? intent(profileId) : buildMissingPlayedWorkTargetIntent();
}
function buildMissingPlayedWorkTargetIntent(): PlatformPlayedWorkOpenIntent {
return {
type: 'noop',
reason: 'missing-target',
};
}
function buildPlayedBigFishFallbackWork(
work: ProfilePlayedWorkSummary,
sessionId: string,
): BigFishWorkSummary {
return {
workId: `big-fish:${sessionId}`,
sourceSessionId: sessionId,
ownerUserId: work.ownerUserId ?? '',
authorDisplayName: work.worldSubtitle || '玩家',
title: work.worldTitle,
subtitle: work.worldSubtitle,
summary: work.worldSubtitle,
coverImageSrc: null,
status: 'published',
updatedAt: work.lastPlayedAt,
publishReady: true,
levelCount: 0,
levelMainImageReadyCount: 0,
levelMotionReadyCount: 0,
backgroundReady: false,
};
}
function buildPlayedRpgDetail(
work: ProfilePlayedWorkSummary,
profileId: string,
ownerUserId: string,
): CustomWorldGalleryCard {
return {
ownerUserId,
profileId,
publicWorkCode: null,
authorPublicUserCode: null,
visibility: 'published',
publishedAt: work.firstPlayedAt,
updatedAt: work.lastPlayedAt,
authorDisplayName: work.worldSubtitle,
worldName: work.worldTitle,
subtitle: work.worldSubtitle,
summaryText: '',
coverImageSrc: null,
themeMode: 'martial',
playableNpcCount: 0,
landmarkCount: 0,
playCount: 0,
remixCount: 0,
likeCount: 0,
};
}
/** 收口个人“玩过作品”点击后的玩法打开意图,壳层只执行副作用。 */
export function resolvePlatformPlayedWorkOpenIntent(
work: ProfilePlayedWorkSummary,
): PlatformPlayedWorkOpenIntent {
const worldType = normalizePlayedWorkWorldType(work.worldType);
if (worldType === 'puzzle' || work.worldKey.startsWith('puzzle:')) {
const profileId = resolvePlayedWorkTargetId(work, 'puzzle');
return resolvePlayedWorkProfileIntent(profileId, (resolvedProfileId) => ({
type: 'open-puzzle',
profileId: resolvedProfileId,
tab: 'profile',
}));
}
if (
worldType === 'match3d' ||
worldType === 'match_3d' ||
work.worldKey.startsWith('match3d:')
) {
const profileId = resolvePlayedWorkTargetId(work, 'match3d');
return resolvePlayedWorkProfileIntent(profileId, (resolvedProfileId) => ({
type: 'open-match3d',
profileId: resolvedProfileId,
}));
}
if (
worldType === 'square-hole' ||
worldType === 'square_hole' ||
work.worldKey.startsWith('square-hole:')
) {
const profileId = resolvePlayedWorkTargetId(work, 'square-hole');
return resolvePlayedWorkProfileIntent(profileId, (resolvedProfileId) => ({
type: 'open-square-hole',
profileId: resolvedProfileId,
}));
}
if (
worldType === 'jump-hop' ||
worldType === 'jump_hop' ||
work.worldKey.startsWith('jump-hop:')
) {
const profileId = resolvePlayedWorkTargetId(work, 'jump-hop');
return resolvePlayedWorkProfileIntent(profileId, (resolvedProfileId) => ({
type: 'open-jump-hop',
profileId: resolvedProfileId,
}));
}
if (
worldType === 'wooden-fish' ||
worldType === 'wooden_fish' ||
work.worldKey.startsWith('wooden-fish:')
) {
const profileId = resolvePlayedWorkTargetId(work, 'wooden-fish');
return resolvePlayedWorkProfileIntent(profileId, (resolvedProfileId) => ({
type: 'open-wooden-fish',
profileId: resolvedProfileId,
}));
}
if (
worldType === 'big_fish' ||
worldType === 'big-fish' ||
work.worldKey.startsWith('big-fish:')
) {
const sessionId = resolvePlayedWorkTargetId(work, 'big-fish');
return sessionId
? {
type: 'open-big-fish',
sessionId,
fallbackWork: buildPlayedBigFishFallbackWork(work, sessionId),
}
: buildMissingPlayedWorkTargetIntent();
}
const profileId = work.profileId ?? work.worldKey;
const ownerUserId = work.ownerUserId;
if (!ownerUserId || !profileId) {
return buildMissingPlayedWorkTargetIntent();
}
return {
type: 'open-rpg',
detail: buildPlayedRpgDetail(work, profileId, ownerUserId),
};
}