mirror of
https://github.com/GiriNeko/YesPlayMusic.git
synced 2025-12-17 13:48:02 +00:00
feat: updates
This commit is contained in:
parent
8f4c3d8e5b
commit
f340a90117
34 changed files with 781 additions and 323 deletions
|
|
@ -4,45 +4,46 @@ import { useEffect, useState } from 'react'
|
|||
import { ease } from '@/web/utils/const'
|
||||
import useIsMobile from '@/web/hooks/useIsMobile'
|
||||
|
||||
const Image = ({
|
||||
type Props = {
|
||||
src?: string
|
||||
srcSet?: string
|
||||
sizes?: string
|
||||
className?: string
|
||||
lazyLoad?: boolean
|
||||
placeholder?: 'artist' | 'album' | 'playlist' | 'podcast' | 'blank' | false
|
||||
onClick?: (e: React.MouseEvent<HTMLImageElement>) => void
|
||||
onMouseOver?: (e: React.MouseEvent<HTMLImageElement>) => void
|
||||
animation?: boolean
|
||||
}
|
||||
|
||||
const ImageDesktop = ({
|
||||
src,
|
||||
srcSet,
|
||||
className,
|
||||
alt,
|
||||
lazyLoad = true,
|
||||
sizes,
|
||||
placeholder = 'blank',
|
||||
onClick,
|
||||
onMouseOver,
|
||||
animation = true,
|
||||
}: {
|
||||
src?: string
|
||||
srcSet?: string
|
||||
sizes?: string
|
||||
className?: string
|
||||
alt: string
|
||||
lazyLoad?: boolean
|
||||
placeholder?: 'artist' | 'album' | 'playlist' | 'podcast' | 'blank' | false
|
||||
onClick?: (e: React.MouseEvent<HTMLImageElement>) => void
|
||||
onMouseOver?: (e: React.MouseEvent<HTMLImageElement>) => void
|
||||
animation?: boolean
|
||||
}) => {
|
||||
const [loaded, setLoaded] = useState(false)
|
||||
}: Props) => {
|
||||
const [error, setError] = useState(false)
|
||||
const animate = useAnimation()
|
||||
const placeholderAnimate = useAnimation()
|
||||
const isMobile = useIsMobile()
|
||||
const isAnimate = animation && !isMobile
|
||||
useEffect(() => setError(false), [src])
|
||||
|
||||
const onLoad = async () => {
|
||||
setLoaded(true)
|
||||
if (isAnimate) animate.start({ opacity: 1 })
|
||||
if (isAnimate) {
|
||||
animate.start({ opacity: 1 })
|
||||
placeholderAnimate.start({ opacity: 0 })
|
||||
}
|
||||
}
|
||||
const onError = () => {
|
||||
setError(true)
|
||||
}
|
||||
|
||||
const hidden = error || !loaded
|
||||
const transition = { duration: 0.6, ease }
|
||||
const motionProps = isAnimate
|
||||
? {
|
||||
|
|
@ -54,6 +55,7 @@ const Image = ({
|
|||
: {}
|
||||
const placeholderMotionProps = isAnimate
|
||||
? {
|
||||
animate: placeholderAnimate,
|
||||
initial: { opacity: 1 },
|
||||
exit: { opacity: 0 },
|
||||
transition,
|
||||
|
|
@ -62,6 +64,8 @@ const Image = ({
|
|||
|
||||
return (
|
||||
<div
|
||||
onClick={onClick}
|
||||
onMouseOver={onMouseOver}
|
||||
className={cx(
|
||||
'overflow-hidden',
|
||||
className,
|
||||
|
|
@ -71,7 +75,6 @@ const Image = ({
|
|||
{/* Image */}
|
||||
<AnimatePresence>
|
||||
<motion.img
|
||||
alt={alt}
|
||||
className='absolute inset-0 h-full w-full'
|
||||
src={src}
|
||||
srcSet={srcSet}
|
||||
|
|
@ -80,15 +83,13 @@ const Image = ({
|
|||
loading={lazyLoad ? 'lazy' : undefined}
|
||||
onError={onError}
|
||||
onLoad={onLoad}
|
||||
onClick={onClick}
|
||||
onMouseOver={onMouseOver}
|
||||
{...motionProps}
|
||||
/>
|
||||
</AnimatePresence>
|
||||
|
||||
{/* Placeholder / Error fallback */}
|
||||
<AnimatePresence>
|
||||
{hidden && placeholder && (
|
||||
{placeholder && (
|
||||
<motion.div
|
||||
{...placeholderMotionProps}
|
||||
className='absolute inset-0 h-full w-full bg-white dark:bg-neutral-800'
|
||||
|
|
@ -99,4 +100,36 @@ const Image = ({
|
|||
)
|
||||
}
|
||||
|
||||
const ImageMobile = (props: Props) => {
|
||||
const { src, className, srcSet, sizes, lazyLoad, onClick, onMouseOver } =
|
||||
props
|
||||
return (
|
||||
<div
|
||||
onClick={onClick}
|
||||
onMouseOver={onMouseOver}
|
||||
className={cx(
|
||||
'overflow-hidden',
|
||||
className,
|
||||
className?.includes('absolute') === false && 'relative'
|
||||
)}
|
||||
>
|
||||
{src && (
|
||||
<img
|
||||
className='absolute inset-0 h-full w-full'
|
||||
src={src}
|
||||
srcSet={srcSet}
|
||||
sizes={sizes}
|
||||
decoding='async'
|
||||
loading={lazyLoad ? 'lazy' : undefined}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const Image = (props: Props) => {
|
||||
const isMobile = useIsMobile()
|
||||
return isMobile ? <ImageMobile {...props} /> : <ImageDesktop {...props} />
|
||||
}
|
||||
|
||||
export default Image
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue