mirror of
https://github.com/langgenius/dify.git
synced 2026-05-01 07:58:02 +08:00
feat(sandbox): use extension field for file icon type mapping
Enhance getFileIconType to accept an extension parameter and cover all 13 FileAppearanceTypeEnum types using an O(1) Map lookup. Update all call sites to pass the API-provided extension for accurate icon display.
This commit is contained in:
@ -24,7 +24,7 @@ const FilePickerTreeNode: FC<FilePickerTreeNodeProps> = ({ node, style, dragHand
|
||||
const { t } = useTranslation('workflow')
|
||||
const isFolder = node.data.node_type === 'folder'
|
||||
const isSelected = node.isSelected
|
||||
const fileIconType = !isFolder ? getFileIconType(node.data.name) : null
|
||||
const fileIconType = !isFolder ? getFileIconType(node.data.name, node.data.extension) : null
|
||||
|
||||
const handleClick = useCallback((e: React.MouseEvent) => {
|
||||
e.stopPropagation()
|
||||
|
||||
@ -33,7 +33,7 @@ const FileReferenceBlock: FC<FileReferenceBlockProps> = ({ nodeKey, resourceId }
|
||||
const currentNode = useMemo(() => nodeMap?.get(resourceId), [nodeMap, resourceId])
|
||||
const isFolder = currentNode?.node_type === 'folder'
|
||||
const displayName = currentNode?.name ?? resourceId
|
||||
const iconType = !isFolder && currentNode ? getFileIconType(currentNode.name) : null
|
||||
const iconType = !isFolder && currentNode ? getFileIconType(currentNode.name, currentNode.extension) : null
|
||||
const title = currentNode?.path ?? displayName
|
||||
|
||||
const handleSelect = useCallback((node: TreeNodeData) => {
|
||||
|
||||
@ -13,6 +13,7 @@ import { getFileIconType } from './utils/file-utils'
|
||||
type FileTabItemProps = {
|
||||
fileId: string
|
||||
name: string
|
||||
extension?: string
|
||||
isActive: boolean
|
||||
isDirty: boolean
|
||||
isPreview: boolean
|
||||
@ -24,6 +25,7 @@ type FileTabItemProps = {
|
||||
const FileTabItem: FC<FileTabItemProps> = ({
|
||||
fileId,
|
||||
name,
|
||||
extension,
|
||||
isActive,
|
||||
isDirty,
|
||||
isPreview,
|
||||
@ -32,7 +34,7 @@ const FileTabItem: FC<FileTabItemProps> = ({
|
||||
onDoubleClick,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const iconType = getFileIconType(name)
|
||||
const iconType = getFileIconType(name, extension)
|
||||
|
||||
const handleClick = useCallback(() => {
|
||||
onClick(fileId)
|
||||
|
||||
@ -86,6 +86,7 @@ const FileTabs: FC = () => {
|
||||
key={fileId}
|
||||
fileId={fileId}
|
||||
name={name}
|
||||
extension={node?.extension}
|
||||
isActive={isActive}
|
||||
isDirty={isDirty}
|
||||
isPreview={isPreview}
|
||||
|
||||
@ -58,7 +58,7 @@ const ArtifactsTreeNode: FC<ArtifactsTreeNodeProps> = ({
|
||||
onDownload(node)
|
||||
}, [node, onDownload])
|
||||
|
||||
const fileIconType = !isFolder ? getFileIconType(node.name) : null
|
||||
const fileIconType = !isFolder ? getFileIconType(node.name, node.extension) : null
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
||||
@ -14,6 +14,7 @@ type TreeNodeIconProps = {
|
||||
isFolder: boolean
|
||||
isOpen: boolean
|
||||
fileName: string
|
||||
extension?: string
|
||||
isDirty: boolean
|
||||
onToggle?: (e: React.MouseEvent) => void
|
||||
}
|
||||
@ -22,6 +23,7 @@ export const TreeNodeIcon: FC<TreeNodeIconProps> = ({
|
||||
isFolder,
|
||||
isOpen,
|
||||
fileName,
|
||||
extension,
|
||||
isDirty,
|
||||
onToggle,
|
||||
}) => {
|
||||
@ -46,7 +48,7 @@ export const TreeNodeIcon: FC<TreeNodeIconProps> = ({
|
||||
)
|
||||
}
|
||||
|
||||
const fileIconType = getFileIconType(fileName)
|
||||
const fileIconType = getFileIconType(fileName, extension)
|
||||
|
||||
return (
|
||||
<div className="relative flex size-full items-center justify-center">
|
||||
|
||||
@ -126,6 +126,7 @@ const TreeNode = ({ node, style, dragHandle, treeChildren }: TreeNodeProps) => {
|
||||
isFolder={isFolder}
|
||||
isOpen={node.isOpen}
|
||||
fileName={node.data.name}
|
||||
extension={node.data.extension}
|
||||
isDirty={isDirty}
|
||||
onToggle={handleToggle}
|
||||
/>
|
||||
|
||||
@ -86,19 +86,33 @@ export function getFileExtension(name?: string, extension?: string): string {
|
||||
return name.split('.').pop()?.toLowerCase() ?? ''
|
||||
}
|
||||
|
||||
export function getFileIconType(name: string): FileAppearanceTypeEnum {
|
||||
const extension = name.split('.').pop()?.toLowerCase() ?? ''
|
||||
const AUDIO_EXTENSIONS = ['mp3', 'm4a', 'wav', 'amr', 'mpga', 'ogg', 'flac', 'aac', 'wma', 'aiff', 'opus']
|
||||
const PDF_EXTENSIONS = ['pdf']
|
||||
const EXCEL_EXTENSIONS = ['xlsx', 'xls', 'csv']
|
||||
const WORD_EXTENSIONS = ['doc', 'docx']
|
||||
const PPT_EXTENSIONS = ['ppt', 'pptx']
|
||||
|
||||
if (MARKDOWN_EXTENSIONS.includes(extension))
|
||||
return FileAppearanceTypeEnum.markdown
|
||||
const EXTENSION_TO_ICON_TYPE = new Map<string, FileAppearanceTypeEnum>(
|
||||
([
|
||||
[['gif'], FileAppearanceTypeEnum.gif],
|
||||
[IMAGE_EXTENSIONS, FileAppearanceTypeEnum.image],
|
||||
[VIDEO_EXTENSIONS, FileAppearanceTypeEnum.video],
|
||||
[AUDIO_EXTENSIONS, FileAppearanceTypeEnum.audio],
|
||||
[PDF_EXTENSIONS, FileAppearanceTypeEnum.pdf],
|
||||
[MARKDOWN_EXTENSIONS, FileAppearanceTypeEnum.markdown],
|
||||
[EXCEL_EXTENSIONS, FileAppearanceTypeEnum.excel],
|
||||
[WORD_EXTENSIONS, FileAppearanceTypeEnum.word],
|
||||
[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]),
|
||||
),
|
||||
)
|
||||
|
||||
if (CODE_EXTENSIONS.includes(extension))
|
||||
return FileAppearanceTypeEnum.code
|
||||
|
||||
if (SQLITE_EXTENSIONS.includes(extension))
|
||||
return FileAppearanceTypeEnum.database
|
||||
|
||||
return FileAppearanceTypeEnum.document
|
||||
export function getFileIconType(name: string, ext?: string | null): FileAppearanceTypeEnum {
|
||||
const extension = ext?.toLowerCase() ?? name.split('.').pop()?.toLowerCase() ?? ''
|
||||
return EXTENSION_TO_ICON_TYPE.get(extension) ?? FileAppearanceTypeEnum.document
|
||||
}
|
||||
|
||||
export function isMarkdownFile(extension: string): boolean {
|
||||
|
||||
@ -73,6 +73,7 @@ function buildTreeFromFlatList(nodes: SandboxFileNode[]): SandboxFileTreeNode[]
|
||||
node_type: node.is_dir ? 'folder' : 'file',
|
||||
size: node.size,
|
||||
mtime: node.mtime,
|
||||
extension: node.extension,
|
||||
children: [],
|
||||
}
|
||||
|
||||
|
||||
@ -18,6 +18,8 @@ export type SandboxFileNode = {
|
||||
size: number | null
|
||||
/** Modification timestamp in seconds (null for some directories) */
|
||||
mtime: number | null
|
||||
/** File extension (null for directories) */
|
||||
extension: string | null
|
||||
}
|
||||
|
||||
/**
|
||||
@ -48,6 +50,8 @@ export type SandboxFileTreeNode = {
|
||||
size: number | null
|
||||
/** Modification timestamp */
|
||||
mtime: number | null
|
||||
/** File extension (null for directories) */
|
||||
extension: string | null
|
||||
/** Child nodes (for folders) */
|
||||
children: SandboxFileTreeNode[]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user