From 5259a2b9e626e2445872c0508fd58e099ee173b4 Mon Sep 17 00:00:00 2001 From: simran2607 Date: Fri, 19 Mar 2021 00:35:45 +0530 Subject: [PATCH 01/61] reconnect-user-to-same-room --- backend/server/index.js | 18 +++++-- .../syntaxmeets/src/components/Home/Home.js | 15 +++++- .../src/components/SyntaxRoom/SyntaxRoom.js | 48 +++++++++++++++++-- 3 files changed, 70 insertions(+), 11 deletions(-) diff --git a/backend/server/index.js b/backend/server/index.js index 0ade59764..6806c235c 100644 --- a/backend/server/index.js +++ b/backend/server/index.js @@ -6,7 +6,8 @@ const io = require("socket.io")(server, { origins: "*:*" }); // instantiate a new rooms object to store all clients in the room const rooms = new Rooms(); - +// to store all the rooms +const roomsCreated = []; // io.origins(["http://localhost:3000"]); app.use(cors()); @@ -22,12 +23,14 @@ io.on("connection", (socket) => { roomId = room; userName = name; userId = socket.id; - + // pushes new rooms created + if(!roomsCreated.includes(room)) + roomsCreated.push(room); + socket.join(room); const oldUser = rooms.getUser(roomId); rooms.addUserToRoom(socket.id, name, room); const users = rooms.getAllUsers(room); - // send all the users to only the new User who joined and id of the current user socket.emit("addusers", { id: socket.id, users }); // inform everyone (excluding the new User) , that a user has been added @@ -56,8 +59,9 @@ io.on("connection", (socket) => { socket.on("disconnect", function () { if (!userName) return; - + const returnId = rooms.deleteUser(roomId, socket.id); + if (returnId) socket.broadcast .to(roomId) @@ -68,7 +72,13 @@ io.on("connection", (socket) => { app.get("/", (req, res) => { res.send({ response: "Server is up and Running." }).status(200); }); +// api call to get rooms created +app.get('/rooms', function(req, res) { + console.log('got the response'); + res.json(roomsCreated); +}); server.listen(process.env.PORT || 4000, function () { console.log("server is working"); }); + diff --git a/frontend/syntaxmeets/src/components/Home/Home.js b/frontend/syntaxmeets/src/components/Home/Home.js index c43fcc3f9..b6d2dbc79 100644 --- a/frontend/syntaxmeets/src/components/Home/Home.js +++ b/frontend/syntaxmeets/src/components/Home/Home.js @@ -12,7 +12,6 @@ import { withStyles } from "@material-ui/core/styles"; import MeetingRoomIcon from '@material-ui/icons/MeetingRoom'; import GroupAddIcon from '@material-ui/icons/GroupAdd'; - function generateRoomId() { var tempId = ""; var characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; @@ -23,9 +22,11 @@ function generateRoomId() { tempId += "-"; } } + return tempId; } + const styles = { input: { color: "#000", @@ -41,7 +42,6 @@ const Home = (props) => { const [name, setName] = useState(""); const [disabledName, setDisabledName] = useState(true); const [disabledRoomId, setDisabledRoomId] = useState(true); - const roomModal = { backgroundImage: "linear-gradient(to top, #d6d4ee, #e1dff2, #ebe9f6, #f5f4fb, #ffffff)", @@ -173,6 +173,11 @@ const Home = (props) => { pathname: roomId, name: name, }} + onClick={()=>{ + localStorage.setItem('roomId',roomId); + localStorage.setItem('name',name); + } + } > Create Room @@ -257,6 +262,12 @@ const Home = (props) => { pathname: joinRoomId, name: name, }} + onClick={ ()=>{ + localStorage.setItem('roomId',joinRoomId) + localStorage.setItem('name',name) + } + + } > Join a Room diff --git a/frontend/syntaxmeets/src/components/SyntaxRoom/SyntaxRoom.js b/frontend/syntaxmeets/src/components/SyntaxRoom/SyntaxRoom.js index 1d146dacf..69d9b66d2 100644 --- a/frontend/syntaxmeets/src/components/SyntaxRoom/SyntaxRoom.js +++ b/frontend/syntaxmeets/src/components/SyntaxRoom/SyntaxRoom.js @@ -1,4 +1,4 @@ -import React, { Fragment, useState, useEffect } from "react"; +import React, { Fragment, useState, useEffect} from "react"; import Navbar from "../Navbar/Navbar"; import { Grid, Snackbar } from "@material-ui/core"; import SyntaxEditor from "../SyntaxEditor/SyntaxEditor"; @@ -16,11 +16,14 @@ const socket = io.connect( process.env.REACT_APP_SYNTAXMEETS_BACKEND_API, connectionOptions ); +// to use for localhost +//var socket = io.connect("http://localhost:4000",connectionOptions); const Alert = (props) => { return ; }; + const SyntaxRoom = (props) => { let paramsRoom = useParams().roomId; const [roomId] = useState(paramsRoom); @@ -33,18 +36,53 @@ const SyntaxRoom = (props) => { const [userLeftName, setUserLeftName] = useState(); const [id, setId] = useState(); // Stores the userid default 1 and then increases and decreases according to the users. const [previousUser, setPreviousUser] = useState({}); //Store the id of an already existing user , so this user will emit the code when a new user joins - + + useEffect(() => { + // fetch the list of active rooms from backend + var roomsList = []; + const url = `${process.env.REACT_APP_SYNTAXMEETS_BACKEND_API}/rooms`; + fetch(url) + .then(res => { + return res.json(); + }) + .then(rooms => { + console.log(rooms); + for (let i = 0; i < rooms.length; i++) + roomsList.push(rooms[i]); + }); + + console.log(roomsList); // If disconnected then connect again to server // Trigerred when user leaves a room + // Trigerred when user leaves a room socket.on("disconnect", (reason) => { + socket.connect(); }); + var roomid = localStorage.getItem('roomId'); + if (props.location.name === undefined || props.location.name === "") { - alert("Please Enter your name"); - setGoToHome(true); + // If user disconnects and want to connect back to same room + var flag = false; + flag = roomsList.includes(roomid); + localStorage.setItem('flag', flag); + if (localStorage.getItem('flag')) { + props.location.name = localStorage.getItem('name'); + let data = { + room: localStorage.getItem('roomId'), + name: localStorage.getItem('name'), + } + // join back to same room + socket.emit("joinroom", data); + } + else { + // direct back to home + alert("Please Enter your name"); + setGoToHome(true); + } } var patt = new RegExp("(([A-Za-z]{4})(-)){2}[A-Za-z]{4}"); @@ -60,7 +98,7 @@ const SyntaxRoom = (props) => { name: name, }; socket.emit("joinroom", data); - + localStorage.setItem("my_name", name); socket.on("addusers", (data) => { // When a new User joins in the room // Get all the users from the backend , when the current user joins in the room From 6d34be85ae462ad306de6615217a3b7234b995ae Mon Sep 17 00:00:00 2001 From: Priyankcoder Date: Thu, 25 Mar 2021 17:43:18 +0530 Subject: [PATCH 02/61] add emoji picker --- frontend/syntaxmeets/package-lock.json | 14 +++-- frontend/syntaxmeets/package.json | 1 + .../src/components/SyntaxChat/SyntaxChat.js | 60 +++++++++++++++++-- 3 files changed, 66 insertions(+), 9 deletions(-) diff --git a/frontend/syntaxmeets/package-lock.json b/frontend/syntaxmeets/package-lock.json index 75deaa83e..f4537b350 100644 --- a/frontend/syntaxmeets/package-lock.json +++ b/frontend/syntaxmeets/package-lock.json @@ -6703,6 +6703,15 @@ "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.7.2.tgz", "integrity": "sha512-A8OG5SR/ij3SsJdWDJdkkSYUjQdCUx6APQXem0SaEePBSRg4eymGYwBkKo1Y6DU+af/Jn2dBQqDBvjnr9Vi8nQ==" }, + "emoji-mart": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/emoji-mart/-/emoji-mart-3.0.1.tgz", + "integrity": "sha512-sxpmMKxqLvcscu6mFn9ITHeZNkGzIvD0BSNFE/LJESPbCA8s1jM6bCDPjWbV31xHq7JXaxgpHxLB54RCbBZSlg==", + "requires": { + "@babel/runtime": "^7.0.0", + "prop-types": "^15.6.0" + } + }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -7938,11 +7947,6 @@ } } }, - "express-rate-limit": { - "version": "5.2.6", - "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-5.2.6.tgz", - "integrity": "sha512-nE96xaxGfxiS5jP3tD3kIW1Jg9yQgX0rXCs3rCkZtmbWHEGyotwaezkLj7bnB41Z0uaOLM8W4AX6qHao4IZ2YA==" - }, "ext": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", diff --git a/frontend/syntaxmeets/package.json b/frontend/syntaxmeets/package.json index 175dab190..71450beff 100644 --- a/frontend/syntaxmeets/package.json +++ b/frontend/syntaxmeets/package.json @@ -13,6 +13,7 @@ "axios": "^0.21.1", "bootstrap": "^4.5.3", "copy-to-clipboard": "^3.3.1", + "emoji-mart": "^3.0.1", "fontsource-poppins": "^3.0.9", "react": "^16.13.1", "react-ace": "^9.1.4", diff --git a/frontend/syntaxmeets/src/components/SyntaxChat/SyntaxChat.js b/frontend/syntaxmeets/src/components/SyntaxChat/SyntaxChat.js index e2f77cdd6..6b763934f 100644 --- a/frontend/syntaxmeets/src/components/SyntaxChat/SyntaxChat.js +++ b/frontend/syntaxmeets/src/components/SyntaxChat/SyntaxChat.js @@ -1,5 +1,6 @@ import React, { useState, useEffect, useRef } from "react"; import { makeStyles } from "@material-ui/core/styles"; +import InsertEmoticonIcon from "@material-ui/icons/InsertEmoticon"; import { Drawer, Button, @@ -13,6 +14,8 @@ import SendIcon from "@material-ui/icons/Send"; import ForumIcon from "@material-ui/icons/Forum"; import { ChatMessage } from "./ChatMessage"; import CloseSharpIcon from "@material-ui/icons/CloseSharp"; +import "emoji-mart/css/emoji-mart.css"; +import { Picker } from "emoji-mart"; const useStyles = makeStyles({ list: { @@ -28,12 +31,14 @@ const SyntaxChat = (props) => { const [message, setMessage] = useState(""); const [messages, setMessages] = useState([]); const [typingUser, setTypingUser] = useState(); + const [emojiPickerState, SetEmojiPicker] = useState(false); const messagesEndRef = useRef(null); const [mCount, setMCount] = useState(0); const [state, setState] = useState(false); const handleMessageSubmit = () => { + SetEmojiPicker(false); if (message === "") return; let data = { name: props.name, @@ -69,7 +74,22 @@ const SyntaxChat = (props) => { } }; + function triggerPicker(event) { + event.preventDefault(); + SetEmojiPicker(!emojiPickerState); + } useEffect(scrollToBottom, [messages]); + let emojiPicker; + if (emojiPickerState) { + emojiPicker = ( + setMessage(message + emoji.native)} + // style={{width: "90%", display: "flex"}} + /> + ); + } const toggleDrawer = (open) => (event) => { if ( @@ -151,7 +171,26 @@ const SyntaxChat = (props) => { ) : undefined} - + {/* */} + + {/* */} + + + {/* */} + + { } }} /> + {/* SetMessage(event.target.value)} + /> */} + + + {emojiPicker} + + From 1010f87825c76d5c380669f05a4a94c815172c43 Mon Sep 17 00:00:00 2001 From: Priyankcoder Date: Thu, 25 Mar 2021 17:51:45 +0530 Subject: [PATCH 03/61] tweak styling --- .../src/components/SyntaxChat/SyntaxChat.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/frontend/syntaxmeets/src/components/SyntaxChat/SyntaxChat.js b/frontend/syntaxmeets/src/components/SyntaxChat/SyntaxChat.js index 6b763934f..adf9b1f47 100644 --- a/frontend/syntaxmeets/src/components/SyntaxChat/SyntaxChat.js +++ b/frontend/syntaxmeets/src/components/SyntaxChat/SyntaxChat.js @@ -170,9 +170,9 @@ const SyntaxChat = (props) => { ) : undefined} - + {/* */} - + {/* - { - setPopup(false); - }} - > - { - setPopup(false); - }} - severity="success" - variant="filled" - > - Room-ID Copied ! - - - + { + return { + users: state.ROOM.users, + }; +}; + +export default connect(mapStateToProps, null)(ParticipantsList); + diff --git a/frontend/syntaxmeets/src/components/SyntaxChat/SyntaxChat.js b/frontend/syntaxmeets/src/components/SyntaxChat/SyntaxChat.js index e2f77cdd6..6331fafe0 100644 --- a/frontend/syntaxmeets/src/components/SyntaxChat/SyntaxChat.js +++ b/frontend/syntaxmeets/src/components/SyntaxChat/SyntaxChat.js @@ -8,7 +8,8 @@ import { Grid, Typography, } from "@material-ui/core"; - +import { connect } from 'react-redux'; +import * as actions from "../../store/actions/chatActions.js"; import SendIcon from "@material-ui/icons/Send"; import ForumIcon from "@material-ui/icons/Forum"; import { ChatMessage } from "./ChatMessage"; @@ -25,40 +26,36 @@ const useStyles = makeStyles({ const SyntaxChat = (props) => { const classes = useStyles(); - const [message, setMessage] = useState(""); - const [messages, setMessages] = useState([]); - const [typingUser, setTypingUser] = useState(); const messagesEndRef = useRef(null); - - const [mCount, setMCount] = useState(0); - const [state, setState] = useState(false); + const [openDrawer, setopenDrawer] = useState(false); const handleMessageSubmit = () => { - if (message === "") return; + if (props.message === "") return; let data = { name: props.name, roomId: props.roomId, - message: message, + message: props.message, }; props.socket.emit("chatmessage", data); - setMessages((messages) => [...messages, data]); - setMCount(mCount + 1); - setMessage(""); + + props.setMessages(data); + props.setMessage(""); }; useEffect(() => { + props.socket.on("chatmessage", (data) => { - setMessages((messages) => [...messages, data]); + props.setMessages(data); }); let timeout; - // recieve the user who is currently typing's data from the backend - props.socket.on("typing", (data) => { - setTypingUser(data.name); + // recieve the user who is currently typing's data from the backend + props.socket.on("typing", (data) => { + props.whoIsTyping(data.name); //Remove the timeout(to clear typing message) , if someone has again typed something clearTimeout(timeout); timeout = setTimeout(() => { //Remove the typing message if no one is typing after 500ms - setTypingUser(); + props.whoIsTyping(); }, 500); }); }, []); @@ -69,17 +66,13 @@ const SyntaxChat = (props) => { } }; - useEffect(scrollToBottom, [messages]); + useEffect(scrollToBottom, [props.messages]); const toggleDrawer = (open) => (event) => { - if ( - event.type === "keydown" && - (event.key === "Tab" || event.key === "Shift") - ) { + if (event.type === "keydown" && (event.key === "Tab" || event.key === "Shift")){ return; } - - setState(open); + setopenDrawer(open); }; return ( @@ -98,7 +91,7 @@ const SyntaxChat = (props) => { > Chat Box - + { height: "90%", }} > - {} + {}
{ - {typingUser ? ( + {props.typingUser ? ( { style={{ marginBottom: "4px" }} gutterBottom > - {typingUser} is typing... + {props.typingUser} is typing... @@ -159,14 +152,13 @@ const SyntaxChat = (props) => { variant="outlined" fullWidth size="small" - value={message} + value={props.message} onChange={(e) => { - // Send the user who is currently typings , name and id to the backend props.socket.emit("typing", { id: props.socket.id, name: props.name, }); - setMessage(e.target.value); + props.setMessage(e.target.value); }} onKeyDown={(e) => { if (e.key === "Enter") { @@ -202,4 +194,19 @@ const SyntaxChat = (props) => { ); }; -export default SyntaxChat; +const mapStateToProps = state => { + return { + typingUser: state.CHAT.typingUser, + message:state.CHAT.message, + messages : state.CHAT.chat, + } +} + +const mapDispatchToProps = (dispatch) => { + return { + setMessage: (msg) => dispatch(actions.setMessage(msg)), + setMessages: (msg) => dispatch(actions.makeMessage(msg)), + whoIsTyping: (user) => dispatch(actions.whoIsTyping(user)) + } +} +export default connect(mapStateToProps,mapDispatchToProps)(SyntaxChat); diff --git a/frontend/syntaxmeets/src/components/SyntaxEditor/CodeInput.js b/frontend/syntaxmeets/src/components/SyntaxEditor/CodeInput.js new file mode 100644 index 000000000..7f6d52068 --- /dev/null +++ b/frontend/syntaxmeets/src/components/SyntaxEditor/CodeInput.js @@ -0,0 +1,35 @@ +import React from "react"; +import AceEditor from "react-ace"; +import { connect } from "react-redux"; +import * as actions from "../../store/actions/editorActions.js"; +const INPUT = (props) => { + const handleIChange = (newValue) => { + props.setCodeInput(newValue); + }; + + return ( + + ); + }; + + const mapStateToProps = (state) => { + return { + codeInput: state.EDITOR.codeInput, + }; + }; + + const mapDispatchToProps = (dispatch) => { + return { + setCodeInput: (input) => dispatch(actions.setCodeInput(input)), + }; + }; + +export default connect(mapStateToProps,mapDispatchToProps)(INPUT); \ No newline at end of file diff --git a/frontend/syntaxmeets/src/components/SyntaxEditor/CodeOutput.js b/frontend/syntaxmeets/src/components/SyntaxEditor/CodeOutput.js new file mode 100644 index 000000000..f5517168d --- /dev/null +++ b/frontend/syntaxmeets/src/components/SyntaxEditor/CodeOutput.js @@ -0,0 +1,34 @@ +import React from "react"; +import AceEditor from "react-ace"; +import { connect } from "react-redux"; + +const OUTPUT = (props) => { + + return ( + + ); + }; + + + const mapStateToProps = (state) => { + return { + codeOutput: state.EDITOR.codeOutput, + fontSize: state.EDITOR.fontSize, + }; + }; +export default connect(mapStateToProps)(OUTPUT); \ No newline at end of file diff --git a/frontend/syntaxmeets/src/components/SyntaxEditor/SyntaxEditor.js b/frontend/syntaxmeets/src/components/SyntaxEditor/SyntaxEditor.js index 30b5b49b5..6ce285705 100644 --- a/frontend/syntaxmeets/src/components/SyntaxEditor/SyntaxEditor.js +++ b/frontend/syntaxmeets/src/components/SyntaxEditor/SyntaxEditor.js @@ -25,7 +25,6 @@ import Alert from "@material-ui/lab/Alert"; import localClasses from "./SyntaxEditor.module.css"; import { languages, - defaultValue, langMode, LangOptions, langId, @@ -34,8 +33,11 @@ import { import ShareIcon from "@material-ui/icons/Share"; import PlayArrowIcon from "@material-ui/icons/PlayArrow"; import FileCopyIcon from "@material-ui/icons/FileCopy"; +import INPUT from "./CodeInput"; +import OUTPUT from "./CodeOutput"; import copy from "copy-to-clipboard"; - +import { connect } from "react-redux"; +import * as actions from "../../store/actions/editorActions.js"; //extracting all the languages recquired languages.forEach((lang) => { require(`ace-builds/src-noconflict/mode-${lang}`); @@ -45,8 +47,6 @@ languages.forEach((lang) => { //extracting themes themes.forEach((theme) => require(`ace-builds/src-noconflict/theme-${theme}`)); -const axios = require("axios"); - const useStyles = makeStyles((mutheme) => ({ formControl: { margin: mutheme.spacing(1), @@ -56,53 +56,27 @@ const useStyles = makeStyles((mutheme) => ({ marginTop: mutheme.spacing(2), }, })); - -const ICE = (props) => { - const handleIChange = (newValue) => { - props.onInputChange(newValue); - }; - - return ( - - ); -}; const SyntaxEditor = (props) => { - const [value, setValue] = useState(defaultValue); - const [currLang, setCurrLang] = useState("C++"); const [theme, setTheme] = useState("monokai"); - const [fontSize, setFontSize] = useState(16); - const [autoCompletion, setautoCompletion] = useState(true); - const [codeInput, setCodeInput] = useState(""); - const [codeOutput, setCodeOutput] = useState(""); - const [isCompiling, setIsCompiling] = useState(false); - const [isError, setIsError] = useState(false); - const [codeError, setCodeError] = useState(""); const [popup, setPopup] = useState(false); + // This will resend a message to update the code of the newly joined user useEffect(() => { + let UpdatedCode = props.code; if (props.previousUser.id === props.id) { - props.socket.emit("message", value); + props.socket.emit("message", UpdatedCode); } }, [props.previousUser]); - var codeToken = 0; const classes = useStyles(); useEffect(() => { props.socket.on("message", (newValue) => { - setValue(newValue); + props.setCode(newValue); }); }, []); const handleChange = (newValue) => { - setValue(newValue); + props.setCode(newValue); props.socket.emit("message", newValue); }; @@ -111,66 +85,8 @@ const SyntaxEditor = (props) => { setPopup(true); }; - const handleInputChange = (newInput) => { - setCodeInput(newInput); - }; - - const handleCodeRun = async () => { - setIsCompiling(true); - - let options = { - method: "POST", - url: "https://judge0-ce.p.rapidapi.com/submissions", - headers: { - "content-type": "application/json", - "x-rapidapi-key": process.env.REACT_APP_ONLINE_JUDGE_API, - "x-rapidapi-host": "judge0-ce.p.rapidapi.com", - }, - data: { - language_id: langId[currLang], - source_code: value, - stdin: codeInput, - }, - }; - - await axios - .request(options) - .then(function (response) { - console.log("compile: ", response); - codeToken = response.data.token; - }) - .catch(function (error) { - console.error(error); - }); - - const delay = (ms) => new Promise((res) => setTimeout(res, ms)); - await delay(7000); - - options = { - method: "GET", - url: "https://judge0-ce.p.rapidapi.com/submissions/" + codeToken, - headers: { - "x-rapidapi-key": process.env.REACT_APP_ONLINE_JUDGE_API, - "x-rapidapi-host": "judge0-ce.p.rapidapi.com", - }, - }; - await axios - .request(options) - .then(function (response) { - if (response.data.stderr !== null) { - setIsCompiling(false); - setCodeError(response.data.stderr); - setIsError(true); - } else { - setCodeOutput(response.data.stdout); - setIsCompiling(false); - } - }) - .catch(function (error) { - setIsCompiling(false); - setCodeError("Compilation Error: " + error.response.data.error); - setIsError(true); - }); + const handleCodeRun = () => { + props.executeCode(langId[props.currLang], props.code, props.codeInput); }; const IONavbar = (props) => { @@ -197,7 +113,7 @@ const SyntaxEditor = (props) => { return ( - + Compiling ...
@@ -208,12 +124,12 @@ const SyntaxEditor = (props) => {
- + Oops Error Occured - {codeError} + {props.codeError}
{ control={ { - setautoCompletion(!autoCompletion); + props.setAutoCompletion(!props.autoCompletion); }} name="EnableAutoCompletion" /> @@ -386,7 +302,7 @@ const SyntaxEditor = (props) => { + + + Date: Sun, 11 Apr 2021 00:50:57 +0530 Subject: [PATCH 24/61] Language gets changed on uploading --- .../syntaxmeets/src/components/SyntaxEditor/SyntaxEditor.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frontend/syntaxmeets/src/components/SyntaxEditor/SyntaxEditor.js b/frontend/syntaxmeets/src/components/SyntaxEditor/SyntaxEditor.js index 40d61d2b5..0c9de379f 100644 --- a/frontend/syntaxmeets/src/components/SyntaxEditor/SyntaxEditor.js +++ b/frontend/syntaxmeets/src/components/SyntaxEditor/SyntaxEditor.js @@ -59,6 +59,7 @@ const useStyles = makeStyles((mutheme) => ({ })); const validExtensions = [".c", ".cpp", ".java", ".js", ".ts", ".clj", ".cljs", ".cs", ".cbl", ".cob", ".cpy", ".erl", ".hrl", ".go", ".py", ".f90", ".f95", ".f03", ".txt", ".groovy", ".gvy", ".gy", ".gsh", ".kt", ".kts", ".ktm", ".php", ".r", ".rb", ".sql", ".swift"]; +const langExtensionDict = {".c": "C", ".cpp": "C++", ".java": "JAVA", ".js": "JavaScript", ".ts": "TypeScript", ".clj": "Closure", ".cljs": "Closure", ".cs": "C#", ".cbl": "COBOL", ".cob": "COBOL", ".cpy": "COBOL", ".erl": "Erlang", ".hrl": "Erlang", ".go": "Go", ".py": "Python", ".f90": "FortRan", ".f95": "FortRan", ".f03": "FortRan", ".txt": "", ".groovy": "Groovy", ".gvy": "Groovy", ".gy": "Groovy", ".gshgsh": "Groovy", ".kt": "Kotlin", ".kts": "Kotlin", ".ktm": "Kotlin", ".php": "PHP", ".r": "R", ".rb": "Ruby", ".sql": "SQL", ".swift": "Swift" }; const SyntaxEditor = (props) => { const [theme, setTheme] = useState("monokai"); @@ -152,6 +153,9 @@ const SyntaxEditor = (props) => { } handleChange(e.target.result); + const fileName = file.name; + const ext = `.${fileName.split(".")[1]}`; + props.setLanguage(langExtensionDict[ext]); }; reader.onerror = function (e) { From 71f097676170821f28ee73d03e239d326f340567 Mon Sep 17 00:00:00 2001 From: Dhruv Kothari Date: Sun, 11 Apr 2021 16:42:26 +0530 Subject: [PATCH 25/61] Add Validations --- frontend/syntaxmeets/src/components/Home/Home.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/frontend/syntaxmeets/src/components/Home/Home.js b/frontend/syntaxmeets/src/components/Home/Home.js index a9f45b537..5b503fbdd 100644 --- a/frontend/syntaxmeets/src/components/Home/Home.js +++ b/frontend/syntaxmeets/src/components/Home/Home.js @@ -148,7 +148,10 @@ const Home = (props) => { onKeyPress={(ev) => { if(ev.key === 'Enter') { ev.preventDefault(); - createRoomButton.current.click(); + if(!disabledName) + { + createRoomButton.current.click(); + } } }} /> @@ -230,7 +233,10 @@ const Home = (props) => { onKeyPress={(ev) => { if(ev.key === 'Enter') { ev.preventDefault(); - joinRoomButton.current.click(); + if(!disabledName && !disabledRoomId) + { + joinRoomButton.current.click(); + } } }} fullWidth From baab372f2eff689e70f7575537eba782817c6880 Mon Sep 17 00:00:00 2001 From: Amaan Ahmad Date: Sun, 11 Apr 2021 19:34:49 +0530 Subject: [PATCH 26/61] ButtonGroup added --- .../components/SyntaxEditor/SyntaxEditor.js | 83 ++++++++++--------- 1 file changed, 44 insertions(+), 39 deletions(-) diff --git a/frontend/syntaxmeets/src/components/SyntaxEditor/SyntaxEditor.js b/frontend/syntaxmeets/src/components/SyntaxEditor/SyntaxEditor.js index 8b4c0732e..4f6e7ccb4 100644 --- a/frontend/syntaxmeets/src/components/SyntaxEditor/SyntaxEditor.js +++ b/frontend/syntaxmeets/src/components/SyntaxEditor/SyntaxEditor.js @@ -19,6 +19,7 @@ import { DialogTitle, DialogActions, Snackbar, + ButtonGroup, } from "@material-ui/core"; import Grid from "@material-ui/core/Grid"; import Alert from "@material-ui/lab/Alert"; @@ -397,7 +398,7 @@ const SyntaxEditor = (props) => { } label={ - Enable Auto-complete + Auto-complete } /> @@ -408,47 +409,51 @@ const SyntaxEditor = (props) => { hidden accept=".c, .cpp, .java, .js, .ts, .clj, .cljs, .cs, .cbl, .cob, .cpy, .erl, .hrl, .go, .py, .f90, .f95, .f03, .txt, .groovy, .gvy, .gy, .gsh, .kt, .kts, .ktm, .php, .r, .rb, .sql, .swift" /> - - - + + + + + From 39f6df20c011bb20f3c8a13dbf289db2fbd9fb0f Mon Sep 17 00:00:00 2001 From: AmeyaJain-25 Date: Tue, 13 Apr 2021 00:18:37 +0530 Subject: [PATCH 31/61] Snackbar created --- .../components/SyntaxEditor/SyntaxEditor.js | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/frontend/syntaxmeets/src/components/SyntaxEditor/SyntaxEditor.js b/frontend/syntaxmeets/src/components/SyntaxEditor/SyntaxEditor.js index 4f6e7ccb4..c883b8758 100644 --- a/frontend/syntaxmeets/src/components/SyntaxEditor/SyntaxEditor.js +++ b/frontend/syntaxmeets/src/components/SyntaxEditor/SyntaxEditor.js @@ -98,6 +98,8 @@ const validExtensions = [ const SyntaxEditor = (props) => { const [theme, setTheme] = useState("monokai"); const [popup, setPopup] = useState(false); + const [filePopup, setFilePopup] = useState(false); + const [fileHandleError, setFileHandleError] = useState(""); // This will resend a message to update the code of the newly joined user useEffect(() => { @@ -194,12 +196,14 @@ const SyntaxEditor = (props) => { reader.onload = function (e) { if (file.size > 10000) { - alert("Error: File size greater than 10KB!"); + setFilePopup(true); + setFileHandleError("Error: File size greater than 10KB!"); return; } if (!checkValidFileExtension(file)) { - alert("Error: Not a Valid File Extension!"); + setFilePopup(true); + setFileHandleError("Error: Not a Valid File Extension!"); return; } @@ -258,6 +262,23 @@ const SyntaxEditor = (props) => { Code Copied Sucessfully + { + setFilePopup(false); + }} + > + { + setFilePopup(false); + }} + severity="error" + variant="filled" + > + {fileHandleError} + +
{ id="upload" onChange={() => handleFileChange()} hidden - accept=".c, .cpp, .java, .js, .ts, .clj, .cljs, .cs, .cbl, .cob, .cpy, .erl, .hrl, .go, .py, .f90, .f95, .f03, .txt, .groovy, .gvy, .gy, .gsh, .kt, .kts, .ktm, .php, .r, .rb, .sql, .swift" + // accept=".c, .cpp, .java, .js, .ts, .clj, .cljs, .cs, .cbl, .cob, .cpy, .erl, .hrl, .go, .py, .f90, .f95, .f03, .txt, .groovy, .gvy, .gy, .gsh, .kt, .kts, .ktm, .php, .r, .rb, .sql, .swift" /> Date: Tue, 13 Apr 2021 12:52:30 +0530 Subject: [PATCH 32/61] =?UTF-8?q?{{=20=E2=9A=92=EF=B8=8F[Fix]:=20Scrollbar?= =?UTF-8?q?=20Customized=20}}?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit {{ Scrollbar-styles added }} --- frontend/syntaxmeets/src/App.css | 25 ++- .../components/SyntaxChat/ParticipantsList.js | 185 +++++++++--------- 2 files changed, 115 insertions(+), 95 deletions(-) diff --git a/frontend/syntaxmeets/src/App.css b/frontend/syntaxmeets/src/App.css index 6d0652c5a..c1f9e7707 100644 --- a/frontend/syntaxmeets/src/App.css +++ b/frontend/syntaxmeets/src/App.css @@ -1,5 +1,24 @@ @import "assets/css/sx-chat.css"; -.ace_print-margin{ - display: none; -} \ No newline at end of file +.ace_print-margin { + display: none; +} + +/* scroll--bar styles */ +::-webkit-scrollbar { + width: 15px; + height: 4px; +} + +::-webkit-scrollbar-track { + background: #000a29; + border-left: 5px solid #000a29; + border-right: 5px solid #000a29; +} + +::-webkit-scrollbar-thumb { + background-image: linear-gradient(#ffd500, #000a29); + border-left: 5px solid #000a29; + border-right: 5px solid #000a29; + border-radius: 30px; +} diff --git a/frontend/syntaxmeets/src/components/SyntaxChat/ParticipantsList.js b/frontend/syntaxmeets/src/components/SyntaxChat/ParticipantsList.js index dde7841b6..3b42dbcb3 100644 --- a/frontend/syntaxmeets/src/components/SyntaxChat/ParticipantsList.js +++ b/frontend/syntaxmeets/src/components/SyntaxChat/ParticipantsList.js @@ -1,108 +1,109 @@ import React, { useState } from "react"; import GroupIcon from "@material-ui/icons/Group"; import { - ListItem, - ListItemText, - ListItemAvatar, - Avatar, - Button, - Drawer, - List, + ListItem, + ListItemText, + ListItemAvatar, + Avatar, + Button, + Drawer, + List, } from "@material-ui/core"; import { makeStyles } from "@material-ui/core/styles"; -import CloseSharpIcon from '@material-ui/icons/CloseSharp'; +import CloseSharpIcon from "@material-ui/icons/CloseSharp"; import { connect } from "react-redux"; const useStyles = makeStyles({ - list: { - width: 400, - }, - fullList: { - width: "auto", - }, + list: { + width: 400, + }, + fullList: { + width: "auto", + }, }); -const nameGenerator = (name) => - (name[0][0] + (name.length > 1 ? name[1][0] : "")).toUpperCase(); +const nameGenerator = name => + (name[0][0] + (name.length > 1 ? name[1][0] : "")).toUpperCase(); function ParticipantsList(props) { - const classes = useStyles(); - const { users } = props; - const [openList, setOpenList] = useState(false); + const classes = useStyles(); + const { users } = props; + const [openList, setOpenList] = useState(false); - const renderParticipants = () => { - return Object.keys(users).map((elem) => { - const name = users[elem]; - return ( - <> - - - - {nameGenerator(name.split(" "))} - - - - - - ); - }); - }; - return ( -
- - setOpenList(false)} - > - setOpenList(false)} /> -
- {renderParticipants()} -
-
-
- ); + const renderParticipants = () => { + return Object.keys(users).map(elem => { + const name = users[elem]; + return ( + <> + + + + {nameGenerator(name.split(" "))} + + + + + + ); + }); + }; + return ( +
+ + setOpenList(false)} + > + setOpenList(false)} + /> +
+ {renderParticipants()} +
+
+
+ ); } -const mapStateToProps = (state) => { - return { - users: state.ROOM.users, - }; +const mapStateToProps = state => { + return { + users: state.ROOM.users, + }; }; export default connect(mapStateToProps, null)(ParticipantsList); - From 4aa14bb7255a523216e9360729c420f81d463e74 Mon Sep 17 00:00:00 2001 From: Aayush Jain Date: Wed, 14 Apr 2021 13:33:42 +0530 Subject: [PATCH 33/61] =?UTF-8?q?=E2=9A=92=EF=B8=8F[Fix]:=20About=20Creato?= =?UTF-8?q?rs=20socials=20css?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../syntaxmeets/src/components/About/Card/MediaCard.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/frontend/syntaxmeets/src/components/About/Card/MediaCard.js b/frontend/syntaxmeets/src/components/About/Card/MediaCard.js index 966a1191a..73bdf0107 100644 --- a/frontend/syntaxmeets/src/components/About/Card/MediaCard.js +++ b/frontend/syntaxmeets/src/components/About/Card/MediaCard.js @@ -44,11 +44,11 @@ const MediaCard = (props) => {
     - {window.open(props.github)}} />           - {window.open(props.twitter)}}/>           - {window.open(props.linkedin)}}/>           - {window.open(props.gmail)}}/>           - {window.open(props.insta)}}/> + {window.open(props.github)}} />           + {window.open(props.twitter)}}/>           + {window.open(props.linkedin)}}/>           + {window.open(props.gmail)}}/>           + {window.open(props.insta)}}/>
From 2292741a854eaab81e447e31b20f61831b6fba70 Mon Sep 17 00:00:00 2001 From: simran2607 Date: Wed, 14 Apr 2021 13:38:54 +0530 Subject: [PATCH 34/61] reconnect-user-on-refresh --- .../syntaxmeets/src/components/Home/Home.js | 100 ++---------------- 1 file changed, 11 insertions(+), 89 deletions(-) diff --git a/frontend/syntaxmeets/src/components/Home/Home.js b/frontend/syntaxmeets/src/components/Home/Home.js index 70da88ace..e287418c0 100644 --- a/frontend/syntaxmeets/src/components/Home/Home.js +++ b/frontend/syntaxmeets/src/components/Home/Home.js @@ -9,32 +9,12 @@ import { Link } from "react-router-dom"; import SkyLight from "react-skylight"; import PropTypes from "prop-types"; import { withStyles } from "@material-ui/core/styles"; - -import MeetingRoomIcon from '@material-ui/icons/MeetingRoom'; -import GroupAddIcon from '@material-ui/icons/GroupAdd'; - -function generateRoomId() { - var tempId = ""; - var characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - var charactersLength = characters.length; - for (var i = 0; i < 12; i++) { - tempId += characters.charAt(Math.floor(Math.random() * charactersLength)); - if ((i + 1) % 4 === 0 && i !== 11) { - tempId += "-"; - } - } - - return tempId; -} - import MeetingRoomIcon from "@material-ui/icons/MeetingRoom"; import GroupAddIcon from "@material-ui/icons/GroupAdd"; import { connect } from "react-redux"; import { validateRoomID } from '../../util/util.js' import * as actions from "../../store/actions/roomActions.js"; - - const styles = { input: { color: "#000", @@ -53,7 +33,6 @@ const Home = (props) => { props.reset(); },[]); - const roomModal = { backgroundImage: "linear-gradient(to top, #d6d4ee, #e1dff2, #ebe9f6, #f5f4fb, #ffffff)", @@ -169,40 +148,6 @@ const Home = (props) => {

- - - { - localStorage.setItem('roomId',roomId); - localStorage.setItem('name',name); - sessionStorage.setItem('isconnected',true); - } - } - > - Create Room - - - - - } - { to={{ pathname: props.joinRoomId, }} + onClick={()=>{ + localStorage.setItem('roomId',props.joinRoomId); + localStorage.setItem('name',props.name); + sessionStorage.setItem('isconnected',true); + }} > Create Room @@ -236,7 +186,6 @@ const Home = (props) => { marginBottom: "10px", fontSize: "2vh", }} - > Enter Your Name
@@ -289,37 +238,6 @@ const Home = (props) => {

- - - { - localStorage.setItem('roomId',joinRoomId) - localStorage.setItem('name',name) - sessionStorage.setItem('isconnected',true) - } - - } - > - Join a Room - - - - - - { to={{ pathname: props.joinRoomId, }} + onClick={ ()=>{ + localStorage.setItem('roomId',props.joinRoomId) + localStorage.setItem('name',props.name) + sessionStorage.setItem('isconnected',true); + }} > Join a Room - @@ -371,4 +293,4 @@ const mapDispatchToProps = (dispatch) => { export default connect( mapStateToProps, mapDispatchToProps -)(withStyles(styles)(Home)); +)(withStyles(styles)(Home)); \ No newline at end of file From e19fe47c0fb32fa83e6e37d413ed8d554d76cb2f Mon Sep 17 00:00:00 2001 From: simran2607 Date: Wed, 14 Apr 2021 13:40:05 +0530 Subject: [PATCH 35/61] reconnect-user-on-refresh --- .../src/components/SyntaxChat/SyntaxChat.js | 47 +++------- .../components/SyntaxEditor/SyntaxEditor.js | 13 +-- .../src/components/SyntaxRoom/SyntaxRoom.js | 90 ++++++------------- 3 files changed, 42 insertions(+), 108 deletions(-) diff --git a/frontend/syntaxmeets/src/components/SyntaxChat/SyntaxChat.js b/frontend/syntaxmeets/src/components/SyntaxChat/SyntaxChat.js index 2d3064b48..3ae545c60 100644 --- a/frontend/syntaxmeets/src/components/SyntaxChat/SyntaxChat.js +++ b/frontend/syntaxmeets/src/components/SyntaxChat/SyntaxChat.js @@ -1,9 +1,6 @@ import React, { useState, useEffect, useRef } from "react"; import { makeStyles } from "@material-ui/core/styles"; - - import InsertEmoticonIcon from "@material-ui/icons/InsertEmoticon"; - import { Drawer, Button, @@ -37,36 +34,21 @@ const SyntaxChat = (props) => { const [openDrawer, setopenDrawer] = useState(false); const handleMessageSubmit = () => { - - - if (localStorage.getItem('flag') && sessionStorage.getItem('isconnected')) { - if (message === "") return; + if(localStorage.getItem('flag') && sessionStorage.getItem('isconnected')){ + if (props.message === "") return; + SetEmojiPicker(false); let data = { name: localStorage.getItem('name'), roomId: localStorage.getItem('roomId'), - message: message, + message: props.message, }; props.socket.emit("chatmessage", data); - setMessages((messages) => [...messages, data]); - setMCount(mCount + 1); - setMessage(""); - } - else { - if (message === "") return; - let data = { - name: props.name, - roomId: props.roomId, - message: message, - }; - props.socket.emit("chatmessage", data); - setMessages((messages) => [...messages, data]); - setMCount(mCount + 1); - setMessage(""); + + props.setMessages(data); + props.setMessage(""); } - - + else{ if (props.message === "") return; - SetEmojiPicker(false); let data = { name: props.name, @@ -74,19 +56,12 @@ const SyntaxChat = (props) => { message: props.message, }; props.socket.emit("chatmessage", data); - - setMessages((messages) => [...messages, data]); - setMCount(mCount + 1); - setMessage(""); - - props.setMessages(data); props.setMessage(""); - + } }; - useEffect(() => { props.socket.on("chatmessage", (data) => { @@ -222,6 +197,8 @@ const SyntaxChat = (props) => { style={{ display: "flex", alignSelf: "center", + marginLeft: "5px", + marginTop: "10px", cursor: "pointer", }} alignContent="center" @@ -306,4 +283,4 @@ const mapDispatchToProps = (dispatch) => { whoIsTyping: (user) => dispatch(actions.whoIsTyping(user)) } } -export default connect(mapStateToProps,mapDispatchToProps)(SyntaxChat); +export default connect(mapStateToProps,mapDispatchToProps)(SyntaxChat); \ No newline at end of file diff --git a/frontend/syntaxmeets/src/components/SyntaxEditor/SyntaxEditor.js b/frontend/syntaxmeets/src/components/SyntaxEditor/SyntaxEditor.js index f830e1fae..5f3ea987e 100644 --- a/frontend/syntaxmeets/src/components/SyntaxEditor/SyntaxEditor.js +++ b/frontend/syntaxmeets/src/components/SyntaxEditor/SyntaxEditor.js @@ -72,7 +72,7 @@ const SyntaxEditor = (props) => { } else if(sessionStorage.getItem('isconnected')) { - setValue(sessionStorage.getItem('code')); + props.setCode(sessionStorage.getItem('code')); //console.log("1"); } }, [props.previousUser]); @@ -80,22 +80,13 @@ const SyntaxEditor = (props) => { const classes = useStyles(); useEffect(() => { props.socket.on("message", (newValue) => { - - setValue(newValue); - - props.setCode(newValue); - }); }, []); const handleChange = (newValue) => { - - setValue(newValue); - sessionStorage.setItem('code',newValue); - props.setCode(newValue); - + sessionStorage.setItem('code',newValue); props.socket.emit("message", newValue); }; diff --git a/frontend/syntaxmeets/src/components/SyntaxRoom/SyntaxRoom.js b/frontend/syntaxmeets/src/components/SyntaxRoom/SyntaxRoom.js index fd397f97f..ff10e5204 100644 --- a/frontend/syntaxmeets/src/components/SyntaxRoom/SyntaxRoom.js +++ b/frontend/syntaxmeets/src/components/SyntaxRoom/SyntaxRoom.js @@ -1,4 +1,4 @@ -import React, { Fragment, useState, useEffect} from "react"; +import React, { Fragment, useEffect } from "react"; import Navbar from "../Navbar/Navbar"; import { Grid } from "@material-ui/core"; import SyntaxEditor from "../SyntaxEditor/SyntaxEditor"; @@ -11,64 +11,36 @@ import { connect } from "react-redux"; import * as actions from "../../store/actions/roomActions.js"; import * as UIactions from "../../store/actions/uiActions.js"; - -var connectionOptions = { - transport: ["websocket"], -}; -const socket = io.connect( - process.env.REACT_APP_SYNTAXMEETS_BACKEND_API, - connectionOptions -); +// use following in case of localhost +//import io from "socket.io-client"; // to use for localhost -//var socket = io.connect("http://localhost:4000",connectionOptions); - -const Alert = (props) => { - return ; -}; - - +//var socket = io.connect("http://localhost:4000"); const SyntaxRoom = (props) => { - - let paramsRoom = useParams().roomId; - const [roomId] = useState(paramsRoom); - const [name] = useState(props.location.name); - const [goToHome, setGoToHome] = useState(false); - const [open, setOpen] = useState(true); - const [users, setUsers] = useState({}); - const [userDisconnect, setUserDisconnect] = useState(false); - const [userJoinedName, setUserJoinedName] = useState(); - const [userLeftName, setUserLeftName] = useState(); - const [id, setId] = useState(); // Stores the userid default 1 and then increases and decreases according to the users. - const [previousUser, setPreviousUser] = useState({}); //Store the id of an already existing user , so this user will emit the code when a new user joins - const roomId = props.roomId; - useEffect(() => { - // fetch the list of active rooms from backend - var roomsList = []; - const url = `${process.env.REACT_APP_SYNTAXMEETS_BACKEND_API}/rooms`; - fetch(url) - .then(res => { - return res.json(); - }) - .then(rooms => { - console.log(rooms); - for (let i = 0; i < rooms.length; i++) - roomsList.push(rooms[i]); - }); - - console.log(roomsList); // If disconnected then connect again to server - // Trigerred when user leaves a room // Trigerred when user leaves a room socket.on("disconnect", (reason) => { - - + props.reset(); socket.connect(); }); - - var roomid = localStorage.getItem('roomId'); + }); + useEffect(() => { + // fetch the list of active rooms from backend + var roomsList = []; + const url = `${process.env.REACT_APP_SYNTAXMEETS_BACKEND_API}/rooms`; + fetch(url) + .then(res => { + return res.json(); + }) + .then(rooms => { + console.log(rooms); + for (let i = 0; i < rooms.length; i++) + roomsList.push(rooms[i]); + }); + + var roomid = localStorage.getItem('roomId'); if (props.location.name === undefined || props.location.name === "") { // If user disconnects and want to connect back to same room @@ -87,19 +59,11 @@ const SyntaxRoom = (props) => { else { // direct back to home alert("Please Enter your name"); - setGoToHome(true); + props.reset(); + props.setGoToHome(true); } - - props.reset(); - socket.connect(); - }); - if (props.Username === undefined || props.Username === "") { - alert("Please Enter your name"); - props.reset(); - props.setGoToHome(true); - } - + if (validateRoomID(roomId) === false || props.location.pathname === "") { alert("Invalid Room Id"); props.reset(); @@ -176,7 +140,7 @@ const SyntaxRoom = (props) => {