dify/web/app/components/plugins/marketplace/home/use-banner-viewability.ts
Coding On Star cb6c04637b
feat(web): add marketplace creator profiles and homepage redesign (#41538)
Co-authored-by: zxhlyh <jasonapring2015@outlook.com>
Co-authored-by: fatelei <fatelei@gmail.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: CodingOnStar <hanxujiang@dify.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: 姜涵煦 <hanxujiang@jianghanxudeMacBook-Pro-2.local>
Co-authored-by: L1nSn0w <l1nsn0w@qq.com>
Co-authored-by: yyh <92089059+lyzno1@users.noreply.github.com>
2026-09-04 08:09:45 +00:00

59 lines
1.4 KiB
TypeScript

import type { RefObject } from 'react'
import { useEffect, useRef } from 'react'
const BANNER_VIEWABILITY_THRESHOLD = 0.5
const BANNER_VIEWABILITY_DWELL_MS = 1000
export function useBannerViewability(
targetRef: RefObject<Element | null>,
onImpression: () => void,
enabled = true,
) {
const onImpressionRef = useRef(onImpression)
onImpressionRef.current = onImpression
useEffect(() => {
if (!enabled) return
const target = targetRef.current
if (!target || typeof IntersectionObserver === 'undefined') return
let dwellTimer: ReturnType<typeof setTimeout> | undefined
let didImpress = false
const clearDwell = () => {
if (dwellTimer === undefined) return
clearTimeout(dwellTimer)
dwellTimer = undefined
}
const observer = new IntersectionObserver(
([entry]) => {
const isViewable = (entry?.intersectionRatio ?? 0) >= BANNER_VIEWABILITY_THRESHOLD
if (!isViewable) {
didImpress = false
clearDwell()
return
}
if (didImpress || dwellTimer !== undefined) return
dwellTimer = setTimeout(() => {
dwellTimer = undefined
didImpress = true
onImpressionRef.current()
}, BANNER_VIEWABILITY_DWELL_MS)
},
{ threshold: BANNER_VIEWABILITY_THRESHOLD },
)
observer.observe(target)
return () => {
clearDwell()
observer.disconnect()
}
}, [enabled, targetRef])
}