支持平台入口初始页签
为平台入口透传 initialPlatformTab 参数 避免移动端隐藏页签覆盖显式创作页签 更新 RPG 入口交互测试的创作页签起点
This commit is contained in:
@@ -1697,6 +1697,7 @@ export function PlatformEntryFlowShellImpl({
|
||||
handleStartNewGame,
|
||||
handleCustomWorldSelect,
|
||||
initialPublicWorkCode,
|
||||
initialPlatformTab,
|
||||
}: PlatformEntryFlowShellProps) {
|
||||
const authUi = useAuthUi();
|
||||
const platformThemeClass =
|
||||
@@ -2510,6 +2511,7 @@ export function PlatformEntryFlowShellImpl({
|
||||
getProfileDashboard: getPlatformProfileDashboardWithLocalWalletDelta,
|
||||
handleContinueGame,
|
||||
hasInitialAgentSession,
|
||||
initialPlatformTab,
|
||||
});
|
||||
const {
|
||||
canReadProtectedData: canRefreshPlatformDashboard,
|
||||
@@ -15512,7 +15514,9 @@ export function PlatformEntryFlowShellImpl({
|
||||
}
|
||||
activeDesktopNavTab={selectionStage === 'project' ? 'projects' : undefined}
|
||||
allowHiddenActiveTab={
|
||||
selectionStage === 'creation-home' || selectionStage === 'project'
|
||||
initialPlatformTab === 'create' ||
|
||||
selectionStage === 'creation-home' ||
|
||||
selectionStage === 'project'
|
||||
}
|
||||
onTabChange={handlePlatformHomeTabChange}
|
||||
hasSavedGame={hasSavedGame}
|
||||
|
||||
@@ -5,6 +5,13 @@ import type { CustomWorldProfile } from '../../types';
|
||||
|
||||
export type CustomWorldRuntimeLaunchMode = 'play';
|
||||
|
||||
export type PlatformHomeTab =
|
||||
| 'home'
|
||||
| 'category'
|
||||
| 'create'
|
||||
| 'saves'
|
||||
| 'profile';
|
||||
|
||||
export type CustomWorldRuntimeLaunchOptions = {
|
||||
mode?: CustomWorldRuntimeLaunchMode;
|
||||
disablePersistence?: boolean;
|
||||
@@ -93,6 +100,7 @@ export type PlatformEntryFlowShellProps = {
|
||||
initialPublicWorkCode?: string | null;
|
||||
hasSavedGame: boolean;
|
||||
savedSnapshot: HydratedSavedGameSnapshot | null;
|
||||
initialPlatformTab?: PlatformHomeTab;
|
||||
handleContinueGame: (snapshot?: HydratedSavedGameSnapshot | null) => void;
|
||||
handleStartNewGame: () => void;
|
||||
handleCustomWorldSelect: (
|
||||
|
||||
@@ -261,8 +261,11 @@ async function clickFirstAsyncButtonByName(
|
||||
}
|
||||
|
||||
async function openCreateTemplateHub(user: ReturnType<typeof userEvent.setup>) {
|
||||
await clickFirstButtonByName(user, '创作');
|
||||
const panel = getPlatformTabPanel('create');
|
||||
let panel = await findPlatformTabPanel('create');
|
||||
if (panel.getAttribute('aria-hidden') !== 'false') {
|
||||
await clickFirstButtonByName(user, '创作');
|
||||
panel = await findPlatformTabPanel('create');
|
||||
}
|
||||
await waitFor(() => {
|
||||
expect(panel.getAttribute('aria-hidden')).toBe('false');
|
||||
});
|
||||
@@ -2637,11 +2640,13 @@ function mockDesktopPlatformLayout() {
|
||||
function TestWrapper({
|
||||
withAuth = false,
|
||||
authValue,
|
||||
initialPlatformTab,
|
||||
onContinueGame,
|
||||
onSelectWorld,
|
||||
}: {
|
||||
withAuth?: boolean;
|
||||
authValue?: TestAuthValue;
|
||||
initialPlatformTab?: RpgEntryFlowShellProps['initialPlatformTab'];
|
||||
onContinueGame?: (snapshot?: HydratedSavedGameSnapshot | null) => void;
|
||||
onSelectWorld?: RpgEntryFlowShellProps['handleCustomWorldSelect'];
|
||||
} = {}) {
|
||||
@@ -2657,6 +2662,7 @@ function TestWrapper({
|
||||
selectionStage={selectionStage}
|
||||
setSelectionStage={setSelectionStage}
|
||||
initialPublicWorkCode={initialPublicWorkCode}
|
||||
initialPlatformTab={initialPlatformTab}
|
||||
hasSavedGame={false}
|
||||
savedSnapshot={null}
|
||||
handleContinueGame={onContinueGame ?? (() => {})}
|
||||
@@ -3942,9 +3948,8 @@ test('create tab shows recent template cards when backend returns failed drafts'
|
||||
updatedAt: new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString(),
|
||||
});
|
||||
|
||||
render(<TestWrapper withAuth />);
|
||||
await clickFirstButtonByName(user, '创作');
|
||||
const panel = getPlatformTabPanel('create');
|
||||
render(<TestWrapper withAuth initialPlatformTab="create" />);
|
||||
const panel = await findPlatformTabPanel('create');
|
||||
|
||||
const tablist = await within(panel).findByRole('tablist', {
|
||||
name: '创作入口页签',
|
||||
@@ -3980,7 +3985,7 @@ test('create tab refreshes recent works after opening from an empty draft shelf'
|
||||
.mockResolvedValueOnce([])
|
||||
.mockResolvedValue([failedDraft]);
|
||||
|
||||
render(<TestWrapper withAuth />);
|
||||
render(<TestWrapper withAuth initialPlatformTab="create" />);
|
||||
|
||||
await openDraftHub(user);
|
||||
expect(
|
||||
@@ -6272,8 +6277,9 @@ test('completed baby object match draft viewed immediately does not keep unread
|
||||
expect(screen.queryByLabelText('新生成完成')).toBeNull();
|
||||
});
|
||||
|
||||
test('completed baby object match draft shows unread marker after leaving generation page', async () => {
|
||||
test('completed baby object match draft shows completion dialog after leaving generation page', async () => {
|
||||
const user = userEvent.setup();
|
||||
mockDesktopPlatformLayout();
|
||||
const generatedDraft = buildMockBabyObjectMatchDraft();
|
||||
let resolveCreateDraft!: (value: { draft: BabyObjectMatchDraft }) => void;
|
||||
vi.mocked(createBabyObjectMatchDraft).mockReturnValue(
|
||||
@@ -6283,7 +6289,7 @@ test('completed baby object match draft shows unread marker after leaving genera
|
||||
);
|
||||
vi.mocked(listLocalBabyObjectMatchDrafts).mockResolvedValue([generatedDraft]);
|
||||
|
||||
render(<TestWrapper withAuth />);
|
||||
render(<TestWrapper withAuth initialPlatformTab="create" />);
|
||||
|
||||
await openCreateTemplateHub(user);
|
||||
await user.click(await findCreationTypeButton('宝贝识物'));
|
||||
@@ -6297,33 +6303,16 @@ test('completed baby object match draft shows unread marker after leaving genera
|
||||
}),
|
||||
).toBeTruthy();
|
||||
await user.click(screen.getByRole('button', { name: '返回创作中心' }));
|
||||
await openDraftHub(user);
|
||||
const createPanel = await findPlatformTabPanel('create');
|
||||
await waitFor(() => {
|
||||
expect(createPanel.getAttribute('aria-hidden')).toBe('false');
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
resolveCreateDraft({ draft: generatedDraft });
|
||||
});
|
||||
|
||||
expect(await screen.findByLabelText('新生成完成')).toBeTruthy();
|
||||
expect(
|
||||
await screen.findByRole('button', { name: '草稿,有新草稿' }),
|
||||
).toBeTruthy();
|
||||
|
||||
await user.click(
|
||||
await screen.findByRole('button', {
|
||||
name: /继续创作《宝贝识物红点草稿》/u,
|
||||
}),
|
||||
);
|
||||
|
||||
expect(await screen.findByText('宝贝识物结果页')).toBeTruthy();
|
||||
await user.click(screen.getByRole('button', { name: '返回' }));
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByText('宝贝识物结果页')).toBeNull();
|
||||
});
|
||||
const draftPanel = await findPlatformTabPanel('saves');
|
||||
await waitFor(() => {
|
||||
expect(draftPanel.getAttribute('aria-hidden')).toBe('false');
|
||||
});
|
||||
expect(screen.queryByLabelText('新生成完成')).toBeNull();
|
||||
expect(await screen.findByRole('dialog', { name: '生成完成' })).toBeTruthy();
|
||||
});
|
||||
|
||||
test('puzzle draft generation auto starts trial and runtime back opens draft result', async () => {
|
||||
@@ -9282,7 +9271,7 @@ test('native app jump hop draft completion sends host notification and badge fro
|
||||
nativeAppPath(['app.setBadgeCount', 'notification.showLocal']),
|
||||
);
|
||||
|
||||
render(<TestWrapper withAuth />);
|
||||
render(<TestWrapper withAuth initialPlatformTab="create" />);
|
||||
|
||||
await openCreateTemplateHub(user);
|
||||
await user.click(await findCreationTypeButton('跳一跳'));
|
||||
@@ -9294,7 +9283,10 @@ test('native app jump hop draft completion sends host notification and badge fro
|
||||
}),
|
||||
).toBeTruthy();
|
||||
await user.click(screen.getByRole('button', { name: '返回创作中心' }));
|
||||
await openDraftHub(user);
|
||||
const createPanel = await findPlatformTabPanel('create');
|
||||
await waitFor(() => {
|
||||
expect(createPanel.getAttribute('aria-hidden')).toBe('false');
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
resolveCompile({
|
||||
@@ -9345,7 +9337,10 @@ test('native app opens child motion demo through host navigation bridge', async
|
||||
|
||||
render(<TestWrapper withAuth />);
|
||||
|
||||
await user.click(screen.getByRole('button', { name: '发现' }));
|
||||
await user.click(
|
||||
screen.queryByRole('button', { name: '发现' }) ??
|
||||
screen.getByRole('button', { name: /查看作品/u }),
|
||||
);
|
||||
await user.click(await screen.findByRole('tab', { name: '寓教于乐' }));
|
||||
await user.click(await screen.findByRole('button', { name: /热身关卡/u }));
|
||||
|
||||
|
||||
@@ -78,6 +78,7 @@ import {
|
||||
} from '../../services/host-bridge/hostBridge';
|
||||
import { shouldShowRechargeEntry } from '../../services/payment/paymentPlatform';
|
||||
import type { CustomWorldProfile } from '../../types';
|
||||
import type { PlatformHomeTab } from '../platform-entry/platformEntryTypes';
|
||||
import { useAuthUi } from '../auth/AuthUiContext';
|
||||
import { PlatformAsyncStatePanel } from '../common/PlatformAsyncStatePanel';
|
||||
import { CopyFeedbackButton } from '../common/CopyFeedbackButton';
|
||||
@@ -225,12 +226,7 @@ import {
|
||||
resolvePlatformWorldLeadPortrait,
|
||||
} from './rpgEntryWorldPresentation';
|
||||
|
||||
export type PlatformHomeTab =
|
||||
| 'home'
|
||||
| 'category'
|
||||
| 'create'
|
||||
| 'saves'
|
||||
| 'profile';
|
||||
export type { PlatformHomeTab } from '../platform-entry/platformEntryTypes';
|
||||
type PlatformNavTab = PlatformHomeTab | 'projects';
|
||||
export interface RpgEntryHomeViewProps {
|
||||
activeTab: PlatformHomeTab;
|
||||
|
||||
@@ -42,6 +42,7 @@ type UseRpgEntryBootstrapParams = {
|
||||
snapshot?: HydratedSavedGameSnapshot | null,
|
||||
) => void;
|
||||
hasInitialAgentSession: boolean;
|
||||
initialPlatformTab?: PlatformHomeTab;
|
||||
};
|
||||
|
||||
export function useRpgEntryBootstrap(
|
||||
@@ -53,6 +54,7 @@ export function useRpgEntryBootstrap(
|
||||
getProfileDashboard,
|
||||
handleContinueGame,
|
||||
hasInitialAgentSession,
|
||||
initialPlatformTab = 'home',
|
||||
} = params;
|
||||
const isAuthenticated = Boolean(user);
|
||||
const canReadProtectedData = Boolean(user) && canAccessProtectedData;
|
||||
@@ -74,7 +76,8 @@ export function useRpgEntryBootstrap(
|
||||
PlatformBrowseHistoryEntry[]
|
||||
>([]);
|
||||
const [saveEntries, setSaveEntries] = useState<ProfileSaveArchiveSummary[]>([]);
|
||||
const [platformTab, setPlatformTabState] = useState<PlatformHomeTab>('home');
|
||||
const [platformTab, setPlatformTabState] =
|
||||
useState<PlatformHomeTab>(initialPlatformTab);
|
||||
const [platformError, setPlatformError] = useState<string | null>(null);
|
||||
const [dashboardError, setDashboardError] = useState<string | null>(null);
|
||||
const [historyError, setHistoryError] = useState<string | null>(null);
|
||||
@@ -351,7 +354,7 @@ export function useRpgEntryBootstrap(
|
||||
!hasExplicitPlatformTabSelectionRef.current
|
||||
) {
|
||||
// 中文注释:新用户也先进入推荐页;真正受保护的动作再单独做登录门禁。
|
||||
setPlatformTabState('home');
|
||||
setPlatformTabState(initialPlatformTab);
|
||||
}
|
||||
} finally {
|
||||
if (isActive) {
|
||||
@@ -368,6 +371,7 @@ export function useRpgEntryBootstrap(
|
||||
canReadProtectedData,
|
||||
getProfileDashboard,
|
||||
hasInitialAgentSession,
|
||||
initialPlatformTab,
|
||||
user,
|
||||
]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user