Files
Genarrative/src/components/ResolvedAssetImage.tsx
T
kdletters f67d228c02 完善创作主页精选素材预览
新增精选素材分组模型,按素材包、角色、UI、音乐、美宣等分类组合展示素材

补齐素材卡片和预览弹窗中的提示词、作者与生成总成本展示

新增接近全屏的素材预览弹窗,支持底部外置缩略图导航切换

让私有图片、视频和音频预览携带 objectKey 换签读取

补充创作主页素材展示文档和聚焦测试
2026-06-22 11:00:05 +08:00

73 lines
1.7 KiB
TypeScript

import React, { type ImgHTMLAttributes, useEffect, useState } from 'react';
import { useResolvedAssetReadUrl } from '../hooks/useResolvedAssetReadUrl';
import { RuntimeResourcePendingMarker } from './common/RuntimeResourcePendingMarker';
type ResolvedAssetImageProps = Omit<
ImgHTMLAttributes<HTMLImageElement>,
'src'
> & {
src?: string | null;
objectKey?: string | null;
fallbackSrc?: string | null;
refreshKey?: string | number | null;
};
export function ResolvedAssetImage({
src,
objectKey,
fallbackSrc,
alt,
refreshKey,
onError,
...rest
}: ResolvedAssetImageProps) {
const { resolvedUrl, isResolving, shouldResolve } = useResolvedAssetReadUrl(src, {
objectKey,
refreshKey,
});
const normalizedSource = src?.trim() ?? '';
const normalizedFallbackSrc = fallbackSrc?.trim() ?? '';
const [useFallbackSrc, setUseFallbackSrc] = useState(false);
const finalSrc =
useFallbackSrc && normalizedFallbackSrc
? normalizedFallbackSrc
: resolvedUrl || normalizedFallbackSrc;
const pendingMarker = (
<RuntimeResourcePendingMarker
source={normalizedSource}
kind="image"
isPending={shouldResolve && isResolving}
/>
);
useEffect(() => {
setUseFallbackSrc(false);
}, [normalizedFallbackSrc, resolvedUrl]);
if (!finalSrc) {
return pendingMarker;
}
return (
<>
{pendingMarker}
<img
{...rest}
src={finalSrc}
alt={alt}
onError={(event) => {
if (
normalizedFallbackSrc &&
!useFallbackSrc &&
finalSrc !== normalizedFallbackSrc
) {
setUseFallbackSrc(true);
}
onError?.(event);
}}
/>
</>
);
}