refactor: 收口推荐滑动卡模型

This commit is contained in:
2026-06-03 21:11:13 +08:00
parent 30ead590e2
commit c238ef9b40
6 changed files with 248 additions and 24 deletions

View File

@@ -189,6 +189,17 @@ import {
selectPlatformRecommendFeedWindow,
sortPlatformCategoryEntries,
} from './rpgEntryPublicGalleryViewModel';
import {
buildRecommendShareText,
buildRecommendSwipeRailClassName,
clampRecommendDragOffset,
hasRecommendDragStarted,
RECOMMEND_ENTRY_COMMIT_ANIMATION_MS,
type RecommendSwipeDirection,
resolveRecommendCommitOffset,
resolveRecommendDragCommitDirection,
shouldAnimateRecommendSwipe,
} from './rpgEntryRecommendSwipeDeckModel';
import {
buildPlatformWorldDisplayTags,
describePlatformPublicWorkKind,
@@ -305,9 +316,6 @@ const AVATAR_OUTPUT_SIZE = 256;
const AVATAR_ALLOWED_TYPES = new Set(['image/jpeg', 'image/png', 'image/webp']);
const PLATFORM_WORK_COVER_CAROUSEL_INTERVAL_MS = 4200;
const PROFILE_INVITE_QUERY_KEYS = ['inviteCode', 'invite_code'] as const;
const RECOMMEND_ENTRY_SWIPE_THRESHOLD_PX = 36;
const RECOMMEND_ENTRY_COMMIT_ANIMATION_MS = 180;
const RECOMMEND_ENTRY_DRAG_LIMIT_PX = 160;
const WECHAT_JS_SDK_URL = 'https://res.wx.qq.com/open/js/jweixin-1.6.0.js';
const WECHAT_PAY_CONFIRM_RETRY_DELAYS_MS = [800, 1600, 3000] as const;
const WECHAT_NATIVE_PAY_QR_IMAGE_SIZE = 180;
@@ -4746,7 +4754,7 @@ export function RpgEntryHomeView({
const nextRecommendEntry = recommendFeedWindow.nextEntry;
const [recommendDragOffsetY, setRecommendDragOffsetY] = useState(0);
const [recommendDragCommitDirection, setRecommendDragCommitDirection] =
useState<1 | -1 | null>(null);
useState<RecommendSwipeDirection | null>(null);
const [recommendShareState, setRecommendShareState] = useState<
'idle' | 'copied' | 'failed'
>('idle');
@@ -4759,7 +4767,7 @@ export function RpgEntryHomeView({
dragging: boolean;
} | null>(null);
const commitRecommendDrag = useCallback(
(direction: 1 | -1) => {
(direction: RecommendSwipeDirection) => {
if (recommendDragCommitDirection) {
return;
}
@@ -4767,9 +4775,8 @@ export function RpgEntryHomeView({
setRecommendDragCommitDirection(direction);
const panelHeight =
recommendCardStageRef.current?.getBoundingClientRect().height ?? 0;
const commitDistance = panelHeight > 0 ? panelHeight : window.innerHeight;
setRecommendDragOffsetY(
direction === 1 ? -commitDistance : commitDistance,
resolveRecommendCommitOffset(direction, panelHeight, window.innerHeight),
);
window.setTimeout(() => {
if (direction === 1) {
@@ -4818,9 +4825,7 @@ export function RpgEntryHomeView({
}
const deltaY = event.clientY - drag.startY;
drag.dragging =
drag.dragging ||
Math.abs(deltaY) >= RECOMMEND_ENTRY_SWIPE_THRESHOLD_PX / 2;
drag.dragging = drag.dragging || hasRecommendDragStarted(deltaY);
if (!drag.dragging) {
return;
}
@@ -4828,9 +4833,7 @@ export function RpgEntryHomeView({
event.preventDefault();
const cardHeight =
recommendCardStageRef.current?.getBoundingClientRect().height ?? 0;
const dragLimit =
cardHeight > 0 ? cardHeight : RECOMMEND_ENTRY_DRAG_LIMIT_PX;
setRecommendDragOffsetY(Math.max(-dragLimit, Math.min(dragLimit, deltaY)));
setRecommendDragOffsetY(clampRecommendDragOffset(deltaY, cardHeight));
}, []);
const endRecommendDrag = useCallback(
(event: PointerEvent<HTMLElement>) => {
@@ -4842,12 +4845,13 @@ export function RpgEntryHomeView({
event.currentTarget.releasePointerCapture?.(drag.pointerId);
recommendDragStartRef.current = null;
const deltaY = event.clientY - drag.startY;
if (Math.abs(deltaY) < RECOMMEND_ENTRY_SWIPE_THRESHOLD_PX) {
const commitDirection = resolveRecommendDragCommitDirection(deltaY);
if (!commitDirection) {
setRecommendDragOffsetY(0);
return;
}
commitRecommendDrag(deltaY < 0 ? 1 : -1);
commitRecommendDrag(commitDirection);
},
[commitRecommendDrag],
);
@@ -4865,16 +4869,17 @@ export function RpgEntryHomeView({
const recommendRailStyle = {
transform: `translate3d(0, ${recommendDragOffsetY}px, 0)`,
} satisfies CSSProperties;
const recommendRailClassName = recommendDragCommitDirection
? 'platform-recommend-swipe-rail--committing'
: recommendDragOffsetY === 0
? 'platform-recommend-swipe-rail--settled'
: 'platform-recommend-swipe-rail--dragging';
const recommendRailClassName = buildRecommendSwipeRailClassName({
offsetY: recommendDragOffsetY,
commitDirection: recommendDragCommitDirection,
});
const selectNextRecommendEntry = useCallback(() => {
if (
isAuthenticated &&
activeRecommendEntry &&
recommendedFeedEntries.length > 1
shouldAnimateRecommendSwipe({
isAuthenticated,
hasActiveEntry: Boolean(activeRecommendEntry),
entryCount: recommendedFeedEntries.length,
})
) {
commitRecommendDrag(1);
return;
@@ -4908,7 +4913,11 @@ export function RpgEntryHomeView({
return;
}
const shareText = `邀请你来玩《${entry.worldName}\n作品号${publicWorkCode}\n${buildPublicWorkDetailUrl(publicWorkCode)}`;
const shareText = buildRecommendShareText({
entry,
publicWorkCode,
detailUrl: buildPublicWorkDetailUrl(publicWorkCode),
});
void copyTextToClipboard(shareText).then((copied) => {
setRecommendShareState(copied ? 'copied' : 'failed');
if (recommendShareResetTimerRef.current !== null) {