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

This commit is contained in:
kdletters
2026-05-26 16:45:57 +08:00
47 changed files with 2678 additions and 79 deletions

View File

@@ -705,7 +705,10 @@ function isRecommendRuntimeReadyForEntry(
return Boolean(state.match3dRun);
}
if (expectedKind === 'puzzle') {
return Boolean(state.puzzleRun);
return (
state.puzzleRun?.entryProfileId === entry.profileId ||
state.puzzleRun?.currentLevel?.profileId === entry.profileId
);
}
if (expectedKind === 'square-hole') {
return Boolean(state.squareHoleRun);
@@ -3149,6 +3152,7 @@ export function PlatformEntryFlowShellImpl({
useState<PuzzleRuntimeAuthMode>('default');
const [isPuzzleLeaderboardBusy, setIsPuzzleLeaderboardBusy] = useState(false);
const submittedPuzzleLeaderboardKeysRef = useRef(new Set<string>());
const puzzleStartInFlightKeyRef = useRef<string | null>(null);
const [puzzleRun, setPuzzleRun] = useState<PuzzleRunSnapshot | null>(null);
const puzzleRunRef = useRef<PuzzleRunSnapshot | null>(null);
const errorSetterRefNoop = useMemo(
@@ -9105,10 +9109,13 @@ export function PlatformEntryFlowShellImpl({
levelId?: string | null,
options: { embedded?: boolean; authMode?: PuzzleRuntimeAuthMode } = {},
) => {
if (isPuzzleBusy) {
const normalizedLevelId = levelId?.trim() ?? '';
const startKey = `${profileId}:${normalizedLevelId}`;
if (isPuzzleBusy || puzzleStartInFlightKeyRef.current === startKey) {
return false;
}
puzzleStartInFlightKeyRef.current = startKey;
setIsPuzzleBusy(true);
setPuzzleError(null);
@@ -9117,7 +9124,7 @@ export function PlatformEntryFlowShellImpl({
detailItem ?? (await getPuzzleGalleryDetail(profileId)).item;
const startRunPayload = {
profileId: item.profileId,
levelId: levelId ?? null,
levelId: normalizedLevelId || null,
};
const canUseRuntimeGuestAuth =
options.embedded || options.authMode === 'isolated';
@@ -9171,6 +9178,9 @@ export function PlatformEntryFlowShellImpl({
}
return false;
} finally {
if (puzzleStartInFlightKeyRef.current === startKey) {
puzzleStartInFlightKeyRef.current = null;
}
setIsPuzzleBusy(false);
}
},
@@ -9949,7 +9959,13 @@ export function PlatformEntryFlowShellImpl({
return;
}
const submitKey = `${puzzleRun.runId}:${currentLevel.profileId}:${currentLevel.gridSize}:${currentLevel.elapsedMs}`;
const submitKey = [
puzzleRun.runId,
currentLevel.profileId,
currentLevel.levelId ?? currentLevel.levelIndex,
currentLevel.gridSize,
currentLevel.elapsedMs,
].join(':');
if (submittedPuzzleLeaderboardKeysRef.current.has(submitKey)) {
return;
}
@@ -9987,7 +10003,6 @@ export function PlatformEntryFlowShellImpl({
void platformBootstrap.refreshSaveArchives();
})
.catch((error) => {
submittedPuzzleLeaderboardKeysRef.current.delete(submitKey);
setPuzzleError(
resolvePuzzleErrorMessage(error, '提交拼图排行榜失败。'),
);
@@ -10034,6 +10049,10 @@ export function PlatformEntryFlowShellImpl({
? await buildRecommendRuntimeGuestOptions()
: {};
const targetProfileId = _target?.profileId?.trim() ?? '';
const preferSimilarWork =
activeRecommendRuntimeKind === 'puzzle' &&
puzzleRuntimeReturnStage === 'platform' &&
puzzleRun.nextLevelMode === 'sameWork';
if (puzzleRun.nextLevelMode === 'similarWorks' && targetProfileId) {
const itemPromise =
selectedPuzzleDetail?.profileId === targetProfileId
@@ -10073,10 +10092,35 @@ export function PlatformEntryFlowShellImpl({
puzzleRuntimeAuthMode === 'isolated'
? await advancePuzzleNextLevel(
puzzleRun.runId,
{},
preferSimilarWork ? { preferSimilarWork: true } : {},
runtimeGuestOptions,
)
: await advancePuzzleNextLevel(puzzleRun.runId);
: await advancePuzzleNextLevel(
puzzleRun.runId,
preferSimilarWork ? { preferSimilarWork: true } : {},
);
const nextProfileId = run.currentLevel?.profileId?.trim() ?? '';
if (
nextProfileId &&
selectedPuzzleDetail?.profileId !== nextProfileId
) {
const item = await getPuzzleGalleryDetail(nextProfileId).then(
(response) => response.item,
);
const nextRecommendEntry =
mapPuzzleWorkToPlatformGalleryCard(item);
setPuzzleGalleryEntries((current) => {
const nextEntries = current.filter(
(entry) => entry.profileId !== item.profileId,
);
nextEntries.push(item);
return nextEntries;
});
setSelectedPuzzleDetail(item);
setActiveRecommendEntryKey(
getPlatformPublicGalleryEntryKey(nextRecommendEntry),
);
}
setPuzzleRun(run);
} catch (error) {
setPuzzleError(resolvePuzzleErrorMessage(error, '准备下一关失败。'));
@@ -10088,8 +10132,12 @@ export function PlatformEntryFlowShellImpl({
[
isPuzzleBusy,
isPuzzleLeaderboardBusy,
activeRecommendRuntimeKind,
puzzleRun,
puzzleRuntimeReturnStage,
puzzleRuntimeAuthMode,
setActiveRecommendEntryKey,
setPuzzleGalleryEntries,
resolvePuzzleErrorMessage,
selectedPuzzleDetail,
setIsPuzzleBusy,
@@ -12489,6 +12537,10 @@ export function PlatformEntryFlowShellImpl({
recommendRuntimeStartRequestRef.current = startRequestId;
const isCurrentStartRequest = () =>
recommendRuntimeStartRequestRef.current === startRequestId;
setActiveRecommendEntryKey(entryKey);
setActiveRecommendRuntimeKind(runtimeKind);
setActiveRecommendRuntimeError(null);
setIsStartingRecommendEntry(true);
if (entryKey !== activeRecommendEntryKey) {
await saveAndExitRecommendPuzzleRuntime();
if (!isCurrentStartRequest()) {
@@ -12641,14 +12693,16 @@ export function PlatformEntryFlowShellImpl({
],
);
const selectAdjacentRecommendRuntimeEntry = useCallback(
(direction: 1 | -1) => {
(direction: 1 | -1, baseEntryKey?: string | null) => {
if (recommendRuntimeEntries.length === 0) {
return;
}
const normalizedBaseEntryKey =
baseEntryKey?.trim() || activeRecommendEntryKey;
const activeIndex = recommendRuntimeEntries.findIndex(
(entry) =>
getPlatformPublicGalleryEntryKey(entry) === activeRecommendEntryKey,
getPlatformPublicGalleryEntryKey(entry) === normalizedBaseEntryKey,
);
const baseIndex = activeIndex >= 0 ? activeIndex : 0;
const nextIndex =
@@ -12659,7 +12713,7 @@ export function PlatformEntryFlowShellImpl({
return;
}
if (
getPlatformPublicGalleryEntryKey(nextEntry) === activeRecommendEntryKey
getPlatformPublicGalleryEntryKey(nextEntry) === normalizedBaseEntryKey
) {
return;
}
@@ -14437,18 +14491,19 @@ export function PlatformEntryFlowShellImpl({
isStartingRecommendEntry={
isStartingRecommendEntry ||
isBigFishBusy ||
isPuzzleBusy ||
(isPuzzleBusy &&
!(activeRecommendRuntimeKind === 'puzzle' && puzzleRun)) ||
isMatch3DBusy ||
isSquareHoleBusy ||
isVisualNovelBusy ||
isWoodenFishBusy
}
recommendRuntimeError={activeRecommendRuntimeError}
onSelectNextRecommendEntry={() =>
selectAdjacentRecommendRuntimeEntry(1)
onSelectNextRecommendEntry={(activeEntryKey) =>
selectAdjacentRecommendRuntimeEntry(1, activeEntryKey)
}
onSelectPreviousRecommendEntry={() =>
selectAdjacentRecommendRuntimeEntry(-1)
onSelectPreviousRecommendEntry={(activeEntryKey) =>
selectAdjacentRecommendRuntimeEntry(-1, activeEntryKey)
}
onLikeRecommendEntry={(entry) => {
likePublicWork(entry);