implemented awareness protocol and added cursor support
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import Tree from '../../lib/Tree.js'
|
||||
import * as ID from '../Util/ID.js'
|
||||
import { getStruct } from '../Util/structReferences.js'
|
||||
import { stringifyID, stringifyItemID } from '../message.js'
|
||||
import { stringifyID, stringifyItemID } from '../protocols/syncProtocol.js'
|
||||
import GC from '../Struct/GC.js'
|
||||
|
||||
export default class OperationStore extends Tree {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { getStructReference } from '../Util/structReferences.js'
|
||||
import * as ID from '../Util/ID.js'
|
||||
import { stringifyID } from '../message.js'
|
||||
import { stringifyID } from '../protocols/syncProtocol.js'
|
||||
import { writeStructToTransaction } from '../Util/Transaction.js'
|
||||
import * as decoding from '../../lib/decoding.js'
|
||||
import * as encoding from '../../lib/encoding.js'
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import Item from './Item.js'
|
||||
import { logItemHelper } from '../message.js'
|
||||
import { logItemHelper } from '../protocols/syncProtocol.js'
|
||||
import * as encoding from '../../lib/encoding.js'
|
||||
import * as decoding from '../../lib/decoding.js'
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import Item from './Item.js'
|
||||
import { logItemHelper } from '../message.js'
|
||||
import { logItemHelper } from '../protocols/syncProtocol.js'
|
||||
import * as encoding from '../../lib/encoding.js'
|
||||
import * as decoding from '../../lib/decoding.js'
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import Item, { splitHelper } from './Item.js'
|
||||
import { logItemHelper } from '../message.js'
|
||||
import { logItemHelper } from '../protocols/syncProtocol.js'
|
||||
import * as encoding from '../../lib/encoding.js'
|
||||
import * as decoding from '../../lib/decoding.js'
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import Item, { splitHelper } from './Item.js'
|
||||
import { logItemHelper } from '../message.js'
|
||||
import { logItemHelper } from '../protocols/syncProtocol.js'
|
||||
import * as encoding from '../../lib/encoding.js'
|
||||
import * as decoding from '../../lib/decoding.js'
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import Type from '../../Struct/Type.js'
|
||||
import ItemJSON from '../../Struct/ItemJSON.js'
|
||||
import ItemString from '../../Struct/ItemString.js'
|
||||
import { stringifyItemID, logItemHelper } from '../../message.js'
|
||||
import { stringifyItemID, logItemHelper } from '../../protocols/syncProtocol.js'
|
||||
import YEvent from '../../Util/YEvent.js'
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import Item from '../../Struct/Item.js'
|
||||
import Type from '../../Struct/Type.js'
|
||||
import ItemJSON from '../../Struct/ItemJSON.js'
|
||||
import { logItemHelper } from '../../message.js'
|
||||
import { logItemHelper } from '../../protocols/syncProtocol.js'
|
||||
import YEvent from '../../Util/YEvent.js'
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import ItemEmbed from '../../Struct/ItemEmbed.js'
|
||||
import ItemString from '../../Struct/ItemString.js'
|
||||
import ItemFormat from '../../Struct/ItemFormat.js'
|
||||
import { logItemHelper } from '../../message.js'
|
||||
import { logItemHelper } from '../../protocols/syncProtocol.js'
|
||||
import { YArrayEvent, default as YArray } from '../YArray/YArray.js'
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,7 +3,7 @@ import YXmlTreeWalker from './YXmlTreeWalker.js'
|
||||
|
||||
import YArray from '../YArray/YArray.js'
|
||||
import YXmlEvent from './YXmlEvent.js'
|
||||
import { logItemHelper } from '../../message.js'
|
||||
import { logItemHelper } from '../../protocols/syncProtocol.js'
|
||||
|
||||
/**
|
||||
* @typedef {import('./YXmlElement.js').default} YXmlElement
|
||||
|
||||
2
src/Y.js
2
src/Y.js
@@ -6,7 +6,7 @@ import { createRootID } from './Util/ID.js'
|
||||
import NamedEventHandler from '../lib/NamedEventHandler.js'
|
||||
import Transaction from './Util/Transaction.js'
|
||||
import * as encoding from '../lib/encoding.js'
|
||||
import * as message from './message.js'
|
||||
import * as message from './protocols/syncProtocol.js'
|
||||
import { integrateRemoteStructs } from './Util/integrateRemoteStructs.js'
|
||||
|
||||
/**
|
||||
|
||||
@@ -30,7 +30,8 @@ export { default as XmlElement } from './Types/YXml/YXmlElement.js'
|
||||
|
||||
export { getRelativePosition, fromRelativePosition } from './Util/relativePosition.js'
|
||||
export { registerStruct as registerType } from './Util/structReferences.js'
|
||||
export * from './message.js'
|
||||
export * from './protocols/syncProtocol.js'
|
||||
export * from './protocols/awarenessProtocol.js'
|
||||
export * from '../lib/encoding.js'
|
||||
export * from '../lib/decoding.js'
|
||||
export * from '../lib/mutex.js'
|
||||
|
||||
98
src/protocols/awarenessProtocol.js
Normal file
98
src/protocols/awarenessProtocol.js
Normal file
@@ -0,0 +1,98 @@
|
||||
|
||||
import * as encoding from '../../lib/encoding.js'
|
||||
import * as decoding from '../../lib/decoding.js'
|
||||
|
||||
const messageUsersStateChanged = 0
|
||||
|
||||
/**
|
||||
* @typedef {Object} UserStateUpdate
|
||||
* @property {number} UserStateUpdate.userID
|
||||
* @property {Object} state
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {encoding.Encoder} encoder
|
||||
* @param {Array<UserStateUpdate>} stateUpdates
|
||||
*/
|
||||
export const writeUsersStateChange = (encoder, stateUpdates) => {
|
||||
const len = stateUpdates.length
|
||||
encoding.writeVarUint(encoder, messageUsersStateChanged)
|
||||
encoding.writeVarUint(encoder, len)
|
||||
for (let i = 0; i < len; i++) {
|
||||
const {userID, state} = stateUpdates[i]
|
||||
encoding.writeVarUint(encoder, userID)
|
||||
encoding.writeVarString(encoder, JSON.stringify(state))
|
||||
}
|
||||
}
|
||||
|
||||
export const readUsersStateChange = (decoder, y) => {
|
||||
const added = []
|
||||
const updated = []
|
||||
const removed = []
|
||||
const len = decoding.readVarUint(decoder)
|
||||
for (let i = 0; i < len; i++) {
|
||||
const userID = decoding.readVarUint(decoder)
|
||||
const state = JSON.parse(decoding.readVarString(decoder))
|
||||
if (userID !== y.userID) {
|
||||
if (state === null) {
|
||||
if (y.awareness.has(userID)) {
|
||||
y.awareness.delete(userID)
|
||||
removed.push(userID)
|
||||
}
|
||||
} else {
|
||||
if (y.awareness.has(userID)) {
|
||||
updated.push(userID)
|
||||
} else {
|
||||
added.push(userID)
|
||||
}
|
||||
y.awareness.set(userID, state)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (added.length > 0 || updated.length > 0 || removed.length > 0) {
|
||||
y.emit('awareness', {
|
||||
added, updated, removed
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {decoding.Decoder} decoder
|
||||
* @param {encoding.Encoder} encoder
|
||||
*/
|
||||
export const forwardUsersStateChange = (decoder, encoder) => {
|
||||
const len = decoding.readVarUint(decoder)
|
||||
const updates = []
|
||||
encoding.writeVarUint(encoder, messageUsersStateChanged)
|
||||
encoding.writeVarUint(encoder, len)
|
||||
for (let i = 0; i < len; i++) {
|
||||
const userID = decoding.readVarUint(decoder)
|
||||
const state = decoding.readVarString(decoder)
|
||||
encoding.writeVarUint(encoder, userID)
|
||||
encoding.writeVarString(encoder, state)
|
||||
updates.push({userID, state: JSON.parse(state)})
|
||||
}
|
||||
return updates
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {decoding.Decoder} decoder
|
||||
*/
|
||||
export const readAwarenessMessage = (decoder, y) => {
|
||||
switch (decoding.readVarUint(decoder)) {
|
||||
case messageUsersStateChanged:
|
||||
readUsersStateChange(decoder, y)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {decoding.Decoder} decoder
|
||||
* @param {encoding.Encoder} encoder
|
||||
*/
|
||||
export const forwardAwarenessMessage = (decoder, encoder) => {
|
||||
switch (decoding.readVarUint(decoder)) {
|
||||
case messageUsersStateChanged:
|
||||
return forwardUsersStateChange(decoder, encoder)
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,17 @@
|
||||
|
||||
import * as encoding from '../lib/encoding.js'
|
||||
import * as decoding from '../lib/decoding.js'
|
||||
import * as ID from './Util/ID.js'
|
||||
import { getStruct } from './Util/structReferences.js'
|
||||
import { deleteItemRange } from './Struct/Delete.js'
|
||||
import { integrateRemoteStruct } from './Util/integrateRemoteStructs.js'
|
||||
import Item from './Struct/Item.js'
|
||||
import * as encoding from '../../lib/encoding.js'
|
||||
import * as decoding from '../../lib/decoding.js'
|
||||
import * as ID from '../Util/ID.js'
|
||||
import { getStruct } from '../Util/structReferences.js'
|
||||
import { deleteItemRange } from '../Struct/Delete.js'
|
||||
import { integrateRemoteStruct } from '../Util/integrateRemoteStructs.js'
|
||||
import Item from '../Struct/Item.js'
|
||||
|
||||
/**
|
||||
* @typedef {import('./Store/StateStore.js').default} StateStore
|
||||
* @typedef {import('./Y.js').default} Y
|
||||
* @typedef {import('./Struct/Item.js').default} Item
|
||||
* @typedef {import('./Store/StateStore.js').StateSet} StateSet
|
||||
* @typedef {import('../Store/StateStore.js').default} StateStore
|
||||
* @typedef {import('../Y.js').default} Y
|
||||
* @typedef {import('../Struct/Item.js').default} Item
|
||||
* @typedef {import('../Store/StateStore.js').StateSet} StateSet
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -439,7 +439,7 @@ export const readUpdate = readStructs
|
||||
* @param {Y} y
|
||||
* @return {string} The message converted to string
|
||||
*/
|
||||
export const stringifyMessage = (decoder, y) => {
|
||||
export const stringifySyncMessage = (decoder, y) => {
|
||||
const messageType = decoding.readVarUint(decoder)
|
||||
let stringifiedMessage
|
||||
let stringifiedMessageType
|
||||
@@ -468,7 +468,7 @@ export const stringifyMessage = (decoder, y) => {
|
||||
* @param {encoding.Encoder} encoder The reply message. Will not be sent if empty.
|
||||
* @param {Y} y
|
||||
*/
|
||||
export const readMessage = (decoder, encoder, y) => {
|
||||
export const readSyncMessage = (decoder, encoder, y) => {
|
||||
const messageType = decoding.readVarUint(decoder)
|
||||
switch (messageType) {
|
||||
case messageYjsSyncStep1:
|
||||
Reference in New Issue
Block a user