Skip to content

Commit

Permalink
Merge branch 'release/0.0.10'
Browse files Browse the repository at this point in the history
  • Loading branch information
pipisebastian committed Nov 28, 2024
2 parents f643cc0 + 89bc91c commit 5226f3d
Show file tree
Hide file tree
Showing 91 changed files with 5,594 additions and 1,153 deletions.
115 changes: 92 additions & 23 deletions @noctaCrdt/Crdt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,12 @@ import {
RemoteBlockInsertOperation,
RemoteCharInsertOperation,
CRDTSerializedProps,
RemoteReorderOperation,
RemoteBlockReorderOperation,
RemoteBlockUpdateOperation,
serializedEditorDataProps,
RemoteCharUpdateOperation,
TextColorType,
BackgroundColorType,
} from "./Interfaces";

export class CRDT<T extends Node<NodeId>> {
Expand Down Expand Up @@ -92,6 +96,7 @@ export class EditorCRDT extends CRDT<Block> {
}

const operation: RemoteBlockDeleteOperation = {
type: "blockDelete",
targetId: nodeToDelete.id,
clock: this.clock,
pageId,
Expand All @@ -103,15 +108,26 @@ export class EditorCRDT extends CRDT<Block> {
return operation;
}

localUpdate(block: Block, pageId: string): RemoteBlockUpdateOperation {
const updatedBlock = this.LinkedList.nodeMap[JSON.stringify(block.id)];
updatedBlock.animation = block.animation;
updatedBlock.icon = block.icon;
updatedBlock.indent = block.indent;
updatedBlock.style = block.style;
updatedBlock.type = block.type;
updatedBlock.listIndex = block.listIndex || undefined;
return { type: "blockUpdate", node: updatedBlock, pageId };
}

remoteUpdate(block: Block, pageId: string): RemoteBlockUpdateOperation {
const updatedBlock = this.LinkedList.nodeMap[JSON.stringify(block.id)];
updatedBlock.animation = block.animation;
updatedBlock.icon = block.icon;
updatedBlock.indent = block.indent;
updatedBlock.style = block.style;
updatedBlock.type = block.type;
// this.LinkedList.nodeMap[JSON.stringify(block.id)] = block;
return { node: updatedBlock, pageId };
updatedBlock.listIndex = block.listIndex || undefined;
return { type: "blockUpdate", node: updatedBlock, pageId };
}

remoteInsert(operation: RemoteBlockInsertOperation): void {
Expand All @@ -120,15 +136,11 @@ export class EditorCRDT extends CRDT<Block> {

newNode.next = operation.node.next;
newNode.prev = operation.node.prev;

newNode.indent = operation.node.indent;
newNode.listIndex = operation.node.listIndex || undefined;
this.LinkedList.insertById(newNode);

this.clock = Math.max(this.clock, operation.node.id.clock) + 1;
/*
if (this.clock <= newNode.id.clock) {
this.clock = newNode.id.clock + 1;
}
*/
}

remoteDelete(operation: RemoteBlockDeleteOperation): void {
Expand All @@ -138,31 +150,32 @@ export class EditorCRDT extends CRDT<Block> {
this.LinkedList.deleteNode(targetNodeId);
}
this.clock = Math.max(this.clock, clock) + 1;
/*
if (this.clock <= clock) {
this.clock = clock + 1;
}
*/
}

localReorder(params: {
targetId: BlockId;
beforeId: BlockId | null;
afterId: BlockId | null;
}): RemoteReorderOperation {
const operation: RemoteReorderOperation = {
pageId: string;
}): RemoteBlockReorderOperation {
const operation: RemoteBlockReorderOperation = {
...params,
type: "blockReorder",
clock: this.clock,
client: this.client,
};

this.LinkedList.reorderNodes(params);
this.LinkedList.reorderNodes({
targetId: params.targetId,
beforeId: params.beforeId,
afterId: params.afterId,
});
this.clock += 1;

return operation;
}

remoteReorder(operation: RemoteReorderOperation): void {
remoteReorder(operation: RemoteBlockReorderOperation): void {
const { targetId, beforeId, afterId, clock } = operation;

this.LinkedList.reorderNodes({
Expand All @@ -171,12 +184,10 @@ export class EditorCRDT extends CRDT<Block> {
afterId,
});

if (this.clock <= clock) {
this.clock = clock + 1;
}
this.clock = Math.max(this.clock, clock) + 1;
}

serialize(): CRDTSerializedProps<Block> {
serialize(): serializedEditorDataProps {
return {
...super.serialize(),
currentBlock: this.currentBlock ? this.currentBlock.serialize() : null,
Expand All @@ -203,14 +214,30 @@ export class BlockCRDT extends CRDT<Char> {
value: string,
blockId: BlockId,
pageId: string,
style?: string[],
color?: TextColorType,
backgroundColor?: BackgroundColorType,
): RemoteCharInsertOperation {
const id = new CharId(this.clock + 1, this.client);
const { node } = this.LinkedList.insertAtIndex(index, value, id);
const { node } = this.LinkedList.insertAtIndex(index, value, id) as { node: Char };
if (style && style.length > 0) {
node.style = style;
}
if (color) {
node.color = color;
}
if (backgroundColor) {
node.backgroundColor = backgroundColor;
}
this.clock += 1;
const operation: RemoteCharInsertOperation = {
type: "charInsert",
node,
blockId,
pageId,
style: node.style || [],
color: node.color,
backgroundColor: node.backgroundColor,
};

return operation;
Expand All @@ -227,6 +254,7 @@ export class BlockCRDT extends CRDT<Char> {
}

const operation: RemoteCharDeleteOperation = {
type: "charDelete",
targetId: nodeToDelete.id,
clock: this.clock,
blockId,
Expand All @@ -239,13 +267,41 @@ export class BlockCRDT extends CRDT<Char> {
return operation;
}

localUpdate(node: Char, blockId: BlockId, pageId: string): RemoteCharUpdateOperation {
const updatedChar = this.LinkedList.nodeMap[JSON.stringify(node.id)];
if (node.style && node.style.length > 0) {
updatedChar.style = [...node.style];
}
if (node.color) {
updatedChar.color = node.color;
}
if (node.backgroundColor !== updatedChar.backgroundColor) {
updatedChar.backgroundColor = node.backgroundColor;
}
return { type: "charUpdate", node: updatedChar, blockId, pageId };
}

remoteInsert(operation: RemoteCharInsertOperation): void {
const newNodeId = new CharId(operation.node.id.clock, operation.node.id.client);
const newNode = new Char(operation.node.value, newNodeId);

newNode.next = operation.node.next;
newNode.prev = operation.node.prev;

if (operation.style && operation.style.length > 0) {
operation.style.forEach((style) => {
newNode.style.push(style);
});
}

if (operation.color) {
newNode.color = operation.color;
}

if (operation.backgroundColor) {
newNode.backgroundColor = operation.backgroundColor;
}

this.LinkedList.insertById(newNode);

if (this.clock <= newNode.id.clock) {
Expand All @@ -264,6 +320,19 @@ export class BlockCRDT extends CRDT<Char> {
}
}

remoteUpdate(operation: RemoteCharUpdateOperation): void {
const updatedChar = this.LinkedList.nodeMap[JSON.stringify(operation.node.id)];
if (operation.node.style && operation.node.style.length > 0) {
updatedChar.style = [...operation.node.style];
}
if (operation.node.color) {
updatedChar.color = operation.node.color;
}
if (operation.node.backgroundColor) {
updatedChar.backgroundColor = operation.node.backgroundColor;
}
}

serialize(): CRDTSerializedProps<Char> {
return {
...super.serialize(),
Expand Down
93 changes: 91 additions & 2 deletions @noctaCrdt/Interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,53 +3,132 @@ import { Block, Char } from "./Node";
import { Page } from "./Page";
import { EditorCRDT } from "./Crdt";

export type ElementType = "p" | "h1" | "h2" | "h3" | "ul" | "ol" | "li" | "checkbox" | "blockquote";
export type ElementType =
| "p"
| "h1"
| "h2"
| "h3"
| "ul"
| "ol"
| "li"
| "checkbox"
| "blockquote"
| "hr";

export type AnimationType = "none" | "highlight" | "gradation";

export type TextStyleType = "bold" | "italic" | "underline" | "strikethrough";

export type BackgroundColorType =
| "black"
| "red"
| "green"
| "blue"
| "white"
| "yellow"
| "purple"
| "brown"
| "transparent";

export type PageIconType =
// ๊ธฐ๋ณธ ๋ฌธ์„œ ํƒ€์ž…
| "Docs" // ์ผ๋ฐ˜ ๋ฌธ์„œ
| "Note" // ํ•„๊ธฐ/๋ฉ”๋ชจ
| "Wiki" // ์ง€์‹ ๋ฒ ์ด์Šค/์œ„ํ‚ค

// ์—…๋ฌด ๊ด€๋ จ
| "Project" // ํ”„๋กœ์ ํŠธ ๊ด€๋ จ
| "Meeting" // ํšŒ์˜๋ก
| "Task" // ํ• ์ผ/์ž‘์—…

// ๊ฐœ์ธ ํ™œ๋™
| "Diary" // ์ผ๊ธฐ/์ €๋„
| "Blog" // ๋ธ”๋กœ๊ทธ ํฌ์ŠคํŠธ
| "Entertain" // ์œ ํŠœ๋ธŒ, ๋„ทํ”Œ๋ฆญ์Šค ๋“ฑ

// ํ•™์Šต ๊ด€๋ จ
| "Study" // ํ•™์Šต ์ž๋ฃŒ
| "Research" // ์—ฐ๊ตฌ/์กฐ์‚ฌ
| "Book" // ๋…์„œ ๋…ธํŠธ

// ํ˜‘์—… ๊ด€๋ จ
| "Team" // ํŒ€ ๋ฌธ์„œ
| "Shared" // ๊ณต์œ  ๋ฌธ์„œ
| "Feedback"; // ํ”ผ๋“œ๋ฐฑ/๋ฆฌ๋ทฐ

export type TextColorType = Exclude<BackgroundColorType, "transparent">;

export interface InsertOperation {
type: "insert";
node: Block | Char;
}

export interface DeleteOperation {
type: "delete";
targetId: BlockId | CharId;
clock: number;
}

export interface RemotePageCreateOperation {
type: "pageCreate";
clientId: number;
workspaceId: string;
page?: Page;
}

export interface RemotePageDeleteOperation {
type: "pageDelete";
clientId: number;
workspaceId: string;
pageId: string;
}

export interface RemoteBlockUpdateOperation {
type: "blockUpdate";
node: Block;
pageId: string;
}

export interface RemoteBlockInsertOperation {
type: "blockInsert";
node: Block;
pageId: string;
}

export interface RemoteCharInsertOperation {
type: "charInsert";
node: Char;
blockId: BlockId;
pageId: string;
style?: string[];
color?: TextColorType;
backgroundColor?: BackgroundColorType;
}

export interface RemoteBlockDeleteOperation {
type: "blockDelete";
targetId: BlockId;
clock: number;
pageId: string;
}

export interface RemoteCharDeleteOperation {
type: "charDelete";
targetId: CharId;
clock: number;
blockId?: BlockId;
pageId: string;
}

export interface RemoteCharUpdateOperation {
type: "charUpdate";
node: Char;
blockId: BlockId;
pageId: string;
}

export interface CursorPosition {
type: "cursor";
clientId: number;
position: number;
}
Expand Down Expand Up @@ -88,15 +167,25 @@ export interface ReorderNodesProps {
afterId: BlockId | null;
}

export interface RemotePageUpdateOperation {
type: "pageUpdate";
workspaceId: string;
pageId: string;
clientId: number;
title?: string;
icon?: PageIconType;
}
export interface WorkSpaceSerializedProps {
id: string;
pageList: Page[];
authUser: Map<string, string>;
}
export interface RemoteReorderOperation {
export interface RemoteBlockReorderOperation {
type: "blockReorder";
targetId: BlockId;
beforeId: BlockId | null;
afterId: BlockId | null;
clock: number;
client: number;
pageId: string;
}
Loading

0 comments on commit 5226f3d

Please sign in to comment.