import { Archive, ArrowRight, Bell, BookOpen, Camera, ChevronRight, Clock3, Coins, Copy, Crown, House, LogIn, MessageCircle, Pencil, Search, Settings, Sparkles, Tags, Ticket, UserPlus, UserRound, } from 'lucide-react'; import { type ComponentType, type ReactNode, useEffect, useMemo, useState, } from 'react'; import type { CustomWorldLibraryEntry, PlatformBrowseHistoryEntry, ProfileDashboardCardKey, ProfileDashboardSummary, ProfileWalletLedgerResponse, ProfileRechargeCenterResponse, ProfileRechargeProduct, ProfileReferralInviteCenterResponse, ProfileSaveArchiveSummary, RedeemProfileReferralInviteCodeResponse, } from '../../../packages/shared/src/contracts/runtime'; import type { HydratedSavedGameSnapshot } from '../../persistence/runtimeSnapshotTypes'; import type { AuthUser } from '../../services/authService'; import { createRpgProfileRechargeOrder, getRpgProfileRechargeCenter, getRpgProfileReferralInviteCenter, getRpgProfileWalletLedger, redeemRpgProfileReferralInviteCode, } from '../../services/rpg-entry/rpgProfileClient'; import type { CustomWorldProfile } from '../../types'; import { useAuthUi } from '../auth/AuthUiContext'; import { ResolvedAssetImage } from '../ResolvedAssetImage'; import { RpgEntryBrandLogo } from './RpgEntryBrandLogo'; import { buildPlatformWorldTags, describePlatformThemeLabel, formatPlatformWorldTime, isBigFishGalleryEntry, isPuzzleGalleryEntry, type PlatformPublicGalleryCard, type PlatformWorldCardLike, resolvePlatformWorldCoverImage, resolvePlatformWorldLeadPortrait, } from './rpgEntryWorldPresentation'; export type PlatformHomeTab = | 'home' | 'category' | 'create' | 'saves' | 'profile'; export interface RpgEntryHomeViewProps { activeTab: PlatformHomeTab; onTabChange: (tab: PlatformHomeTab) => void; hasSavedGame: boolean; savedSnapshot: HydratedSavedGameSnapshot | null; saveEntries: ProfileSaveArchiveSummary[]; saveError: string | null; featuredEntries: PlatformPublicGalleryCard[]; latestEntries: PlatformPublicGalleryCard[]; myEntries: CustomWorldLibraryEntry[]; historyEntries: PlatformBrowseHistoryEntry[]; profileDashboard: ProfileDashboardSummary | null; isLoadingPlatform: boolean; isLoadingDashboard: boolean; isResumingSaveWorldKey: string | null; platformError: string | null; dashboardError: string | null; onContinueGame: (snapshot?: HydratedSavedGameSnapshot | null) => void; onResumeSave: (entry: ProfileSaveArchiveSummary) => void; onOpenCreateWorld: () => void; onOpenCreateTypePicker: () => void; onOpenGalleryDetail: (entry: PlatformPublicGalleryCard) => void; onOpenLibraryDetail: ( entry: CustomWorldLibraryEntry, ) => void; onDeleteLibraryEntry?: ( entry: CustomWorldLibraryEntry, ) => void; deletingLibraryEntryId?: string | null; onSearchPublicCode?: (keyword: string) => void | Promise; isSearchingPublicCode?: boolean; onOpenProfileDashboardCard?: (cardKey: ProfileDashboardCardKey) => void; onRechargeSuccess?: () => void | Promise; createTabContent?: ReactNode; } const PANEL_SURFACE_CLASS = 'platform-surface platform-surface--soft'; const HERO_SURFACE_CLASS = 'platform-surface platform-surface--hero platform-interactive-card min-w-0'; const MOBILE_PAGE_STAGE_CLASS = 'platform-page-stage platform-remap-surface min-w-0 space-y-4 overflow-hidden pb-2'; const DESKTOP_PAGE_STAGE_CLASS = 'platform-page-stage platform-remap-surface min-w-0 space-y-5 pb-4'; const DESKTOP_LAYOUT_QUERY = '(min-width: 1024px)'; const PLATFORM_HOME_TABS: PlatformHomeTab[] = [ 'home', 'category', 'create', 'saves', 'profile', ]; type ProfilePopupPanel = 'invite' | 'redeem' | 'community'; function usePlatformDesktopLayout() { const [isDesktopLayout, setIsDesktopLayout] = useState(() => { if ( typeof window === 'undefined' || typeof window.matchMedia !== 'function' ) { return false; } return window.matchMedia(DESKTOP_LAYOUT_QUERY).matches; }); useEffect(() => { if ( typeof window === 'undefined' || typeof window.matchMedia !== 'function' ) { return; } const mediaQuery = window.matchMedia(DESKTOP_LAYOUT_QUERY); const updateLayout = (event?: MediaQueryListEvent) => { setIsDesktopLayout(event?.matches ?? mediaQuery.matches); }; updateLayout(); // 平台页只挂载当前断点外壳,避免隐藏的移动端/桌面端内容重复抢占查询。 if (typeof mediaQuery.addEventListener === 'function') { mediaQuery.addEventListener('change', updateLayout); return () => mediaQuery.removeEventListener('change', updateLayout); } mediaQuery.addListener(updateLayout); return () => mediaQuery.removeListener(updateLayout); }, []); return isDesktopLayout; } function ResolvedAssetBackdrop({ src, alt, className, ariaHidden = false, }: { src?: string | null; alt: string; className: string; ariaHidden?: boolean; }) { return ( ); } function SectionHeader({ title, detail }: { title: string; detail: string }) { return (
{detail}
{title}
); } function PublicCodeSearchBar({ value, onChange, onSubmit, isSearching, className, }: { value: string; onChange: (value: string) => void; onSubmit: () => void; isSearching: boolean; className?: string; }) { return (
onChange(event.target.value)} onKeyDown={(event) => { if (event.key === 'Enter') { event.preventDefault(); onSubmit(); } }} placeholder="输入 SY / CW / BF / PZ 编号" className="w-full min-w-0 bg-transparent text-sm text-[var(--platform-text-strong)] outline-none placeholder:text-[var(--platform-text-soft)]" />
); } function EmptyShelf({ text }: { text: string }) { return (
{text}
); } function SaveArchivePreview({ entry, label, className, }: { entry: ProfileSaveArchiveSummary; label: string; className: string; }) { return (