Skip to content

Commit

Permalink
chore: 병합 처리
Browse files Browse the repository at this point in the history
  • Loading branch information
hyonun321 committed Nov 26, 2024
1 parent 2207a7b commit e31faa4
Show file tree
Hide file tree
Showing 4 changed files with 15 additions and 297 deletions.
2 changes: 1 addition & 1 deletion @noctaCrdt/Crdt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ export class EditorCRDT extends CRDT<Block> {

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

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

this.clock = Math.max(this.clock, operation.node.id.clock) + 1;
Expand Down
28 changes: 7 additions & 21 deletions client/src/features/editor/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
RemoteCharInsertOperation,
serializedEditorDataProps,
} from "node_modules/@noctaCrdt/Interfaces.ts";
import { useRef, useState, useCallback, useEffect, useMemo } from "react";
import { useRef, useState, useCallback, useEffect } from "react";
import { useSocketStore } from "@src/stores/useSocketStore.ts";
import { setCaretPosition, getAbsoluteCaretPosition } from "@src/utils/caretUtils.ts";
import {
Expand Down Expand Up @@ -134,12 +134,11 @@ export const Editor = ({
) as HTMLDivElement;
if (!clickedElement) return;

editorCRDT.current.currentBlock =
editorCRDT.current.LinkedList.nodeMap[JSON.stringify(blockId)];
editorCRDT.currentBlock = editorCRDT.LinkedList.nodeMap[JSON.stringify(blockId)];
const caretPosition = getAbsoluteCaretPosition(clickedElement);

// 계산된 캐럿 위치 저장
editorCRDT.current.currentBlock.crdt.currentCaret = caretPosition;
editorCRDT.currentBlock.crdt.currentCaret = caretPosition;
}
};

