Skip to content

Commit

Permalink
Replace Tree.onChanges with Document.subscribe (#523)
Browse files Browse the repository at this point in the history
Co-authored-by: hackerwins <[email protected]>
Co-authored-by: JOOHOJANG <[email protected]>
  • Loading branch information
3 people authored Jun 8, 2023
1 parent 8151e8a commit b5cb95a
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 120 deletions.
72 changes: 56 additions & 16 deletions public/prosemirror.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<script src="./yorkie.js"></script>
<script src="./util.js"></script>
</head>

<body>
<div class="layout">
<div class="application">
Expand Down Expand Up @@ -35,11 +36,11 @@ <h2>Transaction</h2>
<div class="data-view">
<div class="tree-view">
<div class="yorkie">
<h2>Yorkie IndexTree</h2>
<h2>Yorkie.IndexTree</h2>
<div id="yorkie-log" class="log-view"></div>
</div>
<div class="list-view">
<h2>Yorkie LinkedList</h2>
<h2>Yorkie.RGASplit</h2>
<div id="yorkie-list-log" class="log-list-view"></div>
</div>
</div>
Expand Down Expand Up @@ -147,6 +148,9 @@ <h2>Yorkie LinkedList</h2>
],
};

/**
* `docToTreeNode` converts ProseMirror's document to Yorkie.TreeNode.
*/
function docToTreeNode(pmNode) {
if (pmNode.type === 'text') {
return {
Expand All @@ -159,12 +163,16 @@ <h2>Yorkie LinkedList</h2>
type: pmNode.type,
children: [],
};
for (const child of pmNode.content) {
const content = pmNode.content || [];
for (const child of content) {
node.children.push(docToTreeNode(child));
}
return node;
}

/**
* `treeNodeToDoc` converts Yorkie.TreeNode to ProseMirror's document.
*/
function treeNodeToDoc(treeNode) {
if (treeNode.type === 'text') {
return {
Expand Down Expand Up @@ -273,7 +281,7 @@ <h2>Yorkie LinkedList</h2>
type: 'selection',
selection: transaction.curSelection,
});
showLog();
printLog();
return;
}

Expand Down Expand Up @@ -325,23 +333,56 @@ <h2>Yorkie LinkedList</h2>
}
}
});
showLog();
printLog();
},
});

// 03. Downstream: yorkie.Tree to ProseMirror.
doc.subscribe('$.tree', (event) => {
if (event.type !== 'remote-change') {
return;
}

for (const change of event.value) {
const { operations } = change;
for (const op of operations) {
if (op.type !== 'tree-edit') {
continue;
}
const { from, to, value: content } = op;
const transform = view.state.tr;
if (content) {
transform.replaceWith(
from,
to,
Node.fromJSON(mySchema, {
type: content.type,
text: content.value,
}),
);
} else {
transform.replace(from, to);
}
const newState = view.state.apply(transform);
view.updateState(newState);
}
printLog();
}
});

window.view = view;
view.focus();
showLog();
printLog();
}

document.getElementById('tr-log').onclick = (e) => {
const index = e.target.getAttribute('data-index');
if (index) {
showTransaction(+index);
printTransaction(+index);
}
};

