Skip to content

Commit adef407

Browse files
committed
refactor: enhance GiscusComment component for dynamic loading and theme updates
1 parent 8a46872 commit adef407

1 file changed

Lines changed: 110 additions & 32 deletions

File tree

src/components/GiscusComment.tsx

Lines changed: 110 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,122 @@
11
'use client'
22

3-
import { useEffect, useRef } from 'react'
3+
import { useTheme } from 'next-themes'
4+
import { usePathname } from 'next/navigation'
5+
import { useEffect, useState } from 'react'
46

57
export default function GiscusComment() {
6-
const ref = useRef<HTMLDivElement>(null)
8+
const { resolvedTheme } = useTheme()
9+
const pathname = usePathname()
10+
const [isGiscusLoaded, setIsGiscusLoaded] = useState(false)
711

12+
// 每当路径变化时,完全重载Giscus
813
useEffect(() => {
9-
if (!ref.current || ref.current.hasChildNodes()) return
10-
11-
// 获取当前完整路径(包括语言前缀等)
12-
const pathname = window.location.pathname
13-
console.log('[Giscus] Loading with pathname:', pathname)
14-
15-
const script = document.createElement('script')
16-
script.src = 'https://giscus.app/client.js'
17-
script.setAttribute('data-repo', 'ScienceOL/docs')
18-
script.setAttribute('data-repo-id', 'R_kgDOOI9EFg')
19-
script.setAttribute('data-category', 'Announcements')
20-
script.setAttribute('data-category-id', 'DIC_kwDOOI9EFs4Cr9K0')
21-
script.setAttribute('data-mapping', 'url')
22-
script.setAttribute('data-strict', '0')
23-
script.setAttribute('data-reactions-enabled', '1')
24-
script.setAttribute('data-emit-metadata', '0')
25-
script.setAttribute('data-input-position', 'top')
26-
script.setAttribute('data-theme', 'preferred_color_scheme')
27-
script.setAttribute('data-lang', 'en')
28-
script.setAttribute('data-loading', 'lazy')
29-
script.crossOrigin = 'anonymous'
30-
script.async = true
31-
32-
script.onerror = (error) => {
33-
console.error('[Giscus] Failed to load script:', error)
14+
// 如果已加载,则先移除现有的Giscus元素
15+
if (isGiscusLoaded) {
16+
const giscusContainer = document.querySelector('.giscus')
17+
if (giscusContainer) {
18+
// 清空容器内容
19+
giscusContainer.innerHTML = ''
20+
// 重新设置标志位
21+
setIsGiscusLoaded(false)
22+
23+
// 延迟重新加载Giscus脚本
24+
setTimeout(() => {
25+
loadGiscus()
26+
}, 300)
27+
}
28+
} else if (document.readyState === 'complete') {
29+
// 首次加载
30+
loadGiscus()
31+
}
32+
33+
// 加载Giscus脚本的函数
34+
function loadGiscus() {
35+
const script = document.createElement('script')
36+
script.src = 'https://giscus.app/client.js'
37+
script.setAttribute('data-repo', 'ScienceOL/docs')
38+
script.setAttribute('data-repo-id', 'R_kgDOOI9EFg')
39+
script.setAttribute('data-category', 'Announcements')
40+
script.setAttribute('data-category-id', 'DIC_kwDOOI9EFs4Cr9K0')
41+
script.setAttribute('data-mapping', 'specific')
42+
script.setAttribute('data-term', pathname)
43+
script.setAttribute('data-strict', '1')
44+
script.setAttribute('data-reactions-enabled', '1')
45+
script.setAttribute('data-emit-metadata', '0')
46+
script.setAttribute('data-input-position', 'top')
47+
script.setAttribute(
48+
'data-theme',
49+
resolvedTheme === 'dark' ? 'transparent_dark' : 'light',
50+
)
51+
script.setAttribute('data-loading', 'lazy')
52+
script.setAttribute('data-lang', 'zh-CN')
53+
script.crossOrigin = 'anonymous'
54+
script.async = true
55+
56+
// 找到Giscus容器并添加脚本
57+
const giscusContainer = document.querySelector('.giscus')
58+
if (giscusContainer) {
59+
giscusContainer.appendChild(script)
60+
setIsGiscusLoaded(true)
61+
}
62+
}
63+
64+
// 监听DOM加载完成事件
65+
const handleDOMContentLoaded = () => {
66+
loadGiscus()
67+
}
68+
69+
if (document.readyState === 'loading') {
70+
document.addEventListener('DOMContentLoaded', handleDOMContentLoaded)
3471
}
3572

36-
script.onload = () => {
37-
console.log('[Giscus] Script loaded successfully')
73+
return () => {
74+
document.removeEventListener('DOMContentLoaded', handleDOMContentLoaded)
75+
} // 依赖 resolvedTheme 是正确的
76+
}, [pathname, resolvedTheme]) // eslint-disable-line react-hooks/exhaustive-deps
77+
78+
// 监听主题变化,实时更新Giscus主题
79+
useEffect(() => {
80+
if (!isGiscusLoaded) return
81+
82+
const updateGiscusTheme = () => {
83+
const iframe = document.querySelector(
84+
'iframe.giscus-frame',
85+
) as HTMLIFrameElement
86+
if (iframe) {
87+
const theme = resolvedTheme === 'dark' ? 'transparent_dark' : 'light'
88+
iframe.contentWindow?.postMessage(
89+
{ giscus: { setConfig: { theme } } },
90+
'https://giscus.app',
91+
)
92+
}
93+
}
94+
95+
// 监听Giscus消息
96+
const handleMessage = (event: MessageEvent) => {
97+
if (
98+
event.origin === 'https://giscus.app' &&
99+
event.data?.giscus?.discussion
100+
) {
101+
updateGiscusTheme()
102+
}
38103
}
39104

40-
ref.current.appendChild(script)
41-
}, [])
105+
window.addEventListener('message', handleMessage)
106+
107+
// 轮询尝试更新主题,确保iframe加载后应用正确主题
108+
let attempts = 0
109+
const interval = setInterval(() => {
110+
updateGiscusTheme()
111+
attempts++
112+
if (attempts >= 10) clearInterval(interval)
113+
}, 500)
114+
115+
return () => {
116+
window.removeEventListener('message', handleMessage)
117+
clearInterval(interval)
118+
}
119+
}, [resolvedTheme, isGiscusLoaded])
42120

43-
return <div ref={ref} className="giscus mt-8" />
121+
return <div className="giscus mt-8">{/* Giscus将在这里动态加载 */}</div>
44122
}

0 commit comments

Comments
 (0)