binary-file.js 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. import React, { useState } from 'react'
  2. import PropTypes from 'prop-types'
  3. import BinaryFileHeader from './binary-file-header'
  4. import BinaryFileImage from './binary-file-image'
  5. import BinaryFileText from './binary-file-text'
  6. import Icon from '../../../shared/components/icon'
  7. import { useTranslation } from 'react-i18next'
  8. const imageExtensions = ['png', 'jpg', 'jpeg', 'gif']
  9. const textExtensions = [
  10. 'tex',
  11. 'latex',
  12. 'sty',
  13. 'cls',
  14. 'bst',
  15. 'bib',
  16. 'bibtex',
  17. 'txt',
  18. 'tikz',
  19. 'mtx',
  20. 'rtex',
  21. 'md',
  22. 'asy',
  23. 'latexmkrc',
  24. 'lbx',
  25. 'bbx',
  26. 'cbx',
  27. 'm',
  28. 'lco',
  29. 'dtx',
  30. 'ins',
  31. 'ist',
  32. 'def',
  33. 'clo',
  34. 'ldf',
  35. 'rmd',
  36. 'lua',
  37. 'gv',
  38. ]
  39. export default function BinaryFile({ file, storeReferencesKeys }) {
  40. const extension = file.name.split('.').pop().toLowerCase()
  41. const [contentLoading, setContentLoading] = useState(true)
  42. const [hasError, setHasError] = useState(false)
  43. const { t } = useTranslation()
  44. const isUnpreviewableFile =
  45. !imageExtensions.includes(extension) && !textExtensions.includes(extension)
  46. function handleLoading() {
  47. if (contentLoading) {
  48. setContentLoading(false)
  49. }
  50. }
  51. function handleError() {
  52. if (!hasError) {
  53. setContentLoading(false)
  54. setHasError(true)
  55. }
  56. }
  57. const content = (
  58. <>
  59. <BinaryFileHeader file={file} storeReferencesKeys={storeReferencesKeys} />
  60. {imageExtensions.includes(extension) && (
  61. <BinaryFileImage
  62. fileName={file.name}
  63. fileId={file.id}
  64. onLoad={handleLoading}
  65. onError={handleError}
  66. />
  67. )}
  68. {textExtensions.includes(extension) && (
  69. <BinaryFileText
  70. file={file}
  71. onLoad={handleLoading}
  72. onError={handleError}
  73. />
  74. )}
  75. </>
  76. )
  77. return (
  78. <div className="binary-file full-size">
  79. {!hasError && content}
  80. {!isUnpreviewableFile && contentLoading && <BinaryFileLoadingIndicator />}
  81. {(isUnpreviewableFile || hasError) && (
  82. <p className="no-preview">{t('no_preview_available')}</p>
  83. )}
  84. </div>
  85. )
  86. }
  87. function BinaryFileLoadingIndicator() {
  88. const { t } = useTranslation()
  89. return (
  90. <div className="loading-panel loading-panel-binary-files">
  91. <span>
  92. <Icon type="refresh" modifier="spin" />
  93. &nbsp;&nbsp;{t('loading')}…
  94. </span>
  95. </div>
  96. )
  97. }
  98. BinaryFile.propTypes = {
  99. file: PropTypes.shape({
  100. id: PropTypes.string,
  101. name: PropTypes.string,
  102. }).isRequired,
  103. storeReferencesKeys: PropTypes.func.isRequired,
  104. }