mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-30 07:39:06 +08:00
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:
parent
3211e3db26
commit
075dfd00ca
@ -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
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user