Skip to content

Commit

Permalink
[mirotalksfu] - #22 add real-time polls
Browse files Browse the repository at this point in the history
  • Loading branch information
miroslavpejic85 committed Jul 18, 2024
1 parent 55c7da4 commit e578553
Show file tree
Hide file tree
Showing 11 changed files with 589 additions and 6 deletions.
23 changes: 23 additions & 0 deletions app/src/Room.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ module.exports = class Room {
this.rtmpFileStreamer = null;
this.rtmpUrlStreamer = null;
this.rtmp = config.server.rtmp || false;

// Polls
this.polls = [];
}

// ####################################################
Expand All @@ -87,10 +90,30 @@ module.exports = class Room {
survey: this.survey,
redirect: this.redirect,
videoAIEnabled: this.videoAIEnabled,
thereIsPolls: this.thereIsPolls(),
peers: JSON.stringify([...this.peers]),
};
}

// ##############################################
// POLLS
// ##############################################

thereIsPolls() {
return this.polls.length > 0;
}

getPolls() {
return this.polls;
}

convertPolls(polls) {
return polls.map((poll) => {
const voters = poll.voters ? Object.fromEntries(poll.voters.entries()) : {};
return { ...poll, voters };
});
}

// ##############################################
// RTMP from FILE
// ##############################################
Expand Down
93 changes: 92 additions & 1 deletion app/src/Server.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ dependencies: {
* @license For commercial or closed source, contact us at [email protected] or purchase directly via CodeCanyon
* @license CodeCanyon: https://codecanyon.net/item/mirotalk-sfu-webrtc-realtime-video-conferences/40769970
* @author Miroslav Pejic - [email protected]
* @version 1.4.99
* @version 1.5.10
*
*/

Expand Down Expand Up @@ -2385,6 +2385,97 @@ function startServer() {
log.debug('endRTMPfromURL - rtmpUrlStreamsCount ---->', rtmpUrlStreamsCount);
});

socket.on('createPoll', (dataObject) => {
if (!roomList.has(socket.room_id)) return;

const data = checkXSS(dataObject);

const { question, options } = data;

const room = roomList.get(socket.room_id);

const newPoll = {
question: question,
options: options,
voters: new Map(),
};

const roomPolls = room.getPolls();

roomPolls.push(newPoll);
room.sendToAll('updatePolls', room.convertPolls(roomPolls));
log.debug('[Poll] createPoll', roomPolls);
});

socket.on('vote', (dataObject) => {
if (!roomList.has(socket.room_id)) return;

const data = checkXSS(dataObject);

const room = roomList.get(socket.room_id);

const roomPolls = room.getPolls();

const poll = roomPolls[data.pollIndex];
if (poll) {
const peer_name = getPeerName(room, false) || socket.id;
poll.voters.set(peer_name, data.option);
room.sendToAll('updatePolls', room.convertPolls(roomPolls));
log.debug('[Poll] vote', roomPolls);
}
});

socket.on('updatePoll', () => {
if (!roomList.has(socket.room_id)) return;

const room = roomList.get(socket.room_id);

const roomPolls = room.getPolls();

if (roomPolls.length > 0) {
room.sendToAll('updatePolls', room.convertPolls(roomPolls));
log.debug('[Poll] updatePoll', roomPolls);
}
});

socket.on('editPoll', (dataObject) => {
if (!roomList.has(socket.room_id)) return;

const data = checkXSS(dataObject);

const { index, question, options } = data;

const room = roomList.get(socket.room_id);

const roomPolls = room.getPolls();

if (roomPolls[index]) {
roomPolls[index].question = question;
roomPolls[index].options = options;
room.sendToAll('updatePolls', roomPolls);
log.debug('[Poll] editPoll', roomPolls);
}
});

socket.on('deletePoll', async (data) => {
if (!roomList.has(socket.room_id)) return;

const { index, peer_name, peer_uuid } = checkXSS(data);

const isPresenter = await isPeerPresenter(socket.room_id, socket.id, peer_name, peer_uuid);

if (!isPresenter) return;

const room = roomList.get(socket.room_id);

const roomPolls = room.getPolls();

if (roomPolls[index]) {
roomPolls.splice(index, 1);
room.sendToAll('updatePolls', roomPolls);
}
});

