80 |
87 |
88 | Room Name:
81 |
82 |
83 |
84 | ├── .github
└── pull_request_template.md
├── .gitignore
├── CONTRIBUTORS.md
├── Designs
├── VineethKumarM.json
├── kaneki-ken260.json
├── template.json
└── varunKT001.json
├── Dockerfile
├── Procfile
├── README.md
├── app.js
├── models
├── message.js
└── user.js
├── package-lock.json
├── package.json
├── public
├── avtars
│ ├── 01.png
│ ├── 02.png
│ ├── 03.png
│ ├── 04.png
│ ├── 05.png
│ ├── 06.png
│ ├── 07.png
│ ├── 08.png
│ ├── 09.png
│ ├── 10.png
│ ├── 11.png
│ └── 12.png
├── js
│ ├── avatar.js
│ ├── dark-mode.js
│ ├── gradient.js
│ ├── index.js
│ ├── lastEncounter.js
│ └── roomMembers.js
├── scss
│ ├── index.scss
│ └── main.scss
├── sounds
│ ├── beep1.mp3
│ ├── beep2.wav
│ └── beep3.mp3
└── uploads
│ └── .gitkeep
├── routes
├── image.js
└── index.js
├── utils
├── message.js
├── roomMembersCount.js
└── users.js
└── views
├── index.html
└── main.html
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
1 | Issue: ISSUENUMBER
2 |
3 |
4 |
5 |
6 | #### Short description of what this resolves:
7 |
8 |
9 |
10 | #### Changes proposed in this pull request and/or Screenshots of changes:
11 |
12 | -
13 | -
14 | -
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | lerna-debug.log*
8 | .DS_Store
9 |
10 | # Diagnostic reports (https://nodejs.org/api/report.html)
11 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
12 |
13 | # Runtime data
14 | pids
15 | *.pid
16 | *.seed
17 | *.pid.lock
18 |
19 | # Directory for instrumented libs generated by jscoverage/JSCover
20 | lib-cov
21 |
22 | # Coverage directory used by tools like istanbul
23 | coverage
24 | *.lcov
25 |
26 | # nyc test coverage
27 | .nyc_output
28 |
29 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
30 | .grunt
31 |
32 | # Bower dependency directory (https://bower.io/)
33 | bower_components
34 |
35 | # node-waf configuration
36 | .lock-wscript
37 |
38 | # Compiled binary addons (https://nodejs.org/api/addons.html)
39 | build/Release
40 |
41 | # Dependency directories
42 | node_modules/
43 | jspm_packages/
44 | # Snowpack dependency directory (https://snowpack.dev/)
45 | web_modules/
46 |
47 | # TypeScript cache
48 | *.tsbuildinfo
49 |
50 | # Optional npm cache directory
51 | .npm
52 |
53 | # Optional eslint cache
54 | .eslintcache
55 |
56 | # Microbundle cache
57 | .rpt2_cache/
58 | .rts2_cache_cjs/
59 | .rts2_cache_es/
60 | .rts2_cache_umd/
61 |
62 | # Optional REPL history
63 | .node_repl_history
64 |
65 | # Output of 'npm pack'
66 | *.tgz
67 |
68 | # Yarn Integrity file
69 | .yarn-integrity
70 |
71 | # dotenv environment variables file
72 | .env
73 | .env.test
74 |
75 | # parcel-bundler cache (https://parceljs.org/)
76 | .cache
77 | .parcel-cache
78 |
79 | # Next.js build output
80 | .next
81 | out
82 |
83 | # Nuxt.js build / generate output
84 | .nuxt
85 | dist
86 |
87 | # Gatsby files
88 | .cache/
89 | # Comment in the public line in if your project uses Gatsby and not Next.js
90 | # https://nextjs.org/blog/next-9-1#public-directory-support
91 | # public
92 |
93 | # vuepress build output
94 | .vuepress/dist
95 |
96 | # Serverless directories
97 | .serverless/
98 |
99 | # FuseBox cache
100 | .fusebox/
101 |
102 | # DynamoDB Local files
103 | .dynamodb/
104 |
105 | # TernJS port file
106 | .tern-port
107 |
108 | # Stores VSCode versions used for testing VSCode extensions
109 | .vscode-test
110 |
111 | # yarn v2
112 | .yarn/cache
113 | .yarn/unplugged
114 | .yarn/build-state.yml
115 | .yarn/install-state.gz
116 | .pnp.*
117 |
118 | public/uploads/*
119 | !public/uploads/.gitkeep
--------------------------------------------------------------------------------
/CONTRIBUTORS.md:
--------------------------------------------------------------------------------
1 | # List of Contributors for GeekChat!
2 |
3 |
5 |
6 | - [Aditi Yadav](https://github.com/adtoria)
7 | - [Prakhar Awasthi](https://github.com/prakhar011)
8 | - [Mallik Prabhanjan](https://github.com/vemulapandu)
9 | - [Varun Tiwari](https://github.com/varunKT001)
10 | - [Vineeth Kumar Munigyala](https://github.com/VineethKumarM)
11 | - [Aman Utkarsh](https://github.com/mitrya)
12 | - [HariPrasath R](https://github.com/HariPrasath-3)
13 | - [Amitvikram Dwivedi](https://github.com/batflarrow)
14 | - [Shailesh Tiwari](https://github.com/shlesh)
15 | - [Agrim Verma](https://github.com/AgrimVerma)
16 | - [Kirti Singla](https://github.com/codesanta142)
17 | - [sai suman kumar](https://github.com/saisumanthkumar)
18 | - [Prasanta Barman](https://github.com/prasanta352)
19 | - [Vijay Karanjkar](https://github.com/Vijay-K-2003)
20 | - [Revathi Ari](https://github.com/Revathi2306)
21 | - [Rohit Yadav](https://github.com/yadav-rohit)
22 | - [Anjali Sahu](https://github.com/99anjali)
23 | - [Danish Ahmed Mirza](https://github.com/try-catch-stack)
24 | - [Raghav Goel](https://github.com/raghavgoel25)
25 | - [Akanksha Gupta](https://github.com/Akanksha2391)
26 | - [Gautam Misra](https://github.com/Darkknight131714)
27 | - [Shantanu](https://github.com/underoot-iota)
28 | - [Puja Saraf](https://github.com/Puja-Saraf)
29 | - [Sauahrd Srivastava](https://github.com/sauhard22)
30 | - [Ramanpreet Singh](https://github.com/raman5911)
31 | - [Srishti Dhir](https://github.com/srishtayy)
32 | - [Divyansh Gupta](https://github.com/The-Divyansh)
33 | - [Prakhar jalan](https://github.com/jalanprakhar)
34 | - [Aashita Chouhan](https://github.com/aashitachouhan)
35 | - [Palak Ahuja](https://github.com/Palak-2109)
36 | - [Janhavi Bawaskar](https://github.com/janhaviiii)
37 | - [Shadaan Hussain](https://github.com/shadaanhussain)
38 | - [Saloni Doshi](https://github.com/saloni33)
39 | - [Pranavi Tadivalasa](https://github.com/Ms-Error)
40 | - [Tanushree](https://github.com/Tanushree-coder)
41 | - [Aaryan Gupta](https://github.com/Aaryan0424)
42 | - [Janhavi Bawaskar](https://github.com/janhaviiii)
43 | - [Sathwik Kuppam](https://github.com/Ksathwik03)
44 | - [Harsh Gupta](https://github.com/Harshgupta5901)
45 | - [Siddharth S](https://github.com/Siddharth1002)
46 | - [Sarthak](https://github.com/daniel-aracquine)
47 | - [Pranav Raj](https://github.com/rajpranav63)
48 | - [Gude Lakshmi](https://github.com/gudelakshmi)
49 | - [Nitheesh](https://github.com/nitheesh96)
50 | - [Rankit](https://github.com/rankit2001)
51 | - [Siddhant](https://github.com/siddhantsingh186)
52 | - [Pratik Raghuvanshi](https://github.com/prxtikk-18)
53 | - [Neeraj Gupta](https://github.com/codelord09)
54 | - [Sravya Kaviti](https://github.com/sravyakaviti)
55 | - [Md Atif](https://github.com/Atif0604)
56 | - [Diya Waghmare](https://github.com/diyawaghmare)
57 | - [Monikinderjit Singh](https://github.com/Monik09)
58 | - [Akshitha Dasa](https://github.com/AKI35429)
59 | - [Kajal Kaushal](https://github.com/Kajal-7)
60 | - [Botte Shreya](https://github.com/shreya-0508)
61 | - [Aditya Singh Machhaiya](https://github.com/asingh1601)
62 | - [Shubhi Pandey](https://github.com/Shubhi2002)
63 | - [Naman Yadav](https://github.com/Naman-11)
64 | - [Shivanshu Singh](https://github.com/Shivanshu97i)
65 | - [Anushtha Bageria](https://github.com/anu-phoenix)
66 | - [BOTTE SHREYA](https://github.com/shreya-0508)
67 | - [Manthan Jain](https://github.com/Manthanjain)
68 | - [Anushtha Bageria](https://github.com/anu-phoenix)
69 | - [Swapnil Manke](https://github.com/mankeswapnil0)
70 | - [Sneh Shah](https://github.com/Sneh16Shah)
71 | - [Neha Singh](https://github.com/neha3001-singh)
72 | - [Karan Chhabra](https://github.com/karankc23)
73 | - [Niyoj Oli](https://github.com/niyoj)
74 | - [Shivansh Dwivedi](https://github.com/shivansh2741)
75 | - [Mohammad Tabish Malik](https://github.com/Dark-Hope-tech)
76 | - [Abhay Parihar](https://github.com/A-Spiral-Forge)
77 | - [Naman Kaushal](https://github.com/naman-c)
78 | - [Pradumn Kumar](https://github.com/kumarpradumn)
79 | - [Himanshu Yadav](https://github.com/SeriousConjurer)
80 | - [Vimal Vinayak](https://github.com/BlaZe-001)
81 | - [Medha Tiwari](https://github.com/medhatiwari)
82 | - [Anushka Kalwale](https://github.com/anu-1989)
83 | - [Anuj Jain](https://github.com/anuj046)
84 | - [Mukilan S](https://github.com/MUKILAN-2003)
85 | - [Isha Rawat](https://github.com/isharawat)
86 | - [Shalini Agrawal](https://github.com/shaliniagrawal2512)
87 | - [Shashwat Mittal](https://github.com/shashwat-mittal)
88 | - [Karus Manisha](https://github.com/sanjay395)
89 | - [Mayank Kumar](https://github.com/mayank-kr)
90 | - [Abhinav Singh](https://github.com/Abhisin90)
91 | - [Abhi Singh](https://github.com/Abhijeet452)
92 |
93 |
94 |
--------------------------------------------------------------------------------
/Designs/VineethKumarM.json:
--------------------------------------------------------------------------------
1 | {
2 | "name":"Vineeth Kumar Munigyala",
3 | "github-Username": "VineethKumarM",
4 | "figma-link":"https://www.figma.com/file/6vF0LscrKRvzr6r6OpuB7N/geekchat?node-id=0%3A1"
5 | }
--------------------------------------------------------------------------------
/Designs/kaneki-ken260.json:
--------------------------------------------------------------------------------
1 | {
2 | "name":"Ritwik Rajput",
3 | "github-Username": "kaneki-ken260",
4 | "figma-link":"https://www.figma.com/file/rKgyJEXMLxa1t11xEQvP0U/GeekChat?node-id=0%3A1"
5 | }
6 |
--------------------------------------------------------------------------------
/Designs/template.json:
--------------------------------------------------------------------------------
1 | {
2 | "name":"",
3 | "github-Username": "",
4 | "figma-link":""
5 | }
--------------------------------------------------------------------------------
/Designs/varunKT001.json:
--------------------------------------------------------------------------------
1 | {
2 | "name":"Varun Tiwari",
3 | "github-Username": "varunKT001",
4 | "figma-link":"https://www.figma.com/file/vNGQo55LWnTYR3Dt4ow9BD/geekchat_ui?node-id=0%3A1"
5 | }
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:14-alpine
2 | ENV NODE_ENV=production
3 | WORKDIR /app
4 | COPY ["package.json", "package-lock.json*", "./"]
5 | RUN npm install --production
6 | COPY . .
7 | CMD ["node", "app.js"]
--------------------------------------------------------------------------------
/Procfile:
--------------------------------------------------------------------------------
1 | web: node app.js
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # GeekChat
2 |
3 | ## What is GeekChat?
4 |
5 | GeekChat is a simple bi-directional communication app where users can join rooms and have live text messaging with other users present in the room. It works on the functionalities of Web Sockets and simple HTTPS requests.[Visit here](https://oc-geekchat.herokuapp.com/)
6 |
7 | And don't forget to star ⭐ the repo, it helps ^^.
8 | ### Tech Stack
9 | * Nodejs
10 | * Express
11 | * Socket.io
12 | * HTML
13 | * CSS(SCSS)
14 | * Javascript
15 |
16 |
17 | ## Local Setup
18 |
19 | ### Pre-Requisites
20 | * [Git](https://git-scm.com/downloads)
21 | * [Node.js](https://nodejs.org/en/)
22 | * [SCSS Live Compiler](https://marketplace.visualstudio.com/items?itemName=ritwickdey.live-sass)(Only if you are changing the styling of the website)
23 |
24 | ### How to Setup?
25 |
26 | * Fork the repo.
27 | * Clone it to your local setup by using the command `git clone
115 | ${seenMsg}${pText.innerHTML}
125 | ${temp.children[1].innerText}
132 | ${seenMsg}${temp.children[1].innerText} many people typing ${TYPING_USERS.join(
320 | ", "
321 | )} are typing ${TYPING_USERS.join(
324 | ", "
325 | )} is typing many people typing ${TYPING_USERS.join(
342 | ", "
343 | )} are typing ${TYPING_USERS.join(
346 | ", "
347 | )} is typing
460 | ${seenMsg}${text.substring(3,text.length - 5)}
81 | ${values[0]["text"]}
82 | `;
83 | playSound("bot");
84 | } else {
85 |
86 | if (div.classList.contains("author")){
87 | color= "000000";
88 | }
89 | var temp = document.createElement("div");
90 | temp.innerHTML = values[0].text;
91 | div.innerHTML += `
92 |
97 | `
100 | //check if its a replied message
101 | if(temp.children.length < 2 ) {
102 | //if more than 50 characters , we truncate the message
103 | var lgMsg = values[0].text;
104 | let pText = document.createElement('p');
105 | pText.innerHTML = lgMsg.substring(3,lgMsg.length-5);
106 | if (pText.innerText.length <= 50) {
107 | div.innerHTML += `
108 | ${values[0].text}
109 | `;
110 | } else {
111 | trnc = true;
112 | var seenMsg = pText.innerText.substring(0,49);
113 | // var extraMsg = pText.innerText.substring(49,);
114 | div.innerHTML += ``
118 | ++cntr;
119 | // }
120 | }
121 | } else {
122 | var msgCntr = temp.children[0].outerHTML;
123 | if (temp.children[1].innerText.length <= 50) {
124 | div.innerHTML += `
116 | Read more${msgCntr}`;
127 | } else {
128 | trnc = true;
129 | var longMsg = temp.children[1].innerText;
130 | var seenMsg = longMsg.substring(0,49);
131 | div.innerHTML += `${msgCntr}`
135 | ++cntr;
136 | }
137 | }
138 | div.innerHTML += `${
139 | values[0].userID === values[1]
140 | ? ` `
143 | : ``
144 | }`;
145 | }
146 | if(trnc) {
147 | div.querySelector(".text").querySelector('p').classList.add('trnc');
148 | }
149 | let repliedMsgCheck = div
150 | .querySelector(".text")
151 | .querySelector(".replied-msg-container");
152 | if (repliedMsgCheck != null || repliedMsgCheck != undefined) {
153 | if (
154 | repliedMsgCheck.querySelector(".replied-msg") != null ||
155 | repliedMsgCheck.querySelector(".replied-msg") != undefined
156 | ) {
157 | repliedMsgCheck
158 | .querySelector(".replied-msg")
159 | .classList.remove("replied-msg");
160 | }
161 | }
162 | div1.appendChild(mssgProfilePhoto);
163 | div1.appendChild(div);
164 | if (values[0].username === "GeekChat Bot")
165 | document.querySelector(".chat-messages").appendChild(div);
166 | else document.querySelector(".chat-messages").appendChild(div1);
167 | scrollToBottom();
168 | }
169 |
170 | const form = document.getElementById("chat-form");
171 | form.addEventListener("submit", (e) => {
172 | e.preventDefault();
173 |
174 | let allList = document.querySelectorAll(".btn-container");
175 | allList.forEach((item) => {
176 | // item.style['display'] = 'none';
177 | item.classList.add("hide");
178 | });
179 |
180 | if (isEditing.status) {
181 | return emitEditedText(e);
182 | }
183 | if (isReplying.status) {
184 | return emitReplyMsg(e);
185 | }
186 |
187 | const msg = e.target.elements.msg.value;
188 | let userID = socket.id;
189 | if (msg.trim() == "") {
190 | } else {
191 | socket.emit("chatMessage", { msg, userID });
192 | }
193 |
194 | e.target.elements.msg.value = "";
195 | e.target.elements.msg.focus();
196 | scrollToBottom();
197 | });
198 |
199 | function scrollToBottom() {
200 | document.querySelector(".chat-messages").scrollTop =
201 | document.querySelector(".chat-messages").scrollHeight;
202 | }
203 |
204 | socket.on("userList", (userList) => {
205 | // console.log(userList)
206 | for (let { name, session_id, profilePhoto } of userList) {
207 | userMap.set(session_id, name);
208 | let user = document.createElement("li");
209 | user.classList.add("fade-in");
210 | user.dataset.id = session_id;
211 | user.innerHTML = name;
212 | const profileImage = document.createElement("img"); // created an img element to add profile photo of each entering new user
213 | profileImage.src = profilePhoto;
214 | profileImage.classList.add("userAvatar");
215 | user.appendChild(profileImage);
216 | users.appendChild(user);
217 | }
218 | });
219 | socket.on("userJoined", ({ id, username, profilePhoto }) => {
220 | userMap.set(id, username);
221 | const user = document.createElement("li");
222 | user.classList.add("fade-in");
223 | user.dataset.id = id;
224 | user.innerHTML = username;
225 | sessionStorage.setItem(username, randColor());
226 | const profileImage = document.createElement("img"); // created an img element to add profile photo of each entering new user
227 | profileImage.src = profilePhoto;
228 | profileImage.classList.add("userAvatar");
229 | user.appendChild(profileImage);
230 | users.appendChild(user);
231 | });
232 |
233 | socket.on("userLeft", ({ id, username }) => {
234 | const user = document.querySelector(`[data-id="${id}"]`);
235 | if (user) user.classList.add("fade-out");
236 | setTimeout(() => {
237 | user.remove();
238 | }, 1500);
239 | userMap.delete(id, username);
240 | });
241 |
242 | socket.on("deleteMsgFromChat", (msgId) => {
243 | if (msgId == null || msgId == undefined) {
244 | return;
245 | }
246 | document.getElementById(msgId).remove();
247 | document.getElementById(`${msgId}-topDiv`).remove();
248 | });
249 |
250 | function deleteMsg(info) {
251 | let [name, id] = info.split("_");
252 | if (name === CURRENT_USER) {
253 | socket.emit("deleteChatMsg", info);
254 | }
255 | }
256 |
257 | const beep1 = document.getElementById("beep1");
258 | const beep2 = document.getElementById("beep2");
259 | const beep3 = document.getElementById("beep3");
260 | const playSound = (beep) => {
261 | if (beep === "send") {
262 | return beep1.play();
263 | }
264 | if (beep === "bot") {
265 | return beep3.play();
266 | }
267 | return beep2.play();
268 | };
269 |
270 | //timeout for removing typing element from dom
271 | var timeout;
272 |
273 | //event for typing
274 | socket.on("typing", (typingUser) => {
275 | //push user to typingusers array
276 | TYPING_USERS.push(typingUser);
277 |
278 | //remove duplicates
279 | TYPING_USERS = [...new Set(TYPING_USERS)];
280 |
281 | //append typing event msg
282 | appendTyping();
283 |
284 | //timeout to delete typing event
285 | if (timeout !== undefined) {
286 | clearTimeout(timeout);
287 | }
288 | if (
289 | document.querySelector(".typing") != null ||
290 | document.querySelector(".typing") != undefined
291 | ) {
292 | timeout = setTimeout(() => {
293 | document.querySelector(".typing").remove();
294 | TYPING_USERS = [];
295 | }, 3000);
296 | }
297 | });
298 |
299 | //list of typing users
300 | var TYPING_USERS = [];
301 |
302 | const emitTyping = () => {
303 | socket.emit("typing", { name: CURRENT_USER, room });
304 | };
305 |
306 | //function to append typing msg
307 | const appendTyping = () => {
308 | //checking for existing typing element
309 | if (
310 | document.querySelector(".typing") != null ||
311 | document.querySelector(".typing") != undefined
312 | ) {
313 | let divEx = document.querySelector(".typing");
314 |
315 | //if found then changing its content
316 | if (TYPING_USERS.length > 2) {
317 | divEx.innerHTML = `
133 | Read more
461 | Read more
479 | Read more
' + temp + '...
'; 574 | } 575 | 576 | let userID = socket.id; 577 | if (repMsg.trim() == "") { 578 | isReplying = { status: false, info: { name: "", text: "" } }; 579 | } else { 580 | const msg = `${repMsg}
`; 581 | socket.emit("chatMessage", { msg, userID }); 582 | isReplying = { status: false, info: { name: "", text: "" } }; 583 | } 584 | //remove popup 585 | const formContainer = document.querySelector(".chat-form-container"); 586 | formContainer.classList.remove("replying-form-container"); 587 | //remove close btn 588 | formContainer.querySelector(".replying-close-btn").remove(); 589 | // //scroll 590 | let allList = document.querySelectorAll(".btn-container"); 591 | allList.forEach((item) => { 592 | // item.style['display'] = 'none'; 593 | item.classList.add("hide"); 594 | }); 595 | e.target.elements.msg.value = ""; 596 | e.target.elements.msg.focus(); 597 | scrollToBottom(); 598 | }; 599 | 600 | const cancelReply = () => { 601 | //exit replying 602 | isReplying = { status: false, info: { name: "", text: "" } }; 603 | //remove popup 604 | const formContainer = document.querySelector(".chat-form-container"); 605 | formContainer.classList.remove("replying-form-container"); 606 | //remove close btn 607 | formContainer.querySelector(".replying-close-btn").remove(); 608 | // //scroll 609 | formContainer.querySelector("#msg").focus(); 610 | scrollToBottom(); 611 | }; 612 | 613 | const cancelEdit = () => { 614 | //exit replying 615 | isEditing = { status: false, id: null }; 616 | //remove popup 617 | const formContainer = document.querySelector(".chat-form-container"); 618 | formContainer.classList.remove("editing-form-container"); 619 | //remove close btn 620 | formContainer.querySelector(".replying-close-btn").remove(); 621 | // //scroll 622 | //remove popup 623 | let allList = document.querySelectorAll(".btn-container"); 624 | allList.forEach((item) => { 625 | // item.style['display'] = 'none'; 626 | item.classList.add("hide"); 627 | }); 628 | formContainer.querySelector("#msg").focus(); 629 | scrollToBottom(); 630 | }; 631 | 632 | var isMenuOpen = false; 633 | const menuOpen = (id) => { 634 | let allList = document.querySelectorAll(".btn-container"); 635 | allList.forEach((item) => { 636 | // item.style['display'] = 'none'; 637 | item.classList.add("hide"); 638 | }); 639 | 640 | const msgDiv = document.getElementById(id); 641 | const btnContainer = msgDiv.querySelector(".btn-container"); 642 | if (!isMenuOpen) { 643 | isMenuOpen = true; 644 | // btnContainer.style['display'] = 'flex'; 645 | btnContainer.classList.remove("hide"); 646 | } else { 647 | isMenuOpen = false; 648 | // btnContainer.style['display'] = 'none'; 649 | btnContainer.classList.add("hide"); 650 | } 651 | }; 652 | 653 | isSideBarOpen = false; 654 | const toggleSideBar = () => { 655 | if (isSideBarOpen) { 656 | document.querySelector(".chat-sidebar").classList.remove("sidemenu-open"); 657 | document.querySelector(".hamburger").classList.remove("is-active"); 658 | isSideBarOpen = false; 659 | } else { 660 | document.querySelector(".chat-sidebar").classList.add("sidemenu-open"); 661 | document.querySelector(".hamburger").classList.add("is-active"); 662 | isSideBarOpen = true; 663 | } 664 | }; 665 | 666 | //image upload 667 | const imageUpload = async () => { 668 | const file = document.getElementById('image-input').files[0]; 669 | const formData = new FormData() 670 | formData.append('image', file) 671 | console.log(formData) 672 | const res = await fetch('/image', { 673 | method: 'post', 674 | body: formData 675 | }) 676 | const imgURL = await res.json(); 677 | document.getElementById('msg').value = `` 678 | document.getElementById('image-input').value = ''; 679 | } 680 | -------------------------------------------------------------------------------- /public/js/lastEncounter.js: -------------------------------------------------------------------------------- 1 | const username = document.querySelector("#exampleFormControlInput1"); 2 | const roomSelector = document.querySelector("#exampleFormControlSelect1"); 3 | const joinChatFrom = document.querySelector("#joinChatForm"); 4 | 5 | const lastUsedUserName = localStorage.getItem("last_used_username"); 6 | const lastJoinedRoom = localStorage.getItem("last_joined_room"); 7 | if (lastUsedUserName !== null) username.value = lastUsedUserName; 8 | if (lastJoinedRoom !== null) roomSelector.value = lastJoinedRoom; 9 | 10 | joinChatFrom.addEventListener("submit", () => { 11 | localStorage.setItem("last_used_username", username.value); 12 | localStorage.setItem("last_joined_room", roomSelector.value); 13 | sessionStorage.setItem("current_user", username.value); 14 | }); 15 | -------------------------------------------------------------------------------- /public/js/roomMembers.js: -------------------------------------------------------------------------------- 1 | const socket = io('/roomMembers'); 2 | socket.on('roomMembersCount', (roomMembersCount) => { 3 | for (let room in roomMembersCount) { 4 | const roomOption = document.querySelector(`option[value="${room}"]`); 5 | roomOption.innerHTML = `${room} (${roomMembersCount[room]})`; 6 | } 7 | }); 8 | socket.on('countUpdate', ({ room, count }) => { 9 | const roomOption = document.querySelector(`option[value="${room}"]`); 10 | roomOption.innerHTML = `${room} (${count})`; 11 | }); 12 | 13 | -------------------------------------------------------------------------------- /public/scss/index.scss: -------------------------------------------------------------------------------- 1 | $primary-color: #63b4b8; 2 | @import url("https://fonts.googleapis.com/css2?family=Gluten:wght@500&display=swap"); 3 | body { 4 | background: linear-gradient(90deg, rgb(0, 40, 70), rgb(255, 115, 115), rgb(255, 175, 123)); 5 | text-align: center; 6 | position: relative; 7 | min-height: 100vh; 8 | 9 | /* dark-mode toggle switch */ 10 | #toggle { 11 | position: absolute; 12 | width: 50px; 13 | height: 50px; 14 | top: 10px; 15 | right: 10px; 16 | cursor: pointer; 17 | } 18 | 19 | #toggle svg { 20 | aspect-ratio: 1; 21 | object-fit: contain; 22 | } 23 | 24 | #toggle .outer-star { 25 | transition: transform 600ms cubic-bezier(0.59, 0.02, 0, 1.26) 0s; 26 | } 27 | 28 | #toggle .inner-dot { 29 | transition: transform 600ms ease 0s; 30 | transform: matrix(1, 0, 0, 1.5, -3, 0); 31 | } 32 | 33 | #toggle.active .outer-star { 34 | transform: rotate(180deg); 35 | } 36 | 37 | #toggle.active .inner-dot { 38 | transform: matrix(1, 0, 0, 1, 0, 0); 39 | } 40 | 41 | .heading { 42 | display: flex; 43 | align-items: center; 44 | justify-content: center; 45 | height: 30vh; 46 | padding: 3%; 47 | iframe { 48 | height: 100%; 49 | pointer-events: none; 50 | width: 10%; 51 | } 52 | h1 { 53 | font-family: "Gluten", cursive; 54 | font-size: 4rem; 55 | font-weight: 600; 56 | transition: all 1s ease-in-out 0s; 57 | display: inline; 58 | } 59 | } 60 | .container-fluid { 61 | padding-bottom: 5rem !important; 62 | } 63 | .main-div { 64 | min-height: 60vh; 65 | max-width: 500px; 66 | margin: auto; 67 | border-radius: 20px; 68 | background:rgba(255,255,255,0.25); 69 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); 70 | backdrop-filter: blur(2px); 71 | padding: 1rem 2rem; 72 | form { 73 | .form-group { 74 | padding: 0; 75 | margin: 1rem auto; 76 | display:flex; 77 | flex-direction:column; 78 | } 79 | label { 80 | font-size: 1rem; 81 | padding: 1%; 82 | margin-left: 3px; 83 | text-align: left; 84 | } 85 | #username{ 86 | padding-right: 15px; 87 | text-align: left; 88 | } 89 | .form-control{ 90 | padding-top: 12px; 91 | padding-bottom: 12px; 92 | } 93 | .border-gradient { 94 | --one: #0098c1; 95 | --two: #00d721; 96 | width: 100%; 97 | padding:5px; 98 | border-radius: 15px; 99 | } 100 | input:focus{ 101 | border:none; 102 | outline:none; 103 | background:white; 104 | } 105 | input { 106 | position: relative; 107 | width: 100%; 108 | padding: 0.65rem; 109 | border-radius: 5px; 110 | border:none; 111 | box-shadow: 1px 1px 8px rgba(0,0,0,0.15); 112 | background: rgba( 255, 255, 255, 0.3 ); 113 | box-shadow: 1px 1px 10px 0 rgba( 31, 38, 135, 0.15 ); 114 | backdrop-filter: blur( 4.5px ); 115 | -webkit-backdrop-filter: blur( 4.5px ); 116 | border-radius: 10px; 117 | border: 1px solid rgba( 255, 255, 255, 0.18 ); 118 | } 119 | 120 | select { 121 | position: relative; 122 | width: 100%; 123 | padding: 0.65rem; 124 | border-radius: 5px; 125 | border:none; 126 | box-shadow: 1px 1px 8px rgba(0,0,0,0.15); 127 | background: rgba( 255, 255, 255, 0.3 ); 128 | box-shadow: 1px 1px 10px 0 rgba( 31, 38, 135, 0.15 ); 129 | backdrop-filter: blur( 4.5px ); 130 | -webkit-backdrop-filter: blur( 4.5px ); 131 | border-radius: 10px; 132 | border: 1px solid rgba( 255, 255, 255, 0.18 ); 133 | } 134 | select:focus { 135 | border:none; 136 | outline:none; 137 | background:white; 138 | } 139 | button { 140 | font-size: 15px; 141 | width: 70%; 142 | font-weight: bold; 143 | background: linear-gradient(45deg, #4daaff,#0cf076); 144 | padding: 10px 30px; 145 | color: #3d3d3d; 146 | transition: color 1s ease 0s; 147 | border: 2px solid hsl(193, 100%, 50%); 148 | border-radius: 10px; 149 | cursor: pointer; 150 | box-shadow: 0 1px 8px rgba(0, 0, 0, 0.1); 151 | -webkit-transition-duration: 0.05s; 152 | transition-duration: 0.05s; 153 | -webkit-transition-property: box-shadow, tranform; 154 | transition-property: box-shadow, transform; 155 | } 156 | button:hover, 157 | button:focus, 158 | button:active { 159 | -webkit-transform: scale(1.1); 160 | transform: scale(1.1); 161 | } 162 | } 163 | } 164 | } 165 | body::before { 166 | content: ""; 167 | position: absolute; 168 | inset: 0; 169 | background: linear-gradient(90deg, #00c9ff, #92fe9e); 170 | opacity: 1; 171 | z-index: -1; 172 | transition: all 1s ease-in-out 0.5s; 173 | } 174 | #joinChat { 175 | margin-top: 10px; 176 | margin-bottom: 20px; 177 | transition: all 1s ease 0s; 178 | } 179 | .form-group { 180 | transition: all 1s ease-in-out 0s; 181 | } 182 | .dark-mode { 183 | color: white; 184 | h1 { 185 | color: white; 186 | } 187 | .form-group { 188 | color:black; 189 | } 190 | .form-group input{ 191 | color:black; 192 | } 193 | .form-group select{ 194 | color:black; 195 | } 196 | select { 197 | color: white; 198 | border: 3px solid white; 199 | } 200 | #joinChat { 201 | background: linear-gradient(45deg, #7e4c5b, #ff7f33); 202 | border: 2px solid #8b5858; 203 | } 204 | input { 205 | color: white; 206 | } 207 | select:focus { 208 | border: 3px solid white; 209 | } 210 | #joinChat { 211 | color: white; 212 | } 213 | .border-gradient { 214 | --one: #a80000 !important; 215 | --two: #ff7631 !important; 216 | } 217 | } 218 | .dark-mode::before { 219 | opacity: 0; 220 | } 221 | /* 222 | =================================== 223 | ***Avatars*** 224 | =================================== 225 | */ 226 | 227 | .profile { 228 | width: 124px; 229 | height: 124px; 230 | margin: 30px auto; 231 | border-radius: 50%; 232 | img { 233 | width: 120px; 234 | height: 120px; 235 | border-radius: 50%; 236 | vertical-align: middle; 237 | box-shadow: rgba(50, 50, 93, 0.25) 0px 50px 100px -20px, rgba(0, 0, 0, 0.3) 0px 30px 60px -30px, 238 | rgba(10, 37, 64, 0.35) 0px -2px 6px 0px inset; 239 | } 240 | &:hover { 241 | cursor: pointer; 242 | } 243 | } 244 | /* 245 | ============================================= 246 | ******Modal Related SCSS******** 247 | ============================================ 248 | */ 249 | .modal_div { 250 | position: fixed; 251 | top: 60%; 252 | left: 50%; 253 | transform: translate(-50%, -50%); 254 | width: 400px; 255 | height: 400px; 256 | // padding: 20px; 257 | display: flex; 258 | align-items: flex-end; 259 | justify-content: center; 260 | flex-direction: column; 261 | border-radius: 10px; 262 | background-color: #fee2f8; 263 | background-image: linear-gradient(315deg, #fee2f8 0%, #dcf8ef 74%); 264 | box-shadow: 0 4rem 6rem rgba(0, 0, 0, 0.3); 265 | z-index: 1000; 266 | opacity: 1; 267 | visibility: visible; 268 | transition: all 0.7s ease 0s; 269 | p.btn--close-modal { 270 | display: block; 271 | text-align: right; 272 | margin: 0 10px; 273 | font-family: "Times New Roman", Times, serif; 274 | cursor: pointer; 275 | font-size: 3rem; 276 | font-weight: bold; 277 | } 278 | } 279 | .modal_box { 280 | width: 400px; 281 | height: 340px; 282 | } 283 | /* 284 | ============================================= 285 | ******Slider Related SCSS******** 286 | ============================================ 287 | */ 288 | 289 | .slideshow-container { 290 | position: relative; 291 | overflow: hidden; 292 | .mySlides { 293 | width: 400px; 294 | height: 240px; 295 | margin: 0 auto; 296 | 297 | 298 | } 299 | } 300 | 301 | .mySlides { 302 | width: 100%; 303 | height: 100%; 304 | display: block; 305 | margin-top: 20px; 306 | position: absolute; 307 | top: 0px; 308 | transition: transform 1s; 309 | 310 | img { 311 | // vertical-align: middle; 312 | width: 240px; 313 | height: 240px; 314 | border-radius: 50%; 315 | cursor: pointer; 316 | } 317 | } 318 | /* Next & previous buttons */ 319 | .prev, 320 | .next { 321 | cursor: pointer; 322 | position: absolute; 323 | top: 33%; 324 | width: auto; 325 | padding: 16px; 326 | margin-top: -22px; 327 | color: grey; 328 | font-weight: bold; 329 | font-size: 22px; 330 | transition: 0.6s ease; 331 | border-radius: 0 3px 3px 0; 332 | user-select: none; 333 | text-decoration: none; 334 | } 335 | 336 | /* Position the "next button" to the right */ 337 | .next { 338 | right: 10px; 339 | border-radius: 3px 0 0 3px; 340 | } 341 | .prev { 342 | left: 10px; 343 | border-radius: 3px 0 0 3px; 344 | } 345 | 346 | /* On hover, add a black background color with a little bit see-through */ 347 | .prev:hover, 348 | .next:hover { 349 | background-color: rgba(41, 129, 151, 0.8); 350 | } 351 | 352 | a.next:hover { 353 | color: white; 354 | } 355 | a.prev:hover { 356 | color: white; 357 | } 358 | /* Caption text */ 359 | .text { 360 | color: grey; 361 | font-size: 15px; 362 | padding: 8px 12px; 363 | position: absolute; 364 | bottom: 8px; 365 | width: 100%; 366 | text-align: center; 367 | } 368 | 369 | /* Number text (1/3 etc) */ 370 | .numbertext { 371 | color: grey; 372 | font-size: 12px; 373 | padding: 12px 16px; 374 | position: absolute; 375 | display: block; 376 | top: 0px; 377 | } 378 | .dotBox { 379 | position: absolute; 380 | bottom: 10px; 381 | left: 10px; 382 | right: 10px; 383 | 384 | .active, 385 | .dot:hover { 386 | background-color: #717171; 387 | } 388 | } 389 | .dot { 390 | cursor: pointer; 391 | height: 15px; 392 | width: 15px; 393 | margin: 0 2px; 394 | background-color: #bbb; 395 | border-radius: 50%; 396 | display: inline-block; 397 | transition: background-color 0.6s ease; 398 | transition: all 0.3s; 399 | } 400 | .selectDot { 401 | background-color: #13b8ff !important; 402 | width: 20px; 403 | height: 20px; 404 | // transition: all 0.6s; 405 | 406 | } 407 | 408 | /* 409 | ============================================= 410 | ******Overlay Related Scss******** 411 | ============================================ 412 | */ 413 | .overlay_div { 414 | position: fixed; 415 | left: 0; 416 | top: 0; 417 | width: 100%; 418 | height: 100%; 419 | background-color: black; 420 | z-index: 100; 421 | transition: all 0.7s; 422 | opacity: 0.5; 423 | visibility: visible; 424 | } 425 | .overlay_hidden { 426 | opacity: 0; 427 | visibility: hidden; 428 | } 429 | img { 430 | transition: all 1s; 431 | } 432 | 433 | i.fa.fa-check.icon_check{ 434 | position: absolute; 435 | font-weight: lighter; 436 | font-weight: 50; 437 | top: 174px; 438 | left: 64%; 439 | font-size: 40px; 440 | color: white; 441 | border-radius: 50%; 442 | width: 50px; 443 | height: 50px; 444 | display: flex; 445 | align-items: center; 446 | justify-content: center; 447 | background-color: #00a6ff; 448 | } 449 | i.fa.fa-check.icon_check.hidden1{ 450 | display: none; 451 | } 452 | /* 453 | 454 | ============================================= 455 | ******Dark MODE OF modal Scss******** 456 | ============================================ 457 | */ 458 | .dark-mode { 459 | .darkModal { 460 | background-color: #d9e4f5; 461 | background-image: linear-gradient(315deg, #d9e4f5 0%, #f5e3e6 74%); 462 | } 463 | .darkClose { 464 | background-color: #d7a385b3; 465 | } 466 | } 467 | @media (max-height: 768px) { 468 | body { 469 | .main-div { 470 | min-height: 55vh; 471 | } 472 | } 473 | } 474 | @media (max-width: 768px) { 475 | body { 476 | .main-div { 477 | width: 95%; 478 | padding: 5% 5% 7% 5%; 479 | } 480 | .heading { 481 | h1 { 482 | font-size: 3rem; 483 | } 484 | } 485 | .main-div { 486 | form { 487 | .form-group { 488 | display: flex; 489 | flex-direction: column; 490 | justify-content: start; 491 | } 492 | #username{ 493 | padding: 2.5px; 494 | } 495 | input { 496 | width: 100%; 497 | margin: 0; 498 | padding: 0.5rem 1rem; 499 | } 500 | select { 501 | padding: auto 1rem; 502 | width: 100%; 503 | } 504 | select:focus { 505 | width: 85%; 506 | } 507 | } 508 | } 509 | } 510 | } 511 | 512 | @media (max-width: 576px) { 513 | body { 514 | .heading { 515 | h1 { 516 | font-size: 2.75rem; 517 | } 518 | iframe { 519 | width: 15%; 520 | } 521 | } 522 | .profile { 523 | width: 84px; 524 | height: 84px; 525 | img { 526 | width: 80px; 527 | height: 80px; 528 | } 529 | } 530 | } 531 | .modal_div { 532 | width: 280px; 533 | height: 280px; 534 | p.btn--close-modal { 535 | font-size: 2rem; 536 | } 537 | } 538 | .modal_box { 539 | width: 280px; 540 | height: 250px; 541 | } 542 | .mySlides { 543 | img { 544 | width: 160px; 545 | height: 160px; 546 | } 547 | } 548 | .prev, 549 | .next, 550 | .text { 551 | font-size: 14px; 552 | } 553 | .prev { 554 | left: 5px; 555 | 556 | } 557 | .next { 558 | right: 5px; 559 | 560 | } 561 | .selectDot { 562 | background-color: #13b8ff !important; 563 | width: 15px; 564 | height: 15px; 565 | // transition: all 0.6s; 566 | 567 | } 568 | 569 | .dot { 570 | width: 10px; 571 | height: 10px; 572 | } 573 | .slideshow-container { 574 | .mySlides { 575 | width: 280px; 576 | height: 240px; 577 | } 578 | height: 240px !important; 579 | } 580 | i.fa.fa-check.icon_check{ 581 | top: 118px; 582 | font-size: 22px; 583 | width: 35px; 584 | height: 35px; 585 | } 586 | 587 | 588 | } 589 | 590 | @media (max-width: 800px) { 591 | } 592 | .hidden { 593 | opacity: 0; 594 | visibility: hidden; 595 | } 596 | 597 | 598 | //avatar form scss 599 | #addAvatar { 600 | text-align: center; 601 | margin: 20px 0; 602 | h5{ 603 | font-weight: 500; 604 | color: #000000; 605 | } 606 | #fileInp { 607 | margin: 20px auto; 608 | position: relative; 609 | display: block; 610 | background: #000000; 611 | color: #5bc0de; 612 | border-radius: 8px; 613 | } 614 | 615 | #upload{ 616 | display: block; 617 | margin: 20px auto; 618 | width: 80px; 619 | height: max-content; 620 | padding: 8px 16px; 621 | font-size: 16px; 622 | font-weight: 500; 623 | border: none; 624 | outline: none; 625 | color: black; 626 | background: #5bc0de; 627 | border-radius: 8px; 628 | cursor: pointer; 629 | } 630 | } 631 | -------------------------------------------------------------------------------- /public/scss/main.scss: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.googleapis.com/css?family=Roboto&display=swap"); 2 | @import url("https://fonts.googleapis.com/css2?family=Gluten:wght@500&display=swap"); 3 | 4 | $dark-color-a: #00adb5; 5 | $dark-color-b: #393e46; 6 | $light-color: #eeeeee; 7 | $light-color-b: #eeeeeed0; 8 | $success-color: #222831; 9 | $error-color: #d9534f; 10 | $transitionchange: all 1s ease 0s; 11 | 12 | * { 13 | box-sizing: border-box; 14 | margin: 0; 15 | padding: 0; 16 | } 17 | 18 | body { 19 | font-family: "Roboto", sans-serif; 20 | font-size: 16px; 21 | // background-color: #FFDEE9; 22 | // background-image: linear-gradient(0deg, #FFDEE9 0%, #B5FFFC 100%); 23 | background-image: linear-gradient(90deg, rgb(0, 40, 70), rgb(255, 115, 115), rgb(255, 175, 123)); 24 | background-position: center; 25 | background-repeat: no-repeat; 26 | background-size: cover; 27 | height: 100vh; 28 | overflow: hidden; 29 | // background: $light-color; 30 | margin: 20px; 31 | } 32 | body * { 33 | transition: all 0.5s linear; 34 | } 35 | body::before { 36 | content: ""; 37 | position: absolute; 38 | inset: 0; 39 | background-image: linear-gradient(90deg, #01cafe 0%, #60ecbf 100%); 40 | opacity: 1; 41 | z-index: -1; 42 | transition: all 0.5s linear; 43 | } 44 | 45 | /* dark-mode toggle switch */ 46 | #toggle { 47 | position: absolute; 48 | width: 50px; 49 | height: 50px; 50 | top: 10px; 51 | right: 10px; 52 | cursor: pointer; 53 | } 54 | 55 | #toggle svg { 56 | aspect-ratio: 1; 57 | object-fit: contain; 58 | } 59 | 60 | #toggle .outer-star { 61 | transition: transform 600ms cubic-bezier(0.59, 0.02, 0, 1.26) 0s; 62 | } 63 | 64 | #toggle .inner-dot { 65 | transition: transform 600ms ease 0s; 66 | transform: matrix(1, 0, 0, 1.5, -3, 0); 67 | } 68 | 69 | #toggle.active .outer-star { 70 | transform: rotate(180deg); 71 | } 72 | 73 | #toggle.active .inner-dot { 74 | transform: matrix(1, 0, 0, 1, 0, 0); 75 | } 76 | 77 | ul { 78 | list-style: none; 79 | } 80 | 81 | a { 82 | text-decoration: none; 83 | } 84 | 85 | .btn { 86 | cursor: pointer; 87 | padding: 5px 15px; 88 | background: $light-color; 89 | color: $dark-color-a; 90 | border: 0; 91 | font-size: 17px; 92 | } 93 | 94 | /* Chat Page */ 95 | 96 | .chat-container { 97 | border-radius: 20px; 98 | max-width: 1100px; 99 | background: #fff; 100 | margin: 40px auto; 101 | overflow: hidden; 102 | opacity: 1; 103 | box-shadow: 10px 10px 58px 3px rgba(0, 0, 0, 0.75); 104 | border: 1px solid #393e46; 105 | } 106 | 107 | .chat-header { 108 | background: #00adb5; 109 | color: #fff; 110 | border-top-left-radius: 5px; 111 | border-top-right-radius: 5px; 112 | padding: 15px; 113 | display: flex; 114 | align-items: center; 115 | 116 | justify-content: space-between; 117 | .main-heading { 118 | font-family: "Gluten", cursive; 119 | } 120 | } 121 | 122 | .chat-main { 123 | display: grid; 124 | min-height: 60vh; 125 | // margin-bottom: 5vh; 126 | grid-template-columns: 1fr 3fr; 127 | } 128 | 129 | .chat-sidebar { 130 | background: $dark-color-b; 131 | color: #fff; 132 | padding: 20px 20px 60px; 133 | overflow-y: scroll; 134 | min-height: 60vh; 135 | } 136 | 137 | .chat-sidebar h2 { 138 | font-size: 20px; 139 | padding: 10px; 140 | } 141 | .room-name-container { 142 | height: 45px; 143 | margin-bottom: 25px; 144 | background: rgba(0, 0, 0, 0.1); 145 | } 146 | .chat-sidebar h3 { 147 | margin-bottom: 15px; 148 | } 149 | 150 | .chat-sidebar ul li { 151 | padding: 5px 0px; 152 | display: flex; 153 | align-items: center; 154 | justify-content: space-between; 155 | } 156 | 157 | .chat-main, 158 | .chat-messages, 159 | .chat-sidebar { 160 | max-height: 64vh; 161 | } 162 | .chat-messages { 163 | padding: 30px; 164 | max-height: 64vh; 165 | overflow-y: scroll; 166 | display: flex; 167 | flex-direction: column; 168 | } 169 | 170 | .chat-messages .message { 171 | position: relative; 172 | box-sizing: border-box; 173 | padding: 0.5rem 1rem; 174 | margin: 1rem auto 1rem 1rem; 175 | color: black; 176 | background: #e5e5ea; 177 | border-radius: 1.125rem 1.125rem 1.125rem 0; 178 | animation: scale-up-tl 700ms; 179 | } 180 | 181 | .chat-messages .author { 182 | position: relative; 183 | margin: 1rem 1rem 1rem auto; 184 | border-radius: 1.125rem 1.125rem 0 1.125rem; 185 | color: white; 186 | background: #0b93f6; 187 | box-sizing: border-box; 188 | padding: 0.5rem 1rem; 189 | animation: scale-up-br 700ms; 190 | } 191 | 192 | .message.bot { 193 | position: relative; 194 | margin: 1rem auto 1rem auto; 195 | padding: 10px 10px 15px; 196 | color: white; 197 | background: #948e8e; 198 | border-radius: 5px; 199 | opacity: 0.8; 200 | box-shadow: $light-color-b 5px 5px; 201 | width: 75%; 202 | height: 11%; 203 | text-align: center; 204 | vertical-align: middle; 205 | animation: fadeDown 700ms ease-out 0s 1 normal none; 206 | } 207 | .message.bot p { 208 | max-width: none !important; 209 | } 210 | .three-dots-menu { 211 | position: relative; 212 | float: right; 213 | margin-bottom: -2px; 214 | transform: rotate(90deg); 215 | cursor: pointer; 216 | } 217 | .chat-messages .author:hover .btn-danger { 218 | opacity: 1; 219 | } 220 | .chat-messages .message:hover .btn-danger { 221 | opacity: 1; 222 | } 223 | 224 | .chat-messages .message .meta { 225 | display: inline-block; 226 | font-size: 15px; 227 | font-weight: bold; 228 | color: $dark-color-b; 229 | opacity: 0.7; 230 | margin-bottom: 7px; 231 | } 232 | .chat-messages .message .replied-msg-container { 233 | background-color: #a9a5a5 !important; 234 | color: white !important; 235 | } 236 | .chat-messages .message .replied-msg-container .meta { 237 | color: white; 238 | } 239 | .chat-messages .message .replied-msg-container .meta span{ 240 | color: white; 241 | } 242 | .chat-messages .message .meta span { 243 | color: #777; 244 | padding-left: 0.6em; 245 | } 246 | .chat-messages .message p { 247 | max-width: 300px; 248 | word-break: break-all; 249 | } 250 | .chat-messages .author .meta { 251 | display: inline-block; 252 | font-size: 15px; 253 | font-weight: bold; 254 | color: $light-color; 255 | opacity: 0.7; 256 | margin-bottom: 7px; 257 | } 258 | .chat-messages .author p { 259 | max-width: 300px; 260 | word-break: break-all; 261 | } 262 | .chat-messages .author .meta span { 263 | color: $light-color-b; 264 | padding-left: 0.6em; 265 | opacity: 1; 266 | } 267 | .chat-messages .author .text img { 268 | width: 100px; 269 | } 270 | .chat-messages .message .text img { 271 | width: 100px; 272 | } 273 | .message.bot .meta { 274 | font-size: 15px; 275 | font-weight: bold; 276 | color: black; 277 | margin-bottom: 7px; 278 | display: none; 279 | } 280 | 281 | .message.bot .meta span { 282 | color: rgb(82, 80, 80); 283 | padding-left: 0.6em; 284 | } 285 | 286 | .chat-form-container { 287 | padding: 20px 30px; 288 | background: #00adb5; 289 | } 290 | 291 | .editing-form-container { 292 | position: relative; 293 | } 294 | .editing-form-container::before { 295 | position: absolute; 296 | content: "Editing a message"; 297 | top: -20px; 298 | left: 65px; 299 | padding: 0.5rem; 300 | background: navajowhite; 301 | font-weight: 800; 302 | border-radius: 10px; 303 | box-shadow: 1px 1px 5px black; 304 | } 305 | .replying-form-container { 306 | position: relative; 307 | } 308 | .replying-form-container::before { 309 | position: absolute; 310 | content: attr(to); 311 | top: -20px; 312 | left: 65px; 313 | padding: 0.5rem; 314 | background: navajowhite; 315 | font-weight: 800; 316 | border-radius: 10px; 317 | box-shadow: 1px 1px 5px black; 318 | } 319 | .replying-close-btn { 320 | position: absolute; 321 | top: -15px; 322 | color: navajowhite; 323 | cursor: pointer; 324 | } 325 | .chat-form-container form { 326 | display: flex; 327 | } 328 | 329 | .chat-form-container input[type="text"] { 330 | position: relative; 331 | font-size: 16px; 332 | padding: 5px 15px; 333 | height: 50px; 334 | flex: 1; 335 | } 336 | 337 | .message_input { 338 | overflow: hidden; 339 | padding: 15px; 340 | // border: solid blue 1px; 341 | border: none; 342 | border-radius: 1.5em; 343 | box-shadow: 0 3px 4px rgb(41, 39, 39); 344 | margin-top: 2.5px; 345 | outline: none; 346 | } 347 | #image-input { 348 | display: none; 349 | } 350 | .message_send_btn { 351 | background: rgba(0, 255, 149, 0.349); 352 | } 353 | 354 | /* Join Page */ 355 | .join-container { 356 | max-width: 500px; 357 | margin: 80px auto; 358 | color: #fff; 359 | transition: $transitionchange; 360 | } 361 | 362 | .join-header { 363 | text-align: center; 364 | padding: 20px; 365 | background: $dark-color-a; 366 | border-top-left-radius: 5px; 367 | border-top-right-radius: 5px; 368 | } 369 | 370 | .join-main { 371 | padding: 30px 40px; 372 | background: $dark-color-b; 373 | } 374 | 375 | .join-main p { 376 | margin-bottom: 20px; 377 | } 378 | 379 | .join-main .form-control { 380 | margin-bottom: 20px; 381 | } 382 | 383 | .join-main label { 384 | display: block; 385 | margin-bottom: 5px; 386 | } 387 | 388 | .join-main input[type="text"] { 389 | font-size: 16px; 390 | padding: 5px; 391 | height: 40px; 392 | width: 100%; 393 | } 394 | 395 | .join-main select { 396 | font-size: 16px; 397 | padding: 5px; 398 | height: 40px; 399 | width: 100%; 400 | } 401 | 402 | .join-main .btn { 403 | margin-top: 20px; 404 | width: 100%; 405 | } 406 | .dark-mode { 407 | background-image: linear-gradient(90deg, rgb(0, 40, 70), rgb(255, 115, 115), rgb(255, 175, 123)); 408 | .chat-header { 409 | background: rgb(0, 40, 70); 410 | transition: $transitionchange; 411 | } 412 | .chat-sidebar { 413 | background: rgb(255, 115, 115); 414 | transition: $transitionchange; 415 | } 416 | .chat-form-container { 417 | background: rgb(0, 40, 70); 418 | transition: $transitionchange; 419 | } 420 | .btn { 421 | color: rgb(0, 40, 70); 422 | transition: $transitionchange; 423 | } 424 | .chat-main { 425 | background: rgba(0, 0, 0, 0.849); 426 | transition: $transitionchange; 427 | } 428 | .message_send_btn, .image-add-btn { 429 | background: rgb(119, 0, 255); 430 | } 431 | .btn-danger, .btn-danger2 { 432 | background-color: #272727 !important; 433 | color: white !important; 434 | } 435 | .btn-danger span { 436 | color: white; 437 | } 438 | .btn-danger-reply:hover { 439 | background-color: #6c6c6c !important; 440 | } 441 | .btn-danger2:hover { 442 | background-color: #6c6c6c !important; 443 | } 444 | .btn-container { 445 | background-color: #272727; 446 | border: 1px solid white; 447 | } 448 | .hamburger-icon { 449 | color: #ffffff; 450 | } 451 | .hamburger .hamburger-inner{ 452 | background: #ffffff; 453 | } 454 | .hamburger .hamburger-inner::after{ 455 | background: #ffffff; 456 | } 457 | .hamburger .hamburger-inner::before{ 458 | background: #ffffff; 459 | } 460 | .hamburger--spin.is-active .hamburger-inner{ 461 | background: #ffffff; 462 | } 463 | .hamburger--spin.is-active .hamburger-inner::after{ 464 | background: #ffffff; 465 | } 466 | .hamburger--spin.is-active .hamburger-inner::before{ 467 | background: #ffffff; 468 | } 469 | ::-webkit-scrollbar-thumb { 470 | background: white; 471 | border-radius: 10px; 472 | } 473 | } 474 | .dark-mode::before { 475 | opacity: 0; 476 | } 477 | .btn-container { 478 | position: absolute; 479 | right: 6px; 480 | bottom: -85px; 481 | z-index: 5; 482 | display: flex; 483 | flex-direction: column; 484 | background-color: white; 485 | border-radius: 10px; 486 | border: 1px solid #393e46; 487 | transition: transform 125ms ease-in; 488 | } 489 | .hide { 490 | transform: scale(0); 491 | } 492 | .btn-danger { 493 | position: absolute; 494 | top: 50%; 495 | left: 70%; 496 | transform: translate(-50%, -50%); 497 | padding: 0.5rem; 498 | outline: none; 499 | border: none; 500 | border-radius: 0.5rem; 501 | color: #ffffff; 502 | background-color: white; 503 | opacity: 0; 504 | } 505 | .msg-head { 506 | display: flex; 507 | justify-content: space-between; 508 | } 509 | .btn-danger2 { 510 | padding: 0.5rem; 511 | outline: none; 512 | border: none; 513 | border-radius: 10px; 514 | background-color: white; 515 | } 516 | .btn-danger2:hover { 517 | background-color: #cacaca; 518 | } 519 | .btn-danger span { 520 | color: black; 521 | } 522 | .btn-danger-edit { 523 | left: 30%; 524 | } 525 | 526 | .author .btn-danger-reply { 527 | left: -25px; 528 | background: none; 529 | color: black; 530 | } 531 | .author .btn-danger-reply:hover { 532 | background-color: #00000080; 533 | color: white; 534 | } 535 | .extra { 536 | display: none; 537 | } 538 | .message .btn-danger-reply { 539 | left: calc(100% + 25px); 540 | background: none !important; 541 | color: black; 542 | } 543 | .message .btn-danger-reply:hover { 544 | background-color: #00000080 !important; 545 | color: white; 546 | } 547 | 548 | .btn-danger:hover { 549 | background: #a20900; 550 | } 551 | 552 | .replied-msg-container { 553 | background-color: #a8cce7; 554 | // opacity: 0.3; 555 | padding: 0.5rem; 556 | margin: 10px -2px; 557 | border-radius: 10px; 558 | } 559 | 560 | #beep1, 561 | #beep2 { 562 | display: none; 563 | } 564 | 565 | .dot-animation { 566 | position: relative; 567 | margin-right: 0.5rem; 568 | } 569 | .dot-animation::after { 570 | position: absolute; 571 | content: ""; 572 | animation: dotdot 1s infinite; 573 | } 574 | .edited-msg { 575 | position: relative; 576 | margin-right: 0.5rem; 577 | } 578 | .edited-msg::after { 579 | content: "(edited)"; 580 | font-size: 0.75rem; 581 | font-family: monospace; 582 | font-weight: 300; 583 | opacity: 0.75; 584 | } 585 | .hamburger-icon { 586 | display: none !important; 587 | } 588 | .hamburger { 589 | display: none !important; 590 | } 591 | @keyframes dotdot { 592 | 0% { 593 | content: "."; 594 | } 595 | 50% { 596 | content: ".."; 597 | } 598 | 100% { 599 | content: "..."; 600 | } 601 | } 602 | @media (max-width: 1200px) { 603 | .chat-container { 604 | position: relative; 605 | margin: 60px auto; 606 | } 607 | } 608 | @media (max-width: 700px) { 609 | .chat-main { 610 | display: block; 611 | max-height: 60vh; 612 | } 613 | .chat-messages { 614 | height: 60vh; 615 | } 616 | .chat-sidebar { 617 | position: absolute; 618 | z-index: 10; 619 | transform: translateX(-100%); 620 | } 621 | .sidemenu-open { 622 | transform: translateX(0); 623 | } 624 | .hamburger-icon { 625 | display: block !important; 626 | position: absolute; 627 | top: 15px; 628 | left: 25px; 629 | transform: scale(1.5); 630 | } 631 | .hamburger { 632 | display: inline-block !important; 633 | } 634 | .top-nav { 635 | display: flex; 636 | flex-direction: row; 637 | justify-content: space-between; 638 | } 639 | } 640 | /* ---------------------------------------------- 641 | * Generated by Animista on 2021-9-30 12:47:32 642 | * Licensed under FreeBSD License. 643 | * See http://animista.net/license for more info. 644 | * w: http://animista.net, t: @cssanimista 645 | * ---------------------------------------------- */ 646 | 647 | /** 648 | * ---------------------------------------- 649 | * animation bounce-in-bottom 650 | * ---------------------------------------- 651 | */ 652 | /* ---------------------------------------------- 653 | * Generated by Animista on 2021-9-30 12:51:35 654 | * Licensed under FreeBSD License. 655 | * See http://animista.net/license for more info. 656 | * w: http://animista.net, t: @cssanimista 657 | * ---------------------------------------------- */ 658 | 659 | /** 660 | * ---------------------------------------- 661 | * animation swing-in-left-bck 662 | * ---------------------------------------- 663 | */ 664 | /* ---------------------------------------------- 665 | * Generated by Animista on 2021-10-16 10:42:35 666 | * Licensed under FreeBSD License. 667 | * See http://animista.net/license for more info. 668 | * w: http://animista.net, t: @cssanimista 669 | * ---------------------------------------------- */ 670 | 671 | /** 672 | * ---------------------------------------- 673 | * animation scale-up-br 674 | * ---------------------------------------- 675 | */ 676 | /* ---------------------------------------------- 677 | * Generated by Animista on 2021-10-16 10:46:11 678 | * Licensed under FreeBSD License. 679 | * See http://animista.net/license for more info. 680 | * w: http://animista.net, t: @cssanimista 681 | * ---------------------------------------------- */ 682 | 683 | /** 684 | * ---------------------------------------- 685 | * animation scale-up-tl 686 | * ---------------------------------------- 687 | */ 688 | @-webkit-keyframes scale-up-tl { 689 | 0% { 690 | -webkit-transform: scale(0.5); 691 | transform: scale(0.5); 692 | -webkit-transform-origin: 0% 0%; 693 | transform-origin: 0% 0%; 694 | } 695 | 100% { 696 | -webkit-transform: scale(1); 697 | transform: scale(1); 698 | -webkit-transform-origin: 0% 0%; 699 | transform-origin: 0% 0%; 700 | } 701 | } 702 | @keyframes scale-up-tl { 703 | 0% { 704 | -webkit-transform: scale(0.5); 705 | transform: scale(0.5); 706 | -webkit-transform-origin: 0% 0%; 707 | transform-origin: 0% 0%; 708 | } 709 | 100% { 710 | -webkit-transform: scale(1); 711 | transform: scale(1); 712 | -webkit-transform-origin: 0% 0%; 713 | transform-origin: 0% 0%; 714 | } 715 | } 716 | 717 | @-webkit-keyframes scale-up-br { 718 | 0% { 719 | -webkit-transform: scale(0.5); 720 | transform: scale(0.5); 721 | -webkit-transform-origin: 100% 100%; 722 | transform-origin: 100% 100%; 723 | } 724 | 100% { 725 | -webkit-transform: scale(1); 726 | transform: scale(1); 727 | -webkit-transform-origin: 100% 100%; 728 | transform-origin: 100% 100%; 729 | } 730 | } 731 | @keyframes scale-up-br { 732 | 0% { 733 | -webkit-transform: scale(0.5); 734 | transform: scale(0.5); 735 | -webkit-transform-origin: 100% 100%; 736 | transform-origin: 100% 100%; 737 | } 738 | 100% { 739 | -webkit-transform: scale(1); 740 | transform: scale(1); 741 | -webkit-transform-origin: 100% 100%; 742 | transform-origin: 100% 100%; 743 | } 744 | } 745 | 746 | @-webkit-keyframes swing-in-left-bck { 747 | 0% { 748 | -webkit-transform: rotateY(-70deg); 749 | transform: rotateY(-70deg); 750 | -webkit-transform-origin: left; 751 | transform-origin: left; 752 | opacity: 0; 753 | } 754 | 100% { 755 | -webkit-transform: rotateY(0); 756 | transform: rotateY(0); 757 | -webkit-transform-origin: left; 758 | transform-origin: left; 759 | opacity: 1; 760 | } 761 | } 762 | ::-webkit-scrollbar { 763 | width: 15px; 764 | } 765 | ::-webkit-scrollbar-track { 766 | box-shadow: inset 0 0 5px grey; 767 | border-radius: 10px; 768 | } 769 | 770 | /* Handle */ 771 | ::-webkit-scrollbar-thumb { 772 | background: #00adb5; 773 | border-radius: 10px; 774 | } 775 | 776 | /* Handle on hover */ 777 | ::-webkit-scrollbar-thumb:hover { 778 | background: #bbbbbb; 779 | } 780 | ::-webkit-scrollbar-button:single-button { 781 | background-color: #bbbbbb; 782 | display: block; 783 | border-style: solid; 784 | height: 13px; 785 | width: 16px; 786 | } 787 | /* Up */ 788 | ::-webkit-scrollbar-button:single-button:vertical:decrement { 789 | border-width: 0 8px 8px 8px; 790 | border-color: transparent transparent #555555 transparent; 791 | } 792 | 793 | ::-webkit-scrollbar-button:single-button:vertical:decrement:hover { 794 | border-color: transparent transparent #777777 transparent; 795 | } 796 | /* Down */ 797 | ::-webkit-scrollbar-button:single-button:vertical:increment { 798 | border-width: 8px 8px 0 8px; 799 | border-color: #555555 transparent transparent transparent; 800 | } 801 | 802 | ::-webkit-scrollbar-button:vertical:single-button:increment:hover { 803 | border-color: #777777 transparent transparent transparent; 804 | } 805 | @keyframes swing-in-left-bck { 806 | 0% { 807 | -webkit-transform: rotateY(-70deg); 808 | transform: rotateY(-70deg); 809 | -webkit-transform-origin: left; 810 | transform-origin: left; 811 | opacity: 0; 812 | } 813 | 100% { 814 | -webkit-transform: rotateY(0); 815 | transform: rotateY(0); 816 | -webkit-transform-origin: left; 817 | transform-origin: left; 818 | opacity: 1; 819 | } 820 | } 821 | 822 | .animate { 823 | animation: shimmer 15s infinite linear; 824 | background: linear-gradient(to right, rgba(0, 0, 0, 0.05) 4%, rgba(0, 0, 0, 0.01) 35%, rgba(0, 0, 0, 0.1) 55%); 825 | background-size: 1000px 100%; 826 | } 827 | 828 | .fade-in { 829 | animation: fadeIn linear 1s; 830 | -webkit-animation: fadeIn linear 1s; 831 | -moz-animation: fadeIn linear 1s; 832 | -o-animation: fadeIn linear 1s; 833 | -ms-animation: fadeIn linear 1s; 834 | } 835 | 836 | /* 837 | ============================================== 838 | *********User List avtar related css******** 839 | ============================================== 840 | */ 841 | .users { 842 | li { 843 | display: flex; 844 | align-items: flex-end; 845 | justify-content: center; 846 | } 847 | } 848 | .userAvatar { 849 | width: 35px; 850 | height: 35px; 851 | border-radius: 50%; 852 | box-shadow: rgba(0, 0, 0, 0.16) 0px 3px 6px, rgba(0, 0, 0, 0.23) 0px 3px 6px; 853 | } 854 | .userAvatar1 { 855 | width: 55px; 856 | height: 55px; 857 | border-radius: 50%; 858 | margin-bottom: 15px; 859 | box-shadow: rgba(0, 0, 0, 0.16) 0px 3px 6px, rgba(0, 0, 0, 0.23) 0px 3px 6px; 860 | } 861 | .profileAdded{ 862 | display: flex; 863 | align-items: center; 864 | justify-content: center; 865 | img{ 866 | margin: 0 5px; 867 | width: 40px; 868 | height: 40px; 869 | box-shadow: rgba(0, 0, 0, 0.16) 0px 3px 6px, rgba(0, 0, 0, 0.23) 0px 3px 6px; 870 | } 871 | } 872 | 873 | /* 874 | ============================================== 875 | *********Message related profiles******** 876 | ============================================== 877 | */ 878 | .profileLeft{ 879 | display: flex; 880 | // flex-direction: row-reverse; 881 | align-items: flex-end; 882 | } 883 | .profileRight{ 884 | display: flex; 885 | flex-direction: row-reverse; 886 | align-items: flex-end; 887 | } 888 | 889 | @keyframes shimmer { 890 | 0% { 891 | background-position: -1000px 0; 892 | } 893 | 100% { 894 | background-position: 1000px 0; 895 | } 896 | } 897 | 898 | @keyframes fadeIn { 899 | 0% { 900 | opacity: 0; 901 | } 902 | 100% { 903 | opacity: 1; 904 | } 905 | } 906 | 907 | @-moz-keyframes fadeIn { 908 | 0% { 909 | opacity: 0; 910 | } 911 | 100% { 912 | opacity: 1; 913 | } 914 | } 915 | 916 | @-webkit-keyframes fadeIn { 917 | 0% { 918 | opacity: 0; 919 | } 920 | 100% { 921 | opacity: 1; 922 | } 923 | } 924 | 925 | @-o-keyframes fadeIn { 926 | 0% { 927 | opacity: 0; 928 | } 929 | 100% { 930 | opacity: 1; 931 | } 932 | } 933 | 934 | @-ms-keyframes fadeIn { 935 | 0% { 936 | opacity: 0; 937 | } 938 | 100% { 939 | opacity: 1; 940 | } 941 | } 942 | 943 | .fade-out { 944 | animation: fadeOut ease 1.5s; 945 | -webkit-animation: fadeOut ease 1.5s; 946 | -moz-animation: fadeOut ease 1.5s; 947 | -o-animation: fadeOut ease 1.5s; 948 | -ms-animation: fadeOut ease 1.5s; 949 | } 950 | 951 | @keyframes fadeOut { 952 | 0% { 953 | opacity: 1; 954 | } 955 | 100% { 956 | opacity: 0; 957 | } 958 | } 959 | 960 | @-moz-keyframes fadeOut { 961 | 0% { 962 | opacity: 1; 963 | } 964 | 100% { 965 | opacity: 0; 966 | } 967 | } 968 | 969 | @-webkit-keyframes fadeOut { 970 | 0% { 971 | opacity: 1; 972 | } 973 | 100% { 974 | opacity: 0; 975 | } 976 | } 977 | 978 | @-o-keyframes fadeOut { 979 | 0% { 980 | opacity: 1; 981 | } 982 | 100% { 983 | opacity: 0; 984 | } 985 | } 986 | 987 | @-ms-keyframes fadeOut { 988 | 0% { 989 | opacity: 1; 990 | } 991 | 100% { 992 | opacity: 0; 993 | } 994 | } 995 | @-webkit-keyframes fadeDown { 996 | 0% { 997 | opacity: 0; 998 | -webkit-transform: translateY(-15px); 999 | } 1000 | 100% { 1001 | opacity: 0.8; 1002 | -webkit-transform: translateY(0); 1003 | } 1004 | } 1005 | 1006 | @keyframes fadeDown { 1007 | 0% { 1008 | opacity: 0; 1009 | transform: translateY(-15px); 1010 | } 1011 | 100% { 1012 | opacity: 0.8; 1013 | transform: translateY(0); 1014 | } 1015 | } 1016 | 1017 | .hamburger { 1018 | position: absolute; 1019 | top: 0; 1020 | left: 10px; 1021 | padding: 15px 15px; 1022 | display: inline-block; 1023 | cursor: pointer; 1024 | transition-property: opacity, filter; 1025 | transition-duration: 0.15s; 1026 | transition-timing-function: linear; 1027 | font: inherit; 1028 | color: inherit; 1029 | text-transform: none; 1030 | background-color: transparent; 1031 | border: 0; 1032 | margin: 0; 1033 | overflow: visible; } 1034 | .hamburger:hover { 1035 | opacity: 0.7; } 1036 | .hamburger.is-active:hover { 1037 | opacity: 0.7; } 1038 | .hamburger.is-active .hamburger-inner, 1039 | .hamburger.is-active .hamburger-inner::before, 1040 | .hamburger.is-active .hamburger-inner::after { 1041 | background-color: #000; } 1042 | 1043 | .hamburger-box { 1044 | width: 40px; 1045 | height: 24px; 1046 | display: inline-block; 1047 | position: relative; } 1048 | 1049 | .hamburger-inner { 1050 | display: block; 1051 | top: 50%; 1052 | margin-top: -2px; } 1053 | .hamburger-inner, .hamburger-inner::before, .hamburger-inner::after { 1054 | width: 40px; 1055 | height: 4px; 1056 | background-color: #000; 1057 | border-radius: 4px; 1058 | position: absolute; 1059 | transition-property: transform; 1060 | transition-duration: 0.15s; 1061 | transition-timing-function: ease; } 1062 | .hamburger-inner::before, .hamburger-inner::after { 1063 | content: ""; 1064 | display: block; } 1065 | .hamburger-inner::before { 1066 | top: -10px; } 1067 | .hamburger-inner::after { 1068 | bottom: -10px; } 1069 | 1070 | .hamburger--spin .hamburger-inner { 1071 | transition-duration: 0.22s; 1072 | transition-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); } 1073 | .hamburger--spin .hamburger-inner::before { 1074 | transition: top 0.1s 0.25s ease-in, opacity 0.1s ease-in; } 1075 | .hamburger--spin .hamburger-inner::after { 1076 | transition: bottom 0.1s 0.25s ease-in, transform 0.22s cubic-bezier(0.55, 0.055, 0.675, 0.19); } 1077 | 1078 | .hamburger--spin.is-active .hamburger-inner { 1079 | transform: rotate(225deg); 1080 | transition-delay: 0.12s; 1081 | transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); } 1082 | .hamburger--spin.is-active .hamburger-inner::before { 1083 | top: 0; 1084 | opacity: 0; 1085 | transition: top 0.1s ease-out, opacity 0.1s 0.12s ease-out; } 1086 | .hamburger--spin.is-active .hamburger-inner::after { 1087 | bottom: 0; 1088 | transform: rotate(-90deg); 1089 | transition: bottom 0.1s ease-out, transform 0.22s 0.12s cubic-bezier(0.215, 0.61, 0.355, 1); } 1090 | -------------------------------------------------------------------------------- /public/sounds/beep1.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opencodeiiita/Geek-Chat/32861b069aaf927a65f7ea1fdae56e76d04beb93/public/sounds/beep1.mp3 -------------------------------------------------------------------------------- /public/sounds/beep2.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opencodeiiita/Geek-Chat/32861b069aaf927a65f7ea1fdae56e76d04beb93/public/sounds/beep2.wav -------------------------------------------------------------------------------- /public/sounds/beep3.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opencodeiiita/Geek-Chat/32861b069aaf927a65f7ea1fdae56e76d04beb93/public/sounds/beep3.mp3 -------------------------------------------------------------------------------- /public/uploads/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opencodeiiita/Geek-Chat/32861b069aaf927a65f7ea1fdae56e76d04beb93/public/uploads/.gitkeep -------------------------------------------------------------------------------- /routes/image.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const path = require('path'); 4 | const fs = require('fs'); 5 | 6 | const avatarsDirectory = path.join(__dirname, '../public/avtars'), 7 | uploadsDirectory = path.join(__dirname, '../public/uploads'); 8 | 9 | function getAvatarIndex() { 10 | return fs.readdirSync(avatarsDirectory).length + 1; 11 | } 12 | 13 | router.post('/image', (req, res) => { 14 | if (!req.files || !req.files.image) return res.json({ success: false }); 15 | 16 | const image = req.files.image; 17 | const pieces = image.name.split('.'); 18 | const filename = `${new Date().getTime()}.${pieces[pieces.length - 1]}`; 19 | 20 | image.mv(path.join(uploadsDirectory, filename)); 21 | return res.json({ success: true, link: `/uploads/${filename}` }); 22 | }); 23 | 24 | router.post('/newAvatar', (req, res) => { 25 | if (!req.files || !req.files.avatar) return res.status(400).send(null); 26 | 27 | const avatar = req.files.avatar; 28 | const pieces = avatar.name.split('.'); 29 | const filename = `${getAvatarIndex()}.${pieces[pieces.length - 1]}`; 30 | 31 | avatar.mv(path.join(avatarsDirectory, filename)); 32 | res.send(filename); 33 | }); 34 | 35 | module.exports = router; 36 | -------------------------------------------------------------------------------- /routes/index.js: -------------------------------------------------------------------------------- 1 | const express= require("express") 2 | const router = express.Router(); 3 | const path = require("path"); 4 | const { stringify } = require('querystring'); 5 | const fetch = require('node-fetch'); 6 | const { usersArr, currentUserData } = require("../utils/users"); 7 | 8 | router.get("/", (req, res) => { 9 | // rendering main.html 10 | res.sendFile(path.join(__dirname , "../views/index.html")); 11 | }); 12 | 13 | router.post("/", async(req, res) => { 14 | // RECAPTCHA SERVER SIDE 15 | if (!req.body['g-recaptcha-response']) 16 | return res.sendFile(path.join(__dirname , "../views/index.html")); 17 | // Secret key 18 | const secretKey = '6Lc20uYcAAAAANeXi5yv3q_YTMsN3J8NTHUcpmD5'; 19 | // Verify URL 20 | const query = stringify({ 21 | secret: secretKey, 22 | response: req.body['g-recaptcha-response'], 23 | remoteip: req.connection.remoteAddress 24 | }); 25 | const verifyURL = `https://google.com/recaptcha/api/siteverify?${query}`; 26 | // Make a request to verifyURL 27 | const body = await fetch(verifyURL).then(resp => resp.json()); 28 | // If not successful 29 | if (body.success !== undefined && !body.success) return res.sendFile(path.join(__dirname, " ../views/index.html")); 30 | // If successful 31 | // return res.json({ success: true, msg: 'Captcha passed' }); 32 | 33 | currentUserData.usrnm = req.body.usrnm; 34 | currentUserData.room = req.body.newroom; 35 | currentUserData.profilePhoto = req.body.imageUrl; 36 | 37 | let { usrnm, room, profilePhoto } = currentUserData; 38 | 39 | if ( 40 | usersArr.find((user) => { 41 | if (currentUserData.usrnm === user.name && currentUserData.room === user.room) return true; 42 | }) 43 | ) { 44 | console.log('here'); 45 | return res.sendFile(path.join(__dirname , "../views/index.html")); 46 | } 47 | if (/\s/g.test(usrnm)) { 48 | return res.sendFile(path.join(__dirname , "../views/index.html")); 49 | } 50 | res.sendFile(path.join(__dirname , "../views/main.html")); 51 | }); 52 | 53 | module.exports=router; -------------------------------------------------------------------------------- /utils/message.js: -------------------------------------------------------------------------------- 1 | const encode = require("html-entities")["encode"]; 2 | const marked = require("marked"); 3 | 4 | const Filter = require("bad-words"); 5 | 6 | const filter = new Filter({ placeHolder: "x" }); 7 | const profanityWarning = marked("**Message blocked**: profanity not allowed!"); 8 | 9 | function sanitizeAndRenderMessage(message, encodeMessage) { 10 | if (encodeMessage) 11 | message = encode(message); 12 | 13 | const fiterMessage = filter.clean(message); 14 | const markdown = marked(fiterMessage); 15 | const reducedString = markdown.replace( /(<([^>]+)>)/ig, ""); 16 | 17 | if (filter.isProfane(reducedString)) 18 | return profanityWarning; 19 | 20 | return markdown; 21 | } 22 | 23 | module.exports = { 24 | sanitizeAndRenderMessage 25 | }; 26 | -------------------------------------------------------------------------------- /utils/roomMembersCount.js: -------------------------------------------------------------------------------- 1 | const roomMembersCount = { 2 | "Web Development": 0, 3 | "App Development": 0, 4 | "FOSS": 0, 5 | "Design": 0, 6 | "Competitive Programming": 0, 7 | "Cyber Security": 0, 8 | "Artificial Intelligence": 0 9 | }; 10 | 11 | 12 | module.exports = { roomMembersCount }; 13 | -------------------------------------------------------------------------------- /utils/users.js: -------------------------------------------------------------------------------- 1 | const { CreateUser } = require('../models/user'); 2 | 3 | var usersArr = []; 4 | var currentUserData = { usrnm: null, room: null, profilePhoto: null }; 5 | 6 | function newUser(name, room, session_id, profilePhoto) { 7 | return usersArr.push(CreateUser(name, room, session_id, profilePhoto)); 8 | } 9 | 10 | module.exports = { usersArr, newUser, currentUserData }; 11 | -------------------------------------------------------------------------------- /views/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 13 | 18 | 19 | 20 | 25 | 26 | 27 | 28 | 29 |