diff-view.tsx 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. import { useEffect, useMemo } from 'react'
  2. import Toolbar from './toolbar/toolbar'
  3. import Main from './main'
  4. import { Diff, DocDiffResponse } from '../../services/types/doc'
  5. import { useHistoryContext } from '../../context/history-context'
  6. import { diffDoc } from '../../services/api'
  7. import { highlightsFromDiffResponse } from '../../utils/highlights-from-diff-response'
  8. import { useErrorBoundary } from 'react-error-boundary'
  9. import useAsync from '../../../../shared/hooks/use-async'
  10. import { useTranslation } from 'react-i18next'
  11. function DiffView() {
  12. const { selection, projectId, loadingFileDiffs, updatesInfo } =
  13. useHistoryContext()
  14. const { isLoading, data, runAsync } = useAsync<DocDiffResponse>()
  15. const { t } = useTranslation()
  16. const { updateRange, selectedFile } = selection
  17. const { showBoundary } = useErrorBoundary()
  18. const isCurrentVersion =
  19. !!updateRange && updatesInfo.updates[0].toV === updateRange.toV
  20. useEffect(() => {
  21. if (!updateRange || !selectedFile?.pathname || loadingFileDiffs) {
  22. return
  23. }
  24. const { fromV, toV } = updateRange
  25. let abortController: AbortController | null = new AbortController()
  26. runAsync(
  27. diffDoc(
  28. projectId,
  29. fromV,
  30. toV,
  31. selectedFile.pathname,
  32. abortController.signal
  33. )
  34. )
  35. .catch(showBoundary)
  36. .finally(() => {
  37. abortController = null
  38. })
  39. // Abort an existing request before starting a new one or on unmount
  40. return () => {
  41. if (abortController) {
  42. abortController.abort()
  43. }
  44. }
  45. }, [
  46. projectId,
  47. runAsync,
  48. updateRange,
  49. selectedFile,
  50. loadingFileDiffs,
  51. showBoundary,
  52. ])
  53. const diff = useMemo(() => {
  54. let diff: Diff | null
  55. if (!data?.diff) {
  56. diff = null
  57. } else if ('binary' in data.diff) {
  58. diff = { binary: true }
  59. } else {
  60. diff = {
  61. binary: false,
  62. docDiff: highlightsFromDiffResponse(data.diff, t),
  63. }
  64. }
  65. return diff
  66. }, [data, t])
  67. return (
  68. <div className="doc-panel">
  69. <div className="history-header toolbar-container">
  70. <Toolbar
  71. diff={diff}
  72. selection={selection}
  73. isCurrentVersion={isCurrentVersion}
  74. />
  75. </div>
  76. <div className="doc-container">
  77. <Main diff={diff} isLoading={isLoading || loadingFileDiffs} />
  78. </div>
  79. </div>
  80. )
  81. }
  82. export default DiffView