merge master into codex/wechat-mini-program-virtual-payment
This commit is contained in:
@@ -150,6 +150,7 @@ import {
|
||||
isWoodenFishGalleryEntry,
|
||||
type PlatformPublicGalleryCard,
|
||||
type PlatformWorldCardLike,
|
||||
resolvePlatformWorkAuthorDisplayName,
|
||||
resolvePlatformPublicWorkCode,
|
||||
resolvePlatformWorldCoverImage,
|
||||
resolvePlatformWorldCoverSlides,
|
||||
@@ -247,7 +248,6 @@ const AVATAR_MAX_FILE_SIZE = 5 * 1024 * 1024;
|
||||
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_REDEEM_ENTRY_VISIBLE_MS = 24 * 60 * 60 * 1000;
|
||||
const PROFILE_INVITE_QUERY_KEYS = ['inviteCode', 'invite_code'] as const;
|
||||
const RECOMMEND_ENTRY_SWIPE_THRESHOLD_PX = 36;
|
||||
const RECOMMEND_ENTRY_COMMIT_ANIMATION_MS = 180;
|
||||
@@ -615,6 +615,7 @@ function WorldCard({
|
||||
onClick,
|
||||
className,
|
||||
authorAvatarUrl,
|
||||
authorSummary,
|
||||
feedCardKey,
|
||||
enableCoverCarousel = false,
|
||||
isCoverCarouselActive = false,
|
||||
@@ -624,6 +625,7 @@ function WorldCard({
|
||||
onClick: () => void;
|
||||
className?: string;
|
||||
authorAvatarUrl?: string | null;
|
||||
authorSummary?: PublicUserSummary | null;
|
||||
feedCardKey?: string;
|
||||
enableCoverCarousel?: boolean;
|
||||
isCoverCarouselActive?: boolean;
|
||||
@@ -657,7 +659,10 @@ function WorldCard({
|
||||
const remixCount = getPlatformWorldRemixCount(entry);
|
||||
const likeCount = getPlatformWorldLikeCount(entry);
|
||||
const typeLabel = describePublicGalleryCardKind(entry);
|
||||
const authorName = entry.authorDisplayName.trim() || '玩家';
|
||||
const authorName = resolvePlatformWorkAuthorDisplayName(
|
||||
entry,
|
||||
authorSummary,
|
||||
);
|
||||
const authorAvatarLabel = getPublicAuthorAvatarLabel(authorName);
|
||||
const normalizedAuthorAvatarUrl = authorAvatarUrl?.trim() ?? '';
|
||||
const cardLabel = `${entry.worldName},${typeLabel},${formatCompactCount(playCount)}游玩,${formatCompactCount(remixCount)}改造,${formatCompactCount(likeCount)}点赞`;
|
||||
@@ -939,6 +944,7 @@ function RecommendRuntimePreviewCard({
|
||||
function RecommendSwipeCard({
|
||||
entry,
|
||||
authorAvatarUrl,
|
||||
authorSummary,
|
||||
isActive,
|
||||
visual,
|
||||
shareState,
|
||||
@@ -952,6 +958,7 @@ function RecommendSwipeCard({
|
||||
}: {
|
||||
entry: PlatformPublicGalleryCard;
|
||||
authorAvatarUrl?: string | null;
|
||||
authorSummary?: PublicUserSummary | null;
|
||||
isActive: boolean;
|
||||
visual: ReactNode;
|
||||
shareState?: 'idle' | 'copied' | 'failed';
|
||||
@@ -976,6 +983,7 @@ function RecommendSwipeCard({
|
||||
<RecommendRuntimeMeta
|
||||
entry={entry}
|
||||
authorAvatarUrl={authorAvatarUrl}
|
||||
authorSummary={authorSummary}
|
||||
isActive={isActive}
|
||||
shareState={shareState}
|
||||
onDragPointerDown={onDragPointerDown}
|
||||
@@ -994,6 +1002,7 @@ function RecommendSwipeCard({
|
||||
function RecommendRuntimeMeta({
|
||||
entry,
|
||||
authorAvatarUrl,
|
||||
authorSummary,
|
||||
onDragPointerDown,
|
||||
onDragPointerMove,
|
||||
onDragPointerUp,
|
||||
@@ -1006,6 +1015,7 @@ function RecommendRuntimeMeta({
|
||||
}: {
|
||||
entry: PlatformPublicGalleryCard;
|
||||
authorAvatarUrl?: string | null;
|
||||
authorSummary?: PublicUserSummary | null;
|
||||
onDragPointerDown?: (event: PointerEvent<HTMLElement>) => void;
|
||||
onDragPointerMove?: (event: PointerEvent<HTMLElement>) => void;
|
||||
onDragPointerUp?: (event: PointerEvent<HTMLElement>) => void;
|
||||
@@ -1018,7 +1028,10 @@ function RecommendRuntimeMeta({
|
||||
}) {
|
||||
const likeCount = getPlatformWorldLikeCount(entry);
|
||||
const remixCount = getPlatformWorldRemixCount(entry);
|
||||
const authorName = entry.authorDisplayName.trim() || '玩家';
|
||||
const authorName = resolvePlatformWorkAuthorDisplayName(
|
||||
entry,
|
||||
authorSummary,
|
||||
);
|
||||
const authorAvatarLabel = getPublicAuthorAvatarLabel(authorName);
|
||||
const normalizedAuthorAvatarUrl = authorAvatarUrl?.trim() ?? '';
|
||||
const displayName = formatPlatformWorkDisplayName(entry.worldName);
|
||||
@@ -1894,28 +1907,28 @@ async function getPublicWorkAuthorSummary(
|
||||
|
||||
function describePublicGalleryCardKind(entry: PlatformPublicGalleryCard) {
|
||||
if (isBigFishGalleryEntry(entry)) {
|
||||
return formatPlatformWorkDisplayTag('??');
|
||||
return formatPlatformWorkDisplayTag('大鱼吃小鱼');
|
||||
}
|
||||
if (isPuzzleGalleryEntry(entry)) {
|
||||
return formatPlatformWorkDisplayTag('??');
|
||||
return formatPlatformWorkDisplayTag('拼图');
|
||||
}
|
||||
if (isMatch3DGalleryEntry(entry)) {
|
||||
return formatPlatformWorkDisplayTag('??');
|
||||
return formatPlatformWorkDisplayTag('抓大鹅');
|
||||
}
|
||||
if (isSquareHoleGalleryEntry(entry)) {
|
||||
return formatPlatformWorkDisplayTag('??');
|
||||
return formatPlatformWorkDisplayTag('方洞挑战');
|
||||
}
|
||||
if (isJumpHopGalleryEntry(entry)) {
|
||||
return formatPlatformWorkDisplayTag('???');
|
||||
return formatPlatformWorkDisplayTag('跳一跳');
|
||||
}
|
||||
if (isWoodenFishGalleryEntry(entry)) {
|
||||
return formatPlatformWorkDisplayTag('???');
|
||||
return formatPlatformWorkDisplayTag('敲木鱼');
|
||||
}
|
||||
if (isVisualNovelGalleryEntry(entry)) {
|
||||
return formatPlatformWorkDisplayTag('??');
|
||||
return formatPlatformWorkDisplayTag('视觉小说');
|
||||
}
|
||||
if (isBarkBattleGalleryEntry(entry)) {
|
||||
return formatPlatformWorkDisplayTag('??');
|
||||
return formatPlatformWorkDisplayTag('汪汪声浪');
|
||||
}
|
||||
if (isEdutainmentGalleryEntry(entry)) {
|
||||
return formatPlatformWorkDisplayTag(entry.templateName);
|
||||
@@ -2214,21 +2227,6 @@ function formatDashboardCount(value: number) {
|
||||
return normalizedValue.toLocaleString('zh-CN');
|
||||
}
|
||||
|
||||
function isWithinProfileInviteRedeemWindow(
|
||||
createdAt: string | null | undefined,
|
||||
) {
|
||||
if (!createdAt) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const createdTime = new Date(createdAt).getTime();
|
||||
if (Number.isNaN(createdTime)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Date.now() - createdTime <= PROFILE_INVITE_REDEEM_ENTRY_VISIBLE_MS;
|
||||
}
|
||||
|
||||
function normalizeProfileInviteQueryCode(value: string | null | undefined) {
|
||||
return (value ?? '')
|
||||
.trim()
|
||||
@@ -2273,16 +2271,13 @@ function buildPublicUserCode(user: AuthUser | null | undefined) {
|
||||
return user.publicUserCode.trim();
|
||||
}
|
||||
|
||||
const raw =
|
||||
user?.id.replace(/[^a-zA-Z0-9]/gu, '').toUpperCase() ||
|
||||
user?.username.replace(/[^a-zA-Z0-9]/gu, '').toUpperCase() ||
|
||||
'00000000';
|
||||
const raw = user?.id.replace(/[^a-zA-Z0-9]/gu, '').toUpperCase() || '00000000';
|
||||
|
||||
return `SY-${raw.slice(-8).padStart(8, '0')}`;
|
||||
}
|
||||
|
||||
function getUserAvatarLabel(user: AuthUser | null | undefined) {
|
||||
return (user?.displayName || user?.username || '叙')
|
||||
return (user?.displayName || '叙')
|
||||
.slice(0, 1)
|
||||
.toUpperCase();
|
||||
}
|
||||
@@ -4198,6 +4193,17 @@ export function RpgEntryHomeView({
|
||||
},
|
||||
[publicAuthorSummariesByKey],
|
||||
);
|
||||
const getPublicEntryAuthorSummary = useCallback(
|
||||
(entry: PlatformPublicGalleryCard) => {
|
||||
const authorLookupKey = buildPublicWorkAuthorLookupKey(entry);
|
||||
if (!authorLookupKey) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return publicAuthorSummariesByKey[authorLookupKey] ?? null;
|
||||
},
|
||||
[publicAuthorSummariesByKey],
|
||||
);
|
||||
const activeCategoryGroup =
|
||||
categoryGroups.find((group) => group.tag === selectedCategoryTag) ??
|
||||
categoryGroups[0] ??
|
||||
@@ -4930,18 +4936,14 @@ export function RpgEntryHomeView({
|
||||
});
|
||||
}, []);
|
||||
useEffect(() => {
|
||||
if (
|
||||
activeTab !== 'profile' ||
|
||||
!isAuthenticated ||
|
||||
!isWithinProfileInviteRedeemWindow(authUi?.user?.createdAt)
|
||||
) {
|
||||
if (activeTab !== 'profile' || !isAuthenticated) {
|
||||
setIsReferralCenterInitialized(false);
|
||||
setReferralCenter(null);
|
||||
return;
|
||||
}
|
||||
|
||||
loadReferralCenter();
|
||||
}, [activeTab, authUi?.user?.createdAt, isAuthenticated, loadReferralCenter]);
|
||||
}, [activeTab, isAuthenticated, loadReferralCenter]);
|
||||
const openProfilePopupPanel = (panel: ProfileReferralPanel) => {
|
||||
setProfilePopupPanel(panel);
|
||||
setReferralError(null);
|
||||
@@ -5589,6 +5591,9 @@ export function RpgEntryHomeView({
|
||||
authorAvatarUrl={getPublicEntryAuthorAvatarUrl(
|
||||
previousRecommendEntry,
|
||||
)}
|
||||
authorSummary={getPublicEntryAuthorSummary(
|
||||
previousRecommendEntry,
|
||||
)}
|
||||
isActive={false}
|
||||
visual={
|
||||
<RecommendRuntimePreviewCard
|
||||
@@ -5606,6 +5611,9 @@ export function RpgEntryHomeView({
|
||||
authorAvatarUrl={getPublicEntryAuthorAvatarUrl(
|
||||
activeRecommendEntry,
|
||||
)}
|
||||
authorSummary={getPublicEntryAuthorSummary(
|
||||
activeRecommendEntry,
|
||||
)}
|
||||
isActive
|
||||
visual={
|
||||
<div className="platform-recommend-runtime-viewport">
|
||||
@@ -5630,6 +5638,9 @@ export function RpgEntryHomeView({
|
||||
authorAvatarUrl={getPublicEntryAuthorAvatarUrl(
|
||||
nextRecommendEntry,
|
||||
)}
|
||||
authorSummary={getPublicEntryAuthorSummary(
|
||||
nextRecommendEntry,
|
||||
)}
|
||||
isActive={false}
|
||||
visual={
|
||||
<RecommendRuntimePreviewCard
|
||||
@@ -5783,6 +5794,7 @@ export function RpgEntryHomeView({
|
||||
onClick={() => onOpenGalleryDetail(entry)}
|
||||
className="w-full"
|
||||
authorAvatarUrl={getPublicEntryAuthorAvatarUrl(entry)}
|
||||
authorSummary={getPublicEntryAuthorSummary(entry)}
|
||||
feedCardKey={cardKey}
|
||||
/>
|
||||
);
|
||||
@@ -5844,13 +5856,14 @@ export function RpgEntryHomeView({
|
||||
return (
|
||||
<WorldCard
|
||||
key={`${cardKey}:mobile-feed:${discoverChannel}`}
|
||||
entry={entry}
|
||||
onClick={() => onOpenGalleryDetail(entry)}
|
||||
className="w-full"
|
||||
authorAvatarUrl={getPublicEntryAuthorAvatarUrl(entry)}
|
||||
feedCardKey={cardKey}
|
||||
enableCoverCarousel={mobileFeedCarouselEnabled}
|
||||
isCoverCarouselActive={
|
||||
entry={entry}
|
||||
onClick={() => onOpenGalleryDetail(entry)}
|
||||
className="w-full"
|
||||
authorAvatarUrl={getPublicEntryAuthorAvatarUrl(entry)}
|
||||
authorSummary={getPublicEntryAuthorSummary(entry)}
|
||||
feedCardKey={cardKey}
|
||||
enableCoverCarousel={mobileFeedCarouselEnabled}
|
||||
isCoverCarouselActive={
|
||||
mobileCenteredCardKey === cardKey
|
||||
}
|
||||
/>
|
||||
@@ -5954,6 +5967,7 @@ export function RpgEntryHomeView({
|
||||
onClick={() => openRecommendGalleryDetail(entry)}
|
||||
className="w-full min-w-0"
|
||||
authorAvatarUrl={getPublicEntryAuthorAvatarUrl(entry)}
|
||||
authorSummary={getPublicEntryAuthorSummary(entry)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
@@ -5981,6 +5995,7 @@ export function RpgEntryHomeView({
|
||||
onClick={() => openRecommendGalleryDetail(entry)}
|
||||
className="w-full min-w-0"
|
||||
authorAvatarUrl={getPublicEntryAuthorAvatarUrl(entry)}
|
||||
authorSummary={getPublicEntryAuthorSummary(entry)}
|
||||
/>
|
||||
))}
|
||||
{onOpenChildMotionDemo ? (
|
||||
@@ -6041,6 +6056,7 @@ export function RpgEntryHomeView({
|
||||
onClick={() => openRecommendGalleryDetail(entry)}
|
||||
className="w-full min-w-0"
|
||||
authorAvatarUrl={getPublicEntryAuthorAvatarUrl(entry)}
|
||||
authorSummary={getPublicEntryAuthorSummary(entry)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
@@ -6556,6 +6572,7 @@ export function RpgEntryHomeView({
|
||||
onClick={() => openRecommendGalleryDetail(entry)}
|
||||
className="w-full min-w-0"
|
||||
authorAvatarUrl={getPublicEntryAuthorAvatarUrl(entry)}
|
||||
authorSummary={getPublicEntryAuthorSummary(entry)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
@@ -6726,6 +6743,7 @@ export function RpgEntryHomeView({
|
||||
onClick={() => openRecommendGalleryDetail(entry)}
|
||||
className="w-full min-w-0"
|
||||
authorAvatarUrl={getPublicEntryAuthorAvatarUrl(entry)}
|
||||
authorSummary={getPublicEntryAuthorSummary(entry)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user