mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-08 13:00:13 +02:00
improve image placeholders and loading
This commit is contained in:
@@ -160,7 +160,12 @@ export const AppIcon = {
|
||||
edit: LuPencilLine,
|
||||
ellipsisHorizontal: LuEllipsis,
|
||||
ellipsisVertical: LuEllipsisVertical,
|
||||
emptyAlbumImage: LuDisc3,
|
||||
emptyArtistImage: LuUser,
|
||||
emptyGenreImage: LuFlag,
|
||||
emptyImage: LuDisc3,
|
||||
emptyPlaylistImage: LuListMusic,
|
||||
emptySongImage: LuMusic,
|
||||
error: LuShieldAlert,
|
||||
externalLink: LuExternalLink,
|
||||
favorite: LuHeart,
|
||||
|
||||
@@ -11,7 +11,7 @@ import { Img } from 'react-image';
|
||||
|
||||
import styles from './image.module.css';
|
||||
|
||||
import { Icon } from '/@/shared/components/icon/icon';
|
||||
import { AppIcon, Icon } from '/@/shared/components/icon/icon';
|
||||
import { Skeleton } from '/@/shared/components/skeleton/skeleton';
|
||||
import { useInViewport } from '/@/shared/hooks/use-in-viewport';
|
||||
|
||||
@@ -23,6 +23,7 @@ export interface ImageProps extends Omit<ImgHTMLAttributes<HTMLImageElement>, 's
|
||||
includeUnloader?: boolean;
|
||||
src: string | string[] | undefined;
|
||||
thumbHash?: string;
|
||||
unloaderIcon?: keyof typeof AppIcon;
|
||||
}
|
||||
|
||||
interface ImageContainerProps extends HTMLAttributes<HTMLDivElement> {
|
||||
@@ -36,6 +37,7 @@ interface ImageLoaderProps {
|
||||
|
||||
interface ImageUnloaderProps {
|
||||
className?: string;
|
||||
icon?: keyof typeof AppIcon;
|
||||
}
|
||||
|
||||
export const FALLBACK_SVG =
|
||||
@@ -49,52 +51,40 @@ export function BaseImage({
|
||||
includeLoader = true,
|
||||
includeUnloader = true,
|
||||
src,
|
||||
unloaderIcon = 'emptyImage',
|
||||
...props
|
||||
}: ImageProps) {
|
||||
const { inViewport, ref } = useInViewport();
|
||||
|
||||
if (src) {
|
||||
return (
|
||||
<Img
|
||||
className={clsx(styles.image, className, {
|
||||
[styles.animated]: enableAnimation,
|
||||
})}
|
||||
container={(children) => (
|
||||
<ImageContainer
|
||||
className={containerClassName}
|
||||
enableAnimation={enableAnimation}
|
||||
ref={ref}
|
||||
{...imageContainerProps}
|
||||
>
|
||||
{children}
|
||||
</ImageContainer>
|
||||
)}
|
||||
decoding="async"
|
||||
fetchPriority={inViewport ? 'high' : 'low'}
|
||||
loader={
|
||||
includeLoader ? (
|
||||
<ImageContainer className={containerClassName}>
|
||||
<ImageLoader className={className} />
|
||||
</ImageContainer>
|
||||
) : null
|
||||
}
|
||||
loading={inViewport ? 'eager' : 'lazy'}
|
||||
src={inViewport ? src : FALLBACK_SVG}
|
||||
unloader={
|
||||
includeUnloader ? (
|
||||
<ImageContainer className={containerClassName}>
|
||||
<ImageUnloader className={className} />
|
||||
</ImageContainer>
|
||||
) : null
|
||||
}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<ImageContainer className={containerClassName}>
|
||||
<ImageUnloader />
|
||||
<ImageContainer
|
||||
className={containerClassName}
|
||||
enableAnimation={enableAnimation}
|
||||
ref={ref}
|
||||
{...imageContainerProps}
|
||||
>
|
||||
{inViewport && src ? (
|
||||
<Img
|
||||
className={clsx(styles.image, className, {
|
||||
[styles.animated]: enableAnimation,
|
||||
})}
|
||||
decoding="async"
|
||||
fetchPriority="high"
|
||||
loader={includeLoader ? <ImageLoader className={className} /> : null}
|
||||
loading="eager"
|
||||
src={src}
|
||||
unloader={
|
||||
includeUnloader ? (
|
||||
<ImageUnloader className={className} icon={unloaderIcon} />
|
||||
) : null
|
||||
}
|
||||
{...props}
|
||||
/>
|
||||
) : !src ? (
|
||||
<ImageUnloader icon={unloaderIcon} />
|
||||
) : (
|
||||
<ImageLoader className={className} />
|
||||
)}
|
||||
</ImageContainer>
|
||||
);
|
||||
}
|
||||
@@ -131,10 +121,10 @@ export function ImageLoader({ className }: ImageLoaderProps) {
|
||||
);
|
||||
}
|
||||
|
||||
export function ImageUnloader({ className }: ImageUnloaderProps) {
|
||||
export function ImageUnloader({ className, icon = 'emptyImage' }: ImageUnloaderProps) {
|
||||
return (
|
||||
<div className={clsx(styles.unloader, className)}>
|
||||
<Icon color="default" icon="emptyImage" size="25%" />
|
||||
<Icon color="default" icon={icon} size="25%" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user