等待推荐页运行态全部资源

推荐页 ready 持续观察运行态图片、背景、音视频和资源 pending 标记
资源换签与玩法图集解析中通过隐藏标记阻止遮罩提前消失
补齐拼图、跳一跳、抓大鹅和敲木鱼运行态资源等待接入
补充推荐页资源等待回归测试和团队文档
This commit is contained in:
2026-06-08 17:49:28 +08:00
parent ccb5023197
commit 52c6f4282f
12 changed files with 802 additions and 125 deletions

View File

@@ -55,6 +55,7 @@ import {
resolveRuntimeCountdownSecondBucket,
} from '../../services/runtimeAudioFeedback';
import { useAuthUi } from '../auth/AuthUiContext';
import { RuntimeResourcePendingMarker } from '../common/RuntimeResourcePendingMarker';
import { ResolvedAssetImage } from '../ResolvedAssetImage';
import {
buildMergedGroupOutlinePath,
@@ -475,6 +476,8 @@ export function PuzzleRuntimeShell({
} | null>(null);
const [uiSpritesheetLayout, setUiSpritesheetLayout] =
useState<PuzzleUiSpritesheetLayout | null>(null);
const [isUiSpritesheetLayoutResolving, setIsUiSpritesheetLayoutResolving] =
useState(false);
const runtimeDragInputControllerRef = useRef(
createRuntimeDragInputController<string>(),
);
@@ -526,22 +529,28 @@ export function PuzzleRuntimeShell({
currentLevel?.backgroundMusic?.audioSrc?.trim() || null;
const levelAudioConfig = DEFAULT_RUNTIME_LEVEL_AUDIO_CONFIG;
const onMusicVolumeChange = authUi?.setMusicVolume ?? (() => {});
const { resolvedUrl: resolvedBackgroundMusicSrc } =
useResolvedAssetReadUrl(backgroundMusicSrc);
const { resolvedUrl: resolvedCoverImage } = useResolvedAssetReadUrl(
const {
resolvedUrl: resolvedBackgroundMusicSrc,
isResolving: isBackgroundMusicResolving,
} = useResolvedAssetReadUrl(backgroundMusicSrc);
const { resolvedUrl: resolvedCoverImage, isResolving: isCoverImageResolving } =
useResolvedAssetReadUrl(
currentLevel?.coverImageSrc ?? null,
);
const { resolvedUrl: resolvedUiBackgroundImage } = useResolvedAssetReadUrl(
resolvePuzzleUiBackgroundSource(currentLevel) ?? null,
);
const rawUiBackgroundImage = resolvePuzzleUiBackgroundSource(currentLevel);
const {
resolvedUrl: resolvedUiBackgroundImage,
isResolving: isUiBackgroundResolving,
} = useResolvedAssetReadUrl(rawUiBackgroundImage ?? null);
const rawUiSpritesheetImage =
currentLevel?.uiSpritesheetImageSrc?.trim() ||
(currentLevel?.uiSpritesheetImageObjectKey?.trim()
? `/${currentLevel.uiSpritesheetImageObjectKey.trim().replace(/^\/+/u, '')}`
: null);
const { resolvedUrl: resolvedUiSpritesheetImage } = useResolvedAssetReadUrl(
rawUiSpritesheetImage,
);
const {
resolvedUrl: resolvedUiSpritesheetImage,
isResolving: isUiSpritesheetResolving,
} = useResolvedAssetReadUrl(rawUiSpritesheetImage);
const hasUiSpritesheet = Boolean(resolvedUiSpritesheetImage);
const tryPlayBackgroundMusic = useCallback(() => {
const audio = backgroundAudioRef.current;
@@ -558,23 +567,27 @@ export function PuzzleRuntimeShell({
useEffect(() => {
if (!rawUiSpritesheetImage) {
setUiSpritesheetLayout(null);
setIsUiSpritesheetLayoutResolving(false);
return;
}
const controller = new AbortController();
setUiSpritesheetLayout(null);
setIsUiSpritesheetLayoutResolving(true);
void loadPuzzleUiSpritesheetLayout(rawUiSpritesheetImage, {
signal: controller.signal,
})
.then((layout) => {
if (!controller.signal.aborted) {
setUiSpritesheetLayout(layout);
setIsUiSpritesheetLayoutResolving(false);
}
})
.catch(() => {
if (!controller.signal.aborted) {
// 中文注释:私有图读取或 canvas 解析失败时回退旧固定六宫格,避免运行态按钮空白。
setUiSpritesheetLayout(null);
setIsUiSpritesheetLayoutResolving(false);
}
});
@@ -1523,6 +1536,26 @@ export function PuzzleRuntimeShell({
<div
className={`platform-ui-shell platform-theme ${platformThemeClass} puzzle-runtime-shell ${embedded ? 'relative h-full min-h-0 w-full' : 'fixed inset-0 z-[100]'} flex justify-center`}
>
<RuntimeResourcePendingMarker
source={backgroundMusicSrc}
kind="audio"
isPending={isBackgroundMusicResolving}
/>
<RuntimeResourcePendingMarker
source={currentLevel.coverImageSrc}
kind="image"
isPending={isCoverImageResolving}
/>
<RuntimeResourcePendingMarker
source={rawUiBackgroundImage}
kind="image"
isPending={isUiBackgroundResolving}
/>
<RuntimeResourcePendingMarker
source={rawUiSpritesheetImage}
kind="image"
isPending={isUiSpritesheetResolving || isUiSpritesheetLayoutResolving}
/>
{resolvedBackgroundMusicSrc ? (
<audio
ref={backgroundAudioRef}