auto-select-file.ts 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. import _ from 'lodash'
  2. import type { Nullable } from '../../../../../types/utils'
  3. import type { HistoryContextValue } from '../context/types/history-context-value'
  4. import type { FileDiff } from '../services/types/file'
  5. import type { DiffOperation } from '../services/types/diff-operation'
  6. import type { Update } from '../services/types/update'
  7. function selectFile(
  8. file: Nullable<FileDiff>,
  9. selection: HistoryContextValue['selection']
  10. ) {
  11. if (file === null) {
  12. return selection
  13. }
  14. const newSelection = {
  15. ...selection,
  16. pathname: file.pathname,
  17. file,
  18. }
  19. return newSelection
  20. }
  21. function getUpdateForVersion(
  22. version: Update['toV'],
  23. updates: HistoryContextValue['updates']
  24. ): Nullable<Update> {
  25. return updates.filter(update => update.toV === version)?.[0] ?? null
  26. }
  27. type FileWithOps = {
  28. pathname: FileDiff['pathname']
  29. operation: DiffOperation
  30. }
  31. function getFilesWithOps(
  32. viewMode: HistoryContextValue['viewMode'],
  33. selection: HistoryContextValue['selection'],
  34. updates: HistoryContextValue['updates']
  35. ): FileWithOps[] {
  36. if (selection.range.toV && viewMode === 'point_in_time') {
  37. const filesWithOps: FileWithOps[] = []
  38. const currentUpdate = getUpdateForVersion(selection.range.toV, updates)
  39. if (currentUpdate !== null) {
  40. for (const pathname of currentUpdate.pathnames) {
  41. filesWithOps.push({
  42. pathname,
  43. operation: 'edited',
  44. })
  45. }
  46. for (const op of currentUpdate.project_ops) {
  47. let fileWithOps: Nullable<FileWithOps> = null
  48. if (op.add) {
  49. fileWithOps = {
  50. pathname: op.add.pathname,
  51. operation: 'added',
  52. }
  53. } else if (op.remove) {
  54. fileWithOps = {
  55. pathname: op.remove.pathname,
  56. operation: 'removed',
  57. }
  58. } else if (op.rename) {
  59. fileWithOps = {
  60. pathname: op.rename.newPathname,
  61. operation: 'renamed',
  62. }
  63. }
  64. if (fileWithOps !== null) {
  65. filesWithOps.push(fileWithOps)
  66. }
  67. }
  68. }
  69. return filesWithOps
  70. } else {
  71. const filesWithOps = _.reduce(
  72. selection.files,
  73. (curFilesWithOps, file) => {
  74. if ('operation' in file) {
  75. curFilesWithOps.push({
  76. pathname: file.pathname,
  77. operation: file.operation,
  78. })
  79. }
  80. return curFilesWithOps
  81. },
  82. <FileWithOps[]>[]
  83. )
  84. return filesWithOps
  85. }
  86. }
  87. const orderedOpTypes: DiffOperation[] = [
  88. 'edited',
  89. 'added',
  90. 'renamed',
  91. 'removed',
  92. ]
  93. export function autoSelectFile(
  94. files: FileDiff[],
  95. selection: HistoryContextValue['selection'],
  96. viewMode: HistoryContextValue['viewMode'],
  97. updates: HistoryContextValue['updates']
  98. ) {
  99. let fileToSelect: Nullable<FileDiff> = null
  100. const filesWithOps = getFilesWithOps(viewMode, selection, updates)
  101. for (const opType of orderedOpTypes) {
  102. const fileWithMatchingOpType = _.find(filesWithOps, {
  103. operation: opType,
  104. })
  105. if (fileWithMatchingOpType != null) {
  106. fileToSelect =
  107. _.find(files, {
  108. pathname: fileWithMatchingOpType.pathname,
  109. }) ?? null
  110. break
  111. }
  112. }
  113. if (!fileToSelect) {
  114. const mainFile = _.find(files, function (file) {
  115. return /main\.tex$/.test(file.pathname)
  116. })
  117. if (mainFile) {
  118. fileToSelect = mainFile
  119. } else {
  120. const anyTeXFile = _.find(files, function (file) {
  121. return /\.tex$/.test(file.pathname)
  122. })
  123. if (anyTeXFile) {
  124. fileToSelect = anyTeXFile
  125. } else {
  126. fileToSelect = files[0]
  127. }
  128. }
  129. }
  130. return selectFile(fileToSelect, selection)
  131. }