-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathindex.jsx
More file actions
123 lines (104 loc) · 3.12 KB
/
index.jsx
File metadata and controls
123 lines (104 loc) · 3.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import React from 'react';
import ReactDOM from 'react-dom/client';
function Chat({ webSocket }) {
const [name, setName] = React.useState('');
return (
<main>
<Name updateName={setName} />
<Message name={name} webSocket={webSocket} />
<Conversation webSocket={webSocket} />
</main>
);
}
function Name({ updateName }) {
return (
<main>
<div className='name'>
<fieldset id='name-controls'>
<legend>My Name</legend>
<input onChange={(e) => updateName(e.target.value)} id='my-name' type='text' />
</fieldset>
</div>
</main>
);
}
function Message({ name, webSocket }) {
const [message, setMessage] = React.useState('');
function doneMessage(e) {
if (e.key === 'Enter') {
sendMsg();
}
}
function sendMsg() {
webSocket.sendMessage(name, message);
setMessage('');
}
const disabled = name === '' || !webSocket.connected;
return (
<main>
<fieldset id='chat-controls'>
<legend>Chat</legend>
<input disabled={disabled} onKeyDown={(e) => doneMessage(e)} value={message} onChange={(e) => setMessage(e.target.value)} type='text' />
<button disabled={disabled || !message} onClick={sendMsg}>
Send
</button>
</fieldset>
</main>
);
}
function Conversation({ webSocket }) {
const [chats, setChats] = React.useState([]);
React.useEffect(() => {
webSocket.addObserver((chat) => {
setChats((prevMessages) => [...prevMessages, chat]);
});
}, [webSocket]);
const chatEls = chats.map((chat, index) => (
<div key={index}>
<span className={chat.event}>{chat.from}</span> {chat.msg}
</div>
));
return (
<main>
<div id='chat-text'>{chatEls}</div>
</main>
);
}
class ChatClient {
observers = [];
connected = false;
constructor() {
// Adjust the webSocket protocol to what is being used for HTTP
const protocol = window.location.protocol === 'http:' ? 'ws' : 'wss';
this.socket = new WebSocket(`${protocol}://${window.location.host}/ws`);
// Display that we have opened the webSocket
this.socket.onopen = (event) => {
this.notifyObservers('system', 'websocket', 'connected');
this.connected = true;
};
// Display messages we receive from our friends
this.socket.onmessage = async (event) => {
const text = await event.data.text();
const chat = JSON.parse(text);
this.notifyObservers('received', chat.name, chat.msg);
};
// If the webSocket is closed then disable the interface
this.socket.onclose = (event) => {
this.notifyObservers('system', 'websocket', 'disconnected');
this.connected = false;
};
}
// Send a message over the webSocket
sendMessage(name, msg) {
this.notifyObservers('sent', 'me', msg);
this.socket.send(JSON.stringify({ name, msg }));
}
addObserver(observer) {
this.observers.push(observer);
}
notifyObservers(event, from, msg) {
this.observers.forEach((h) => h({ event, from, msg }));
}
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Chat webSocket={new ChatClient()} />);