Compare commits

..

14 Commits

Author SHA1 Message Date
Kevin Jahns
013fee2421 v13.0.0-7 -- distribution files 2017-07-22 01:17:21 +02:00
Kevin Jahns
bb45abbb70 13.0.0-7 2017-07-22 01:16:50 +02:00
Kevin Jahns
67b47fd868 bugfix - sync step 2 also authenticates) 2017-07-22 01:15:13 +02:00
Kevin Jahns
2c18b9ffad 13.0.0-6 2017-07-21 23:56:13 +02:00
Kevin Jahns
a6b7d76544 bugfix: unable to deliver message. fixes receiving message before authentication 2017-07-21 23:55:11 +02:00
Kevin Jahns
442ea7ec70 13.0.0-5 2017-07-19 21:22:37 +02:00
Kevin Jahns
747da52c0b fix two clients syncing at the time 2017-07-19 21:19:41 +02:00
Kevin Jahns
cd3f4a72d6 13.0.0-4 2017-07-06 15:17:23 +02:00
Kevin Jahns
2c852c85c6 add node build 2017-07-06 15:16:13 +02:00
Kevin Jahns
434ec84837 13.0.0-3 2017-07-06 03:29:09 +02:00
Kevin Jahns
2b618cd83c change to correct main file 2017-07-06 03:28:06 +02:00
Kevin Jahns
f4327529b9 13.0.0-2 2017-07-05 18:41:26 +02:00
Kevin Jahns
67189f4d44 dont lint in postversion 2017-07-05 18:40:41 +02:00
Kevin Jahns
6225fb4dfd fix linting of examples 2017-07-05 18:33:16 +02:00
22 changed files with 23141 additions and 69 deletions

14
.gitignore vendored
View File

@@ -1,15 +1,3 @@
node_modules
bower_components
build
build_test
.directory
.codio
.settings
.jshintignore
.jshintrc
.validate.json
/y.js
/y.js.map
/y-*
.vscode
jsconfig.json
/y.*

View File

