refactor: 收口公开详情编辑意图
This commit is contained in:
@@ -532,6 +532,7 @@ import {
|
||||
resolvePlatformPublicWorkActionMode,
|
||||
resolvePlatformPublicWorkDetailOpenDecision,
|
||||
resolvePlatformPublicWorkDetailOpenStrategy,
|
||||
resolvePlatformPublicWorkEditIntent,
|
||||
resolvePlatformPublicWorkLikeIntent,
|
||||
resolvePlatformPublicWorkRemixIntent,
|
||||
resolvePlatformPublicWorkStartIntent,
|
||||
@@ -13513,117 +13514,65 @@ export function PlatformEntryFlowShellImpl({
|
||||
runProtectedAction(async () => {
|
||||
setPublicWorkDetailError(null);
|
||||
|
||||
// 中文注释:自有公开作品必须恢复原草稿,不能复用 remix 复制链路。
|
||||
if (isBigFishGalleryEntry(entry)) {
|
||||
const work = mapPublicWorkDetailToBigFishWork(entry);
|
||||
if (!work?.sourceSessionId?.trim()) {
|
||||
setPublicWorkDetailError(
|
||||
'这份大鱼吃小鱼作品缺少原草稿会话,暂时无法编辑。',
|
||||
const intent = resolvePlatformPublicWorkEditIntent(entry, {
|
||||
selectedPuzzleDetail,
|
||||
selectedRpgDetailEntry: selectedDetailEntry,
|
||||
visualNovelWorks,
|
||||
barkBattleGalleryEntries,
|
||||
barkBattleWorks,
|
||||
mapMatch3DWork: mapPublicWorkDetailToMatch3DWork,
|
||||
});
|
||||
|
||||
switch (intent.type) {
|
||||
case 'blocked':
|
||||
setPublicWorkDetailError(intent.errorMessage);
|
||||
return;
|
||||
case 'edit-big-fish':
|
||||
void openBigFishDraft(intent.work);
|
||||
return;
|
||||
case 'edit-puzzle':
|
||||
void openPuzzleDraft(intent.work);
|
||||
return;
|
||||
case 'edit-match3d':
|
||||
void openMatch3DDraft(intent.work, {
|
||||
forceDraft: intent.forceDraft,
|
||||
});
|
||||
return;
|
||||
case 'edit-square-hole':
|
||||
void openSquareHoleDraft(intent.work, {
|
||||
forceDraft: intent.forceDraft,
|
||||
});
|
||||
return;
|
||||
case 'edit-visual-novel':
|
||||
void openVisualNovelDraft(intent.work, {
|
||||
forceDraft: intent.forceDraft,
|
||||
});
|
||||
return;
|
||||
case 'resolve-edutainment-draft': {
|
||||
const matchedDraft = await resolveBabyObjectMatchRuntimeDraft(
|
||||
intent.entry,
|
||||
);
|
||||
if (!matchedDraft) {
|
||||
setPublicWorkDetailError('这份宝贝识物缺少可编辑草稿。');
|
||||
return;
|
||||
}
|
||||
|
||||
openBabyObjectMatchDraft(matchedDraft);
|
||||
return;
|
||||
}
|
||||
void openBigFishDraft(work);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isPuzzleGalleryEntry(entry)) {
|
||||
const work =
|
||||
selectedPuzzleDetail?.profileId === entry.profileId
|
||||
? selectedPuzzleDetail
|
||||
: mapPublicWorkDetailToPuzzleWork(entry);
|
||||
if (!work?.sourceSessionId?.trim()) {
|
||||
setPublicWorkDetailError(
|
||||
'这份拼图作品缺少原草稿会话,暂时无法编辑。',
|
||||
);
|
||||
case 'edit-bark-battle':
|
||||
openBarkBattleDraft(intent.work, {
|
||||
forceDraft: intent.forceDraft,
|
||||
});
|
||||
return;
|
||||
}
|
||||
void openPuzzleDraft(work);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isMatch3DGalleryEntry(entry)) {
|
||||
const work = mapPublicWorkDetailToMatch3DWork(entry);
|
||||
if (!work?.sourceSessionId?.trim()) {
|
||||
setPublicWorkDetailError(
|
||||
'这份抓大鹅作品缺少原草稿会话,暂时无法编辑。',
|
||||
);
|
||||
case 'edit-rpg-gallery':
|
||||
void detailNavigation.openSavedCustomWorldEditor(intent.entry);
|
||||
return;
|
||||
default: {
|
||||
const exhaustive: never = intent;
|
||||
return exhaustive;
|
||||
}
|
||||
void openMatch3DDraft(work, { forceDraft: true });
|
||||
return;
|
||||
}
|
||||
|
||||
if (isSquareHoleGalleryEntry(entry)) {
|
||||
const work = mapPublicWorkDetailToSquareHoleWork(entry);
|
||||
if (!work?.sourceSessionId?.trim()) {
|
||||
setPublicWorkDetailError(
|
||||
'这份方洞挑战作品缺少原草稿会话,暂时无法编辑。',
|
||||
);
|
||||
return;
|
||||
}
|
||||
void openSquareHoleDraft(work, { forceDraft: true });
|
||||
return;
|
||||
}
|
||||
|
||||
if (isJumpHopGalleryEntry(entry)) {
|
||||
setPublicWorkDetailError('这份跳一跳作品暂时请从作品架编辑。');
|
||||
return;
|
||||
}
|
||||
|
||||
if (isWoodenFishGalleryEntry(entry)) {
|
||||
setPublicWorkDetailError('这份敲木鱼作品暂时请从作品架编辑。');
|
||||
return;
|
||||
}
|
||||
|
||||
if (isVisualNovelGalleryEntry(entry)) {
|
||||
const matchedWork = visualNovelWorks.find(
|
||||
(work) => work.profileId === entry.profileId,
|
||||
);
|
||||
if (!matchedWork) {
|
||||
setPublicWorkDetailError('这份视觉小说缺少可编辑草稿。');
|
||||
return;
|
||||
}
|
||||
void openVisualNovelDraft(matchedWork, { forceDraft: true });
|
||||
return;
|
||||
}
|
||||
|
||||
if (isEdutainmentGalleryEntry(entry)) {
|
||||
const matchedDraft = await resolveBabyObjectMatchRuntimeDraft(entry);
|
||||
if (!matchedDraft) {
|
||||
setPublicWorkDetailError('这份宝贝识物缺少可编辑草稿。');
|
||||
return;
|
||||
}
|
||||
|
||||
openBabyObjectMatchDraft(matchedDraft);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isBarkBattleGalleryEntry(entry)) {
|
||||
const matchedWork =
|
||||
barkBattleWorks.find((work) => work.workId === entry.workId) ??
|
||||
barkBattleGalleryEntries.find(
|
||||
(work) => work.workId === entry.workId,
|
||||
) ??
|
||||
mapBarkBattlePublicDetailToWorkSummary(entry);
|
||||
if (!matchedWork?.draftId?.trim()) {
|
||||
setPublicWorkDetailError('这份汪汪声浪缺少可编辑草稿。');
|
||||
return;
|
||||
}
|
||||
|
||||
openBarkBattleDraft(matchedWork, { forceDraft: true });
|
||||
return;
|
||||
}
|
||||
|
||||
const editEntry =
|
||||
selectedDetailEntry?.profileId === entry.profileId
|
||||
? selectedDetailEntry
|
||||
: null;
|
||||
if (!editEntry) {
|
||||
setPublicWorkDetailError('作品详情尚未读取完成。');
|
||||
return;
|
||||
}
|
||||
|
||||
void detailNavigation.openSavedCustomWorldEditor(editEntry);
|
||||
});
|
||||
},
|
||||
[
|
||||
|
||||
@@ -6,10 +6,14 @@ 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 { CustomWorldGalleryCard } from '../../../packages/shared/src/contracts/runtime';
|
||||
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 } from '../../../packages/shared/src/contracts/woodenFish';
|
||||
import type { CustomWorldProfile } from '../../types';
|
||||
import {
|
||||
EDUTAINMENT_BABY_OBJECT_MATCH_TEMPLATE_ID,
|
||||
EDUTAINMENT_BABY_OBJECT_MATCH_TEMPLATE_NAME,
|
||||
@@ -31,11 +35,13 @@ import {
|
||||
mapWoodenFishWorkToPublicWorkDetail,
|
||||
type PlatformPublicWorkDetailKind,
|
||||
type PlatformPublicWorkDetailOpenStrategy,
|
||||
type PlatformPublicWorkEditIntentDeps,
|
||||
type PlatformPublicWorkStartIntentDeps,
|
||||
resolveActivePlatformPublicWorkAuthorEntry,
|
||||
resolvePlatformPublicWorkActionMode,
|
||||
resolvePlatformPublicWorkDetailOpenDecision,
|
||||
resolvePlatformPublicWorkDetailOpenStrategy,
|
||||
resolvePlatformPublicWorkEditIntent,
|
||||
resolvePlatformPublicWorkLikeIntent,
|
||||
resolvePlatformPublicWorkRemixIntent,
|
||||
resolvePlatformPublicWorkStartIntent,
|
||||
@@ -88,6 +94,18 @@ function buildRpgEntry(
|
||||
};
|
||||
}
|
||||
|
||||
function buildRpgLibraryEntry(
|
||||
overrides: Partial<CustomWorldLibraryEntry<CustomWorldProfile>> = {},
|
||||
): CustomWorldLibraryEntry<CustomWorldProfile> {
|
||||
return {
|
||||
...buildRpgEntry(overrides),
|
||||
profile: {
|
||||
id: overrides.profileId ?? 'rpg-profile',
|
||||
} as unknown as CustomWorldProfile,
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
function buildTypedEntry<TSourceType extends PlatformGallerySourceType>(
|
||||
sourceType: TSourceType,
|
||||
overrides: TypedPlatformPublicGalleryCardOverrides<TSourceType> = {},
|
||||
@@ -410,6 +428,20 @@ function buildStartIntentDeps(
|
||||
};
|
||||
}
|
||||
|
||||
function buildEditIntentDeps(
|
||||
overrides: Partial<PlatformPublicWorkEditIntentDeps> = {},
|
||||
): PlatformPublicWorkEditIntentDeps {
|
||||
return {
|
||||
selectedPuzzleDetail: null,
|
||||
selectedRpgDetailEntry: null,
|
||||
visualNovelWorks: [],
|
||||
barkBattleGalleryEntries: [],
|
||||
barkBattleWorks: [],
|
||||
mapMatch3DWork: () => buildMatch3DWork(),
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
test('platform public work detail flow resolves detail kind for every play kind', () => {
|
||||
const cases: Array<
|
||||
[sourceType: PlatformGallerySourceType, kind: PlatformPublicWorkDetailKind]
|
||||
@@ -435,7 +467,7 @@ test('platform public work detail flow resolves detail kind for every play kind'
|
||||
});
|
||||
|
||||
test('platform public work detail flow resolves open strategy', () => {
|
||||
const rpgEntry = buildRpgEntry();
|
||||
const rpgEntry = buildRpgLibraryEntry();
|
||||
const cases: Array<
|
||||
[
|
||||
entry: PlatformPublicGalleryCard,
|
||||
@@ -522,7 +554,7 @@ test('platform public work detail flow resolves open strategy', () => {
|
||||
});
|
||||
|
||||
test('platform public work detail flow maps work summaries to detail entries', () => {
|
||||
const rpgEntry = buildRpgEntry();
|
||||
const rpgEntry = buildRpgLibraryEntry();
|
||||
|
||||
expect(mapRpgGalleryCardToPublicWorkDetail(rpgEntry)).toBe(rpgEntry);
|
||||
expect(mapPuzzleWorkToPublicWorkDetail(buildPuzzleWork())).toMatchObject({
|
||||
@@ -843,6 +875,205 @@ test('platform public work detail flow resolves remix intent', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('platform public work detail flow resolves edit intent for draft-backed works', () => {
|
||||
const bigFishEntry = buildTypedEntry('big-fish');
|
||||
expect(resolvePlatformPublicWorkEditIntent(bigFishEntry, buildEditIntentDeps()))
|
||||
.toEqual({
|
||||
type: 'edit-big-fish',
|
||||
work: mapPublicWorkDetailToBigFishWork(bigFishEntry),
|
||||
});
|
||||
|
||||
const selectedPuzzleDetail = buildPuzzleWork({
|
||||
profileId: 'puzzle-profile',
|
||||
sourceSessionId: 'selected-puzzle-session',
|
||||
});
|
||||
expect(
|
||||
resolvePlatformPublicWorkEditIntent(
|
||||
buildTypedEntry('puzzle'),
|
||||
buildEditIntentDeps({ selectedPuzzleDetail }),
|
||||
),
|
||||
).toEqual({
|
||||
type: 'edit-puzzle',
|
||||
work: selectedPuzzleDetail,
|
||||
});
|
||||
|
||||
const puzzleEntry = buildTypedEntry('puzzle', {
|
||||
profileId: 'fallback-puzzle-profile',
|
||||
sourceSessionId: 'fallback-puzzle-session',
|
||||
});
|
||||
expect(
|
||||
resolvePlatformPublicWorkEditIntent(
|
||||
puzzleEntry,
|
||||
buildEditIntentDeps({
|
||||
selectedPuzzleDetail: buildPuzzleWork({ profileId: 'stale-profile' }),
|
||||
}),
|
||||
),
|
||||
).toEqual({
|
||||
type: 'edit-puzzle',
|
||||
work: mapPublicWorkDetailToPuzzleWork(puzzleEntry),
|
||||
});
|
||||
|
||||
expect(
|
||||
resolvePlatformPublicWorkEditIntent(
|
||||
buildTypedEntry('puzzle', { sourceSessionId: null }),
|
||||
buildEditIntentDeps(),
|
||||
),
|
||||
).toEqual({
|
||||
type: 'blocked',
|
||||
errorMessage: '这份拼图作品缺少原草稿会话,暂时无法编辑。',
|
||||
});
|
||||
});
|
||||
|
||||
test('platform public work detail flow resolves edit intent for mapper-backed works', () => {
|
||||
const match3DEntry = buildTypedEntry('match3d');
|
||||
const match3DWork = buildMatch3DWork({ workId: 'editable-match3d-work' });
|
||||
expect(
|
||||
resolvePlatformPublicWorkEditIntent(
|
||||
match3DEntry,
|
||||
buildEditIntentDeps({
|
||||
mapMatch3DWork: (entry) =>
|
||||
entry === match3DEntry ? match3DWork : null,
|
||||
}),
|
||||
),
|
||||
).toEqual({
|
||||
type: 'edit-match3d',
|
||||
work: match3DWork,
|
||||
forceDraft: true,
|
||||
});
|
||||
expect(
|
||||
resolvePlatformPublicWorkEditIntent(
|
||||
match3DEntry,
|
||||
buildEditIntentDeps({
|
||||
mapMatch3DWork: () => buildMatch3DWork({ sourceSessionId: ' ' }),
|
||||
}),
|
||||
),
|
||||
).toEqual({
|
||||
type: 'blocked',
|
||||
errorMessage: '这份抓大鹅作品缺少原草稿会话,暂时无法编辑。',
|
||||
});
|
||||
|
||||
const squareHoleEntry = buildTypedEntry('square-hole', {
|
||||
sourceSessionId: 'square-hole-session',
|
||||
});
|
||||
expect(
|
||||
resolvePlatformPublicWorkEditIntent(squareHoleEntry, buildEditIntentDeps()),
|
||||
).toEqual({
|
||||
type: 'edit-square-hole',
|
||||
work: mapPublicWorkDetailToSquareHoleWork(squareHoleEntry),
|
||||
forceDraft: true,
|
||||
});
|
||||
expect(
|
||||
resolvePlatformPublicWorkEditIntent(
|
||||
buildTypedEntry('square-hole', { sourceSessionId: null }),
|
||||
buildEditIntentDeps(),
|
||||
),
|
||||
).toEqual({
|
||||
type: 'blocked',
|
||||
errorMessage: '这份方洞挑战作品缺少原草稿会话,暂时无法编辑。',
|
||||
});
|
||||
});
|
||||
|
||||
test('platform public work detail flow resolves edit intent for cached work lookups', () => {
|
||||
const visualNovelWork = buildVisualNovelWork();
|
||||
expect(
|
||||
resolvePlatformPublicWorkEditIntent(
|
||||
buildTypedEntry('visual-novel'),
|
||||
buildEditIntentDeps({ visualNovelWorks: [visualNovelWork] }),
|
||||
),
|
||||
).toEqual({
|
||||
type: 'edit-visual-novel',
|
||||
work: visualNovelWork,
|
||||
forceDraft: true,
|
||||
});
|
||||
expect(
|
||||
resolvePlatformPublicWorkEditIntent(
|
||||
buildTypedEntry('visual-novel'),
|
||||
buildEditIntentDeps(),
|
||||
),
|
||||
).toEqual({
|
||||
type: 'blocked',
|
||||
errorMessage: '这份视觉小说缺少可编辑草稿。',
|
||||
});
|
||||
|
||||
const entry = buildTypedEntry('bark-battle');
|
||||
const galleryWork = buildBarkBattleWork({
|
||||
workId: 'bark-battle-work',
|
||||
draftId: 'gallery-draft',
|
||||
});
|
||||
const loadedWork = buildBarkBattleWork({
|
||||
workId: 'bark-battle-work',
|
||||
draftId: 'loaded-draft',
|
||||
});
|
||||
expect(
|
||||
resolvePlatformPublicWorkEditIntent(
|
||||
entry,
|
||||
buildEditIntentDeps({
|
||||
barkBattleGalleryEntries: [galleryWork],
|
||||
barkBattleWorks: [loadedWork],
|
||||
}),
|
||||
),
|
||||
).toEqual({
|
||||
type: 'edit-bark-battle',
|
||||
work: loadedWork,
|
||||
forceDraft: true,
|
||||
});
|
||||
expect(
|
||||
resolvePlatformPublicWorkEditIntent(
|
||||
buildTypedEntry('bark-battle', { sourceSessionId: null }),
|
||||
buildEditIntentDeps(),
|
||||
),
|
||||
).toEqual({
|
||||
type: 'blocked',
|
||||
errorMessage: '这份汪汪声浪缺少可编辑草稿。',
|
||||
});
|
||||
});
|
||||
|
||||
test('platform public work detail flow resolves edit intent for unsupported and deferred works', () => {
|
||||
expect(
|
||||
resolvePlatformPublicWorkEditIntent(
|
||||
buildTypedEntry('jump-hop'),
|
||||
buildEditIntentDeps(),
|
||||
),
|
||||
).toEqual({
|
||||
type: 'blocked',
|
||||
errorMessage: '这份跳一跳作品暂时请从作品架编辑。',
|
||||
});
|
||||
expect(
|
||||
resolvePlatformPublicWorkEditIntent(
|
||||
buildTypedEntry('wooden-fish'),
|
||||
buildEditIntentDeps(),
|
||||
),
|
||||
).toEqual({
|
||||
type: 'blocked',
|
||||
errorMessage: '这份敲木鱼作品暂时请从作品架编辑。',
|
||||
});
|
||||
|
||||
const edutainmentEntry = buildTypedEntry('edutainment');
|
||||
expect(
|
||||
resolvePlatformPublicWorkEditIntent(edutainmentEntry, buildEditIntentDeps()),
|
||||
).toEqual({
|
||||
type: 'resolve-edutainment-draft',
|
||||
entry: edutainmentEntry,
|
||||
});
|
||||
|
||||
const rpgEntry = buildRpgLibraryEntry();
|
||||
expect(
|
||||
resolvePlatformPublicWorkEditIntent(
|
||||
rpgEntry,
|
||||
buildEditIntentDeps({ selectedRpgDetailEntry: rpgEntry }),
|
||||
),
|
||||
).toEqual({
|
||||
type: 'edit-rpg-gallery',
|
||||
entry: rpgEntry,
|
||||
});
|
||||
expect(
|
||||
resolvePlatformPublicWorkEditIntent(rpgEntry, buildEditIntentDeps()),
|
||||
).toEqual({
|
||||
type: 'blocked',
|
||||
errorMessage: '作品详情尚未读取完成。',
|
||||
});
|
||||
});
|
||||
|
||||
test('platform public work detail flow resolves start intent for direct launches', () => {
|
||||
const bigFishEntry = buildTypedEntry('big-fish');
|
||||
expect(
|
||||
|
||||
@@ -7,7 +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 { CustomWorldGalleryCard } from '../../../packages/shared/src/contracts/runtime';
|
||||
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 {
|
||||
@@ -15,6 +18,7 @@ import type {
|
||||
WoodenFishWorkProfileResponse,
|
||||
} from '../../../packages/shared/src/contracts/woodenFish';
|
||||
import { buildPublicWorkStagePath } from '../../routing/appPageRoutes';
|
||||
import type { CustomWorldProfile } from '../../types';
|
||||
import {
|
||||
isBarkBattleGalleryEntry,
|
||||
isBigFishGalleryEntry,
|
||||
@@ -51,6 +55,10 @@ export type PlatformPublicWorkDetailKind =
|
||||
| 'visual-novel'
|
||||
| 'wooden-fish';
|
||||
|
||||
export type PlatformRpgPublicWorkDetailEntry =
|
||||
| CustomWorldGalleryCard
|
||||
| CustomWorldLibraryEntry<CustomWorldProfile>;
|
||||
|
||||
export type PlatformPublicWorkDetailOpenStrategy =
|
||||
| {
|
||||
type: 'use-entry';
|
||||
@@ -77,7 +85,7 @@ export type PlatformPublicWorkDetailOpenStrategy =
|
||||
}
|
||||
| {
|
||||
type: 'load-rpg-detail';
|
||||
entry: CustomWorldGalleryCard;
|
||||
entry: PlatformRpgPublicWorkDetailEntry;
|
||||
};
|
||||
|
||||
export type PlatformPublicWorkActionMode = 'edit' | 'remix';
|
||||
@@ -122,6 +130,59 @@ export type PlatformPublicWorkRemixIntent =
|
||||
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<CustomWorldProfile>;
|
||||
};
|
||||
|
||||
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';
|
||||
@@ -175,12 +236,12 @@ export type PlatformPublicWorkStartIntent =
|
||||
}
|
||||
| {
|
||||
type: 'record-rpg-gallery-play';
|
||||
entry: CustomWorldGalleryCard;
|
||||
entry: PlatformRpgPublicWorkDetailEntry;
|
||||
};
|
||||
|
||||
export type PlatformPublicWorkStartIntentDeps = {
|
||||
selectedPuzzleDetail?: PuzzleWorkSummary | null;
|
||||
selectedRpgDetailEntry?: CustomWorldGalleryCard | null;
|
||||
selectedRpgDetailEntry?: PlatformRpgPublicWorkDetailEntry | null;
|
||||
barkBattleGalleryEntries?: readonly BarkBattleWorkSummary[];
|
||||
barkBattleWorks?: readonly BarkBattleWorkSummary[];
|
||||
mapMatch3DWork: (
|
||||
@@ -213,21 +274,27 @@ export type PlatformPublicWorkDetailOpenDecisionDeps = {
|
||||
export type ActivePlatformPublicWorkAuthorEntryInput = {
|
||||
selectionStage: string;
|
||||
selectedPublicWorkDetail: PlatformPublicGalleryCard | null;
|
||||
selectedRpgDetailEntry: CustomWorldGalleryCard | null;
|
||||
selectedRpgDetailEntry: PlatformRpgPublicWorkDetailEntry | null;
|
||||
};
|
||||
|
||||
export function isRpgPublicWorkDetailEntry(
|
||||
entry: PlatformPublicGalleryCard,
|
||||
): entry is CustomWorldGalleryCard {
|
||||
): entry is PlatformRpgPublicWorkDetailEntry {
|
||||
return !('sourceType' in entry);
|
||||
}
|
||||
|
||||
export function mapRpgGalleryCardToPublicWorkDetail(
|
||||
entry: CustomWorldGalleryCard,
|
||||
entry: PlatformRpgPublicWorkDetailEntry,
|
||||
): PlatformPublicGalleryCard {
|
||||
return entry;
|
||||
}
|
||||
|
||||
function isRpgPublicWorkLibraryEntry(
|
||||
entry: PlatformRpgPublicWorkDetailEntry | null | undefined,
|
||||
): entry is CustomWorldLibraryEntry<CustomWorldProfile> {
|
||||
return Boolean(entry && 'profile' in entry);
|
||||
}
|
||||
|
||||
export function mapPuzzleWorkToPublicWorkDetail(
|
||||
item: PuzzleWorkSummary,
|
||||
): PlatformPublicGalleryCard {
|
||||
@@ -689,6 +756,154 @@ export function resolvePlatformPublicWorkRemixIntent(
|
||||
};
|
||||
}
|
||||
|
||||
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 (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,
|
||||
|
||||
Reference in New Issue
Block a user