function showTransaction(index) {
function printTransaction(index) {
const t = window.transactions[index || 0];

if (t) {
Expand All @@ -354,20 +395,19 @@ <h2>Yorkie LinkedList</h2>
2,
)}</pre>`;
} else {
document.getElementById('tr-info').innerHTML = `<pre>
selection : ${JSON.stringify(
document.getElementById(
'tr-info',
).innerHTML = `<pre>selection: ${JSON.stringify(
t.transaction.curSelection.toJSON(),
null,
2,
)}
transaction
${JSON.stringify(t.transaction.steps, null, 2)}
</pre>`;
)}, steps: ${JSON.stringify(t.transaction.steps, null, 2)}
</pre>`;
}
}
}

function showLog() {
function printLog() {
// how to show transaction view
document.getElementById('tr-log').innerHTML = window.transactions
.slice(0, 100)
Expand All @@ -379,7 +419,7 @@ <h2>Yorkie LinkedList</h2>
return `<span data-index="${index}" class="tr-item">T</span>`;
})
.join('');
showTransaction();
printTransaction();

printDoc(doc.getRoot().tree.tree.getRoot(), 'yorkie-log');
printDoc(view.state.doc, 'pm-log');
Expand Down
32 changes: 5 additions & 27 deletions src/document/crdt/tree.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { ActorID } from './../time/actor_id';
/*
* Copyright 2023 The Yorkie Authors. All rights reserved.
*
Expand Down Expand Up @@ -27,6 +26,7 @@ import {
TreeNodeType,
traverse,
} from '@yorkie-js-sdk/src/util/index_tree';
import { ActorID } from './../time/actor_id';
import { LLRBTree } from '@yorkie-js-sdk/src/util/llrb_tree';

/**
Expand Down Expand Up @@ -70,6 +70,8 @@ export interface TreeChange {
type: TreeChangeType;
from: number;
to: number;
fromPath: Array<number>;
toPath: Array<number>;
value?: TreeNode;
}

Expand Down Expand Up @@ -300,9 +302,6 @@ function toStructure(node: CRDTTreeNode): TreeNodeForTest {
* `CRDTTree` is a CRDT implementation of a tree.
*/
export class CRDTTree extends CRDTElement {
public onChangesHandler?: () => void;
public changeCollector?: (changes: Array<TreeChange>) => void;

private dummyHead: CRDTTreeNode;
private indexTree: IndexTree<CRDTTreeNode>;
private nodeMapByPos: LLRBTree<CRDTTreePos, CRDTTreeNode>;
Expand Down Expand Up @@ -338,21 +337,6 @@ export class CRDTTree extends CRDTElement {
this.indexTree.nodesBetween(from, to, callback);
}

/**
* `onChanges` registers a handler of onChanges event.
*/
public onChanges(handler: () => void): void {
this.onChangesHandler = handler;
}

/**
* `onChanges` registers a handler of onChanges event.
*/
public onChangeCollect(
collector: (changes: Array<TreeChange>) => void,
): void {
this.changeCollector = collector;
}
/**
* `nodesBetween` returns the nodes between the given range.
* This method includes the given left node but excludes the given right node.
Expand Down Expand Up @@ -461,14 +445,12 @@ export class CRDTTree extends CRDTElement {
type: TreeChangeType.Content,
from: this.toIndex(range[0]),
to: this.toIndex(range[1]),
fromPath: this.indexTree.treePosToPath(fromPos),
toPath: this.indexTree.treePosToPath(toPos),
actor: editedAt.getActorID()!,
value: content ? toJSON(content) : undefined,
});

if (this.changeCollector) {
this.changeCollector(changes);
}

const toBeRemoveds: Array<CRDTTreeNode> = [];
// 02. remove the nodes and update linked list and index tree.
if (fromRight !== toRight) {
Expand Down Expand Up @@ -530,10 +512,6 @@ export class CRDTTree extends CRDTElement {
}
}

if (this.onChangesHandler) {
this.onChangesHandler();
}

return changes;
}

Expand Down
42 changes: 3 additions & 39 deletions src/document/json/tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -276,50 +276,14 @@ export class Tree {
}

/**
* `onChanges` registers a handler of onChanges event.
* `indexToPath` returns the path of the given index.
*/
onChanges(handler: (changes: Array<TreeChange>) => void): void {
public indexToPath(index: number): Array<number> {
if (!this.context || !this.tree) {
throw new Error('it is not initialized yet');
}
let localChanges: Array<TreeChange> = [];

this.tree.onChangeCollect((changes: Array<TreeChange>) => {
localChanges.push(...changes);
});
this.tree.onChanges(() => {
handler(localChanges as Array<TreeChange>);

localChanges = [];
});
}

/**
* `onChangesByPath` registers a handler of onChanges event.
*/
onChangesByPath(handler: (changes: Array<TreeChangeWithPath>) => void): void {
if (!this.context || !this.tree) {
throw new Error('it is not initialized yet');
}
let localChanges: Array<TreeChangeWithPath> = [];
const collect = (changes: Array<TreeChange>) => {
const changeWithPath = changes.map(({ from, to, ...rest }) => {
return {
from: this.tree!.indexToPath(from),
to: this.tree!.indexToPath(to),
...rest,
};
});

(localChanges as Array<TreeChangeWithPath>).push(...changeWithPath);
};

this.tree.onChangeCollect(collect);
this.tree.onChanges(() => {
handler(localChanges as Array<TreeChangeWithPath>);

localChanges = [];
});
return this.tree.indexToPath(index);
}

/**
Expand Down
2 changes: 2 additions & 0 deletions src/document/operation/operation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ export type TreeEditOpInfo = {
type: 'tree-edit';
from: number;
to: number;
fromPath: Array<number>;
toPath: Array<number>;
value: TreeNode;
path: string;
};
Expand Down
4 changes: 3 additions & 1 deletion src/document/operation/tree_edit_operation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,14 @@ export class TreeEditOperation extends Operation {
this.getExecutedAt(),
);

return changes.map(({ from, to, value }) => {
return changes.map(({ from, to, value, fromPath, toPath }) => {
return {
type: 'tree-edit',
from,
to,
value,
fromPath,
toPath,
element: this.getParentCreatedAt(),
};
}) as Array<InternalOpInfo>;
Expand Down
Loading

0 comments on commit b5cb95a

Please sign in to comment.