Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8739fd3a9c | ||
|
|
b3b12958fa | ||
|
|
42aa7ec5c9 | ||
|
|
73e53e3dcc | ||
|
|
222ffea11e |
34
README.md
34
README.md
@@ -22,6 +22,7 @@ is a list of the modules we know of:
|
|||||||
|[webrtc](https://github.com/y-js/y-webrtc) | Propagate updates Browser2Browser via WebRTC|
|
|[webrtc](https://github.com/y-js/y-webrtc) | Propagate updates Browser2Browser via WebRTC|
|
||||||
|[websockets](https://github.com/y-js/y-websockets-client) | Set up [a central server](https://github.com/y-js/y-websockets-client), and connect to it via websockets |
|
|[websockets](https://github.com/y-js/y-websockets-client) | Set up [a central server](https://github.com/y-js/y-websockets-client), and connect to it via websockets |
|
||||||
|[xmpp](https://github.com/y-js/y-xmpp) | Propagate updates in a XMPP multi-user-chat room ([XEP-0045](http://xmpp.org/extensions/xep-0045.html))|
|
|[xmpp](https://github.com/y-js/y-xmpp) | Propagate updates in a XMPP multi-user-chat room ([XEP-0045](http://xmpp.org/extensions/xep-0045.html))|
|
||||||
|
|[ipfs](https://github.com/ipfs-labs/y-ipfs-connector) | Connector for the [Interplanetary File System](https://ipfs.io/)!|
|
||||||
|[test](https://github.com/y-js/y-test) | A Connector for testing purposes. It is designed to simulate delays that happen in worst case scenarios|
|
|[test](https://github.com/y-js/y-test) | A Connector for testing purposes. It is designed to simulate delays that happen in worst case scenarios|
|
||||||
|
|
||||||
##### Database adapters
|
##### Database adapters
|
||||||
@@ -54,23 +55,23 @@ Install Yjs, and its modules with [bower](http://bower.io/), or
|
|||||||
[npm](https://www.npmjs.org/package/yjs).
|
[npm](https://www.npmjs.org/package/yjs).
|
||||||
|
|
||||||
### Bower
|
### Bower
|
||||||
```
|
```sh
|
||||||
bower install --save yjs y-array % add all y-* modules you want to use
|
bower install --save yjs y-array % add all y-* modules you want to use
|
||||||
```
|
```
|
||||||
You only need to include the `y.js` file. Yjs is able to automatically require
|
You only need to include the `y.js` file. Yjs is able to automatically require
|
||||||
missing modules.
|
missing modules.
|
||||||
```
|
```html
|
||||||
<script src="./bower_components/yjs/y.js"></script>
|
<script src="./bower_components/yjs/y.js"></script>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Npm
|
### Npm
|
||||||
```
|
```sh
|
||||||
npm install --save yjs % add all y-* modules you want to use
|
npm install --save yjs % add all y-* modules you want to use
|
||||||
```
|
```
|
||||||
|
|
||||||
If you don't include via script tag, you have to explicitly include all modules!
|
If you don't include via script tag, you have to explicitly include all modules!
|
||||||
(Same goes for other module systems)
|
(Same goes for other module systems)
|
||||||
```
|
```js
|
||||||
var Y = require('yjs')
|
var Y = require('yjs')
|
||||||
require('y-array')(Y) // add the y-array type to Yjs
|
require('y-array')(Y) // add the y-array type to Yjs
|
||||||
require('y-websockets-client')(Y)
|
require('y-websockets-client')(Y)
|
||||||
@@ -83,7 +84,7 @@ require('y-text')(Y)
|
|||||||
```
|
```
|
||||||
|
|
||||||
### ES6 Syntax
|
### ES6 Syntax
|
||||||
```
|
```js
|
||||||
import Y from 'yjs'
|
import Y from 'yjs'
|
||||||
import yArray from 'y-array'
|
import yArray from 'y-array'
|
||||||
import yWebsocketsClient from 'y-webrtc'
|
import yWebsocketsClient from 'y-webrtc'
|
||||||
@@ -97,7 +98,7 @@ Y.extend(yArray, yWebsocketsClient, yMemory, yArray, yMap, yText /*, .. */)
|
|||||||
|
|
||||||
# Text editing example
|
# Text editing example
|
||||||
Install dependencies
|
Install dependencies
|
||||||
```
|
```sh
|
||||||
bower i yjs y-memory y-webrtc y-array y-text
|
bower i yjs y-memory y-webrtc y-array y-text
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -165,6 +166,25 @@ soon, if possible.
|
|||||||
endpoint of the used connector.
|
endpoint of the used connector.
|
||||||
* All of our connectors also have a default connection endpoint that you can
|
* All of our connectors also have a default connection endpoint that you can
|
||||||
use for development.
|
use for development.
|
||||||
|
* We provide basic authentification for all connectors. The value of
|
||||||
|
`options.connector.auth` (this can be a passphase) is sent to all connected
|
||||||
|
Yjs instances. `options.connector.checkAuth` may grant read or write access
|
||||||
|
depending on the `auth` information.
|
||||||
|
Example: A client specifies `options.connector.auth = 'superSecretPassword`.
|
||||||
|
A server specifies
|
||||||
|
```js
|
||||||
|
options.connector.checkAuth = function (auth, yjsInstance, sender) {
|
||||||
|
return new Promise(function (resolve, reject){
|
||||||
|
if (auth === 'superSecretPassword') {
|
||||||
|
resolve('write') // grant read-write access
|
||||||
|
} else if (auth === 'different password') {
|
||||||
|
resolve('read') // grant read-only access
|
||||||
|
} else {
|
||||||
|
reject('wrong password!') // reject connection
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
```
|
||||||
* Set `options.connector.generateUserId = true` in order to genenerate a
|
* Set `options.connector.generateUserId = true` in order to genenerate a
|
||||||
userid, instead of receiving one from the server. This way the `Y(..)` is
|
userid, instead of receiving one from the server. This way the `Y(..)` is
|
||||||
immediately going to be resolved, without waiting for any confirmation from
|
immediately going to be resolved, without waiting for any confirmation from
|
||||||
@@ -180,7 +200,7 @@ soon, if possible.
|
|||||||
* Defaults to `/bower_components`
|
* Defaults to `/bower_components`
|
||||||
* Not required when running on `nodejs` / `iojs`
|
* Not required when running on `nodejs` / `iojs`
|
||||||
* When using nodejs you need to manually extend Yjs:
|
* When using nodejs you need to manually extend Yjs:
|
||||||
```
|
```js
|
||||||
var Y = require('yjs')
|
var Y = require('yjs')
|
||||||
// you have to require a db, connector, and *all* types you use!
|
// you have to require a db, connector, and *all* types you use!
|
||||||
require('y-memory')(Y)
|
require('y-memory')(Y)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "yjs",
|
"name": "yjs",
|
||||||
"version": "12.2.0",
|
"version": "12.3.3",
|
||||||
"homepage": "y-js.org",
|
"homepage": "y-js.org",
|
||||||
"authors": [
|
"authors": [
|
||||||
"Kevin Jahns <kevin.jahns@rwth-aachen.de>"
|
"Kevin Jahns <kevin.jahns@rwth-aachen.de>"
|
||||||
|
|||||||
152
y.es6
152
y.es6
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* yjs - A framework for real-time p2p shared editing on any data
|
* yjs - A framework for real-time p2p shared editing on any data
|
||||||
* @version v12.1.7
|
* @version v12.3.2
|
||||||
* @link http://y-js.org
|
* @link http://y-js.org
|
||||||
* @license MIT
|
* @license MIT
|
||||||
*/
|
*/
|
||||||
@@ -48,20 +48,20 @@ function useColors() {
|
|||||||
// NB: In an Electron preload script, document will be defined but not fully
|
// NB: In an Electron preload script, document will be defined but not fully
|
||||||
// initialized. Since we know we're in Chrome, we'll just detect this case
|
// initialized. Since we know we're in Chrome, we'll just detect this case
|
||||||
// explicitly
|
// explicitly
|
||||||
if (typeof window !== 'undefined' && window && typeof window.process !== 'undefined' && window.process.type === 'renderer') {
|
if (typeof window !== 'undefined' && window.process && window.process.type === 'renderer') {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// is webkit? http://stackoverflow.com/a/16459606/376773
|
// is webkit? http://stackoverflow.com/a/16459606/376773
|
||||||
// document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
|
// document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
|
||||||
return (typeof document !== 'undefined' && document && 'WebkitAppearance' in document.documentElement.style) ||
|
return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) ||
|
||||||
// is firebug? http://stackoverflow.com/a/398120/376773
|
// is firebug? http://stackoverflow.com/a/398120/376773
|
||||||
(typeof window !== 'undefined' && window && window.console && (console.firebug || (console.exception && console.table))) ||
|
(typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) ||
|
||||||
// is firefox >= v31?
|
// is firefox >= v31?
|
||||||
// https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
|
// https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
|
||||||
(typeof navigator !== 'undefined' && navigator && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) ||
|
(typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) ||
|
||||||
// double check webkit in userAgent just in case we are in a worker
|
// double check webkit in userAgent just in case we are in a worker
|
||||||
(typeof navigator !== 'undefined' && navigator && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/));
|
(typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -403,11 +403,11 @@ function coerce(val) {
|
|||||||
* Helpers.
|
* Helpers.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var s = 1000
|
var s = 1000;
|
||||||
var m = s * 60
|
var m = s * 60;
|
||||||
var h = m * 60
|
var h = m * 60;
|
||||||
var d = h * 24
|
var d = h * 24;
|
||||||
var y = d * 365.25
|
var y = d * 365.25;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse or format the given `val`.
|
* Parse or format the given `val`.
|
||||||
@@ -424,17 +424,18 @@ var y = d * 365.25
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
module.exports = function(val, options) {
|
module.exports = function(val, options) {
|
||||||
options = options || {}
|
options = options || {};
|
||||||
var type = typeof val
|
var type = typeof val;
|
||||||
if (type === 'string' && val.length > 0) {
|
if (type === 'string' && val.length > 0) {
|
||||||
return parse(val)
|
return parse(val);
|
||||||
} else if (type === 'number' && isNaN(val) === false) {
|
} else if (type === 'number' && isNaN(val) === false) {
|
||||||
return options.long ?
|
return options.long ? fmtLong(val) : fmtShort(val);
|
||||||
fmtLong(val) :
|
|
||||||
fmtShort(val)
|
|
||||||
}
|
|
||||||
throw new Error('val is not a non-empty string or a valid number. val=' + JSON.stringify(val))
|
|
||||||
}
|
}
|
||||||
|
throw new Error(
|
||||||
|
'val is not a non-empty string or a valid number. val=' +
|
||||||
|
JSON.stringify(val)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse the given `str` and return milliseconds.
|
* Parse the given `str` and return milliseconds.
|
||||||
@@ -445,53 +446,55 @@ module.exports = function (val, options) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function parse(str) {
|
function parse(str) {
|
||||||
str = String(str)
|
str = String(str);
|
||||||
if (str.length > 10000) {
|
if (str.length > 100) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(str)
|
var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(
|
||||||
|
str
|
||||||
|
);
|
||||||
if (!match) {
|
if (!match) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
var n = parseFloat(match[1])
|
var n = parseFloat(match[1]);
|
||||||
var type = (match[2] || 'ms').toLowerCase()
|
var type = (match[2] || 'ms').toLowerCase();
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'years':
|
case 'years':
|
||||||
case 'year':
|
case 'year':
|
||||||
case 'yrs':
|
case 'yrs':
|
||||||
case 'yr':
|
case 'yr':
|
||||||
case 'y':
|
case 'y':
|
||||||
return n * y
|
return n * y;
|
||||||
case 'days':
|
case 'days':
|
||||||
case 'day':
|
case 'day':
|
||||||
case 'd':
|
case 'd':
|
||||||
return n * d
|
return n * d;
|
||||||
case 'hours':
|
case 'hours':
|
||||||
case 'hour':
|
case 'hour':
|
||||||
case 'hrs':
|
case 'hrs':
|
||||||
case 'hr':
|
case 'hr':
|
||||||
case 'h':
|
case 'h':
|
||||||
return n * h
|
return n * h;
|
||||||
case 'minutes':
|
case 'minutes':
|
||||||
case 'minute':
|
case 'minute':
|
||||||
case 'mins':
|
case 'mins':
|
||||||
case 'min':
|
case 'min':
|
||||||
case 'm':
|
case 'm':
|
||||||
return n * m
|
return n * m;
|
||||||
case 'seconds':
|
case 'seconds':
|
||||||
case 'second':
|
case 'second':
|
||||||
case 'secs':
|
case 'secs':
|
||||||
case 'sec':
|
case 'sec':
|
||||||
case 's':
|
case 's':
|
||||||
return n * s
|
return n * s;
|
||||||
case 'milliseconds':
|
case 'milliseconds':
|
||||||
case 'millisecond':
|
case 'millisecond':
|
||||||
case 'msecs':
|
case 'msecs':
|
||||||
case 'msec':
|
case 'msec':
|
||||||
case 'ms':
|
case 'ms':
|
||||||
return n
|
return n;
|
||||||
default:
|
default:
|
||||||
return undefined
|
return undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -505,18 +508,18 @@ function parse(str) {
|
|||||||
|
|
||||||
function fmtShort(ms) {
|
function fmtShort(ms) {
|
||||||
if (ms >= d) {
|
if (ms >= d) {
|
||||||
return Math.round(ms / d) + 'd'
|
return Math.round(ms / d) + 'd';
|
||||||
}
|
}
|
||||||
if (ms >= h) {
|
if (ms >= h) {
|
||||||
return Math.round(ms / h) + 'h'
|
return Math.round(ms / h) + 'h';
|
||||||
}
|
}
|
||||||
if (ms >= m) {
|
if (ms >= m) {
|
||||||
return Math.round(ms / m) + 'm'
|
return Math.round(ms / m) + 'm';
|
||||||
}
|
}
|
||||||
if (ms >= s) {
|
if (ms >= s) {
|
||||||
return Math.round(ms / s) + 's'
|
return Math.round(ms / s) + 's';
|
||||||
}
|
}
|
||||||
return ms + 'ms'
|
return ms + 'ms';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -532,7 +535,7 @@ function fmtLong(ms) {
|
|||||||
plural(ms, h, 'hour') ||
|
plural(ms, h, 'hour') ||
|
||||||
plural(ms, m, 'minute') ||
|
plural(ms, m, 'minute') ||
|
||||||
plural(ms, s, 'second') ||
|
plural(ms, s, 'second') ||
|
||||||
ms + ' ms'
|
ms + ' ms';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -541,12 +544,12 @@ function fmtLong(ms) {
|
|||||||
|
|
||||||
function plural(ms, n, name) {
|
function plural(ms, n, name) {
|
||||||
if (ms < n) {
|
if (ms < n) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
if (ms < n * 1.5) {
|
if (ms < n * 1.5) {
|
||||||
return Math.floor(ms / n) + ' ' + name
|
return Math.floor(ms / n) + ' ' + name;
|
||||||
}
|
}
|
||||||
return Math.ceil(ms / n) + ' ' + name + 's'
|
return Math.ceil(ms / n) + ' ' + name + 's';
|
||||||
}
|
}
|
||||||
|
|
||||||
},{}],4:[function(require,module,exports){
|
},{}],4:[function(require,module,exports){
|
||||||
@@ -736,9 +739,6 @@ process.chdir = function (dir) {
|
|||||||
process.umask = function() { return 0; };
|
process.umask = function() { return 0; };
|
||||||
|
|
||||||
},{}],5:[function(require,module,exports){
|
},{}],5:[function(require,module,exports){
|
||||||
/* @flow */
|
|
||||||
'use strict'
|
|
||||||
|
|
||||||
function canRead (auth) { return auth === 'read' || auth === 'write' }
|
function canRead (auth) { return auth === 'read' || auth === 'write' }
|
||||||
function canWrite (auth) { return auth === 'write' }
|
function canWrite (auth) { return auth === 'write' }
|
||||||
|
|
||||||
@@ -777,7 +777,6 @@ module.exports = function (Y/* :any */) {
|
|||||||
// this client receives operations from only one other client.
|
// this client receives operations from only one other client.
|
||||||
// In particular, this does not work with y-webrtc.
|
// In particular, this does not work with y-webrtc.
|
||||||
// It will work with y-websockets-client
|
// It will work with y-websockets-client
|
||||||
this.preferUntransformed = opts.preferUntransformed || false
|
|
||||||
if (opts.role == null || opts.role === 'master') {
|
if (opts.role == null || opts.role === 'master') {
|
||||||
this.role = 'master'
|
this.role = 'master'
|
||||||
} else if (opts.role === 'slave') {
|
} else if (opts.role === 'slave') {
|
||||||
@@ -817,7 +816,7 @@ module.exports = function (Y/* :any */) {
|
|||||||
}
|
}
|
||||||
reconnect () {
|
reconnect () {
|
||||||
this.log('reconnecting..')
|
this.log('reconnecting..')
|
||||||
this.y.db.startGarbageCollector()
|
return this.y.db.startGarbageCollector()
|
||||||
}
|
}
|
||||||
disconnect () {
|
disconnect () {
|
||||||
this.log('discronnecting..')
|
this.log('discronnecting..')
|
||||||
@@ -826,7 +825,8 @@ module.exports = function (Y/* :any */) {
|
|||||||
this.currentSyncTarget = null
|
this.currentSyncTarget = null
|
||||||
this.syncingClients = []
|
this.syncingClients = []
|
||||||
this.whenSyncedListeners = []
|
this.whenSyncedListeners = []
|
||||||
return this.y.db.stopGarbageCollector()
|
this.y.db.stopGarbageCollector()
|
||||||
|
return this.y.db.whenTransactionsFinished()
|
||||||
}
|
}
|
||||||
repair () {
|
repair () {
|
||||||
this.log('Repairing the state of Yjs. This can happen if messages get lost, and Yjs detects that something is wrong. If this happens often, please report an issue here: https://github.com/y-js/yjs/issues')
|
this.log('Repairing the state of Yjs. This can happen if messages get lost, and Yjs detects that something is wrong. If this happens often, please report an issue here: https://github.com/y-js/yjs/issues')
|
||||||
@@ -928,9 +928,6 @@ module.exports = function (Y/* :any */) {
|
|||||||
protocolVersion: conn.protocolVersion,
|
protocolVersion: conn.protocolVersion,
|
||||||
auth: conn.authInfo
|
auth: conn.authInfo
|
||||||
}
|
}
|
||||||
if (conn.preferUntransformed && Object.keys(stateSet).length === 0) {
|
|
||||||
answer.preferUntransformed = true
|
|
||||||
}
|
|
||||||
conn.send(syncUser, answer)
|
conn.send(syncUser, answer)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
@@ -1009,7 +1006,7 @@ module.exports = function (Y/* :any */) {
|
|||||||
}
|
}
|
||||||
if (message.auth != null && this.connections[sender] != null) {
|
if (message.auth != null && this.connections[sender] != null) {
|
||||||
// authenticate using auth in message
|
// authenticate using auth in message
|
||||||
var auth = this.checkAuth(message.auth, this.y)
|
var auth = this.checkAuth(message.auth, this.y, sender)
|
||||||
this.connections[sender].auth = auth
|
this.connections[sender].auth = auth
|
||||||
auth.then(auth => {
|
auth.then(auth => {
|
||||||
for (var f of this.userEventListeners) {
|
for (var f of this.userEventListeners) {
|
||||||
@@ -1022,7 +1019,7 @@ module.exports = function (Y/* :any */) {
|
|||||||
})
|
})
|
||||||
} else if (this.connections[sender] != null && this.connections[sender].auth == null) {
|
} else if (this.connections[sender] != null && this.connections[sender].auth == null) {
|
||||||
// authenticate without otherwise
|
// authenticate without otherwise
|
||||||
this.connections[sender].auth = this.checkAuth(null, this.y)
|
this.connections[sender].auth = this.checkAuth(null, this.y, sender)
|
||||||
}
|
}
|
||||||
if (this.connections[sender] != null && this.connections[sender].auth != null) {
|
if (this.connections[sender] != null && this.connections[sender].auth != null) {
|
||||||
return this.connections[sender].auth.then((auth) => {
|
return this.connections[sender].auth.then((auth) => {
|
||||||
@@ -1044,11 +1041,7 @@ module.exports = function (Y/* :any */) {
|
|||||||
protocolVersion: this.protocolVersion,
|
protocolVersion: this.protocolVersion,
|
||||||
auth: this.authInfo
|
auth: this.authInfo
|
||||||
}
|
}
|
||||||
if (message.preferUntransformed === true && Object.keys(m.stateSet).length === 0) {
|
|
||||||
answer.osUntransformed = yield* this.getOperationsUntransformed()
|
|
||||||
} else {
|
|
||||||
answer.os = yield* this.getOperations(m.stateSet)
|
answer.os = yield* this.getOperations(m.stateSet)
|
||||||
}
|
|
||||||
conn.send(sender, answer)
|
conn.send(sender, answer)
|
||||||
if (this.forwardToSyncingClients) {
|
if (this.forwardToSyncingClients) {
|
||||||
conn.syncingClients.push(sender)
|
conn.syncingClients.push(sender)
|
||||||
@@ -2533,7 +2526,7 @@ module.exports = function (Y/* :any */) {
|
|||||||
send.push(Y.Struct[op.struct].encode(op))
|
send.push(Y.Struct[op.struct].encode(op))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.store.y.connector.isSynced && send.length > 0) { // TODO: && !this.store.forwardAppliedOperations (but then i don't send delete ops)
|
if (send.length > 0) { // TODO: && !this.store.forwardAppliedOperations (but then i don't send delete ops)
|
||||||
// is connected, and this is not going to be send in addOperation
|
// is connected, and this is not going to be send in addOperation
|
||||||
this.store.y.connector.broadcastOps(send)
|
this.store.y.connector.broadcastOps(send)
|
||||||
}
|
}
|
||||||
@@ -3154,7 +3147,7 @@ module.exports = function (Y/* :any */) {
|
|||||||
}
|
}
|
||||||
* addOperation (op) {
|
* addOperation (op) {
|
||||||
yield* this.os.put(op)
|
yield* this.os.put(op)
|
||||||
if (this.store.y.connector.isSynced && this.store.forwardAppliedOperations && typeof op.id[1] !== 'string') {
|
if (this.store.forwardAppliedOperations && typeof op.id[1] !== 'string') {
|
||||||
// is connected, and this is not going to be send in addOperation
|
// is connected, and this is not going to be send in addOperation
|
||||||
this.store.y.connector.broadcastOps([op])
|
this.store.y.connector.broadcastOps([op])
|
||||||
}
|
}
|
||||||
@@ -3459,7 +3452,7 @@ module.exports = function (Y/* :any */) {
|
|||||||
var ops = []
|
var ops = []
|
||||||
yield* this.os.iterate(this, null, null, function * (op) {
|
yield* this.os.iterate(this, null, null, function * (op) {
|
||||||
if (op.id[0] !== '_') {
|
if (op.id[0] !== '_') {
|
||||||
ops.push(Y.Struct[op.struct].encode(op))
|
ops.push(op)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return {
|
return {
|
||||||
@@ -3563,6 +3556,24 @@ module.exports = function (Y/* :any */) {
|
|||||||
module.exports = function (Y /* : any*/) {
|
module.exports = function (Y /* : any*/) {
|
||||||
Y.utils = {}
|
Y.utils = {}
|
||||||
|
|
||||||
|
Y.utils.bubbleEvent = function (type, event) {
|
||||||
|
type.eventHandler.callEventListeners(event)
|
||||||
|
event.path = []
|
||||||
|
while (type != null && type._deepEventHandler != null) {
|
||||||
|
type._deepEventHandler.callEventListeners(event)
|
||||||
|
var parent = null
|
||||||
|
if (type._parent != null) {
|
||||||
|
parent = type.os.getType(type._parent)
|
||||||
|
}
|
||||||
|
if (parent != null && parent._getPathToChild != null) {
|
||||||
|
event.path = [parent._getPathToChild(type._model)].concat(event.path)
|
||||||
|
type = parent
|
||||||
|
} else {
|
||||||
|
type = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class EventListenerHandler {
|
class EventListenerHandler {
|
||||||
constructor () {
|
constructor () {
|
||||||
this.eventListeners = []
|
this.eventListeners = []
|
||||||
@@ -3587,7 +3598,11 @@ module.exports = function (Y /* : any*/) {
|
|||||||
callEventListeners (event) {
|
callEventListeners (event) {
|
||||||
for (var i = 0; i < this.eventListeners.length; i++) {
|
for (var i = 0; i < this.eventListeners.length; i++) {
|
||||||
try {
|
try {
|
||||||
this.eventListeners[i](event)
|
var _event = {}
|
||||||
|
for (var name in event) {
|
||||||
|
_event[name] = event[name]
|
||||||
|
}
|
||||||
|
this.eventListeners[i](_event)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Your observer threw an error. This error was caught so that Yjs still can ensure data consistency! In order to debug this error you have to check "Pause On Caught Exceptions"', e)
|
console.error('Your observer threw an error. This error was caught so that Yjs still can ensure data consistency! In order to debug this error you have to check "Pause On Caught Exceptions"', e)
|
||||||
}
|
}
|
||||||
@@ -3997,7 +4012,20 @@ module.exports = function (Y /* : any*/) {
|
|||||||
Default class of custom types!
|
Default class of custom types!
|
||||||
*/
|
*/
|
||||||
class CustomType {
|
class CustomType {
|
||||||
|
getPath () {
|
||||||
|
var parent = null
|
||||||
|
if (this._parent != null) {
|
||||||
|
parent = this.os.getType(this._parent)
|
||||||
|
}
|
||||||
|
if (parent != null && parent._getPathToChild != null) {
|
||||||
|
var firstKey = parent._getPathToChild(this._model)
|
||||||
|
var parentKeys = parent.getPath()
|
||||||
|
parentKeys.push(firstKey)
|
||||||
|
return parentKeys
|
||||||
|
} else {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Y.utils.CustomType = CustomType
|
Y.utils.CustomType = CustomType
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user