auto-select-file.ts 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. import type { Nullable } from '../../../../../types/utils'
  2. import type { FileDiff } from '../services/types/file'
  3. import type { FileOperation } from '../services/types/file-operation'
  4. import type { LoadedUpdate, Version } from '../services/types/update'
  5. import type { Selection } from '../services/types/selection'
  6. import { fileFinalPathname, isFileEditable } from './file-diff'
  7. type FileWithOps = {
  8. pathname: FileDiff['pathname']
  9. editable: boolean
  10. operation: FileOperation
  11. }
  12. function getFilesWithOps(
  13. files: FileDiff[],
  14. toV: Version,
  15. comparing: boolean,
  16. updateForToV: LoadedUpdate | undefined
  17. ): FileWithOps[] {
  18. if (toV && !comparing) {
  19. const filesWithOps: FileWithOps[] = []
  20. if (updateForToV) {
  21. const filesByPathname = new Map<string, FileDiff>()
  22. for (const file of files) {
  23. const pathname = fileFinalPathname(file)
  24. filesByPathname.set(pathname, file)
  25. }
  26. const isEditable = (pathname: string) => {
  27. const fileDiff = filesByPathname.get(pathname)
  28. if (!fileDiff) {
  29. return false
  30. }
  31. return isFileEditable(fileDiff)
  32. }
  33. for (const pathname of updateForToV.pathnames) {
  34. filesWithOps.push({
  35. pathname,
  36. editable: isEditable(pathname),
  37. operation: 'edited',
  38. })
  39. }
  40. for (const op of updateForToV.project_ops) {
  41. let pathAndOp: Nullable<Pick<FileWithOps, 'pathname' | 'operation'>> =
  42. null
  43. if (op.add) {
  44. pathAndOp = {
  45. pathname: op.add.pathname,
  46. operation: 'added',
  47. }
  48. } else if (op.remove) {
  49. pathAndOp = {
  50. pathname: op.remove.pathname,
  51. operation: 'removed',
  52. }
  53. } else if (op.rename) {
  54. pathAndOp = {
  55. pathname: op.rename.newPathname,
  56. operation: 'renamed',
  57. }
  58. }
  59. if (pathAndOp !== null) {
  60. filesWithOps.push({
  61. editable: isEditable(pathAndOp.pathname),
  62. ...pathAndOp,
  63. })
  64. }
  65. }
  66. }
  67. return filesWithOps
  68. } else {
  69. const filesWithOps = files.reduce(
  70. (curFilesWithOps, file) => {
  71. if ('operation' in file) {
  72. curFilesWithOps.push({
  73. pathname: file.pathname,
  74. editable: isFileEditable(file),
  75. operation: file.operation,
  76. })
  77. }
  78. return curFilesWithOps
  79. },
  80. <FileWithOps[]>[]
  81. )
  82. return filesWithOps
  83. }
  84. }
  85. const orderedOpTypes: FileOperation[] = [
  86. 'edited',
  87. 'added',
  88. 'renamed',
  89. 'removed',
  90. ]
  91. export function autoSelectFile(
  92. files: FileDiff[],
  93. toV: Version,
  94. comparing: boolean,
  95. updateForToV: LoadedUpdate | undefined,
  96. previouslySelectedPathname: Selection['previouslySelectedPathname']
  97. ): FileDiff {
  98. const filesWithOps = getFilesWithOps(files, toV, comparing, updateForToV)
  99. const previouslySelectedFile = files.find(file => {
  100. return file.pathname === previouslySelectedPathname
  101. })
  102. const previouslySelectedFileHasOp = filesWithOps.some(file => {
  103. return file.pathname === previouslySelectedPathname
  104. })
  105. if (previouslySelectedFile && previouslySelectedFileHasOp) {
  106. return previouslySelectedFile
  107. }
  108. for (const opType of orderedOpTypes) {
  109. const fileWithMatchingOpType = filesWithOps.find(
  110. file => file.operation === opType && file.editable
  111. )
  112. if (fileWithMatchingOpType) {
  113. const fileToSelect = files.find(
  114. file => fileFinalPathname(file) === fileWithMatchingOpType.pathname
  115. )
  116. if (fileToSelect) {
  117. return fileToSelect
  118. }
  119. }
  120. }
  121. return (
  122. previouslySelectedFile ||
  123. files.find(file => /main\.tex$/.test(file.pathname)) ||
  124. files.find(file => /\.tex$/.test(file.pathname)) ||
  125. files[0]
  126. )
  127. }