Skip to content

Commit 6400376

Browse files
se030dohun31
andauthored
Feat/#396-K: 회의록 및 텍스트 블럭 관련 소켓 메세지 인터페이스 정의 (#397)
* feat: 회의록 소켓 메세지 인터페이스 추가 * feat: 블럭 소켓 메세지 인터페이스 추가 * refactor: 반복되는 initialization 메서드로 분리 * fix: syncCRDT 매개변수 타입 변경 * fix: block.ts에서 중복된 부분 제거 * fix: 누락된 인터페이스 추가 Co-authored-by: hodun <[email protected]> * fix: 서버 타입 이슈 우회 - Created 메세지는 인터페이스 제거 - 추후 개선 필요 * fix: 회의록 소켓 서버 네임스페이스 변경 * fix: 폴더명 수정 위해 rm --cached * fix: socket/Mom socket/mom 으로 변경 Co-authored-by: hodun <[email protected]>
1 parent 08a812b commit 6400376

File tree

15 files changed

+414
-226
lines changed

15 files changed

+414
-226
lines changed

@wabinar/api-types/block.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { BlockType } from '@wabinar/constants/block';
2+
import LinkedList, {
3+
RemoteDeleteOperation,
4+
RemoteInsertOperation,
5+
} from '@wabinar/crdt/linked-list';
6+
7+
export interface LoadType {
8+
id: string;
9+
}
10+
11+
export interface LoadedType {
12+
type: BlockType;
13+
}
14+
15+
export interface UpdateType {
16+
id: string;
17+
type: BlockType;
18+
}
19+
20+
export interface UpdatedType {
21+
id: string;
22+
type: BlockType;
23+
}
24+
25+
export interface InitText {
26+
id: string;
27+
}
28+
29+
export interface InitializedText {
30+
id: string;
31+
crdt: LinkedList;
32+
}
33+
34+
export interface InsertText {
35+
id: string;
36+
op: RemoteInsertOperation;
37+
}
38+
39+
export interface InsertedText {
40+
id: string;
41+
op: RemoteInsertOperation;
42+
}
43+
44+
export interface DeleteText {
45+
id: string;
46+
op: RemoteDeleteOperation;
47+
}
48+
49+
export interface DeletedText {
50+
id: string;
51+
op: RemoteDeleteOperation;
52+
}
53+
54+
export interface UpdateText {
55+
id: string;
56+
ops: RemoteInsertOperation[];
57+
}
58+
59+
export interface UpdatedText {
60+
id: string;
61+
crdt: LinkedList;
62+
}

@wabinar/api-types/mom.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import LinkedList, {
2+
RemoteDeleteOperation,
3+
RemoteInsertOperation,
4+
} from '@wabinar/crdt/linked-list';
5+
6+
export type Mom = {
7+
_id: string;
8+
title: string;
9+
createdAt: Date;
10+
};
11+
12+
export interface Created {
13+
mom: Mom;
14+
}
15+
16+
export interface Select {
17+
id: string;
18+
}
19+
20+
export interface Selected {
21+
mom: Mom;
22+
}
23+
24+
export interface UpdateTitle {
25+
title: string;
26+
}
27+
28+
export interface UpdatedTitle {
29+
title: string;
30+
}
31+
32+
export interface Initialized {
33+
crdt: LinkedList;
34+
}
35+
36+
export interface InsertBlock {
37+
blockId: string;
38+
op: RemoteInsertOperation;
39+
}
40+
41+
export interface InsertedBlock {
42+
op: RemoteInsertOperation;
43+
}
44+
45+
export interface DeleteBlock {
46+
blockId: string;
47+
op: RemoteDeleteOperation;
48+
}
49+
50+
export interface DeletedBlock {
51+
op: RemoteDeleteOperation;
52+
}

client/src/components/Block/TextBlock.tsx

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
/* eslint-disable @typescript-eslint/no-non-null-assertion */
22
/* TextBlock 마운트 이후 항상 존재하는 blockRef.current 존재 여부 확인하는 불필요한 가드를 제거하기 위함 */
33

