implemented awareness protocol and added cursor support

This commit is contained in:
Kevin Jahns
2018-11-09 00:13:30 +01:00
parent 31d6ef6296
commit aafe15757f
19 changed files with 391 additions and 100 deletions

View File

@@ -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 {

View File

@@ -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'

View File

@@ -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'

View File

@@ -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'

View File

@@ -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'

View File

@@ -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'

View File

@@ -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'
/**

View File

@@ -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'
/**

View File

@@ -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'
/**

View File

@@ -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

View File

@@ -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'
/**

View File

@@ -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'

View 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)
}
}

View File

@@ -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: