Files
dify/web/app/components/workflow/skill/viewer/read-only-file-preview.tsx
yyh 76484406a2 feat(inspect): add read-only file preview in ArtifactsTab
Implement ReadOnlyFilePreview to render sandbox files by type
(code, markdown, image, video, SQLite, unsupported) using existing
skill viewer components with readOnly support. Add
useSandboxFileDownloadUrl and useFetchTextContent hooks for data
fetching, and generalize useFileTypeInfo to accept any file-like
object.
2026-01-29 16:42:22 +08:00

81 lines
2.1 KiB
TypeScript

'use client'
import dynamic from 'next/dynamic'
import * as React from 'react'
import Loading from '@/app/components/base/loading'
import { useFetchTextContent } from '../hooks/use-fetch-text-content'
import { useFileTypeInfo } from '../hooks/use-file-type-info'
import { getFileLanguage } from '../utils/file-utils'
import MediaFilePreview from './media-file-preview'
import UnsupportedFileDownload from './unsupported-file-download'
const ReadOnlyCodePreview = dynamic(
() => import('./read-only-code-preview'),
{ ssr: false, loading: () => <Loading type="area" /> },
)
const ReadOnlyMarkdownPreview = dynamic(
() => import('./read-only-markdown-preview'),
{ ssr: false, loading: () => <Loading type="area" /> },
)
const SQLiteFilePreview = dynamic(
() => import('./sqlite-file-preview'),
{ ssr: false, loading: () => <Loading type="area" /> },
)
type ReadOnlyFilePreviewProps = {
downloadUrl: string
fileName: string
extension?: string | null
fileSize?: number | null
}
const ReadOnlyFilePreview = ({
downloadUrl,
fileName,
extension,
fileSize,
}: ReadOnlyFilePreviewProps) => {
const fileNode = React.useMemo(
() => ({ name: fileName, extension }),
[fileName, extension],
)
const { isMarkdown, isCodeOrText, isImage, isVideo, isSQLite } = useFileTypeInfo(fileNode)
const isTextFile = isMarkdown || isCodeOrText
const { data: textContent, isLoading: isTextLoading } = useFetchTextContent(
isTextFile ? downloadUrl : undefined,
)
if (isTextFile && isTextLoading)
return <Loading type="area" />
if (isMarkdown)
return <ReadOnlyMarkdownPreview value={textContent ?? ''} />
if (isCodeOrText) {
return (
<ReadOnlyCodePreview
value={textContent ?? ''}
language={getFileLanguage(fileName)}
/>
)
}
if (isImage || isVideo)
return <MediaFilePreview type={isImage ? 'image' : 'video'} src={downloadUrl} />
if (isSQLite)
return <SQLiteFilePreview downloadUrl={downloadUrl} />
return (
<UnsupportedFileDownload
name={fileName}
size={fileSize ?? undefined}
downloadUrl={downloadUrl}
/>
)
}
export default React.memo(ReadOnlyFilePreview)