Merge remote-tracking branch 'origin/master' into codex/pr57-p0-p2
# Conflicts: # docs/【玩法创作】平台入口与玩法链路-2026-05-15.md # docs/【项目基线】当前产品与工程约束-2026-05-15.md
This commit is contained in:
@@ -38,6 +38,7 @@ import {
|
||||
type CSSProperties,
|
||||
type PointerEvent,
|
||||
type ReactNode,
|
||||
Suspense,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
@@ -196,6 +197,7 @@ export interface RpgEntryHomeViewProps {
|
||||
recommendRuntimeContent?: ReactNode;
|
||||
activeRecommendEntryKey?: string | null;
|
||||
isStartingRecommendEntry?: boolean;
|
||||
isRecommendRuntimeReady?: boolean;
|
||||
recommendRuntimeError?: string | null;
|
||||
onSelectNextRecommendEntry?: (activeEntryKey?: string | null) => void;
|
||||
onSelectPreviousRecommendEntry?: (activeEntryKey?: string | null) => void;
|
||||
@@ -952,6 +954,115 @@ function RecommendRuntimePreviewCard({
|
||||
);
|
||||
}
|
||||
|
||||
function RecommendRuntimeCover({
|
||||
entry,
|
||||
className = '',
|
||||
}: {
|
||||
entry: PlatformPublicGalleryCard;
|
||||
className?: string;
|
||||
}) {
|
||||
const coverImage = resolvePlatformWorldCoverImage(entry);
|
||||
const fallbackCoverImage = resolvePlatformWorldFallbackCoverImage(entry);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`platform-recommend-runtime-cover ${className}`}
|
||||
aria-hidden="true"
|
||||
>
|
||||
{coverImage || fallbackCoverImage ? (
|
||||
<PlatformWorkCoverArtwork
|
||||
entry={entry}
|
||||
imageSrc={coverImage}
|
||||
fallbackSrc={fallbackCoverImage}
|
||||
alt=""
|
||||
className="absolute inset-0 h-full w-full object-cover"
|
||||
/>
|
||||
) : (
|
||||
<div className="absolute inset-0 bg-[radial-gradient(circle_at_22%_18%,rgba(255,255,255,0.28),transparent_30%),linear-gradient(135deg,rgba(255,118,117,0.42),rgba(89,164,255,0.34))]" />
|
||||
)}
|
||||
<div className="absolute inset-0 bg-[linear-gradient(180deg,rgba(0,0,0,0.05),rgba(0,0,0,0.34))]" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function RecommendRuntimeMountedProbe({
|
||||
onMounted,
|
||||
}: {
|
||||
onMounted: () => void;
|
||||
}) {
|
||||
useEffect(() => {
|
||||
const animationFrameId = window.requestAnimationFrame(onMounted);
|
||||
return () => window.cancelAnimationFrame(animationFrameId);
|
||||
}, [onMounted]);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function RecommendRuntimeVisual({
|
||||
entry,
|
||||
runtimeContent,
|
||||
isStarting,
|
||||
isRuntimeReady,
|
||||
}: {
|
||||
entry: PlatformPublicGalleryCard;
|
||||
runtimeContent?: ReactNode;
|
||||
isStarting: boolean;
|
||||
isRuntimeReady: boolean;
|
||||
}) {
|
||||
const [isRuntimeMounted, setIsRuntimeMounted] = useState(false);
|
||||
const activeEntryKey = buildPublicGalleryCardKey(entry);
|
||||
const previousEntryKeyRef = useRef(activeEntryKey);
|
||||
|
||||
useEffect(() => {
|
||||
if (previousEntryKeyRef.current === activeEntryKey) {
|
||||
return;
|
||||
}
|
||||
previousEntryKeyRef.current = activeEntryKey;
|
||||
setIsRuntimeMounted((currentValue) => {
|
||||
// 中文注释:拼图推荐流“下一关”会在同一个 run 内切到相似作品;
|
||||
// 此时只更新作品信息和分享基准,不应重显封面造成运行态闪跳。
|
||||
if (currentValue && !isStarting && isRuntimeReady) {
|
||||
return currentValue;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}, [activeEntryKey, isRuntimeReady, isStarting]);
|
||||
|
||||
const handleRuntimeMounted = useCallback(() => {
|
||||
if (!isStarting && isRuntimeReady) {
|
||||
setIsRuntimeMounted(true);
|
||||
}
|
||||
}, [isRuntimeReady, isStarting]);
|
||||
|
||||
const shouldShowCover =
|
||||
!runtimeContent || isStarting || !isRuntimeReady || !isRuntimeMounted;
|
||||
|
||||
return (
|
||||
<div className="platform-recommend-runtime-visual">
|
||||
{runtimeContent ? (
|
||||
<Suspense fallback={null}>
|
||||
<div
|
||||
className="platform-recommend-runtime-viewport"
|
||||
aria-hidden={shouldShowCover}
|
||||
>
|
||||
{runtimeContent}
|
||||
</div>
|
||||
<RecommendRuntimeMountedProbe
|
||||
key={activeEntryKey}
|
||||
onMounted={handleRuntimeMounted}
|
||||
/>
|
||||
</Suspense>
|
||||
) : null}
|
||||
<RecommendRuntimeCover
|
||||
entry={entry}
|
||||
className={
|
||||
shouldShowCover ? '' : 'platform-recommend-runtime-cover--hidden'
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function RecommendSwipeCard({
|
||||
entry,
|
||||
authorAvatarUrl,
|
||||
@@ -4014,6 +4125,7 @@ export function RpgEntryHomeView({
|
||||
recommendRuntimeContent,
|
||||
activeRecommendEntryKey = null,
|
||||
isStartingRecommendEntry = false,
|
||||
isRecommendRuntimeReady = false,
|
||||
recommendRuntimeError = null,
|
||||
onSelectNextRecommendEntry,
|
||||
onSelectPreviousRecommendEntry,
|
||||
@@ -5712,10 +5824,6 @@ export function RpgEntryHomeView({
|
||||
{recommendRuntimeError}
|
||||
</button>
|
||||
</section>
|
||||
) : isStartingRecommendEntry ? (
|
||||
<section className="platform-recommend-runtime-panel">
|
||||
<div className="platform-recommend-runtime-state">加载中...</div>
|
||||
</section>
|
||||
) : activeRecommendEntry ? (
|
||||
<div
|
||||
ref={recommendCardStageRef}
|
||||
@@ -5757,9 +5865,12 @@ export function RpgEntryHomeView({
|
||||
)}
|
||||
isActive
|
||||
visual={
|
||||
<div className="platform-recommend-runtime-viewport">
|
||||
{recommendRuntimeContent}
|
||||
</div>
|
||||
<RecommendRuntimeVisual
|
||||
entry={activeRecommendEntry}
|
||||
runtimeContent={recommendRuntimeContent}
|
||||
isStarting={isStartingRecommendEntry}
|
||||
isRuntimeReady={isRecommendRuntimeReady}
|
||||
/>
|
||||
}
|
||||
onDragPointerDown={beginRecommendDrag}
|
||||
onDragPointerMove={moveRecommendDrag}
|
||||
|
||||
Reference in New Issue
Block a user