├── Procfile ├── client ├── src │ ├── assets │ │ ├── meeting.png │ │ ├── online-interview.png │ │ ├── heart.png │ │ ├── home.png │ │ ├── home2.png │ │ ├── note.png │ │ ├── note1.png │ │ ├── note2.png │ │ ├── github.png │ │ ├── linkedin.png │ │ ├── homeVideo.mp4 │ │ ├── homeVideo1.mp4 │ │ ├── interview.png │ │ ├── video-call.png │ │ ├── styles │ │ │ └── _mixins.scss │ │ └── video-call.svg │ ├── common │ │ ├── spin.gif │ │ ├── spin1.gif │ │ ├── Spinner.js │ │ └── AntSwitch.js │ ├── constants.js │ ├── setupTests.js │ ├── App.test.js │ ├── index.css │ ├── reportWebVitals.js │ ├── index.js │ ├── Components │ │ ├── Messages │ │ │ ├── Message.js │ │ │ ├── Messages.css │ │ │ ├── Messages.scss │ │ │ └── Messages.js │ │ ├── Notes │ │ │ ├── Notes.scss │ │ │ ├── Notes.css │ │ │ └── Notes.js │ │ ├── Footer │ │ │ ├── Footer.css │ │ │ ├── Footer.scss │ │ │ └── Footer.js │ │ ├── Editor │ │ │ ├── Editor.css │ │ │ ├── Editor.scss │ │ │ └── Editor.js │ │ ├── Join │ │ │ ├── Join.css │ │ │ ├── Join.scss │ │ │ └── Join.js │ │ ├── Navbar │ │ │ ├── Navbar.js │ │ │ ├── Navbar.css │ │ │ └── Navbar.scss │ │ ├── Options │ │ │ ├── Options.css │ │ │ ├── Options.scss │ │ │ └── Options.js │ │ ├── Home │ │ │ ├── Home.js │ │ │ ├── Home.css │ │ │ └── Home.scss │ │ └── Meet │ │ │ ├── Meet.js │ │ │ ├── Meet.css │ │ │ └── Meet.scss │ ├── App.js │ ├── App.css │ ├── logo.svg │ └── SocketContext.js ├── public │ ├── robots.txt │ ├── home.png │ ├── favicon.ico │ ├── home2.png │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── index.html ├── .firebaserc ├── firebase.json ├── .gitignore ├── package.json └── .firebase │ └── hosting.YnVpbGQ.cache ├── .gitignore ├── package.json ├── .github └── workflows │ ├── Deployment.yml │ ├── main.yml │ ├── docker-publish.yml │ └── codeql-analysis.yml ├── README.md └── server.js /Procfile: -------------------------------------------------------------------------------- 1 | web: node server.js -------------------------------------------------------------------------------- /client/src/assets/meeting.png: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /client/src/assets/online-interview.png: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /client/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /client/.firebaserc: -------------------------------------------------------------------------------- 1 | { 2 | "projects": { 3 | "default": "alanbinu-video-conference" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /client/public/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlanBinu007/Live-Video-Chat-Application-for-Interview-purposes/HEAD/client/public/home.png -------------------------------------------------------------------------------- /client/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlanBinu007/Live-Video-Chat-Application-for-Interview-purposes/HEAD/client/public/favicon.ico -------------------------------------------------------------------------------- /client/public/home2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlanBinu007/Live-Video-Chat-Application-for-Interview-purposes/HEAD/client/public/home2.png -------------------------------------------------------------------------------- /client/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlanBinu007/Live-Video-Chat-Application-for-Interview-purposes/HEAD/client/public/logo192.png -------------------------------------------------------------------------------- /client/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlanBinu007/Live-Video-Chat-Application-for-Interview-purposes/HEAD/client/public/logo512.png -------------------------------------------------------------------------------- /client/src/assets/heart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlanBinu007/Live-Video-Chat-Application-for-Interview-purposes/HEAD/client/src/assets/heart.png -------------------------------------------------------------------------------- /client/src/assets/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlanBinu007/Live-Video-Chat-Application-for-Interview-purposes/HEAD/client/src/assets/home.png -------------------------------------------------------------------------------- /client/src/assets/home2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlanBinu007/Live-Video-Chat-Application-for-Interview-purposes/HEAD/client/src/assets/home2.png -------------------------------------------------------------------------------- /client/src/assets/note.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlanBinu007/Live-Video-Chat-Application-for-Interview-purposes/HEAD/client/src/assets/note.png -------------------------------------------------------------------------------- /client/src/assets/note1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlanBinu007/Live-Video-Chat-Application-for-Interview-purposes/HEAD/client/src/assets/note1.png -------------------------------------------------------------------------------- /client/src/assets/note2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlanBinu007/Live-Video-Chat-Application-for-Interview-purposes/HEAD/client/src/assets/note2.png -------------------------------------------------------------------------------- /client/src/common/spin.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlanBinu007/Live-Video-Chat-Application-for-Interview-purposes/HEAD/client/src/common/spin.gif -------------------------------------------------------------------------------- /client/src/common/spin1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlanBinu007/Live-Video-Chat-Application-for-Interview-purposes/HEAD/client/src/common/spin1.gif -------------------------------------------------------------------------------- /client/src/assets/github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlanBinu007/Live-Video-Chat-Application-for-Interview-purposes/HEAD/client/src/assets/github.png -------------------------------------------------------------------------------- /client/src/assets/linkedin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlanBinu007/Live-Video-Chat-Application-for-Interview-purposes/HEAD/client/src/assets/linkedin.png -------------------------------------------------------------------------------- /client/src/assets/homeVideo.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlanBinu007/Live-Video-Chat-Application-for-Interview-purposes/HEAD/client/src/assets/homeVideo.mp4 -------------------------------------------------------------------------------- /client/src/assets/homeVideo1.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlanBinu007/Live-Video-Chat-Application-for-Interview-purposes/HEAD/client/src/assets/homeVideo1.mp4 -------------------------------------------------------------------------------- /client/src/assets/interview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlanBinu007/Live-Video-Chat-Application-for-Interview-purposes/HEAD/client/src/assets/interview.png -------------------------------------------------------------------------------- /client/src/assets/video-call.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlanBinu007/Live-Video-Chat-Application-for-Interview-purposes/HEAD/client/src/assets/video-call.png -------------------------------------------------------------------------------- /client/src/constants.js: -------------------------------------------------------------------------------- 1 | export const APP_NAME = 'Merge'; 2 | export const APP_URL = 'https://alanbinu-video-conference.web.app'; 3 | export const BACKEND_URL = 'https://video-chat-meet-backend.herokuapp.com'; 4 | // export const BACKEND_URL='http://localhost:5000'; -------------------------------------------------------------------------------- /client/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /client/src/App.test.js: -------------------------------------------------------------------------------- 1 | import { render, screen } from '@testing-library/react'; 2 | import App from './App'; 3 | 4 | test('renders learn react link', () => { 5 | render(); 6 | const linkElement = screen.getByText(/learn react/i); 7 | expect(linkElement).toBeInTheDocument(); 8 | }); 9 | -------------------------------------------------------------------------------- /client/firebase.json: -------------------------------------------------------------------------------- 1 | { 2 | "hosting": { 3 | "public": "build", 4 | "ignore": [ 5 | "firebase.json", 6 | "**/.*", 7 | "**/node_modules/**" 8 | ], 9 | "rewrites": [ 10 | { 11 | "source": "**", 12 | "destination": "/index.html" 13 | } 14 | ] 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /client/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /client/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /client/src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = onPerfEntry => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 4 | getCLS(onPerfEntry); 5 | getFID(onPerfEntry); 6 | getFCP(onPerfEntry); 7 | getLCP(onPerfEntry); 8 | getTTFB(onPerfEntry); 9 | }); 10 | } 11 | }; 12 | 13 | export default reportWebVitals; 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | # /client 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | 25 | # Local Netlify folder 26 | .netlify -------------------------------------------------------------------------------- /client/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import "antd/dist/antd.css"; 5 | import App from './App'; 6 | import reportWebVitals from './reportWebVitals'; 7 | 8 | ReactDOM.render(, document.getElementById('root')); 9 | 10 | // If you want to start measuring performance in your app, pass a function 11 | // to log results (for example: reportWebVitals(console.log)) 12 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 13 | reportWebVitals(); 14 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "video-chat-app", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "server.js", 6 | "scripts": { 7 | "start": "node server.js", 8 | "server": "nodemon server.js", 9 | "test": "echo \"Error: no test specified\" && exit 1" 10 | }, 11 | "keywords": [], 12 | "author": "", 13 | "license": "ISC", 14 | "dependencies": { 15 | "cors": "^2.8.5", 16 | "express": "^4.17.1", 17 | "socket.io": "^4.1.2" 18 | }, 19 | "devDependencies": { 20 | "nodemon": "^2.0.7" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /client/src/Components/Messages/Message.js: -------------------------------------------------------------------------------- 1 | import React, { useContext } from 'react'; 2 | import { SocketContext } from '../../SocketContext'; 3 | import './Messages.css'; 4 | 5 | const Message = (props) => { 6 | const { me } = useContext(SocketContext); 7 | 8 | return ( 9 |
12 |
{props.message.text}
13 |
14 | ); 15 | }; 16 | 17 | export default Message; 18 | -------------------------------------------------------------------------------- /client/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "I-Meet", 3 | "name": "I-Meet", 4 | "icons": [ 5 | { 6 | "src": "home.png", 7 | "type": "image/png", 8 | "sizes": "192x192" 9 | }, 10 | { 11 | "src": "home2.png", 12 | "type": "image/png", 13 | "sizes": "512x512" 14 | }, 15 | { 16 | "src": "home1.png", 17 | "sizes": "64x64 32x32 24x24 16x16", 18 | "type": "image/png" 19 | } 20 | ], 21 | "start_url": "/", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /client/src/assets/styles/_mixins.scss: -------------------------------------------------------------------------------- 1 | $phone-width: 576px; 2 | $tablet-width: 767px; 3 | $desktop-width: 992px; 4 | $xl-width: 1200px; 5 | 6 | @mixin mobile { 7 | @media (max-width: $phone-width) { 8 | @content; 9 | } 10 | } 11 | 12 | @mixin landscape { 13 | @media (max-width: $tablet-width) { 14 | @content; 15 | } 16 | } 17 | 18 | @mixin tablet { 19 | @media (max-width: $desktop-width) { 20 | @content; 21 | } 22 | } 23 | 24 | @mixin desktop { 25 | @media (min-width: $desktop-width) { 26 | @content; 27 | } 28 | } 29 | 30 | @mixin xl-desktop { 31 | @media (min-width: $xl-width) { 32 | @content; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /.github/workflows/Deployment.yml: -------------------------------------------------------------------------------- 1 | 2 | name: CI + CD 3 | 4 | on: 5 | workflow_dispatch: 6 | 7 | jobs: 8 | Production: 9 | runs-on: ubuntu-latest 10 | environment: Development 11 | steps: 12 | - uses: actions/checkout@v2 13 | - name: Run a script 14 | run: firebase login ${{scerets.FIREBASE_ID}} ${{scerets.FIREBASE_PASS}} 15 | firebase deploy 16 | 17 | 18 | Development: 19 | runs-on: ubuntu-latest 20 | environment: Production 21 | needs: Production 22 | steps: 23 | - uses: actions/checkout@v2 24 | - name: Run a script 25 | run: echo "Deployed" 26 | 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Merge - Video Chat for Online Interviews 3 | 4 | **Project Link** - ***https://alanbinu-video-conference.web.app/*** 5 | 6 | ## Features 7 | 8 | - 1:1 Video chat 9 | - Live Editor(Whiteboard) with syntax highlighting for interviews 10 | - Notes (downloadable as PDF) 11 | - Instantly join a call with a meeting link 12 | - Real time chat 13 | - Chat Notifications 14 | - Instant notifications of ongoing meeting 15 | - Mute audio/video 16 | - Neat and clean UI 17 | 18 | ## Steps to run in your machine 19 | 20 | #### Run the following commands 21 | ``` 22 | npm i 23 | npm run server 24 | cd client 25 | npm i 26 | npm run start 27 | ``` 28 | 29 | 30 | 31 | 32 | #### Hope you liked this project, dont forget to ⭐ the repo. 33 | -------------------------------------------------------------------------------- /client/src/Components/Notes/Notes.scss: -------------------------------------------------------------------------------- 1 | .notes { 2 | height: 50vh; 3 | width: 40vw; 4 | outline: none; 5 | .btn-div { 6 | display: flex; 7 | justify-content: space-between; 8 | h3 { 9 | padding: 0 10px; 10 | } 11 | .flex-btns-div { 12 | width: 15%; 13 | display: flex; 14 | justify-content: space-between; 15 | padding-right:10px ; 16 | button { 17 | background: none; 18 | border: none; 19 | cursor: pointer; 20 | outline: none; 21 | } 22 | } 23 | } 24 | textarea { 25 | border: none; 26 | border-top: 0.5px solid rgb(220, 220, 220); 27 | padding: 10px; 28 | height: 90%; 29 | width: 100%; 30 | outline: none; 31 | resize: none; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /client/src/Components/Footer/Footer.css: -------------------------------------------------------------------------------- 1 | .footer { 2 | height: 5vh; 3 | display: flex; 4 | justify-content: center; 5 | align-items: center; 6 | margin: auto; 7 | } 8 | 9 | .footer p { 10 | margin: auto 0; 11 | font-size: 17px; 12 | font-weight: 500; 13 | } 14 | 15 | .footer p svg { 16 | fill: #f80303; 17 | } 18 | 19 | .footer img { 20 | height: 17px; 21 | width: 17px; 22 | z-index: 1; 23 | } 24 | 25 | .footer svg { 26 | z-index: 1; 27 | margin-top: 0px; 28 | margin-left: 30px; 29 | padding: 0px; 30 | float: right; 31 | } 32 | 33 | .footer .heartIcon span svg { 34 | font-size: 21px; 35 | fill: red; 36 | } 37 | 38 | .footer .linkIcon svg { 39 | font-size: 21px; 40 | fill: #0e76a8; 41 | } 42 | 43 | .footer .githubIcon svg { 44 | font-size: 20px; 45 | fill: black; 46 | } 47 | -------------------------------------------------------------------------------- /client/src/common/Spinner.js: -------------------------------------------------------------------------------- 1 | import React, { Fragment } from 'react'; 2 | import spinner from './spin1.gif'; 3 | const Spinner = (props) => { 4 | return ( 5 |
6 | Loading...... 20 |

21 | {props.starting ? 'Starting your meeting...' : 'Loading your video...'} 22 |

23 |
24 | ); 25 | }; 26 | 27 | export default Spinner; 28 | -------------------------------------------------------------------------------- /client/src/App.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from 'react'; 2 | import './App.css'; 3 | import Meet from './Components/Meet/Meet'; 4 | import Join from './Components/Join/Join'; 5 | import Home from './Components/Home/Home'; 6 | import { ContextProvider } from './SocketContext'; 7 | import { 8 | BrowserRouter as Router, 9 | Switch, 10 | Route, 11 | } from 'react-router-dom'; 12 | 13 | function App() { 14 | 15 | useEffect(() => { 16 | if (!navigator.onLine) alert('Connect to internet!'); 17 | }, [navigator]); 18 | 19 | return ( 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | ); 30 | } 31 | 32 | export default App; 33 | -------------------------------------------------------------------------------- /client/src/Components/Notes/Notes.css: -------------------------------------------------------------------------------- 1 | .notes { 2 | height: 50vh; 3 | width: 40vw; 4 | outline: none; 5 | } 6 | 7 | .notes .btn-div { 8 | display: flex; 9 | justify-content: space-between; 10 | } 11 | 12 | .notes .btn-div h3 { 13 | padding: 0 10px; 14 | } 15 | 16 | .notes .btn-div .flex-btns-div { 17 | width: 15%; 18 | display: flex; 19 | justify-content: space-between; 20 | padding-right: 10px; 21 | } 22 | 23 | .notes .btn-div .flex-btns-div button { 24 | background: none; 25 | border: none; 26 | cursor: pointer; 27 | outline: none; 28 | } 29 | 30 | .notes textarea { 31 | border: none; 32 | border-top: 0.5px solid gainsboro; 33 | padding: 10px; 34 | height: 90%; 35 | width: 100%; 36 | outline: none; 37 | resize: none; 38 | } 39 | 40 | .notesesed textareaese { 41 | border: none; 42 | border-top: 0.5px solid gainsboro; 43 | padding: 10px; 44 | height: 90%; 45 | width: 100%; 46 | outline: none; 47 | resize: none; 48 | } 49 | -------------------------------------------------------------------------------- /client/src/Components/Footer/Footer.scss: -------------------------------------------------------------------------------- 1 | .footer { 2 | height: 5vh; 3 | // z-index: 1; 4 | // background-color: black; 5 | display: flex; 6 | justify-content: center; 7 | align-items: center; 8 | // color: white; 9 | margin: auto; 10 | p { 11 | margin: auto 0; 12 | font-size: 17px; 13 | font-weight: 500; 14 | svg { 15 | fill: rgb(248, 3, 3); 16 | } 17 | } 18 | img { 19 | height: 17px; 20 | width: 17px; 21 | z-index: 1; 22 | } 23 | svg { 24 | z-index: 1; 25 | margin-top: 0px; 26 | margin-left: 30px; 27 | padding: 0px; 28 | float: right; 29 | } 30 | .heartIcon { 31 | span { 32 | svg { 33 | font-size: 21px; 34 | fill: red; 35 | } 36 | } 37 | } 38 | .linkIcon { 39 | svg { 40 | font-size: 21px; 41 | fill: #0e76a8; 42 | } 43 | } 44 | .githubIcon { 45 | svg { 46 | font-size: 20px; 47 | fill: black; 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /client/src/Components/Footer/Footer.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import './Footer.css'; 3 | import heartIcon from '../../assets/heart.png'; 4 | import githubIcon from '../../assets/github.png'; 5 | import linkedIcon from '../../assets/linkedin.png'; 6 | import GitHubIcon from '@material-ui/icons/GitHub'; 7 | import LinkedInIcon from '@material-ui/icons/LinkedIn'; 8 | import FavoriteIcon from '@material-ui/icons/Favorite'; 9 | const Footer = () => { 10 | return ( 11 |
12 |

13 | Made with heart by Alan 14 |

{' '} 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 |
24 | ); 25 | }; 26 | export default Footer; 27 | -------------------------------------------------------------------------------- /client/src/Components/Editor/Editor.css: -------------------------------------------------------------------------------- 1 | *, 2 | *::after, 3 | *::before { 4 | box-sizing: border-box; 5 | margin: 0; 6 | } 7 | 8 | body { 9 | background-color: #fafafa; 10 | margin: 0; 11 | } 12 | 13 | .editor { 14 | height: 92vh; 15 | overflow-y: scroll; 16 | overflow-x: hidden; 17 | } 18 | 19 | .editor .ql-editor { 20 | width: 9.5in; 21 | min-height: 20in; 22 | box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.2); 23 | padding: 0.4in; 24 | margin: 1rem; 25 | background-color: white; 26 | } 27 | 28 | .editor .ql-container.ql-snow { 29 | display: flex; 30 | justify-content: center; 31 | border: none; 32 | } 33 | 34 | .editor .ql-toolbar.ql-snow { 35 | display: flex; 36 | justify-content: center; 37 | position: sticky; 38 | top: 0; 39 | z-index: 1; 40 | background-color: #fafafa; 41 | box-shadow: rgba(99, 99, 99, 0.2) 0px 2px 8px 0px; 42 | } 43 | 44 | .ql-snow .ql-editor pre.ql-syntax { 45 | background-color: #f2f2f2; 46 | color: black; 47 | font-size: 16px; 48 | } 49 | 50 | @page { 51 | margin: 1in; 52 | } 53 | -------------------------------------------------------------------------------- /client/src/Components/Editor/Editor.scss: -------------------------------------------------------------------------------- 1 | *, 2 | *::after, 3 | *::before { 4 | box-sizing: border-box; 5 | margin: 0; 6 | } 7 | body { 8 | background-color: #fafafa; 9 | margin: 0; 10 | } 11 | .editor { 12 | height: 92vh; 13 | overflow-y: scroll; 14 | overflow-x: hidden; 15 | } 16 | 17 | .editor .ql-editor { 18 | width: 9.5in; 19 | min-height: 20in; 20 | // height: auto; 21 | box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.2); 22 | padding: 0.4in; 23 | margin: 1rem; 24 | background-color: white; 25 | } 26 | .editor .ql-container.ql-snow { 27 | display: flex; 28 | justify-content: center; 29 | border: none; 30 | } 31 | 32 | .editor .ql-toolbar.ql-snow { 33 | display: flex; 34 | justify-content: center; 35 | position: sticky; 36 | top: 0; 37 | z-index: 1; 38 | background-color: #fafafa; 39 | box-shadow: rgba(99, 99, 99, 0.2) 0px 2px 8px 0px; 40 | } 41 | 42 | .ql-snow .ql-editor pre.ql-syntax { 43 | background-color: #f2f2f2; 44 | color: black; 45 | font-size: 16px; 46 | } 47 | 48 | @page { 49 | margin: 1in; 50 | } 51 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: CI + CD 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | jobs: 7 | Staging: 8 | runs-on: ubuntu-latest 9 | environment: Staging 10 | steps: 11 | - uses: actions/checkout@v2 12 | - name: Run a script 13 | run: echo "Running in Staging" 14 | 15 | Quality_Assurance: 16 | runs-on: ubuntu-latest 17 | environment: Quality_Assurance 18 | needs: Staging 19 | steps: 20 | - uses: actions/checkout@v2 21 | - name: Run a script 22 | run: echo "Running in QA" 23 | 24 | Production: 25 | runs-on: ubuntu-latest 26 | environment: Development 27 | needs: Quality_Assurance 28 | steps: 29 | - uses: actions/checkout@v2 30 | - name: Run a script 31 | run: echo "Running in production" 32 | 33 | Development: 34 | runs-on: ubuntu-latest 35 | environment: Production 36 | needs: Production 37 | steps: 38 | - uses: actions/checkout@v2 39 | - name: Run a script 40 | run: echo "Deployed" 41 | 42 | 43 | -------------------------------------------------------------------------------- /client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "video-chat", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@material-ui/core": "^4.11.4", 7 | "@material-ui/icons": "^4.11.2", 8 | "@testing-library/jest-dom": "^5.12.0", 9 | "@testing-library/react": "^11.2.7", 10 | "@testing-library/user-event": "^12.8.3", 11 | "antd": "^4.16.0", 12 | "file-saver": "^2.0.5", 13 | "highlight.js": "^11.0.1", 14 | "jspdf": "^2.3.1", 15 | "netlify-cli": "^3.35.2", 16 | "quill": "^1.3.7", 17 | "quill-to-pdf": "^1.0.7", 18 | "react": "^17.0.2", 19 | "react-copy-to-clipboard": "^5.0.3", 20 | "react-dom": "^17.0.2", 21 | "react-router-dom": "^5.2.0", 22 | "react-scripts": "4.0.3", 23 | "simple-peer": "^9.11.0", 24 | "socket.io-client": "^4.1.2", 25 | "web-vitals": "^1.1.2" 26 | }, 27 | "scripts": { 28 | "start": "SET PORT=443 && react-scripts start", 29 | "build": "react-scripts build", 30 | "test": "react-scripts test", 31 | "eject": "react-scripts eject" 32 | }, 33 | "eslintConfig": { 34 | "extends": [ 35 | "react-app", 36 | "react-app/jest" 37 | ] 38 | }, 39 | "browserslist": { 40 | "production": [ 41 | ">0.2%", 42 | "not dead", 43 | "not op_mini all" 44 | ], 45 | "development": [ 46 | "last 1 chrome version", 47 | "last 1 firefox version", 48 | "last 1 safari version" 49 | ] 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /client/src/Components/Join/Join.css: -------------------------------------------------------------------------------- 1 | .join-page { 2 | padding-top: 5%; 3 | display: flex; 4 | justify-content: center; 5 | align-items: center; 6 | place-content: center; 7 | margin: auto; 8 | text-align: center; 9 | background-color: white; 10 | height: 90vh; 11 | } 12 | 13 | .join-page .video-div video { 14 | width: 50%; 15 | height: 40%; 16 | } 17 | 18 | .join-page input { 19 | margin-top: 5%; 20 | padding: 0.5rem; 21 | border: 2px solid #d1d1d1; 22 | outline: none; 23 | border-radius: 10px; 24 | width: 70%; 25 | font-size: 18px; 26 | transition-duration: 0.4s; 27 | z-index: 100; 28 | } 29 | 30 | .join-page input:focus { 31 | border-color: #2cbdc7; 32 | } 33 | 34 | .join-page .join-btns-div { 35 | width: 40%; 36 | display: flex; 37 | justify-content: space-between; 38 | text-align: center; 39 | margin: auto; 40 | padding: 1rem 0.5rem; 41 | } 42 | 43 | .join-page .join-btns-div .btn { 44 | margin: auto; 45 | padding: 0.5rem 1rem; 46 | border-radius: 10px; 47 | border: none; 48 | cursor: pointer; 49 | font-size: 17px; 50 | border: 2px solid #16c071; 51 | background-color: #0d4b85; 52 | color: white; 53 | transition-duration: 0.4s; 54 | } 55 | 56 | .join-page .join-btns-div .btn:hover { 57 | background-color: #1b8299; 58 | color: white; 59 | } 60 | 61 | @media (max-width: 576px) { 62 | .join-page .join-btns-div { 63 | width: 100%; 64 | } 65 | } 66 | 67 | @media (max-width: 576px) { 68 | .join-page .video-div video { 69 | width: 70%; 70 | height: 50%; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /client/src/Components/Navbar/Navbar.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import homeIcon from '../../assets/video-call.png'; 3 | import './Navbar.css'; 4 | import StarIcon from '@material-ui/icons/Star'; 5 | 6 | const Navbar = () => { 7 | return ( 8 |
9 |
10 | 11 |

HAVE FUN

12 |
13 | 14 | 15 |
16 |

My Protfolio

17 | 18 |
19 |
20 | 21 | 22 |
23 |

My Blog Page

24 | 25 |
26 |
27 | 28 | 29 |
30 |

My Company Page

31 | 32 |
33 |
34 | 35 | 36 |
37 |

Github

38 |

Give repo a star

39 |
40 |
41 |
42 | ); 43 | }; 44 | 45 | export default Navbar; 46 | -------------------------------------------------------------------------------- /client/src/assets/video-call.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /client/src/Components/Join/Join.scss: -------------------------------------------------------------------------------- 1 | @import '../../assets/styles/_mixins.scss'; 2 | 3 | 4 | .join-page { 5 | padding-top: 5%; 6 | display: flex; 7 | justify-content: center; 8 | align-items: center; 9 | place-content: center; 10 | margin: auto; 11 | text-align: center; 12 | background-color: white; 13 | height: 90vh; 14 | .video-div { 15 | video { 16 | width: 50%; 17 | height: 40%; 18 | } 19 | } 20 | input { 21 | margin-top: 5%; 22 | padding: 0.5rem; 23 | border: 2px solid rgb(209, 209, 209); 24 | outline: none; 25 | border-radius: 10px; 26 | width: 70%; 27 | font-size: 18px; 28 | transition-duration: 0.4s; 29 | &:focus { 30 | border-color: rgb(44, 189, 199); 31 | } 32 | z-index: 100; 33 | } 34 | .join-btns-div { 35 | width: 40%; 36 | display: flex; 37 | justify-content: space-between; 38 | text-align: center; 39 | margin: auto; 40 | padding: 1rem 0.5rem; 41 | .btn { 42 | margin: auto; 43 | padding: 0.5rem 1rem; 44 | border-radius: 10px; 45 | border: none; 46 | cursor: pointer; 47 | font-size: 17px; 48 | border: 2px solid rgb(22, 192, 113); 49 | background-color: rgb(13, 75, 133); 50 | color: white; 51 | transition-duration: 0.4s; 52 | &:hover { 53 | background-color: rgb(27, 130, 153); 54 | color: white; 55 | } 56 | } 57 | @include mobile { 58 | width: 100%; 59 | } 60 | } 61 | @include mobile { 62 | // margin-top: 20%; 63 | .video-div { 64 | video { 65 | width: 70%; 66 | height: 50%; 67 | } 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | const app = require('express')(); 2 | const cors = require('cors'); 3 | const server = require('http').createServer(app); 4 | const PORT = process.env.PORT || 5000; 5 | const io = require('socket.io')(server, { 6 | cors: { 7 | origin: '*', 8 | methods: ['GET', 'POST'], 9 | }, 10 | }); 11 | 12 | app.use(cors()); 13 | 14 | io.on('connection', (socket) => { 15 | socket.emit('me', socket.id); 16 | 17 | socket.on('updateMyMedia', (data) => { 18 | io.to(data.userToUpdate).emit('updateUserMedia', data.data); 19 | }); 20 | 21 | socket.on('calluser', ({ userToCall, from, name, signal, documentId }) => { 22 | io.to(userToCall).emit('calluser', { signal, from, name, documentId }); 23 | }); 24 | 25 | socket.on('answercall', (data) => { 26 | io.to(data.to).emit('updateUserMedia', { 27 | type: data.type, 28 | mediaStatus: data.mediaStatus, 29 | }); 30 | io.to(data.to).emit('callaccepted', data.signal,data.name); 31 | }); 32 | 33 | socket.on('send-changes', (delta, userId) => { 34 | // console.log(userId) 35 | io.to(userId).emit('recieve-changes', delta); 36 | }); 37 | 38 | socket.on('send-message', (data) => { 39 | io.to(data.userToSend).emit('recieve-message', data.data); 40 | }); 41 | 42 | socket.on('callended', (userToUpdate) => { 43 | io.to(userToUpdate).emit('callended'); 44 | }); 45 | 46 | // socket.on('disconnect', () => { 47 | // socket.broadcast.emit('callended'); 48 | // }); 49 | 50 | }); 51 | 52 | app.get('/', (req, res) => { 53 | res.send('Server is running'); 54 | }); 55 | 56 | server.listen(PORT, () => { 57 | console.log(`Server is running at port ${PORT}`); 58 | }); 59 | -------------------------------------------------------------------------------- /client/src/Components/Navbar/Navbar.css: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.googleapis.com/css2?family=Jua&display=swap"); 2 | @import url("https://fonts.googleapis.com/css2?family=Jua&family=Skranji:wght@700&display=swap"); 3 | @import url("https://fonts.googleapis.com/css2?family=Spinnaker&display=swap"); 4 | .navbar { 5 | background-color: black; 6 | display: flex; 7 | justify-content: space-between; 8 | height: 8vh; 9 | padding: 0 20px; 10 | } 11 | 12 | .navbar .title-div { 13 | align-items: center; 14 | width: 40%; 15 | display: flex; 16 | justify-content: flex-start; 17 | grid-column-gap: 10px; 18 | } 19 | 20 | .navbar .title-div img { 21 | height: 70%; 22 | } 23 | 24 | .navbar .title-div h3 { 25 | font-family: 'Spinnaker', sans-serif; 26 | font-size: 25px; 27 | font-weight: 400; 28 | margin: auto 0; 29 | color: white; 30 | } 31 | 32 | .navbar .repo { 33 | display: flex; 34 | justify-content: flex-end; 35 | align-items: center; 36 | grid-column-gap: 5px; 37 | width: auto; 38 | background: none; 39 | border: none; 40 | outline: none; 41 | cursor: pointer; 42 | text-decoration: none; 43 | } 44 | .navbar .repo1 { 45 | display: flex; 46 | justify-content: flex-end; 47 | align-items: right; 48 | grid-column-gap: 5px; 49 | width: auto; 50 | background: none; 51 | border: none; 52 | outline: none; 53 | cursor: pointer; 54 | text-decoration: none; 55 | } 56 | 57 | .navbar .repo svg { 58 | fill: #fade0a; 59 | font-size: 30px; 60 | } 61 | 62 | .navbar .repo .repo-text { 63 | text-align: left; 64 | display: block; 65 | } 66 | 67 | .navbar .repo .repo-text .repo-name { 68 | font-size: 11px; 69 | color: white; 70 | padding: 0; 71 | margin: 0; 72 | } 73 | 74 | .navbar .repo .repo-text .github-name { 75 | font-size: 15px; 76 | color: white; 77 | padding: 0; 78 | margin: 0; 79 | } 80 | -------------------------------------------------------------------------------- /client/src/Components/Navbar/Navbar.scss: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Jua&display=swap'); 2 | @import url('https://fonts.googleapis.com/css2?family=Jua&family=Skranji:wght@700&display=swap'); 3 | @import url('https://fonts.googleapis.com/css2?family=Spinnaker&display=swap'); 4 | .navbar { 5 | // box-shadow: rgba(0, 0, 0, 0.16) 0px 3px 6px, rgba(0, 0, 0, 0.23) 0px 3px 6px; 6 | background-color: black; 7 | display: flex; 8 | justify-content: space-between; 9 | height: 8vh; 10 | padding: 0 20px; 11 | .title-div { 12 | align-items: center; 13 | // padding: 0 20px; 14 | width: 40%; 15 | display: flex; 16 | justify-content: flex-start; 17 | grid-column-gap: 10px; 18 | img { 19 | // width: 70%; 20 | height: 70%; 21 | } 22 | h3 { 23 | // font-family: 'Jua', sans-serif; 24 | // font-family: 'Skranji', cursive; 25 | font-family: 'Spinnaker', sans-serif; 26 | font-size: 25px; 27 | font-weight: 400; 28 | // margin-left: 10px; 29 | margin: auto 0; 30 | color: white; 31 | } 32 | } 33 | .repo { 34 | display: flex; 35 | justify-content: flex-end; 36 | align-items: center; 37 | grid-column-gap: 5px; 38 | width:auto; 39 | background: none; 40 | border: none; 41 | outline: none; 42 | cursor: pointer; 43 | text-decoration: none; 44 | svg { 45 | fill: rgb(250, 222, 10); 46 | font-size: 30px; 47 | // animation: rotation 2s infinite linear; 48 | } 49 | .repo-text { 50 | text-align: left; 51 | display: block; 52 | // flex-direction: column; 53 | .repo-name { 54 | font-size: 11px; 55 | color: white; 56 | padding: 0; 57 | margin: 0; 58 | } 59 | .github-name { 60 | font-size: 15px; 61 | color: white; 62 | padding: 0; 63 | margin: 0; 64 | } 65 | } 66 | } 67 | } 68 | 69 | -------------------------------------------------------------------------------- /client/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 33 | HAVE FUN - Video chat for Interviews 34 | 35 | 36 | 37 |
38 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /.github/workflows/docker-publish.yml: -------------------------------------------------------------------------------- 1 | name: Docker 2 | 3 | # This workflow uses actions that are not certified by GitHub. 4 | # They are provided by a third-party and are governed by 5 | # separate terms of service, privacy policy, and support 6 | # documentation. 7 | 8 | on: 9 | schedule: 10 | - cron: '41 16 * * *' 11 | push: 12 | branches: [ master ] 13 | # Publish semver tags as releases. 14 | tags: [ 'v*.*.*' ] 15 | pull_request: 16 | branches: [ master ] 17 | 18 | env: 19 | # Use docker.io for Docker Hub if empty 20 | REGISTRY: ghcr.io 21 | # github.repository as / 22 | IMAGE_NAME: ${{ github.repository }} 23 | 24 | 25 | jobs: 26 | build: 27 | 28 | runs-on: ubuntu-latest 29 | permissions: 30 | contents: read 31 | packages: write 32 | 33 | steps: 34 | - name: Checkout repository 35 | uses: actions/checkout@v2 36 | 37 | # Login against a Docker registry except on PR 38 | # https://github.com/docker/login-action 39 | - name: Log into registry ${{ env.REGISTRY }} 40 | if: github.event_name != 'pull_request' 41 | uses: docker/login-action@28218f9b04b4f3f62068d7b6ce6ca5b26e35336c 42 | with: 43 | registry: ${{ env.REGISTRY }} 44 | username: ${{ github.actor }} 45 | password: ${{ secrets.GITHUB_TOKEN }} 46 | 47 | # Extract metadata (tags, labels) for Docker 48 | # https://github.com/docker/metadata-action 49 | - name: Extract Docker metadata 50 | id: meta 51 | uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38 52 | with: 53 | images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} 54 | 55 | # Build and push Docker image with Buildx (don't push on PR) 56 | # https://github.com/docker/build-push-action 57 | - name: Build and push Docker image 58 | uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc 59 | with: 60 | context: . 61 | push: ${{ github.event_name != 'pull_request' }} 62 | tags: ${{ steps.meta.outputs.tags }} 63 | labels: ${{ steps.meta.outputs.labels }} 64 | -------------------------------------------------------------------------------- /client/src/App.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | margin: 0; 4 | padding: 0; 5 | } 6 | 7 | body{ 8 | /* font-family: 'Raleway', sans-serif; */ 9 | } 10 | .editor::-webkit-scrollbar-track { 11 | -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3); 12 | border-radius: 10px; 13 | background-color: #f5f5f5; 14 | } 15 | 16 | .editor::-webkit-scrollbar { 17 | width: 8px; 18 | background-color: #f5f5f5; 19 | } 20 | 21 | .editor::-webkit-scrollbar-thumb { 22 | border-radius: 10px; 23 | -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3); 24 | background-color: #b5b5b5; 25 | } 26 | .editor::-webkit-scrollbar-thumb:hover { 27 | background-color: #5c5c5c; 28 | } 29 | .tooltip { 30 | position: relative; 31 | display: inline-block; 32 | border-bottom: 1px dotted black; 33 | } 34 | 35 | .tooltip .tooltiptext { 36 | visibility: hidden; 37 | width: 80px; 38 | background-color: rgb(55, 55, 55); 39 | color: #fff; 40 | text-align: center; 41 | border-radius: 6px; 42 | padding: 5px 0; 43 | position: absolute; 44 | z-index: 1; 45 | bottom: 150%; 46 | left: 50%; 47 | margin-left: -40px; 48 | } 49 | 50 | .tooltip .tooltiptext::after { 51 | content: ''; 52 | position: absolute; 53 | top: 100%; 54 | left: 50%; 55 | margin-left: -5px; 56 | border-width: 5px; 57 | border-style: solid; 58 | border-color: black transparent transparent transparent; 59 | } 60 | 61 | .tooltip:hover .tooltiptext { 62 | transition-duration: 1s; 63 | visibility: visible; 64 | } 65 | 66 | .slide-left { 67 | animation: 0.5s slide-left; 68 | } 69 | @keyframes slide-left { 70 | from { 71 | margin-left: 100%; 72 | } 73 | to { 74 | margin-left: 0%; 75 | } 76 | } 77 | 78 | .slide-right { 79 | animation: 1s slide-right; 80 | } 81 | @keyframes slide-right { 82 | from { 83 | margin-left: -100%; 84 | } 85 | to { 86 | margin-left: 0%; 87 | } 88 | } 89 | 90 | .rotate { 91 | animation: rotation 5s infinite linear; 92 | } 93 | 94 | @keyframes rotation { 95 | from { 96 | transform: rotate(0deg); 97 | } 98 | to { 99 | transform: rotate(359deg); 100 | } 101 | } -------------------------------------------------------------------------------- /client/src/Components/Messages/Messages.css: -------------------------------------------------------------------------------- 1 | .outer-div { 2 | height: 40vh; 3 | width: 30vw; 4 | } 5 | 6 | @media (max-width: 576px) { 7 | .outer-div { 8 | height: 60vh; 9 | width: 70vw; 10 | } 11 | } 12 | 13 | .btn-div { 14 | display: flex; 15 | justify-content: space-between; 16 | } 17 | 18 | .btn-div h3 { 19 | padding: 0 10px; 20 | } 21 | 22 | .btn-div button { 23 | background-color: white; 24 | border: none; 25 | cursor: pointer; 26 | } 27 | 28 | .messages { 29 | overflow-y: scroll; 30 | padding: 0 10px; 31 | width: 100%; 32 | height: 100%; 33 | flex: auto; 34 | overflow: auto; 35 | } 36 | 37 | .messages h3 { 38 | text-align: center; 39 | } 40 | 41 | .message-div { 42 | display: flex; 43 | margin-top: 10px; 44 | word-wrap: break-word; 45 | } 46 | 47 | .message { 48 | display: flex; 49 | max-width: 60%; 50 | padding: 3px 10px; 51 | border-radius: 10px; 52 | word-wrap: break-word; 53 | overflow-x: hidden; 54 | border: 1.5px solid #888888; 55 | font-weight: 500; 56 | } 57 | 58 | .bg-dark { 59 | color: white; 60 | background-color: #33b0dd; 61 | } 62 | 63 | .tr { 64 | justify-content: flex-end; 65 | } 66 | 67 | .tl { 68 | justify-content: flex-start; 69 | } 70 | 71 | .inputs { 72 | display: flex; 73 | justify-content: space-between; 74 | align-items: center; 75 | margin-top: 20px; 76 | } 77 | 78 | .inputs input { 79 | width: 80%; 80 | border: 1px solid grey; 81 | outline: none; 82 | border-radius: 10px; 83 | padding: 5px; 84 | } 85 | 86 | @media (max-width: 576px) { 87 | .inputs input { 88 | width: 70%; 89 | } 90 | } 91 | 92 | .scrollbar { 93 | overflow: auto; 94 | } 95 | 96 | .scrollbar::-webkit-scrollbar { 97 | width: 7px; 98 | height: 6px; 99 | } 100 | 101 | .scrollbar::-webkit-scrollbar-thumb { 102 | border-radius: 5px; 103 | -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1); 104 | background: rgba(0, 0, 0, 0.2); 105 | } 106 | 107 | .scrollbar-primary::-webkit-scrollbar { 108 | scroll-margin: auto; 109 | } 110 | 111 | .scrollbar-primary { 112 | scrollbar-color: #76c5f3; 113 | } 114 | 115 | .scrollbar-primary::-webkit-scrollbar-thumb { 116 | border-radius: 10px; 117 | -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1); 118 | background-color: #5ebdfc; 119 | } 120 | -------------------------------------------------------------------------------- /client/src/Components/Options/Options.css: -------------------------------------------------------------------------------- 1 | .options { 2 | background-color: black; 3 | height: 10vh; 4 | margin: 0 auto; 5 | padding: 0 10px; 6 | display: flex; 7 | align-items: center; 8 | justify-content: space-around; 9 | outline: none; 10 | border-top-left-radius: 25px; 11 | border-top-right-radius: 25px; 12 | border-bottom-left-radius: 0px; 13 | border-bottom-right-radius: 0px; 14 | } 15 | 16 | .options button { 17 | display: flex; 18 | align-items: center; 19 | border-radius: 50%; 20 | outline: none; 21 | border: none; 22 | padding: 10px; 23 | cursor: pointer; 24 | transition-duration: 0.4s; 25 | box-shadow: rgba(60, 64, 67, 0.3) 0px 1px 2px 0px, rgba(60, 64, 67, 0.15) 0px 1px 3px 1px; 26 | } 27 | 28 | .options .bg-grey { 29 | background-color: #8f8f8f; 30 | } 31 | 32 | .options .red-btn { 33 | border-radius: 35%; 34 | padding: 7px 15px; 35 | background-color: #c20505; 36 | } 37 | 38 | .options .red-btn svg { 39 | fill: white; 40 | } 41 | 42 | .options .red-btn:hover { 43 | background-color: #e44646; 44 | } 45 | 46 | @media (max-width: 576px) { 47 | .options { 48 | position: fixed; 49 | bottom: 0; 50 | } 51 | } 52 | 53 | .options-menu { 54 | padding: 0 1rem; 55 | display: block; 56 | text-align: center; 57 | outline: none; 58 | } 59 | 60 | .options-menu div { 61 | padding: 0.5rem; 62 | } 63 | 64 | .options-menu input { 65 | border-radius: 10px; 66 | border: 1px solid #9e9e9e; 67 | outline: none; 68 | padding: 10px; 69 | } 70 | 71 | .options-menu .btn-div { 72 | display: flex; 73 | justify-content: space-between; 74 | } 75 | 76 | .options-menu .btn-div h3 { 77 | padding: 0 10px; 78 | } 79 | 80 | .options-menu .btn-div button { 81 | background-color: white; 82 | border: none; 83 | cursor: pointer; 84 | } 85 | 86 | .w100 { 87 | border-radius: 25px; 88 | width: 45%; 89 | } 90 | 91 | @media (max-width: 576px) { 92 | .w100 { 93 | width: 100%; 94 | border-top-left-radius: 25px; 95 | border-top-right-radius: 25px; 96 | border-bottom-left-radius: 0px; 97 | border-bottom-right-radius: 0px; 98 | } 99 | } 100 | 101 | .call-div p { 102 | font-size: 20px; 103 | } 104 | 105 | .call-div .flex { 106 | display: flex; 107 | justify-content: space-between; 108 | align-items: center; 109 | } 110 | -------------------------------------------------------------------------------- /client/src/common/AntSwitch.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { withStyles } from '@material-ui/core/styles'; 3 | import Switch from '@material-ui/core/Switch'; 4 | 5 | const AntSwitch = withStyles((theme) => ({ 6 | root: { 7 | width: 44, 8 | height: 24, 9 | padding: 0, 10 | margin: theme.spacing(1), 11 | }, 12 | switchBase: { 13 | padding: 1, 14 | '&$checked': { 15 | transform: 'translateX(20px)', 16 | color: theme.palette.common.white, 17 | '& + $track': { 18 | backgroundColor: '#52d869', 19 | opacity: 1, 20 | border: 'none', 21 | }, 22 | }, 23 | '&$focusVisible $thumb': { 24 | color: '#52d869', 25 | border: '6px solid #fff', 26 | }, 27 | }, 28 | thumb: { 29 | width: 22, 30 | height: 22, 31 | }, 32 | track: { 33 | borderRadius: 24 / 2, 34 | border: `1px solid ${theme.palette.grey[400]}`, 35 | backgroundColor: theme.palette.grey[80], 36 | opacity: 1, 37 | transition: theme.transitions.create(['background-color', 'border']), 38 | }, 39 | checked: {}, 40 | focusVisible: {}, 41 | }))(({ classes, ...props }) => { 42 | return ( 43 | 55 | ); 56 | }); 57 | // const AntSwitch = withStyles((theme) => ({ 58 | // root: { 59 | // width: 42, 60 | // height: 26, 61 | // padding: 0, 62 | // display: 'flex', 63 | // }, 64 | // switchBase: { 65 | // padding: 1, 66 | // color: theme.palette.grey[500], 67 | // '&$checked': { 68 | // transform: 'translateX(12px)', 69 | // color: theme.palette.common.white, 70 | // '& + $track': { 71 | // opacity: 1, 72 | // backgroundColor: theme.palette.primary.main, 73 | // borderColor: theme.palette.primary.main, 74 | // }, 75 | // }, 76 | // }, 77 | // thumb: { 78 | // width: 24, 79 | // height: 24, 80 | // boxShadow: 'none', 81 | // }, 82 | // track: { 83 | // border: `1px solid ${theme.palette.grey[500]}`, 84 | // borderRadius: 26 / 2, 85 | // opacity: 1, 86 | // backgroundColor: theme.palette.common.white, 87 | // }, 88 | // checked: {}, 89 | // }))(Switch); 90 | 91 | export default AntSwitch; 92 | -------------------------------------------------------------------------------- /client/src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ master ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ master ] 20 | schedule: 21 | - cron: '16 6 * * 0' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'javascript' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] 37 | # Learn more about CodeQL language support at https://git.io/codeql-language-support 38 | 39 | steps: 40 | - name: Checkout repository 41 | uses: actions/checkout@v2 42 | 43 | # Initializes the CodeQL tools for scanning. 44 | - name: Initialize CodeQL 45 | uses: github/codeql-action/init@v1 46 | with: 47 | languages: ${{ matrix.language }} 48 | # If you wish to specify custom queries, you can do so here or in a config file. 49 | # By default, queries listed here will override any specified in a config file. 50 | # Prefix the list here with "+" to use these queries and those in the config file. 51 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 52 | 53 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 54 | # If this step fails, then you should remove it and run the build manually (see below) 55 | - name: Autobuild 56 | uses: github/codeql-action/autobuild@v1 57 | 58 | # ℹ️ Command-line programs to run using the OS shell. 59 | # 📚 https://git.io/JvXDl 60 | 61 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 62 | # and modify them (or add more) to build your code if your project 63 | # uses a compiled language 64 | 65 | #- run: | 66 | # make bootstrap 67 | # make release 68 | 69 | - name: Perform CodeQL Analysis 70 | uses: github/codeql-action/analyze@v1 71 | -------------------------------------------------------------------------------- /client/src/Components/Options/Options.scss: -------------------------------------------------------------------------------- 1 | @import '../../assets/styles/_mixins.scss'; 2 | .options { 3 | background-color: rgb(0, 0, 0); 4 | // width: 30%; 5 | height: 10vh; 6 | margin: 0 auto; 7 | // border-radius: 10px; 8 | padding: 0 10px; 9 | display: flex; 10 | align-items: center; 11 | justify-content: space-around; 12 | // position: fixed; 13 | // bottom: 0; 14 | outline: none; 15 | border-top-left-radius: 25px; 16 | border-top-right-radius: 25px; 17 | border-bottom-left-radius: 0px; 18 | border-bottom-right-radius: 0px; 19 | button { 20 | display: flex; 21 | align-items: center; 22 | border-radius: 50%; 23 | outline: none; 24 | border: none; 25 | padding: 10px; 26 | cursor: pointer; 27 | transition-duration: 0.4s; 28 | box-shadow: rgba(60, 64, 67, 0.3) 0px 1px 2px 0px, 29 | rgba(60, 64, 67, 0.15) 0px 1px 3px 1px; 30 | // &:hover { 31 | // background-color: rgb(221, 221, 221); 32 | // } 33 | } 34 | .bg-white { 35 | // background-color: rgb(221, 221, 221); 36 | } 37 | .bg-grey { 38 | background-color: rgb(143, 143, 143); 39 | } 40 | .red-btn { 41 | border-radius: 35%; 42 | padding: 7px 15px; 43 | background-color: rgb(194, 5, 5); 44 | svg { 45 | fill: white; 46 | } 47 | &:hover { 48 | background-color: rgb(228, 70, 70); 49 | } 50 | } 51 | @include mobile { 52 | position: fixed; 53 | bottom: 0; 54 | } 55 | } 56 | .options-menu { 57 | padding: 0 1rem; 58 | display: block; 59 | text-align: center; 60 | outline: none; 61 | div { 62 | padding: 0.5rem; 63 | } 64 | input { 65 | border-radius: 10px; 66 | border: 1px solid rgb(158, 158, 158); 67 | outline: none; 68 | padding: 10px; 69 | } 70 | .btn-div { 71 | display: flex; 72 | justify-content: space-between; 73 | h3 { 74 | padding: 0 10px; 75 | } 76 | button { 77 | background-color: white; 78 | border: none; 79 | cursor: pointer; 80 | // box-shadow: rgba(100, 100, 111, 0.2) 0px 7px 29px 0px; 81 | } 82 | } 83 | } 84 | .w100 { 85 | border-radius: 25px; 86 | 87 | width: 45%; 88 | @include mobile { 89 | width: 100%; 90 | border-top-left-radius: 25px; 91 | border-top-right-radius: 25px; 92 | border-bottom-left-radius: 0px; 93 | border-bottom-right-radius: 0px; 94 | } 95 | } 96 | 97 | .call-div { 98 | p { 99 | font-size: 20px; 100 | } 101 | .flex { 102 | display: flex; 103 | justify-content: space-between; 104 | align-items: center; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /client/src/Components/Notes/Notes.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect, useCallback, useContext } from 'react'; 2 | import { message } from 'antd'; 3 | import { SocketContext } from '../../SocketContext'; 4 | import EventNoteIcon from '@material-ui/icons/EventNote'; 5 | import './Notes.css'; 6 | import CloseIcon from '@material-ui/icons/Close'; 7 | import GetAppIcon from '@material-ui/icons/GetApp'; 8 | import Menu from '@material-ui/core/Menu'; 9 | import { jsPDF } from 'jspdf'; 10 | 11 | const Notes = () => { 12 | const { notes, setNotes } = useContext(SocketContext); 13 | const [anchorEl, setAnchorEl] = useState(null); 14 | const [mobileView, setMobileView] = useState(false); 15 | 16 | const resize = () => { 17 | setMobileView(window.innerWidth <= 600); 18 | }; 19 | 20 | useEffect(() => { 21 | resize(); 22 | window.addEventListener('resize', resize); 23 | }, []); 24 | 25 | const handleClick = (event) => { 26 | setAnchorEl(event.currentTarget); 27 | }; 28 | 29 | const handleClose = () => { 30 | setAnchorEl(null); 31 | }; 32 | const downLoadAsPdf = () => { 33 | if (notes.trim().length == 0) { 34 | message.error('Please write some text to download'); 35 | return; 36 | } 37 | const pdfDoc = new jsPDF(); 38 | pdfDoc.text(notes, 10, 10); 39 | message.success('Your notes is downloading'); 40 | pdfDoc.save('meet notes.pdf'); 41 | }; 42 | 43 | return ( 44 | <> 45 | {!mobileView && ( 46 | 50 | )} 51 | 58 |
59 |
60 |
61 |

Notes

62 |
63 |
64 | 67 | 70 |
71 |
72 | 73 |