import styles from './AISummary.module.css' import { useEffect, useState } from 'react' import { useGlobal } from '@/lib/global' const AISummary = ({ aiSummary }) => { const { locale } = useGlobal() const [summary, setSummary] = useState(aiSummary) useEffect(() => { showAiSummaryAnimation(aiSummary, setSummary) }, []) return ( aiSummary && (
{locale.AI_SUMMARY.NAME}
GPT
{summary} {summary !== aiSummary && ( )}
) ) } const showAiSummaryAnimation = (rawSummary, setSummary) => { if (!rawSummary) return let currentIndex = 0 const typingDelay = 20 const punctuationDelayMultiplier = 6 let animationRunning = true let lastUpdateTime = performance.now() const animate = () => { if (currentIndex < rawSummary.length && animationRunning) { const currentTime = performance.now() const timeDiff = currentTime - lastUpdateTime const letter = rawSummary.slice(currentIndex, currentIndex + 1) const isPunctuation = /[,。!、?,.!?]/.test(letter) const delay = isPunctuation ? typingDelay * punctuationDelayMultiplier : typingDelay if (timeDiff >= delay) { setSummary(rawSummary.slice(0, currentIndex + 1)) lastUpdateTime = currentTime currentIndex++ if (currentIndex < rawSummary.length) { setSummary(rawSummary.slice(0, currentIndex)) } else { setSummary(rawSummary) observer.disconnect() } } requestAnimationFrame(animate) } } animate(rawSummary) const observer = new IntersectionObserver( entries => { animationRunning = entries[0].isIntersecting if (animationRunning && currentIndex === 0) { setTimeout(() => { requestAnimationFrame(animate) }, 200) } }, { threshold: 0 } ) let post_ai = document.querySelector('.post-ai') if (post_ai) { observer.observe(post_ai) } } export default AISummary