Simple Chat
Video Lecture
![Simple Chat](/img/yt_btn_sm.gif)
Description
Creating a simple chat client and server.
./src/server/randomScreenNameGenerator.ts
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 | export default class RandomScreenNameGenerator {
private animals = [
'Cat',
'Dog',
'Bird',
'Tiger',
'Giraffe',
'Elephant',
'Koala',
'Bee',
'Fly',
'Fish',
'Frog'
]
private colours = ['Red', 'Green', 'Blue', 'Yellow', 'Orange', 'Purple']
public generateRandomScreenName() {
let colour = this.colours[Math.floor(Math.random() * this.colours.length)]
let animal = this.animals[Math.floor(Math.random() * this.animals.length)]
let screenName = {
name: colour + ' ' + animal,
abbreviation: colour[0] + animal[0]
}
return screenName
}
}
|
./src/server/server.ts
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 | import { createServer } from 'http'
import { Server } from 'socket.io'
import * as express from 'express'
import * as path from 'path'
import RandomScreenNameGenerator from './randomScreenNameGenerator'
const port = 3000
const app = express()
app.use(express.static(path.join(__dirname, '../client')))
const server = createServer(app)
const io = new Server(server)
const randomScreenNameGenerator = new RandomScreenNameGenerator()
io.on('connection', (socket) => {
console.log('a user connected : ' + socket.id)
let screenName = randomScreenNameGenerator.generateRandomScreenName()
socket.emit('screenName', screenName)
socket.broadcast.emit('systemMessage', screenName.name + ' has joined the chat')
socket.on('disconnect', () => {
console.log('socket disconnected : ' + socket.id)
socket.broadcast.emit('systemMessage', screenName.name + ' has left the chat')
})
socket.on('chatMessage', (message: ChatMessage) => {
socket.broadcast.emit('chatMessage', message)
})
})
server.listen(port, () => {
console.log('Server listening on port ' + port)
})
|
./src/typings/index.d.ts
| type ScreenName = {
name: string
abbreviation: string
}
type ChatMessage = {
message: string
from: string
}
|
./src/server/tsconfig.json
| {
"compilerOptions": {
"target": "ES6",
"module": "commonjs",
"outDir": "../../dist/server",
"strict": true
},
"include": ["**/*.ts", "../typings/*"]
}
|
./src/client/client.ts
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 | import { io } from 'socket.io-client'
let screenName: ScreenName
const messageList = document.getElementById('messageList') as HTMLOListElement
const messageText = document.getElementById('messageText') as HTMLInputElement
const sendButton = document.getElementById('sendButton') as HTMLButtonElement
const socket = io()
socket.on('connect', () => {
console.log('connect')
})
socket.on('disconnect', (message) => {
console.log('disconnect ' + message)
})
socket.on('screenName', (message: ScreenName) => {
screenName = message
;(document.getElementsByClassName('screenName')[0] as HTMLSpanElement).innerText =
screenName.name
})
socket.on('chatMessage', (message: ChatMessage) => {
const li = document.createElement('li')
li.innerHTML =
"<span class='circle' style='float: right;'>" +
message.from +
"</span><div class='otherMessage'>" +
message.message +
'</div>'
messageList.appendChild(li)
scrollChatWindow()
})
socket.on('systemMessage', (message) => {
const li = document.createElement('li')
li.innerHTML = "<div class='systemMessage'>" + message + '</div>'
messageList.appendChild(li)
scrollChatWindow()
})
messageText.addEventListener('keypress', (e) => {
if (e.code === 'Enter') {
sendMessage()
return false
}
})
function sendMessage() {
if (messageText.value.length > 0) {
socket.emit('chatMessage', <ChatMessage>{
message: messageText.value,
from: screenName.abbreviation
})
const li = document.createElement('li')
li.innerHTML =
"<span class='circle' style='float: left;'>" +
screenName.abbreviation +
"</span><div class='myMessage'>" +
messageText.value +
'</div>'
messageList.appendChild(li)
messageText.value = ''
scrollChatWindow()
}
}
sendButton.addEventListener('click', () => {
sendMessage()
})
function scrollChatWindow() {
const count = document.querySelectorAll('#messageList li').length
if (count > 10) {
messageList.removeChild(messageList.firstChild as HTMLLIElement)
}
messageList.scrollTo({ top: messageList.scrollHeight, behavior: 'smooth' })
}
|
./src/client/tsconfig.json
| {
"compilerOptions": {
"target": "ESNext",
"module": "NodeNext",
"outDir": "../../dist/client/",
"moduleResolution": "NodeNext",
"strict": true
},
"include": ["**/*.ts", "../typings/*"]
}
|
./dist/client/index.html
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
124
125
126
127 | <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>
Simple Chat : Socket.IO TypeScript Tutorials by Sean Bradley :
https://sbcode.net/tssock/
</title>
<style>
body {
font-family: Arial;
}
.chatPanel {
border: solid 1px gray;
border-radius: 20px 0px 4px 4px;
box-shadow: 15px 10px #dddddd;
background: rgb(34, 193, 195);
background: linear-gradient(
56deg,
rgba(34, 193, 195, 0.49193275943189773) 0%,
rgba(253, 187, 45, 0.494733879880077) 100%
);
position: relative;
width: 500px;
}
.chatMessageInputDiv {
position: absolute;
bottom: 0px;
width: 100%;
}
#messageText {
width: 400px;
font-size: 21px;
}
#sendButton {
position: absolute;
right: 0px;
width: 93px;
height: 31px;
border-radius: 0;
border: 0px;
color: #fff;
background-color: #17a2b8;
border-color: #17a2b8;
font-size: 21px;
}
#messageList {
padding-left: 0;
overflow: hidden;
height: 338px;
margin-bottom: 40px;
}
#messageList li {
list-style-type: none;
margin-bottom: 30px;
padding: 6px 6px 6px 6px;
display: block;
}
.otherMessage {
background: #ffcda3;
border: solid 1px gray;
margin: 0px 5px 5px 0px;
float: right;
padding: 0px 6px 0px 6px;
border-radius: 10px 10px 0 10px;
font-size: 21px;
}
.myMessage {
background: #1bffbb;
border: solid 1px gray;
margin: 0px 5px 5px 5px;
float: left;
padding: 0px 6px 0px 6px;
border-radius: 10px 10px 10px 0;
font-size: 21px;
}
.systemMessage {
background: #dddddd;
border: solid 1px gray;
margin: 0px 5px 5px 0px;
float: right;
padding: 0px 6px 0px 6px;
border-radius: 10px 10px 0 10px;
font-size: 21px;
}
.screenName {
padding: 6px 6px 6px 6px;
border-radius: 10px 10px 10px 10px;
font-weight: bold;
background: #1bffbb;
}
.circle {
padding: 6px;
background: gray;
border-radius: 50px;
}
</style>
</head>
<body>
<h1>Your Screen Name is <span class="screenName"></span></h1>
<div class="chatPanel">
<ol id="messageList"></ol>
<div class="chatMessageInputDiv">
<div>
<input id="messageText" placeholder="Enter Chat Message" />
<span>
<button id="sendButton">Send</button>
</span>
</div>
</div>
</div>
<script type="module" src="bundle.js"></script>
</body>
</html>
|