mirror of https://github.com/langgenius/dify.git
feat: add pause functionality to explore page banner for improved user interaction
This commit is contained in:
parent
53a80a5dbe
commit
df76527f29
|
|
@ -22,9 +22,10 @@ export type BannerData = {
|
|||
type BannerItemProps = {
|
||||
banner: BannerData
|
||||
autoplayDelay: number
|
||||
isPaused?: boolean
|
||||
}
|
||||
|
||||
export const BannerItem: FC<BannerItemProps> = ({ banner, autoplayDelay }) => {
|
||||
export const BannerItem: FC<BannerItemProps> = ({ banner, autoplayDelay, isPaused = false }) => {
|
||||
const { t } = useTranslation()
|
||||
const { api, selectedIndex } = useCarousel()
|
||||
const [resetKey, setResetKey] = useState(0)
|
||||
|
|
@ -102,6 +103,7 @@ export const BannerItem: FC<BannerItemProps> = ({ banner, autoplayDelay }) => {
|
|||
isNextSlide={index === slideInfo.nextIndex}
|
||||
autoplayDelay={autoplayDelay}
|
||||
resetKey={resetKey}
|
||||
isPaused={isPaused}
|
||||
onClick={() => handleIndicatorClick(index)}
|
||||
/>
|
||||
))}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import type { FC } from 'react'
|
||||
import React, { useMemo } from 'react'
|
||||
import React, { useMemo, useState } from 'react'
|
||||
import { Carousel } from '@/app/components/base/carousel'
|
||||
import { useGetBanners } from '@/service/use-explore'
|
||||
import Loading from '../../base/loading'
|
||||
|
|
@ -12,6 +12,7 @@ const MIN_LOADING_HEIGHT = 168
|
|||
const Banner: FC = () => {
|
||||
const { locale } = useI18N()
|
||||
const { data: banners, isLoading, isError } = useGetBanners(locale)
|
||||
const [isHovered, setIsHovered] = useState(false)
|
||||
|
||||
const enabledBanners = useMemo(
|
||||
() => banners?.filter((banner: BannerData) => banner.status === 'enabled') ?? [],
|
||||
|
|
@ -39,14 +40,17 @@ const Banner: FC = () => {
|
|||
Carousel.Plugin.Autoplay({
|
||||
delay: AUTOPLAY_DELAY,
|
||||
stopOnInteraction: false,
|
||||
stopOnMouseEnter: true,
|
||||
}),
|
||||
]}
|
||||
className="rounded-2xl"
|
||||
onMouseEnter={() => setIsHovered(true)}
|
||||
onMouseLeave={() => setIsHovered(false)}
|
||||
>
|
||||
<Carousel.Content>
|
||||
{enabledBanners.map((banner: BannerData) => (
|
||||
<Carousel.Item key={banner.id}>
|
||||
<BannerItem banner={banner} autoplayDelay={AUTOPLAY_DELAY} />
|
||||
<BannerItem banner={banner} autoplayDelay={AUTOPLAY_DELAY} isPaused={isHovered} />
|
||||
</Carousel.Item>
|
||||
))}
|
||||
</Carousel.Content>
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ type IndicatorButtonProps = {
|
|||
isNextSlide: boolean
|
||||
autoplayDelay: number
|
||||
resetKey: number
|
||||
isPaused?: boolean
|
||||
onClick: () => void
|
||||
}
|
||||
|
||||
|
|
@ -20,12 +21,12 @@ export const IndicatorButton: FC<IndicatorButtonProps> = ({
|
|||
isNextSlide,
|
||||
autoplayDelay,
|
||||
resetKey,
|
||||
isPaused = false,
|
||||
onClick,
|
||||
}) => {
|
||||
const [progress, setProgress] = useState(0)
|
||||
const [isPageVisible, setIsPageVisible] = useState(true)
|
||||
const frameIdRef = useRef<number | undefined>(undefined)
|
||||
const pausedTimeRef = useRef(0)
|
||||
const startTimeRef = useRef(0)
|
||||
|
||||
// Listen to page visibility changes
|
||||
|
|
@ -52,13 +53,12 @@ export const IndicatorButton: FC<IndicatorButtonProps> = ({
|
|||
// reset and start new animation
|
||||
setProgress(0)
|
||||
startTimeRef.current = Date.now()
|
||||
pausedTimeRef.current = 0
|
||||
|
||||
const animate = () => {
|
||||
// Only continue animation when page is visible
|
||||
if (!document.hidden) {
|
||||
// Only continue animation when page is visible and not paused
|
||||
if (!document.hidden && !isPaused) {
|
||||
const now = Date.now()
|
||||
const elapsed = now - startTimeRef.current - pausedTimeRef.current
|
||||
const elapsed = now - startTimeRef.current
|
||||
const newProgress = Math.min((elapsed / autoplayDelay) * PROGRESS_MAX, PROGRESS_MAX)
|
||||
setProgress(newProgress)
|
||||
|
||||
|
|
@ -69,14 +69,14 @@ export const IndicatorButton: FC<IndicatorButtonProps> = ({
|
|||
frameIdRef.current = requestAnimationFrame(animate)
|
||||
}
|
||||
}
|
||||
if (!document.hidden)
|
||||
if (!document.hidden && !isPaused)
|
||||
frameIdRef.current = requestAnimationFrame(animate)
|
||||
|
||||
return () => {
|
||||
if (frameIdRef.current)
|
||||
cancelAnimationFrame(frameIdRef.current)
|
||||
}
|
||||
}, [isNextSlide, autoplayDelay, resetKey, isPageVisible])
|
||||
}, [isNextSlide, autoplayDelay, resetKey, isPageVisible, isPaused])
|
||||
|
||||
const isActive = index === selectedIndex
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue