Hi,marijn
I want to update only the clientID of the collab plugin, is there a way to achieve this?
No, that has to be passed in when creating the extension and is assumed not to change. It seems odd to change the client ID in a running collab editing session. Wouldn’t it make more sense to reinitialize the entire extension?
I have a special need. When the browser requests agentuserid, it will first check whether there is an offline agentuserid, and assign it to the user if there is one. Therefore, the agentuserid assigned by tab(1) is 1 at the beginning, but it is not necessarily 1 after it is disconnected and reconnected. At this point, the clientID of the collab plugin needs to be updated.
Only the clinetID is updated, the rest of the logical processing does not need to be changed, the entire plug-in is reinitialized, is it reasonable?
I would suggest you give the extension some random client ID, and map between that and the client’s actual current ID in your communication layer (sendableUpdates
/receiveUpdates
).
Thanks, I’ll change my implementation
HI,marijn。
I follow the idea you provided to implement,but there is a problem。When the clientID specified by the receiveUpdates method is inconsistent with the clientID specified by the collab plugin。sendableUpdates will always have updates,resulting in an infinite loop of the following code
collab({
startVersion,
clientID: `${Math.random()}`,
sharedEffects: (tr) => {
return tr.selection
? [StateEffect.define<EditorSelection>().of(tr.selection)]
: [];
},
}),
// pushOTUpdates --- client to server
const fullUpdates= sendableUpdates(this.view.state);
const updates = fullUpdates.map((u) => {
return {
agentUserId: currentAgentUserId, // real clientID
changes: u.changes.toJSON(),
selection: u.origin.selection?.toJSON(),
};
});
// pushOTUpdates --- server to client
const mapUpdates = updates.map((u) => {
return {
changes: ChangeSet.fromJSON(u.changes),
clientID: u.agentUserId, // The value is currentAgentUserId
};
});
this.view.dispatch(receiveUpdates(this.view.state, mapUpdates));
const fullUpdates= sendableUpdates(this.view.state);
if(fullUpdates.length){
this,push(fullUpdates); // Execute the above client to server operation
}
It is also unreasonable to be consistent. Other users push their updates and cannot consume them.
Yes, that’s why I mention mapping from and to it. Don’t just push in a random ID and forget about it, but use a know value, so that you can update the data you get from and put into the extension to replace that ID with the proper client ID.
I saved clientIdMap in store. clientID maps to the current agentuserid。
The syncOT after reconnection is no longer consumed. Because the agentuserid is changed to the consumed agentuserid
clientIdMap: {
clientID: uuidv4(),
agentUserId: currentAgentUserId, // When user data changes, I update currentAgentUserId
}
// collab
collab({
clientID: clientIdMap.clientID,
sharedEffects: (tr) => {
return tr.selection
? [StateEffect.define<EditorSelection>().of(tr.selection)]
: [];
},
}),
// pushOT client to server
const fullUpdates= sendableUpdates(this.view.state);
const agentUserId = clientIdMap.agentUserId;
const updates = fullUpdates.map((u) => {
return {
agentUserId,
changes: u.changes.toJSON(),
selection: u.origin.selection?.toJSON(),
};
});
// syncOT server to client (After reconnection, actively sync the data of the server once)
const mapUpdates = updates.map((u) => { // updates from pushOT records from the server
const clientID =
u.agentUserId === clientIdMap.agentUserId
? clientIdMap.clientID
: u.agentUserId;
return {
changes: ChangeSet.fromJSON(u.changes),
clientID,
};
});
this.view.dispatch(receiveUpdates(this.view.state, mapUpdates));
It seems that the clientID must always be consistent, even if the collab plugin is refreshed midway. Also doesn’t do what I expect.
PS: Thank you very much for your patience