继续收口首页公开分区异步状态壳

统一首页公开列表与我的创作分区的异步状态切换到 PlatformAsyncStatePanel
补充首页异步状态回归测试覆盖登录态作品分区与桌面公开空态
更新 PlatformUiKit 收口计划与共享决策记录
This commit is contained in:
2026-06-11 02:53:31 +08:00
parent 84ded19f11
commit ae1a15cee0
4 changed files with 132 additions and 65 deletions

View File

@@ -983,7 +983,11 @@ function renderLoggedInHomeView(
overrides: Partial<
Pick<
RpgEntryHomeViewProps,
'activeTab' | 'hasUnreadDraftUpdate' | 'draftTabContent'
| 'activeTab'
| 'hasUnreadDraftUpdate'
| 'draftTabContent'
| 'myEntries'
| 'isLoadingPlatform'
>
> = {},
) {
@@ -1025,10 +1029,10 @@ function renderLoggedInHomeView(
saveError={null}
featuredEntries={[]}
latestEntries={[]}
myEntries={[]}
myEntries={overrides.myEntries ?? []}
historyEntries={[]}
profileDashboard={null}
isLoadingPlatform={false}
isLoadingPlatform={overrides.isLoadingPlatform ?? false}
isLoadingDashboard={false}
isResumingSaveWorldKey={null}
platformError={null}
@@ -3514,6 +3518,40 @@ test('logged in draft bottom tab shows unread marker', () => {
expect(draftButton.querySelector('.platform-nav-unread-dot')).toBeTruthy();
});
test('logged in saves tab shows loading state while fetching my entries', () => {
renderLoggedInHomeView({
activeTab: 'saves',
isLoadingPlatform: true,
});
expect(screen.getByText('我的创作')).toBeTruthy();
expect(screen.getByText('正在读取你的作品...')).toBeTruthy();
expect(
screen.queryByText('你还没有保存任何自定义世界,先创建一个草稿开始吧。'),
).toBeNull();
});
test('logged in saves tab shows empty state when my entries are missing', () => {
renderLoggedInHomeView({
activeTab: 'saves',
myEntries: [],
});
expect(screen.getByText('我的创作')).toBeTruthy();
expect(
screen.getByText('你还没有保存任何自定义世界,先创建一个草稿开始吧。'),
).toBeTruthy();
expect(screen.queryByText('正在读取你的作品...')).toBeNull();
});
test('desktop home shows empty states when public shelves are unavailable', () => {
mockDesktopLayout();
renderLoggedOutHomeView(vi.fn(), {}, 'home', true);
expect(screen.getByText('今天暂时还没有新游戏。')).toBeTruthy();
expect(screen.getByText('暂时还没有推荐作品。')).toBeTruthy();
});
test('logged in create tab shows real wallet balance beside the brand', () => {
mockNarrowMobileLayout();

View File

@@ -74,6 +74,7 @@ import { shouldShowRechargeEntry } from '../../services/payment/paymentPlatform'
import type { CustomWorldProfile } from '../../types';
import { useAuthUi } from '../auth/AuthUiContext';
import { PlatformAcknowledgeStatusDialog } from '../common/PlatformAcknowledgeStatusDialog';
import { PlatformAsyncStatePanel } from '../common/PlatformAsyncStatePanel';
import { CopyFeedbackButton } from '../common/CopyFeedbackButton';
import { LegalDocumentModal } from '../common/LegalDocumentModal';
import {
@@ -3539,9 +3540,14 @@ export function RpgEntryHomeView({
}
/>
{isLoadingPlatform ? (
<PlatformEmptyState>...</PlatformEmptyState>
) : rankingEntries.length > 0 ? (
<PlatformAsyncStatePanel
isLoading={isLoadingPlatform}
loadingState={<PlatformEmptyState>...</PlatformEmptyState>}
isEmpty={rankingEntries.length === 0}
emptyState={
<PlatformEmptyState>{activeRankingConfig.emptyText}</PlatformEmptyState>
}
>
<div className="mt-3 grid min-w-0 gap-2.5">
{rankingEntries.map((entry, index) => (
<PlatformRankingItem
@@ -3553,9 +3559,7 @@ export function RpgEntryHomeView({
/>
))}
</div>
) : (
<PlatformEmptyState>{activeRankingConfig.emptyText}</PlatformEmptyState>
)}
</PlatformAsyncStatePanel>
</section>
);
@@ -3823,11 +3827,18 @@ export function RpgEntryHomeView({
</section>
) : discoverChannel === 'edutainment' ? (
<section className="platform-mobile-home-feed">
{isLoadingPlatform ? (
<PlatformEmptyState>...</PlatformEmptyState>
) : edutainmentFeedEntries.length > 0 ||
onOpenChildMotionDemo ||
onOpenBabyLoveDrawing ? (
<PlatformAsyncStatePanel
isLoading={isLoadingPlatform}
loadingState={<PlatformEmptyState>...</PlatformEmptyState>}
isEmpty={
edutainmentFeedEntries.length === 0 &&
!onOpenChildMotionDemo &&
!onOpenBabyLoveDrawing
}
emptyState={
<PlatformEmptyState></PlatformEmptyState>
}
>
<div className="grid min-w-0 gap-3">
{edutainmentFeedEntries.map((entry) => {
const cardKey = buildPublicGalleryCardKey(entry);
@@ -3881,20 +3892,23 @@ export function RpgEntryHomeView({
</button>
) : null}
</div>
) : (
<PlatformEmptyState>
</PlatformEmptyState>
)}
</PlatformAsyncStatePanel>
</section>
) : (
<section
ref={mobileDiscoverFeedRef}
className="platform-mobile-home-feed"
>
{isLoadingPlatform ? (
<PlatformEmptyState>...</PlatformEmptyState>
) : discoverFeedEntries.length > 0 ? (
<PlatformAsyncStatePanel
isLoading={isLoadingPlatform}
loadingState={<PlatformEmptyState>...</PlatformEmptyState>}
isEmpty={discoverFeedEntries.length === 0}
emptyState={
<PlatformEmptyState>
广
</PlatformEmptyState>
}
>
<div className="grid min-w-0 gap-3">
{discoverFeedEntries.map(
(entry: PlatformPublicGalleryCard) => {
@@ -3918,11 +3932,7 @@ export function RpgEntryHomeView({
},
)}
</div>
) : (
<PlatformEmptyState>
广
</PlatformEmptyState>
)}
</PlatformAsyncStatePanel>
</section>
)}
</>
@@ -4043,11 +4053,18 @@ export function RpgEntryHomeView({
) : discoverChannel === 'edutainment' ? (
<section className="platform-desktop-panel px-5 py-5">
<SectionHeader title={EDUTAINMENT_WORK_TAG} detail="EDUTAINMENT" />
{isLoadingPlatform ? (
<PlatformEmptyState>...</PlatformEmptyState>
) : edutainmentFeedEntries.length > 0 ||
onOpenChildMotionDemo ||
onOpenBabyLoveDrawing ? (
<PlatformAsyncStatePanel
isLoading={isLoadingPlatform}
loadingState={<PlatformEmptyState>...</PlatformEmptyState>}
isEmpty={
edutainmentFeedEntries.length === 0 &&
!onOpenChildMotionDemo &&
!onOpenBabyLoveDrawing
}
emptyState={
<PlatformEmptyState></PlatformEmptyState>
}
>
<div className="grid gap-4 xl:grid-cols-3">
{edutainmentFeedEntries.map((entry) => (
<WorldCard
@@ -4096,9 +4113,7 @@ export function RpgEntryHomeView({
</button>
) : null}
</div>
) : (
<PlatformEmptyState></PlatformEmptyState>
)}
</PlatformAsyncStatePanel>
</section>
) : (
<section className="platform-desktop-panel px-5 py-5">
@@ -4106,9 +4121,16 @@ export function RpgEntryHomeView({
title={discoverChannel === 'today' ? '今日游戏' : '推荐'}
detail={discoverChannel === 'today' ? 'TODAY GAMES' : 'RECOMMENDED'}
/>
{isLoadingPlatform ? (
<PlatformEmptyState>...</PlatformEmptyState>
) : discoverFeedEntries.length > 0 ? (
<PlatformAsyncStatePanel
isLoading={isLoadingPlatform}
loadingState={<PlatformEmptyState>...</PlatformEmptyState>}
isEmpty={discoverFeedEntries.length === 0}
emptyState={
<PlatformEmptyState>
广
</PlatformEmptyState>
}
>
<div className="grid gap-4 xl:grid-cols-3">
{discoverFeedEntries.map((entry) => (
<WorldCard
@@ -4121,11 +4143,7 @@ export function RpgEntryHomeView({
/>
))}
</div>
) : (
<PlatformEmptyState>
广
</PlatformEmptyState>
)}
</PlatformAsyncStatePanel>
</section>
)}
</div>
@@ -4181,9 +4199,18 @@ export function RpgEntryHomeView({
{platformError}
</PlatformStatusMessage>
) : null}
{isLoadingPlatform ? (
<PlatformEmptyState>...</PlatformEmptyState>
) : myEntries.length > 0 ? (
<PlatformAsyncStatePanel
isLoading={isLoadingPlatform}
loadingState={<PlatformEmptyState>...</PlatformEmptyState>}
isEmpty={myEntries.length === 0}
emptyState={
<PlatformEmptyState>
{isAuthenticated
? '你还没有保存任何自定义世界,先创建一个草稿开始吧。'
: '登录后查看你的作品。'}
</PlatformEmptyState>
}
>
<div className="grid grid-cols-2 gap-2.5 sm:gap-3 xl:grid-cols-3">
{myEntries.map(
(entry: CustomWorldLibraryEntry<CustomWorldProfile>) => (
@@ -4201,13 +4228,7 @@ export function RpgEntryHomeView({
),
)}
</div>
) : (
<PlatformEmptyState>
{isAuthenticated
? '你还没有保存任何自定义世界,先创建一个草稿开始吧。'
: '登录后查看你的作品。'}
</PlatformEmptyState>
)}
</PlatformAsyncStatePanel>
</section>
</div>
);
@@ -4629,9 +4650,14 @@ export function RpgEntryHomeView({
TODAY
</PlatformPillBadge>
</div>
{isLoadingPlatform ? (
<PlatformEmptyState>...</PlatformEmptyState>
) : desktopTodayEntries.length > 0 ? (
<PlatformAsyncStatePanel
isLoading={isLoadingPlatform}
loadingState={<PlatformEmptyState>...</PlatformEmptyState>}
isEmpty={desktopTodayEntries.length === 0}
emptyState={
<PlatformEmptyState></PlatformEmptyState>
}
>
<div className="space-y-3">
{desktopTodayEntries.slice(0, 3).map((entry, index) => (
<DesktopTrendingItem
@@ -4642,9 +4668,7 @@ export function RpgEntryHomeView({
/>
))}
</div>
) : (
<PlatformEmptyState></PlatformEmptyState>
)}
</PlatformAsyncStatePanel>
</section>
</div>
@@ -4653,9 +4677,14 @@ export function RpgEntryHomeView({
>
<section className="platform-desktop-panel px-5 py-5">
<SectionHeader title="推荐" detail="RECOMMENDED" />
{isLoadingPlatform ? (
<PlatformEmptyState>...</PlatformEmptyState>
) : desktopFeaturedGrid.length > 0 ? (
<PlatformAsyncStatePanel
isLoading={isLoadingPlatform}
loadingState={<PlatformEmptyState>...</PlatformEmptyState>}
isEmpty={desktopFeaturedGrid.length === 0}
emptyState={
<PlatformEmptyState></PlatformEmptyState>
}
>
<div className="grid gap-4 xl:grid-cols-2">
{desktopFeaturedGrid.map((entry) => (
<WorldCard
@@ -4668,9 +4697,7 @@ export function RpgEntryHomeView({
/>
))}
</div>
) : (
<PlatformEmptyState></PlatformEmptyState>
)}
</PlatformAsyncStatePanel>
</section>
{desktopLibraryPreview.length > 0 ||