Discussions related to Shared Editing, Distributed Apps, and Yjs. Questions about Yjs should go to discuss.yjs.dev. Bug reports to the issue tracker.
Hi @dmonad Yes, I concluded that the origin is always the provider and cannot be reassigned. But I am still keen to label a transaction with the client that originated it. I note that the transaction object has a meta field, which is a map, but it doesn't seem to be possible for a client to set the map (am I right?). Can you think of any other way of labelling a transaction with the originating client, such that the originating client Id would be visible to peers that observe the transaction?
That's not possible unformutately, as changes from multiple clients are often bundled. Then you could use something like the versioning approach that allows you to store which user created which content.
y-protocols
instead?
Hello everyone :)
I've just started with yjs and have found it amazing! I'm particularly interested in the subdocuments feature, but i'm facing some issues with the example in the docs (https://docs.yjs.dev/api/subdocuments) - it doesn't seem to be working right.
Here's what the docs say
A new feature that was introduced in Yjs@13.4.0 is that all documents are given a GUID. The documents are identified with GUIDs and used as a room-name to sync documents. This allows you to duplicate data in the document structure.
Here's some sample code:
const rootDoc = new Y.Doc();const doc = new Y.Doc(); doc.getMap().set("data", "some initial data");
rootDoc.getMap().set("file.txt", doc);
const copy = new Y.Doc({ guid: doc.guid });
rootDoc.getMap().set("copy.txt", copy);
console.log(copy.getMap().get("data"));
console.log(doc.getMap().get("data"));
Here's the output:
undefined
some initial data
Shouldn't the output be the same? Or did I miss something here? Any help is appreciated! Thank you.
i have built an application in which users can create diagrams for a specific domain, and work on them collaboratively. This application uses yjs + y-websocket for this. Awareness is used heavily for different features.
I want to build a feature where a diagram can be made accessible publically, but everyone viewing the diagram loads a local copy of the diagram and can interact with it.
I want to re-use the core engine which is used by the diagram editor, and load the yDoc in it. The problem is that awareness is used to keep track of collaborator cursor, object drags, object highlights and so on.
I want an awareness implementation that operates locally. Is there some way to make this work?
i have built an application in which users can create diagrams for a specific domain, and work on them collaboratively. This application uses yjs + y-websocket for this. Awareness is used heavily for different features.
I want to build a feature where a diagram can be made accessible publically, but everyone viewing the diagram loads a local copy of the diagram and can interact with it.
I want to re-use the core engine which is used by the diagram editor, and load the yDoc in it. The problem is that awareness is used to keep track of collaborator cursor, object drags, object highlights and so on.
I want an awareness implementation that operates locally. Is there some way to make this work?
by the way I managed to do this by building a local-awareness-provider :)
js/prsm.js
)
webrtc
provider btw, can't find much info on its events
Hello friends,
I want to subscribe Yjs events to update my React state!!!
So users will type down using a rich text editor. The output is xmlFragment. Now i would like to represent the output in HTML using React. However, I want to update only parts that have changed using to re-render only thoes parts. Is there any solution for this problem
any Ideas ?
useSyncExternalStoreWithSelector
to update the react tree efficiently.
@dmonad I'm running into an issue with using yjs for a collaborative text editing tool. When I inspect the IndexedDB database, it appears that the initial state update is getting stored twice. The documents can be quite large, so I don't want to waste all of this space.
That said, I'm trying to understand encodeStateAsUpdate
's second parameter, as it appears to exist to mitigate this issue, but it isn't operating the way I expect. My understanding is that if you supply the same state as the target object, you should get a very small or nonexistent update, but that's not happening.
Example code for testing:
const docA = new Y.Doc();
const docB = new Y.Doc();
docB.on('update', (update: Uint8Array) => {
console.log('update', update);
});
docA.getMap().set('name', new Y.Text('El Pollo Diablo'));
docB.getMap().set('name', new Y.Text('El Pollo Diablo'));
const docBState = Y.encodeStateVector(docB);
const update = Y.encodeStateAsUpdate(docA, docBState);
console.log('before update');
Y.applyUpdate(docB, update);
console.log('after update');
console.log(docA.getMap().toJSON());
console.log(docB.getMap().toJSON());
Output:
update Uint8Array(42) [
1, 2, 168, 154, 142, 211, 8, 0, 39, 1,
0, 4, 110, 97, 109, 101, 2, 4, 0, 168,
154, 142, 211, 8, 0, 15, 69, 108, 32, 80,
111, 108, 108, 111, 32, 68, 105, 97, 98, 108,
111, 0
]
before update
update Uint8Array(50) [
1, 2, 152, 205, 189, 164, 9, 0, 39, 1, 0,
4, 110, 97, 109, 101, 2, 4, 0, 152, 205, 189,
164, 9, 0, 15, 69, 108, 32, 80, 111, 108, 108,
111, 32, 68, 105, 97, 98, 108, 111, 1, 168, 154,
142, 211, 8, 1, 0, 16
]
after update
{ name: 'El Pollo Diablo' }
{ name: 'El Pollo Diablo' }
encodeStateAsUpdate
?
Yjs never performs a diff between states (we don't even include any kind of diffing library in Yjs). It simply exchanges operations and transforms them so that everyone ends up with the same content.
In your case, you simply perform the operation: set YText("El Pollo Diabolo") in a Y.Map with the key 'name'. One of the edits will win and overwrite the other state. Instead, you should perform operations on the Y.Text if you want more granular merges.