Files
syncfilm/public/video.js
T
2025-06-10 01:17:19 +02:00

315 lines
9.6 KiB
JavaScript

// Select DOM elements
const video = document.getElementById("video");
const playPauseBtn = document.getElementById("play-pause");
const progressBar = document.getElementById("progress-bar");
const currentTimeElem = document.getElementById("current-time");
const durationElem = document.getElementById("duration");
const muteBtn = document.getElementById("mute");
const volumeSlider = document.getElementById("volume");
const loadingElem = document.getElementById("loading");
const fullscreenBtn = document.getElementById("fullscreen");
const rewindBtn = document.getElementById("rewind");
const forwardBtn = document.getElementById("forward");
const playIcon = document.getElementById("play-icon");
const pauseIcon = document.getElementById("pause-icon");
const soundIcon = document.getElementById("sound-icon");
const muteIcon = document.getElementById("mute-icon");
const videoPlayer = document.getElementById("video-player");
const socket = io(); // Initialize socket.io connection
// Prompt for the user's name if not already stored
let userName = localStorage.getItem("userName");
if (!userName) {
userName = prompt("Enter your name:");
if (userName) {
localStorage.setItem("userName", userName);
socket.emit("setName", userName); // Send the name to the server
}
} else {
socket.emit("setName", userName); // Send the stored name to the server
}
// Handle synchronization actions from the server
socket.on("make", (data) => {
controls.style.display = "none";
loadingElem.style.display = "block"; // Show loading for all users
video.pause();
video.currentTime = data.time;
socket.emit("ok", data); // Acknowledge the action
});
// Handle synchronization completion
socket.on("allOk", (data) => {
loadingElem.style.display = "none"; // Hide loading for all users
controls.style.display = "flex";
if (data.action === "play") {
video.play(); // Resume playback
playIcon.style.opacity = "0";
pauseIcon.style.opacity = "1";
} else {
video.pause(); // Pause the video
playIcon.style.opacity = "1";
pauseIcon.style.opacity = "0";
}
});
// Display notifications (e.g., user connected/disconnected)
function showNotification(message, color) {
const notificationContainer = document.getElementById("notification-container");
if (!notificationContainer) {
const container = document.createElement("div");
container.id = "notification-container";
container.style.position = "fixed";
container.style.top = "20px";
container.style.right = "20px";
container.style.zIndex = "1000";
container.style.display = "flex";
container.style.flexDirection = "column";
container.style.gap = "10px";
document.body.appendChild(container);
}
const notification = document.createElement("div");
notification.textContent = message;
notification.style.backgroundColor = color;
notification.style.color = "white";
notification.style.padding = "10px 20px";
notification.style.borderRadius = "5px";
notification.style.boxShadow = "0 4px 8px rgba(0, 0, 0, 0.2)";
notification.style.animation = "fadeOut 3s forwards";
document.getElementById("notification-container").appendChild(notification);
setTimeout(() => {
notification.remove();
}, 3000);
}
// Add fade-out animation for notifications
const style = document.createElement("style");
style.textContent = `
@keyframes fadeOut {
0% { opacity: 1; }
90% { opacity: 1; }
100% { opacity: 0; transform: translateY(-10px); }
}
`;
document.head.appendChild(style);
// Listen for notifications from the server
socket.on("notification", (data) => {
showNotification(data.message, data.color);
});
// Format time in minutes:seconds
function formatTime(seconds) {
const minutes = Math.floor(seconds / 60);
seconds = Math.floor(seconds % 60);
return `${minutes}:${seconds < 10 ? "0" : ""}${seconds}`;
}
// Get the current video state (play/pause and time)
function getVideoData() {
return {
action: video.paused ? "pause" : "play",
time: video.currentTime,
};
}
// Rewind the video by 10 seconds
rewindBtn.addEventListener("click", () => {
video.currentTime = Math.max(0, video.currentTime - 10);
socket.emit("action", getVideoData());
});
// Fast forward the video by 10 seconds
forwardBtn.addEventListener("click", () => {
video.currentTime = Math.min(video.duration, video.currentTime + 10);
socket.emit("action", getVideoData());
});
// Toggle play/pause
playPauseBtn.addEventListener("click", () => {
if (video.paused) {
video.play();
socket.emit("action", getVideoData());
playIcon.style.opacity = "0";
pauseIcon.style.opacity = "1";
} else {
video.pause();
socket.emit("action", getVideoData());
playIcon.style.opacity = "1";
pauseIcon.style.opacity = "0";
}
});
// Toggle play/pause by clicking on the video
video.addEventListener("click", () => {
playPauseBtn.click();
});
// Add keyboard shortcut for play/pause
document.addEventListener("keydown", (event) => {
if (event.code === "Space") {
event.preventDefault(); // Prevent scrolling
playPauseBtn.click();
}
});
// Update progress bar and current time display
let isDragging = false;
video.addEventListener("timeupdate", () => {
if (!isDragging) {
progressBar.value = (video.currentTime / video.duration) * 100;
currentTimeElem.textContent = formatTime(video.currentTime);
}
});
// Update video time while dragging the progress bar
progressBar.addEventListener("input", () => {
isDragging = true;
currentTimeElem.textContent = formatTime(
(progressBar.value / 100) * video.duration
);
});
// Seek to a specific time when progress bar is released
progressBar.addEventListener("change", () => {
video.currentTime = (progressBar.value / 100) * video.duration;
isDragging = false;
socket.emit("action", getVideoData());
});
// Initialize video duration display
video.addEventListener("loadedmetadata", () => {
durationElem.textContent = formatTime(video.duration);
progressBar.value = 0;
currentTimeElem.textContent = "0:00";
});
// Reset progress bar when loading a new video
video.addEventListener("loadstart", () => {
progressBar.value = 0;
currentTimeElem.textContent = "0:00";
});
// Restore saved volume settings
const savedVolume = localStorage.getItem("videoVolume");
if (savedVolume !== null) {
video.volume = savedVolume;
volumeSlider.value = savedVolume * 100;
}
// Adjust volume and save the setting
volumeSlider.addEventListener("input", () => {
const newVolume = volumeSlider.value / 100;
video.volume = newVolume;
localStorage.setItem("videoVolume", newVolume);
});
// Toggle mute/unmute
muteBtn.addEventListener("click", () => {
video.muted = !video.muted;
if (video.muted) {
soundIcon.style.display = "none";
muteIcon.style.display = "block";
localStorage.setItem("videoMuted", "true");
} else {
soundIcon.style.display = "block";
muteIcon.style.display = "none";
localStorage.setItem("videoMuted", "false");
}
});
// Restore mute state on page load
const savedMuted = localStorage.getItem("videoMuted");
if (savedMuted === "true") {
video.muted = true;
soundIcon.style.display = "none";
muteIcon.style.display = "block";
}
// Show/hide controls on hover
let hideControlsTimeout;
function showControls() {
controls.style.opacity = "1";
controls.style.visibility = "visible";
if (hideControlsTimeout) {
clearTimeout(hideControlsTimeout);
}
hideControlsTimeout = setTimeout(hideControls, 3000);
}
function hideControls() {
controls.style.opacity = "0";
controls.style.visibility = "hidden";
}
videoPlayer.addEventListener("mousemove", showControls);
videoPlayer.addEventListener("mouseleave", hideControls);
// Handle fullscreen mode
let isFullscreen = false;
function enterFullscreen(element) {
if (element.requestFullscreen) {
element.requestFullscreen();
} else if (element.mozRequestFullScreen) {
element.mozRequestFullScreen();
} else if (element.webkitRequestFullscreen) {
element.webkitRequestFullscreen();
} else if (element.msRequestFullscreen) {
element.msRequestFullscreen();
}
}
function exitFullscreen() {
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen();
} else if (document.msExitFullscreen) {
document.msExitFullscreen();
}
}
function handleFullscreenChange() {
isFullscreen =
document.fullscreenElement ||
document.mozFullScreenElement ||
document.webkitFullscreenElement ||
document.msFullscreenElement;
if (isFullscreen) {
videoPlayer.classList.add("fullscreen");
} else {
videoPlayer.classList.remove("fullscreen");
}
}
// Listen for fullscreen changes
document.addEventListener("fullscreenchange", handleFullscreenChange);
document.addEventListener("mozfullscreenchange", handleFullscreenChange);
document.addEventListener("webkitfullscreenchange", handleFullscreenChange);
document.addEventListener("MSFullscreenChange", handleFullscreenChange);
// Exit fullscreen on Escape key
document.addEventListener("keydown", (event) => {
if (event.key === "Escape" && isFullscreen) {
exitFullscreen();
}
});
// Toggle fullscreen mode
fullscreenBtn.addEventListener("click", () => {
if (!isFullscreen) {
enterFullscreen(videoPlayer);
} else {
exitFullscreen();
}
});