Improve handling of doc:saved events (#12522)

GitOrigin-RevId: 0ebf198548f6aeecb356405b0c582d3fd64db391
This commit is contained in:
Alf Eaton 2023-04-14 09:56:24 +01:00 committed by Copybot
parent a8ed6b65e1
commit 39df55787c
5 changed files with 62 additions and 12 deletions

View file

@ -20,7 +20,11 @@ export const startCompileKeypress = event => {
}
}
export default function useCompileTriggers(startCompile, setChangedAt) {
export default function useCompileTriggers(
startCompile,
setChangedAt,
setSavedAt
) {
const handleKeyDown = useCallback(
event => {
if (startCompileKeypress(event)) {
@ -54,5 +58,16 @@ export default function useCompileTriggers(startCompile, setChangedAt) {
setOrTriggerChangedAt(Date.now())
}, [setOrTriggerChangedAt])
useEventListener('doc:changed', setChangedAtHandler)
useEventListener('doc:saved', setChangedAtHandler) // TODO: store this separately?
// record when the server acknowledges saving changes
const setOrTriggerSavedAt = useDetachAction(
'set-saved-at',
setSavedAt,
'detacher',
'detached'
)
const setSavedAtHandler = useCallback(() => {
setOrTriggerSavedAt(Date.now())
}, [setOrTriggerSavedAt])
useEventListener('doc:saved', setSavedAtHandler)
}

View file

@ -20,6 +20,7 @@ export default class DocumentCompiler {
projectId,
rootDocId,
setChangedAt,
setSavedAt,
setCompiling,
setData,
setFirstRenderDone,
@ -32,6 +33,7 @@ export default class DocumentCompiler {
this.projectId = projectId
this.rootDocId = rootDocId
this.setChangedAt = setChangedAt
this.setSavedAt = setSavedAt
this.setCompiling = setCompiling
this.setData = setData
this.setFirstRenderDone = setFirstRenderDone
@ -83,6 +85,7 @@ export default class DocumentCompiler {
try {
// reset values
this.setChangedAt(0) // TODO: wait for doc:saved?
this.setSavedAt(0)
this.validationIssues = undefined
window.dispatchEvent(new CustomEvent('flush-changes')) // TODO: wait for this?

View file

@ -56,7 +56,8 @@ function useCodeMirrorScope(view: EditorView) {
// set up scope listeners
const { logEntryAnnotations, uncompiled, compiling } = useCompileContext()
const { logEntryAnnotations, editedSinceCompileStarted, compiling } =
useCompileContext()
const [loadingThreads] = useScopeValue<boolean>('loadingThreads')
@ -394,7 +395,7 @@ function useCodeMirrorScope(view: EditorView) {
// the project "changed at" date is reset at the start of the compile, i.e. "the project hasn't changed",
// but we don't want to display the compile log diagnostics from the previous compile.
const enableCompileLogLinter =
!syntaxValidation || (!uncompiled && !compiling)
!syntaxValidation || (!editedSinceCompileStarted && !compiling)
// store enableCompileLogLinter in a ref for use in useEffect
const enableCompileLogLinterRef = useRef(enableCompileLogLinter)

View file

@ -30,6 +30,7 @@ export function DetachCompileProvider({ children }) {
compiling: _compiling,
deliveryLatencies: _deliveryLatencies,
draft: _draft,
editedSinceCompileStarted: _editedSinceCompileStarted,
error: _error,
fileList: _fileList,
forceNewDomainVariant: _forceNewDomainVariant,
@ -69,6 +70,7 @@ export function DetachCompileProvider({ children }) {
startCompile: _startCompile,
stopCompile: _stopCompile,
setChangedAt: _setChangedAt,
setSavedAt: _setSavedAt,
clearCache: _clearCache,
} = localCompileContext
@ -224,6 +226,12 @@ export function DetachCompileProvider({ children }) {
'detacher',
'detached'
)
const [editedSinceCompileStarted] = useDetachStateWatcher(
'editedSinceCompileStarted',
_editedSinceCompileStarted,
'detacher',
'detached'
)
const [validationIssues] = useDetachStateWatcher(
'validationIssues',
_validationIssues,
@ -345,6 +353,12 @@ export function DetachCompileProvider({ children }) {
'detached',
'detacher'
)
const setSavedAt = useDetachAction(
'setSavedAt',
_setSavedAt,
'detached',
'detacher'
)
const clearCache = useDetachAction(
'clearCache',
_clearCache,
@ -352,7 +366,7 @@ export function DetachCompileProvider({ children }) {
'detacher'
)
useCompileTriggers(startCompile, setChangedAt)
useCompileTriggers(startCompile, setChangedAt, setSavedAt)
useEffect(() => {
// Sync the split test variant across the editor and pdf-detach.
const variants = getMeta('ol-splitTestVariants') || {}
@ -370,6 +384,7 @@ export function DetachCompileProvider({ children }) {
compiling,
deliveryLatencies,
draft,
editedSinceCompileStarted,
error,
fileList,
forceNewDomainVariant,
@ -423,6 +438,7 @@ export function DetachCompileProvider({ children }) {
deliveryLatencies,
draft,
error,
editedSinceCompileStarted,
fileList,
forceNewDomainVariant,
hasChanges,

View file

@ -123,9 +123,13 @@ export function LocalCompileProvider({ children }) {
setPdfUrl(pdfFile?.pdfUrl)
}, [pdfFile, setPdfDownloadUrl, setPdfUrl])
// the project is considered to be "uncompiled" if a doc has changed since the last compile started
// the project is considered to be "uncompiled" if a doc has changed, or finished saving, since the last compile started.
const [uncompiled, setUncompiled] = useScopeValue('pdf.uncompiled')
// whether a doc has been edited since the last compile started
const [editedSinceCompileStarted, setEditedSinceCompileStarted] =
useState(false)
// the id of the CLSI server which ran the compile
const [clsiServerId, setClsiServerId] = useState()
@ -223,9 +227,12 @@ export function LocalCompileProvider({ children }) {
// whether syntax validation is enabled globally
const [syntaxValidation] = useScopeValue('settings.syntaxValidation')
// the timestamp that a doc was last changed or saved
// the timestamp that a doc was last changed
const [changedAt, setChangedAt] = useState(0)
// the timestamp that a doc was last saved
const [savedAt, setSavedAt] = useState(0)
const { signal } = useAbortController()
const cleanupCompileResult = useCallback(() => {
@ -246,6 +253,7 @@ export function LocalCompileProvider({ children }) {
projectId,
rootDocId,
setChangedAt,
setSavedAt,
setCompiling,
setData,
setFirstRenderDone,
@ -272,10 +280,13 @@ export function LocalCompileProvider({ children }) {
compiler.setOption('stopOnFirstError', stopOnFirstError)
}, [compiler, stopOnFirstError])
// pass the "uncompiled" value up into the scope for use outside this context provider
useEffect(() => {
setUncompiled(changedAt > 0)
}, [setUncompiled, changedAt])
setUncompiled(changedAt > 0 || savedAt > 0)
}, [setUncompiled, changedAt, savedAt])
useEffect(() => {
setEditedSinceCompileStarted(changedAt > 0)
}, [setEditedSinceCompileStarted, changedAt])
// always compile the PDF once after opening the project, after the doc has loaded
useEffect(() => {
@ -468,13 +479,13 @@ export function LocalCompileProvider({ children }) {
// call the debounced autocompile function if the project is available for auto-compiling and it has changed
useEffect(() => {
if (canAutoCompile) {
if (changedAt > 0) {
if (changedAt > 0 || savedAt > 0) {
compiler.debouncedAutoCompile()
}
} else {
compiler.debouncedAutoCompile.cancel()
}
}, [compiler, canAutoCompile, changedAt])
}, [compiler, canAutoCompile, changedAt, savedAt])
// cancel debounced recompile on unmount
useEffect(() => {
@ -533,6 +544,7 @@ export function LocalCompileProvider({ children }) {
compiling,
deliveryLatencies,
draft,
editedSinceCompileStarted,
error,
fileList,
forceNewDomainVariant,
@ -573,6 +585,7 @@ export function LocalCompileProvider({ children }) {
validationIssues,
firstRenderDone,
setChangedAt,
setSavedAt,
cleanupCompileResult,
}),
[
@ -585,6 +598,7 @@ export function LocalCompileProvider({ children }) {
compiling,
deliveryLatencies,
draft,
editedSinceCompileStarted,
error,
fileList,
forceNewDomainVariant,
@ -620,6 +634,7 @@ export function LocalCompileProvider({ children }) {
validationIssues,
firstRenderDone,
setChangedAt,
setSavedAt,
cleanupCompileResult,
setShowLogs,
toggleLogs,