Skip to content

Commit e746625

Browse files
committed
enh(sync): recover automatically from outdated / renamed doc
If no changes have been made offline clear the indexedDb cache and reload Editor.vue to load the latest editing session from the server. Signed-off-by: Max <[email protected]>
1 parent 384132d commit e746625

File tree

4 files changed

+46
-4
lines changed

4 files changed

+46
-4
lines changed

src/components/Editor.vue

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ export default defineComponent({
232232
})
233233
const ydoc = new Doc()
234234
const awareness = new Awareness(ydoc)
235-
const { dirty, getBaseVersionEtag, setBaseVersionEtag } =
235+
const { dirty, getBaseVersionEtag, setBaseVersionEtag, clearIndexedDb } =
236236
useIndexedDbProvider(props, ydoc)
237237
238238
const hasConnectionIssue = ref(false)
@@ -286,6 +286,7 @@ export default defineComponent({
286286
287287
return {
288288
awareness,
289+
clearIndexedDb,
289290
connection,
290291
dirty,
291292
editor,
@@ -341,6 +342,13 @@ export default defineComponent({
341342
hasDocumentParameters() {
342343
return this.fileId || this.shareToken || this.initialSession
343344
},
345+
hasOutdatedDocument() {
346+
return (
347+
this.syncError
348+
&& this.syncError.type === ERROR_TYPE.LOAD_ERROR
349+
&& this.syncError.data.status === 412
350+
)
351+
},
344352
currentDirectory() {
345353
return this.relativePath
346354
? this.relativePath.split('/').slice(0, -1).join('/')
@@ -395,6 +403,18 @@ export default defineComponent({
395403
}
396404
this.setEditable(!val)
397405
},
406+
hasOutdatedDocument(val) {
407+
if (!val) {
408+
return
409+
}
410+
if (this.dirty) {
411+
// handle conflict between active editing session and offline content
412+
} else {
413+
// clear the outdated cached content and reload without it.
414+
this.clearIndexedDb()
415+
this.emit('reload')
416+
}
417+
},
398418
},
399419
mounted() {
400420
if (!this.richWorkspace) {

src/components/ViewerComponent.vue

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,16 @@
55

66
<template>
77
<Editor
8-
v-if="!useSourceView"
8+
v-if="!useSourceView && !reloading"
99
:file-id="fileid"
1010
:relative-path="filename"
1111
:active="active || isEmbedded"
1212
:autofocus="autofocus"
1313
:share-token="shareToken"
1414
:class="{ 'text-editor--embedding': isEmbedded }"
1515
:mime="mime"
16-
:show-outline-outside="showOutlineOutside" />
16+
:show-outline-outside="showOutlineOutside"
17+
@reload="reloading = true" />
1718
<div
1819
v-else
1920
id="editor-container"
@@ -107,6 +108,7 @@ export default {
107108
return {
108109
content: '',
109110
hasToggledInteractiveEmbedding: false,
111+
reloading: false,
110112
}
111113
},
112114
computed: {
@@ -142,6 +144,13 @@ export default {
142144
source() {
143145
this.loadFileContent()
144146
},
147+
reloading(val) {
148+
if (val) {
149+
this.$nextTick(() => {
150+
this.reloading = false
151+
})
152+
}
153+
},
145154
},
146155
147156
mounted() {

src/composables/useConnection.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,11 @@ function openInitialSession(
106106
throw new Error(
107107
'Base version etag did not match when opening initial session.',
108108
)
109-
// In order to handle this properly we'd need to:
109+
// We need to handle dirty documents differently from 'clean' ones.
110+
// For clean ones we need to
111+
// * call .clearData() on the provider
112+
// * reinitialize the editing session - maybe by reloading the component.
113+
// In order to handle the dirty state - i.e. a conflict properly we'd need to:
110114
// * fetch the file content.
111115
// * throw the same exception as a 409 response.
112116
// * include the file content as `outsideChange` in the error.

src/composables/useIndexedDbProvider.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,16 @@ export function useIndexedDbProvider(
4848
return indexedDbProvider.set('baseVersionEtag', val)
4949
}
5050

51+
/**
52+
* Clear the current document from indexed db.
53+
* Used to reset the browser state to load a new editing session.
54+
*/
55+
function clearIndexedDb() {
56+
return indexedDbProvider.clearData()
57+
}
58+
5159
return {
60+
clearIndexedDb,
5261
dirty,
5362
getBaseVersionEtag,
5463
setBaseVersionEtag,

0 commit comments

Comments
 (0)