Expand Down Expand Up @@ -189,7 +188,7 @@ export const Editor = ({
sendCharDeleteOperation(operationNode);

// 캐럿 위치 업데이트
editorCRDT.current.currentBlock!.crdt.currentCaret = deletePosition;
editorCRDT.currentBlock!.crdt.currentCaret = deletePosition;
}
}
setEditorState({
Expand Down Expand Up @@ -316,28 +315,15 @@ export const Editor = ({

onRemoteCharUpdate: (operation) => {
console.log(operation, "char : 업데이트 확인합니다이");
if (!editorCRDT.current) return;
const targetBlock =
editorCRDT.current.LinkedList.nodeMap[JSON.stringify(operation.blockId)];
if (!editorCRDT) return;
const targetBlock = editorCRDT.LinkedList.nodeMap[JSON.stringify(operation.blockId)];
targetBlock.crdt.remoteUpdate(operation);
setEditorState({
clock: editorCRDT.clock,
linkedList: editorCRDT.LinkedList,
});
},

onRemoteCharUpdate: (operation) => {
console.log(operation, "char : 업데이트 확인합니다이");
if (!editorCRDT.current) return;
const targetBlock =
editorCRDT.current.LinkedList.nodeMap[JSON.stringify(operation.blockId)];
targetBlock.crdt.remoteUpdate(operation);
setEditorState({
clock: editorCRDT.current.clock,
linkedList: editorCRDT.current.LinkedList,
});
},

onRemoteCursor: (position) => {
console.log(position, "커서위치 수신");
},
Expand All @@ -353,7 +339,7 @@ export const Editor = ({
if (!editorCRDT) return;
const index = editorCRDT.LinkedList.spread().length;
const operation = editorCRDT.localInsert(index, "");
editorCRDT.current.currentBlock = operation.node;
editorCRDT.currentBlock = operation.node;
sendBlockInsertOperation({ node: operation.node, pageId });
setEditorState(() => ({
clock: editorCRDT.clock,
Expand Down
274 changes: 3 additions & 271 deletions client/src/features/editor/hooks/useMarkdownGrammer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,7 @@ export const useMarkdownGrammer = ({
blockId: targetBlock.id,
linkedList: editorCRDT.LinkedList,
position: Math.min(caretPosition, targetBlock.crdt.read().length),
rootElement: editorRef.current,
});
break;
}
Expand All @@ -321,6 +322,7 @@ export const useMarkdownGrammer = ({
blockId: prevBlock.id,
linkedList: editorCRDT.LinkedList,
position: prevBlock.crdt.read().length,
rootElement: editorRef.current,
});
}
break;
Expand All @@ -339,6 +341,7 @@ export const useMarkdownGrammer = ({
blockId: nextBlock.id,
linkedList: editorCRDT.LinkedList,
position: 0,
rootElement: editorRef.current,
});
}
break;
Expand All @@ -360,274 +363,3 @@ export const useMarkdownGrammer = ({

return { handleKeyDown };
};

/*
switch (e.key) {
case "Enter": {
e.preventDefault();
const selection = window.getSelection();
if (!selection) return;
const caretPosition = selection.focusOffset;
const currentContent = currentBlock.crdt.read();
const afterText = currentContent.slice(caretPosition);
if (!currentContent && currentBlock.type !== "p") {
currentBlock.type = "p";
sendBlockUpdateOperation(editorCRDT.localUpdate(currentBlock, pageId));
editorCRDT.currentBlock = currentBlock;
updateEditorState();
break;
}
if (!currentContent && currentBlock.type === "p") {
// 새로운 기본 블록 생성
const operation = createNewBlock(currentIndex + 1);
operation.node.indent = currentBlock.indent;
operation.node.crdt = new BlockCRDT(editorCRDT.client);
sendBlockInsertOperation({ node: operation.node, pageId });
updateEditorState(operation.node.id);
break;
}
// 현재 캐럿 위치 이후의 텍스트가 있으면 현재 블록 내용 업데이트
if (afterText) {
// 캐럿 이후의 텍스트만 제거
for (let i = currentContent.length - 1; i >= caretPosition; i--) {
sendCharDeleteOperation(currentBlock.crdt.localDelete(i, currentBlock.id, pageId));
}
}
// 새 블록 생성
const operation = createNewBlock(currentIndex + 1);
operation.node.crdt = new BlockCRDT(editorCRDT.client);
operation.node.indent = currentBlock.indent;
sendBlockInsertOperation({ node: operation.node, pageId });
// 캐럿 이후의 텍스트 있으면 새 블록에 추가
if (afterText) {
afterText.split("").forEach((char, i) => {
sendCharInsertOperation(
operation.node.crdt.localInsert(i, char, operation.node.id, pageId),
);
});
}
// 현재 블록이 li나 checkbox면 동일한 타입으로 생성
if (["ul", "ol", "checkbox"].includes(currentBlock.type)) {
operation.node.type = currentBlock.type;
sendBlockUpdateOperation(editorCRDT.localUpdate(operation.node, pageId));
}
updateEditorState(operation.node.id);
break;
}
case "Backspace": {
const selection = window.getSelection();
const caretPosition = selection?.focusOffset || 0;
const currentContent = currentBlock.crdt.read();
if (currentContent === "") {
e.preventDefault();
if (currentBlock.indent > 0) {
currentBlock.indent -= 1;
sendBlockUpdateOperation(editorCRDT.localUpdate(currentBlock, pageId));
editorCRDT.currentBlock = currentBlock;
updateEditorState();
break;
}
if (currentBlock.type !== "p") {
// 마지막 블록이면 기본 블록으로 변경
currentBlock.type = "p";
sendBlockUpdateOperation(editorCRDT.localUpdate(currentBlock, pageId));
editorCRDT.currentBlock = currentBlock;
updateEditorState();
break;
}
const prevBlock =
currentIndex > 0 ? editorCRDT.LinkedList.findByIndex(currentIndex - 1) : null;
if (prevBlock) {
sendBlockDeleteOperation(editorCRDT.localDelete(currentIndex, undefined, pageId));
prevBlock.crdt.currentCaret = prevBlock.crdt.read().length;
editorCRDT.currentBlock = prevBlock;
updateEditorState(prevBlock.id);
}
break;
} else {
if (caretPosition === 0) {
if (currentBlock.indent > 0) {
currentBlock.indent -= 1;
sendBlockUpdateOperation(editorCRDT.localUpdate(currentBlock, pageId));
editorCRDT.currentBlock = currentBlock;
updateEditorState();
break;
}
if (currentBlock.type !== "p") {
currentBlock.type = "p";
sendBlockUpdateOperation(editorCRDT.localUpdate(currentBlock, pageId));
editorCRDT.currentBlock = currentBlock;
updateEditorState();
// FIX: 서윤님 피드백 반영
} else {
const prevBlock =
currentIndex > 0 ? editorCRDT.LinkedList.findByIndex(currentIndex - 1) : null;
if (prevBlock) {
const prevBlockEndCaret = prevBlock.crdt.read().length;
currentContent.split("").forEach((char) => {
sendCharInsertOperation(
prevBlock.crdt.localInsert(
prevBlock.crdt.read().length,
char,
prevBlock.id,
pageId,
),
);
sendCharDeleteOperation(
currentBlock.crdt.localDelete(caretPosition, currentBlock.id, pageId),
);
});
prevBlock.crdt.currentCaret = prevBlockEndCaret;
sendBlockDeleteOperation(editorCRDT.localDelete(currentIndex, undefined, pageId));
updateEditorState(prevBlock.id);
e.preventDefault();
}
}
}
break;
}
}
case "Tab": {
e.preventDefault();
if (currentBlock) {
if (e.shiftKey) {
// shift + tab: 들여쓰기 감소
if (currentBlock.indent > 0) {
currentBlock.indent -= 1;
sendBlockUpdateOperation(editorCRDT.localUpdate(currentBlock, pageId));
editorCRDT.currentBlock = currentBlock;
updateEditorState();
}
} else {
// tab: 들여쓰기 증가
const maxIndent = 3;
if (currentBlock.indent < maxIndent) {
currentBlock.indent += 1;
sendBlockUpdateOperation(editorCRDT.localUpdate(currentBlock, pageId));
editorCRDT.currentBlock = currentBlock;
updateEditorState();
}
}
}
break;
}
case " ": {
// 여기 수정함
const selection = window.getSelection();
if (!selection) return;
const currentContent = currentBlock.crdt.read();
const markdownElement = checkMarkdownPattern(currentContent);
if (markdownElement && currentBlock.type === "p") {
e.preventDefault();
// 마크다운 패턴 매칭 시 타입 변경하고 내용 비우기
currentBlock.type = markdownElement.type;
let deleteCount = 0;
while (deleteCount < markdownElement.length) {
sendCharDeleteOperation(currentBlock.crdt.localDelete(0, currentBlock.id, pageId));
deleteCount += 1;
}
sendBlockUpdateOperation(editorCRDT.localUpdate(currentBlock, pageId));
currentBlock.crdt.currentCaret = 0;
editorCRDT.currentBlock = currentBlock;
updateEditorState();
}
break;
}
case "ArrowUp":
case "ArrowDown": {
const hasPrevBlock = currentIndex > 0;
const hasNextBlock = currentIndex < editorCRDT.LinkedList.spread().length - 1;
if (e.key === "ArrowUp" && !hasPrevBlock) {
e.preventDefault();
return;
}
if (e.key === "ArrowDown" && !hasNextBlock) {
e.preventDefault();
return;
}
const selection = window.getSelection();
const caretPosition = selection?.focusOffset || 0;
// 이동할 블록 결정
const targetIndex = e.key === "ArrowUp" ? currentIndex - 1 : currentIndex + 1;
const targetBlock = editorCRDT.LinkedList.findByIndex(targetIndex);
if (!targetBlock) return;
e.preventDefault();
targetBlock.crdt.currentCaret = Math.min(caretPosition, targetBlock.crdt.read().length);
editorCRDT.currentBlock = targetBlock;
setCaretPosition({
blockId: targetBlock.id,
linkedList: editorCRDT.LinkedList,
position: Math.min(caretPosition, targetBlock.crdt.read().length),
rootElement: editorRef.current,
});
break;
}
case "ArrowLeft":
case "ArrowRight": {
const selection = window.getSelection();
const caretPosition = selection?.focusOffset || 0;
const textLength = currentBlock.crdt.read().length;
// 왼쪽 끝에서 이전 블록으로
if (e.key === "ArrowLeft" && caretPosition === 0 && currentIndex > 0) {
e.preventDefault(); // 기본 동작 방지
const prevBlock = editorCRDT.LinkedList.findByIndex(currentIndex - 1);
if (prevBlock) {
prevBlock.crdt.currentCaret = prevBlock.crdt.read().length;
editorCRDT.currentBlock = prevBlock;
setCaretPosition({
blockId: prevBlock.id,
linkedList: editorCRDT.LinkedList,
position: prevBlock.crdt.read().length,
rootElement: editorRef.current,
});
}
break;
// 오른쪽 끝에서 다음 블록으로
} else if (
e.key === "ArrowRight" &&
caretPosition === textLength &&
currentIndex < editorCRDT.LinkedList.spread().length - 1
) {
e.preventDefault(); // 기본 동작 방지
const nextBlock = editorState.linkedList.findByIndex(currentIndex + 1);
if (nextBlock) {
nextBlock.crdt.currentCaret = 0;
editorCRDT.currentBlock = nextBlock;
setCaretPosition({
blockId: nextBlock.id,
linkedList: editorCRDT.LinkedList,
position: 0,
rootElement: editorRef.current,
});
}
break;
// 블록 내에서 이동하는 경우
} else {
if (e.key === "ArrowLeft") {
currentBlock.crdt.currentCaret -= 1;
} else {
currentBlock.crdt.currentCaret += 1;
}
}
break;
}
}
*/
Loading

0 comments on commit e31faa4

Please sign in to comment.