213 lines
5.5 KiB
TypeScript
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),
|
|
};
|
|
}
|