mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-07 20:31:06 -05:00
Merge pull request #18323 from overleaf/mj-editor-loss-debug
[web] DEBUG: Calculate diff size when detecting edit-loss GitOrigin-RevId: 750f7ed91d5ce81beb520e23181a6a8dc22b6078
This commit is contained in:
parent
c1a4e4a873
commit
2ce41e0ee6
3 changed files with 108 additions and 4 deletions
|
@ -11,7 +11,7 @@ import { useGlobalAlertsContainer } from '@/features/ide-react/context/global-al
|
|||
const MAX_UNSAVED_SECONDS = 15 // lock the editor after this time if unsaved
|
||||
|
||||
export const UnsavedDocs: FC = () => {
|
||||
const { openDocs } = useEditorManagerContext()
|
||||
const { openDocs, debugTimers } = useEditorManagerContext()
|
||||
const { permissionsLevel, setPermissionsLevel } = useEditorContext()
|
||||
const [isLocked, setIsLocked] = useState(false)
|
||||
const [unsavedDocs, setUnsavedDocs] = useState(new Map<string, number>())
|
||||
|
@ -47,6 +47,7 @@ export const UnsavedDocs: FC = () => {
|
|||
// NOTE: openDocs should never change, so it's safe to use as a dependency here
|
||||
useEffect(() => {
|
||||
const interval = window.setInterval(() => {
|
||||
debugTimers.current.CheckUnsavedDocs = Date.now()
|
||||
const unsavedDocs = new Map()
|
||||
|
||||
const unsavedDocIds = openDocs.unsavedDocIds()
|
||||
|
@ -67,7 +68,7 @@ export const UnsavedDocs: FC = () => {
|
|||
return () => {
|
||||
window.clearInterval(interval)
|
||||
}
|
||||
}, [openDocs])
|
||||
}, [openDocs, debugTimers])
|
||||
|
||||
const maxUnsavedSeconds = Math.max(0, ...unsavedDocs.values())
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ import useEventListener from '@/shared/hooks/use-event-listener'
|
|||
import { EditorType } from '@/features/ide-react/editor/types/editor-type'
|
||||
import { DocId } from '../../../../../types/project-settings'
|
||||
import { Update } from '@/features/history/services/types/update'
|
||||
import { useDebugDiffTracker } from '../hooks/use-debug-diff-tracker'
|
||||
|
||||
interface GotoOffsetOptions {
|
||||
gotoOffset: number
|
||||
|
@ -60,6 +61,7 @@ export type EditorManager = {
|
|||
setWantTrackChanges: React.Dispatch<
|
||||
React.SetStateAction<EditorManager['wantTrackChanges']>
|
||||
>
|
||||
debugTimers: React.MutableRefObject<Record<string, number>>
|
||||
}
|
||||
|
||||
function hasGotoLine(options: OpenDocOptions): options is GotoLineOptions {
|
||||
|
@ -126,12 +128,32 @@ export const EditorManagerProvider: FC = ({ children }) => {
|
|||
|
||||
const [ignoringExternalUpdates, setIgnoringExternalUpdates] = useState(false)
|
||||
|
||||
const { createDebugDiff, debugTimers } = useDebugDiffTracker(
|
||||
projectId,
|
||||
currentDocument
|
||||
)
|
||||
|
||||
const [globalEditorWatchdogManager] = useState(
|
||||
() =>
|
||||
new EditorWatchdogManager({
|
||||
onTimeoutHandler: (meta: Record<string, any>) => {
|
||||
sendMB('losing-edits', meta)
|
||||
reportError('losing-edits', meta)
|
||||
let diffSize: number | null = null
|
||||
createDebugDiff()
|
||||
.then(calculatedDiffSize => {
|
||||
diffSize = calculatedDiffSize
|
||||
})
|
||||
.finally(() => {
|
||||
sendMB('losing-edits', {
|
||||
...meta,
|
||||
diffSize,
|
||||
timers: debugTimers.current,
|
||||
})
|
||||
reportError('losing-edits', {
|
||||
...meta,
|
||||
diffSize,
|
||||
timers: debugTimers.current,
|
||||
})
|
||||
})
|
||||
},
|
||||
})
|
||||
)
|
||||
|
@ -616,6 +638,7 @@ export const EditorManagerProvider: FC = ({ children }) => {
|
|||
jumpToLine,
|
||||
wantTrackChanges,
|
||||
setWantTrackChanges,
|
||||
debugTimers,
|
||||
}),
|
||||
[
|
||||
getEditorType,
|
||||
|
@ -633,6 +656,7 @@ export const EditorManagerProvider: FC = ({ children }) => {
|
|||
jumpToLine,
|
||||
wantTrackChanges,
|
||||
setWantTrackChanges,
|
||||
debugTimers,
|
||||
]
|
||||
)
|
||||
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
import { useEffect, useMemo, useRef } from 'react'
|
||||
import { DocumentContainer } from '../editor/document-container'
|
||||
import { DocId } from '../../../../../types/project-settings'
|
||||
import { debugConsole } from '@/utils/debugging'
|
||||
import { diffChars } from 'diff'
|
||||
|
||||
const DIFF_TIMEOUT_MS = 5000
|
||||
|
||||
async function tryGetDiffSize(
|
||||
currentContents: string | null | undefined,
|
||||
projectId: string | null,
|
||||
docId: DocId | null | undefined
|
||||
): Promise<number | null> {
|
||||
debugConsole.debug('tryGetDiffSize')
|
||||
// If we don't know the current content or id, there's not much we can do
|
||||
if (!projectId) {
|
||||
debugConsole.debug('tryGetDiffSize: missing projectId')
|
||||
return null
|
||||
}
|
||||
if (!currentContents) {
|
||||
debugConsole.debug('tryGetDiffSize: missing currentContents')
|
||||
return null
|
||||
}
|
||||
if (!docId) {
|
||||
debugConsole.debug('tryGetDiffSize: missing docId')
|
||||
return null
|
||||
}
|
||||
try {
|
||||
const response = await fetch(
|
||||
`/Project/${projectId}/doc/${docId}/download`,
|
||||
{ signal: AbortSignal.timeout(DIFF_TIMEOUT_MS) }
|
||||
)
|
||||
const serverContent = await response.text()
|
||||
|
||||
const differences = diffChars(serverContent, currentContents)
|
||||
let diffSize = 0
|
||||
for (const diff of differences) {
|
||||
if (diff.added || diff.removed) {
|
||||
diffSize += diff.value.length
|
||||
}
|
||||
}
|
||||
return diffSize
|
||||
} catch {
|
||||
// There's a good chance we're offline, so just return null
|
||||
debugConsole.debug('tryGetDiffSize: fetch failed')
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
export const useDebugDiffTracker = (
|
||||
projectId: string,
|
||||
currentDocument: DocumentContainer
|
||||
) => {
|
||||
const debugCurrentDocument = useRef<DocumentContainer | null>(null)
|
||||
const debugProjectId = useRef<string | null>(null)
|
||||
const debugTimers = useRef<Record<string, number>>({})
|
||||
|
||||
useEffect(() => {
|
||||
debugCurrentDocument.current = currentDocument
|
||||
}, [currentDocument])
|
||||
useEffect(() => {
|
||||
debugProjectId.current = projectId
|
||||
}, [projectId])
|
||||
|
||||
const createDebugDiff = useMemo(
|
||||
() => async () =>
|
||||
await tryGetDiffSize(
|
||||
debugCurrentDocument.current?.getSnapshot(),
|
||||
debugProjectId.current,
|
||||
debugCurrentDocument.current?.doc_id as DocId | undefined
|
||||
),
|
||||
[]
|
||||
)
|
||||
|
||||
return {
|
||||
createDebugDiff,
|
||||
debugTimers,
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue