Skip to content

Commit

Permalink
fix: 병합과정에서 생긴 문제 해결
Browse files Browse the repository at this point in the history
  • Loading branch information
Ludovico7 committed Nov 26, 2024
1 parent cc68ebd commit 8cc6dc3
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 80 deletions.
3 changes: 3 additions & 0 deletions @noctaCrdt/Crdt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,8 @@ export class BlockCRDT extends CRDT<Char> {
blockId,
pageId,
style: node.style || [],
color: node.color,
backgroundColor: node.backgroundColor,
};

return operation;
Expand Down Expand Up @@ -325,6 +327,7 @@ export class BlockCRDT extends CRDT<Char> {

remoteUpdate(operation: RemoteCharUpdateOperation): void {
const updatedChar = this.LinkedList.nodeMap[JSON.stringify(operation.node.id)];
console.log("remoteUpdate", updatedChar);
if (operation.node.style && operation.node.style.length > 0) {
updatedChar.style = [...operation.node.style];
}
Expand Down
132 changes: 63 additions & 69 deletions client/src/features/editor/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
TextColorType,
BackgroundColorType,
} from "node_modules/@noctaCrdt/Interfaces.ts";
import { useRef, useState, useCallback, useEffect } from "react";
import { useRef, useState, useCallback, useEffect, useMemo } from "react";
import { useSocketStore } from "@src/stores/useSocketStore.ts";
import { setCaretPosition, getAbsoluteCaretPosition } from "@src/utils/caretUtils.ts";
import {
Expand Down Expand Up @@ -58,46 +58,36 @@ export const Editor = ({
sendBlockUpdateOperation,
} = useSocketStore();
const { clientId } = useSocketStore();
const editorRef = useRef<HTMLDivElement | null>(null); // Add ref for the editor
// editorCRDT를 useState로 관리하여 페이지별로 인스턴스를 분리
const [editorCRDT, setEditorCRDT] = useState<EditorCRDT>(() => new EditorCRDT(0));

useEffect(() => {
const editorCRDTInstance = useMemo(() => {
let newEditorCRDT;
if (serializedEditorData) {
newEditorCRDT = new EditorCRDT(serializedEditorData.client);
newEditorCRDT.deserialize(serializedEditorData);
} else {
newEditorCRDT = new EditorCRDT(clientId ? clientId : 0);
}
setEditorCRDT(newEditorCRDT);
return newEditorCRDT;
}, [serializedEditorData, clientId]);

const editorCRDT = useRef<EditorCRDT>(editorCRDTInstance);

// editorState도 editorCRDT가 변경될 때마다 업데이트
const [editorState, setEditorState] = useState<EditorStateProps>({
clock: editorCRDT?.clock || 0,
linkedList: editorCRDT?.LinkedList || new BlockLinkedList(),
clock: editorCRDT.current.clock,
linkedList: editorCRDT.current.LinkedList,
});

useEffect(() => {
if (editorCRDT) {
setEditorState({
clock: editorCRDT.clock,
linkedList: editorCRDT.LinkedList,
});
}
}, [editorCRDT]);

const { sensors, handleDragEnd } = useBlockDragAndDrop({
editorCRDT,
editorCRDT: editorCRDT.current,
editorState,
setEditorState,
pageId,
});

const { handleTypeSelect, handleAnimationSelect, handleCopySelect, handleDeleteSelect } =
useBlockOptionSelect({
editorCRDT,
editorCRDT: editorCRDT.current,
editorState,
setEditorState,
pageId,
Expand All @@ -108,7 +98,7 @@ export const Editor = ({
});

const { handleKeyDown: onKeyDown } = useMarkdownGrammer({
editorCRDT,
editorCRDT: editorCRDT.current,
editorState,
setEditorState,
pageId,
Expand All @@ -117,12 +107,11 @@ export const Editor = ({
sendBlockUpdateOperation,
sendCharDeleteOperation,
sendCharInsertOperation,
editorRef,
});

const { onTextStyleUpdate, onTextColorUpdate, onTextBackgroundColorUpdate } = useTextOptionSelect(
{
editorCRDT,
editorCRDT: editorCRDT.current,
setEditorState,
pageId,
},
Expand All @@ -142,11 +131,12 @@ export const Editor = ({
) as HTMLDivElement;
if (!clickedElement) return;

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

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

Expand Down Expand Up @@ -185,7 +175,7 @@ export const Editor = ({
const addedChar = newContent[validCaretPosition - 1];
charNode = block.crdt.localInsert(validCaretPosition - 1, addedChar, block.id, pageId);
}
editorCRDT.currentBlock!.crdt.currentCaret = caretPosition;
editorCRDT.current.currentBlock!.crdt.currentCaret = caretPosition;
sendCharInsertOperation({ node: charNode.node, blockId: block.id, pageId });
} else if (newContent.length < currentContent.length) {
// 문자가 삭제된 경우
Expand All @@ -196,12 +186,12 @@ export const Editor = ({
sendCharDeleteOperation(operationNode);

// 캐럿 위치 업데이트
editorCRDT.currentBlock!.crdt.currentCaret = deletePosition;
editorCRDT.current.currentBlock!.crdt.currentCaret = deletePosition;
}
}
setEditorState({
clock: editorCRDT.clock,
linkedList: editorCRDT.LinkedList,
clock: editorCRDT.current.clock,
linkedList: editorCRDT.current.LinkedList,
});
},
[sendCharInsertOperation, sendCharDeleteOperation, editorCRDT, pageId, updatePageData],
Expand Down Expand Up @@ -237,8 +227,8 @@ export const Editor = ({

block.crdt.currentCaret = startOffset;
setEditorState({
clock: editorCRDT.clock,
linkedList: editorCRDT.LinkedList,
clock: editorCRDT.current.clock,
linkedList: editorCRDT.current.LinkedList,
});
} else {
onKeyDown(e);
Expand Down Expand Up @@ -315,7 +305,7 @@ export const Editor = ({
});
});

editorCRDT.currentBlock!.crdt.currentCaret = caretPosition + metadata.length;
editorCRDT.current.currentBlock!.crdt.currentCaret = caretPosition + metadata.length;
} else {
const text = e.clipboardData.getData("text/plain");

Expand All @@ -335,12 +325,12 @@ export const Editor = ({
});

// 캐럿 위치 업데이트
editorCRDT.currentBlock!.crdt.currentCaret = caretPosition + text.length;
editorCRDT.current.currentBlock!.crdt.currentCaret = caretPosition + text.length;
}

setEditorState({
clock: editorCRDT.clock,
linkedList: editorCRDT.LinkedList,
clock: editorCRDT.current.clock,
linkedList: editorCRDT.current.LinkedList,
});
};

Expand All @@ -365,23 +355,23 @@ export const Editor = ({
});

block.crdt.currentCaret = caretPosition;
updatePageData(pageId, editorCRDT.serialize());
updatePageData(pageId, editorCRDT.current.serialize());
},
[editorCRDT, pageId, sendCharInsertOperation, updatePageData],
);

const subscriptionRef = useRef(false);

useEffect(() => {
if (!editorCRDT || !editorCRDT.currentBlock) return;
if (!editorCRDT || !editorCRDT.current.currentBlock) return;
setCaretPosition({
blockId: editorCRDT.currentBlock.id,
linkedList: editorCRDT.LinkedList,
position: editorCRDT.currentBlock?.crdt.currentCaret,
rootElement: editorRef.current,
blockId: editorCRDT.current.currentBlock.id,
linkedList: editorCRDT.current.LinkedList,
position: editorCRDT.current.currentBlock?.crdt.currentCaret,
pageId,
});
// 서윤님 피드백 반영
}, [editorCRDT, editorCRDT?.currentBlock?.id.serialize()]);
}, [editorCRDT.current.currentBlock?.id.serialize()]);

useEffect(() => {
if (!editorCRDT) return;
Expand All @@ -392,77 +382,81 @@ export const Editor = ({
onRemoteBlockInsert: (operation) => {
console.log(operation, "block : 입력 확인합니다이");
if (operation.pageId !== pageId) return;
editorCRDT.remoteInsert(operation);
editorCRDT.current.remoteInsert(operation);
setEditorState({
clock: editorCRDT.clock,
linkedList: editorCRDT.LinkedList,
clock: editorCRDT.current.clock,
linkedList: editorCRDT.current.LinkedList,
});
},

onRemoteBlockDelete: (operation) => {
console.log(operation, "block : 삭제 확인합니다이");
if (operation.pageId !== pageId) return;
editorCRDT.remoteDelete(operation);
editorCRDT.current.remoteDelete(operation);
setEditorState({
clock: editorCRDT.clock,
linkedList: editorCRDT.LinkedList,
clock: editorCRDT.current.clock,
linkedList: editorCRDT.current.LinkedList,
});
},

onRemoteCharInsert: (operation) => {
console.log(operation, "char : 입력 확인합니다이");
if (operation.pageId !== pageId) return;
const targetBlock = editorCRDT.LinkedList.nodeMap[JSON.stringify(operation.blockId)];
const targetBlock =
editorCRDT.current.LinkedList.nodeMap[JSON.stringify(operation.blockId)];
if (targetBlock) {
targetBlock.crdt.remoteInsert(operation);
setEditorState({
clock: editorCRDT.clock,
linkedList: editorCRDT.LinkedList,
clock: editorCRDT.current.clock,
linkedList: editorCRDT.current.LinkedList,
});
}
},

onRemoteCharDelete: (operation) => {
console.log(operation, "char : 삭제 확인합니다이");
if (operation.pageId !== pageId) return;
const targetBlock = editorCRDT.LinkedList.nodeMap[JSON.stringify(operation.blockId)];
const targetBlock =
editorCRDT.current.LinkedList.nodeMap[JSON.stringify(operation.blockId)];
if (targetBlock) {
targetBlock.crdt.remoteDelete(operation);
setEditorState({
clock: editorCRDT.clock,
linkedList: editorCRDT.LinkedList,
clock: editorCRDT.current.clock,
linkedList: editorCRDT.current.LinkedList,
});
}
},

onRemoteBlockUpdate: (operation) => {
console.log(operation, "block : 업데이트 확인합니다이");
if (operation.pageId !== pageId) return;
editorCRDT.remoteUpdate(operation.node, operation.pageId);
editorCRDT.current.remoteUpdate(operation.node, operation.pageId);
setEditorState({
clock: editorCRDT.clock,
linkedList: editorCRDT.LinkedList,
clock: editorCRDT.current.clock,
linkedList: editorCRDT.current.LinkedList,
});
},

onRemoteBlockReorder: (operation) => {
console.log(operation, "block : 재정렬 확인합니다이");
if (operation.pageId !== pageId) return;
editorCRDT.remoteReorder(operation);
editorCRDT.current.remoteReorder(operation);
setEditorState({
clock: editorCRDT.clock,
linkedList: editorCRDT.LinkedList,
clock: editorCRDT.current.clock,
linkedList: editorCRDT.current.LinkedList,
});
},

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

Expand All @@ -479,15 +473,15 @@ export const Editor = ({

const addNewBlock = () => {
if (!editorCRDT) return;
const index = editorCRDT.LinkedList.spread().length;
const operation = editorCRDT.localInsert(index, "");
editorCRDT.currentBlock = operation.node;
const index = editorCRDT.current.LinkedList.spread().length;
const operation = editorCRDT.current.localInsert(index, "");
editorCRDT.current.currentBlock = operation.node;
sendBlockInsertOperation({ node: operation.node, pageId });
setEditorState(() => ({
clock: editorCRDT.clock,
linkedList: editorCRDT.LinkedList,
clock: editorCRDT.current.clock,
linkedList: editorCRDT.current.LinkedList,
}));
updatePageData(pageId, editorCRDT.serialize());
updatePageData(pageId, editorCRDT.current.serialize());
};

// 로딩 상태 체크
Expand Down Expand Up @@ -516,7 +510,7 @@ export const Editor = ({
key={`${block.id.client}-${block.id.clock}`}
id={`${block.id.client}-${block.id.clock}`}
block={block}
isActive={block.id === editorCRDT.currentBlock?.id}
isActive={block.id === editorCRDT.current.currentBlock?.id}
onInput={handleBlockInput}
onCompositionEnd={handleCompositionEnd}
onKeyDown={handleKeyDown}
Expand Down
10 changes: 4 additions & 6 deletions client/src/features/editor/hooks/useMarkdownGrammer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ import { setCaretPosition, getAbsoluteCaretPosition } from "@src/utils/caretUtil

interface useMarkdownGrammerProps {
editorCRDT: EditorCRDT;
editorState: EditorStateProps;
editorRef: React.RefObject<HTMLDivElement>; // Add editorRef
editorState: EditorStateProps; // Add editorRef
setEditorState: React.Dispatch<
React.SetStateAction<{
clock: number;
Expand All @@ -40,7 +39,6 @@ export const useMarkdownGrammer = ({
sendCharDeleteOperation,
sendCharInsertOperation,
sendBlockUpdateOperation,
editorRef,
}: useMarkdownGrammerProps) => {
const handleKeyDown = useCallback(
(e: React.KeyboardEvent<HTMLDivElement>) => {
Expand Down Expand Up @@ -300,7 +298,7 @@ export const useMarkdownGrammer = ({
blockId: targetBlock.id,
linkedList: editorCRDT.LinkedList,
position: Math.min(caretPosition, targetBlock.crdt.read().length),
rootElement: editorRef.current,
pageId,
});
break;
}
Expand All @@ -322,7 +320,7 @@ export const useMarkdownGrammer = ({
blockId: prevBlock.id,
linkedList: editorCRDT.LinkedList,
position: prevBlock.crdt.read().length,
rootElement: editorRef.current,
pageId,
});
}
break;
Expand All @@ -341,7 +339,7 @@ export const useMarkdownGrammer = ({
blockId: nextBlock.id,
linkedList: editorCRDT.LinkedList,
position: 0,
rootElement: editorRef.current,
pageId,
});
}
break;
Expand Down
1 change: 1 addition & 0 deletions client/src/features/page/Page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export const Page = ({
return (
<AnimatePresence>
<div
id={id}
className={pageContainer}
style={{
width: `${size.width}px`,
Expand Down
Loading

0 comments on commit 8cc6dc3

Please sign in to comment.