Refactoring
parent
610fe9de6d
commit
eebf920a9d
|
@ -1,4 +1,5 @@
|
|||
import { Extension, HocuspocusProvider, Y, yCollab } from "../deps.ts";
|
||||
import { SyncService } from "../sync_service.ts";
|
||||
|
||||
const userColors = [
|
||||
{ color: "#30bced", light: "#30bced33" },
|
||||
|
@ -17,15 +18,31 @@ export class CollabState {
|
|||
private yundoManager: Y.UndoManager;
|
||||
|
||||
constructor(
|
||||
serverUrl: string,
|
||||
name: string,
|
||||
username: string,
|
||||
onStateless: (data: any) => any,
|
||||
private serverUrl: string,
|
||||
private pageName: string,
|
||||
private token: string,
|
||||
private username: string,
|
||||
private syncService: SyncService,
|
||||
) {
|
||||
this.collabProvider = new HocuspocusProvider({
|
||||
url: serverUrl,
|
||||
name: name,
|
||||
onStateless,
|
||||
name: token,
|
||||
|
||||
// Receive broadcasted messages from the server (right now only "page has been persisted" notifications)
|
||||
onStateless: (
|
||||
{ payload },
|
||||
) => {
|
||||
const message = JSON.parse(payload);
|
||||
switch (message.type) {
|
||||
case "persisted": {
|
||||
// Received remote persist notification, updating snapshot
|
||||
syncService.updateRemoteLastModified(
|
||||
message.path,
|
||||
message.lastModified,
|
||||
).catch(console.error);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
this.collabProvider.on("status", (e: any) => {
|
||||
|
@ -46,12 +63,18 @@ export class CollabState {
|
|||
}
|
||||
|
||||
stop() {
|
||||
// this.collabProvider.disconnect();
|
||||
console.log("[COLLAB] Destroying collab provider");
|
||||
this.collabProvider.destroy();
|
||||
// For whatever reason, destroy() doesn't properly clean up everything so we need to help a bit
|
||||
this.collabProvider.configuration.websocketProvider.webSocket = null;
|
||||
this.collabProvider.configuration.websocketProvider.destroy();
|
||||
|
||||
// When stopping collaboration, we're going back to sync mode. Make sure we got the latest and greatest remote timestamp to avoid
|
||||
// conflicts
|
||||
this.syncService.fetchAndPersistRemoteLastModified(`${this.pageName}.md`)
|
||||
.catch(
|
||||
console.error,
|
||||
);
|
||||
}
|
||||
|
||||
collabExtension(): Extension {
|
||||
|
|
|
@ -1155,7 +1155,7 @@ export class Editor {
|
|||
await this.save(true);
|
||||
// And stop the collab session
|
||||
if (this.collabState) {
|
||||
this.stopCollab(previousPage);
|
||||
this.stopCollab();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1525,49 +1525,25 @@ export class Editor {
|
|||
this.collabState.stop();
|
||||
}
|
||||
const initialText = this.editorView!.state.sliceDoc();
|
||||
this.collabState = new CollabState(serverUrl, token, username, (
|
||||
{ payload },
|
||||
) => {
|
||||
const message = JSON.parse(payload);
|
||||
switch (message.type) {
|
||||
case "persisted": {
|
||||
// console.log(
|
||||
// "Received remote persist notification, updating snapshot",
|
||||
// message,
|
||||
// );
|
||||
this.syncService.updateRemoteLastModified(
|
||||
message.path,
|
||||
message.lastModified,
|
||||
).catch(console.error);
|
||||
}
|
||||
}
|
||||
});
|
||||
this.collabState = new CollabState(
|
||||
serverUrl,
|
||||
this.currentPage!,
|
||||
token,
|
||||
username,
|
||||
this.syncService,
|
||||
);
|
||||
|
||||
// this.collabState.collabProvider.on("synced", () => {
|
||||
// if (this.collabState?.ytext.toString() === "") {
|
||||
// console.error("Synced value is empty, putting back original text");
|
||||
// this.collabState?.ytext.insert(0, initialText);
|
||||
// }
|
||||
// });
|
||||
this.rebuildEditorState();
|
||||
|
||||
// Don't watch for local changes in this mode
|
||||
this.space.unwatch();
|
||||
}
|
||||
|
||||
stopCollab(pageName: string) {
|
||||
stopCollab() {
|
||||
if (this.collabState) {
|
||||
this.collabState.stop();
|
||||
this.collabState = undefined;
|
||||
this.rebuildEditorState();
|
||||
// Switching off collab mode
|
||||
this.syncService.remoteSpace.getFileMeta(`${pageName}.md`).then(
|
||||
(meta) => {
|
||||
return this.syncService.updateRemoteLastModified(
|
||||
meta.name,
|
||||
meta.lastModified,
|
||||
);
|
||||
},
|
||||
).catch(console.error);
|
||||
}
|
||||
// Start file watching again
|
||||
this.space.watch();
|
||||
|
|
|
@ -165,6 +165,16 @@ export class SyncService {
|
|||
await this.registerSyncStop();
|
||||
}
|
||||
|
||||
// Reach out out to remote space, fetch the latest lastModified time and update the local snapshot
|
||||
// This is used when exiting collab mode
|
||||
async fetchAndPersistRemoteLastModified(path: string) {
|
||||
const meta = await this.remoteSpace.getFileMeta(path);
|
||||
await this.updateRemoteLastModified(
|
||||
meta.name,
|
||||
meta.lastModified,
|
||||
);
|
||||
}
|
||||
|
||||
// When in collab mode, we delegate the sync to the CDRT engine, to avoid conflicts, we try to keep the lastModified time in sync when local changes happen
|
||||
async updateLocalLastModified(path: string, lastModified: number) {
|
||||
await this.noOngoingSync();
|
||||
|
|
|
@ -14,7 +14,7 @@ export function collabSyscalls(editor: Editor): SysCallMapping {
|
|||
"collab.stop": (
|
||||
_ctx,
|
||||
) => {
|
||||
editor.stopCollab(editor.currentPage!);
|
||||
editor.stopCollab();
|
||||
},
|
||||
"collab.ping": async (
|
||||
_ctx,
|
||||
|
|
Loading…
Reference in New Issue