Skip to content

Commit

Permalink
Refactor presence event code in examples (#614)
Browse files Browse the repository at this point in the history
* Remove unused code

* Display remote cursors when the client connects to the document

* Apply quill changes to 'multi' example

* Refactor the presence event

* Change selection color to be set by the presence
  • Loading branch information
chacha912 authored Aug 14, 2023
1 parent 53185d5 commit 9ea05a4
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 119 deletions.
8 changes: 2 additions & 6 deletions public/counter.html
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,8 @@

// 02. create a document then attach it into the client.
const doc = new yorkie.Document('counter');
doc.subscribe('my-presence', (event) => {
if (event.type === 'initialized') {
displayOnlineClients(doc.getPresences(), client.getID());
}
});
doc.subscribe('others', (event) => {
doc.subscribe('presence', (event) => {
if (event.type === 'presence-changed') return;
displayOnlineClients(doc.getPresences(), client.getID());
});

Expand Down
9 changes: 3 additions & 6 deletions public/drawing.html
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,12 @@

// 02. create a document then attach it into the client.
const doc = new yorkie.Document('drawing-panel');
doc.subscribe('my-presence', (event) => {
doc.subscribe('presence', (event) => {
displayOnlineClients(doc.getPresences(), client.getID());
if (event.type === 'presence-changed' && doc.getRoot().shapes) {
if (event.type === 'presence-changed') {
paintCanvas();
}
});
doc.subscribe('others', (event) => {
displayOnlineClients(doc.getPresences(), client.getID());
paintCanvas();
});
await client.attach(doc);

let draftShape = null;
Expand All @@ -77,6 +73,7 @@
context.clearRect(0, 0, 500, 500);

const shapes = doc.getRoot().shapes;
if (!shapes) return;
for (const shape of shapes) {
context.beginPath();
let isMoved = false;
Expand Down
87 changes: 43 additions & 44 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,6 @@
<script src="./yorkie.js"></script>
<script src="./util.js"></script>
<script>
const colors = ['#FECEEA', '#FEF1D2', '#A9FDD8', '#D7F8FF', '#CEC5FA'];
let nextColorIdx = 0;

const statusHolder = document.getElementById('network-status');
const placeholder = document.getElementById('placeholder');
const onlineClientsHolder = document.getElementById(
Expand All @@ -40,6 +37,12 @@
const textLogHolder = document.getElementById('text-log-holder');
const selectionMap = new Map();

function getRandomColor() {
const colors = ['#FECEEA', '#FEF1D2', '#A9FDD8', '#D7F8FF', '#CEC5FA'];
const randomIndex = Math.floor(Math.random() * colors.length);
return colors[randomIndex];
}

function displayLog(doc, codemirror) {
logHolder.innerText = doc.toJSON();

Expand Down Expand Up @@ -83,46 +86,50 @@
});
}

function displayRemoteSelection(cm, change, actor) {
let color;
if (selectionMap.has(actor)) {
const selection = selectionMap.get(actor);
color = selection.color;
function displayRemoteSelection(cm, doc, user) {
const { clientID, presence } = user;
if (!presence.selection) return;
if (selectionMap.has(clientID)) {
const selection = selectionMap.get(clientID);
selection.marker.clear();
} else {
color = colors[nextColorIdx];
nextColorIdx = (nextColorIdx + 1) % colors.length;
}

if (change.from === change.to) {
const pos = cm.posFromIndex(change.from);
const [from, to] = doc
.getRoot()
.content.posRangeToIndexRange(presence.selection);

console.log(
`%c remote selection from:${from} to:${to}`,
'color: skyblue',
);

if (from === to) {
const pos = cm.posFromIndex(from);
const cursorCoords = cm.cursorCoords(pos);
const cursorElement = document.createElement('span');
cursorElement.style.borderLeftWidth = '2px';
cursorElement.style.borderLeftStyle = 'solid';
cursorElement.style.borderLeftColor = color;
cursorElement.style.borderLeftColor = presence.color;
cursorElement.style.marginLeft = cursorElement.style.marginRight =
'-1px';
cursorElement.style.height =
(cursorCoords.bottom - cursorCoords.top) * 0.9 + 'px';
cursorElement.setAttribute('data-actor-id', actor);
cursorElement.setAttribute('data-actor-id', clientID);
cursorElement.style.zIndex = 0;

selectionMap.set(actor, {
color: color,
selectionMap.set(clientID, {
marker: cm.setBookmark(pos, {
widget: cursorElement,
insertLeft: true,
}),
});
} else {
const fromPos = cm.posFromIndex(Math.min(change.from, change.to));
const toPos = cm.posFromIndex(Math.max(change.from, change.to));
const fromPos = cm.posFromIndex(Math.min(from, to));
const toPos = cm.posFromIndex(Math.max(from, to));

selectionMap.set(actor, {
color: color,
selectionMap.set(clientID, {
marker: cm.markText(fromPos, toPos, {
css: `background: ${color}`,
css: `background: ${presence.color}`,
insertLeft: true,
}),
});
Expand All @@ -141,12 +148,14 @@

// 02. create a document then attach it into the client.
const doc = new yorkie.Document('codemirror');
doc.subscribe('my-presence', (event) => {
if (event.type === 'initialized') {
displayOnlineClients(doc.getPresences(), client.getID());
}
doc.subscribe('presence', (event) => {
if (event.type === 'presence-changed') return;
displayOnlineClients(doc.getPresences(), client.getID());
});

await client.attach(doc, {
initialPresence: { color: getRandomColor() },
});
await client.attach(doc);

doc.update((root) => {
if (!root.content) {
Expand All @@ -163,28 +172,14 @@
});

doc.subscribe('others', (event) => {
if (event.type === 'watched') {
displayOnlineClients(doc.getPresences(), client.getID());
} else if (event.type === 'unwatched') {
displayOnlineClients(doc.getPresences(), client.getID());
if (event.type === 'unwatched') {
const { clientID } = event.value;
if (selectionMap.has(clientID)) {
const selection = selectionMap.get(clientID);
selection.marker.clear();
}
} else if (event.type === 'presence-changed') {
const { clientID, presence } = event.value;
const range = doc
.getRoot()
.content.posRangeToIndexRange(presence.selection);
displayRemoteSelection(
codemirror,
{
from: range[0],
to: range[1],
},
clientID,
);
displayRemoteSelection(codemirror, doc, event.value);
}
});

Expand Down Expand Up @@ -253,7 +248,7 @@
// NOTE: The following conditional statement ignores cursor changes
// that occur while applying remote changes to CodeMirror
// and handles only movement by keyboard and mouse.
if (!change.origin) {
if (change.origin === undefined) {
return;
}

Expand Down Expand Up @@ -289,6 +284,10 @@
// 05. synchronize text of document and codemirror.
codemirror.setValue(doc.getRoot().content.toString());
displayLog(doc, codemirror);
for (const user of doc.getPresences()) {
if (user.clientID === client.getID()) continue;
displayRemoteSelection(codemirror, doc, user);
}
} catch (e) {
console.error(e);
}
Expand Down
56 changes: 28 additions & 28 deletions public/multi.html
Original file line number Diff line number Diff line change
Expand Up @@ -92,15 +92,9 @@ <h2>yorkie document</h2>

// 02. create a document then attach it into the client.
const doc = new yorkie.Document('multi-example');
doc.subscribe('my-presence', (event) => {
if (event.type === 'initialized') {
displayOnlineClients(doc.getPresences(), client.getID());
}
});
doc.subscribe('others', (event) => {
if (event.type === 'watched' || event.type === 'unwatched') {
displayOnlineClients(doc.getPresences(), client.getID());
}
doc.subscribe('presence', (event) => {
if (event.type === 'presence-changed') return;
displayOnlineClients(doc.getPresences(), client.getID());
});

doc.subscribe((event) => {
Expand Down Expand Up @@ -261,23 +255,9 @@ <h2>yorkie document</h2>
});
doc.subscribe('others', (event) => {
if (event.type === 'unwatched') {
const { clientID } = event.value;
cursors.removeCursor(doc.getPresence(clientID).username);
cursors.removeCursor(event.value.presence.username);
} else if (event.type === 'presence-changed') {
const { clientID, presence } = event.value;
const range = doc
.getRoot()
.content.posRangeToIndexRange(presence.selection);

cursors.createCursor(
presence.username,
presence.username,
colorHash.hex(presence.username),
);
cursors.moveCursor(presence.username, {
index: range[0],
length: range[1] - range[0],
});
displayRemoteCursor(event.value);
}
});

Expand Down Expand Up @@ -305,6 +285,19 @@ <h2>yorkie document</h2>
theme: 'snow',
});
const cursors = quill.getModule('cursors');
function displayRemoteCursor(user) {
const {
clientID: id,
presence: { username, selection },
} = user;
if (!selection || id === client.getID()) return;
const range = doc.getRoot().content.posRangeToIndexRange(selection);
cursors.createCursor(username, username, colorHash.hex(username));
cursors.moveCursor(username, {
index: range[0],
length: range[1] - range[0],
});
}

// 05-1. Quill to Document.
quill
Expand Down Expand Up @@ -369,8 +362,13 @@ <h2>yorkie document</h2>
to = from + op.delete;
console.log(`%c local: ${from}-${to}: ''`, 'color: green');

doc.update((root) => {
root.content.edit(from, to, '');
doc.update((root, presence) => {
const range = root.content.edit(from, to, '');
if (range) {
presence.set({
selection: root.content.indexRangeToPosRange(range),
});
}
}, `update content by ${client.getID()}`);
} else if (op.retain !== undefined) {
from = to + op.retain;
Expand Down Expand Up @@ -459,7 +457,6 @@ <h2>yorkie document</h2>
// 05-3. synchronize text of document and Quill.
function syncText() {
const text = doc.getRoot().content;

const delta = {
ops: text.values().map((val) => toDeltaOperation(val)),
};
Expand All @@ -470,6 +467,9 @@ <h2>yorkie document</h2>
displayCount();
displayTodos();
displayLog();
for (const user of doc.getPresences()) {
displayRemoteCursor(user);
}
} catch (e) {
console.error(e);
}
Expand Down
57 changes: 22 additions & 35 deletions public/quill.html
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,9 @@

// 02. create a document then attach it into the client.
const doc = new yorkie.Document(documentKey);
doc.subscribe('my-presence', (event) => {
if (event.type === 'initialized') {
displayOnlineClients(doc.getPresences(), client.getID());
}
});
doc.subscribe('others', (event) => {
if (event.type === 'watched' || event.type === 'unwatched') {
displayOnlineClients(doc.getPresences(), client.getID());
}
doc.subscribe('presence', (event) => {
if (event.type === 'presence-changed') return;
displayOnlineClients(doc.getPresences(), client.getID());
});

await client.attach(doc, {
Expand Down Expand Up @@ -110,23 +104,9 @@
});
doc.subscribe('others', (event) => {
if (event.type === 'unwatched') {
const { clientID, presence } = event.value;
cursors.removeCursor(presence.username);
cursors.removeCursor(event.value.presence.username);
} else if (event.type === 'presence-changed') {
const { clientID, presence } = event.value;
const range = doc
.getRoot()
.content.posRangeToIndexRange(presence.selection);

cursors.createCursor(
presence.username,
presence.username,
colorHash.hex(presence.username),
);
cursors.moveCursor(presence.username, {
index: range[0],
length: range[1] - range[0],
});
displayRemoteCursor(event.value);
}
});

Expand Down Expand Up @@ -158,6 +138,20 @@
});
const cursors = quill.getModule('cursors');

function displayRemoteCursor(user) {
const {
clientID: id,
presence: { username, selection },
} = user;
if (!selection || id === client.getID()) return;
const range = doc.getRoot().content.posRangeToIndexRange(selection);
cursors.createCursor(username, username, colorHash.hex(username));
cursors.moveCursor(username, {
index: range[0],
length: range[1] - range[0],
});
}

// 04. bind the document with the Quill.
// 04-1. Quill to Document.
quill
Expand Down Expand Up @@ -300,16 +294,6 @@

deltaOperations.push(deltaOp);
}
} else if (op.type === 'select') {
cursors.createCursor(
actorName,
actorName,
colorHash.hex(actorName),
);
cursors.moveCursor(actorName, {
index: from,
length: retainTo,
});
}

prevTo = to;
Expand All @@ -335,6 +319,9 @@

syncText();
displayLog(documentElem, documentTextElem, doc);
for (const user of doc.getPresences()) {
displayRemoteCursor(user);
}
} catch (e) {
console.error(e);
}
Expand Down

0 comments on commit 9ea05a4

Please sign in to comment.