transmit awareness
This commit is contained in:
parent
05220efd00
commit
12772bfcfa
4 changed files with 119 additions and 22 deletions
2
package-lock.json
generated
2
package-lock.json
generated
|
@ -19,6 +19,7 @@
|
|||
"lodash.difference": "^4.5.0",
|
||||
"lodash.differencewith": "^4.5.0",
|
||||
"lodash.isequal": "^4.5.0",
|
||||
"mitt": "^3.0.1",
|
||||
"nprogress": "^0.2.0",
|
||||
"pinia": "^2.3.0",
|
||||
"qrcode": "^1.5.3",
|
||||
|
@ -7145,7 +7146,6 @@
|
|||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz",
|
||||
"integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/mkdirp-classic": {
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
"lodash.difference": "^4.5.0",
|
||||
"lodash.differencewith": "^4.5.0",
|
||||
"lodash.isequal": "^4.5.0",
|
||||
"mitt": "^3.0.1",
|
||||
"nprogress": "^0.2.0",
|
||||
"pinia": "^2.3.0",
|
||||
"qrcode": "^1.5.3",
|
||||
|
|
74
src/helpers/awareness.ts
Normal file
74
src/helpers/awareness.ts
Normal file
|
@ -0,0 +1,74 @@
|
|||
import mitt from "mitt";
|
||||
|
||||
export interface Editor {
|
||||
username: string;
|
||||
firstname: string;
|
||||
lastname: string;
|
||||
color: string;
|
||||
}
|
||||
|
||||
export interface EditorState {
|
||||
field: string;
|
||||
cursor: any;
|
||||
range: any;
|
||||
}
|
||||
|
||||
export type AwarenessActions = "update" | "remove";
|
||||
|
||||
export type AwarenessEvents = {
|
||||
update: { data: EditorState };
|
||||
};
|
||||
|
||||
export class Awareness {
|
||||
private editors = new Map<string, Editor>();
|
||||
private editorStates = new Map<string, EditorState>();
|
||||
public readonly emitter = mitt<AwarenessEvents>();
|
||||
|
||||
public getEditors() {
|
||||
return this.editors;
|
||||
}
|
||||
|
||||
public getEditor(key: string) {
|
||||
return this.editors.get(key);
|
||||
}
|
||||
|
||||
public getEditorsByField(field: string) {
|
||||
return Array.from(this.editorStates.entries())
|
||||
.filter(([key, val]) => val.field == field)
|
||||
.map(([key, val]) => key);
|
||||
}
|
||||
|
||||
public getEditorStates() {
|
||||
return this.editorStates;
|
||||
}
|
||||
|
||||
public updateEditor(socketId: string, { action, data }: { action: AwarenessActions; data: Editor }) {
|
||||
if (action == "update") {
|
||||
this.editors.set(socketId, data);
|
||||
} else if (action == "remove") {
|
||||
this.editors.delete(socketId);
|
||||
}
|
||||
}
|
||||
|
||||
public updateEditorState(socketId: string, { action, data }: { action: AwarenessActions; data: EditorState }) {
|
||||
if (action == "update") {
|
||||
this.editorStates.set(socketId, data);
|
||||
} else if (action == "remove") {
|
||||
this.editorStates.delete(socketId);
|
||||
}
|
||||
}
|
||||
|
||||
public publishMyState(data: EditorState) {
|
||||
this.emitter.emit("update", { data });
|
||||
}
|
||||
|
||||
public reset() {
|
||||
this.editors.clear();
|
||||
this.editorStates.clear();
|
||||
}
|
||||
|
||||
public destroy() {
|
||||
this.emitter.all.clear();
|
||||
this.reset();
|
||||
}
|
||||
}
|
|
@ -1,12 +1,13 @@
|
|||
import { defineStore } from "pinia";
|
||||
import { useConnectionStore } from "./connection";
|
||||
import * as Y from "yjs";
|
||||
import { Awareness, type Editor, type EditorState } from "@/helpers/awareness";
|
||||
|
||||
export const useMissionDetailStore = defineStore("missionDetail", {
|
||||
state: () => {
|
||||
return {
|
||||
yDoc: new Y.Doc(),
|
||||
awareness: undefined as undefined,
|
||||
awareness: new Awareness(),
|
||||
docId: null as null | string,
|
||||
lastUpdateTimestamp: 0 as number,
|
||||
connectionStatus: "disconnected", // 'disconnected', 'connecting', 'connected', 'syncing', 'synced'
|
||||
|
@ -17,8 +18,6 @@ export const useMissionDetailStore = defineStore("missionDetail", {
|
|||
this.docId = docId;
|
||||
|
||||
this.lastUpdateTimestamp = this.loadLastUpdateFromLocalStorage();
|
||||
// this.awareness = new AwarenessProtocol.Awareness(this.yDoc);
|
||||
// this.awareness.setLocalStateField("user", { name: "hi", color: "#123456" });
|
||||
|
||||
this.setupSocketHandlers();
|
||||
this.setupYjsObservers();
|
||||
|
@ -54,8 +53,42 @@ export const useMissionDetailStore = defineStore("missionDetail", {
|
|||
});
|
||||
});
|
||||
|
||||
connectionStore.connection?.on("package-init-awareness", (data) => {
|
||||
if (data.type == "editors") {
|
||||
let update = data.update as Array<[string, Editor]>;
|
||||
for (const e of update) {
|
||||
this.awareness.updateEditor(e[0], {
|
||||
action: "update",
|
||||
data: e[1],
|
||||
});
|
||||
}
|
||||
} else if (data.type == "state") {
|
||||
let update = data.update as Array<[string, EditorState]>;
|
||||
for (const e of update) {
|
||||
this.awareness.updateEditorState(e[0], {
|
||||
action: "update",
|
||||
data: e[1],
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
connectionStore.connection?.on("package-sync-awareness", (data) => {
|
||||
// TODO self implement where users edit what and cursors
|
||||
if (connectionStore.connection?.id == data.socketId) return;
|
||||
if (data.type == "editors") {
|
||||
this.awareness.updateEditor(data.socketId, {
|
||||
action: data.action,
|
||||
data: data.update,
|
||||
});
|
||||
} else if (data.type == "state") {
|
||||
this.awareness.updateEditorState(data.socketId, {
|
||||
action: data.action,
|
||||
data: data.update,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
connectionStore.connection?.on("disconnect", () => {
|
||||
this.awareness.reset();
|
||||
});
|
||||
|
||||
this.joinDocument();
|
||||
|
@ -77,18 +110,10 @@ export const useMissionDetailStore = defineStore("missionDetail", {
|
|||
},
|
||||
|
||||
setupAwarenessObservers() {
|
||||
if (!this.awareness) return;
|
||||
|
||||
// this.awareness.on("update", (update: { added: number[]; updated: number[]; removed: number[] }) => {
|
||||
// if (this.awareness != undefined) {
|
||||
// const changedClients = update.added.concat(update.updated).concat(update.removed);
|
||||
// const connectionStore = useConnectionStore();
|
||||
// connectionStore.connection?.emit(
|
||||
// "mission:sync-client-awareness",
|
||||
// Uint8Array.from(AwarenessProtocol.encodeAwarenessUpdate(this.awareness, changedClients))
|
||||
// );
|
||||
// }
|
||||
// });
|
||||
this.awareness.emitter.on("update", (update: { data: EditorState }) => {
|
||||
const connectionStore = useConnectionStore();
|
||||
connectionStore.connection?.emit("mission:sync-client-awareness", update.data);
|
||||
});
|
||||
},
|
||||
|
||||
joinDocument() {
|
||||
|
@ -119,13 +144,10 @@ export const useMissionDetailStore = defineStore("missionDetail", {
|
|||
},
|
||||
|
||||
cleanup() {
|
||||
// if (this.awareness) {
|
||||
// AwarenessProtocol.removeAwarenessStates(this.awareness, [this.yDoc.clientID], "window unload");
|
||||
// this.awareness.destroy();
|
||||
// }
|
||||
|
||||
this.yDoc.destroy();
|
||||
this.yDoc = new Y.Doc();
|
||||
this.awareness.destroy();
|
||||
this.awareness = new Awareness();
|
||||
|
||||
this.lastUpdateTimestamp = 0;
|
||||
localStorage.removeItem("yjsDoc_timestamp");
|
||||
|
|
Loading…
Add table
Reference in a new issue