Merge pull request #13146 from overleaf/ii-history-react-save-last-selected-file-in-local-storage

[web] Save lastly selected file in the file tree

GitOrigin-RevId: 4b4dcdcb1340e253d4cd2003280f67385975d664
This commit is contained in:
ilkin-overleaf 2023-05-30 13:15:38 +03:00 committed by Copybot
parent 9fd9e991a7
commit bb815268f2
11 changed files with 89 additions and 32 deletions

View file

@ -26,8 +26,8 @@ else
minimum-restore-size-west="130"
custom-toggler-pane=hasFeature('custom-togglers') ? "west" : false
custom-toggler-msg-when-open=hasFeature('custom-togglers') ? translate("tooltip_hide_filetree") : false
custom-toggler-msg-when-closed=hasFeature('custom-togglers') ? translate("tooltip_show_filetree") : false
tabindex="0"
custom-toggler-msg-when-closed=hasFeature('custom-togglers') ? translate("tooltip_show_filetree") : false
tabindex="0"
initial-size-east="250"
init-closed-east="true"
open-east="ui.chatOpen"
@ -44,9 +44,7 @@ else
include ./editor
if (historyViewReact)
history-root(
ng-if="ui.view == 'history'"
)
history-root()
else
include ./history

View file

@ -24,11 +24,12 @@ function Compare({
e.stopPropagation()
closeDropdown()
setSelection({
setSelection(({ previouslySelectedPathname }) => ({
updateRange: comparisonRange,
comparing: true,
files: [],
})
previouslySelectedPathname,
}))
}
return (

View file

@ -21,11 +21,12 @@ function HistoryVersionDetails({
const handleSelect = (e: MouseEvent<HTMLDivElement>) => {
const target = e.target as HTMLElement
if (!target.closest('.dropdown') && e.currentTarget.contains(target)) {
setSelection({
setSelection(({ previouslySelectedPathname }) => ({
updateRange,
comparing: false,
files: [],
})
previouslySelectedPathname,
}))
}
}

View file

@ -46,11 +46,12 @@ function ToggleSwitch({ labelsOnly, setLabelsOnly }: ToggleSwitchProps) {
updateRange
)
setSelection({
setSelection(({ previouslySelectedPathname }) => ({
updateRange: range,
comparing: false,
files: [],
})
previouslySelectedPathname,
}))
}
}
}

View file

@ -30,6 +30,7 @@ function HistoryFileTreeFolderList({
return {
...prevSelection,
selectedFile: file,
previouslySelectedPathname: file.pathname,
}
}

View file

@ -1,6 +1,7 @@
import ChangeList from './change-list/change-list'
import DiffView from './diff-view/diff-view'
import { HistoryProvider, useHistoryContext } from '../context/history-context'
import { useLayoutContext } from '../../../shared/context/layout-context'
import { createPortal } from 'react-dom'
import HistoryFileTree from './history-file-tree'
import LoadingSpinner from '../../../shared/components/loading-spinner'
@ -10,8 +11,13 @@ import withErrorBoundary from '../../../infrastructure/error-boundary'
const fileTreeContainer = document.getElementById('history-file-tree')
function Main() {
const { view } = useLayoutContext()
const { updatesInfo } = useHistoryContext()
if (view !== 'history') {
return null
}
let content
if (updatesInfo.loadingState === 'loadingInitial') {
content = <LoadingSpinner />

View file

@ -63,6 +63,16 @@ const selectionInitialState: Selection = {
updateRange: null,
comparing: false,
files: [],
previouslySelectedPathname: null,
}
const updatesInfoInitialState: HistoryContextValue['updatesInfo'] = {
updates: [],
visibleUpdateCount: null,
atEnd: false,
freeHistoryLimitHit: false,
nextBeforeTimestamp: undefined,
loadingState: 'loadingInitial',
}
function useHistory() {
@ -81,14 +91,7 @@ function useHistory() {
const [updatesInfo, setUpdatesInfo] = useState<
HistoryContextValue['updatesInfo']
>({
updates: [],
visibleUpdateCount: null,
atEnd: false,
freeHistoryLimitHit: false,
nextBeforeTimestamp: undefined,
loadingState: 'loadingInitial',
})
>(updatesInfoInitialState)
const [labels, setLabels] = useState<HistoryContextValue['labels']>(null)
const [labelsOnly, setLabelsOnly] = usePersistedState(
`history.userPrefs.showOnlyLabels.${projectId}`,
@ -220,6 +223,20 @@ function useHistory() {
}
}, [view, fetchNextBatchOfUpdates])
useEffect(() => {
// Reset some parts of the state
if (view !== 'history') {
initialFetch.current = false
setSelection(prevSelection => ({
...selectionInitialState,
// retain the previously selected pathname
previouslySelectedPathname: prevSelection.previouslySelectedPathname,
}))
setUpdatesInfo(updatesInfoInitialState)
setLabels(null)
}
}, [view])
const resetSelection = useCallback(() => {
setSelection(selectionInitialState)
}, [])
@ -249,7 +266,8 @@ function useHistory() {
files,
toV,
previousSelection.comparing,
updateForToV
updateForToV,
previousSelection.previouslySelectedPathname
)
const newFiles = files.map(file => {
if (isFileRenamed(file) && file.newPathname) {
@ -258,7 +276,12 @@ function useHistory() {
return file
})
return { ...previousSelection, files: newFiles, selectedFile }
return {
...previousSelection,
files: newFiles,
selectedFile,
previouslySelectedPathname: selectedFile.pathname,
}
})
})
.catch(handleError)
@ -277,7 +300,8 @@ function useHistory() {
useEffect(() => {
// Set update range if there isn't one and updates have loaded
if (updates.length && !updateRange) {
setSelection({
setSelection(prevSelection => ({
...prevSelection,
updateRange: {
fromV: updates[0].fromV,
toV: updates[0].toV,
@ -286,7 +310,7 @@ function useHistory() {
},
comparing: false,
files: [],
})
}))
}
}, [updateRange, updates])

View file

@ -1,9 +1,11 @@
import { FileDiff } from './file'
import { FileDiff, FileUnchanged } from './file'
import { UpdateRange } from './update'
import { Nullable } from '../../../../../../types/utils'
export interface Selection {
updateRange: UpdateRange | null
comparing: boolean
files: FileDiff[]
selectedFile?: FileDiff
previouslySelectedPathname: Nullable<FileUnchanged['pathname']>
}

View file

@ -2,6 +2,7 @@ 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 = {
@ -100,9 +101,21 @@ export function autoSelectFile(
files: FileDiff[],
toV: Version,
comparing: boolean,
updateForToV: LoadedUpdate | undefined
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
@ -119,6 +132,7 @@ export function autoSelectFile(
}
return (
previouslySelectedFile ||
files.find(file => /main\.tex$/.test(file.pathname)) ||
files.find(file => /\.tex$/.test(file.pathname)) ||
files[0]

View file

@ -54,6 +54,7 @@ describe('history toolbar', function () {
pathname: 'main.tex',
editable: true,
},
previouslySelectedPathname: null,
}
cy.mount(
@ -103,6 +104,7 @@ describe('history toolbar', function () {
pathname: 'main.tex',
editable: true,
},
previouslySelectedPathname: null,
}
cy.mount(

View file

@ -270,7 +270,8 @@ describe('autoSelectFile', function () {
files,
updates[0].toV,
comparing,
getUpdateForVersion(updates[0].toV, updates)
getUpdateForVersion(updates[0].toV, updates),
null
)
expect(pathname).to.equal('newfolder1/newfile10.tex')
@ -344,7 +345,8 @@ describe('autoSelectFile', function () {
files,
updates[0].toV,
comparing,
getUpdateForVersion(updates[0].toV, updates)
getUpdateForVersion(updates[0].toV, updates),
null
)
expect(pathname).to.equal('newfile1.tex')
@ -449,7 +451,8 @@ describe('autoSelectFile', function () {
files,
updates[0].toV,
comparing,
getUpdateForVersion(updates[0].toV, updates)
getUpdateForVersion(updates[0].toV, updates),
null
)
expect(pathname).to.equal('main3.tex')
@ -624,7 +627,8 @@ describe('autoSelectFile', function () {
files,
updates[0].toV,
comparing,
getUpdateForVersion(updates[0].toV, updates)
getUpdateForVersion(updates[0].toV, updates),
null
)
expect(pathname).to.equal('main.tex')
@ -735,7 +739,8 @@ describe('autoSelectFile', function () {
files,
updates[0].toV,
comparing,
getUpdateForVersion(updates[0].toV, updates)
getUpdateForVersion(updates[0].toV, updates),
null
)
expect(pathname).to.equal('certainly_not_main.tex')
@ -808,7 +813,8 @@ describe('autoSelectFile', function () {
files,
updates[0].toV,
comparing,
getUpdateForVersion(updates[0].toV, updates)
getUpdateForVersion(updates[0].toV, updates),
null
)
)
@ -883,7 +889,8 @@ describe('autoSelectFile', function () {
files,
updates[0].toV,
comparing,
getUpdateForVersion(updates[0].toV, updates)
getUpdateForVersion(updates[0].toV, updates),
null
)
expect(pathname).to.equal('main.tex')