Add public work read model and smooth puzzle transitions
This commit is contained in:
@@ -695,7 +695,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);
|
||||
@@ -3139,6 +3142,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(
|
||||
@@ -9019,10 +9023,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);
|
||||
|
||||
@@ -9031,7 +9038,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';
|
||||
@@ -9086,6 +9093,9 @@ export function PlatformEntryFlowShellImpl({
|
||||
}
|
||||
return false;
|
||||
} finally {
|
||||
if (puzzleStartInFlightKeyRef.current === startKey) {
|
||||
puzzleStartInFlightKeyRef.current = null;
|
||||
}
|
||||
setIsPuzzleBusy(false);
|
||||
}
|
||||
},
|
||||
@@ -9857,7 +9867,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;
|
||||
}
|
||||
@@ -9895,7 +9911,6 @@ export function PlatformEntryFlowShellImpl({
|
||||
void platformBootstrap.refreshSaveArchives();
|
||||
})
|
||||
.catch((error) => {
|
||||
submittedPuzzleLeaderboardKeysRef.current.delete(submitKey);
|
||||
setPuzzleError(
|
||||
resolvePuzzleErrorMessage(error, '提交拼图排行榜失败。'),
|
||||
);
|
||||
@@ -9942,6 +9957,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
|
||||
@@ -9981,10 +10000,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, '准备下一关失败。'));
|
||||
@@ -9996,8 +10040,12 @@ export function PlatformEntryFlowShellImpl({
|
||||
[
|
||||
isPuzzleBusy,
|
||||
isPuzzleLeaderboardBusy,
|
||||
activeRecommendRuntimeKind,
|
||||
puzzleRun,
|
||||
puzzleRuntimeReturnStage,
|
||||
puzzleRuntimeAuthMode,
|
||||
setActiveRecommendEntryKey,
|
||||
setPuzzleGalleryEntries,
|
||||
resolvePuzzleErrorMessage,
|
||||
selectedPuzzleDetail,
|
||||
setIsPuzzleBusy,
|
||||
@@ -12394,6 +12442,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()) {
|
||||
@@ -12546,14 +12598,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 =
|
||||
@@ -12564,7 +12618,7 @@ export function PlatformEntryFlowShellImpl({
|
||||
return;
|
||||
}
|
||||
if (
|
||||
getPlatformPublicGalleryEntryKey(nextEntry) === activeRecommendEntryKey
|
||||
getPlatformPublicGalleryEntryKey(nextEntry) === normalizedBaseEntryKey
|
||||
) {
|
||||
return;
|
||||
}
|
||||
@@ -14325,18 +14379,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);
|
||||
|
||||
Reference in New Issue
Block a user