Added manual + synchornization check
This commit is contained in:
parent
16f06d331a
commit
797ec9dffc
@ -1,42 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
|
|
||||||
<title>Watch With Friends!</title>
|
|
||||||
<link rel="icon" href="/img/favicon.png">
|
|
||||||
<link rel="stylesheet" href="/css/styles.min.css">
|
|
||||||
<link rel="stylesheet" href="/css/styles.css">
|
|
||||||
<meta name="description" content="Watch with Friends!">
|
|
||||||
<meta name="author" content="Kacper Maj">
|
|
||||||
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/3.0.1/mustache.min.js"></script>
|
|
||||||
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>
|
|
||||||
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/qs/6.6.0/qs.min.js"></script>
|
|
||||||
<script defer src="/socket.io/socket.io.js"></script>
|
|
||||||
<script defer src="/js/chat.js"></script>
|
|
||||||
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div class="chat">
|
|
||||||
<div class="chat__sidebar">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="chat__main">
|
|
||||||
<div id="messages-container" class="chat__messages"> </div>
|
|
||||||
|
|
||||||
<div class="compose">
|
|
||||||
<form action="POST" id="sendMessForm">
|
|
||||||
<input placeholder="Write your message">
|
|
||||||
<button type="submit" id="formButton">Send</button>
|
|
||||||
</form>
|
|
||||||
<button id="sendLocation">Send location!</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -87,6 +87,7 @@ button:disabled {
|
|||||||
|
|
||||||
.chat {
|
.chat {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
visibility: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat__sidebar {
|
.chat__sidebar {
|
||||||
@ -110,7 +111,7 @@ button:disabled {
|
|||||||
top: 1vh;
|
top: 1vh;
|
||||||
width: 49%;
|
width: 49%;
|
||||||
height: 49%;
|
height: 49%;
|
||||||
z-index: 1;
|
z-index: 2;
|
||||||
/* margin-top: 5px; */
|
/* margin-top: 5px; */
|
||||||
/* margin-left: 5px; */
|
/* margin-left: 5px; */
|
||||||
}
|
}
|
||||||
@ -214,3 +215,46 @@ button:disabled {
|
|||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
color: #333333;
|
color: #333333;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The Modal (background) */
|
||||||
|
.modal {
|
||||||
|
display: block; /* Hidden by default */
|
||||||
|
position: fixed; /* Stay in place */
|
||||||
|
z-index: 1; /* Sit on top */
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 100%; /* Full width */
|
||||||
|
height: 100%; /* Full height */
|
||||||
|
overflow: auto; /* Enable scroll if needed */
|
||||||
|
background-color: rgb(72, 65, 138); /* Fallback color */
|
||||||
|
background-color: rgba(0, 0, 0, 0.616); /* Black w/ opacity */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Modal Content/Box */
|
||||||
|
.modal-content {
|
||||||
|
background-color: #333744;
|
||||||
|
margin: 10% auto; /* 15% from the top and centered */
|
||||||
|
border-radius: 7px;
|
||||||
|
padding: 25px;
|
||||||
|
color: #d1d1d1;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 100;
|
||||||
|
width: 60%; /* Could be more or less, depending on screen size */
|
||||||
|
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
|
||||||
|
text-align: justify;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The Close Button */
|
||||||
|
.close {
|
||||||
|
color: #aaa;
|
||||||
|
float: right;
|
||||||
|
font-size: 28px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close:hover,
|
||||||
|
.close:focus {
|
||||||
|
color: black;
|
||||||
|
text-decoration: none;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
@ -9,40 +9,11 @@ const messageContainer = document.querySelector('#messages-container');
|
|||||||
const sidebarContainer = document.querySelector('.chat__sidebar');
|
const sidebarContainer = document.querySelector('.chat__sidebar');
|
||||||
const changeVideoButton = document.querySelector('#changeVideo');
|
const changeVideoButton = document.querySelector('#changeVideo');
|
||||||
const syncVideosButton = document.querySelector('#syncVideos');
|
const syncVideosButton = document.querySelector('#syncVideos');
|
||||||
|
const chatBox = document.querySelector('.chat');
|
||||||
|
const modal = document.getElementById('myModal');
|
||||||
|
const span = document.getElementsByClassName('close')[0];
|
||||||
|
|
||||||
// TEMPLATES
|
// ###### YOUTUBE PLAYER ###### //
|
||||||
const sidebarTemplate = `<h2 class="room-title">{{room}}</h2>
|
|
||||||
<h3 class="list-title">Users</h3>
|
|
||||||
<ul class="users">
|
|
||||||
{{#users}}
|
|
||||||
<li>{{username}}</li>
|
|
||||||
{{/users}}
|
|
||||||
</ul>`;
|
|
||||||
|
|
||||||
const htmlTemplate = [
|
|
||||||
`<div class="message">
|
|
||||||
<p>
|
|
||||||
<span class="message__name"> {{user}} </span>
|
|
||||||
<span class="message__meta"> {{createdAt}} </span>
|
|
||||||
</p>
|
|
||||||
<p>{{string}}</p>
|
|
||||||
</div>`,
|
|
||||||
`<div class="message">
|
|
||||||
<p>
|
|
||||||
<span class="message__name"> {{user}} </span>
|
|
||||||
<span class="message__meta"> {{createdAt}} </span>
|
|
||||||
</p>
|
|
||||||
<p><a href="{{string}}">Link</a></p>
|
|
||||||
</div>`,
|
|
||||||
`<div class="message">
|
|
||||||
<p class="welcome-mess">{{string}}</p>
|
|
||||||
</div>`,
|
|
||||||
];
|
|
||||||
|
|
||||||
let message = '';
|
|
||||||
let videoId = '';
|
|
||||||
|
|
||||||
// YT PLAYER LOGIC
|
|
||||||
|
|
||||||
// Load the IFrame Player API code asynchronously.
|
// Load the IFrame Player API code asynchronously.
|
||||||
var tag = document.createElement('script');
|
var tag = document.createElement('script');
|
||||||
@ -70,50 +41,13 @@ function onYouTubePlayerAPIReady() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// ON PLAYER STATE DATA RECV
|
// Parsing room query
|
||||||
socket.on('onPlayerState', (data, time) => {
|
|
||||||
if (data === 1 || data === -1) {
|
const { username, room } = Qs.parse(location.search, {
|
||||||
// player.seekTo(time, true);
|
ignoreQueryPrefix: true,
|
||||||
player.playVideo();
|
|
||||||
} else if (data === 2) {
|
|
||||||
if (Math.abs(player.getCurrentTime() - time) > 2) {
|
|
||||||
player.seekTo(time, true);
|
|
||||||
player.playVideo();
|
|
||||||
} else {
|
|
||||||
player.pauseVideo();
|
|
||||||
}
|
|
||||||
} else if (data === 0) player.stopVideo();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const videoIdParse = (link) => {
|
// ###### SOCKETS LOGIC ###### //
|
||||||
if (link.includes('&ab_channel')) {
|
|
||||||
const substr = link.substring(
|
|
||||||
link.indexOf('v=') + 2,
|
|
||||||
link.indexOf('&')
|
|
||||||
);
|
|
||||||
return substr;
|
|
||||||
} else {
|
|
||||||
return link.slice(link.indexOf('v=') + 2);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// SYNC VIDEOS
|
|
||||||
syncVideosButton.addEventListener('click', () => {
|
|
||||||
console.log(player.getVideoUrl());
|
|
||||||
|
|
||||||
// If video is the same as starting video
|
|
||||||
if (
|
|
||||||
videoIdParse(player.getVideoUrl()) ===
|
|
||||||
videoIdParse(`https://youtube.com/watch?v=M7lc1UVf-VE`)
|
|
||||||
)
|
|
||||||
return alert(
|
|
||||||
'This is a default video, you cannot synchronize it. \nWrite a request for synchronization in the chat or paste your own link.'
|
|
||||||
);
|
|
||||||
|
|
||||||
const time = player.getCurrentTime();
|
|
||||||
const id = videoIdParse(player.getVideoUrl());
|
|
||||||
socket.emit('videoSync', time, id);
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on('videoSync', (time, id) => {
|
socket.on('videoSync', (time, id) => {
|
||||||
// console.log(time, id);
|
// console.log(time, id);
|
||||||
@ -121,47 +55,10 @@ socket.on('videoSync', (time, id) => {
|
|||||||
// player.seekTo(time);
|
// player.seekTo(time);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Change video
|
|
||||||
changeVideoButton.addEventListener('click', () => {
|
|
||||||
let link = input.value;
|
|
||||||
if (!link) return alert('You should pass the youtube link');
|
|
||||||
const videoId = videoIdParse(link);
|
|
||||||
socket.emit('changeVideo', videoId);
|
|
||||||
player.loadVideoById(`${videoId}`, 'large');
|
|
||||||
input.value = '';
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on('changeVideo', (videoId) => {
|
socket.on('changeVideo', (videoId) => {
|
||||||
player.loadVideoById(`${videoId}`, 'large');
|
player.loadVideoById(`${videoId}`, 'large');
|
||||||
});
|
});
|
||||||
|
|
||||||
const autoscroll = () => {
|
|
||||||
// New message elemnt
|
|
||||||
const newMessage = messageContainer.lastElementChild;
|
|
||||||
|
|
||||||
// Height of the new message
|
|
||||||
const newMessageStyles = getComputedStyle(newMessage);
|
|
||||||
const newMessageMargin = parseInt(newMessageStyles.marginBottom);
|
|
||||||
const newMessageHeight = newMessage.offsetHeight + newMessageMargin;
|
|
||||||
|
|
||||||
// Visible height
|
|
||||||
const visibleHeight = messageContainer.offsetHeight;
|
|
||||||
|
|
||||||
// Height of messages container
|
|
||||||
const containerHeight = messageContainer.scrollHeight;
|
|
||||||
|
|
||||||
// scrolloffset
|
|
||||||
const scrolloffset = messageContainer.scrollTop + visibleHeight + 120;
|
|
||||||
|
|
||||||
if (containerHeight - newMessageHeight <= scrolloffset) {
|
|
||||||
messageContainer.scrollTop = messageContainer.scrollHeight;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const { username, room } = Qs.parse(location.search, {
|
|
||||||
ignoreQueryPrefix: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on('message', (object) => {
|
socket.on('message', (object) => {
|
||||||
// console.log(object);
|
// console.log(object);
|
||||||
const string = object.text;
|
const string = object.text;
|
||||||
@ -195,12 +92,72 @@ socket.on('message', (object) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
socket.on('roomData', ({ room, users }) => {
|
||||||
|
const html = Mustache.render(sidebarTemplate, { room, users });
|
||||||
|
sidebarContainer.innerHTML = html;
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('videoData', (videoData) => {
|
||||||
|
player.loadVideoById(`${videoData}`, 'large');
|
||||||
|
});
|
||||||
|
|
||||||
|
// ON PLAYER STATE DATA RECV
|
||||||
|
socket.on('onPlayerState', (data, time) => {
|
||||||
|
if (data === 1 || data === -1) {
|
||||||
|
// player.seekTo(time, true);
|
||||||
|
player.playVideo();
|
||||||
|
} else if (data === 2) {
|
||||||
|
if (Math.abs(player.getCurrentTime() - time) > 2) {
|
||||||
|
player.seekTo(time, true);
|
||||||
|
player.playVideo();
|
||||||
|
} else {
|
||||||
|
player.pauseVideo();
|
||||||
|
}
|
||||||
|
} else if (data === 0) player.stopVideo();
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.emit('join', { username, room }, (error) => {
|
||||||
|
if (error) {
|
||||||
|
alert(error);
|
||||||
|
location.href = '/';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// ####### EVENT LISTENERS ####### //
|
||||||
|
|
||||||
|
// SYNC VIDEOS
|
||||||
|
syncVideosButton.addEventListener('click', () => {
|
||||||
|
console.log(player.getVideoUrl());
|
||||||
|
|
||||||
|
// If video is the same as starting video
|
||||||
|
if (
|
||||||
|
videoIdParse(player.getVideoUrl()) ===
|
||||||
|
videoIdParse(`https://youtube.com/watch?v=M7lc1UVf-VE`)
|
||||||
|
)
|
||||||
|
return alert(
|
||||||
|
'This is a default video, you cannot synchronize it. \nWrite a request for synchronization in the chat or paste your own link.'
|
||||||
|
);
|
||||||
|
|
||||||
|
const time = player.getCurrentTime();
|
||||||
|
const id = videoIdParse(player.getVideoUrl());
|
||||||
|
socket.emit('videoSync', time, id);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Change video
|
||||||
|
changeVideoButton.addEventListener('click', () => {
|
||||||
|
let link = input.value;
|
||||||
|
if (!link) return alert('You should pass the youtube link');
|
||||||
|
const videoId = videoIdParse(link);
|
||||||
|
socket.emit('changeVideo', videoId);
|
||||||
|
player.loadVideoById(`${videoId}`, 'large');
|
||||||
|
input.value = '';
|
||||||
|
});
|
||||||
|
|
||||||
|
// Form submission
|
||||||
form.addEventListener('submit', (e) => {
|
form.addEventListener('submit', (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
input.focus();
|
input.focus();
|
||||||
|
|
||||||
// Disable form
|
// Disable form
|
||||||
|
|
||||||
if (input.value === '') return;
|
if (input.value === '') return;
|
||||||
button.setAttribute('disabled', 'disabled');
|
button.setAttribute('disabled', 'disabled');
|
||||||
|
|
||||||
@ -208,7 +165,6 @@ form.addEventListener('submit', (e) => {
|
|||||||
// Re-enable form
|
// Re-enable form
|
||||||
button.removeAttribute('disabled');
|
button.removeAttribute('disabled');
|
||||||
if (error) return console.log(error);
|
if (error) return console.log(error);
|
||||||
// console.log('Message delivered');
|
|
||||||
input.value = '';
|
input.value = '';
|
||||||
input.focus();
|
input.focus();
|
||||||
});
|
});
|
||||||
@ -232,18 +188,81 @@ buttonLocation.addEventListener('click', (e) => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('roomData', ({ room, users }) => {
|
// ###### UTILITIES ######//
|
||||||
const html = Mustache.render(sidebarTemplate, { room, users });
|
|
||||||
sidebarContainer.innerHTML = html;
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on('videoData', (videoData) => {
|
// Auto scroll function
|
||||||
player.loadVideoById(`${videoData}`, 'large');
|
const autoscroll = () => {
|
||||||
});
|
// New message elemnt
|
||||||
|
const newMessage = messageContainer.lastElementChild;
|
||||||
|
|
||||||
socket.emit('join', { username, room }, (error) => {
|
// Height of the new message
|
||||||
if (error) {
|
const newMessageStyles = getComputedStyle(newMessage);
|
||||||
alert(error);
|
const newMessageMargin = parseInt(newMessageStyles.marginBottom);
|
||||||
location.href = '/';
|
const newMessageHeight = newMessage.offsetHeight + newMessageMargin;
|
||||||
|
|
||||||
|
// Visible height
|
||||||
|
const visibleHeight = messageContainer.offsetHeight;
|
||||||
|
|
||||||
|
// Height of messages container
|
||||||
|
const containerHeight = messageContainer.scrollHeight;
|
||||||
|
|
||||||
|
// scrolloffset
|
||||||
|
const scrolloffset = messageContainer.scrollTop + visibleHeight + 120;
|
||||||
|
|
||||||
|
if (containerHeight - newMessageHeight <= scrolloffset) {
|
||||||
|
messageContainer.scrollTop = messageContainer.scrollHeight;
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
|
// Parsing yt video
|
||||||
|
const videoIdParse = (link) => {
|
||||||
|
if (link.includes('&ab_channel')) {
|
||||||
|
const substr = link.substring(
|
||||||
|
link.indexOf('v=') + 2,
|
||||||
|
link.indexOf('&')
|
||||||
|
);
|
||||||
|
return substr;
|
||||||
|
} else {
|
||||||
|
return link.slice(link.indexOf('v=') + 2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
span.onclick = function () {
|
||||||
|
modal.style.display = 'none';
|
||||||
|
chatBox.style.visibility = 'visible';
|
||||||
|
};
|
||||||
|
window.onclick = function (event) {
|
||||||
|
if (event.target == modal) {
|
||||||
|
modal.style.display = 'none';
|
||||||
|
chatBox.style.visibility = 'visible';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// TEMPLATES
|
||||||
|
const sidebarTemplate = `<h2 class="room-title">{{room}}</h2>
|
||||||
|
<h3 class="list-title">Users</h3>
|
||||||
|
<ul class="users">
|
||||||
|
{{#users}}
|
||||||
|
<li>{{username}}</li>
|
||||||
|
{{/users}}
|
||||||
|
</ul>`;
|
||||||
|
|
||||||
|
const htmlTemplate = [
|
||||||
|
`<div class="message">
|
||||||
|
<p>
|
||||||
|
<span class="message__name"> {{user}} </span>
|
||||||
|
<span class="message__meta"> {{createdAt}} </span>
|
||||||
|
</p>
|
||||||
|
<p>{{string}}</p>
|
||||||
|
</div>`,
|
||||||
|
`<div class="message">
|
||||||
|
<p>
|
||||||
|
<span class="message__name"> {{user}} </span>
|
||||||
|
<span class="message__meta"> {{createdAt}} </span>
|
||||||
|
</p>
|
||||||
|
<p><a href="{{string}}">Link</a></p>
|
||||||
|
</div>`,
|
||||||
|
`<div class="message">
|
||||||
|
<p class="welcome-mess">{{string}}</p>
|
||||||
|
</div>`,
|
||||||
|
];
|
||||||
|
@ -19,6 +19,20 @@
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
<!-- The Modal -->
|
||||||
|
<div id="myModal" class="modal">
|
||||||
|
<!-- Modal content -->
|
||||||
|
<div class="modal-content">
|
||||||
|
<span class="close">×</span>
|
||||||
|
<p class="modal-text"><h4>Manual:</h4>
|
||||||
|
To send messages write text in the input and then click "Send" button<br>
|
||||||
|
To send location just click "Send Location" button<br>
|
||||||
|
To change video paste your youtube link and click "Change video"<br>
|
||||||
|
To synchronize your video between users, click "Synchronize videos" button<br>
|
||||||
|
If you see the video "YouTube Developers live:..." you can paste your own link to the youtube video or ask for a synchronization<br>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="chat">
|
<div class="chat">
|
||||||
<div class = player id="ytplayer"></div>
|
<div class = player id="ytplayer"></div>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user