file-view-refresh-button.tsx 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. import {
  2. type Dispatch,
  3. type SetStateAction,
  4. type ElementType,
  5. useCallback,
  6. useState,
  7. } from 'react'
  8. import { useTranslation } from 'react-i18next'
  9. import { postJSON } from '@/infrastructure/fetch-json'
  10. import { useProjectContext } from '@/shared/context/project-context'
  11. import type { BinaryFile } from '../types/binary-file'
  12. import { Nullable } from '../../../../../types/utils'
  13. import importOverleafModules from '../../../../macros/import-overleaf-module.macro'
  14. import OLButton from '@/shared/components/ol/ol-button'
  15. import { sendMB } from '@/infrastructure/event-tracking'
  16. import useIsMounted from '@/shared/hooks/use-is-mounted'
  17. import clientId from '@/utils/client-id'
  18. import { useReferencesContext } from '@/features/ide-react/context/references-context'
  19. type FileViewRefreshButtonProps = {
  20. setRefreshError: Dispatch<SetStateAction<Nullable<string>>>
  21. file: BinaryFile
  22. }
  23. const tprFileViewRefreshButton = importOverleafModules(
  24. 'tprFileViewRefreshButton'
  25. ) as {
  26. import: { TPRFileViewRefreshButton: ElementType }
  27. path: string
  28. }[]
  29. export default function FileViewRefreshButton({
  30. setRefreshError,
  31. file,
  32. }: FileViewRefreshButtonProps) {
  33. const { projectId } = useProjectContext()
  34. const [refreshing, setRefreshing] = useState(false)
  35. const isMountedRef = useIsMounted()
  36. const { indexAllReferences } = useReferencesContext()
  37. const refreshFile = useCallback(
  38. (isTPR: Nullable<boolean>) => {
  39. setRefreshing(true)
  40. // Replacement of the file handled by the file tree
  41. window.expectingLinkedFileRefreshedSocketFor = file.name
  42. const shouldReindexReferences = isTPR || /\.bib$/.test(file.name)
  43. const body = {
  44. shouldReindexReferences,
  45. clientId: clientId.get(),
  46. }
  47. postJSON(`/project/${projectId}/linked_file/${file.id}/refresh`, {
  48. body,
  49. })
  50. .then(() => {
  51. if (isMountedRef.current) {
  52. setRefreshing(false)
  53. }
  54. if (shouldReindexReferences) {
  55. indexAllReferences(false)
  56. }
  57. sendMB('refresh-linked-file', {
  58. provider: file.linkedFileData?.provider,
  59. })
  60. })
  61. .catch(err => {
  62. if (isMountedRef.current) {
  63. setRefreshing(false)
  64. setRefreshError(err.data?.message || err.message)
  65. }
  66. })
  67. },
  68. [file, projectId, setRefreshError, isMountedRef, indexAllReferences]
  69. )
  70. if (tprFileViewRefreshButton.length > 0) {
  71. return tprFileViewRefreshButton.map(
  72. ({ import: { TPRFileViewRefreshButton }, path }) => (
  73. <TPRFileViewRefreshButton
  74. key={path}
  75. file={file}
  76. refreshFile={refreshFile}
  77. refreshing={refreshing}
  78. />
  79. )
  80. )[0]
  81. } else {
  82. return (
  83. <FileViewRefreshButtonDefault
  84. refreshFile={refreshFile}
  85. refreshing={refreshing}
  86. />
  87. )
  88. }
  89. }
  90. type FileViewRefreshButtonDefaultProps = {
  91. refreshFile: (isTPR: Nullable<boolean>) => void
  92. refreshing: boolean
  93. }
  94. function FileViewRefreshButtonDefault({
  95. refreshFile,
  96. refreshing,
  97. }: FileViewRefreshButtonDefaultProps) {
  98. const { t } = useTranslation()
  99. return (
  100. <OLButton
  101. variant="primary"
  102. onClick={() => refreshFile(null)}
  103. disabled={refreshing}
  104. isLoading={refreshing}
  105. loadingLabel={t('refreshing')}
  106. >
  107. {t('refresh')}
  108. </OLButton>
  109. )
  110. }