├── .gitignore ├── README.md ├── package.json ├── static ├── dateTime.js ├── client.js └── style.css ├── server.js └── client.html /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # chat-room 2 | * A simple real time chat app using socket.io 3 | * Link to [chat-room](https://chat-room.adarshkumar35.repl.co) 4 | 5 | ## how to use? 6 | * clone the project into your local pc 7 | * run the command ``` npm install ``` to install all required dependencies 8 | * now run ``` node server.js ``` 9 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nodejs", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "server.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "@types/node": "^18.0.6", 14 | "express": "^4.18.2", 15 | "node-fetch": "^3.2.6", 16 | "socket.io": "^4.6.1" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /static/dateTime.js: -------------------------------------------------------------------------------- 1 | let month = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] 2 | 3 | function getTime() { 4 | let d = new Date(); 5 | 6 | let time = { 7 | date: d.getDate(), 8 | month: month[d.getMonth() - 1], 9 | year: d.getFullYear(), 10 | hours: d.getHours(), 11 | minutes: d.getMinutes(), 12 | seconds: d.getSeconds(), 13 | meridiem: (d.getHours() < 13) ? 'AM' : 'PM' 14 | } 15 | 16 | return time; 17 | } 18 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const app = express(); 3 | 4 | const path = require('path'); 5 | 6 | app.use('/static', express.static(path.join(__dirname, 'static'))); 7 | app.use(express.urlencoded()); 8 | 9 | const http = require('http'); 10 | const server = http.createServer(app); 11 | 12 | let users = {} 13 | 14 | const io = require('socket.io')(server); 15 | console.log('server started'); 16 | // socket server 17 | io.on('connection', (socket) => { 18 | socket.on('disconnect', () => { 19 | if (users[socket.id] != undefined) { 20 | console.log(`${users[socket.id]} leaved`); 21 | socket.broadcast.emit('user leaved', `${users[socket.id]} leaved`); 22 | } 23 | else { 24 | console.log(`${users[socket.id]} leaved`); 25 | } 26 | }); 27 | 28 | socket.on('user message', (sender, msg) => { 29 | socket.broadcast.emit('um', sender, msg); 30 | }); 31 | 32 | socket.on('user name', (name) => { 33 | users[socket.id] = name; 34 | console.log(name, ' connected'); 35 | console.log(`${users[socket.id]}'s id :`, socket.id); 36 | socket.broadcast.emit('un', name); 37 | }); 38 | }); 39 | 40 | app.get('/', (req, res) => { 41 | res.sendFile(__dirname + '/client.html'); 42 | }); 43 | 44 | // app.get('./send icon.svg', (req, res) => { 45 | // res.sendFile(__dirname + '/sendIcon.svg'); 46 | // }) 47 | 48 | server.listen(8000, () => { 49 | console.log('server running on port 8000'); 50 | }); -------------------------------------------------------------------------------- /client.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Chat Room 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 |
18 |
19 | 20 | 21 | 42 | 43 | 44 |
45 |
46 |
47 | 48 | 49 |
50 |
51 |
52 |
53 | 54 | 55 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /static/client.js: -------------------------------------------------------------------------------- 1 | // messageContainer.children[messageContainer.childElementCount - 1] 2 | 3 | messageContainer = document.querySelector('.messageContainer'); 4 | 5 | function displayMsg(sender, senderName, msg) { 6 | let newMsg = document.createElement('div'); 7 | newMsg.setAttribute('class', `msg ${sender}`); 8 | // if (senderName == lastMsgSender) { 9 | // if (sender == 'mm') { 10 | // newMsg.innerHTML = ` 11 | //
${msg}
`; 12 | // } 13 | // else { 14 | // newMsg.innerHTML = ` 15 | //
${msg}
`; 16 | // } 17 | // console.log('same'); 18 | // } 19 | // else { 20 | // newMsg.setAttribute('style', 'margin : 8px 0px 0px 0px'); 21 | // if (sender == 'mm') { 22 | newMsg.innerHTML = ` 23 |
24 |
@${senderName}
25 |
${getTime().date} ${getTime().month} ${getTime().year} ${getTime().hours}:${getTime().minutes}:${getTime().seconds} ${getTime().meridiem}
26 |
27 | 28 |
${msg}
`; 29 | // } 30 | // else { 31 | // newMsg.innerHTML = ` 32 | //
@${senderName}
33 | //
${msg}
`; 34 | // } 35 | console.log(getTime()); 36 | // console.log('not same'); 37 | // } 38 | // newMsgLine.appendChild(newMsg); 39 | messageContainer.appendChild(newMsg); 40 | messageContainer.scroll(0, messageContainer.scrollHeight); 41 | lastMsgSender = senderName; 42 | } 43 | 44 | function notify(notification) { 45 | let notifier = document.createElement('div'); 46 | notifier.innerText = notification; 47 | notifier.setAttribute('class', 'notifier'); 48 | messageContainer.appendChild(notifier); 49 | messageContainer.scroll(0, messageContainer.scrollHeight); 50 | } 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | name = getName('enter your name :'); 59 | function getName(str) { 60 | let userName = prompt(str); 61 | if (userName == '' || userName == null) { 62 | getName('please specify your name to join the chat room :'); 63 | } 64 | if (userName.length > 26) { 65 | getName( 66 | `sorry! can't set username.\nusername should contain less than 26 characters.`); 67 | } 68 | else { 69 | socket.emit('user name', userName); 70 | notify(`you joined the chat as ${userName}`); 71 | return userName; 72 | } 73 | } 74 | 75 | socket.on('un', (name) => { 76 | notify(`${name} joined the chat`); 77 | }); 78 | socket.on('user leaved', (wholeaved) => { 79 | notify(wholeaved); 80 | }); 81 | 82 | let form = document.querySelector('form'); 83 | let message = document.querySelector('input'); 84 | form.addEventListener('submit', (e) => { 85 | e.preventDefault(); 86 | if (message.value != 0) { 87 | socket.emit('user message', name, message.value); 88 | displayMsg('mm', name, message.value); 89 | message.value = ''; 90 | } 91 | }); 92 | 93 | socket.on('um', (sender, msg) => { 94 | displayMsg('om', sender, msg); 95 | }); -------------------------------------------------------------------------------- /static/style.css: -------------------------------------------------------------------------------- 1 | :root { 2 | /* --themebg: #1e2b2b; 3 | --themebgdark : #121a1a; 4 | --themeclr: #d7d28a; */ 5 | /* --hoverclr: #374c4c; */ 6 | 7 | --themebg: #303440; 8 | --themebgdark: #121a1a; 9 | --themeclr: #8b8ad7; 10 | --hoverclr: #9caad724; 11 | } 12 | * { 13 | margin: 0; 14 | padding: 0; 15 | } 16 | html{ 17 | overflow: auto; 18 | } 19 | .container { 20 | height: calc(100vh - 2px); 21 | background: #4c4c4c; 22 | display: flex; 23 | flex-direction: column; 24 | align-items: center; 25 | padding-top: 2px; 26 | } 27 | 28 | .chatContainer { 29 | /* background: #1c2333; */ 30 | background-color: var(--themebg); 31 | height: 100%; 32 | width: 100%; 33 | display: flex; 34 | flex-direction: column; 35 | align-items: center; 36 | padding: 0px 0px 2px 0px; 37 | } 38 | 39 | .messageContainer { 40 | width: 96%; 41 | height: -webkit-fill-available; 42 | border-radius: 10px 10px 0px 0px; 43 | overflow: auto; 44 | padding: 0px 7px; 45 | } 46 | 47 | .msg { 48 | color: lightgrey; 49 | min-height: 52px; 50 | height: 52px; 51 | /* border-bottom: 1px solid #3c3c3c; */ 52 | display: flex; 53 | align-items: center; 54 | padding-left: 10px; 55 | } 56 | .msg:hover{ 57 | background: var(--hoverclr); 58 | } 59 | .msg.mm{ 60 | background-color: transparent; 61 | } 62 | .msg.om{ 63 | background-color: transparent; 64 | } 65 | .at{ 66 | color: gray; 67 | } 68 | .sender { 69 | color: var(--themeclr); 70 | border-right: 1px solid gray; 71 | padding-right: 10px; 72 | padding-left: 10px; 73 | height: 80%; 74 | width: 10%; 75 | display: flex; 76 | flex-direction: column; 77 | justify-content: center; 78 | align-items: end; 79 | gap: 2px; 80 | } 81 | .s{ 82 | font-size: 17px; 83 | } 84 | .time { 85 | font-size: 12px; 86 | color: gray; 87 | } 88 | .mm, .om{ 89 | min-width: 86%; 90 | } 91 | .mm { 92 | /* background: #47598b; */ 93 | padding-left: 10px; 94 | } 95 | .om { 96 | /* background: #47598b; */ 97 | padding-left: 10px; 98 | } 99 | .notifier { 100 | color: #808080a6; 101 | border: 1px solid #80808087; 102 | background: transparent; 103 | height: 30px; 104 | display: flex; 105 | justify-content: center; 106 | align-items: center; 107 | border: none; 108 | border-bottom: 1px solid #3c3c3c87; 109 | border-top: 1px solid #3c3c3c87; 110 | } 111 | 112 | .sendMsg { 113 | width: 100%; 114 | height: 66px; 115 | position: sticky; 116 | bottom: 0; 117 | } 118 | 119 | 120 | 121 | 122 | /* new form style */ 123 | form{ 124 | border-top: 1px solid #3c445c; 125 | position: sticky; 126 | bottom: 0; 127 | padding: 0px 0px 0px 0px; 128 | background: #1c2333; 129 | } 130 | button{ 131 | font-size: 26px !important; 132 | height: 94% !important; 133 | width: 10% !important; 134 | background: transparent !important; 135 | display: flex !important; 136 | justify-content: center !important; 137 | align-items: center !important; 138 | } 139 | i{ 140 | color: #374058; 141 | } 142 | 143 | /* */ 144 | 145 | 146 | 147 | 148 | form { 149 | width: 100%; 150 | height: 100%; 151 | display: flex; 152 | justify-content: center; 153 | align-items: center; 154 | } 155 | 156 | input { 157 | color: white; 158 | width: 85%; 159 | height: 51%; 160 | background: transparent; 161 | border: none; 162 | outline: none; 163 | padding-left: 20px; 164 | font-size: 18px; 165 | background: #2b3245; 166 | border-radius: 7px; 167 | margin-right: 30px; 168 | height: 57%; 169 | } 170 | 171 | button { 172 | height: 100%; 173 | width: 5%; 174 | font-size: 20px; 175 | font-family: system-ui; 176 | background: #e0e3ff; 177 | color: white; 178 | border: none; 179 | cursor: pointer; 180 | } 181 | 182 | .messageContainer::-webkit-scrollbar { 183 | background: transparent; 184 | width: 5px; 185 | } 186 | 187 | .messageContainer::-webkit-scrollbar-thumb { 188 | background: #ffffff26; 189 | border-radius: 4px; 190 | } 191 | 192 | @media (max-width: 600px) { 193 | .container { 194 | height: 100vh; 195 | } 196 | 197 | .container>h1 { 198 | font-size: 20px; 199 | } 200 | 201 | .chatContainer{ 202 | background-size: cover; 203 | } 204 | 205 | .messageContainer { 206 | height: calc(100% - 30px); 207 | width: 100%; 208 | } 209 | 210 | .msg.mm, .msg.om{ 211 | margin: 8px 0px 8px 0px; 212 | box-shadow: black 0px 0px 8px -2px; 213 | min-height: 70px; 214 | display: block; 215 | height: auto; 216 | padding-bottom: 8px; 217 | } 218 | .msg.mm{ 219 | border-left: 2px solid #8688c5; 220 | } 221 | .msg.om{ 222 | border-left: 2px solid #7cb7b7; 223 | } 224 | .sender{ 225 | width: 91%; 226 | border-right: none; 227 | flex-direction: row; 228 | align-items: center; 229 | height: 27px; 230 | gap: 52%; 231 | padding: 0; 232 | } 233 | 234 | .notifier { 235 | height: 14px; 236 | font-size: 12px; 237 | /* min-width: auto; 238 | width: fit-content; */ 239 | } 240 | 241 | 242 | input{ 243 | margin: 10px 5px 10px 5px; 244 | width: 70%; 245 | } 246 | 247 | button { 248 | font-size: 16px; 249 | width: 12%; 250 | height: 90%; 251 | margin-right: 1px; 252 | } 253 | } --------------------------------------------------------------------------------