socket.on('disconnect', async () => {
if (!roomList.has(socket.room_id)) return;

Expand Down
1 change: 1 addition & 0 deletions app/src/config.template.js
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,7 @@ module.exports = {
startScreenButton: true,
swapCameraButton: true,
chatButton: true,
pollButton: true,
raiseHandButton: true,
transcriptionButton: true,
whiteboardButton: true,
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "mirotalksfu",
"version": "1.4.99",
"version": "1.5.10",
"description": "WebRTC SFU browser-based video calls",
"main": "Server.js",
"scripts": {
Expand Down Expand Up @@ -57,7 +57,7 @@
},
"dependencies": {
"@sentry/integrations": "7.114.0",
"@sentry/node": "8.17.0",
"@sentry/node": "8.18.0",
"axios": "^1.7.2",
"body-parser": "1.20.2",
"colors": "1.4.0",
Expand Down
167 changes: 167 additions & 0 deletions public/css/Polls.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
.pls-container {
z-index: 5;
position: absolute;
background: var(--body-bg);
padding: 20px;
border-radius: 8px;
border: var(--border);
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
width: 100%;
height: 100%;
max-width: 600px;
max-height: 600px;
overflow-x: hidden;
}

.poll-header {
display: inline-flex;
text-align: left;
margin-bottom: 20px;
width: 100%;
cursor: move;
}

.poll-creation {
margin-bottom: 20px;
max-height: 480px;
overflow: hidden;
}

.poll-h1,
.poll-h2,
.poll-h3 {
margin-top: 5px;
color: #fff !important;
}

.form {
display: flex;
flex-direction: column;
max-height: 500px;
overflow-x: hidden;
}

.form-group {
margin-bottom: 15px;
}

.form-group label {
margin-bottom: 15px;
}

.form label {
margin-bottom: 10px;
font-weight: bold;
color: #fff;
}

.form input {
padding: 10px;
border: var(--border);
border-radius: 4px;
width: 100%;
box-sizing: border-box;
}

.poll-btns {
display: flex;
gap: 10px;
margin-top: 15px;
margin-bottom: 15px;
}

.poll-btn {
padding: 10px 15px;
background: var(--body-bg);
color: #fff;
border: none;
border-radius: 4px;
cursor: pointer;
transition: background 0.3s;
}

.poll-btn:hover {
background: var(--btns-bg-color) !important;
color: #fff;
}

.del-btn {
padding: 10px 15px;
background: #dc3545;
color: #fff;
border: none;
border-radius: 4px;
cursor: pointer;
transition: background 0.3s;
}

.del-btn:hover {
background: #c82333;
color: #fff;
}

.polls-container {
margin-top: 20px;
}

.poll {
background: var(--body-bg);
padding: 15px;
margin-bottom: 20px;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}

.poll .options {
margin-top: 10px;
}

.poll .options div {
margin-bottom: 5px;
}

.poll ul {
list-style-type: none;
padding: 0;
margin-top: 10px;
}

.poll ul li {
background: var(--body-bg);
padding: 8px;
border: var(--border);
border-radius: 4px;
margin-bottom: 5px;
color: #fff;
}

.options input {
cursor: pointer;
}

.options label {
margin-left: 5px;
color: #fff;
}

.view-btn {
padding: 10px 15px;
background: var(--body-bg);
color: #fff;
border: none;
border-radius: 4px;
cursor: pointer;
transition: background 0.3s;
}

.view-btn:hover {
background: var(--btns-bg-color) !important;
color: #fff;
}

#pollCloseBtn {
position: absolute;
float: right;
right: 20px;
font-size: 1.6rem;
}
2 changes: 2 additions & 0 deletions public/css/Room.css
Original file line number Diff line number Diff line change
Expand Up @@ -1504,6 +1504,8 @@ z-index:
- 3 control buttons
- 4 whiteboard
- 5 chat group
- 5 polls
- 5 transcription
- 6 settings
- 7 participants/lobby
- 8 send receive progress
Expand Down
Loading

1 comment on commit e578553

@miroslavpejic85
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Real-time polls

mirotalk-sfu-real-time-polls

Please sign in to comment.