file-view.js 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. import { useState, useCallback } from 'react'
  2. import PropTypes from 'prop-types'
  3. import { useTranslation } from 'react-i18next'
  4. import FileViewHeader from './file-view-header'
  5. import FileViewImage from './file-view-image'
  6. import FileViewText from './file-view-text'
  7. import Icon from '../../../shared/components/icon'
  8. const imageExtensions = ['png', 'jpg', 'jpeg', 'gif']
  9. export default function FileView({ file, storeReferencesKeys }) {
  10. const [contentLoading, setContentLoading] = useState(true)
  11. const [hasError, setHasError] = useState(false)
  12. const { t } = useTranslation()
  13. const { textExtensions } = window.ExposedSettings
  14. const extension = file.name.split('.').pop().toLowerCase()
  15. const isUnpreviewableFile =
  16. !imageExtensions.includes(extension) && !textExtensions.includes(extension)
  17. const handleLoad = useCallback(() => {
  18. setContentLoading(false)
  19. }, [])
  20. const handleError = useCallback(() => {
  21. if (!hasError) {
  22. setContentLoading(false)
  23. setHasError(true)
  24. }
  25. }, [hasError])
  26. const content = (
  27. <>
  28. <FileViewHeader file={file} storeReferencesKeys={storeReferencesKeys} />
  29. {imageExtensions.includes(extension) && (
  30. <FileViewImage
  31. fileName={file.name}
  32. fileId={file.id}
  33. onLoad={handleLoad}
  34. onError={handleError}
  35. />
  36. )}
  37. {textExtensions.includes(extension) && (
  38. <FileViewText file={file} onLoad={handleLoad} onError={handleError} />
  39. )}
  40. </>
  41. )
  42. return (
  43. <div className="file-view full-size">
  44. {!hasError && content}
  45. {!isUnpreviewableFile && contentLoading && <FileViewLoadingIndicator />}
  46. {(isUnpreviewableFile || hasError) && (
  47. <p className="no-preview">{t('no_preview_available')}</p>
  48. )}
  49. </div>
  50. )
  51. }
  52. function FileViewLoadingIndicator() {
  53. const { t } = useTranslation()
  54. return (
  55. <div className="loading-panel loading-panel-file-view">
  56. <span>
  57. <Icon type="refresh" spin />
  58. &nbsp;&nbsp;{t('loading')}…
  59. </span>
  60. </div>
  61. )
  62. }
  63. FileView.propTypes = {
  64. file: PropTypes.shape({
  65. id: PropTypes.string,
  66. name: PropTypes.string,
  67. }).isRequired,
  68. storeReferencesKeys: PropTypes.func.isRequired,
  69. }