@@ -1,5 +1,4 @@
/* @flow */
/* global Y */
/* global Y, chat */
// initialize a shared object. This function call returns a promise!
Y({
@@ -17,10 +16,10 @@ Y({
}).then(function (y) {
window.yChat = y
// This functions inserts a message at the specified position in the DOM
function appendMessage(message, position) {
function appendMessage (message, position) {
var p = document.createElement('p')
var uname = document.createElement('span')
uname.appendChild(document.createTextNode(message.username + ": "))
uname.appendChild(document.createTextNode(message.username + ': '))
p.appendChild(uname)
p.appendChild(document.createTextNode(message.message))
document.querySelector('#chat').insertBefore(p, chat.children[position] || null)
@@ -28,23 +27,22 @@ Y({
// This function makes sure that only 7 messages exist in the chat history.
// The rest is deleted
function cleanupChat () {
var len
while ((len = y.share.chat.length) > 7) {
y.share.chat.delete(0)
if (y.share.chat.length > 7) {
y.share.chat.delete(0, y.chat.length - 7)
}
}
// Insert the initial content
y.share.chat.toArray().forEach(appendMessage)
cleanupChat()
// whenever content changes, make sure to reflect the changes in the DOM
y.share.chat.observe(function (event) {
if (event.type === 'insert') {
for (var i = 0; i < event.length; i++) {
for (let i = 0; i < event.length; i++) {
appendMessage(event.values[i], event.index + i)
}
} else if (event.type === 'delete') {
for (var i = 0; i < event.length; i++) {
for (let i = 0; i < event.length; i++) {
chat.children[event.index].remove()
}
}
@@ -54,8 +52,8 @@ Y({
document.querySelector('#chatform').onsubmit = function (event) {
// the form is submitted
var message = {
username: this.querySelector("[name=username]").value,
message: this.querySelector("[name=message]").value
username: this.querySelector('[name=username]').value,
message: this.querySelector('[name=message]').value
}
if (message.username.length > 0 && message.message.length > 0) {
if (y.share.chat.length > 6) {
@@ -66,10 +64,10 @@ Y({
// This will call the observe function (see line 40)
// and reflect the change in the DOM
y.share.chat.push([message])
this.querySelector("[name=message]").value = ""
this.querySelector('[name=message]').value = ''
}
// Do not send this form!
event.preventDefault()
return false
}
})
})

View File

@@ -19,11 +19,16 @@ Y({
}
}).then(function (y) {
window.yJigsaw = y
var origin // mouse start position - translation of piece
var origin // mouse start position - translation of piece
var drag = d3.behavior.drag()
.on('dragstart', function (params) {
// get the translation of the element
var translation = d3.select(this).attr('transform').slice(10,-1).split(',').map(Number)
var translation = d3
.select(this)
.attr('transform')
.slice(10, -1)
.split(',')
.map(Number)
// mouse coordinates
var mouse = d3.mouse(this.parentNode)
origin = {
@@ -31,11 +36,11 @@ Y({
y: mouse[1] - translation[1]
}
})
.on("drag", function(){
.on('drag', function () {
var mouse = d3.mouse(this.parentNode)
var x = mouse[0] - origin.x // =^= mouse - mouse at dragstart + translation at dragstart
var y = mouse[1] - origin.y
d3.select(this).attr("transform", "translate(" + x + "," + y + ")")
d3.select(this).attr('transform', 'translate(' + x + ',' + y + ')')
})
.on('dragend', function (piece, i) {
// save the current translation of the puzzle piece
@@ -46,24 +51,24 @@ Y({
})
var data = [y.share.piece1, y.share.piece2, y.share.piece3, y.share.piece4]
var pieces = d3.select(document.querySelector("#puzzle-example")).selectAll("path").data(data)
var pieces = d3.select(document.querySelector('#puzzle-example')).selectAll('path').data(data)
pieces
.classed('draggable', true)
.attr("transform", function (piece) {
.attr('transform', function (piece) {
var translation = piece.get('translation') || {x: 0, y: 0}
return "translate(" + translation.x + "," + translation.y + ")"
return 'translate(' + translation.x + ',' + translation.y + ')'
}).call(drag)
data.forEach(function(piece){
data.forEach(function (piece) {
piece.observe(function () {
// whenever a property of a piece changes, update the translation of the pieces
pieces
.transition()
.attr("transform", function (piece) {
.attr('transform', function (piece) {
var translation = piece.get('translation') || {x: 0, y: 0}
return "translate(" + translation.x + "," + translation.y + ")"
return 'translate(' + translation.x + ',' + translation.y + ')'
})
})
})
})
})

View File

@@ -1,8 +1,8 @@
/* global Y */
/* global Y, monaco */
require.config({ paths: { 'vs': '../node_modules/monaco-editor/min/vs' }})
require(['vs/editor/editor.main'], function() {
require.config({ paths: { 'vs': '../node_modules/monaco-editor/min/vs' } })
require(['vs/editor/editor.main'], function () {
// Initialize a shared object. This function call returns a promise!
Y({
db: {
@@ -28,4 +28,3 @@ require(['vs/editor/editor.main'], function() {
y.share.monaco.bindMonaco(editor)
})
})

1173
examples/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -6,5 +6,11 @@
"license": "MIT",
"dependencies": {
"monaco-editor": "^0.8.3"
},
"devDependencies": {
"standard": "^10.0.2"
},
"standard": {
"ignore": ["bower_components"]
}
}

View File

@@ -29,11 +29,11 @@ Y({
[{ script: 'sub' }, { script: 'super' }],
['link', 'image'],
['link', 'code-block'],
[{list: 'ordered' }]
[{ list: 'ordered' }]
]
},
theme: 'snow'
});
})
// bind quill to richtext type
y.share.richtext.bind(window.quill)
})
})

View File

@@ -1,13 +1,13 @@
/* global Y, Quill */
// register yjs service worker
if('serviceWorker' in navigator){
if ('serviceWorker' in navigator) {
// Register service worker
// it is important to copy yjs-sw-template to the root directory!
navigator.serviceWorker.register('./yjs-sw-template.js').then(function(reg){
console.log("Yjs service worker registration succeeded. Scope is " + reg.scope);
}).catch(function(err){
console.error("Yjs service worker registration failed with error " + err);
navigator.serviceWorker.register('./yjs-sw-template.js').then(function (reg) {
console.log('Yjs service worker registration succeeded. Scope is ' + reg.scope)
}).catch(function (err) {
console.error('Yjs service worker registration failed with error ' + err)
})
}
@@ -39,7 +39,7 @@ Y({
[{ script: 'sub' }, { script: 'super' }],
['link', 'image'],
['link', 'code-block'],
[{list: 'ordered' }]
[{ list: 'ordered' }]
]
},
theme: 'snow'

View File

@@ -6,7 +6,7 @@
<script src="../../../y-array/y-array.js"></script>
<script src="../../../y-text/dist/y-text.js"></script>
<script src="../../../y-memory/y-memory.js"></script>
<script src="../../../y-websockets-client/dist/y-websockets-client.js"></script>
<script src="../../../y-websockets-client/y-websockets-client.js"></script>
<script src="./index.js"></script>
</body>
</html>

View File

@@ -7,7 +7,7 @@ Y({
},
connector: {
name: 'websockets-client',
room: 'Textarea-example'
room: 'Textarea-example-dev'
// url: '127.0.0.1:1234'
},
sourceDir: '/bower_components',

2
package-lock.json generated
View File

@@ -1,6 +1,6 @@
{
"name": "yjs",
"version": "13.0.0-1",
"version": "13.0.0-7",
"lockfileVersion": 1,
"dependencies": {
"acorn": {

View File

@@ -1,13 +1,15 @@
{
"name": "yjs",
"version": "13.0.0-1",
"version": "13.0.0-7",
"description": "A framework for real-time p2p shared editing on any data",
"main": "./src/y.js",
"main": "./y.node.js",
"browser": "./y.js",
"module": "./src/y.js",
"scripts": {
"test": "npm run lint",
"lint": "standard",
"dist": "rollup -c rollup.dist.js",
"serve": "concurrently 'serve ..' 'rollup -wc rollup.dist.js -o examples/bower_components/yjs/y.js'",
"postversion": "npm run lint && npm run dist",
"dist": "rollup -c rollup.browser.js; rollup -c rollup.node.js",
"postversion": "npm run dist",
"postpublish": "tag-dist-files --overwrite-existing-tag"
},
"files": [

26
rollup.node.js Normal file
View File

@@ -0,0 +1,26 @@
import nodeResolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs'
var pkg = require('./package.json')
export default {
entry: 'src/y.js',
moduleName: 'Y',
format: 'umd',
plugins: [
nodeResolve({
main: true,
module: true,
browser: true
}),
commonjs()
],
dest: 'y.node.js',
sourceMap: true,
banner: `
/**
* ${pkg.name} - ${pkg.description}
* @version v${pkg.version}
* @license ${pkg.license}
*/
`
}

View File

@@ -1,5 +1,3 @@
/* @flow */
'use strict'
function canRead (auth) { return auth === 'read' || auth === 'write' }
function canWrite (auth) { return auth === 'write' }
@@ -143,7 +141,9 @@ export default function extendConnector (Y/* :any */) {
this.log('User joined: %s', user)
this.connections[user] = {
isSynced: false,
role: role
role: role,
waitingMessages: [],
auth: null
}
let defer = {}
defer.promise = new Promise(function (resolve) { defer.resolve = resolve })
@@ -269,11 +269,20 @@ export default function extendConnector (Y/* :any */) {
})
return Promise.reject(new Error('Incompatible protocol version'))
}
if (message.auth != null && this.connections[sender] != null) {
if ((message.type === 'sync step 1' || message.type === 'sync step 2') && this.connections[sender] != null && this.connections[sender].auth == null) {
// authenticate using auth in message
var auth = this.checkAuth(message.auth, this.y)
this.connections[sender].auth = auth
auth.then(auth => {
// in case operations were received before sender was received
// we apply the messages after authentication
this.connections[sender].syncStep2.promise.then(() => {
// we do it after sync step 1
this.connections[sender].waitingMessages.forEach(msg => {
this.receiveMessage(sender, msg)
})
this.connections[sender].waitingMessages = null
})
for (var f of this.userEventListeners) {
f({
action: 'userAuthenticated',
@@ -282,9 +291,6 @@ export default function extendConnector (Y/* :any */) {
})
}
})
} else if (this.connections[sender] != null && this.connections[sender].auth == null) {
// authenticate without otherwise
this.connections[sender].auth = this.checkAuth(null, this.y)
}
if (this.connections[sender] != null && this.connections[sender].auth != null) {
return this.connections[sender].auth.then((auth) => {
@@ -384,8 +390,13 @@ export default function extendConnector (Y/* :any */) {
this.y.db.apply(message.ops)
}
})
} else if (this.connections[sender] != null) {
// wait for authentication
let senderConn = this.connections[sender]
senderConn.waitingMessages = senderConn.waitingMessages || []
senderConn.waitingMessages.push(message)
} else {
return Promise.reject(new Error('Unable to deliver message'))
return Promise.reject(new Error('Unknown user - Unable to deliver message'))
}
}
_setSyncedWith (user) {

View File

@@ -96,7 +96,7 @@ export default function extendTransaction (Y) {
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
this.store.y.connector.broadcastOps(send)
}
@@ -712,7 +712,7 @@ export default function extendTransaction (Y) {
}
* addOperation (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
this.store.y.connector.broadcastOps([op])
}

9
y.js Normal file

File diff suppressed because one or more lines are too long

1
y.js.map Normal file

File diff suppressed because one or more lines are too long

4255
y.node.js Normal file

File diff suppressed because it is too large Load Diff

1
y.node.js.map Normal file

File diff suppressed because one or more lines are too long

17597
y.test.js Normal file

File diff suppressed because one or more lines are too long

1
y.test.js.map Normal file

File diff suppressed because one or more lines are too long