mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-30 17:53:37 -05:00
bb815268f2
[web] Save lastly selected file in the file tree GitOrigin-RevId: 4b4dcdcb1340e253d4cd2003280f67385975d664
140 lines
3.7 KiB
TypeScript
140 lines
3.7 KiB
TypeScript
import type { Nullable } from '../../../../../types/utils'
|
|
import type { FileDiff } from '../services/types/file'
|
|
import type { FileOperation } from '../services/types/file-operation'
|
|
import type { LoadedUpdate, Version } from '../services/types/update'
|
|
import type { Selection } from '../services/types/selection'
|
|
import { fileFinalPathname, isFileEditable } from './file-diff'
|
|
|
|
type FileWithOps = {
|
|
pathname: FileDiff['pathname']
|
|
editable: boolean
|
|
operation: FileOperation
|
|
}
|
|
|
|
function getFilesWithOps(
|
|
files: FileDiff[],
|
|
toV: Version,
|
|
comparing: boolean,
|
|
updateForToV: LoadedUpdate | undefined
|
|
): FileWithOps[] {
|
|
if (toV && !comparing) {
|
|
const filesWithOps: FileWithOps[] = []
|
|
|
|
if (updateForToV) {
|
|
const filesByPathname = new Map<string, FileDiff>()
|
|
for (const file of files) {
|
|
const pathname = fileFinalPathname(file)
|
|
filesByPathname.set(pathname, file)
|
|
}
|
|
|
|
const isEditable = (pathname: string) => {
|
|
const fileDiff = filesByPathname.get(pathname)
|
|
if (!fileDiff) {
|
|
return false
|
|
}
|
|
return isFileEditable(fileDiff)
|
|
}
|
|
|
|
for (const pathname of updateForToV.pathnames) {
|
|
filesWithOps.push({
|
|
pathname,
|
|
editable: isEditable(pathname),
|
|
operation: 'edited',
|
|
})
|
|
}
|
|
|
|
for (const op of updateForToV.project_ops) {
|
|
let pathAndOp: Nullable<Pick<FileWithOps, 'pathname' | 'operation'>> =
|
|
null
|
|
|
|
if (op.add) {
|
|
pathAndOp = {
|
|
pathname: op.add.pathname,
|
|
operation: 'added',
|
|
}
|
|
} else if (op.remove) {
|
|
pathAndOp = {
|
|
pathname: op.remove.pathname,
|
|
operation: 'removed',
|
|
}
|
|
} else if (op.rename) {
|
|
pathAndOp = {
|
|
pathname: op.rename.newPathname,
|
|
operation: 'renamed',
|
|
}
|
|
}
|
|
|
|
if (pathAndOp !== null) {
|
|
filesWithOps.push({
|
|
editable: isEditable(pathAndOp.pathname),
|
|
...pathAndOp,
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
return filesWithOps
|
|
} else {
|
|
const filesWithOps = files.reduce((curFilesWithOps, file) => {
|
|
if ('operation' in file) {
|
|
curFilesWithOps.push({
|
|
pathname: file.pathname,
|
|
editable: isFileEditable(file),
|
|
operation: file.operation,
|
|
})
|
|
}
|
|
return curFilesWithOps
|
|
}, <FileWithOps[]>[])
|
|
|
|
return filesWithOps
|
|
}
|
|
}
|
|
|
|
const orderedOpTypes: FileOperation[] = [
|
|
'edited',
|
|
'added',
|
|
'renamed',
|
|
'removed',
|
|
]
|
|
|
|
export function autoSelectFile(
|
|
files: FileDiff[],
|
|
toV: Version,
|
|
comparing: boolean,
|
|
updateForToV: LoadedUpdate | undefined,
|
|
previouslySelectedPathname: Selection['previouslySelectedPathname']
|
|
): FileDiff {
|
|
const filesWithOps = getFilesWithOps(files, toV, comparing, updateForToV)
|
|
const previouslySelectedFile = files.find(file => {
|
|
return file.pathname === previouslySelectedPathname
|
|
})
|
|
const previouslySelectedFileHasOp = filesWithOps.some(file => {
|
|
return file.pathname === previouslySelectedPathname
|
|
})
|
|
|
|
if (previouslySelectedFile && previouslySelectedFileHasOp) {
|
|
return previouslySelectedFile
|
|
}
|
|
|
|
for (const opType of orderedOpTypes) {
|
|
const fileWithMatchingOpType = filesWithOps.find(
|
|
file => file.operation === opType && file.editable
|
|
)
|
|
|
|
if (fileWithMatchingOpType) {
|
|
const fileToSelect = files.find(
|
|
file => fileFinalPathname(file) === fileWithMatchingOpType.pathname
|
|
)
|
|
if (fileToSelect) {
|
|
return fileToSelect
|
|
}
|
|
}
|
|
}
|
|
|
|
return (
|
|
previouslySelectedFile ||
|
|
files.find(file => /main\.tex$/.test(file.pathname)) ||
|
|
files.find(file => /\.tex$/.test(file.pathname)) ||
|
|
files[0]
|
|
)
|
|
}
|