refactor(HtmlArtifactsPopup): improve preview handling and state synchronization

- Updated internal state synchronization for HTML content and preview.
- Enhanced preview refresh logic to check for content changes every 2 seconds.
- Improved comments for clarity and consistency in English.
This commit is contained in:
kangfenmao 2025-08-07 15:49:23 +08:00
parent 3211e3db26
commit 075dfd00ca
2 changed files with 23 additions and 14 deletions

View File

@ -22,45 +22,51 @@ const HtmlArtifactsPopup: React.FC<HtmlArtifactsPopupProps> = ({ open, title, ht
const [currentHtml, setCurrentHtml] = useState(html) const [currentHtml, setCurrentHtml] = useState(html)
const [isFullscreen, setIsFullscreen] = useState(false) const [isFullscreen, setIsFullscreen] = useState(false)
// 预览刷新相关状态 // Preview refresh related state
const [previewHtml, setPreviewHtml] = useState(html) const [previewHtml, setPreviewHtml] = useState(html)
const intervalRef = useRef<NodeJS.Timeout | null>(null) const intervalRef = useRef<NodeJS.Timeout | null>(null)
const latestHtmlRef = useRef(html) const latestHtmlRef = useRef(html)
const currentPreviewHtmlRef = useRef(html)
// 当外部html更新时同步更新内部状态 // Sync internal state when external html updates
useEffect(() => { useEffect(() => {
setCurrentHtml(html) setCurrentHtml(html)
latestHtmlRef.current = html latestHtmlRef.current = html
}, [html]) }, [html])
// 当内部编辑的html更新时更新引用 // Update reference when internally edited html changes
useEffect(() => { useEffect(() => {
latestHtmlRef.current = currentHtml latestHtmlRef.current = currentHtml
}, [currentHtml]) }, [currentHtml])
// 2秒定时检查并刷新预览仅在内容变化时 // Update reference when preview content changes
useEffect(() => {
currentPreviewHtmlRef.current = previewHtml
}, [previewHtml])
// Check and refresh preview every 2 seconds (only when content changes)
useEffect(() => { useEffect(() => {
if (!open) return if (!open) return
// 立即设置初始预览内容 // Set initial preview content immediately
setPreviewHtml(currentHtml) setPreviewHtml(latestHtmlRef.current)
// 设置定时器每2秒检查一次内容是否有变化 // Set timer to check for content changes every 2 seconds
intervalRef.current = setInterval(() => { intervalRef.current = setInterval(() => {
if (latestHtmlRef.current !== previewHtml) { if (latestHtmlRef.current !== currentPreviewHtmlRef.current) {
setPreviewHtml(latestHtmlRef.current) setPreviewHtml(latestHtmlRef.current)
} }
}, 2000) }, 2000)
// 清理函数 // Cleanup function
return () => { return () => {
if (intervalRef.current) { if (intervalRef.current) {
clearInterval(intervalRef.current) clearInterval(intervalRef.current)
} }
} }
}, [currentHtml, open, previewHtml]) }, [open])
// 全屏时防止 body 滚动 // Prevent body scroll when fullscreen
useEffect(() => { useEffect(() => {
if (!open || !isFullscreen) return if (!open || !isFullscreen) return
@ -160,7 +166,7 @@ const HtmlArtifactsPopup: React.FC<HtmlArtifactsPopupProps> = ({ open, title, ht
<PreviewSection> <PreviewSection>
{previewHtml.trim() ? ( {previewHtml.trim() ? (
<PreviewFrame <PreviewFrame
key={previewHtml} // 强制重新创建iframe当预览内容变化时 key={previewHtml} // Force recreate iframe when preview content changes
srcDoc={previewHtml} srcDoc={previewHtml}
title="HTML Preview" title="HTML Preview"
sandbox="allow-scripts allow-same-origin allow-forms" sandbox="allow-scripts allow-same-origin allow-forms"
@ -177,7 +183,6 @@ const HtmlArtifactsPopup: React.FC<HtmlArtifactsPopupProps> = ({ open, title, ht
) )
} }
// 简化的样式组件
const StyledModal = styled(Modal)<{ $isFullscreen?: boolean }>` const StyledModal = styled(Modal)<{ $isFullscreen?: boolean }>`
${(props) => ${(props) =>
props.$isFullscreen props.$isFullscreen

View File

@ -609,7 +609,11 @@ const DataSettings: FC = () => {
<SettingRow> <SettingRow>
<SettingRowTitle>{t('settings.data.app_data.label')}</SettingRowTitle> <SettingRowTitle>{t('settings.data.app_data.label')}</SettingRowTitle>
<PathRow> <PathRow>
<PathText style={{ color: 'var(--color-text-3)' }}>{appInfo?.appDataPath}</PathText> <PathText
style={{ color: 'var(--color-text-3)' }}
onClick={() => handleOpenPath(appInfo?.appDataPath)}>
{appInfo?.appDataPath}
</PathText>
<StyledIcon onClick={() => handleOpenPath(appInfo?.appDataPath)} style={{ flexShrink: 0 }} /> <StyledIcon onClick={() => handleOpenPath(appInfo?.appDataPath)} style={{ flexShrink: 0 }} />
<HStack gap="5px" style={{ marginLeft: '8px' }}> <HStack gap="5px" style={{ marginLeft: '8px' }}>
<Button onClick={handleSelectAppDataPath}>{t('settings.data.app_data.select')}</Button> <Button onClick={handleSelectAppDataPath}>{t('settings.data.app_data.select')}</Button>