1
+ import Quill from "quill" ;
2
+ import "quill/dist/quill.snow.css" ;
3
+
4
+ import { Box } from "@mui/material" ;
5
+ import { useEffect , useState } from "react" ;
6
+
7
+ import styled from "@emotion/styled" ;
8
+
9
+ import { io } from "socket.io-client" ;
10
+ import { useParams } from "react-router-dom" ;
11
+
12
+
13
+ const Component = styled . div `
14
+ background: #F5F5F5;
15
+ `
16
+
17
+ const toolbarOptions = [
18
+ [ 'bold' , 'italic' , 'underline' , 'strike' ] , // toggled buttons
19
+ [ 'blockquote' , 'code-block' ] ,
20
+
21
+ [ { 'header' : 1 } , { 'header' : 2 } ] , // custom button values
22
+ [ { 'list' : 'ordered' } , { 'list' : 'bullet' } ] ,
23
+ [ { 'script' : 'sub' } , { 'script' : 'super' } ] , // superscript/subscript
24
+ [ { 'indent' : '-1' } , { 'indent' : '+1' } ] , // outdent/indent
25
+ [ { 'direction' : 'rtl' } ] , // text direction
26
+
27
+ [ { 'size' : [ 'small' , false , 'large' , 'huge' ] } ] , // custom dropdown
28
+ [ { 'header' : [ 1 , 2 , 3 , 4 , 5 , 6 , false ] } ] ,
29
+ [ 'link' , 'image' ] ,
30
+ [ { 'color' : [ ] } , { 'background' : [ ] } ] , // dropdown with defaults from theme
31
+ [ { 'font' : [ ] } ] ,
32
+ [ { 'align' : [ ] } ] ,
33
+
34
+ [ 'clean' ] // remove formatting button
35
+ ] ;
36
+
37
+
38
+ const Editor = ( ) => {
39
+
40
+ const [ socket , setSocket ] = useState ( ) ;
41
+ const [ quill , setQuill ] = useState ( ) ;
42
+ const { id} = useParams ( ) ;
43
+
44
+ useEffect ( ( ) => {
45
+ const quillserver = new Quill ( '#container' , { theme : 'snow' , modules : { toolbar : toolbarOptions } } ) ;
46
+ quillserver . disable ( ) ;
47
+ quillserver . setText ( 'Loading the Document ...' )
48
+ setQuill ( quillserver ) ;
49
+ } , [ ] )
50
+
51
+ useEffect ( ( ) => {
52
+ const socketServer = io ( 'http://localhost:9000' ) ;
53
+ setSocket ( socketServer ) ;
54
+ return ( ) => {
55
+ socketServer . disconnect ( ) ;
56
+ }
57
+ } , [ ] )
58
+
59
+ useEffect ( ( ) => {
60
+
61
+ if ( socket === null || quill === null ) return ;
62
+
63
+ const handleChange = ( delta , oldData , source ) => {
64
+ if ( source !== 'user' ) return ;
65
+
66
+ socket && socket . emit ( 'send-changes' , delta ) ;
67
+
68
+ }
69
+
70
+ quill && quill . on ( 'text-change' , handleChange ) ;
71
+
72
+ return ( ) => {
73
+ quill && quill . off ( 'text-change' , handleChange ) ;
74
+ }
75
+ } , [ quill , socket ] ) ;
76
+
77
+
78
+ useEffect ( ( ) => {
79
+
80
+ if ( socket === null || quill === null ) return ;
81
+
82
+ const handleChange = ( delta ) => {
83
+
84
+ quill . updateContents ( delta ) ;
85
+
86
+ }
87
+
88
+ socket && socket . on ( 'receive-changes' , handleChange ) ;
89
+
90
+ return ( ) => {
91
+ socket && socket . off ( 'receive-changes' , handleChange ) ;
92
+ }
93
+ } , [ quill , socket ] ) ;
94
+
95
+ useEffect ( ( ) => {
96
+ if ( socket === null || quill === null ) return ;
97
+
98
+ socket && socket . once ( 'load-document' , document => {
99
+ quill && quill . setContents ( document ) ;
100
+ quill && quill . enable ( ) ;
101
+ } )
102
+
103
+ socket && socket . emit ( 'get-document' , id )
104
+ } , [ quill , socket , id ] ) ;
105
+
106
+ useEffect ( ( ) => {
107
+ if ( socket === null || quill === null ) return ;
108
+
109
+ const interval = setInterval ( ( ) => {
110
+ socket && socket . emit ( 'save-document' , quill . getContents ( ) )
111
+ } , 2000 ) ;
112
+
113
+ return ( ) => {
114
+ clearInterval ( interval ) ;
115
+ }
116
+ } , [ socket , quill ] ) ;
117
+
118
+ return (
119
+ < Component >
120
+ < Box className = 'container' id = 'container' > </ Box >
121
+ </ Component >
122
+
123
+ )
124
+ }
125
+
126
+ export default Editor
0 commit comments