Merge remote-tracking branch 'origin/master' into codex/fix-draft-result-back-target

# Conflicts:
#	src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx
This commit is contained in:
kdletters
2026-05-26 16:43:30 +08:00
123 changed files with 1963 additions and 324 deletions
File diff suppressed because it is too large Load Diff
+33 -5
View File
@@ -78,6 +78,7 @@ import type {
WechatMiniProgramPayParams,
WechatNativePayment,
} from '../../../packages/shared/src/contracts/runtime';
import { isMatch3DDemoProfileId } from '../../data/match3dDemoGalleryCard';
import type { HydratedSavedGameSnapshot } from '../../persistence/runtimeSnapshotTypes';
import { buildPublicWorkDetailUrl } from '../../routing/appPageRoutes';
import type { AuthUser } from '../../services/authService';
@@ -4064,6 +4065,7 @@ export function RpgEntryHomeView({
const [mobileCenteredCardKey, setMobileCenteredCardKey] = useState<
string | null
>(null);
const hasManualCategoryTagSelectionRef = useRef(false);
const pendingPublicAuthorKeysRef = useRef<Set<string>>(new Set());
const [publicAuthorSummariesByKey, setPublicAuthorSummariesByKey] = useState<
Record<string, PublicUserSummary | null>
@@ -4288,16 +4290,33 @@ export function RpgEntryHomeView({
useEffect(() => {
if (categoryGroups.length === 0) {
setSelectedCategoryTag(null);
hasManualCategoryTagSelectionRef.current = false;
return;
}
const firstCategoryGroup = categoryGroups[0];
const firstCategoryGroup =
categoryGroups.find((group) =>
group.entries.some((entry) => !isMatch3DDemoProfileId(entry.profileId)),
) ?? categoryGroups[0];
const selectedCategoryGroup =
categoryGroups.find((group) => group.tag === selectedCategoryTag) ?? null;
if (
firstCategoryGroup &&
!categoryGroups.some((group) => group.tag === selectedCategoryTag)
(!selectedCategoryGroup ||
(!hasManualCategoryTagSelectionRef.current &&
selectedCategoryGroup.entries.every((entry) =>
isMatch3DDemoProfileId(entry.profileId),
) &&
firstCategoryGroup.tag !== selectedCategoryGroup.tag))
) {
setSelectedCategoryTag(firstCategoryGroup.tag);
}
if (
selectedCategoryTag &&
!categoryGroups.some((group) => group.tag === selectedCategoryTag)
) {
hasManualCategoryTagSelectionRef.current = false;
}
}, [categoryGroups, selectedCategoryTag]);
useEffect(() => {
@@ -5612,7 +5631,10 @@ export function RpgEntryHomeView({
<button
key={group.tag}
type="button"
onClick={() => setSelectedCategoryTag(group.tag)}
onClick={() => {
hasManualCategoryTagSelectionRef.current = true;
setSelectedCategoryTag(group.tag);
}}
className={`platform-category-chip ${active ? 'platform-category-chip--active' : ''}`}
>
{group.tag}
@@ -5810,7 +5832,10 @@ export function RpgEntryHomeView({
<button
key={`${group.tag}:desktop-discover-category`}
type="button"
onClick={() => setSelectedCategoryTag(group.tag)}
onClick={() => {
hasManualCategoryTagSelectionRef.current = true;
setSelectedCategoryTag(group.tag);
}}
className={`platform-category-chip shrink-0 ${active ? 'platform-category-chip--active' : ''}`}
>
{group.tag}
@@ -6590,7 +6615,10 @@ export function RpgEntryHomeView({
<button
key={`${group.tag}:desktop-category`}
type="button"
onClick={() => setSelectedCategoryTag(group.tag)}
onClick={() => {
hasManualCategoryTagSelectionRef.current = true;
setSelectedCategoryTag(group.tag);
}}
className={`platform-category-chip shrink-0 ${active ? 'platform-category-chip--active' : ''}`}
>
{group.tag}
@@ -10,6 +10,7 @@ import {
formatPlatformWorldTime,
isBarkBattleGalleryEntry,
isEdutainmentGalleryEntry,
isMatch3DGalleryEntry,
isVisualNovelGalleryEntry,
isWoodenFishGalleryEntry,
mapBabyObjectMatchDraftToPlatformGalleryCard,
@@ -21,6 +22,7 @@ import {
resolvePlatformPublicWorkCode,
resolvePlatformWorldFallbackCoverImage,
} from './rpgEntryWorldPresentation';
import { buildMatch3DDemoGalleryCard } from '../../data/match3dDemoGalleryCard';
test('formatPlatformWorldTime formats backend seconds timestamp text as date', () => {
expect(formatPlatformWorldTime('1777110165.990127Z')).toBe('2026-04-25');
@@ -78,6 +80,24 @@ test('platform public cards use play type reference images as cover fallback', (
);
});
test('builds local Match3D demo gallery card with generated runtime assets intact', () => {
const card = buildMatch3DDemoGalleryCard();
expect(isMatch3DGalleryEntry(card)).toBe(true);
expect(card.publicWorkCode).toBe('M3-20260525');
expect(resolvePlatformPublicWorkCode(card)).toBe('M3-20260525');
expect(card.coverImageSrc).toBe(
'/match3d-demo/undersea-candy-market/level-scene.png',
);
expect(card.generatedBackgroundAsset?.uiSpritesheetImageSrc).toBe(
'/match3d-demo/undersea-candy-market/ui-spritesheet.png',
);
expect(card.generatedBackgroundAsset?.containerImageSrc).toBeNull();
expect(card.generatedItemAssets?.[0]?.imageViews?.[0]?.imageSrc).toBe(
'/match3d-demo/undersea-candy-market/item-slices/item-01/view-01.png',
);
});
test('buildPuzzleWorkCoverSlides prefers each level formal image', () => {
const slides = buildPuzzleWorkCoverSlides({
workId: 'work-1',