diff --git a/web/app/components/workflow/skill/file-content-panel.tsx b/web/app/components/workflow/skill/file-content-panel.tsx index eceb6a97e3..7e207b183f 100644 --- a/web/app/components/workflow/skill/file-content-panel.tsx +++ b/web/app/components/workflow/skill/file-content-panel.tsx @@ -56,7 +56,7 @@ const FileContentPanel = () => { const currentFileNode = fileTabId ? nodeMap?.get(fileTabId) : undefined - const { isMarkdown, isCodeOrText, isImage, isVideo, isSQLite, isEditable } = useFileTypeInfo(currentFileNode) + const { isMarkdown, isCodeOrText, isImage, isVideo, isSQLite, isEditable, isPreviewable } = useFileTypeInfo(currentFileNode) const { fileContent, downloadUrlData, isLoading, error } = useSkillFileData(appId, fileTabId, isEditable) @@ -210,7 +210,7 @@ const FileContentPanel = () => { const downloadUrl = downloadUrlData?.download_url || '' const fileName = currentFileNode?.name || '' const fileSize = currentFileNode?.size - const isUnsupportedFile = !isMarkdown && !isCodeOrText && !isImage && !isVideo && !isSQLite + const isUnsupportedFile = !isPreviewable return (
diff --git a/web/app/components/workflow/skill/hooks/use-file-type-info.ts b/web/app/components/workflow/skill/hooks/use-file-type-info.ts index a867950c44..b582deb6c1 100644 --- a/web/app/components/workflow/skill/hooks/use-file-type-info.ts +++ b/web/app/components/workflow/skill/hooks/use-file-type-info.ts @@ -16,11 +16,25 @@ export type FileTypeInfo = { isSQLite: boolean isEditable: boolean isMediaFile: boolean + isPreviewable: boolean } export function useFileTypeInfo(fileNode: { name: string, extension?: string | null } | undefined): FileTypeInfo { return useMemo(() => { - const ext = getFileExtension(fileNode?.name, fileNode?.extension ?? undefined) + if (!fileNode) { + return { + isMarkdown: false, + isCodeOrText: false, + isImage: false, + isVideo: false, + isSQLite: false, + isEditable: false, + isMediaFile: false, + isPreviewable: false, + } + } + + const ext = getFileExtension(fileNode.name, fileNode.extension ?? undefined) const markdown = isMarkdownFile(ext) const image = isImageFile(ext) const video = isVideoFile(ext) @@ -36,6 +50,7 @@ export function useFileTypeInfo(fileNode: { name: string, extension?: string | n isSQLite: sqlite, isEditable: editable, isMediaFile: image || video, + isPreviewable: editable || image || video || sqlite, } }, [fileNode?.name, fileNode?.extension]) } diff --git a/web/app/components/workflow/skill/utils/file-utils.ts b/web/app/components/workflow/skill/utils/file-utils.ts index ae8e6d4148..811e9c57ae 100644 --- a/web/app/components/workflow/skill/utils/file-utils.ts +++ b/web/app/components/workflow/skill/utils/file-utils.ts @@ -1,12 +1,12 @@ import { FileAppearanceTypeEnum } from '@/app/components/base/file-uploader/types' -const MARKDOWN_EXTENSIONS = ['md', 'markdown', 'mdx'] -const CODE_EXTENSIONS = ['json', 'yaml', 'yml', 'toml', 'js', 'jsx', 'ts', 'tsx', 'py', 'schema'] -const IMAGE_EXTENSIONS = ['png', 'jpg', 'jpeg', 'gif', 'webp', 'svg', 'bmp', 'ico', 'tiff', 'psd', 'heic', 'heif', 'avif'] -const VIDEO_EXTENSIONS = ['mp4', 'mov', 'webm', 'mpeg', 'mpg', 'm4v', 'avi', 'mkv', 'flv', 'wmv', '3gp'] -const SQLITE_EXTENSIONS = ['db', 'sqlite', 'sqlite3'] +const MARKDOWN_EXTENSIONS = new Set(['md', 'markdown', 'mdx']) +const CODE_EXTENSIONS = new Set(['json', 'yaml', 'yml', 'toml', 'js', 'jsx', 'ts', 'tsx', 'py', 'schema']) +const IMAGE_EXTENSIONS = new Set(['png', 'jpg', 'jpeg', 'gif', 'webp', 'svg', 'bmp', 'ico', 'tiff', 'psd', 'heic', 'heif', 'avif']) +const VIDEO_EXTENSIONS = new Set(['mp4', 'mov', 'webm', 'mpeg', 'mpg', 'm4v', 'avi', 'mkv', 'flv', 'wmv', '3gp']) +const SQLITE_EXTENSIONS = new Set(['db', 'sqlite', 'sqlite3']) -const BINARY_EXTENSIONS = [ +const BINARY_EXTENSIONS = new Set([ 'mp3', 'wav', 'ogg', @@ -76,7 +76,7 @@ const BINARY_EXTENSIONS = [ 'ipa', 'aab', 'lock', -] +]) export function getFileExtension(name?: string, extension?: string): string { if (extension) @@ -105,8 +105,8 @@ const EXTENSION_TO_ICON_TYPE = new Map( [PPT_EXTENSIONS, FileAppearanceTypeEnum.ppt], [CODE_EXTENSIONS, FileAppearanceTypeEnum.code], [SQLITE_EXTENSIONS, FileAppearanceTypeEnum.database], - ] as [string[], FileAppearanceTypeEnum][]).flatMap( - ([exts, type]) => exts.map(e => [e, type] as [string, FileAppearanceTypeEnum]), + ] as [Iterable, FileAppearanceTypeEnum][]).flatMap( + ([exts, type]) => [...exts].map(e => [e, type] as [string, FileAppearanceTypeEnum]), ), ) @@ -116,11 +116,11 @@ export function getFileIconType(name: string, ext?: string | null): FileAppearan } export function isMarkdownFile(extension: string): boolean { - return MARKDOWN_EXTENSIONS.includes(extension) + return MARKDOWN_EXTENSIONS.has(extension) } export function isBinaryFile(extension: string): boolean { - return BINARY_EXTENSIONS.includes(extension) + return BINARY_EXTENSIONS.has(extension) } export function isTextLikeFile(extension: string): boolean { @@ -128,15 +128,15 @@ export function isTextLikeFile(extension: string): boolean { } export function isImageFile(extension: string): boolean { - return IMAGE_EXTENSIONS.includes(extension) + return IMAGE_EXTENSIONS.has(extension) } export function isVideoFile(extension: string): boolean { - return VIDEO_EXTENSIONS.includes(extension) + return VIDEO_EXTENSIONS.has(extension) } export function isSQLiteFile(extension: string): boolean { - return SQLITE_EXTENSIONS.includes(extension) + return SQLITE_EXTENSIONS.has(extension) } export function getFileLanguage(name: string): string { diff --git a/web/app/components/workflow/skill/viewer/read-only-file-preview.tsx b/web/app/components/workflow/skill/viewer/read-only-file-preview.tsx index deb5c9a060..8d59d002f1 100644 --- a/web/app/components/workflow/skill/viewer/read-only-file-preview.tsx +++ b/web/app/components/workflow/skill/viewer/read-only-file-preview.tsx @@ -41,12 +41,22 @@ const ReadOnlyFilePreview = ({ () => ({ name: fileName, extension }), [fileName, extension], ) - const { isMarkdown, isCodeOrText, isImage, isVideo, isSQLite } = useFileTypeInfo(fileNode) - const isTextFile = isMarkdown || isCodeOrText + const { isMarkdown, isCodeOrText, isImage, isVideo, isSQLite, isPreviewable } = useFileTypeInfo(fileNode) + const isTextFile = isPreviewable && (isMarkdown || isCodeOrText) const { data: textContent, isLoading: isTextLoading } = useFetchTextContent( isTextFile ? downloadUrl : undefined, ) + if (!isPreviewable) { + return ( + + ) + } + if (isTextFile && isTextLoading) return