4+
import * as BlockMessage from '@wabinar/api-types/block';
45
import { BlockType } from '@wabinar/constants/block';
56
import { BLOCK_EVENT } from '@wabinar/constants/socket-message';
6-
import {
7+
import LinkedList, {
78
RemoteDeleteOperation,
89
RemoteInsertOperation,
910
} from '@wabinar/crdt/linked-list';
@@ -37,7 +38,8 @@ function TextBlock({
3738
const { momSocket: socket } = useSocketContext();
3839

3940
const initBlock = () => {
40-
socket.emit(BLOCK_EVENT.INIT_TEXT, id);
41+
const message: BlockMessage.InitText = { id };
42+
socket.emit(BLOCK_EVENT.INIT_TEXT, message);
4143
};
4244

4345
const {
@@ -87,7 +89,7 @@ function TextBlock({
8789
setOffset();
8890
};
8991

90-
const onInitialize = (crdt: unknown) => {
92+
const onInitialize = (crdt: LinkedList) => {
9193
syncCRDT(crdt);
9294

9395
blockRef.current!.innerText = readCRDT();
@@ -158,7 +160,9 @@ function TextBlock({
158160
useEffect(() => {
159161
if (isLocalTypeUpdate && readCRDT().length) {
160162
const remoteDeletion = localDeleteCRDT(0);
161-
socket.emit(BLOCK_EVENT.DELETE_TEXT, id, remoteDeletion);
163+
164+
const message: BlockMessage.DeleteText = { id, op: remoteDeletion };
165+
socket.emit(BLOCK_EVENT.DELETE_TEXT, message);
162166

163167
blockRef.current!.innerText = readCRDT();
164168
blockRef.current!.focus();
@@ -191,7 +195,8 @@ function TextBlock({
191195
return;
192196
}
193197

194-
socket.emit(BLOCK_EVENT.DELETE_TEXT, id, remoteDeletion);
198+
const message: BlockMessage.DeleteText = { id, op: remoteDeletion };
199+
socket.emit(BLOCK_EVENT.DELETE_TEXT, message);
195200
return;
196201
}
197202

@@ -204,9 +209,11 @@ function TextBlock({
204209
remoteInsertion = localInsertCRDT(previousLetterIndex, letter);
205210
} catch {
206211
initBlock();
212+
return;
207213
}
208214

209-
socket.emit(BLOCK_EVENT.INSERT_TEXT, id, remoteInsertion);
215+
const message: BlockMessage.InsertText = { id, op: remoteInsertion };
216+
socket.emit(BLOCK_EVENT.INSERT_TEXT, message);
210217
};
211218

212219
// 한글 입력 핸들링
@@ -224,7 +231,8 @@ function TextBlock({
224231

225232
const remoteInsertion = localInsertCRDT(previousLetterIndex, letter);
226233

227-
socket.emit(BLOCK_EVENT.INSERT_TEXT, id, remoteInsertion);
234+
const message: BlockMessage.InsertText = { id, op: remoteInsertion };
235+
socket.emit(BLOCK_EVENT.INSERT_TEXT, message);
228236
});
229237
};
230238

@@ -246,7 +254,8 @@ function TextBlock({
246254
.split('')
247255
.map((letter) => localInsertCRDT(previousLetterIndex++, letter));
248256

249-
socket.emit(BLOCK_EVENT.UPDATE_TEXT, id, remoteInsertions);
257+
const message: BlockMessage.UpdateText = { id, ops: remoteInsertions };
258+
socket.emit(BLOCK_EVENT.UPDATE_TEXT, message);
250259

251260
blockRef.current!.innerText = previousText + pastedText + nextText;
252261
updateCaretPosition(pastedText.length);

client/src/components/Block/index.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { BiPlus } from '@react-icons/all-files/bi/BiPlus';
2+
import * as BlockMessage from '@wabinar/api-types/block';
23
import { BLOCK_EVENT } from '@wabinar/constants/socket-message';
34
import ee from 'components/Mom/EventEmitter';
45
import { memo, useEffect, useRef, useState } from 'react';
@@ -39,7 +40,10 @@ function Block({
3940
const localUpdateFlagRef = useRef<boolean>(false);
4041

4142
useEffect(() => {
42-
socket.emit(BLOCK_EVENT.LOAD_TYPE, id, (type: BlockType) => setType(type));
43+
const message: BlockMessage.LoadType = { id };
44+
const callback = ({ type }: BlockMessage.LoadedType) => setType(type);
45+
46+
socket.emit(BLOCK_EVENT.LOAD_TYPE, message, callback);
4347

4448
ee.on(`${BLOCK_EVENT.UPDATE_TYPE}-${id}`, (type) => {
4549
setType(type);
@@ -48,8 +52,9 @@ function Block({
4852
}, []);
4953

5054
useEffect(() => {
51-
if (localUpdateFlagRef.current) {
52-
socket.emit(BLOCK_EVENT.UPDATE_TYPE, id, type);
55+
if (localUpdateFlagRef.current && type) {
56+
const message: BlockMessage.UpdateType = { id, type };
57+
socket.emit(BLOCK_EVENT.UPDATE_TYPE, message);
5358
}
5459
}, [type]);
5560

client/src/components/Mom/index.tsx

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import * as BlockMessage from '@wabinar/api-types/block';
2+
import * as MomMessage from '@wabinar/api-types/mom';
13
import { BLOCK_EVENT, MOM_EVENT } from '@wabinar/constants/socket-message';
24
import Block from 'components/Block';
35
import { useEffect, useRef, useState } from 'react';
@@ -14,6 +16,13 @@ import style from './style.module.scss';
1416
function Mom() {
1517
const { selectedMom } = useSelectedMomContext();
1618
const { momSocket: socket } = useSocketContext();
19+
20+
const initMom = () => {
21+
if (!selectedMom) return;
22+
23+
socket.emit(MOM_EVENT.INIT);
24+
};
25+
1726
const {
1827
syncCRDT,
1928
spreadCRDT,
@@ -31,18 +40,15 @@ function Mom() {
3140
const [isLoaded, setIsLoaded] = useState<boolean>(false);
3241
const [isMomsEmpty, setIsMomsEmpty] = useState(false);
3342

34-
const initMom = () => {
35-
if (!selectedMom) return;
36-
socket.emit(MOM_EVENT.INIT, selectedMom._id);
37-
};
38-
3943
const onTitleUpdate: React.FormEventHandler<HTMLHeadingElement> = useDebounce(
4044
() => {
4145
if (!titleRef.current) return;
4246

4347
const title = titleRef.current.innerText;
4448

45-
socket.emit(MOM_EVENT.UPDATE_TITLE, title);
49+
const message: MomMessage.UpdateTitle = { title };
50+
socket.emit(MOM_EVENT.UPDATE_TITLE, message);
51+
4652
ee.emit(MOM_EVENT.UPDATE_TITLE, title);
4753
},
4854
500,
@@ -86,9 +92,11 @@ function Mom() {
8692
remoteInsertion = localInsertCRDT(index, blockId);
8793
} catch {
8894
initMom();
95+
return;
8996
}
9097

91-
socket.emit(MOM_EVENT.INSERT_BLOCK, blockId, remoteInsertion);
98+
const message: MomMessage.InsertBlock = { blockId, op: remoteInsertion };
99+
socket.emit(MOM_EVENT.INSERT_BLOCK, message);
92100
};
93101

94102
const deleteBlock = (id: string, index: number) => {
@@ -98,9 +106,11 @@ function Mom() {
98106
remoteDeletion = localDeleteCRDT(index);
99107
} catch {
100108
initMom();
109+
return;
101110
}
102111

103-
socket.emit(MOM_EVENT.DELETE_BLOCK, id, remoteDeletion);
112+
const message: MomMessage.DeleteBlock = { blockId: id, op: remoteDeletion };
113+
socket.emit(MOM_EVENT.DELETE_BLOCK, message);
104114
};
105115

106116
const onHandleBlocks: React.KeyboardEventHandler = (e) => {
@@ -141,12 +151,12 @@ function Mom() {
141151
useEffect(() => {
142152
initMom();
143153

144-
socket.on(MOM_EVENT.INIT, (crdt) => {
154+
socket.on(MOM_EVENT.INIT, ({ crdt }: MomMessage.Initialized) => {
145155
syncCRDT(crdt);
146156
setBlocks(spreadCRDT());
147157
});
148158

149-
socket.on(MOM_EVENT.UPDATE_TITLE, (title) => {
159+
socket.on(MOM_EVENT.UPDATE_TITLE, ({ title }: MomMessage.UpdatedTitle) => {
150160
if (!titleRef.current) return;
151161

152162
titleRef.current.innerText = title;
@@ -157,7 +167,7 @@ function Mom() {
157167
setBlocks(spreadCRDT());
158168
});
159169

160-
socket.on(MOM_EVENT.INSERT_BLOCK, (op) => {
170+
socket.on(MOM_EVENT.INSERT_BLOCK, ({ op }: MomMessage.InsertedBlock) => {
161171
try {
162172
remoteInsertCRDT(op);
163173
} catch {
@@ -169,7 +179,7 @@ function Mom() {
169179
setBlocks(spreadCRDT());
170180
});
171181

172-
socket.on(MOM_EVENT.DELETE_BLOCK, (op) => {
182+
socket.on(MOM_EVENT.DELETE_BLOCK, ({ op }: MomMessage.DeletedBlock) => {
173183
try {
174184
remoteDeleteCRDT(op);
175185
} catch {
@@ -181,25 +191,31 @@ function Mom() {
181191
setBlocks(spreadCRDT());
182192
});
183193

184-
socket.on(BLOCK_EVENT.INIT_TEXT, (id, crdt) => {
194+
const onInitializedText = ({ id, crdt }: BlockMessage.InitializedText) => {
185195
ee.emit(`${BLOCK_EVENT.INIT_TEXT}-${id}`, crdt);
186-
});
196+
};
187197

188-
socket.on(BLOCK_EVENT.INSERT_TEXT, (id, op) => {
198+
const onInsertedText = ({ id, op }: BlockMessage.InsertedText) => {
189199
ee.emit(`${BLOCK_EVENT.INSERT_TEXT}-${id}`, op);
190-
});
200+
};
191201

192-
socket.on(BLOCK_EVENT.DELETE_TEXT, (id, op) => {
202+
const onDeletedText = ({ id, op }: BlockMessage.DeletedText) => {
193203
ee.emit(`${BLOCK_EVENT.DELETE_TEXT}-${id}`, op);
194-
});
204+
};
195205

196-
socket.on(BLOCK_EVENT.UPDATE_TEXT, (id, crdt) => {
206+
const onUpdatedText = ({ id, crdt }: BlockMessage.UpdatedText) => {
197207
ee.emit(`${BLOCK_EVENT.UPDATE_TEXT}-${id}`, crdt);
198-
});
208+
};
199209

200-
socket.on(BLOCK_EVENT.UPDATE_TYPE, (id, type) => {
210+
const onUpdatedType = ({ id, type }: BlockMessage.UpdatedType) => {
201211
ee.emit(`${BLOCK_EVENT.UPDATE_TYPE}-${id}`, type);
202-
});
212+
};
213+
214+
socket.on(BLOCK_EVENT.INIT_TEXT, onInitializedText);
215+
socket.on(BLOCK_EVENT.INSERT_TEXT, onInsertedText);
216+
socket.on(BLOCK_EVENT.DELETE_TEXT, onDeletedText);
217+
socket.on(BLOCK_EVENT.UPDATE_TEXT, onUpdatedText);
218+
socket.on(BLOCK_EVENT.UPDATE_TYPE, onUpdatedType);
203219

204220
return () => {
205221
[

0 commit comments

Comments
 (0)