Skip to content

Commit 2c03655

Browse files
committed
fix(Editor): separate close and disconnect functions
* `close` is for closing the editor. It tries to save the document and clean everything up. * `disconnect` is for cleaning up the current collaboration sessions. It will not save the document and asumes the editing will be resumed after a reconnect. Move `sendRemainingSteps` out to the sync service. Also make close in the websocket polyfill sync. Just clean up the polyfills state. Signed-off-by: Max <max@nextcloud.com>
1 parent e993f5f commit 2c03655

File tree

3 files changed

+39
-37
lines changed

3 files changed

+39
-37
lines changed

src/components/Editor.vue

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ export default {
352352
const timeout = new Promise((resolve) => setTimeout(resolve, 2000))
353353
await Promise.any([timeout, this.$syncService.save()])
354354
}
355-
this.$providers.forEach(p => p.destroy())
355+
this.close()
356356
},
357357
methods: {
358358
...mapActions('text', [
@@ -380,8 +380,6 @@ export default {
380380
381381
this.listenSyncServiceEvents()
382382
383-
this.$providers.forEach(p => p?.destroy())
384-
this.$providers = []
385383
const syncServiceProvider = createSyncServiceProvider({
386384
ydoc: this.$ydoc,
387385
syncService: this.$syncService,
@@ -429,7 +427,7 @@ export default {
429427
reconnect() {
430428
this.contentLoaded = false
431429
this.hasConnectionIssue = false
432-
this.close().then(this.initSession)
430+
this.disconnect().then(this.initSession)
433431
this.idle = false
434432
},
435433
@@ -659,14 +657,19 @@ export default {
659657
await this.$syncService.save()
660658
},
661659
660+
async disconnect() {
661+
await this.$syncService.close()
662+
this.unlistenSyncServiceEvents()
663+
this.$providers.forEach(p => p?.destroy())
664+
this.$providers = []
665+
this.$syncService = null
666+
// disallow editing while still showing the content
667+
this.readOnly = true
668+
},
669+
662670
async close() {
663-
if (this.currentSession && this.$syncService) {
664-
await this.$syncService.close()
665-
this.unlistenSyncServiceEvents()
666-
this.$syncService = null
667-
// disallow editing while still showing the content
668-
this.readOnly = true
669-
}
671+
await this.$syncService.sendRemainingSteps(this.$queue)
672+
await this.disconnect()
670673
if (this.$editor) {
671674
try {
672675
this.unlistenEditorEvents()

src/services/SyncService.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import debounce from 'debounce'
2525

2626
import PollingBackend from './PollingBackend.js'
2727
import SessionApi, { Connection } from './SessionApi.js'
28+
import { encodeArrayBuffer } from '../helpers/base64.ts'
2829
import { logger } from '../helpers/logger.js'
2930

3031
/**
@@ -293,6 +294,29 @@ class SyncService {
293294
return this.save({ manualSave: false })
294295
}
295296

297+
async sendRemainingSteps(queue) {
298+
if (queue.length === 0) {
299+
return
300+
}
301+
let outbox = []
302+
const steps = queue.map(s => encodeArrayBuffer(s))
303+
.filter(s => s < 'AQ')
304+
const awareness = queue.map(s => encodeArrayBuffer(s))
305+
.findLast(s => s > 'AQ') || ''
306+
return this.sendStepsNow(() => {
307+
const data = { steps, awareness, version: this.version }
308+
outbox = [...queue]
309+
logger.debug('sending final steps ', data)
310+
return data
311+
})?.then(() => {
312+
// only keep the steps that were not send yet
313+
queue.splice(0,
314+
queue.length,
315+
...queue.filter(s => !outbox.includes(s)),
316+
)
317+
}, err => logger.error(err))
318+
}
319+
296320
async close() {
297321
// Make sure to leave no pending requests behind.
298322
this.autosave.clear()

src/services/WebSocketPolyfill.js

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -114,37 +114,12 @@ export default function initWebSocketPolyfill(syncService, fileId, initialSessio
114114
}
115115

116116
async close() {
117-
await this.#sendRemainingSteps()
118117
Object.entries(this.#handlers)
119118
.forEach(([key, value]) => syncService.off(key, value))
120119
this.#handlers = []
121-
syncService.close().then(() => {
122-
this.onclose()
123-
})
120+
this.onclose()
124121
logger.debug('Websocket closed')
125122
}
126123

127-
#sendRemainingSteps() {
128-
if (queue.length) {
129-
let outbox = []
130-
return syncService.sendStepsNow(() => {
131-
const data = {
132-
steps: this.#steps,
133-
awareness: this.#awareness,
134-
version: this.#version,
135-
}
136-
outbox = [...queue]
137-
logger.debug('sending final steps ', data)
138-
return data
139-
})?.then(() => {
140-
// only keep the steps that were not send yet
141-
queue.splice(0,
142-
queue.length,
143-
...queue.filter(s => !outbox.includes(s)),
144-
)
145-
}, err => logger.error(err))
146-
}
147-
}
148-
149124
}
150125
}

0 commit comments

Comments
 (0)