import { ArrowLeft, Copy, Share2 } from 'lucide-react'; import { useState } from 'react'; import type { CustomWorldLibraryEntry } from '../../../packages/shared/src/contracts/runtime'; import { buildCustomWorldPlayableCharacters } from '../../data/characterPresets'; import { buildPublicWorkDetailUrl } from '../../routing/appPageRoutes'; import { copyTextToClipboard } from '../../services/clipboard'; import type { CustomWorldProfile } from '../../types'; import { ResolvedAssetImage } from '../ResolvedAssetImage'; import { buildPlatformWorldDisplayTags, describePlatformThemeLabel, formatPlatformWorkDisplayName, formatPlatformWorkDisplayTag, formatPlatformWorldTime, resolvePlatformPublicWorkCode, resolvePlatformWorldCoverImage, resolvePlatformWorldLeadPortrait, } from './rpgEntryWorldPresentation'; export interface RpgEntryWorldDetailViewProps { entry: CustomWorldLibraryEntry; isMutating: boolean; error: string | null; onBack: () => void; onStartGame: () => void; onContinueEdit?: (() => void) | null; onPublish?: (() => void) | null; onDelete?: (() => void) | null; onUnpublish?: (() => void) | null; } function ActionButton({ label, onClick, tone = 'default', disabled = false, }: { label: string; onClick: () => void; tone?: 'default' | 'primary' | 'danger'; disabled?: boolean; }) { const toneClass = tone === 'primary' ? 'platform-button platform-button--primary' : tone === 'danger' ? 'platform-button platform-button--danger' : 'platform-button platform-button--secondary'; return ( ); } export function RpgEntryWorldDetailView({ entry, isMutating, error, onBack, onStartGame, onContinueEdit, onPublish, onDelete, onUnpublish, }: RpgEntryWorldDetailViewProps) { const coverImage = resolvePlatformWorldCoverImage(entry); const leadPortrait = resolvePlatformWorldLeadPortrait(entry); const publicWorkCode = resolvePlatformPublicWorkCode(entry); const [copyState, setCopyState] = useState<'idle' | 'copied' | 'failed'>( 'idle', ); const [shareState, setShareState] = useState<'idle' | 'copied' | 'failed'>( 'idle', ); const canStartGame = entry.visibility === 'published'; const previewCharacters = buildCustomWorldPlayableCharacters( entry.profile, ).slice(0, 3); const previewLandmarks = entry.profile.landmarks.slice(0, 3); const displayName = formatPlatformWorkDisplayName(entry.worldName); const tags = buildPlatformWorldDisplayTags(entry, 3); const copyPublicWorkCode = () => { if (!publicWorkCode) { return; } void copyTextToClipboard(publicWorkCode).then((copied) => { setCopyState(copied ? 'copied' : 'failed'); window.setTimeout(() => setCopyState('idle'), 1400); }); }; const sharePublicWork = () => { if (!publicWorkCode) { return; } const shareUrl = buildPublicWorkDetailUrl(publicWorkCode); const shareText = `邀请你来玩《${entry.worldName}》\n作品号:${publicWorkCode}\n${shareUrl}`; void copyTextToClipboard(shareText).then((copied) => { setShareState(copied ? 'copied' : 'failed'); window.setTimeout(() => setShareState('idle'), 1400); }); }; return (
{entry.visibility === 'published' ? '已发布' : '草稿'}
{coverImage ? ( ) : null} {leadPortrait ? (
); } export const PlatformWorldDetailView = RpgEntryWorldDetailView;