file-item.tsx 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. import {
  2. memo,
  3. useMemo,
  4. } from 'react'
  5. import {
  6. RiDeleteBinLine,
  7. RiDownloadLine,
  8. } from '@remixicon/react'
  9. import FileTypeIcon from '../file-type-icon'
  10. import {
  11. fileIsUploaded,
  12. getFileAppearanceType,
  13. getFileExtension,
  14. } from '../utils'
  15. import FileImageRender from '../file-image-render'
  16. import type { FileEntity } from '../types'
  17. import ActionButton from '@/app/components/base/action-button'
  18. import ProgressCircle from '@/app/components/base/progress-bar/progress-circle'
  19. import { formatFileSize } from '@/utils/format'
  20. import cn from '@/utils/classnames'
  21. import { ReplayLine } from '@/app/components/base/icons/src/vender/other'
  22. import { SupportUploadFileTypes } from '@/app/components/workflow/types'
  23. type FileInAttachmentItemProps = {
  24. file: FileEntity
  25. showDeleteAction?: boolean
  26. showDownloadAction?: boolean
  27. onRemove?: (fileId: string) => void
  28. onReUpload?: (fileId: string) => void
  29. }
  30. const FileInAttachmentItem = ({
  31. file,
  32. showDeleteAction,
  33. showDownloadAction = true,
  34. onRemove,
  35. onReUpload,
  36. }: FileInAttachmentItemProps) => {
  37. const { id, name, type, progress, supportFileType, base64Url, url } = file
  38. const ext = getFileExtension(name, type)
  39. const isImageFile = supportFileType === SupportUploadFileTypes.image
  40. const nameArr = useMemo(() => {
  41. const nameMatch = name.match(/(.+)\.([^.]+)$/)
  42. if (nameMatch)
  43. return [nameMatch[1], nameMatch[2]]
  44. return [name, '']
  45. }, [name])
  46. return (
  47. <div className={cn(
  48. 'flex items-center pr-3 h-12 rounded-lg border-[0.5px] border-components-panel-border bg-components-panel-on-panel-item-bg shadow-xs',
  49. progress === -1 && 'bg-state-destructive-hover border-state-destructive-border',
  50. )}>
  51. <div className='flex items-center justify-center w-12 h-12'>
  52. {
  53. isImageFile && (
  54. <FileImageRender
  55. className='w-8 h-8'
  56. imageUrl={base64Url || url || ''}
  57. />
  58. )
  59. }
  60. {
  61. !isImageFile && (
  62. <FileTypeIcon
  63. type={getFileAppearanceType(name, type)}
  64. size='lg'
  65. />
  66. )
  67. }
  68. </div>
  69. <div className='grow w-0 mr-1'>
  70. <div
  71. className='flex items-center mb-0.5 system-xs-medium text-text-secondary truncate'
  72. title={file.name}
  73. >
  74. <div className='truncate'>{nameArr[0]}</div>
  75. {
  76. nameArr[1] && (
  77. <span>.{nameArr[1]}</span>
  78. )
  79. }
  80. </div>
  81. <div className='flex items-center system-2xs-medium-uppercase text-text-tertiary'>
  82. {
  83. ext && (
  84. <span>{ext.toLowerCase()}</span>
  85. )
  86. }
  87. {
  88. ext && (
  89. <span className='mx-1 system-2xs-medium'>•</span>
  90. )
  91. }
  92. <span>{formatFileSize(file.size || 0)}</span>
  93. </div>
  94. </div>
  95. <div className='shrink-0 flex items-center'>
  96. {
  97. progress >= 0 && !fileIsUploaded(file) && (
  98. <ProgressCircle
  99. className='mr-2.5'
  100. percentage={progress}
  101. />
  102. )
  103. }
  104. {
  105. progress === -1 && (
  106. <ActionButton
  107. className='mr-1'
  108. onClick={() => onReUpload?.(id)}
  109. >
  110. <ReplayLine className='w-4 h-4 text-text-tertiary' />
  111. </ActionButton>
  112. )
  113. }
  114. {
  115. showDeleteAction && (
  116. <ActionButton onClick={() => onRemove?.(id)}>
  117. <RiDeleteBinLine className='w-4 h-4' />
  118. </ActionButton>
  119. )
  120. }
  121. {
  122. showDownloadAction && (
  123. <ActionButton
  124. size='xs'
  125. >
  126. <RiDownloadLine className='w-3.5 h-3.5 text-text-tertiary' />
  127. </ActionButton>
  128. )
  129. }
  130. </div>
  131. </div>
  132. )
  133. }
  134. export default memo(FileInAttachmentItem)